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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines