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.5 by root, Thu Aug 31 17:54:14 2006 UTC vs.
Revision 1.22 by pippijn, Sat Jan 6 14:42:28 2007 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines