Crossfire Server, Trunk
gate.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
19 #include "global.h"
20 
21 #include <stdlib.h>
22 
23 #include "ob_methods.h"
24 #include "ob_types.h"
25 #include "sounds.h"
26 #include "sproto.h"
27 
28 static method_ret gate_type_process(object *op);
29 static method_ret timed_gate_type_process(object *op);
30 
34 void init_type_gate(void) {
37 }
38 
44 static method_ret gate_type_process(object *op) {
45  object *tmp, *part;
46 
47  if (op->stats.wc < 0 || (int)op->stats.wc >= NUM_ANIMATIONS(op)) {
48  StringBuffer *sb;
49  char *diff;
50 
51  LOG(llevError, "Gate error: animation was %d, max=%d, on %s (%d, %d)\n", op->stats.wc, NUM_ANIMATIONS(op), map_get_path(op), op->x, op->y);
52  sb = stringbuffer_new();
53  object_dump(op, sb);
54  diff = stringbuffer_finish(sb);
55  LOG(llevError, "%s\n", diff);
56  free(diff);
57  op->stats.wc = 0;
58  }
59 
60  /* We're going down */
61  if (op->value) {
62  if (--op->stats.wc <= 0) { /* Reached bottom, let's stop */
63  op->stats.wc = 0;
64  if (op->arch->clone.speed)
65  op->value = 0;
66  else {
67  op->speed = 0;
69  }
70  }
71 
72  for (part = op; part != NULL; part = part->more) {
73  if ((int)op->stats.wc < (NUM_ANIMATIONS(op)/2+1)) {
74  part->move_block = 0;
76  update_all_los(part->map, part->x, part->y);
77  }
78  SET_ANIMATION(part, op->stats.wc);
79  }
81  play_sound_map(SOUND_TYPE_GROUND, op, 0, "gate moving");
82  return METHOD_OK;
83  }
84 
85  /* We're going up */
86 
87  /* First, lets see if we are already at the top */
88  if ((unsigned char)op->stats.wc == (NUM_ANIMATIONS(op)-1)) {
89  /* Check to make sure that only non pickable and non rollable
90  * objects are above the gate. If so, we finish closing the gate,
91  * otherwise, we fall through to the code below which should lower
92  * the gate slightly.
93  */
94 
95  for (tmp = op->above; tmp != NULL; tmp = tmp->above)
99  break;
100 
101  if (tmp == NULL) {
102  if (op->arch->clone.speed)
103  op->value = 1;
104  else {
105  op->speed = 0;
106  object_update_speed(op); /* Reached top, let's stop */
107  }
108  return METHOD_OK;
109  }
110  }
111 
112  if (op->stats.food) { /* The gate is going temporarily down */
113  if (--op->stats.wc <= 0) { /* Gone all the way down? */
114  op->stats.food = 0; /* Then let's try again */
115  op->stats.wc = 0;
116  }
117  } else { /* The gate is still going up */
118  op->stats.wc++;
119 
120  if ((int)op->stats.wc >= (NUM_ANIMATIONS(op)))
121  op->stats.wc = (signed char)NUM_ANIMATIONS(op)-1;
122 
123  /* If there is something on top of the gate, we try to roll it off.
124  * If a player/monster, we don't roll, we just hit them with damage
125  */
126  if ((int)op->stats.wc >= NUM_ANIMATIONS(op)/2) {
127  /* Halfway or further, check blocks */
128  /* First, get the top object on the square. */
129  for (tmp = op->above; tmp != NULL && tmp->above != NULL; tmp = tmp->above)
130  ;
131 
132  if (tmp != NULL) {
133  if (QUERY_FLAG(tmp, FLAG_ALIVE)) {
134  hit_player(tmp, random_roll(1, op->stats.dam, tmp, PREFER_LOW), op, AT_PHYSICAL, 1);
135  if (tmp->type == PLAYER)
137  "You are crushed by the %s!",
138  op->name);
139  } else
140  /* If the object is not alive, and the object either can
141  * be picked up or the object rolls, move the object
142  * off the gate.
143  *
144  * If the top item is not interactable, then check items below it
145  * instead. This allows us to use gates with translucent roofs
146  * or ambient weather effects on the map that end up above the other items.
147  */
148  while (tmp != op) {
149  if (!QUERY_FLAG(tmp, FLAG_ALIVE)
151  /* If it has speed, it should move itself, otherwise: */
152  int i = object_find_free_spot(tmp, op->map, op->x, op->y, 1, 9);
153 
154  /* If there is a free spot, move the object someplace */
155  if (i != -1) {
157  object_insert_in_map_at(tmp, op->map, op, 0, op->x+freearr_x[i], op->y+freearr_y[i]);
158  }
159  break;
160  }
161  tmp = tmp->below;
162  }
163  }
164 
165  /* See if there is still anything blocking the gate */
166  for (tmp = op->above; tmp != NULL; tmp = tmp->above)
170  break;
171 
172  /* IF there is, start putting the gate down */
173  if (tmp) {
174  op->stats.food = 1;
175  } else {
176  object* part;
177  for (part = op; part != NULL; part = part->more) {
178  if (!part->stats.luck)
179  part->move_block = MOVE_ALL;
180  if (!part->stats.ac) {
181  SET_FLAG(part, FLAG_BLOCKSVIEW);
182  update_all_los(part->map, part->x, part->y);
183  }
184  }
185  }
186  } /* gate is halfway up */
187 
188  for (part = op; part != NULL; part = part->more) {
189  SET_ANIMATION(part, op->stats.wc);
190  }
192  play_sound_map(SOUND_TYPE_GROUND, op, 0, "gate moving");
193  } /* gate is going up */
194 
195  return METHOD_OK;
196 }
197 
208  int v = op->value;
209 
210  if (op->stats.sp) {
212  if (op->value != v) /* change direction ? */
213  op->stats.sp = 0;
214  return METHOD_OK;
215  }
216  if (--op->stats.hp <= 0) { /* keep gate down */
218  if (op->value != v) { /* ready ? */
219  op->speed = 0;
221  }
222  }
223  return METHOD_OK;
224 }
PLAYER
@ PLAYER
Definition: object.h:107
global.h
object_remove
void object_remove(object *op)
Definition: object.c:1806
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.c:57
obj::move_block
MoveType move_block
Definition: object.h:429
llevError
@ llevError
Definition: logger.h:11
MOVE_ALL
#define MOVE_ALL
Definition: define.h:398
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
object_update
void object_update(object *op, int action)
Definition: object.c:1407
obj::map
struct mapdef * map
Definition: object.h:298
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
timed_gate_type_process
static method_ret timed_gate_type_process(object *op)
Definition: gate.c:207
register_process
void register_process(int ob_type, process_func method)
Definition: ob_types.c:71
AT_PHYSICAL
#define AT_PHYSICAL
Definition: attack.h:76
METHOD_OK
#define METHOD_OK
Definition: ob_methods.h:15
PREFER_LOW
#define PREFER_LOW
Definition: define.h:564
TIMED_GATE
@ TIMED_GATE
Definition: object.h:128
SET_ANIMATION
#define SET_ANIMATION(ob, newanim)
Definition: global.h:160
play_sound_map
void play_sound_map(int8_t sound_type, object *emitter, int dir, const char *action)
Definition: sounds.c:108
Ice.tmp
int tmp
Definition: Ice.py:207
init_type_gate
void init_type_gate(void)
Definition: gate.c:34
FLAG_BLOCKSVIEW
#define FLAG_BLOCKSVIEW
Definition: define.h:269
MSG_TYPE_VICTIM
#define MSG_TYPE_VICTIM
Definition: newclient.h:415
freearr_x
short freearr_x[SIZEOFFREE]
Definition: object.c:288
FLAG_NO_PICK
#define FLAG_NO_PICK
Definition: define.h:239
freearr_y
short freearr_y[SIZEOFFREE]
Definition: object.c:294
FLAG_ALIVE
#define FLAG_ALIVE
Definition: define.h:230
liv::luck
int8_t luck
Definition: living.h:39
object_dump
void object_dump(const object *op, StringBuffer *sb)
Definition: object.c:638
obj::x
int16_t x
Definition: object.h:328
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:76
FLAG_CAN_ROLL
#define FLAG_CAN_ROLL
Definition: define.h:254
sproto.h
map_get_path
const char * map_get_path(const object *item)
Definition: map.c:2712
MSG_TYPE_VICTIM_WAS_HIT
#define MSG_TYPE_VICTIM_WAS_HIT
Definition: newclient.h:651
StringBuffer
Definition: stringbuffer.c:25
gate_type_process
static method_ret gate_type_process(object *op)
Definition: gate.c:44
random_roll
int random_roll(int min, int max, const object *op, int goodbad)
Definition: utils.c:42
obj::y
int16_t y
Definition: object.h:328
method_ret
char method_ret
Definition: ob_methods.h:14
ob_types.h
sounds.h
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:262
obj::stats
living stats
Definition: object.h:371
SOUND_TYPE_GROUND
#define SOUND_TYPE_GROUND
Definition: newclient.h:336
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
give.op
op
Definition: give.py:33
object_find_free_spot
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
Definition: object.c:3509
hit_player
int hit_player(object *op, int dam, object *hitter, uint32_t type, int full_hit)
Definition: attack.c:1853
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
NUM_ANIMATIONS
#define NUM_ANIMATIONS(ob)
Definition: global.h:169
update_all_los
void update_all_los(const mapstruct *map, int x, int y)
Definition: los.c:536
object_update_speed
void object_update_speed(object *op)
Definition: object.c:1317
obj::more
struct obj * more
Definition: object.h:296
liv::ac
int8_t ac
Definition: living.h:38
object_insert_in_map_at
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.c:2067
UP_OBJ_CHANGE
#define UP_OBJ_CHANGE
Definition: object.h:519
ob_methods.h
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Definition: main.c:319
GATE
@ GATE
Definition: object.h:206