Crossfire Server, Trunk  R20513
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(ob_methods *context, object *op);
29 static method_ret timed_gate_type_process(ob_methods *context, object *op);
30 
34 void init_type_gate(void) {
37 }
38 
45 static method_ret gate_type_process(ob_methods *context, 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  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)
96  if (!QUERY_FLAG(tmp, FLAG_NO_PICK)
97  || QUERY_FLAG(tmp, FLAG_CAN_ROLL)
98  || QUERY_FLAG(tmp, FLAG_ALIVE))
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 (!QUERY_FLAG(tmp, FLAG_ALIVE)
145  && (!QUERY_FLAG(tmp, FLAG_NO_PICK) || QUERY_FLAG(tmp, FLAG_CAN_ROLL))) {
146  /* If it has speed, it should move itself, otherwise: */
147  int i = object_find_free_spot(tmp, op->map, op->x, op->y, 1, 9);
148 
149  /* If there is a free spot, move the object someplace */
150  if (i != -1) {
151  object_remove(tmp);
152  object_insert_in_map_at(tmp, op->map, op, 0, op->x+freearr_x[i], op->y+freearr_y[i]);
153  }
154  }
155  }
156 
157  /* See if there is still anything blocking the gate */
158  for (tmp = op->above; tmp != NULL; tmp = tmp->above)
159  if (!QUERY_FLAG(tmp, FLAG_NO_PICK)
160  || QUERY_FLAG(tmp, FLAG_CAN_ROLL)
161  || QUERY_FLAG(tmp, FLAG_ALIVE))
162  break;
163 
164  /* IF there is, start putting the gate down */
165  if (tmp) {
166  op->stats.food = 1;
167  } else {
168  object* part;
169  for (part = op; part != NULL; part = part->more) {
170  if (!part->stats.luck)
171  part->move_block = MOVE_ALL;
172  if (!part->stats.ac) {
173  SET_FLAG(part, FLAG_BLOCKSVIEW);
174  update_all_los(part->map, part->x, part->y);
175  }
176  }
177  }
178  } /* gate is halfway up */
179 
180  for (part = op; part != NULL; part = part->more) {
181  SET_ANIMATION(part, op->stats.wc);
182  }
184  } /* gate is going up */
185 
186  return METHOD_OK;
187 }
188 
199 static method_ret timed_gate_type_process(ob_methods *context, object *op) {
200  int v = op->value;
201 
202  if (op->stats.sp) {
203  gate_type_process(context, op);
204  if (op->value != v) /* change direction ? */
205  op->stats.sp = 0;
206  return METHOD_OK;
207  }
208  if (--op->stats.hp <= 0) { /* keep gate down */
209  gate_type_process(context, op);
210  if (op->value != v) { /* ready ? */
211  op->speed = 0;
213  }
214  }
215  return METHOD_OK;
216 }
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Sends message to player(s).
Definition: main.c:315
Error, serious thing.
Definition: logger.h:11
static method_ret gate_type_process(ob_methods *context, object *op)
Handle ob_process for all gate objects.
Definition: gate.c:45
Sound-related defines.
int8_t ac
Armour Class, how hard to hit, the lower the better.
Definition: living.h:37
#define SET_FLAG(xyz, p)
Definition: define.h:223
Typedefs for ob_methods.
Definition: ob_methods.h:45
static method_ret timed_gate_type_process(ob_methods *context, object *op)
Handle ob_process for all timed gate objects.
Definition: gate.c:199
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
Definition: stringbuffer.c:57
#define SET_ANIMATION(ob, newanim)
Definition: global.h:171
object clone
An object from which to do object_copy()
Definition: object.h:470
short freearr_x[SIZEOFFREE]
X offset when searching around a spot.
Definition: object.c:65
#define PREFER_LOW
Definition: define.h:600
struct obj * above
Pointer to the object stacked above this one.
Definition: object.h:288
void object_update(object *op, int action)
object_update() updates the array which represents the map.
Definition: object.c:1239
int16_t sp
Spell points.
Definition: living.h:41
Global type definitions and header inclusions.
const char * map_get_path(const object *item)
Return the map path on which the specified item is.
Definition: map.c:2690
int16_t hp
Hit Points.
Definition: living.h:39
#define FLAG_CAN_ROLL
Object can be rolled.
Definition: define.h:254
short freearr_y[SIZEOFFREE]
Y offset when searching around a spot.
Definition: object.c:71
#define MOVE_ALL
Mask of all movement types.
Definition: define.h:413
char method_ret
Define some standard return values for callbacks which don&#39;t need to return any other results...
Definition: ob_methods.h:14
int16_t y
Position in the map for this object.
Definition: object.h:326
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
Definition: object.c:1921
void object_dump(const object *op, StringBuffer *sb)
Dumps an object.
Definition: object.c:394
#define FLAG_ALIVE
Object can fight (or be fought)
Definition: define.h:230
#define MSG_TYPE_VICTIM
Something bad is happening to the player.
Definition: newclient.h:392
void update_all_los(const mapstruct *map, int x, int y)
This function makes sure that update_los() will be called for all players on the given map within the...
Definition: los.c:532
#define METHOD_OK
Definition: ob_methods.h:15
struct mapdef * map
Pointer to the map in which this object is present.
Definition: object.h:297
int16_t dam
How much damage this object does when hitting.
Definition: living.h:45
#define FLAG_BLOCKSVIEW
Object blocks view.
Definition: define.h:269
const char * name
The name of the object, obviously...
Definition: object.h:311
#define MSG_TYPE_VICTIM_WAS_HIT
Player was hit by something.
Definition: newclient.h:647
void init_type_gate(void)
Initializer for the gate object type.
Definition: gate.c:34
int8_t luck
Affects thaco and ac from time to time.
Definition: living.h:38
#define AT_PHYSICAL
Definition: attack.h:76
float speed
The overall speed of this object.
Definition: object.h:328
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define CLEAR_FLAG(xyz, p)
Definition: define.h:224
int16_t x
Definition: object.h:326
int8_t wc
Weapon Class, how skilled, the lower the better.
Definition: living.h:36
Object type variables.
See Player.
Definition: object.h:107
#define UP_OBJ_CHANGE
Object changed.
Definition: object.h:518
#define NUM_ANIMATIONS(ob)
Definition: global.h:179
living stats
Str, Con, Dex, etc.
Definition: object.h:368
struct archt * arch
Pointer to archetype.
Definition: object.h:412
See Gate.
Definition: object.h:206
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:338
See Timed Gate.
Definition: object.h:128
void register_process(int ob_type, process_func method)
Registers the process method for the given type.
Definition: ob_types.c:71
#define NDI_UNIQUE
Print immediately, don&#39;t buffer.
Definition: newclient.h:245
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.c:51
MoveType move_block
What movement types this blocks.
Definition: object.h:425
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
object_find_free_spot(object, map, x, y, start, stop) will search for a spot at the given map and coo...
Definition: object.c:3415
A buffer that will be expanded as content is added to it.
Definition: stringbuffer.c:25
int random_roll(int min, int max, const object *op, int goodbad)
Roll a random number between min and max.
Definition: utils.c:42
#define FLAG_NO_PICK
Object can&#39;t be picked up.
Definition: define.h:239
int hit_player(object *op, int dam, object *hitter, uint32_t type, int full_hit)
Object is attacked by something.
Definition: attack.c:1861
Object type functions and variables.
struct obj * more
Pointer to the rest of a large body of objects.
Definition: object.h:295
void object_update_speed(object *op)
Updates the speed of an object.
Definition: object.c:1129
int32_t value
How much money it is worth (or contains)
Definition: object.h:350
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
Definition: stringbuffer.c:76
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to...
Definition: object.c:1654
int32_t food
How much food in stomach.
Definition: living.h:47