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.3 by elmex, Tue Aug 29 17:29:27 2006 UTC vs.
Revision 1.25 by elmex, Tue Jan 9 22:14:29 2007 UTC

1/*
2 * static char *rcsid_button_c =
3 * "$Id: button.C,v 1.3 2006/08/29 17:29:27 elmex 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 (INVOKE_MAP (TRIGGER, op->map, ARG_INT64(obp->value), ARG_INT(op->value))) 172 if (!obp)
180 return; 173 return;
181 174
182 if (obp && obp->link) 175 if (INVOKE_MAP (TRIGGER, op->map, ARG_INT64 (obp->value), ARG_INT (op->value)))
176 return;
177
183 activate_connection_link (obp->link, op->value, op); 178 activate_connection_link (obp->link, op->value, op);
184} 179}
185 180
186/* 181/*
187 * elmex: 182 * elmex:
188 * This activates a connection, similar to push_button (object *op) but it takes 183 * This activates a connection, similar to push_button (object *op) but it takes
189 * 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
190 * 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
191 * who have FLAG_ACTIVATE_ON_PUSH/RELEASE set properly. 186 * who have FLAG_ACTIVATE_ON_PUSH/RELEASE set properly.
192 * 187 *
193 */ 188 */
189void
194void activate_connection (mapstruct *map, long connection, bool state) 190activate_connection (maptile *map, long connection, bool state)
195{ 191{
196 if (INVOKE_MAP (TRIGGER, map, ARG_INT64(connection), ARG_INT(state))) 192 if (INVOKE_MAP (TRIGGER, map, ARG_INT64 (connection), ARG_INT (state)))
197 return; 193 return;
198 194
199 oblinkpt *obp = get_connection_links (map, connection); 195 oblinkpt *obp = get_connection_links (map, connection);
200 if (obp && obp->link) 196
197 if (obp)
201 activate_connection_link (obp->link, state); 198 activate_connection_link (obp->link, state);
202} 199}
203 200
204/* 201/*
205 * Updates everything connected with the button op. 202 * Updates everything connected with the button op.
206 * 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
207 * 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
208 * button reacts to the (eventual) change of state. 205 * button reacts to the (eventual) change of state.
209 */ 206 */
210 207void
211void update_button(object *op) { 208update_button (object *op)
209{
212 object *ab,*tmp,*head; 210 object *ab, *tmp, *head;
213 int tot,any_down=0, old_value=op->value; 211 int tot, any_down = 0, old_value = op->value;
214 oblinkpt *obp = 0; 212 oblinkpt *obp = 0;
215 objectlink *ol; 213 objectlink *ol;
216 214
217 obp = get_button_links (op); 215 obp = get_button_links (op);
218 /* LOG(llevDebug, "update_button: %s (%d)\n", op->name, op->count); */ 216 /* LOG(llevDebug, "update_button: %s (%d)\n", op->name, op->count); */
219 if (obp) 217 if (obp)
220 for (ol = obp->link; ol; ol = ol->next) { 218 for (ol = obp->link; ol; ol = ol->next)
221 if (!ol->ob || ol->ob->count != ol->id) { 219 {
220 if (!ol->ob)
221 {
222 LOG(llevDebug, "Internal error in update_button (%s).\n", op->name); 222 LOG (llevDebug, "Internal error in update_button (%s).\n", &op->name);
223 continue; 223 continue;
224 } 224 }
225
225 tmp = ol->ob; 226 tmp = ol->ob;
226 if (tmp->type==BUTTON) { 227 if (tmp->type == BUTTON)
228 {
227 for(ab=tmp->above,tot=0;ab!=NULL;ab=ab->above) 229 for (ab = tmp->above, tot = 0; ab != NULL; ab = ab->above)
228 /* Bug? The pedestal code below looks for the head of 230 /* Bug? The pedestal code below looks for the head of
229 * 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
230 * for head here also. Maybe it also makese sense to 232 * for head here also. Maybe it also makese sense to
231 * make the for ab=tmp->above loop common, and alter 233 * make the for ab=tmp->above loop common, and alter
232 * behaviour based on object within that loop? 234 * behaviour based on object within that loop?
233 */ 235 */
234 236
235 /* Basically, if the move_type matches that on what the 237 /* Basically, if the move_type matches that on what the
236 * button wants, we count it. The second check is so that 238 * button wants, we count it. The second check is so that
237 * objects don't move (swords, etc) will count. Note that 239 * objects don't move (swords, etc) will count. Note that
238 * this means that more work is needed to make buttons 240 * this means that more work is needed to make buttons
239 * that are only triggered by flying objects. 241 * that are only triggered by flying objects.
240 */ 242 */
241 if ((ab->move_type & tmp->move_on) || ab->move_type==0 ) 243 if ((ab->move_type & tmp->move_on) || ab->move_type == 0)
242 tot+=ab->weight*(ab->nrof?ab->nrof:1)+ab->carrying; 244 tot += ab->weight * (ab->nrof ? ab->nrof : 1) + ab->carrying;
243 245
244 tmp->value=(tot>=tmp->weight)?1:0; 246 tmp->value = (tot >= tmp->weight) ? 1 : 0;
245 if(tmp->value) 247 if (tmp->value)
246 any_down=1; 248 any_down = 1;
249 }
247 } else if (tmp->type == PEDESTAL) { 250 else if (tmp->type == PEDESTAL)
251 {
248 tmp->value = 0; 252 tmp->value = 0;
249 for(ab=tmp->above; ab!=NULL; ab=ab->above) { 253 for (ab = tmp->above; ab != NULL; ab = ab->above)
254 {
250 head = ab->head ? ab->head : ab; 255 head = ab->head ? ab->head : ab;
251 /* Same note regarding move_type for buttons above apply here. */ 256 /* Same note regarding move_type for buttons above apply here. */
252 if ( ((head->move_type & tmp->move_on) || ab->move_type==0) && 257 if (((head->move_type & tmp->move_on) || ab->move_type == 0) &&
253 (head->race==tmp->slaying || 258 (head->race == tmp->slaying ||
254 ((head->type==SPECIAL_KEY) && (head->slaying==tmp->slaying)) || 259 ((head->type == SPECIAL_KEY) && (head->slaying == tmp->slaying)) ||
255 (!strcmp (tmp->slaying, "player") && 260 (!strcmp (tmp->slaying, "player") && head->type == PLAYER)))
256 head->type == PLAYER)))
257 tmp->value = 1; 261 tmp->value = 1;
258 } 262 }
259 if(tmp->value) 263 if (tmp->value)
260 any_down=1; 264 any_down = 1;
261 } 265 }
262 } 266 }
263 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 */
264 op->value=1; 268 op->value = 1;
265 269
266 /* If this button hasn't changed, don't do anything */ 270 /* If this button hasn't changed, don't do anything */
267 if (op->value != old_value) { 271 if (op->value != old_value)
272 {
268 SET_ANIMATION(op, op->value); 273 SET_ANIMATION (op, op->value);
269 update_object(op, UP_OBJ_FACE); 274 update_object (op, UP_OBJ_FACE);
270 push_button(op); /* Make all other buttons the same */ 275 push_button (op); /* Make all other buttons the same */
271 }
272}
273
274/*
275 * Updates every button on the map (by calling update_button() for them).
276 */
277
278void update_buttons(mapstruct *m) {
279 objectlink *ol;
280 oblinkpt *obp;
281 for (obp = m->buttons; obp; obp = obp->next)
282 for (ol = obp->link; ol; ol = ol->next) {
283 if (!ol->ob || ol->ob->count != ol->id) {
284 LOG(llevError, "Internal error in update_button (%s (%dx%d):%d, connected %ld).\n",
285 ol->ob?ol->ob->name:"null",
286 ol->ob?ol->ob->x:-1,
287 ol->ob?ol->ob->y:-1,
288 ol->id,
289 obp->value);
290 continue;
291 } 276 }
292 if (ol->ob->type==BUTTON || ol->ob->type==PEDESTAL)
293 {
294 update_button(ol->ob);
295 break;
296 }
297 }
298} 277}
299 278
279void
300void use_trigger(object *op) 280use_trigger (object *op)
301{ 281{
302
303 /* Toggle value */ 282 /* Toggle value */
304 op->value = !op->value; 283 op->value = !op->value;
305 push_button(op); 284 push_button (op);
306} 285}
307 286
308/* 287/*
309 * Note: animate_object should be used instead of this, 288 * Note: animate_object should be used instead of this,
310 * but it can't handle animations in the 8 directions 289 * but it can't handle animations in the 8 directions
311 */ 290 */
312 291void
313void animate_turning(object *op) /* only one part objects */ 292animate_turning (object *op) /* only one part objects */
314{ 293{
315 if (++op->state >= NUM_ANIMATIONS(op)/8) 294 if (++op->state >= NUM_ANIMATIONS (op) / 8)
316 op->state=0; 295 op->state = 0;
317 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);
318 op->state);
319 update_object(op,UP_OBJ_FACE); 297 update_object (op, UP_OBJ_FACE);
320} 298}
321 299
322#define ARCH_SACRIFICE(xyz) ((xyz)->slaying) 300#define ARCH_SACRIFICE(xyz) ((xyz)->slaying)
323#define NROF_SACRIFICE(xyz) ((uint32)(xyz)->stats.food) 301#define NROF_SACRIFICE(xyz) ((uint32)(xyz)->stats.food)
324 302
330 * 308 *
331 * 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
332 * 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
333 * objects on the same space that take the same sacrifice. 311 * objects on the same space that take the same sacrifice.
334 */ 312 */
335 313
314int
336int check_altar_sacrifice (const object *altar, const object *sacrifice) 315check_altar_sacrifice (const object *altar, const object *sacrifice)
337{ 316{
338 if ( ! QUERY_FLAG (sacrifice, FLAG_ALIVE) 317 if (!QUERY_FLAG (sacrifice, FLAG_ALIVE) && !QUERY_FLAG (sacrifice, FLAG_IS_LINKED) && sacrifice->type != PLAYER)
339 && ! QUERY_FLAG (sacrifice, FLAG_IS_LINKED)
340 && sacrifice->type != PLAYER)
341 { 318 {
342 if ((ARCH_SACRIFICE(altar) == sacrifice->arch->name || 319 if ((ARCH_SACRIFICE (altar) == sacrifice->arch->name ||
343 ARCH_SACRIFICE(altar) == sacrifice->name || 320 ARCH_SACRIFICE (altar) == sacrifice->name ||
344 ARCH_SACRIFICE(altar) == sacrifice->slaying || 321 ARCH_SACRIFICE (altar) == sacrifice->slaying ||
345 (!strcmp(ARCH_SACRIFICE(altar),query_base_name(sacrifice,0)))) 322 (!strcmp (ARCH_SACRIFICE (altar), query_base_name (sacrifice, 0))))
346 && NROF_SACRIFICE(altar) <= (sacrifice->nrof?sacrifice->nrof:1)) 323 && NROF_SACRIFICE (altar) <= (sacrifice->nrof ? sacrifice->nrof : 1))
347 return 1; 324 return 1;
325
348 if (strcmp (ARCH_SACRIFICE(altar), "money") == 0 326 if (strcmp (ARCH_SACRIFICE (altar), "money") == 0
349 && sacrifice->type == MONEY
350 && sacrifice->nrof * sacrifice->value >= NROF_SACRIFICE(altar)) 327 && sacrifice->type == MONEY && sacrifice->nrof * sacrifice->value >= NROF_SACRIFICE (altar))
351 return 1; 328 return 1;
352 } 329 }
330
353 return 0; 331 return 0;
354} 332}
355
356 333
357/* 334/*
358 * operate_altar checks if sacrifice was accepted and removes sacrificed 335 * operate_altar checks if sacrifice was accepted and removes sacrificed
359 * 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
360 * call check_altar_sacrifice (above) than depend on the return value, 337 * call check_altar_sacrifice (above) than depend on the return value,
361 * since operate_altar will remove the sacrifice also. 338 * since operate_altar will remove the sacrifice also.
362 * 339 *
363 * 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
364 * 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.
365 */ 342 */
366 343int
367int operate_altar (object *altar, object **sacrifice) 344operate_altar (object *altar, object **sacrifice)
368{ 345{
369
370 if ( ! altar->map) { 346 if (!altar->map)
347 {
371 LOG (llevError, "BUG: operate_altar(): altar has no map\n"); 348 LOG (llevError, "BUG: operate_altar(): altar has no map\n");
372 return 0; 349 return 0;
373 } 350 }
374 351
375 if (!altar->slaying || altar->value) 352 if (!altar->slaying || altar->value)
376 return 0; 353 return 0;
377 354
378 if ( ! check_altar_sacrifice (altar, *sacrifice)) 355 if (!check_altar_sacrifice (altar, *sacrifice))
379 return 0; 356 return 0;
380 357
381 /* check_altar_sacrifice should have already verified that enough money 358 /* check_altar_sacrifice should have already verified that enough money
382 * has been dropped. 359 * has been dropped.
383 */ 360 */
384 if (!strcmp(ARCH_SACRIFICE(altar), "money")) { 361 if (!strcmp (ARCH_SACRIFICE (altar), "money"))
362 {
385 int number=NROF_SACRIFICE(altar) / (*sacrifice)->value; 363 int number = NROF_SACRIFICE (altar) / (*sacrifice)->value;
386 364
387 /* Round up any sacrifices. Altars don't make change either */ 365 /* Round up any sacrifices. Altars don't make change either */
388 if (NROF_SACRIFICE(altar) % (*sacrifice)->value) number++; 366 if (NROF_SACRIFICE (altar) % (*sacrifice)->value)
367 number++;
368
389 *sacrifice = decrease_ob_nr (*sacrifice, number); 369 *sacrifice = decrease_ob_nr (*sacrifice, number);
390 } 370 }
391 else 371 else
392 *sacrifice = decrease_ob_nr (*sacrifice, NROF_SACRIFICE(altar)); 372 *sacrifice = decrease_ob_nr (*sacrifice, NROF_SACRIFICE (altar));
393 373
394 if (altar->msg) 374 if (altar->msg)
395 new_info_map(NDI_BLACK, altar->map, altar->msg); 375 new_info_map (NDI_BLACK, altar->map, altar->msg);
376
396 return 1; 377 return 1;
397} 378}
398 379
380void
399void trigger_move (object *op, int state) /* 1 down and 0 up */ 381trigger_move (object *op, int state) /* 1 down and 0 up */
400{ 382{
401 op->stats.wc = state; 383 op->stats.wc = state;
402 if (state) { 384 if (state)
385 {
403 use_trigger(op); 386 use_trigger (op);
404 if (op->stats.exp > 0) /* check sanity */ 387 op->set_speed (op->stats.exp > 0 ? 1. / op->stats.exp : 1.);
405 op->speed = 1.0 / op->stats.exp;
406 else
407 op->speed = 1.0;
408 update_ob_speed(op);
409 op->speed_left = -1; 388 op->speed_left = -1;
410 } else { 389 }
390 else
391 {
411 use_trigger(op); 392 use_trigger (op);
412 op->speed = 0; 393 op->set_speed (0);
413 update_ob_speed(op);
414 } 394 }
415} 395}
416 396
417 397
418/* 398/*
425 * 405 *
426 * TRIGGER: Returns 1 if handle could be moved, 0 if not. 406 * TRIGGER: Returns 1 if handle could be moved, 0 if not.
427 * 407 *
428 * TRIGGER_BUTTON, TRIGGER_PEDESTAL: Returns 0. 408 * TRIGGER_BUTTON, TRIGGER_PEDESTAL: Returns 0.
429 */ 409 */
410int
430int check_trigger (object *op, object *cause) 411check_trigger (object *op, object *cause)
431{ 412{
432 object *tmp; 413 object *tmp;
433 int push = 0, tot = 0; 414 int push = 0, tot = 0;
434 int in_movement = op->stats.wc || op->speed; 415 int in_movement = op->stats.wc || op->speed;
435 416
436 switch (op->type) { 417 switch (op->type)
418 {
437 case TRIGGER_BUTTON: 419 case TRIGGER_BUTTON:
438 if (op->weight > 0) { 420 if (op->weight > 0)
421 {
439 if (cause) { 422 if (cause)
423 {
440 for (tmp = op->above; tmp; tmp = tmp->above) 424 for (tmp = op->above; tmp; tmp = tmp->above)
441 /* Comment reproduced from update_buttons(): */ 425 /* Comment reproduced from update_buttons(): */
442 /* Basically, if the move_type matches that on what the 426 /* Basically, if the move_type matches that on what the
443 * button wants, we count it. The second check is so that 427 * button wants, we count it. The second check is so that
444 * objects that don't move (swords, etc) will count. Note that 428 * objects that don't move (swords, etc) will count. Note that
445 * this means that more work is needed to make buttons 429 * this means that more work is needed to make buttons
446 * that are only triggered by flying objects. 430 * that are only triggered by flying objects.
447 */ 431 */
448 432
449 if ((tmp->move_type & op->move_on) || tmp->move_type==0) { 433 if ((tmp->move_type & op->move_on) || tmp->move_type == 0)
434 {
450 tot += tmp->weight * (tmp->nrof ? tmp->nrof : 1) 435 tot += tmp->weight * (tmp->nrof ? tmp->nrof : 1) + tmp->carrying;
451 + tmp->carrying;
452 } 436 }
453 if (tot >= op->weight) 437 if (tot >= op->weight)
454 push = 1; 438 push = 1;
455 if (op->stats.ac == push) 439 if (op->stats.ac == push)
456 return 0; 440 return 0;
457 op->stats.ac = push; 441 op->stats.ac = push;
458 if (NUM_ANIMATIONS(op) > 1) { 442 if (NUM_ANIMATIONS (op) > 1)
443 {
459 SET_ANIMATION (op, push); 444 SET_ANIMATION (op, push);
460 update_object (op, UP_OBJ_FACE); 445 update_object (op, UP_OBJ_FACE);
461 } 446 }
462 if (in_movement || ! push) 447 if (in_movement || !push)
463 return 0; 448 return 0;
464 } 449 }
465 trigger_move (op, push); 450 trigger_move (op, push);
466 } 451 }
467 return 0; 452 return 0;
468 453
469 case TRIGGER_PEDESTAL: 454 case TRIGGER_PEDESTAL:
470 if (cause) { 455 if (cause)
456 {
471 for (tmp = op->above; tmp; tmp = tmp->above) { 457 for (tmp = op->above; tmp; tmp = tmp->above)
458 {
472 object *head = tmp->head ? tmp->head : tmp; 459 object *head = tmp->head ? tmp->head : tmp;
473 460
474 /* See comment in TRIGGER_BUTTON about move_types */ 461 /* See comment in TRIGGER_BUTTON about move_types */
475 if (((head->move_type & op->move_on) || head->move_type==0) 462 if (((head->move_type & op->move_on) || head->move_type == 0)
476 && (head->race==op->slaying ||
477 (!strcmp (op->slaying, "player") && head->type == PLAYER))) { 463 && (head->race == op->slaying || (!strcmp (op->slaying, "player") && head->type == PLAYER)))
464 {
478 push = 1; 465 push = 1;
479 break; 466 break;
480 } 467 }
481 } 468 }
482 if (op->stats.ac == push) 469 if (op->stats.ac == push)
483 return 0; 470 return 0;
484 op->stats.ac = push; 471 op->stats.ac = push;
485 if (NUM_ANIMATIONS(op) > 1) { 472 if (NUM_ANIMATIONS (op) > 1)
473 {
486 SET_ANIMATION (op, push); 474 SET_ANIMATION (op, push);
487 update_object (op, UP_OBJ_FACE); 475 update_object (op, UP_OBJ_FACE);
488 } 476 }
489 update_object(op,UP_OBJ_FACE); 477 update_object (op, UP_OBJ_FACE);
490 if (in_movement || ! push) 478 if (in_movement || !push)
491 return 0; 479 return 0;
492 } 480 }
493 trigger_move (op, push); 481 trigger_move (op, push);
494 return 0; 482 return 0;
495 483
496 case TRIGGER_ALTAR: 484 case TRIGGER_ALTAR:
497 if (cause) { 485 if (cause)
486 {
498 if (in_movement) 487 if (in_movement)
499 return 0; 488 return 0;
500 if (operate_altar (op, &cause)) { 489 if (operate_altar (op, &cause))
490 {
501 if (NUM_ANIMATIONS(op) > 1) { 491 if (NUM_ANIMATIONS (op) > 1)
492 {
502 SET_ANIMATION (op, 1); 493 SET_ANIMATION (op, 1);
503 update_object(op, UP_OBJ_FACE); 494 update_object (op, UP_OBJ_FACE);
504 } 495 }
505 if (op->last_sp >= 0) { 496 if (op->last_sp >= 0)
497 {
506 trigger_move (op, 1); 498 trigger_move (op, 1);
507 if (op->last_sp > 0) 499 if (op->last_sp > 0)
508 op->last_sp = -op->last_sp; 500 op->last_sp = -op->last_sp;
509 } 501 }
510 else { 502 else
503 {
511 /* for trigger altar with last_sp, the ON/OFF 504 /* for trigger altar with last_sp, the ON/OFF
512 * status (-> +/- value) is "simulated": 505 * status (-> +/- value) is "simulated":
513 */ 506 */
514 op->value = !op->value; 507 op->value = !op->value;
515 trigger_move (op, 1); 508 trigger_move (op, 1);
516 op->last_sp = -op->last_sp; 509 op->last_sp = -op->last_sp;
517 op->value = !op->value; 510 op->value = !op->value;
518 } 511 }
519 return cause == NULL; 512 return cause == NULL;
520 } else {
521 return 0;
522 } 513 }
523 } else { 514 else
524 if (NUM_ANIMATIONS(op) > 1) {
525 SET_ANIMATION (op, 0);
526 update_object(op, UP_OBJ_FACE);
527 } 515 {
528 516 return 0;
529 /* If trigger_altar has "last_sp > 0" set on the map,
530 * it will push the connected value only once per sacrifice.
531 * Otherwise (default), the connected value will be
532 * pushed twice: First by sacrifice, second by reset! -AV
533 */
534 if (!op->last_sp)
535 trigger_move (op, 0);
536 else {
537 op->stats.wc = 0;
538 op->value = !op->value;
539 op->speed = 0;
540 update_ob_speed(op);
541 } 517 }
542 } 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 }
543 return 0; 541 return 0;
544 542
545 case TRIGGER: 543 case TRIGGER:
546 if (cause) { 544 if (cause)
545 {
547 if (in_movement) 546 if (in_movement)
548 return 0; 547 return 0;
548
549 push = 1; 549 push = 1;
550 } 550 }
551
551 if (NUM_ANIMATIONS(op) > 1) { 552 if (NUM_ANIMATIONS (op) > 1)
553 {
552 SET_ANIMATION (op, push); 554 SET_ANIMATION (op, push);
553 update_object(op, UP_OBJ_FACE); 555 update_object (op, UP_OBJ_FACE);
554 } 556 }
557
555 trigger_move (op, push); 558 trigger_move (op, push);
556 return 1; 559 return 1;
557 560
558 default: 561 default:
559 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);
560 return 0; 563 return 0;
561 } 564 }
562} 565}
563 566
567void
564void add_button_link(object *button, mapstruct *map, int connected) { 568add_button_link (object *button, maptile *map, int connected)
569{
565 oblinkpt *obp; 570 oblinkpt *obp;
566 objectlink *ol = get_objectlink(); 571 objectlink *ol = get_objectlink ();
567 572
568 if (!map) { 573 if (!map)
574 {
569 LOG(llevError, "Tried to add button-link without map.\n"); 575 LOG (llevError, "Tried to add button-link without map.\n");
570 return; 576 return;
571 } 577 }
578
572 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
573 a connected map from a template map. */ 580 a connected map from a template map. */
574/* LOG(llevDebug,"adding button %s (%d)\n", button->name, connected);*/
575 581
576 SET_FLAG(button,FLAG_IS_LINKED); 582 SET_FLAG (button, FLAG_IS_LINKED);
577 583
578 ol->ob = button; 584 ol->ob = button;
579 ol->id = button->count;
580 585
581 for (obp = map->buttons; obp && obp->value != connected; obp = obp->next); 586 for (obp = map->buttons; obp && obp->value != connected; obp = obp->next)
587 ;
582 588
583 if (obp) { 589 if (obp)
590 {
584 ol->next = obp->link; 591 ol->next = obp->link;
585 obp->link = ol; 592 obp->link = ol;
593 }
586 } else { 594 else
595 {
587 obp = get_objectlinkpt(); 596 obp = get_objectlinkpt ();
588 obp->value = connected; 597 obp->value = connected;
589 598
590 obp->next = map->buttons; 599 obp->next = map->buttons;
591 map->buttons = obp; 600 map->buttons = obp;
592 obp->link = ol; 601 obp->link = ol;
593 } 602 }
594} 603}
595 604
596/* 605/*
597 * 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.
598 * This is only needed by editors. 607 * This is only needed by editors.
599 */ 608 */
600 609
610void
601void remove_button_link(object *op) { 611remove_button_link (object *op)
612{
602 oblinkpt *obp; 613 oblinkpt *obp;
603 objectlink **olp, *ol; 614 objectlink **olp, *ol;
604 615
605 if (op->map == NULL) { 616 if (op->map == NULL)
617 {
606 LOG(llevError, "remove_button_link() in object without map.\n"); 618 LOG (llevError, "remove_button_link() in object without map.\n");
607 return; 619 return;
608 } 620 }
621
609 if (!QUERY_FLAG(op,FLAG_IS_LINKED)) { 622 if (!QUERY_FLAG (op, FLAG_IS_LINKED))
623 {
610 LOG(llevError, "remove_button_linked() in unlinked object.\n"); 624 LOG (llevError, "remove_button_linked() in unlinked object.\n");
611 return; 625 return;
612 } 626 }
627
613 for (obp = op->map->buttons; obp; obp = obp->next) 628 for (obp = op->map->buttons; obp; obp = obp->next)
614 for (olp = &obp->link; (ol = *olp); olp = &ol->next) 629 for (olp = &obp->link; (ol = *olp); olp = &ol->next)
615 if (ol->ob == op) { 630 if (ol->ob == op)
631 {
632
616/* 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",
617 obp->value, op->name, op->map->path); 634 obp->value, op->name, op->map->path);
618*/ 635*/
619 *olp = ol->next; 636 *olp = ol->next;
620 free(ol); 637 delete ol;
621 return; 638 return;
622 } 639 }
640
623 LOG(llevError, "remove_button_linked(): couldn't find object.\n"); 641 LOG (llevError, "remove_button_linked(): couldn't find object.\n");
624 CLEAR_FLAG(op,FLAG_IS_LINKED); 642 CLEAR_FLAG (op, FLAG_IS_LINKED);
625} 643}
626 644
627/* 645/*
628 * Gets the objectlink for this connection from the map. 646 * Gets the objectlink for this connection from the map.
629 */ 647 */
648oblinkpt *
630oblinkpt *get_connection_links (mapstruct *map, long connection) 649get_connection_links (maptile *map, long connection)
631{ 650{
632 for (oblinkpt *obp = map->buttons; obp; obp = obp->next) 651 for (oblinkpt * obp = map->buttons; obp; obp = obp->next)
633 if (obp->value == connection) 652 if (obp->value == connection)
634 return obp; 653 return obp;
654
635 return 0; 655 return 0;
636} 656}
637 657
638/* 658/*
639 * Return the first objectlink in the objects linked to this one 659 * Return the first objectlink in the objects linked to this one
640 */ 660 */
641 661
662oblinkpt *
642oblinkpt *get_button_links(const object *button) { 663get_button_links (const object *button)
664{
643 oblinkpt *obp; 665 oblinkpt *obp;
644 objectlink *ol; 666 objectlink *ol;
645 667
646 if (!button->map) 668 if (!button->map)
647 return NULL; 669 return NULL;
670
648 for (obp = button->map->buttons; obp; obp = obp->next) 671 for (obp = button->map->buttons; obp; obp = obp->next)
649 for (ol = obp->link; ol; ol = ol->next) 672 for (ol = obp->link; ol; ol = ol->next)
650 if (ol->ob == button && ol->id == button->count) 673 if (ol->ob == button)
651 return obp; 674 return obp;
675
652 return NULL; 676 return NULL;
653} 677}
654 678
655/* 679/*
656 * Made as a separate function to increase efficiency 680 * Made as a separate function to increase efficiency
657 */ 681 */
658 682
683int
659int get_button_value(const object *button) { 684get_button_value (const object *button)
685{
660 oblinkpt *obp; 686 oblinkpt *obp;
661 objectlink *ol; 687 objectlink *ol;
662 688
663 if (!button->map) 689 if (!button->map)
664 return 0; 690 return 0;
665 for (obp = button->map->buttons; obp; obp = obp->next) 691 for (obp = button->map->buttons; obp; obp = obp->next)
666 for (ol = obp->link; ol; ol = ol->next) 692 for (ol = obp->link; ol; ol = ol->next)
667 if (ol->ob == button && ol->id == button->count) 693 if (ol->ob == button)
668 return obp->value; 694 return obp->value;
669 return 0; 695 return 0;
670} 696}
671 697
672/* This routine makes monsters who are 698/* This routine makes monsters who are
675 * If floor is to be triggered must have 701 * If floor is to be triggered must have
676 * a speed of zero (default is 1 for all 702 * a speed of zero (default is 1 for all
677 * but the charm floor type). 703 * but the charm floor type).
678 * by b.t. thomas@nomad.astro.psu.edu 704 * by b.t. thomas@nomad.astro.psu.edu
679 */ 705 */
680 706
707void
681void do_mood_floor(object *op, object *source) { 708do_mood_floor (object *op, object *source)
709{
682 object *tmp; 710 object *tmp;
683 object *tmp2; 711 object *tmp2;
684 712
685 if (!source) 713 if (!source)
686 source = op; 714 source = op;
687 715
688 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)
689 if (QUERY_FLAG(tmp, FLAG_MONSTER)) break; 717 if (QUERY_FLAG (tmp, FLAG_MONSTER))
718 break;
690 719
691 /* 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
692 * be a monster here. 721 * be a monster here.
693 */ 722 */
694 if (!tmp || tmp->type == PLAYER) return; 723 if (!tmp || tmp->type == PLAYER)
724 return;
695 725
696 switch(op->last_sp) { 726 switch (op->last_sp)
727 {
697 case 0: /* furious--make all monsters mad */ 728 case 0: /* furious--make all monsters mad */
698 if(QUERY_FLAG(tmp, FLAG_UNAGGRESSIVE))
699 CLEAR_FLAG(tmp, FLAG_UNAGGRESSIVE);
700 if(QUERY_FLAG(tmp, FLAG_FRIENDLY)) {
701 CLEAR_FLAG(tmp, FLAG_FRIENDLY);
702 remove_friendly_object(tmp);
703 tmp->attack_movement = 0;
704 /* lots of checks here, but want to make sure we don't
705 * dereference a null value
706 */
707 if (tmp->type == GOLEM && tmp->owner && tmp->owner->type==PLAYER &&
708 tmp->owner->contr->ranges[range_golem]==tmp) {
709 tmp->owner->contr->ranges[range_golem]=NULL;
710 tmp->owner->contr->golem_count = 0;
711 }
712 tmp->owner = 0;
713 }
714 break;
715 case 1: /* angry -- get neutral monsters mad */
716 if(QUERY_FLAG(tmp, FLAG_UNAGGRESSIVE)&& 729 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE))
717 !QUERY_FLAG(tmp, FLAG_FRIENDLY))
718 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 }
719 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;
720 case 2: /* calm -- pacify unfriendly monsters */ 749 case 2: /* calm -- pacify unfriendly monsters */
721 if(!QUERY_FLAG(tmp, FLAG_UNAGGRESSIVE)) 750 if (!QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE))
722 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)
723 break; 764 break;
724 case 3: /* make all monsters fall asleep */
725 if(!QUERY_FLAG(tmp, FLAG_SLEEP))
726 SET_FLAG(tmp, FLAG_SLEEP);
727 break;
728 case 4: /* charm all monsters */
729 if (op == source) break; /* only if 'connected' */
730 765
731 for(tmp2=get_map_ob(source->map,source->x,source->y); /* finding an owner */
732 tmp2->type!=PLAYER;tmp2=tmp2->above)
733 if(tmp2->above==NULL) break;
734
735 if (tmp2->type != PLAYER) 766 if (tmp2->type != PLAYER)
736 break; 767 break;
737 set_owner(tmp,tmp2); 768
769 tmp->set_owner (tmp2);
738 SET_FLAG(tmp,FLAG_MONSTER); 770 SET_FLAG (tmp, FLAG_MONSTER);
771
739 tmp->stats.exp = 0; 772 tmp->stats.exp = 0;
740 SET_FLAG(tmp, FLAG_FRIENDLY); 773
741 add_friendly_object (tmp); 774 add_friendly_object (tmp);
742 tmp->attack_movement = PETMOVE; 775 tmp->attack_movement = PETMOVE;
743 break; 776 break;
744 777
745 default: 778 default:
746 break; 779 break;
747
748 } 780 }
749} 781}
750 782
751/* this function returns the object it matches, or NULL if non. 783/* this function returns the object it matches, or NULL if non.
752 * It will descend through containers to find the object. 784 * It will descend through containers to find the object.
753 * slaying = match object slaying flag 785 * slaying = match object slaying flag
754 * race = match object archetype name flag 786 * race = match object archetype name flag
755 * hp = match object type (excpt type '0'== PLAYER) 787 * hp = match object type (excpt type '0'== PLAYER)
756 */ 788 */
757 789object *
758object * check_inv_recursive(object *op, const object *trig) 790check_inv_recursive (object *op, const object *trig)
759{ 791{
760 object *tmp,*ret=NULL; 792 object *tmp, *ret = NULL;
761 793
762 /* First check the object itself. */ 794 /* First check the object itself. */
763 if((trig->stats.hp && (op->type == trig->stats.hp)) 795 if ((trig->stats.hp && (op->type == trig->stats.hp))
764 || (trig->slaying && (op->slaying == trig->slaying)) 796 || (trig->slaying && (op->slaying == trig->slaying))
765 || (trig->race && (op->arch->name == trig->race))) 797 || (trig->race && (op->arch->name == trig->race)))
766 return op; 798 return op;
767 799
768 for(tmp=op->inv; tmp; tmp=tmp->below) { 800 for (tmp = op->inv; tmp; tmp = tmp->below)
801 {
769 if (tmp->inv) { 802 if (tmp->inv)
803 {
770 ret=check_inv_recursive(tmp, trig); 804 ret = check_inv_recursive (tmp, trig);
805 if (ret)
771 if (ret) return ret; 806 return ret;
772 } 807 }
773 else if((trig->stats.hp && (tmp->type == trig->stats.hp)) 808 else if ((trig->stats.hp && (tmp->type == trig->stats.hp))
774 || (trig->slaying && (tmp->slaying == trig->slaying)) 809 || (trig->slaying && (tmp->slaying == trig->slaying))
775 || (trig->race && (tmp->arch->name == trig->race))) 810 || (trig->race && (tmp->arch->name == trig->race)))
776 return tmp; 811 return tmp;
777 } 812 }
778 return NULL; 813 return NULL;
779} 814}
780 815
781/* check_inv(), a function to search the inventory, 816/* check_inv(), a function to search the inventory,
782 * of a player and then based on a set of conditions, 817 * of a player and then based on a set of conditions,
783 * the square will activate connected items. 818 * the square will activate connected items.
784 * Monsters can't trigger this square (for now) 819 * Monsters can't trigger this square (for now)
785 * Values are: last_sp = 1/0 obj/no obj triggers 820 * Values are: last_sp = 1/0 obj/no obj triggers
786 * last_heal = 1/0 remove/dont remove obj if triggered 821 * last_heal = 1/0 remove/dont remove obj if triggered
787 * -b.t. (thomas@nomad.astro.psu.edu 822 * -b.t. (thomas@nomad.astro.psu.edu
788 */ 823 *
789 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
790void check_inv (object *op, object *trig) { 835check_inv (object *op, object *trig)
791object *match; 836{
837 trig->value = 0; // deactivate if none of the following conditions apply
792 838
793 if(op->type != PLAYER) return; 839 if (object *pl = trig->ms ().player ())
840 {
794 match = check_inv_recursive(op,trig); 841 object *match = check_inv_recursive (pl, trig);
842
795 if (match && trig->last_sp) { 843 if (match && trig->last_sp) // match == having
844 {
796 if(trig->last_heal) 845 if (trig->last_heal)
797 decrease_ob(match); 846 decrease_ob (match);
798 use_trigger(trig);
799 }
800 else if (!match && !trig->last_sp)
801 use_trigger(trig);
802}
803 847
804 848 trig->value = 1;
805/* This does a minimal check of the button link consistency for object
806 * map. All it really does it much sure the object id link that is set
807 * matches what the object has.
808 */
809void verify_button_links(const mapstruct *map) {
810 oblinkpt *obp;
811 objectlink *ol;
812
813 if (!map) return;
814
815 for (obp = map->buttons; obp; obp = obp->next) {
816 for (ol=obp->link; ol; ol=ol->next) {
817 if (ol->id!=ol->ob->count)
818 LOG(llevError,"verify_button_links: object %s on list is corrupt (%d!=%d)\n",ol->ob->name, ol->id, ol->ob->count);
819 } 849 }
850 else if (!match && !trig->last_sp) // match == not having
851 trig->value = 1;
820 } 852 }
853
854 push_button (trig);
821} 855}
856

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines