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.51 by root, Thu Jan 8 03:03:23 2009 UTC vs.
Revision 1.55 by root, Mon Oct 12 04:02:17 2009 UTC

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 */
36void 37static void
37activate_connection_link (objectlink *ol, bool state, object *source = 0) 38activate_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 */
182void 181void
183push_button (object *op) 182push_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 */
202void 201void
203maptile::trigger (shstr_tmp id, bool state, object *originator) 202maptile::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 */
218void 217void
219update_button (object *op) 218update_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
286void 291void
287use_trigger (object *op) 292use_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
321int 327int
322check_altar_sacrifice (const object *altar, const object *sacrifice) 328check_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 */
353int 365int
354operate_altar (object *altar, object **sacrifice) 366operate_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
392void 404void
393trigger_move (object *op, int state) /* 1 down and 0 up */ 405trigger_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 */
422int 435int
423check_trigger (object *op, object *cause) 436check_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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines