ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/button.C
(Generate patch)

Comparing deliantra/server/common/button.C (file contents):
Revision 1.4 by elmex, Wed Aug 30 12:42:56 2006 UTC vs.
Revision 1.21 by root, Sat Dec 30 10:16:10 2006 UTC

1/*
2 * static char *rcsid_button_c =
3 * "$Id: button.C,v 1.4 2006/08/30 12:42:56 elmex Exp $";
4 */
5
6/* 1/*
7 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
8 3
9 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
10 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
21 16
22 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 20
26 The authors can be reached via e-mail at crossfire-devel@real-time.com 21 The authors can be reached via e-mail at <crossfire@schmorp.de>
27*/ 22*/
28 23
29#include <global.h> 24#include <global.h>
30#include <funcpoint.h> 25#include <funcpoint.h>
31 26
37 * elmex: 32 * elmex:
38 * This function takes a objectlink list with all the objects are going to be activated. 33 * This function takes a objectlink list with all the objects are going to be activated.
39 * state is a true/false flag that will actiavte objects that have FLAG_ACTIVATE_ON_PUSH/RELEASE set. 34 * state is a true/false flag that will actiavte objects that have FLAG_ACTIVATE_ON_PUSH/RELEASE set.
40 * The source argument can be 0 or the source object for this activation. 35 * The source argument can be 0 or the source object for this activation.
41 */ 36 */
37void
42void activate_connection_link (objectlink *ol, bool state, object *source = 0) 38activate_connection_link (objectlink * ol, bool state, object *source = 0)
43{ 39{
44 object *tmp = 0;
45
46 for (; ol; ol = ol->next) 40 for (; ol; ol = ol->next)
47 { 41 {
48 if (!ol->ob || ol->ob->count != ol->id) 42 if (!ol->ob)
49 { 43 {
50 LOG (llevError, "Internal error in activate_connection_link (%ld).\n", ol->id); 44 LOG (llevError, "Internal error in activate_connection_link.\n");
51 continue; 45 continue;
52 } 46 }
47
53 /* a button link object can become freed when the map is saving. As 48 /* a button link object can become freed when the map is saving. As
54 * a map is saved, objects are removed and freed, and if an object is 49 * a map is saved, objects are removed and freed, and if an object is
55 * on top of a button, this function is eventually called. If a map 50 * on top of a button, this function is eventually called. If a map
56 * is getting moved out of memory, the status of buttons and levers 51 * is getting moved out of memory, the status of buttons and levers
57 * probably isn't important - it will get sorted out when the map is 52 * probably isn't important - it will get sorted out when the map is
58 * re-loaded. As such, just exit this function if that is the case. 53 * re-loaded. As such, just exit this function if that is the case.
59 */ 54 */
60 55
61 if (QUERY_FLAG (ol->ob, FLAG_FREED)) 56 if (QUERY_FLAG (ol->ob, FLAG_FREED))
62 return; 57 return;
58
63 tmp = ol->ob; 59 object *tmp = ol->ob;
64 60
65 /* if the criteria isn't appropriate, don't do anything */ 61 /* if the criteria isn't appropriate, don't do anything */
66 if (state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_PUSH)) 62 if (state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_PUSH))
67 continue; 63 continue;
68 if (!state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_RELEASE)) 64 if (!state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_RELEASE))
69 continue; 65 continue;
70 66
71 switch (tmp->type) 67 switch (tmp->type)
72 { 68 {
73 case GATE: 69 case GATE:
74 case HOLE: 70 case HOLE:
75 tmp->value = tmp->stats.maxsp ? !state : state; 71 tmp->value = tmp->stats.maxsp ? !state : state;
76 tmp->speed = 0.5; 72 tmp->set_speed (0.5);
77 update_ob_speed (tmp);
78 break; 73 break;
79 74
80 case CF_HANDLE: 75 case CF_HANDLE:
81 SET_ANIMATION (tmp, 76 SET_ANIMATION (tmp, (tmp->value = tmp->stats.maxsp ? !state : state));
82 (tmp->value =
83 tmp->stats.maxsp ? !state : state));
84 update_object (tmp, UP_OBJ_FACE); 77 update_object (tmp, UP_OBJ_FACE);
85 break; 78 break;
86 79
87 case SIGN: 80 case SIGN:
88 if (!tmp->stats.food || tmp->last_eat < tmp->stats.food) 81 if (!tmp->stats.food || tmp->last_eat < tmp->stats.food)
89 { 82 {
90 new_info_map (NDI_UNIQUE | NDI_NAVY, tmp->map, tmp->msg); 83 new_info_map (NDI_UNIQUE | NDI_NAVY, tmp->map, tmp->msg);
91 if (tmp->stats.food) 84 if (tmp->stats.food)
92 tmp->last_eat++; 85 tmp->last_eat++;
93 } 86 }
94 break; 87 break;
95 88
96 case ALTAR: 89 case ALTAR:
97 tmp->value = 1; 90 tmp->value = 1;
98 SET_ANIMATION (tmp, tmp->value); 91 SET_ANIMATION (tmp, tmp->value);
99 update_object (tmp, UP_OBJ_FACE); 92 update_object (tmp, UP_OBJ_FACE);
100 break; 93 break;
101 94
102 case BUTTON: 95 case BUTTON:
103 case PEDESTAL: 96 case PEDESTAL:
104 tmp->value = state; 97 tmp->value = state;
105 SET_ANIMATION (tmp, tmp->value); 98 SET_ANIMATION (tmp, tmp->value);
106 update_object (tmp, UP_OBJ_FACE); 99 update_object (tmp, UP_OBJ_FACE);
107 break; 100 break;
108 101
109 case MOOD_FLOOR: 102 case MOOD_FLOOR:
110 do_mood_floor (tmp, source); 103 do_mood_floor (tmp, source);
111 break; 104 break;
112 105
113 case TIMED_GATE: 106 case TIMED_GATE:
114 tmp->speed = tmp->arch->clone.speed; 107 tmp->set_speed (tmp->arch->clone.speed);
115 update_ob_speed (tmp); /* original values */
116 tmp->value = tmp->arch->clone.value; 108 tmp->value = tmp->arch->clone.value;
117 tmp->stats.sp = 1; 109 tmp->stats.sp = 1;
118 tmp->stats.hp = tmp->stats.maxhp; 110 tmp->stats.hp = tmp->stats.maxhp;
119 /* Handle multipart gates. We copy the value for the other parts 111 /* Handle multipart gates. We copy the value for the other parts
120 * from the head - this ensures that the data will consistent 112 * from the head - this ensures that the data will consistent
121 */ 113 */
122 for (tmp = tmp->more; tmp != NULL; tmp = tmp->more) 114 for (tmp = tmp->more; tmp; tmp = tmp->more)
123 { 115 {
124 tmp->speed = tmp->head->speed;
125 tmp->value = tmp->head->value; 116 tmp->value = tmp->head->value;
126 tmp->stats.sp = tmp->head->stats.sp; 117 tmp->stats.sp = tmp->head->stats.sp;
127 tmp->stats.hp = tmp->head->stats.hp; 118 tmp->stats.hp = tmp->head->stats.hp;
128 update_ob_speed (tmp); 119 tmp->set_speed (tmp->head->speed);
129 } 120 }
130 break; 121 break;
131 122
132 case DIRECTOR: 123 case DIRECTOR:
133 case FIREWALL: 124 case FIREWALL:
134 if (!QUERY_FLAG (tmp, FLAG_ANIMATE) && tmp->type == FIREWALL) 125 if (!QUERY_FLAG (tmp, FLAG_ANIMATE) && tmp->type == FIREWALL)
135 move_firewall (tmp); 126 move_firewall (tmp);
136 else 127 else
137 { 128 {
138 if ((tmp->stats.sp += tmp->stats.maxsp) > 8) /* next direction */ 129 if ((tmp->stats.sp += tmp->stats.maxsp) > 8) /* next direction */
139 tmp->stats.sp = ((tmp->stats.sp - 1) % 8) + 1; 130 tmp->stats.sp = ((tmp->stats.sp - 1) % 8) + 1;
140 animate_turning (tmp); 131 animate_turning (tmp);
141 } 132 }
142 break; 133 break;
143 134
144 case TELEPORTER: 135 case TELEPORTER:
145 move_teleporter (tmp); 136 move_teleporter (tmp);
146 break; 137 break;
147 138
148 case CREATOR: 139 case CREATOR:
149 move_creator (tmp); 140 move_creator (tmp);
150 break; 141 break;
151 142
152 case TRIGGER_MARKER: 143 case TRIGGER_MARKER:
153 move_marker (tmp); 144 move_marker (tmp);
154 break; 145 break;
155 146
156 case DUPLICATOR: 147 case DUPLICATOR:
157 move_duplicator (tmp); 148 move_duplicator (tmp);
158 break; 149 break;
159 } 150 }
160 } 151 }
161} 152}
162 153
163/* 154/*
170 * altars/pedestals/holes in the whole map. 161 * altars/pedestals/holes in the whole map.
171 * Changed the routine to loop through _all_ objects. 162 * Changed the routine to loop through _all_ objects.
172 * Better hurry with that linked list... 163 * Better hurry with that linked list...
173 * 164 *
174 */ 165 */
166void
175void push_button (object *op) 167push_button (object *op)
176{ 168{
177 oblinkpt *obp = get_button_links (op); 169 oblinkpt *obp = get_button_links (op);
178 170
179 if (!obp) 171 if (!obp)
180 return; 172 return;
181 173
182 if (INVOKE_MAP (TRIGGER, op->map, ARG_INT64(obp->value), ARG_INT(op->value))) 174 if (INVOKE_MAP (TRIGGER, op->map, ARG_INT64 (obp->value), ARG_INT (op->value)))
183 return; 175 return;
184 176
185 activate_connection_link (obp->link, op->value, op); 177 activate_connection_link (obp->link, op->value, op);
186} 178}
187 179
191 * only a map, a connection value and a true or false flag that indicated whether 183 * only a map, a connection value and a true or false flag that indicated whether
192 * the connection was 'state' or 'released'. So that you can activate objects 184 * the connection was 'state' or 'released'. So that you can activate objects
193 * who have FLAG_ACTIVATE_ON_PUSH/RELEASE set properly. 185 * who have FLAG_ACTIVATE_ON_PUSH/RELEASE set properly.
194 * 186 *
195 */ 187 */
188void
196void activate_connection (mapstruct *map, long connection, bool state) 189activate_connection (maptile *map, long connection, bool state)
197{ 190{
198 if (INVOKE_MAP (TRIGGER, map, ARG_INT64(connection), ARG_INT(state))) 191 if (INVOKE_MAP (TRIGGER, map, ARG_INT64 (connection), ARG_INT (state)))
199 return; 192 return;
200 193
201 oblinkpt *obp = get_connection_links (map, connection); 194 oblinkpt *obp = get_connection_links (map, connection);
195
202 if (obp) 196 if (obp)
203 activate_connection_link (obp->link, state); 197 activate_connection_link (obp->link, state);
204} 198}
205 199
206/* 200/*
207 * Updates everything connected with the button op. 201 * Updates everything connected with the button op.
208 * After changing the state of a button, this function must be called 202 * After changing the state of a button, this function must be called
209 * to make sure that all gates and other buttons connected to the 203 * to make sure that all gates and other buttons connected to the
210 * button reacts to the (eventual) change of state. 204 * button reacts to the (eventual) change of state.
211 */ 205 */
212 206void
213void update_button(object *op) { 207update_button (object *op)
208{
214 object *ab,*tmp,*head; 209 object *ab, *tmp, *head;
215 int tot,any_down=0, old_value=op->value; 210 int tot, any_down = 0, old_value = op->value;
216 oblinkpt *obp = 0; 211 oblinkpt *obp = 0;
217 objectlink *ol; 212 objectlink *ol;
218 213
219 obp = get_button_links (op); 214 obp = get_button_links (op);
220 /* LOG(llevDebug, "update_button: %s (%d)\n", op->name, op->count); */ 215 /* LOG(llevDebug, "update_button: %s (%d)\n", op->name, op->count); */
221 if (obp) 216 if (obp)
222 for (ol = obp->link; ol; ol = ol->next) { 217 for (ol = obp->link; ol; ol = ol->next)
223 if (!ol->ob || ol->ob->count != ol->id) { 218 {
219 if (!ol->ob)
220 {
224 LOG(llevDebug, "Internal error in update_button (%s).\n", op->name); 221 LOG (llevDebug, "Internal error in update_button (%s).\n", &op->name);
225 continue; 222 continue;
226 } 223 }
224
227 tmp = ol->ob; 225 tmp = ol->ob;
228 if (tmp->type==BUTTON) { 226 if (tmp->type == BUTTON)
227 {
229 for(ab=tmp->above,tot=0;ab!=NULL;ab=ab->above) 228 for (ab = tmp->above, tot = 0; ab != NULL; ab = ab->above)
230 /* Bug? The pedestal code below looks for the head of 229 /* Bug? The pedestal code below looks for the head of
231 * the object, this bit doesn't. I'd think we should check 230 * the object, this bit doesn't. I'd think we should check
232 * for head here also. Maybe it also makese sense to 231 * for head here also. Maybe it also makese sense to
233 * make the for ab=tmp->above loop common, and alter 232 * make the for ab=tmp->above loop common, and alter
234 * behaviour based on object within that loop? 233 * behaviour based on object within that loop?
235 */ 234 */
236 235
237 /* Basically, if the move_type matches that on what the 236 /* Basically, if the move_type matches that on what the
238 * button wants, we count it. The second check is so that 237 * button wants, we count it. The second check is so that
239 * objects don't move (swords, etc) will count. Note that 238 * objects don't move (swords, etc) will count. Note that
240 * this means that more work is needed to make buttons 239 * this means that more work is needed to make buttons
241 * that are only triggered by flying objects. 240 * that are only triggered by flying objects.
242 */ 241 */
243 if ((ab->move_type & tmp->move_on) || ab->move_type==0 ) 242 if ((ab->move_type & tmp->move_on) || ab->move_type == 0)
244 tot+=ab->weight*(ab->nrof?ab->nrof:1)+ab->carrying; 243 tot += ab->weight * (ab->nrof ? ab->nrof : 1) + ab->carrying;
245 244
246 tmp->value=(tot>=tmp->weight)?1:0; 245 tmp->value = (tot >= tmp->weight) ? 1 : 0;
247 if(tmp->value) 246 if (tmp->value)
248 any_down=1; 247 any_down = 1;
248 }
249 } else if (tmp->type == PEDESTAL) { 249 else if (tmp->type == PEDESTAL)
250 {
250 tmp->value = 0; 251 tmp->value = 0;
251 for(ab=tmp->above; ab!=NULL; ab=ab->above) { 252 for (ab = tmp->above; ab != NULL; ab = ab->above)
253 {
252 head = ab->head ? ab->head : ab; 254 head = ab->head ? ab->head : ab;
253 /* Same note regarding move_type for buttons above apply here. */ 255 /* Same note regarding move_type for buttons above apply here. */
254 if ( ((head->move_type & tmp->move_on) || ab->move_type==0) && 256 if (((head->move_type & tmp->move_on) || ab->move_type == 0) &&
255 (head->race==tmp->slaying || 257 (head->race == tmp->slaying ||
256 ((head->type==SPECIAL_KEY) && (head->slaying==tmp->slaying)) || 258 ((head->type == SPECIAL_KEY) && (head->slaying == tmp->slaying)) ||
257 (!strcmp (tmp->slaying, "player") && 259 (!strcmp (tmp->slaying, "player") && head->type == PLAYER)))
258 head->type == PLAYER)))
259 tmp->value = 1; 260 tmp->value = 1;
260 } 261 }
261 if(tmp->value) 262 if (tmp->value)
262 any_down=1; 263 any_down = 1;
263 } 264 }
264 } 265 }
265 if(any_down) /* If any other buttons were down, force this to remain down */ 266 if (any_down) /* If any other buttons were down, force this to remain down */
266 op->value=1; 267 op->value = 1;
267 268
268 /* If this button hasn't changed, don't do anything */ 269 /* If this button hasn't changed, don't do anything */
269 if (op->value != old_value) { 270 if (op->value != old_value)
271 {
270 SET_ANIMATION(op, op->value); 272 SET_ANIMATION (op, op->value);
271 update_object(op, UP_OBJ_FACE); 273 update_object (op, UP_OBJ_FACE);
272 push_button(op); /* Make all other buttons the same */ 274 push_button (op); /* Make all other buttons the same */
273 }
274}
275
276/*
277 * Updates every button on the map (by calling update_button() for them).
278 */
279
280void update_buttons(mapstruct *m) {
281 objectlink *ol;
282 oblinkpt *obp;
283 for (obp = m->buttons; obp; obp = obp->next)
284 for (ol = obp->link; ol; ol = ol->next) {
285 if (!ol->ob || ol->ob->count != ol->id) {
286 LOG(llevError, "Internal error in update_button (%s (%dx%d):%d, connected %ld).\n",
287 ol->ob?ol->ob->name:"null",
288 ol->ob?ol->ob->x:-1,
289 ol->ob?ol->ob->y:-1,
290 ol->id,
291 obp->value);
292 continue;
293 } 275 }
294 if (ol->ob->type==BUTTON || ol->ob->type==PEDESTAL)
295 {
296 update_button(ol->ob);
297 break;
298 }
299 }
300} 276}
301 277
278void
302void use_trigger(object *op) 279use_trigger (object *op)
303{ 280{
304
305 /* Toggle value */ 281 /* Toggle value */
306 op->value = !op->value; 282 op->value = !op->value;
307 push_button(op); 283 push_button (op);
308} 284}
309 285
310/* 286/*
311 * Note: animate_object should be used instead of this, 287 * Note: animate_object should be used instead of this,
312 * but it can't handle animations in the 8 directions 288 * but it can't handle animations in the 8 directions
313 */ 289 */
314 290void
315void animate_turning(object *op) /* only one part objects */ 291animate_turning (object *op) /* only one part objects */
316{ 292{
317 if (++op->state >= NUM_ANIMATIONS(op)/8) 293 if (++op->state >= NUM_ANIMATIONS (op) / 8)
318 op->state=0; 294 op->state = 0;
319 SET_ANIMATION(op, (op->stats.sp-1) * NUM_ANIMATIONS(op) / 8 + 295 SET_ANIMATION (op, (op->stats.sp - 1) * NUM_ANIMATIONS (op) / 8 + op->state);
320 op->state);
321 update_object(op,UP_OBJ_FACE); 296 update_object (op, UP_OBJ_FACE);
322} 297}
323 298
324#define ARCH_SACRIFICE(xyz) ((xyz)->slaying) 299#define ARCH_SACRIFICE(xyz) ((xyz)->slaying)
325#define NROF_SACRIFICE(xyz) ((uint32)(xyz)->stats.food) 300#define NROF_SACRIFICE(xyz) ((uint32)(xyz)->stats.food)
326 301
332 * 307 *
333 * 0.93.4: Linked objects (ie, objects that are connected) can not be 308 * 0.93.4: Linked objects (ie, objects that are connected) can not be
334 * sacrificed. This fixes a bug of trying to put multiple altars/related 309 * sacrificed. This fixes a bug of trying to put multiple altars/related
335 * objects on the same space that take the same sacrifice. 310 * objects on the same space that take the same sacrifice.
336 */ 311 */
337 312
313int
338int check_altar_sacrifice (const object *altar, const object *sacrifice) 314check_altar_sacrifice (const object *altar, const object *sacrifice)
339{ 315{
340 if ( ! QUERY_FLAG (sacrifice, FLAG_ALIVE) 316 if (!QUERY_FLAG (sacrifice, FLAG_ALIVE) && !QUERY_FLAG (sacrifice, FLAG_IS_LINKED) && sacrifice->type != PLAYER)
341 && ! QUERY_FLAG (sacrifice, FLAG_IS_LINKED)
342 && sacrifice->type != PLAYER)
343 { 317 {
344 if ((ARCH_SACRIFICE(altar) == sacrifice->arch->name || 318 if ((ARCH_SACRIFICE (altar) == sacrifice->arch->name ||
345 ARCH_SACRIFICE(altar) == sacrifice->name || 319 ARCH_SACRIFICE (altar) == sacrifice->name ||
346 ARCH_SACRIFICE(altar) == sacrifice->slaying || 320 ARCH_SACRIFICE (altar) == sacrifice->slaying ||
347 (!strcmp(ARCH_SACRIFICE(altar),query_base_name(sacrifice,0)))) 321 (!strcmp (ARCH_SACRIFICE (altar), query_base_name (sacrifice, 0))))
348 && NROF_SACRIFICE(altar) <= (sacrifice->nrof?sacrifice->nrof:1)) 322 && NROF_SACRIFICE (altar) <= (sacrifice->nrof ? sacrifice->nrof : 1))
349 return 1; 323 return 1;
324
350 if (strcmp (ARCH_SACRIFICE(altar), "money") == 0 325 if (strcmp (ARCH_SACRIFICE (altar), "money") == 0
351 && sacrifice->type == MONEY
352 && sacrifice->nrof * sacrifice->value >= NROF_SACRIFICE(altar)) 326 && sacrifice->type == MONEY && sacrifice->nrof * sacrifice->value >= NROF_SACRIFICE (altar))
353 return 1; 327 return 1;
354 } 328 }
329
355 return 0; 330 return 0;
356} 331}
357
358 332
359/* 333/*
360 * operate_altar checks if sacrifice was accepted and removes sacrificed 334 * operate_altar checks if sacrifice was accepted and removes sacrificed
361 * objects. If sacrifice was succeed return 1 else 0. Might be better to 335 * objects. If sacrifice was succeed return 1 else 0. Might be better to
362 * call check_altar_sacrifice (above) than depend on the return value, 336 * call check_altar_sacrifice (above) than depend on the return value,
363 * since operate_altar will remove the sacrifice also. 337 * since operate_altar will remove the sacrifice also.
364 * 338 *
365 * If this function returns 1, '*sacrifice' is modified to point to the 339 * If this function returns 1, '*sacrifice' is modified to point to the
366 * remaining sacrifice, or is set to NULL if the sacrifice was used up. 340 * remaining sacrifice, or is set to NULL if the sacrifice was used up.
367 */ 341 */
368 342int
369int operate_altar (object *altar, object **sacrifice) 343operate_altar (object *altar, object **sacrifice)
370{ 344{
371
372 if ( ! altar->map) { 345 if (!altar->map)
346 {
373 LOG (llevError, "BUG: operate_altar(): altar has no map\n"); 347 LOG (llevError, "BUG: operate_altar(): altar has no map\n");
374 return 0; 348 return 0;
375 } 349 }
376 350
377 if (!altar->slaying || altar->value) 351 if (!altar->slaying || altar->value)
378 return 0; 352 return 0;
379 353
380 if ( ! check_altar_sacrifice (altar, *sacrifice)) 354 if (!check_altar_sacrifice (altar, *sacrifice))
381 return 0; 355 return 0;
382 356
383 /* check_altar_sacrifice should have already verified that enough money 357 /* check_altar_sacrifice should have already verified that enough money
384 * has been dropped. 358 * has been dropped.
385 */ 359 */
386 if (!strcmp(ARCH_SACRIFICE(altar), "money")) { 360 if (!strcmp (ARCH_SACRIFICE (altar), "money"))
361 {
387 int number=NROF_SACRIFICE(altar) / (*sacrifice)->value; 362 int number = NROF_SACRIFICE (altar) / (*sacrifice)->value;
388 363
389 /* Round up any sacrifices. Altars don't make change either */ 364 /* Round up any sacrifices. Altars don't make change either */
390 if (NROF_SACRIFICE(altar) % (*sacrifice)->value) number++; 365 if (NROF_SACRIFICE (altar) % (*sacrifice)->value)
366 number++;
367
391 *sacrifice = decrease_ob_nr (*sacrifice, number); 368 *sacrifice = decrease_ob_nr (*sacrifice, number);
392 } 369 }
393 else 370 else
394 *sacrifice = decrease_ob_nr (*sacrifice, NROF_SACRIFICE(altar)); 371 *sacrifice = decrease_ob_nr (*sacrifice, NROF_SACRIFICE (altar));
395 372
396 if (altar->msg) 373 if (altar->msg)
397 new_info_map(NDI_BLACK, altar->map, altar->msg); 374 new_info_map (NDI_BLACK, altar->map, altar->msg);
375
398 return 1; 376 return 1;
399} 377}
400 378
379void
401void trigger_move (object *op, int state) /* 1 down and 0 up */ 380trigger_move (object *op, int state) /* 1 down and 0 up */
402{ 381{
403 op->stats.wc = state; 382 op->stats.wc = state;
404 if (state) { 383 if (state)
384 {
405 use_trigger(op); 385 use_trigger (op);
406 if (op->stats.exp > 0) /* check sanity */ 386 op->set_speed (op->stats.exp > 0 ? 1. / op->stats.exp : 1.);
407 op->speed = 1.0 / op->stats.exp;
408 else
409 op->speed = 1.0;
410 update_ob_speed(op);
411 op->speed_left = -1; 387 op->speed_left = -1;
412 } else { 388 }
389 else
390 {
413 use_trigger(op); 391 use_trigger (op);
414 op->speed = 0; 392 op->set_speed (0);
415 update_ob_speed(op);
416 } 393 }
417} 394}
418 395
419 396
420/* 397/*
427 * 404 *
428 * TRIGGER: Returns 1 if handle could be moved, 0 if not. 405 * TRIGGER: Returns 1 if handle could be moved, 0 if not.
429 * 406 *
430 * TRIGGER_BUTTON, TRIGGER_PEDESTAL: Returns 0. 407 * TRIGGER_BUTTON, TRIGGER_PEDESTAL: Returns 0.
431 */ 408 */
409int
432int check_trigger (object *op, object *cause) 410check_trigger (object *op, object *cause)
433{ 411{
434 object *tmp; 412 object *tmp;
435 int push = 0, tot = 0; 413 int push = 0, tot = 0;
436 int in_movement = op->stats.wc || op->speed; 414 int in_movement = op->stats.wc || op->speed;
437 415
438 switch (op->type) { 416 switch (op->type)
417 {
439 case TRIGGER_BUTTON: 418 case TRIGGER_BUTTON:
440 if (op->weight > 0) { 419 if (op->weight > 0)
420 {
441 if (cause) { 421 if (cause)
422 {
442 for (tmp = op->above; tmp; tmp = tmp->above) 423 for (tmp = op->above; tmp; tmp = tmp->above)
443 /* Comment reproduced from update_buttons(): */ 424 /* Comment reproduced from update_buttons(): */
444 /* Basically, if the move_type matches that on what the 425 /* Basically, if the move_type matches that on what the
445 * button wants, we count it. The second check is so that 426 * button wants, we count it. The second check is so that
446 * objects that don't move (swords, etc) will count. Note that 427 * objects that don't move (swords, etc) will count. Note that
447 * this means that more work is needed to make buttons 428 * this means that more work is needed to make buttons
448 * that are only triggered by flying objects. 429 * that are only triggered by flying objects.
449 */ 430 */
450 431
451 if ((tmp->move_type & op->move_on) || tmp->move_type==0) { 432 if ((tmp->move_type & op->move_on) || tmp->move_type == 0)
433 {
452 tot += tmp->weight * (tmp->nrof ? tmp->nrof : 1) 434 tot += tmp->weight * (tmp->nrof ? tmp->nrof : 1) + tmp->carrying;
453 + tmp->carrying;
454 } 435 }
455 if (tot >= op->weight) 436 if (tot >= op->weight)
456 push = 1; 437 push = 1;
457 if (op->stats.ac == push) 438 if (op->stats.ac == push)
458 return 0; 439 return 0;
459 op->stats.ac = push; 440 op->stats.ac = push;
460 if (NUM_ANIMATIONS(op) > 1) { 441 if (NUM_ANIMATIONS (op) > 1)
442 {
461 SET_ANIMATION (op, push); 443 SET_ANIMATION (op, push);
462 update_object (op, UP_OBJ_FACE); 444 update_object (op, UP_OBJ_FACE);
463 } 445 }
464 if (in_movement || ! push) 446 if (in_movement || !push)
465 return 0; 447 return 0;
466 } 448 }
467 trigger_move (op, push); 449 trigger_move (op, push);
468 } 450 }
469 return 0; 451 return 0;
470 452
471 case TRIGGER_PEDESTAL: 453 case TRIGGER_PEDESTAL:
472 if (cause) { 454 if (cause)
455 {
473 for (tmp = op->above; tmp; tmp = tmp->above) { 456 for (tmp = op->above; tmp; tmp = tmp->above)
457 {
474 object *head = tmp->head ? tmp->head : tmp; 458 object *head = tmp->head ? tmp->head : tmp;
475 459
476 /* See comment in TRIGGER_BUTTON about move_types */ 460 /* See comment in TRIGGER_BUTTON about move_types */
477 if (((head->move_type & op->move_on) || head->move_type==0) 461 if (((head->move_type & op->move_on) || head->move_type == 0)
478 && (head->race==op->slaying ||
479 (!strcmp (op->slaying, "player") && head->type == PLAYER))) { 462 && (head->race == op->slaying || (!strcmp (op->slaying, "player") && head->type == PLAYER)))
463 {
480 push = 1; 464 push = 1;
481 break; 465 break;
482 } 466 }
483 } 467 }
484 if (op->stats.ac == push) 468 if (op->stats.ac == push)
485 return 0; 469 return 0;
486 op->stats.ac = push; 470 op->stats.ac = push;
487 if (NUM_ANIMATIONS(op) > 1) { 471 if (NUM_ANIMATIONS (op) > 1)
472 {
488 SET_ANIMATION (op, push); 473 SET_ANIMATION (op, push);
489 update_object (op, UP_OBJ_FACE); 474 update_object (op, UP_OBJ_FACE);
490 } 475 }
491 update_object(op,UP_OBJ_FACE); 476 update_object (op, UP_OBJ_FACE);
492 if (in_movement || ! push) 477 if (in_movement || !push)
493 return 0; 478 return 0;
494 } 479 }
495 trigger_move (op, push); 480 trigger_move (op, push);
496 return 0; 481 return 0;
497 482
498 case TRIGGER_ALTAR: 483 case TRIGGER_ALTAR:
499 if (cause) { 484 if (cause)
485 {
500 if (in_movement) 486 if (in_movement)
501 return 0; 487 return 0;
502 if (operate_altar (op, &cause)) { 488 if (operate_altar (op, &cause))
489 {
503 if (NUM_ANIMATIONS(op) > 1) { 490 if (NUM_ANIMATIONS (op) > 1)
491 {
504 SET_ANIMATION (op, 1); 492 SET_ANIMATION (op, 1);
505 update_object(op, UP_OBJ_FACE); 493 update_object (op, UP_OBJ_FACE);
506 } 494 }
507 if (op->last_sp >= 0) { 495 if (op->last_sp >= 0)
496 {
508 trigger_move (op, 1); 497 trigger_move (op, 1);
509 if (op->last_sp > 0) 498 if (op->last_sp > 0)
510 op->last_sp = -op->last_sp; 499 op->last_sp = -op->last_sp;
511 } 500 }
512 else { 501 else
502 {
513 /* for trigger altar with last_sp, the ON/OFF 503 /* for trigger altar with last_sp, the ON/OFF
514 * status (-> +/- value) is "simulated": 504 * status (-> +/- value) is "simulated":
515 */ 505 */
516 op->value = !op->value; 506 op->value = !op->value;
517 trigger_move (op, 1); 507 trigger_move (op, 1);
518 op->last_sp = -op->last_sp; 508 op->last_sp = -op->last_sp;
519 op->value = !op->value; 509 op->value = !op->value;
520 } 510 }
521 return cause == NULL; 511 return cause == NULL;
522 } else {
523 return 0;
524 } 512 }
525 } else { 513 else
526 if (NUM_ANIMATIONS(op) > 1) {
527 SET_ANIMATION (op, 0);
528 update_object(op, UP_OBJ_FACE);
529 } 514 {
530 515 return 0;
531 /* If trigger_altar has "last_sp > 0" set on the map,
532 * it will push the connected value only once per sacrifice.
533 * Otherwise (default), the connected value will be
534 * pushed twice: First by sacrifice, second by reset! -AV
535 */
536 if (!op->last_sp)
537 trigger_move (op, 0);
538 else {
539 op->stats.wc = 0;
540 op->value = !op->value;
541 op->speed = 0;
542 update_ob_speed(op);
543 } 516 }
544 } 517 }
518 else
519 {
520 if (NUM_ANIMATIONS (op) > 1)
521 {
522 SET_ANIMATION (op, 0);
523 update_object (op, UP_OBJ_FACE);
524 }
525
526 /* If trigger_altar has "last_sp > 0" set on the map,
527 * it will push the connected value only once per sacrifice.
528 * Otherwise (default), the connected value will be
529 * pushed twice: First by sacrifice, second by reset! -AV
530 */
531 if (!op->last_sp)
532 trigger_move (op, 0);
533 else
534 {
535 op->stats.wc = 0;
536 op->value = !op->value;
537 op->set_speed (0);
538 }
539 }
545 return 0; 540 return 0;
546 541
547 case TRIGGER: 542 case TRIGGER:
548 if (cause) { 543 if (cause)
544 {
549 if (in_movement) 545 if (in_movement)
550 return 0; 546 return 0;
547
551 push = 1; 548 push = 1;
552 } 549 }
550
553 if (NUM_ANIMATIONS(op) > 1) { 551 if (NUM_ANIMATIONS (op) > 1)
552 {
554 SET_ANIMATION (op, push); 553 SET_ANIMATION (op, push);
555 update_object(op, UP_OBJ_FACE); 554 update_object (op, UP_OBJ_FACE);
556 } 555 }
556
557 trigger_move (op, push); 557 trigger_move (op, push);
558 return 1; 558 return 1;
559 559
560 default: 560 default:
561 LOG(llevDebug, "Unknown trigger type: %s (%d)\n", op->name, op->type); 561 LOG (llevDebug, "Unknown trigger type: %s (%d)\n", &op->name, op->type);
562 return 0; 562 return 0;
563 } 563 }
564} 564}
565 565
566void
566void add_button_link(object *button, mapstruct *map, int connected) { 567add_button_link (object *button, maptile *map, int connected)
568{
567 oblinkpt *obp; 569 oblinkpt *obp;
568 objectlink *ol = get_objectlink(); 570 objectlink *ol = get_objectlink ();
569 571
570 if (!map) { 572 if (!map)
573 {
571 LOG(llevError, "Tried to add button-link without map.\n"); 574 LOG (llevError, "Tried to add button-link without map.\n");
572 return; 575 return;
573 } 576 }
577
574 if (!editor) button->path_attuned = connected; /* peterm: I need this so I can rebuild 578 button->path_attuned = connected; /* peterm: I need this so I can rebuild
575 a connected map from a template map. */ 579 a connected map from a template map. */
576/* LOG(llevDebug,"adding button %s (%d)\n", button->name, connected);*/
577 580
578 SET_FLAG(button,FLAG_IS_LINKED); 581 SET_FLAG (button, FLAG_IS_LINKED);
579 582
580 ol->ob = button; 583 ol->ob = button;
581 ol->id = button->count;
582 584
583 for (obp = map->buttons; obp && obp->value != connected; obp = obp->next); 585 for (obp = map->buttons; obp && obp->value != connected; obp = obp->next)
586 ;
584 587
585 if (obp) { 588 if (obp)
589 {
586 ol->next = obp->link; 590 ol->next = obp->link;
587 obp->link = ol; 591 obp->link = ol;
592 }
588 } else { 593 else
594 {
589 obp = get_objectlinkpt(); 595 obp = get_objectlinkpt ();
590 obp->value = connected; 596 obp->value = connected;
591 597
592 obp->next = map->buttons; 598 obp->next = map->buttons;
593 map->buttons = obp; 599 map->buttons = obp;
594 obp->link = ol; 600 obp->link = ol;
595 } 601 }
596} 602}
597 603
598/* 604/*
599 * Remove the object from the linked lists of buttons in the map. 605 * Remove the object from the linked lists of buttons in the map.
600 * This is only needed by editors. 606 * This is only needed by editors.
601 */ 607 */
602 608
609void
603void remove_button_link(object *op) { 610remove_button_link (object *op)
611{
604 oblinkpt *obp; 612 oblinkpt *obp;
605 objectlink **olp, *ol; 613 objectlink **olp, *ol;
606 614
607 if (op->map == NULL) { 615 if (op->map == NULL)
616 {
608 LOG(llevError, "remove_button_link() in object without map.\n"); 617 LOG (llevError, "remove_button_link() in object without map.\n");
609 return; 618 return;
610 } 619 }
620
611 if (!QUERY_FLAG(op,FLAG_IS_LINKED)) { 621 if (!QUERY_FLAG (op, FLAG_IS_LINKED))
622 {
612 LOG(llevError, "remove_button_linked() in unlinked object.\n"); 623 LOG (llevError, "remove_button_linked() in unlinked object.\n");
613 return; 624 return;
614 } 625 }
626
615 for (obp = op->map->buttons; obp; obp = obp->next) 627 for (obp = op->map->buttons; obp; obp = obp->next)
616 for (olp = &obp->link; (ol = *olp); olp = &ol->next) 628 for (olp = &obp->link; (ol = *olp); olp = &ol->next)
617 if (ol->ob == op) { 629 if (ol->ob == op)
630 {
631
618/* LOG(llevDebug, "Removed link %d in button %s and map %s.\n", 632/* LOG(llevDebug, "Removed link %d in button %s and map %s.\n",
619 obp->value, op->name, op->map->path); 633 obp->value, op->name, op->map->path);
620*/ 634*/
621 *olp = ol->next; 635 *olp = ol->next;
622 free(ol); 636 delete ol;
623 return; 637 return;
624 } 638 }
639
625 LOG(llevError, "remove_button_linked(): couldn't find object.\n"); 640 LOG (llevError, "remove_button_linked(): couldn't find object.\n");
626 CLEAR_FLAG(op,FLAG_IS_LINKED); 641 CLEAR_FLAG (op, FLAG_IS_LINKED);
627} 642}
628 643
629/* 644/*
630 * Gets the objectlink for this connection from the map. 645 * Gets the objectlink for this connection from the map.
631 */ 646 */
647oblinkpt *
632oblinkpt *get_connection_links (mapstruct *map, long connection) 648get_connection_links (maptile *map, long connection)
633{ 649{
634 for (oblinkpt *obp = map->buttons; obp; obp = obp->next) 650 for (oblinkpt * obp = map->buttons; obp; obp = obp->next)
635 if (obp->value == connection) 651 if (obp->value == connection)
636 return obp; 652 return obp;
653
637 return 0; 654 return 0;
638} 655}
639 656
640/* 657/*
641 * Return the first objectlink in the objects linked to this one 658 * Return the first objectlink in the objects linked to this one
642 */ 659 */
643 660
661oblinkpt *
644oblinkpt *get_button_links(const object *button) { 662get_button_links (const object *button)
663{
645 oblinkpt *obp; 664 oblinkpt *obp;
646 objectlink *ol; 665 objectlink *ol;
647 666
648 if (!button->map) 667 if (!button->map)
649 return NULL; 668 return NULL;
669
650 for (obp = button->map->buttons; obp; obp = obp->next) 670 for (obp = button->map->buttons; obp; obp = obp->next)
651 for (ol = obp->link; ol; ol = ol->next) 671 for (ol = obp->link; ol; ol = ol->next)
652 if (ol->ob == button && ol->id == button->count) 672 if (ol->ob == button)
653 return obp; 673 return obp;
674
654 return NULL; 675 return NULL;
655} 676}
656 677
657/* 678/*
658 * Made as a separate function to increase efficiency 679 * Made as a separate function to increase efficiency
659 */ 680 */
660 681
682int
661int get_button_value(const object *button) { 683get_button_value (const object *button)
684{
662 oblinkpt *obp; 685 oblinkpt *obp;
663 objectlink *ol; 686 objectlink *ol;
664 687
665 if (!button->map) 688 if (!button->map)
666 return 0; 689 return 0;
667 for (obp = button->map->buttons; obp; obp = obp->next) 690 for (obp = button->map->buttons; obp; obp = obp->next)
668 for (ol = obp->link; ol; ol = ol->next) 691 for (ol = obp->link; ol; ol = ol->next)
669 if (ol->ob == button && ol->id == button->count) 692 if (ol->ob == button)
670 return obp->value; 693 return obp->value;
671 return 0; 694 return 0;
672} 695}
673 696
674/* This routine makes monsters who are 697/* This routine makes monsters who are
677 * If floor is to be triggered must have 700 * If floor is to be triggered must have
678 * a speed of zero (default is 1 for all 701 * a speed of zero (default is 1 for all
679 * but the charm floor type). 702 * but the charm floor type).
680 * by b.t. thomas@nomad.astro.psu.edu 703 * by b.t. thomas@nomad.astro.psu.edu
681 */ 704 */
682 705
706void
683void do_mood_floor(object *op, object *source) { 707do_mood_floor (object *op, object *source)
708{
684 object *tmp; 709 object *tmp;
685 object *tmp2; 710 object *tmp2;
686 711
687 if (!source) 712 if (!source)
688 source = op; 713 source = op;
689 714
690 for (tmp = GET_MAP_OB(op->map, op->x, op->y); tmp; tmp=tmp->above) 715 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp; tmp = tmp->above)
691 if (QUERY_FLAG(tmp, FLAG_MONSTER)) break; 716 if (QUERY_FLAG (tmp, FLAG_MONSTER))
717 break;
692 718
693 /* doesn't effect players, and if there is a player on this space, won't also 719 /* doesn't effect players, and if there is a player on this space, won't also
694 * be a monster here. 720 * be a monster here.
695 */ 721 */
696 if (!tmp || tmp->type == PLAYER) return; 722 if (!tmp || tmp->type == PLAYER)
723 return;
697 724
698 switch(op->last_sp) { 725 switch (op->last_sp)
726 {
699 case 0: /* furious--make all monsters mad */ 727 case 0: /* furious--make all monsters mad */
700 if(QUERY_FLAG(tmp, FLAG_UNAGGRESSIVE))
701 CLEAR_FLAG(tmp, FLAG_UNAGGRESSIVE);
702 if(QUERY_FLAG(tmp, FLAG_FRIENDLY)) {
703 CLEAR_FLAG(tmp, FLAG_FRIENDLY);
704 remove_friendly_object(tmp);
705 tmp->attack_movement = 0;
706 /* lots of checks here, but want to make sure we don't
707 * dereference a null value
708 */
709 if (tmp->type == GOLEM && tmp->owner && tmp->owner->type==PLAYER &&
710 tmp->owner->contr->ranges[range_golem]==tmp) {
711 tmp->owner->contr->ranges[range_golem]=NULL;
712 tmp->owner->contr->golem_count = 0;
713 }
714 tmp->owner = 0;
715 }
716 break;
717 case 1: /* angry -- get neutral monsters mad */
718 if(QUERY_FLAG(tmp, FLAG_UNAGGRESSIVE)&& 728 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE))
719 !QUERY_FLAG(tmp, FLAG_FRIENDLY))
720 CLEAR_FLAG(tmp, FLAG_UNAGGRESSIVE); 729 CLEAR_FLAG (tmp, FLAG_UNAGGRESSIVE);
730 if (QUERY_FLAG (tmp, FLAG_FRIENDLY))
731 {
732 CLEAR_FLAG (tmp, FLAG_FRIENDLY);
733 remove_friendly_object (tmp);
734 tmp->attack_movement = 0;
735 /* lots of checks here, but want to make sure we don't
736 * dereference a null value
737 */
738 if (tmp->type == GOLEM && tmp->owner && tmp->owner->type == PLAYER && tmp->owner->contr->ranges[range_golem] == tmp)
739 tmp->owner->contr->ranges[range_golem] = 0;
740
741 tmp->owner = 0;
742 }
721 break; 743 break;
744 case 1: /* angry -- get neutral monsters mad */
745 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (tmp, FLAG_FRIENDLY))
746 CLEAR_FLAG (tmp, FLAG_UNAGGRESSIVE);
747 break;
722 case 2: /* calm -- pacify unfriendly monsters */ 748 case 2: /* calm -- pacify unfriendly monsters */
723 if(!QUERY_FLAG(tmp, FLAG_UNAGGRESSIVE)) 749 if (!QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE))
724 SET_FLAG(tmp, FLAG_UNAGGRESSIVE); 750 SET_FLAG (tmp, FLAG_UNAGGRESSIVE);
751 break;
752 case 3: /* make all monsters fall asleep */
753 if (!QUERY_FLAG (tmp, FLAG_SLEEP))
754 SET_FLAG (tmp, FLAG_SLEEP);
755 break;
756 case 4: /* charm all monsters */
757 if (op == source)
758 break; /* only if 'connected' */
759
760 for (tmp2 = GET_MAP_OB (source->map, source->x, source->y); /* finding an owner */
761 tmp2->type != PLAYER; tmp2 = tmp2->above)
762 if (tmp2->above == NULL)
725 break; 763 break;
726 case 3: /* make all monsters fall asleep */
727 if(!QUERY_FLAG(tmp, FLAG_SLEEP))
728 SET_FLAG(tmp, FLAG_SLEEP);
729 break;
730 case 4: /* charm all monsters */
731 if (op == source) break; /* only if 'connected' */
732 764
733 for(tmp2=get_map_ob(source->map,source->x,source->y); /* finding an owner */
734 tmp2->type!=PLAYER;tmp2=tmp2->above)
735 if(tmp2->above==NULL) break;
736
737 if (tmp2->type != PLAYER) 765 if (tmp2->type != PLAYER)
738 break; 766 break;
739 set_owner(tmp,tmp2); 767
768 tmp->set_owner (tmp2);
740 SET_FLAG(tmp,FLAG_MONSTER); 769 SET_FLAG (tmp, FLAG_MONSTER);
770
741 tmp->stats.exp = 0; 771 tmp->stats.exp = 0;
742 SET_FLAG(tmp, FLAG_FRIENDLY); 772 SET_FLAG (tmp, FLAG_FRIENDLY);
773
743 add_friendly_object (tmp); 774 add_friendly_object (tmp);
744 tmp->attack_movement = PETMOVE; 775 tmp->attack_movement = PETMOVE;
745 break; 776 break;
746 777
747 default: 778 default:
748 break; 779 break;
749
750 } 780 }
751} 781}
752 782
753/* this function returns the object it matches, or NULL if non. 783/* this function returns the object it matches, or NULL if non.
754 * It will descend through containers to find the object. 784 * It will descend through containers to find the object.
755 * slaying = match object slaying flag 785 * slaying = match object slaying flag
756 * race = match object archetype name flag 786 * race = match object archetype name flag
757 * hp = match object type (excpt type '0'== PLAYER) 787 * hp = match object type (excpt type '0'== PLAYER)
758 */ 788 */
759 789object *
760object * check_inv_recursive(object *op, const object *trig) 790check_inv_recursive (object *op, const object *trig)
761{ 791{
762 object *tmp,*ret=NULL; 792 object *tmp, *ret = NULL;
763 793
764 /* First check the object itself. */ 794 /* First check the object itself. */
765 if((trig->stats.hp && (op->type == trig->stats.hp)) 795 if ((trig->stats.hp && (op->type == trig->stats.hp))
766 || (trig->slaying && (op->slaying == trig->slaying)) 796 || (trig->slaying && (op->slaying == trig->slaying))
767 || (trig->race && (op->arch->name == trig->race))) 797 || (trig->race && (op->arch->name == trig->race)))
768 return op; 798 return op;
769 799
770 for(tmp=op->inv; tmp; tmp=tmp->below) { 800 for (tmp = op->inv; tmp; tmp = tmp->below)
801 {
771 if (tmp->inv) { 802 if (tmp->inv)
803 {
772 ret=check_inv_recursive(tmp, trig); 804 ret = check_inv_recursive (tmp, trig);
805 if (ret)
773 if (ret) return ret; 806 return ret;
774 } 807 }
775 else if((trig->stats.hp && (tmp->type == trig->stats.hp)) 808 else if ((trig->stats.hp && (tmp->type == trig->stats.hp))
776 || (trig->slaying && (tmp->slaying == trig->slaying)) 809 || (trig->slaying && (tmp->slaying == trig->slaying))
777 || (trig->race && (tmp->arch->name == trig->race))) 810 || (trig->race && (tmp->arch->name == trig->race)))
778 return tmp; 811 return tmp;
779 } 812 }
780 return NULL; 813 return NULL;
781} 814}
782 815
783/* check_inv(), a function to search the inventory, 816/* check_inv(), a function to search the inventory,
784 * of a player and then based on a set of conditions, 817 * of a player and then based on a set of conditions,
785 * the square will activate connected items. 818 * the square will activate connected items.
786 * Monsters can't trigger this square (for now) 819 * Monsters can't trigger this square (for now)
787 * Values are: last_sp = 1/0 obj/no obj triggers 820 * Values are: last_sp = 1/0 obj/no obj triggers
788 * last_heal = 1/0 remove/dont remove obj if triggered 821 * last_heal = 1/0 remove/dont remove obj if triggered
789 * -b.t. (thomas@nomad.astro.psu.edu 822 * -b.t. (thomas@nomad.astro.psu.edu
790 */ 823 *
791 824 * Tue Dec 19 15:34:00 CET 2006 elmex: changed the function to ignore op
825 * because the check-inventory semantic essentially only applies when
826 * something is above the inventory checker.
827 * The semantic prior this change was: trigger if something has moved on or off
828 * and has a matching item. Imagine what happens if someone steps on the inventory
829 * checker with a matching item, has it, activates the connection, throws the item
830 * away, and then leaves the inventory checker. That would've caused an always-enabled
831 * state in the inventory checker. This won't happen anymore now.
832 *
833 */
834void
792void check_inv (object *op, object *trig) { 835check_inv (object *op, object *trig)
793object *match; 836{
837 trig->value = 0; // deactivate if none of the following conditions apply
794 838
795 if(op->type != PLAYER) return; 839 if (object *pl = trig->ms ().player ())
840 {
796 match = check_inv_recursive(op,trig); 841 object *match = check_inv_recursive (pl, trig);
842
797 if (match && trig->last_sp) { 843 if (match && trig->last_sp) // match == having
844 {
798 if(trig->last_heal) 845 if (trig->last_heal)
799 decrease_ob(match); 846 decrease_ob (match);
800 use_trigger(trig);
801 }
802 else if (!match && !trig->last_sp)
803 use_trigger(trig);
804}
805 847
806 848 trig->value = 1;
807/* This does a minimal check of the button link consistency for object
808 * map. All it really does it much sure the object id link that is set
809 * matches what the object has.
810 */
811void verify_button_links(const mapstruct *map) {
812 oblinkpt *obp;
813 objectlink *ol;
814
815 if (!map) return;
816
817 for (obp = map->buttons; obp; obp = obp->next) {
818 for (ol=obp->link; ol; ol=ol->next) {
819 if (ol->id!=ol->ob->count)
820 LOG(llevError,"verify_button_links: object %s on list is corrupt (%d!=%d)\n",ol->ob->name, ol->id, ol->ob->count);
821 } 849 }
850 else if (!match && !trig->last_sp) // match == not having
851 trig->value = 1;
822 } 852 }
853
854 push_button (trig);
823} 855}
856

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines