Atrinik Server  4.0
door.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
32 #include <global.h>
33 #include <arch.h>
34 #include <player.h>
35 #include <object.h>
36 #include <object_methods.h>
37 #include <door.h>
38 #include <key.h>
39 #include <rune.h>
40 
42 static void
43 process_func (object *op)
44 {
45  HARD_ASSERT(op != NULL);
46 
47  /* Check to see if the door should still remain open. */
48  if (op->last_sp-- > 0) {
49  return;
50  }
51 
52  /* If there's something blocking the door from closing, reset the
53  * counter. */
54  if (GET_MAP_FLAGS(op->map, op->x, op->y) & (P_NO_PASS |
55  P_IS_MONSTER |
56  P_IS_PLAYER)) {
57  op->last_sp = op->stats.sp;
58  return;
59  }
60 
61  /* The door is no longer open. */
62  op->last_eat = 0;
63 
64  /* Remove from active list. */
65  op->speed = 0.0;
66  op->speed_left = 0.0;
68 
69  op->state = 0;
70 
71  if (QUERY_FLAG(&op->arch->clone, FLAG_BLOCKSVIEW)) {
73  }
74 
76 
77  /* Update animation state. */
79  SET_ANIMATION(op, ((NUM_ANIMATIONS(op) / NUM_FACINGS(op)) *
80  op->direction + op->state));
81  }
82 
83  if (op->sub_type == ST1_DOOR_NORMAL) {
84  play_sound_map(op->map,
85  CMD_SOUND_EFFECT,
86  "door_close.ogg",
87  op->x,
88  op->y,
89  0,
90  0);
91  }
92 
94 }
95 
97 static int
98 apply_func (object *op, object *applier, int aflags)
99 {
100  HARD_ASSERT(op != NULL);
101  HARD_ASSERT(applier != NULL);
103 }
104 
109 {
110  OBJECT_METHODS(DOOR)->process_func = process_func;
111  OBJECT_METHODS(DOOR)->apply_func = apply_func;
112 }
113 
124 static void
125 door_open (object *op, object *opener, bool nearby)
126 {
127  /* Already open, nothing to do. */
128  if (op->last_eat == 1) {
129  return;
130  }
131 
132  /* Spring any traps in the door's inventory. */
133  FOR_INV_PREPARE(op, tmp) {
134  if (tmp->type == RUNE && tmp->level != 0) {
135  rune_spring(tmp, opener);
136  }
137  } FOR_INV_FINISH();
138 
139  /* Mark this door as open. */
140  op->last_eat = 1;
141  /* Put it on the active list, so it will close automatically. */
142  op->speed = 0.1;
144  op->speed_left = -0.2;
145  op->state = 1;
146  /* Initialize counter that controls how long to allow the door to
147  * stay open. */
148  op->last_sp = op->stats.sp;
149 
152 
153  /* Update animation state. */
155  SET_ANIMATION(op, ((NUM_ANIMATIONS(op) / NUM_FACINGS(op)) *
156  op->direction + op->state));
157  }
158 
159  if (op->sub_type == ST1_DOOR_NORMAL && !nearby) {
160  play_sound_map(op->map,
161  CMD_SOUND_EFFECT,
162  "door.ogg",
163  op->x,
164  op->y,
165  0,
166  0);
167  }
168 
170 }
171 
180 static void
181 doors_open (object *op, object *opener)
182 {
183  HARD_ASSERT(op != NULL);
184  HARD_ASSERT(opener != NULL);
185 
186  door_open(op, opener, false);
187 
188  /* Try to open nearby doors. */
189  for (int i = 1; i <= SIZEOFFREE1; i += 2) {
190  int x = op->x + freearr_x[i];
191  int y = op->y + freearr_y[i];
192  mapstruct *m = get_map_from_coord(op->map, &x, &y);
193  if (m == NULL) {
194  continue;
195  }
196 
197  /* If there's no closed door, no need to check the objects on
198  * this square. */
199  if (!(GET_MAP_FLAGS(m, x, y) & P_DOOR_CLOSED)) {
200  continue;
201  }
202 
203  object *tmp;
204  FOR_MAP_LAYER_BEGIN(m, x, y, LAYER_WALL, -1, tmp) {
205  if (tmp->type == DOOR && tmp->slaying == op->slaying) {
206  door_open(tmp, opener, true);
207  }
209  }
210 }
211 
230 bool
231 door_try_open (object *op, mapstruct *m, int x, int y, bool test)
232 {
233  HARD_ASSERT(op != NULL);
234  HARD_ASSERT(m != NULL);
235  HARD_ASSERT(!OUT_OF_MAP(m, x, y));
236 
237  /* Don't bother opening doors when the player has collision disabled. */
238  if (op->type == PLAYER && CONTR(op)->tcl) {
239  return false;
240  }
241 
242  /* Cannot open doors. */
243  if (!(op->behavior & BEHAVIOR_OPEN_DOORS)) {
244  return false;
245  }
246 
247  /* There isn't a door on this tile. */
248  if (!(GET_MAP_FLAGS(m, x, y) & P_DOOR_CLOSED)) {
249  return false;
250  }
251 
252  /* Pass through is set on the tile, and the object can pass through, so
253  * don't open doors. */
254  if (GET_MAP_FLAGS(m, x, y) & P_PASS_THRU &&
256  return false;
257  }
258 
259  object *tmp;
260  FOR_MAP_LAYER_BEGIN(m, x, y, LAYER_WALL, -1, tmp) {
261  if (tmp->type != DOOR) {
262  continue;
263  }
264 
265  if (tmp->slaying != NULL) {
266  object *key = key_match(op, tmp);
267  if (key == NULL) {
268  if (!test) {
269  draw_info(COLOR_NAVY, op, tmp->msg);
270  }
271 
272  return false;
273  } else if (!test) {
274  if (key->type == KEY) {
275  char *key_name = object_get_base_name_s(key, op);
276  draw_info_format(COLOR_WHITE, op,
277  "You open the %s with the %s.",
278  tmp->name, key_name);
279  efree(key_name);
280  } else if (key->type == FORCE) {
281  draw_info_format(COLOR_WHITE, op,
282  "The %s is opened for you.",
283  tmp->name);
284  }
285  }
286  }
287 
288  /* If we are here, the door can be opened. */
289  if (!test) {
290  doors_open(tmp, op);
291  }
292 
293  return true;
295 
296  return false;
297 }
298 
311 void
312 door_show_message (object *op, mapstruct *m, int x, int y)
313 {
314  HARD_ASSERT(op != NULL);
315  HARD_ASSERT(m != NULL);
316  HARD_ASSERT(!OUT_OF_MAP(m, x, y));
317 
318  object *tmp;
319  FOR_MAP_LAYER_BEGIN(m, x, y, LAYER_WALL, -1, tmp) {
320  if (tmp->type == DOOR) {
321  draw_info(COLOR_NAVY, op, tmp->msg);
322  return;
323  }
325 }
static int apply_func(object *op, object *applier, int aflags)
Definition: door.c:98
void door_show_message(object *op, mapstruct *m, int x, int y)
Definition: door.c:312
#define NUM_FACINGS(ob)
Definition: global.h:300
OBJECT_TYPE_INIT_DEFINE(door)
Definition: door.c:108
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:1691
#define FOR_INV_FINISH()
Definition: define.h:1698
#define FLAG_ANIMATE
Definition: define.h:912
double speed_left
Definition: object.h:472
mapstruct * get_map_from_coord(mapstruct *m, int *x, int *y)
Definition: map.c:1869
#define SIZEOFFREE1
Definition: define.h:654
#define SET_ANIMATION(ob, newanim)
Definition: global.h:282
#define P_NO_PASS
Definition: map.h:254
const char * slaying
Definition: object.h:180
int16_t last_sp
Definition: object.h:313
#define OUT_OF_MAP(M, X, Y)
Definition: map.h:240
#define PLAYER
Definition: define.h:122
int16_t sp
Definition: living.h:78
#define P_PASS_THRU
Definition: map.h:288
#define FLAG_IS_TURNABLE
Definition: define.h:960
#define QUERY_FLAG(xyz, p)
Definition: define.h:761
struct archetype * arch
Definition: object.h:225
static void doors_open(object *op, object *opener)
Definition: door.c:181
int16_t y
Definition: object.h:276
#define P_DOOR_CLOSED
Definition: map.h:272
#define P_IS_PLAYER
Definition: map.h:256
void object_update(object *op, int action)
Definition: object.c:1117
int8_t direction
Definition: object.h:350
char * object_get_base_name_s(const object *op, const object *caller)
Definition: item.c:534
static void door_open(object *op, object *opener, bool nearby)
Definition: door.c:125
struct mapdef * map
Definition: object.h:139
const char * name
Definition: object.h:168
#define SET_FLAG(xyz, p)
Definition: define.h:741
uint8_t state
Definition: object.h:344
#define FLAG_CAN_PASS_THRU
Definition: define.h:1058
#define FOR_MAP_LAYER_END
Definition: define.h:1657
double speed
Definition: object.h:469
#define OBJECT_METHOD_UNHANDLED
#define FLAG_DOOR_CLOSED
Definition: define.h:1314
int16_t x
Definition: object.h:273
#define FOR_MAP_LAYER_BEGIN(_m, _x, _y, _layer, _sub_layer, _obj)
Definition: define.h:1630
int16_t last_eat
Definition: object.h:319
void play_sound_map(mapstruct *map, int type, const char *filename, int x, int y, int loop, int volume)
Definition: sounds.c:159
#define FLAG_BLOCKSVIEW
Definition: define.h:1008
bool door_try_open(object *op, mapstruct *m, int x, int y, bool test)
Definition: door.c:231
#define NUM_ANIMATIONS(ob)
Definition: global.h:298
living stats
Definition: object.h:481
int freearr_x[SIZEOFFREE]
Definition: object.c:84
uint8_t behavior
Definition: object.h:399
uint8_t type
Definition: object.h:360
#define CLEAR_FLAG(xyz, p)
Definition: define.h:751
#define OBJECT_METHODS(type)
const char * msg
Definition: object.h:183
#define RUNE
Definition: define.h:522
#define BEHAVIOR_OPEN_DOORS
Definition: object.h:604
#define KEY
Definition: define.h:198
#define DOOR
Definition: define.h:194
void rune_spring(object *op, object *victim)
Definition: rune.c:48
#define P_IS_MONSTER
Definition: map.h:258
#define ST1_DOOR_NORMAL
Definition: define.h:590
void object_update_speed(object *op)
Definition: object.c:1043
Definition: map.h:536
#define FORCE
Definition: define.h:465
int freearr_y[SIZEOFFREE]
Definition: object.c:99
#define UP_OBJ_FLAGS
Definition: object.h:535
object clone
An object from which to do object_copy().
Definition: arch.h:47
#define LAYER_WALL
Definition: map.h:57
static void process_func(object *op)
Definition: door.c:43
object * key_match(object *op, const object *locked)
Definition: key.c:48
uint8_t sub_type
Definition: object.h:363