… | |
… | |
29 | |
29 | |
30 | /* |
30 | /* |
31 | * elmex: |
31 | * elmex: |
32 | * This function takes a objectlink list with all the objects are going to be activated. |
32 | * This function takes a objectlink list with all the objects are going to be activated. |
33 | * state is a true/false flag that will actiavte objects that have FLAG_ACTIVATE_ON_PUSH/RELEASE set. |
33 | * state is a true/false flag that will actiavte objects that have FLAG_ACTIVATE_ON_PUSH/RELEASE set. |
34 | * The source argument can be 0 or the source object for this activation. |
34 | * The activator argument can be 0 or the source object for this activation. |
|
|
35 | * the originator is the player or monster who did something. |
35 | */ |
36 | */ |
36 | void |
37 | static void |
37 | activate_connection_link (objectlink *ol, bool state, object *source = 0) |
38 | activate_connection_link (objectlink *ol, int state, object *activator, object *originator) |
38 | { |
39 | { |
39 | for (; ol; ol = ol->next) |
40 | for (; ol; ol = ol->next) |
40 | { |
41 | { |
41 | if (!ol->ob) |
42 | if (!ol->ob) |
42 | { |
43 | { |
… | |
… | |
105 | SET_ANIMATION (tmp, tmp->value); |
106 | SET_ANIMATION (tmp, tmp->value); |
106 | update_object (tmp, UP_OBJ_FACE); |
107 | update_object (tmp, UP_OBJ_FACE); |
107 | break; |
108 | break; |
108 | |
109 | |
109 | case MOOD_FLOOR: |
110 | case MOOD_FLOOR: |
110 | do_mood_floor (tmp, source); |
111 | do_mood_floor (tmp, activator); |
111 | break; |
112 | break; |
112 | |
113 | |
113 | case TIMED_GATE: |
114 | case TIMED_GATE: |
114 | if (!tmp->active) |
115 | if (!tmp->active) |
115 | tmp->play_sound (tmp->sound ? tmp->sound : sound_find ("trigger_gate")); |
116 | tmp->play_sound (tmp->sound ? tmp->sound : sound_find ("trigger_gate")); |
… | |
… | |
134 | case FIREWALL: |
135 | case FIREWALL: |
135 | if (!QUERY_FLAG (tmp, FLAG_ANIMATE) && tmp->type == FIREWALL) |
136 | if (!QUERY_FLAG (tmp, FLAG_ANIMATE) && tmp->type == FIREWALL) |
136 | move_firewall (tmp); |
137 | move_firewall (tmp); |
137 | else |
138 | else |
138 | { |
139 | { |
139 | if ((tmp->stats.sp += tmp->stats.maxsp) > 8) /* next direction */ |
140 | tmp->stats.sp = absdir (tmp->stats.sp + tmp->stats.maxsp); /* next direction */ |
140 | tmp->stats.sp = ((tmp->stats.sp - 1) % 8) + 1; |
|
|
141 | |
|
|
142 | animate_turning (tmp); |
141 | animate_turning (tmp); |
143 | } |
142 | } |
144 | break; |
143 | break; |
145 | |
144 | |
146 | case TELEPORTER: |
145 | case TELEPORTER: |
… | |
… | |
159 | case DUPLICATOR: |
158 | case DUPLICATOR: |
160 | move_duplicator (tmp); |
159 | move_duplicator (tmp); |
161 | break; |
160 | break; |
162 | |
161 | |
163 | case MAPSCRIPT: |
162 | case MAPSCRIPT: |
164 | cfperl_mapscript_activate (tmp, source, state); |
163 | cfperl_mapscript_activate (tmp, state, activator, originator); |
165 | break; |
164 | break; |
166 | } |
165 | } |
167 | } |
166 | } |
168 | } |
167 | } |
169 | |
168 | |
… | |
… | |
178 | * Changed the routine to loop through _all_ objects. |
177 | * Changed the routine to loop through _all_ objects. |
179 | * Better hurry with that linked list... |
178 | * Better hurry with that linked list... |
180 | * |
179 | * |
181 | */ |
180 | */ |
182 | void |
181 | void |
183 | push_button (object *op) |
182 | push_button (object *op, object *originator) |
184 | { |
183 | { |
185 | if (oblinkpt *obp = op->find_link ()) |
184 | if (oblinkpt *obp = op->find_link ()) |
186 | { |
185 | { |
187 | if (INVOKE_MAP (TRIGGER, op->map, ARG_STRING (&obp->id), ARG_INT (op->value))) |
186 | if (INVOKE_MAP (TRIGGER, op->map, ARG_STRING (&obp->id), ARG_INT (op->value), ARG_OBJECT (op), ARG_OBJECT (originator))) |
188 | return; |
187 | return; |
189 | |
188 | |
190 | activate_connection_link (obp->link, op->value, op); |
189 | activate_connection_link (obp->link, op->value, op, originator); |
191 | } |
190 | } |
192 | } |
191 | } |
193 | |
192 | |
194 | /* |
193 | /* |
195 | * elmex: |
194 | * elmex: |
… | |
… | |
198 | * the connection was 'state' or 'released'. So that you can activate objects |
197 | * the connection was 'state' or 'released'. So that you can activate objects |
199 | * who have FLAG_ACTIVATE_ON_PUSH/RELEASE set properly. |
198 | * who have FLAG_ACTIVATE_ON_PUSH/RELEASE set properly. |
200 | * |
199 | * |
201 | */ |
200 | */ |
202 | void |
201 | void |
203 | maptile::trigger (shstr_tmp id, bool state, object *originator) |
202 | maptile::trigger (shstr_tmp id, int state, object *activator, object *originator) |
204 | { |
203 | { |
205 | if (INVOKE_MAP (TRIGGER, this, ARG_STRING (&id), ARG_INT (state), ARG_OBJECT (originator))) |
204 | if (INVOKE_MAP (TRIGGER, this, ARG_STRING (&id), ARG_INT (state), ARG_OBJECT (originator))) |
206 | return; |
205 | return; |
207 | |
206 | |
208 | if (oblinkpt *obp = find_link (id)) |
207 | if (oblinkpt *obp = find_link (id)) |
209 | activate_connection_link (obp->link, state, originator); |
208 | activate_connection_link (obp->link, state, activator, originator); |
210 | } |
209 | } |
211 | |
210 | |
212 | /* |
211 | /* |
213 | * Updates everything connected with the button op. |
212 | * Updates everything connected with the button op. |
214 | * After changing the state of a button, this function must be called |
213 | * After changing the state of a button, this function must be called |
215 | * to make sure that all gates and other buttons connected to the |
214 | * to make sure that all gates and other buttons connected to the |
216 | * button reacts to the (eventual) change of state. |
215 | * button reacts to the (eventual) change of state. |
217 | */ |
216 | */ |
218 | void |
217 | void |
219 | update_button (object *op) |
218 | update_button (object *op, object *originator) |
220 | { |
219 | { |
221 | int any_down = 0, old_value = op->value; |
220 | int any_down = 0, old_value = op->value; |
222 | |
221 | |
223 | if (oblinkpt *obp = op->find_link ()) |
222 | if (oblinkpt *obp = op->find_link ()) |
224 | for (objectlink *ol = obp->link; ol; ol = ol->next) |
223 | for (objectlink *ol = obp->link; ol; ol = ol->next) |
… | |
… | |
249 | |
248 | |
250 | any_down = any_down || tmp->value; |
249 | any_down = any_down || tmp->value; |
251 | } |
250 | } |
252 | else if (tmp->type == PEDESTAL) |
251 | else if (tmp->type == PEDESTAL) |
253 | { |
252 | { |
|
|
253 | bool is_match = is_match_expr (tmp->slaying); |
254 | tmp->value = 0; |
254 | tmp->value = 0; |
255 | |
255 | |
256 | for (object *ab = tmp->above; ab; ab = ab->above) |
256 | for (object *ab = tmp->above; ab; ab = ab->above) |
257 | { |
257 | { |
258 | object *head = ab->head_ (); |
258 | object *head = ab->head_ (); |
259 | |
259 | |
260 | /* Same note regarding move_type for buttons above apply here. */ |
260 | /* Same note regarding move_type for buttons above apply here. */ |
261 | if (((ab->move_type & tmp->move_on) || ab->move_type == 0) |
261 | if (((ab->move_type & tmp->move_on) || ab->move_type == 0)) |
|
|
262 | if (is_match |
|
|
263 | ? match (tmp->slaying, head, tmp, originator) |
262 | && (head->race == tmp->slaying |
264 | : (head->race == tmp->slaying |
263 | || (head->type == SPECIAL_KEY && head->slaying == tmp->slaying) |
265 | || (head->type == SPECIAL_KEY && head->slaying == tmp->slaying) |
264 | || (tmp->slaying == shstr_player && head->type == PLAYER))) |
266 | || (tmp->slaying == shstr_player && head->type == PLAYER))) |
|
|
267 | { |
265 | tmp->value = 1; |
268 | tmp->value = 1; |
|
|
269 | break; |
|
|
270 | } |
266 | } |
271 | } |
267 | |
272 | |
268 | any_down = any_down || tmp->value; |
273 | any_down = any_down || tmp->value; |
269 | } |
274 | } |
270 | } |
275 | } |
… | |
… | |
277 | /* If this button hasn't changed, don't do anything */ |
282 | /* If this button hasn't changed, don't do anything */ |
278 | if (op->value != old_value) |
283 | if (op->value != old_value) |
279 | { |
284 | { |
280 | SET_ANIMATION (op, op->value); |
285 | SET_ANIMATION (op, op->value); |
281 | update_object (op, UP_OBJ_FACE); |
286 | update_object (op, UP_OBJ_FACE); |
282 | push_button (op); /* Make all other buttons the same */ |
287 | push_button (op, originator); /* Make all other buttons the same */ |
283 | } |
288 | } |
284 | } |
289 | } |
285 | |
290 | |
286 | void |
291 | void |
287 | use_trigger (object *op) |
292 | use_trigger (object *op, object *originator) |
288 | { |
293 | { |
289 | /* Toggle value */ |
294 | /* Toggle value */ |
290 | op->value = !op->value; |
295 | op->value = !op->value; |
|
|
296 | |
291 | push_button (op); |
297 | push_button (op, originator); |
292 | } |
298 | } |
293 | |
299 | |
294 | /* |
300 | /* |
295 | * Note: animate_object should be used instead of this, |
301 | * Note: animate_object should be used instead of this, |
296 | * but it can't handle animations in the 8 directions |
302 | * but it can't handle animations in the 8 directions |
… | |
… | |
317 | * sacrificed. This fixes a bug of trying to put multiple altars/related |
323 | * sacrificed. This fixes a bug of trying to put multiple altars/related |
318 | * objects on the same space that take the same sacrifice. |
324 | * objects on the same space that take the same sacrifice. |
319 | */ |
325 | */ |
320 | |
326 | |
321 | int |
327 | int |
322 | check_altar_sacrifice (const object *altar, const object *sacrifice) |
328 | check_altar_sacrifice (object *altar, object *sacrifice, object *originator) |
323 | { |
329 | { |
|
|
330 | if (sacrifice->flag [FLAG_UNPAID]) |
|
|
331 | return 0; |
|
|
332 | |
|
|
333 | if (is_match_expr (ARCH_SACRIFICE (altar))) |
|
|
334 | return match (ARCH_SACRIFICE (altar), altar, originator); |
|
|
335 | |
324 | if (!QUERY_FLAG (sacrifice, FLAG_ALIVE) |
336 | if (!QUERY_FLAG (sacrifice, FLAG_ALIVE) |
325 | && !QUERY_FLAG (sacrifice, FLAG_IS_LINKED) |
337 | && !QUERY_FLAG (sacrifice, FLAG_IS_LINKED) |
326 | && sacrifice->type != PLAYER) |
338 | && sacrifice->type != PLAYER) |
327 | { |
339 | { |
328 | if (ARCH_SACRIFICE (altar) == shstr_money |
340 | if (ARCH_SACRIFICE (altar) == shstr_money |
… | |
… | |
349 | * |
361 | * |
350 | * If this function returns 1, '*sacrifice' is modified to point to the |
362 | * If this function returns 1, '*sacrifice' is modified to point to the |
351 | * remaining sacrifice, or is set to NULL if the sacrifice was used up. |
363 | * remaining sacrifice, or is set to NULL if the sacrifice was used up. |
352 | */ |
364 | */ |
353 | int |
365 | int |
354 | operate_altar (object *altar, object **sacrifice) |
366 | operate_altar (object *altar, object **sacrifice, object *originator) |
355 | { |
367 | { |
356 | if (!altar->map) |
368 | if (!altar->map) |
357 | { |
369 | { |
358 | LOG (llevError, "BUG: operate_altar(): altar has no map\n"); |
370 | LOG (llevError, "BUG: operate_altar(): altar has no map\n"); |
359 | return 0; |
371 | return 0; |
360 | } |
372 | } |
361 | |
373 | |
362 | if (!altar->slaying || altar->value) |
374 | if (!altar->slaying || altar->value) |
363 | return 0; |
375 | return 0; |
364 | |
376 | |
365 | if (!check_altar_sacrifice (altar, *sacrifice)) |
377 | if (!check_altar_sacrifice (altar, *sacrifice, originator)) |
366 | return 0; |
378 | return 0; |
367 | |
379 | |
368 | /* check_altar_sacrifice should have already verified that enough money |
380 | /* check_altar_sacrifice should have already verified that enough money |
369 | * has been dropped. |
381 | * has been dropped. |
370 | */ |
382 | */ |
… | |
… | |
388 | |
400 | |
389 | return 1; |
401 | return 1; |
390 | } |
402 | } |
391 | |
403 | |
392 | void |
404 | void |
393 | trigger_move (object *op, int state) /* 1 down and 0 up */ |
405 | trigger_move (object *op, int state, object *originator) /* 1 down and 0 up */ |
394 | { |
406 | { |
395 | op->stats.wc = state; |
407 | op->stats.wc = state; |
|
|
408 | |
396 | if (state) |
409 | if (state) |
397 | { |
410 | { |
398 | use_trigger (op); |
411 | use_trigger (op, originator); |
399 | op->set_speed (op->stats.exp > 0 ? 1. / op->stats.exp : 1.); |
412 | op->set_speed (op->stats.exp > 0 ? 1. / op->stats.exp : 1.); |
400 | op->speed_left = -1; |
413 | op->speed_left = -1; |
401 | } |
414 | } |
402 | else |
415 | else |
403 | { |
416 | { |
404 | use_trigger (op); |
417 | use_trigger (op, originator); |
405 | op->set_speed (0); |
418 | op->set_speed (0); |
406 | } |
419 | } |
407 | } |
420 | } |
408 | |
421 | |
409 | |
422 | |
… | |
… | |
418 | * TRIGGER: Returns 1 if handle could be moved, 0 if not. |
431 | * TRIGGER: Returns 1 if handle could be moved, 0 if not. |
419 | * |
432 | * |
420 | * TRIGGER_BUTTON, TRIGGER_PEDESTAL: Returns 0. |
433 | * TRIGGER_BUTTON, TRIGGER_PEDESTAL: Returns 0. |
421 | */ |
434 | */ |
422 | int |
435 | int |
423 | check_trigger (object *op, object *cause) |
436 | check_trigger (object *op, object *cause, object *originator) |
424 | { |
437 | { |
425 | object *tmp; |
438 | object *tmp; |
426 | int push = 0, tot = 0; |
439 | int push = 0, tot = 0; |
427 | int in_movement = op->stats.wc || op->speed; |
440 | int in_movement = op->stats.wc || op->speed; |
428 | |
441 | |
… | |
… | |
458 | } |
471 | } |
459 | |
472 | |
460 | if (in_movement || !push) |
473 | if (in_movement || !push) |
461 | return 0; |
474 | return 0; |
462 | } |
475 | } |
|
|
476 | |
463 | trigger_move (op, push); |
477 | trigger_move (op, push, cause); |
464 | } |
478 | } |
465 | |
479 | |
466 | return 0; |
480 | return 0; |
467 | |
481 | |
468 | case TRIGGER_PEDESTAL: |
482 | case TRIGGER_PEDESTAL: |
… | |
… | |
496 | |
510 | |
497 | if (in_movement || !push) |
511 | if (in_movement || !push) |
498 | return 0; |
512 | return 0; |
499 | } |
513 | } |
500 | |
514 | |
501 | trigger_move (op, push); |
515 | trigger_move (op, push, cause); |
502 | return 0; |
516 | return 0; |
503 | |
517 | |
504 | case TRIGGER_ALTAR: |
518 | case TRIGGER_ALTAR: |
505 | if (cause) |
519 | if (cause) |
506 | { |
520 | { |
507 | if (in_movement) |
521 | if (in_movement) |
508 | return 0; |
522 | return 0; |
509 | |
523 | |
510 | if (operate_altar (op, &cause)) |
524 | if (operate_altar (op, &cause)) /* TODO: originator? */ |
511 | { |
525 | { |
512 | if (NUM_ANIMATIONS (op) > 1) |
526 | if (NUM_ANIMATIONS (op) > 1) |
513 | { |
527 | { |
514 | SET_ANIMATION (op, 1); |
528 | SET_ANIMATION (op, 1); |
515 | update_object (op, UP_OBJ_FACE); |
529 | update_object (op, UP_OBJ_FACE); |
516 | } |
530 | } |
517 | |
531 | |
518 | if (op->last_sp >= 0) |
532 | if (op->last_sp >= 0) |
519 | { |
533 | { |
520 | trigger_move (op, 1); |
534 | trigger_move (op, 1, cause); |
|
|
535 | |
521 | if (op->last_sp > 0) |
536 | if (op->last_sp > 0) |
522 | op->last_sp = -op->last_sp; |
537 | op->last_sp = -op->last_sp; |
523 | } |
538 | } |
524 | else |
539 | else |
525 | { |
540 | { |
526 | /* for trigger altar with last_sp, the ON/OFF |
541 | /* for trigger altar with last_sp, the ON/OFF |
527 | * status (-> +/- value) is "simulated": |
542 | * status (-> +/- value) is "simulated": |
528 | */ |
543 | */ |
529 | op->value = !op->value; |
544 | op->value = !op->value; |
530 | trigger_move (op, 1); |
545 | trigger_move (op, 1, cause); |
531 | op->last_sp = -op->last_sp; |
546 | op->last_sp = -op->last_sp; |
532 | op->value = !op->value; |
547 | op->value = !op->value; |
533 | } |
548 | } |
534 | |
549 | |
535 | return cause == NULL; |
550 | return cause == NULL; |
… | |
… | |
549 | * it will push the connected value only once per sacrifice. |
564 | * it will push the connected value only once per sacrifice. |
550 | * Otherwise (default), the connected value will be |
565 | * Otherwise (default), the connected value will be |
551 | * pushed twice: First by sacrifice, second by reset! -AV |
566 | * pushed twice: First by sacrifice, second by reset! -AV |
552 | */ |
567 | */ |
553 | if (!op->last_sp) |
568 | if (!op->last_sp) |
554 | trigger_move (op, 0); |
569 | trigger_move (op, 0, cause); |
555 | else |
570 | else |
556 | { |
571 | { |
557 | op->stats.wc = 0; |
572 | op->stats.wc = 0; |
558 | op->value = !op->value; |
573 | op->value = !op->value; |
559 | op->set_speed (0); |
574 | op->set_speed (0); |
… | |
… | |
574 | { |
589 | { |
575 | SET_ANIMATION (op, push); |
590 | SET_ANIMATION (op, push); |
576 | update_object (op, UP_OBJ_FACE); |
591 | update_object (op, UP_OBJ_FACE); |
577 | } |
592 | } |
578 | |
593 | |
579 | trigger_move (op, push); |
594 | trigger_move (op, push, cause); |
580 | return 1; |
595 | return 1; |
581 | |
596 | |
582 | default: |
597 | default: |
583 | 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); |
584 | return 0; |
599 | return 0; |
… | |
… | |
665 | continue; |
680 | continue; |
666 | } |
681 | } |
667 | |
682 | |
668 | if (ol->ob->type == BUTTON || ol->ob->type == PEDESTAL) |
683 | if (ol->ob->type == BUTTON || ol->ob->type == PEDESTAL) |
669 | { |
684 | { |
670 | update_button (ol->ob); |
685 | update_button (ol->ob, 0); |
671 | break; |
686 | break; |
672 | } |
687 | } |
673 | } |
688 | } |
674 | } |
689 | } |
675 | |
690 | |
… | |
… | |
880 | { |
895 | { |
881 | if (trig->last_heal) |
896 | if (trig->last_heal) |
882 | match->decrease (); |
897 | match->decrease (); |
883 | |
898 | |
884 | trig->value = (pl == op ? 1 : 0); // 1 if matching player entered, and 0 if he left |
899 | trig->value = (pl == op ? 1 : 0); // 1 if matching player entered, and 0 if he left |
885 | push_button (trig); |
900 | push_button (trig, op); |
886 | } |
901 | } |
887 | else if (!match && !trig->last_sp) // match == not having |
902 | else if (!match && !trig->last_sp) // match == not having |
888 | { |
903 | { |
889 | trig->value = (pl == op ? 1 : 0); // 1 if matching player entered, and 0 if he left |
904 | trig->value = (pl == op ? 1 : 0); // 1 if matching player entered, and 0 if he left |
890 | push_button (trig); |
905 | push_button (trig, op); |
891 | } |
906 | } |
892 | } |
907 | } |
893 | |
908 | |