Crossfire Server, Trunk
gate.cpp
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 
20 #include "global.h"
21 
22 #include <stdlib.h>
23 
24 #include "ob_methods.h"
25 #include "ob_types.h"
26 #include "sounds.h"
27 #include "sproto.h"
28 
29 static method_ret gate_type_process(object *op);
30 static method_ret timed_gate_type_process(object *op);
31 
35 void init_type_gate(void) {
38 }
39 
45 static method_ret gate_type_process(object *op) {
46  object *tmp, *part;
47 
48  if (op->stats.wc < 0 || (int)op->stats.wc >= NUM_ANIMATIONS(op)) {
49  StringBuffer *sb;
50  char *diff;
51 
52  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);
53  sb = stringbuffer_new();
54  object_dump(op, sb);
55  diff = stringbuffer_finish(sb);
56  LOG(llevError, "%s\n", diff);
57  free(diff);
58  op->stats.wc = 0;
59  }
60 
61  /* We're going down */
62  if (op->value) {
63  if (--op->stats.wc <= 0) { /* Reached bottom, let's stop */
64  op->stats.wc = 0;
65  if (op->arch->clone.speed)
66  op->value = 0;
67  else {
68  op->speed = 0;
70  }
71  }
72 
73  for (part = op; part != NULL; part = part->more) {
74  if ((int)op->stats.wc < (NUM_ANIMATIONS(op)/2+1)) {
75  part->move_block = 0;
77  update_all_los(part->map, part->x, part->y);
78  }
79  SET_ANIMATION(part, op->stats.wc);
80  }
82  play_sound_map(SOUND_TYPE_GROUND, op, 0, "gate moving");
83  return METHOD_OK;
84  }
85 
86  /* We're going up */
87 
88  /* First, lets see if we are already at the top */
89  if ((unsigned char)op->stats.wc == (NUM_ANIMATIONS(op)-1)) {
90  /* Check to make sure that only non pickable and non rollable
91  * objects are above the gate. If so, we finish closing the gate,
92  * otherwise, we fall through to the code below which should lower
93  * the gate slightly.
94  */
95 
96  for (tmp = op->above; tmp != NULL; tmp = tmp->above)
100  break;
101 
102  if (tmp == NULL) {
103  if (op->arch->clone.speed)
104  op->value = 1;
105  else {
106  op->speed = 0;
107  object_update_speed(op); /* Reached top, let's stop */
108  }
109  return METHOD_OK;
110  }
111  }
112 
113  if (op->stats.food) { /* The gate is going temporarily down */
114  if (--op->stats.wc <= 0) { /* Gone all the way down? */
115  op->stats.food = 0; /* Then let's try again */
116  op->stats.wc = 0;
117  }
118  } else { /* The gate is still going up */
119  op->stats.wc++;
120 
121  if ((int)op->stats.wc >= (NUM_ANIMATIONS(op)))
122  op->stats.wc = (signed char)NUM_ANIMATIONS(op)-1;
123 
124  /* If there is something on top of the gate, we try to roll it off.
125  * If a player/monster, we don't roll, we just hit them with damage
126  */
127  if ((int)op->stats.wc >= NUM_ANIMATIONS(op)/2) {
128  /* Halfway or further, check blocks */
129  /* First, get the top object on the square. */
130  for (tmp = op->above; tmp != NULL && tmp->above != NULL; tmp = tmp->above)
131  ;
132 
133  if (tmp != NULL) {
134  if (QUERY_FLAG(tmp, FLAG_ALIVE)) {
135  hit_player(tmp, random_roll(1, op->stats.dam, tmp, PREFER_LOW), op, AT_PHYSICAL, 1);
136  if (tmp->type == PLAYER)
138  "You are crushed by the %s!",
139  op->name);
140  } else
141  /* If the object is not alive, and the object either can
142  * be picked up or the object rolls, move the object
143  * off the gate.
144  *
145  * If the top item is not interactable, then check items below it
146  * instead. This allows us to use gates with translucent roofs
147  * or ambient weather effects on the map that end up above the other items.
148  */
149  while (tmp != op) {
150  if (!QUERY_FLAG(tmp, FLAG_ALIVE)
152  /* If it has speed, it should move itself, otherwise: */
153  int i = object_find_free_spot(tmp, op->map, op->x, op->y, 1, 9);
154 
155  /* If there is a free spot, move the object someplace */
156  if (i != -1) {
158  object_insert_in_map_at(tmp, op->map, op, 0, op->x+freearr_x[i], op->y+freearr_y[i]);
159  }
160  break;
161  }
162  tmp = tmp->below;
163  }
164  }
165 
166  /* See if there is still anything blocking the gate */
167  for (tmp = op->above; tmp != NULL; tmp = tmp->above)
171  break;
172 
173  /* IF there is, start putting the gate down */
174  if (tmp) {
175  op->stats.food = 1;
176  } else {
177  object* part;
178  for (part = op; part != NULL; part = part->more) {
179  if (!part->stats.luck)
180  part->move_block = MOVE_ALL;
181  if (!part->stats.ac) {
182  SET_FLAG(part, FLAG_BLOCKSVIEW);
183  update_all_los(part->map, part->x, part->y);
184  }
185  }
186  }
187  } /* gate is halfway up */
188 
189  for (part = op; part != NULL; part = part->more) {
190  SET_ANIMATION(part, op->stats.wc);
191  }
193  play_sound_map(SOUND_TYPE_GROUND, op, 0, "gate moving");
194  } /* gate is going up */
195 
196  return METHOD_OK;
197 }
198 
209  int v = op->value;
210 
211  if (op->stats.sp) {
213  if (op->value != v) /* change direction ? */
214  op->stats.sp = 0;
215  return METHOD_OK;
216  }
217  if (--op->stats.hp <= 0) { /* keep gate down */
219  if (op->value != v) { /* ready ? */
220  op->speed = 0;
222  }
223  }
224  return METHOD_OK;
225 }
PLAYER
@ PLAYER
Definition: object.h:110
global.h
obj::move_block
MoveType move_block
Definition: object.h:433
llevError
@ llevError
Definition: logger.h:11
MOVE_ALL
#define MOVE_ALL
Definition: define.h:398
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:51
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
obj::map
struct mapdef * map
Definition: object.h:303
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
AT_PHYSICAL
#define AT_PHYSICAL
Definition: attack.h:76
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.cpp:57
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:131
SET_ANIMATION
#define SET_ANIMATION(ob, newanim)
Definition: global.h:162
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,...) PRINTF_ARGS(6
play_sound_map
void play_sound_map(int8_t sound_type, object *emitter, int dir, const char *action)
Definition: sounds.cpp:113
Ice.tmp
int tmp
Definition: Ice.py:207
FLAG_BLOCKSVIEW
#define FLAG_BLOCKSVIEW
Definition: define.h:269
register_process
void register_process(int ob_type, process_func method)
Definition: ob_types.cpp:71
timed_gate_type_process
static method_ret timed_gate_type_process(object *op)
Definition: gate.cpp:208
MSG_TYPE_VICTIM
#define MSG_TYPE_VICTIM
Definition: newclient.h:415
FLAG_NO_PICK
#define FLAG_NO_PICK
Definition: define.h:239
FLAG_ALIVE
#define FLAG_ALIVE
Definition: define.h:230
init_type_gate
void init_type_gate(void)
Definition: gate.cpp:35
liv::luck
int8_t luck
Definition: living.h:39
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.cpp:76
object_update
void object_update(object *op, int action)
Definition: object.cpp:1434
freearr_y
short freearr_y[SIZEOFFREE]
Definition: object.cpp:305
object_dump
void object_dump(const object *op, StringBuffer *sb)
Definition: object.cpp:645
object_update_speed
void object_update_speed(object *op)
Definition: object.cpp:1349
obj::x
int16_t x
Definition: object.h:333
FLAG_CAN_ROLL
#define FLAG_CAN_ROLL
Definition: define.h:254
sproto.h
MSG_TYPE_VICTIM_WAS_HIT
#define MSG_TYPE_VICTIM_WAS_HIT
Definition: newclient.h:651
random_roll
int random_roll(int min, int max, const object *op, int goodbad)
Definition: utils.cpp:42
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.cpp:2098
StringBuffer
Definition: stringbuffer.cpp:25
obj::y
int16_t y
Definition: object.h:333
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:376
SOUND_TYPE_GROUND
#define SOUND_TYPE_GROUND
Definition: newclient.h:336
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.cpp:3552
hit_player
int hit_player(object *op, int dam, object *hitter, uint32_t type, int full_hit)
Definition: attack.cpp:1860
map_get_path
const char * map_get_path(const object *item)
Definition: map.cpp:2730
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
NUM_ANIMATIONS
#define NUM_ANIMATIONS(ob)
Definition: global.h:171
obj::more
struct obj * more
Definition: object.h:301
liv::ac
int8_t ac
Definition: living.h:38
object_remove
void object_remove(object *op)
Definition: object.cpp:1833
UP_OBJ_CHANGE
#define UP_OBJ_CHANGE
Definition: object.h:521
update_all_los
void update_all_los(const mapstruct *map, int x, int y)
Definition: los.cpp:536
ob_methods.h
gate_type_process
static method_ret gate_type_process(object *op)
Definition: gate.cpp:45
freearr_x
short freearr_x[SIZEOFFREE]
Definition: object.cpp:299
GATE
@ GATE
Definition: object.h:209