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.7 by root, Sun Sep 10 16:00:23 2006 UTC vs.
Revision 1.20 by root, Tue Dec 26 08:54:58 2006 UTC

1
2/*
3 * static char *rcsid_button_c =
4 * "$Id: button.C,v 1.7 2006/09/10 16:00:23 root Exp $";
5 */
6
7/* 1/*
8 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
9 3
10 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
11 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
22 16
23 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
24 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 20
27 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>
28*/ 22*/
29 23
30#include <global.h> 24#include <global.h>
31#include <funcpoint.h> 25#include <funcpoint.h>
32 26
41 * 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.
42 */ 36 */
43void 37void
44activate_connection_link (objectlink * ol, bool state, object *source = 0) 38activate_connection_link (objectlink * ol, bool state, object *source = 0)
45{ 39{
46 object *tmp = 0;
47
48 for (; ol; ol = ol->next) 40 for (; ol; ol = ol->next)
49 { 41 {
50 if (!ol->ob || ol->ob->count != ol->id) 42 if (!ol->ob)
51 { 43 {
52 LOG (llevError, "Internal error in activate_connection_link (%ld).\n", ol->id); 44 LOG (llevError, "Internal error in activate_connection_link.\n");
53 continue; 45 continue;
54 } 46 }
47
55 /* a button link object can become freed when the map is saving. As 48 /* a button link object can become freed when the map is saving. As
56 * a map is saved, objects are removed and freed, and if an object is 49 * a map is saved, objects are removed and freed, and if an object is
57 * on top of a button, this function is eventually called. If a map 50 * on top of a button, this function is eventually called. If a map
58 * is getting moved out of memory, the status of buttons and levers 51 * is getting moved out of memory, the status of buttons and levers
59 * probably isn't important - it will get sorted out when the map is 52 * probably isn't important - it will get sorted out when the map is
60 * re-loaded. As such, just exit this function if that is the case. 53 * re-loaded. As such, just exit this function if that is the case.
61 */ 54 */
62 55
63 if (QUERY_FLAG (ol->ob, FLAG_FREED)) 56 if (QUERY_FLAG (ol->ob, FLAG_FREED))
64 return; 57 return;
58
65 tmp = ol->ob; 59 object *tmp = ol->ob;
66 60
67 /* if the criteria isn't appropriate, don't do anything */ 61 /* if the criteria isn't appropriate, don't do anything */
68 if (state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_PUSH)) 62 if (state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_PUSH))
69 continue; 63 continue;
70 if (!state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_RELEASE)) 64 if (!state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_RELEASE))
71 continue; 65 continue;
72 66
73 switch (tmp->type) 67 switch (tmp->type)
74 { 68 {
75 case GATE: 69 case GATE:
76 case HOLE: 70 case HOLE:
77 tmp->value = tmp->stats.maxsp ? !state : state; 71 tmp->value = tmp->stats.maxsp ? !state : state;
78 tmp->speed = 0.5; 72 tmp->set_speed (0.5);
79 update_ob_speed (tmp);
80 break; 73 break;
81 74
82 case CF_HANDLE: 75 case CF_HANDLE:
83 SET_ANIMATION (tmp, (tmp->value = tmp->stats.maxsp ? !state : state)); 76 SET_ANIMATION (tmp, (tmp->value = tmp->stats.maxsp ? !state : state));
84 update_object (tmp, UP_OBJ_FACE); 77 update_object (tmp, UP_OBJ_FACE);
85 break; 78 break;
86 79
87 case SIGN: 80 case SIGN:
88 if (!tmp->stats.food || tmp->last_eat < tmp->stats.food) 81 if (!tmp->stats.food || tmp->last_eat < tmp->stats.food)
89 { 82 {
90 new_info_map (NDI_UNIQUE | NDI_NAVY, tmp->map, tmp->msg); 83 new_info_map (NDI_UNIQUE | NDI_NAVY, tmp->map, tmp->msg);
91 if (tmp->stats.food) 84 if (tmp->stats.food)
92 tmp->last_eat++; 85 tmp->last_eat++;
93 } 86 }
94 break; 87 break;
95 88
96 case ALTAR: 89 case ALTAR:
97 tmp->value = 1; 90 tmp->value = 1;
98 SET_ANIMATION (tmp, tmp->value); 91 SET_ANIMATION (tmp, tmp->value);
99 update_object (tmp, UP_OBJ_FACE); 92 update_object (tmp, UP_OBJ_FACE);
100 break; 93 break;
101 94
102 case BUTTON: 95 case BUTTON:
103 case PEDESTAL: 96 case PEDESTAL:
104 tmp->value = state; 97 tmp->value = state;
105 SET_ANIMATION (tmp, tmp->value); 98 SET_ANIMATION (tmp, tmp->value);
106 update_object (tmp, UP_OBJ_FACE); 99 update_object (tmp, UP_OBJ_FACE);
107 break; 100 break;
108 101
109 case MOOD_FLOOR: 102 case MOOD_FLOOR:
110 do_mood_floor (tmp, source); 103 do_mood_floor (tmp, source);
111 break; 104 break;
112 105
113 case TIMED_GATE: 106 case TIMED_GATE:
114 tmp->speed = tmp->arch->clone.speed; 107 tmp->set_speed (tmp->arch->clone.speed);
115 update_ob_speed (tmp); /* original values */
116 tmp->value = tmp->arch->clone.value; 108 tmp->value = tmp->arch->clone.value;
117 tmp->stats.sp = 1; 109 tmp->stats.sp = 1;
118 tmp->stats.hp = tmp->stats.maxhp; 110 tmp->stats.hp = tmp->stats.maxhp;
119 /* Handle multipart gates. We copy the value for the other parts 111 /* Handle multipart gates. We copy the value for the other parts
120 * from the head - this ensures that the data will consistent 112 * from the head - this ensures that the data will consistent
121 */ 113 */
122 for (tmp = tmp->more; tmp != NULL; tmp = tmp->more) 114 for (tmp = tmp->more; tmp; tmp = tmp->more)
123 { 115 {
124 tmp->speed = tmp->head->speed;
125 tmp->value = tmp->head->value; 116 tmp->value = tmp->head->value;
126 tmp->stats.sp = tmp->head->stats.sp; 117 tmp->stats.sp = tmp->head->stats.sp;
127 tmp->stats.hp = tmp->head->stats.hp; 118 tmp->stats.hp = tmp->head->stats.hp;
128 update_ob_speed (tmp); 119 tmp->set_speed (tmp->head->speed);
129 } 120 }
130 break; 121 break;
131 122
132 case DIRECTOR: 123 case DIRECTOR:
133 case FIREWALL: 124 case FIREWALL:
134 if (!QUERY_FLAG (tmp, FLAG_ANIMATE) && tmp->type == FIREWALL) 125 if (!QUERY_FLAG (tmp, FLAG_ANIMATE) && tmp->type == FIREWALL)
135 move_firewall (tmp); 126 move_firewall (tmp);
136 else 127 else
137 { 128 {
138 if ((tmp->stats.sp += tmp->stats.maxsp) > 8) /* next direction */ 129 if ((tmp->stats.sp += tmp->stats.maxsp) > 8) /* next direction */
139 tmp->stats.sp = ((tmp->stats.sp - 1) % 8) + 1; 130 tmp->stats.sp = ((tmp->stats.sp - 1) % 8) + 1;
140 animate_turning (tmp); 131 animate_turning (tmp);
141 } 132 }
142 break; 133 break;
143 134
144 case TELEPORTER: 135 case TELEPORTER:
145 move_teleporter (tmp); 136 move_teleporter (tmp);
146 break; 137 break;
147 138
148 case CREATOR: 139 case CREATOR:
149 move_creator (tmp); 140 move_creator (tmp);
150 break; 141 break;
151 142
152 case TRIGGER_MARKER: 143 case TRIGGER_MARKER:
153 move_marker (tmp); 144 move_marker (tmp);
154 break; 145 break;
155 146
156 case DUPLICATOR: 147 case DUPLICATOR:
157 move_duplicator (tmp); 148 move_duplicator (tmp);
158 break; 149 break;
159 } 150 }
160 } 151 }
161} 152}
162 153
163/* 154/*
193 * the connection was 'state' or 'released'. So that you can activate objects 184 * the connection was 'state' or 'released'. So that you can activate objects
194 * who have FLAG_ACTIVATE_ON_PUSH/RELEASE set properly. 185 * who have FLAG_ACTIVATE_ON_PUSH/RELEASE set properly.
195 * 186 *
196 */ 187 */
197void 188void
198activate_connection (mapstruct *map, long connection, bool state) 189activate_connection (maptile *map, long connection, bool state)
199{ 190{
200 if (INVOKE_MAP (TRIGGER, map, ARG_INT64 (connection), ARG_INT (state))) 191 if (INVOKE_MAP (TRIGGER, map, ARG_INT64 (connection), ARG_INT (state)))
201 return; 192 return;
202 193
203 oblinkpt *obp = get_connection_links (map, connection); 194 oblinkpt *obp = get_connection_links (map, connection);
210 * Updates everything connected with the button op. 201 * Updates everything connected with the button op.
211 * After changing the state of a button, this function must be called 202 * After changing the state of a button, this function must be called
212 * to make sure that all gates and other buttons connected to the 203 * to make sure that all gates and other buttons connected to the
213 * button reacts to the (eventual) change of state. 204 * button reacts to the (eventual) change of state.
214 */ 205 */
215
216void 206void
217update_button (object *op) 207update_button (object *op)
218{ 208{
219 object *ab, *tmp, *head; 209 object *ab, *tmp, *head;
220 int tot, any_down = 0, old_value = op->value; 210 int tot, any_down = 0, old_value = op->value;
224 obp = get_button_links (op); 214 obp = get_button_links (op);
225 /* LOG(llevDebug, "update_button: %s (%d)\n", op->name, op->count); */ 215 /* LOG(llevDebug, "update_button: %s (%d)\n", op->name, op->count); */
226 if (obp) 216 if (obp)
227 for (ol = obp->link; ol; ol = ol->next) 217 for (ol = obp->link; ol; ol = ol->next)
228 { 218 {
229 if (!ol->ob || ol->ob->count != ol->id) 219 if (!ol->ob)
230 { 220 {
231 LOG (llevDebug, "Internal error in update_button (%s).\n", &op->name); 221 LOG (llevDebug, "Internal error in update_button (%s).\n", &op->name);
232 continue; 222 continue;
233 } 223 }
224
234 tmp = ol->ob; 225 tmp = ol->ob;
235 if (tmp->type == BUTTON) 226 if (tmp->type == BUTTON)
236 { 227 {
237 for (ab = tmp->above, tot = 0; ab != NULL; ab = ab->above) 228 for (ab = tmp->above, tot = 0; ab != NULL; ab = ab->above)
238 /* Bug? The pedestal code below looks for the head of 229 /* Bug? The pedestal code below looks for the head of
287/* 278/*
288 * Updates every button on the map (by calling update_button() for them). 279 * Updates every button on the map (by calling update_button() for them).
289 */ 280 */
290 281
291void 282void
292update_buttons (mapstruct *m) 283update_buttons (maptile *m)
293{ 284{
294 objectlink *ol; 285 objectlink *ol;
295 oblinkpt *obp; 286 oblinkpt *obp;
296 287
297 for (obp = m->buttons; obp; obp = obp->next) 288 for (obp = m->buttons; obp; obp = obp->next)
298 for (ol = obp->link; ol; ol = ol->next) 289 for (ol = obp->link; ol; ol = ol->next)
299 { 290 {
300 if (!ol->ob || ol->ob->count != ol->id) 291 if (!ol->ob)
301 { 292 {
302 LOG (llevError, "Internal error in update_button (%s (%dx%d):%d, connected %ld).\n", 293 LOG (llevError, "Internal error in update_button (%s (%dx%d), connected %ld).\n",
303 ol->ob ? (const char *) ol->ob->name : "null", ol->ob ? ol->ob->x : -1, ol->ob ? ol->ob->y : -1, ol->id, obp->value); 294 ol->ob ? (const char *) ol->ob->name : "null", ol->ob ? ol->ob->x : -1, ol->ob ? ol->ob->y : -1, obp->value);
304 continue; 295 continue;
305 } 296 }
297
306 if (ol->ob->type == BUTTON || ol->ob->type == PEDESTAL) 298 if (ol->ob->type == BUTTON || ol->ob->type == PEDESTAL)
307 { 299 {
308 update_button (ol->ob); 300 update_button (ol->ob);
309 break; 301 break;
310 } 302 }
357 ARCH_SACRIFICE (altar) == sacrifice->name || 349 ARCH_SACRIFICE (altar) == sacrifice->name ||
358 ARCH_SACRIFICE (altar) == sacrifice->slaying || 350 ARCH_SACRIFICE (altar) == sacrifice->slaying ||
359 (!strcmp (ARCH_SACRIFICE (altar), query_base_name (sacrifice, 0)))) 351 (!strcmp (ARCH_SACRIFICE (altar), query_base_name (sacrifice, 0))))
360 && NROF_SACRIFICE (altar) <= (sacrifice->nrof ? sacrifice->nrof : 1)) 352 && NROF_SACRIFICE (altar) <= (sacrifice->nrof ? sacrifice->nrof : 1))
361 return 1; 353 return 1;
354
362 if (strcmp (ARCH_SACRIFICE (altar), "money") == 0 355 if (strcmp (ARCH_SACRIFICE (altar), "money") == 0
363 && sacrifice->type == MONEY && sacrifice->nrof * sacrifice->value >= NROF_SACRIFICE (altar)) 356 && sacrifice->type == MONEY && sacrifice->nrof * sacrifice->value >= NROF_SACRIFICE (altar))
364 return 1; 357 return 1;
365 } 358 }
359
366 return 0; 360 return 0;
367} 361}
368
369 362
370/* 363/*
371 * operate_altar checks if sacrifice was accepted and removes sacrificed 364 * operate_altar checks if sacrifice was accepted and removes sacrificed
372 * objects. If sacrifice was succeed return 1 else 0. Might be better to 365 * objects. If sacrifice was succeed return 1 else 0. Might be better to
373 * call check_altar_sacrifice (above) than depend on the return value, 366 * call check_altar_sacrifice (above) than depend on the return value,
374 * since operate_altar will remove the sacrifice also. 367 * since operate_altar will remove the sacrifice also.
375 * 368 *
376 * If this function returns 1, '*sacrifice' is modified to point to the 369 * If this function returns 1, '*sacrifice' is modified to point to the
377 * remaining sacrifice, or is set to NULL if the sacrifice was used up. 370 * remaining sacrifice, or is set to NULL if the sacrifice was used up.
378 */ 371 */
379
380int 372int
381operate_altar (object *altar, object **sacrifice) 373operate_altar (object *altar, object **sacrifice)
382{ 374{
383
384 if (!altar->map) 375 if (!altar->map)
385 { 376 {
386 LOG (llevError, "BUG: operate_altar(): altar has no map\n"); 377 LOG (llevError, "BUG: operate_altar(): altar has no map\n");
387 return 0; 378 return 0;
388 } 379 }
401 int number = NROF_SACRIFICE (altar) / (*sacrifice)->value; 392 int number = NROF_SACRIFICE (altar) / (*sacrifice)->value;
402 393
403 /* Round up any sacrifices. Altars don't make change either */ 394 /* Round up any sacrifices. Altars don't make change either */
404 if (NROF_SACRIFICE (altar) % (*sacrifice)->value) 395 if (NROF_SACRIFICE (altar) % (*sacrifice)->value)
405 number++; 396 number++;
397
406 *sacrifice = decrease_ob_nr (*sacrifice, number); 398 *sacrifice = decrease_ob_nr (*sacrifice, number);
407 } 399 }
408 else 400 else
409 *sacrifice = decrease_ob_nr (*sacrifice, NROF_SACRIFICE (altar)); 401 *sacrifice = decrease_ob_nr (*sacrifice, NROF_SACRIFICE (altar));
410 402
411 if (altar->msg) 403 if (altar->msg)
412 new_info_map (NDI_BLACK, altar->map, altar->msg); 404 new_info_map (NDI_BLACK, altar->map, altar->msg);
405
413 return 1; 406 return 1;
414} 407}
415 408
416void 409void
417trigger_move (object *op, int state) /* 1 down and 0 up */ 410trigger_move (object *op, int state) /* 1 down and 0 up */
418{ 411{
419 op->stats.wc = state; 412 op->stats.wc = state;
420 if (state) 413 if (state)
421 { 414 {
422 use_trigger (op); 415 use_trigger (op);
423 if (op->stats.exp > 0) /* check sanity */ 416 op->set_speed (op->stats.exp > 0 ? 1. / op->stats.exp : 1.);
424 op->speed = 1.0 / op->stats.exp;
425 else
426 op->speed = 1.0;
427 update_ob_speed (op);
428 op->speed_left = -1; 417 op->speed_left = -1;
429 } 418 }
430 else 419 else
431 { 420 {
432 use_trigger (op); 421 use_trigger (op);
433 op->speed = 0; 422 op->set_speed (0);
434 update_ob_speed (op);
435 } 423 }
436} 424}
437 425
438 426
439/* 427/*
574 trigger_move (op, 0); 562 trigger_move (op, 0);
575 else 563 else
576 { 564 {
577 op->stats.wc = 0; 565 op->stats.wc = 0;
578 op->value = !op->value; 566 op->value = !op->value;
579 op->speed = 0; 567 op->set_speed (0);
580 update_ob_speed (op);
581 } 568 }
582 } 569 }
583 return 0; 570 return 0;
584 571
585 case TRIGGER: 572 case TRIGGER:
586 if (cause) 573 if (cause)
587 { 574 {
588 if (in_movement) 575 if (in_movement)
589 return 0; 576 return 0;
577
590 push = 1; 578 push = 1;
591 } 579 }
580
592 if (NUM_ANIMATIONS (op) > 1) 581 if (NUM_ANIMATIONS (op) > 1)
593 { 582 {
594 SET_ANIMATION (op, push); 583 SET_ANIMATION (op, push);
595 update_object (op, UP_OBJ_FACE); 584 update_object (op, UP_OBJ_FACE);
596 } 585 }
586
597 trigger_move (op, push); 587 trigger_move (op, push);
598 return 1; 588 return 1;
599 589
600 default: 590 default:
601 LOG (llevDebug, "Unknown trigger type: %s (%d)\n", &op->name, op->type); 591 LOG (llevDebug, "Unknown trigger type: %s (%d)\n", &op->name, op->type);
602 return 0; 592 return 0;
603 } 593 }
604} 594}
605 595
606void 596void
607add_button_link (object *button, mapstruct *map, int connected) 597add_button_link (object *button, maptile *map, int connected)
608{ 598{
609 oblinkpt *obp; 599 oblinkpt *obp;
610 objectlink *ol = get_objectlink (); 600 objectlink *ol = get_objectlink ();
611 601
612 if (!map) 602 if (!map)
613 { 603 {
614 LOG (llevError, "Tried to add button-link without map.\n"); 604 LOG (llevError, "Tried to add button-link without map.\n");
615 return; 605 return;
616 } 606 }
617 if (!editor) 607
618 button->path_attuned = connected; /* peterm: I need this so I can rebuild 608 button->path_attuned = connected; /* peterm: I need this so I can rebuild
619 a connected map from a template map. */ 609 a connected map from a template map. */
620
621/* LOG(llevDebug,"adding button %s (%d)\n", button->name, connected);*/
622 610
623 SET_FLAG (button, FLAG_IS_LINKED); 611 SET_FLAG (button, FLAG_IS_LINKED);
624 612
625 ol->ob = button; 613 ol->ob = button;
626 ol->id = button->count;
627 614
628 for (obp = map->buttons; obp && obp->value != connected; obp = obp->next); 615 for (obp = map->buttons; obp && obp->value != connected; obp = obp->next)
616 ;
629 617
630 if (obp) 618 if (obp)
631 { 619 {
632 ol->next = obp->link; 620 ol->next = obp->link;
633 obp->link = ol; 621 obp->link = ol;
657 if (op->map == NULL) 645 if (op->map == NULL)
658 { 646 {
659 LOG (llevError, "remove_button_link() in object without map.\n"); 647 LOG (llevError, "remove_button_link() in object without map.\n");
660 return; 648 return;
661 } 649 }
650
662 if (!QUERY_FLAG (op, FLAG_IS_LINKED)) 651 if (!QUERY_FLAG (op, FLAG_IS_LINKED))
663 { 652 {
664 LOG (llevError, "remove_button_linked() in unlinked object.\n"); 653 LOG (llevError, "remove_button_linked() in unlinked object.\n");
665 return; 654 return;
666 } 655 }
656
667 for (obp = op->map->buttons; obp; obp = obp->next) 657 for (obp = op->map->buttons; obp; obp = obp->next)
668 for (olp = &obp->link; (ol = *olp); olp = &ol->next) 658 for (olp = &obp->link; (ol = *olp); olp = &ol->next)
669 if (ol->ob == op) 659 if (ol->ob == op)
670 { 660 {
671 661
672/* LOG(llevDebug, "Removed link %d in button %s and map %s.\n", 662/* LOG(llevDebug, "Removed link %d in button %s and map %s.\n",
673 obp->value, op->name, op->map->path); 663 obp->value, op->name, op->map->path);
674*/ 664*/
675 *olp = ol->next; 665 *olp = ol->next;
676 free (ol); 666 delete ol;
677 return; 667 return;
678 } 668 }
669
679 LOG (llevError, "remove_button_linked(): couldn't find object.\n"); 670 LOG (llevError, "remove_button_linked(): couldn't find object.\n");
680 CLEAR_FLAG (op, FLAG_IS_LINKED); 671 CLEAR_FLAG (op, FLAG_IS_LINKED);
681} 672}
682 673
683/* 674/*
684 * Gets the objectlink for this connection from the map. 675 * Gets the objectlink for this connection from the map.
685 */ 676 */
686oblinkpt * 677oblinkpt *
687get_connection_links (mapstruct *map, long connection) 678get_connection_links (maptile *map, long connection)
688{ 679{
689 for (oblinkpt * obp = map->buttons; obp; obp = obp->next) 680 for (oblinkpt * obp = map->buttons; obp; obp = obp->next)
690 if (obp->value == connection) 681 if (obp->value == connection)
691 return obp; 682 return obp;
683
692 return 0; 684 return 0;
693} 685}
694 686
695/* 687/*
696 * Return the first objectlink in the objects linked to this one 688 * Return the first objectlink in the objects linked to this one
702 oblinkpt *obp; 694 oblinkpt *obp;
703 objectlink *ol; 695 objectlink *ol;
704 696
705 if (!button->map) 697 if (!button->map)
706 return NULL; 698 return NULL;
699
707 for (obp = button->map->buttons; obp; obp = obp->next) 700 for (obp = button->map->buttons; obp; obp = obp->next)
708 for (ol = obp->link; ol; ol = ol->next) 701 for (ol = obp->link; ol; ol = ol->next)
709 if (ol->ob == button && ol->id == button->count) 702 if (ol->ob == button)
710 return obp; 703 return obp;
704
711 return NULL; 705 return NULL;
712} 706}
713 707
714/* 708/*
715 * Made as a separate function to increase efficiency 709 * Made as a separate function to increase efficiency
723 717
724 if (!button->map) 718 if (!button->map)
725 return 0; 719 return 0;
726 for (obp = button->map->buttons; obp; obp = obp->next) 720 for (obp = button->map->buttons; obp; obp = obp->next)
727 for (ol = obp->link; ol; ol = ol->next) 721 for (ol = obp->link; ol; ol = ol->next)
728 if (ol->ob == button && ol->id == button->count) 722 if (ol->ob == button)
729 return obp->value; 723 return obp->value;
730 return 0; 724 return 0;
731} 725}
732 726
733/* This routine makes monsters who are 727/* This routine makes monsters who are
758 if (!tmp || tmp->type == PLAYER) 752 if (!tmp || tmp->type == PLAYER)
759 return; 753 return;
760 754
761 switch (op->last_sp) 755 switch (op->last_sp)
762 { 756 {
763 case 0: /* furious--make all monsters mad */ 757 case 0: /* furious--make all monsters mad */
764 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE)) 758 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE))
765 CLEAR_FLAG (tmp, FLAG_UNAGGRESSIVE); 759 CLEAR_FLAG (tmp, FLAG_UNAGGRESSIVE);
766 if (QUERY_FLAG (tmp, FLAG_FRIENDLY)) 760 if (QUERY_FLAG (tmp, FLAG_FRIENDLY))
767 { 761 {
768 CLEAR_FLAG (tmp, FLAG_FRIENDLY); 762 CLEAR_FLAG (tmp, FLAG_FRIENDLY);
769 remove_friendly_object (tmp); 763 remove_friendly_object (tmp);
770 tmp->attack_movement = 0; 764 tmp->attack_movement = 0;
771 /* lots of checks here, but want to make sure we don't 765 /* lots of checks here, but want to make sure we don't
772 * dereference a null value 766 * dereference a null value
773 */ 767 */
774 if (tmp->type == GOLEM && tmp->owner && tmp->owner->type == PLAYER && tmp->owner->contr->ranges[range_golem] == tmp) 768 if (tmp->type == GOLEM && tmp->owner && tmp->owner->type == PLAYER && tmp->owner->contr->ranges[range_golem] == tmp)
775 {
776 tmp->owner->contr->ranges[range_golem] = NULL; 769 tmp->owner->contr->ranges[range_golem] = 0;
777 tmp->owner->contr->golem_count = 0; 770
778 }
779 tmp->owner = 0; 771 tmp->owner = 0;
780 } 772 }
773 break;
774 case 1: /* angry -- get neutral monsters mad */
775 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (tmp, FLAG_FRIENDLY))
776 CLEAR_FLAG (tmp, FLAG_UNAGGRESSIVE);
777 break;
778 case 2: /* calm -- pacify unfriendly monsters */
779 if (!QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE))
780 SET_FLAG (tmp, FLAG_UNAGGRESSIVE);
781 break;
782 case 3: /* make all monsters fall asleep */
783 if (!QUERY_FLAG (tmp, FLAG_SLEEP))
784 SET_FLAG (tmp, FLAG_SLEEP);
785 break;
786 case 4: /* charm all monsters */
787 if (op == source)
788 break; /* only if 'connected' */
789
790 for (tmp2 = GET_MAP_OB (source->map, source->x, source->y); /* finding an owner */
791 tmp2->type != PLAYER; tmp2 = tmp2->above)
792 if (tmp2->above == NULL)
793 break;
794
795 if (tmp2->type != PLAYER)
781 break; 796 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;
786 case 2: /* calm -- pacify unfriendly monsters */
787 if (!QUERY_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 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)
801 break;
802
803 if (tmp2->type != PLAYER)
804 break;
805 set_owner (tmp, tmp2); 798 tmp->set_owner (tmp2);
806 SET_FLAG (tmp, FLAG_MONSTER); 799 SET_FLAG (tmp, FLAG_MONSTER);
800
807 tmp->stats.exp = 0; 801 tmp->stats.exp = 0;
808 SET_FLAG (tmp, FLAG_FRIENDLY); 802 SET_FLAG (tmp, FLAG_FRIENDLY);
803
809 add_friendly_object (tmp); 804 add_friendly_object (tmp);
810 tmp->attack_movement = PETMOVE; 805 tmp->attack_movement = PETMOVE;
811 break; 806 break;
812 807
813 default: 808 default:
814 break; 809 break;
815
816 } 810 }
817} 811}
818 812
819/* this function returns the object it matches, or NULL if non. 813/* this function returns the object it matches, or NULL if non.
820 * It will descend through containers to find the object. 814 * It will descend through containers to find the object.
821 * slaying = match object slaying flag 815 * slaying = match object slaying flag
822 * race = match object archetype name flag 816 * race = match object archetype name flag
823 * hp = match object type (excpt type '0'== PLAYER) 817 * hp = match object type (excpt type '0'== PLAYER)
824 */ 818 */
825
826object * 819object *
827check_inv_recursive (object *op, const object *trig) 820check_inv_recursive (object *op, const object *trig)
828{ 821{
829 object *tmp, *ret = NULL; 822 object *tmp, *ret = NULL;
830 823
831 /* First check the object itself. */ 824 /* First check the object itself. */
832 if ((trig->stats.hp && (op->type == trig->stats.hp)) 825 if ((trig->stats.hp && (op->type == trig->stats.hp))
833 || (trig->slaying && (op->slaying == trig->slaying)) || (trig->race && (op->arch->name == trig->race))) 826 || (trig->slaying && (op->slaying == trig->slaying))
827 || (trig->race && (op->arch->name == trig->race)))
834 return op; 828 return op;
835 829
836 for (tmp = op->inv; tmp; tmp = tmp->below) 830 for (tmp = op->inv; tmp; tmp = tmp->below)
837 { 831 {
838 if (tmp->inv) 832 if (tmp->inv)
840 ret = check_inv_recursive (tmp, trig); 834 ret = check_inv_recursive (tmp, trig);
841 if (ret) 835 if (ret)
842 return ret; 836 return ret;
843 } 837 }
844 else if ((trig->stats.hp && (tmp->type == trig->stats.hp)) 838 else if ((trig->stats.hp && (tmp->type == trig->stats.hp))
845 || (trig->slaying && (tmp->slaying == trig->slaying)) || (trig->race && (tmp->arch->name == trig->race))) 839 || (trig->slaying && (tmp->slaying == trig->slaying))
840 || (trig->race && (tmp->arch->name == trig->race)))
846 return tmp; 841 return tmp;
847 } 842 }
848 return NULL; 843 return NULL;
849} 844}
850 845
853 * the square will activate connected items. 848 * the square will activate connected items.
854 * Monsters can't trigger this square (for now) 849 * Monsters can't trigger this square (for now)
855 * Values are: last_sp = 1/0 obj/no obj triggers 850 * Values are: last_sp = 1/0 obj/no obj triggers
856 * last_heal = 1/0 remove/dont remove obj if triggered 851 * last_heal = 1/0 remove/dont remove obj if triggered
857 * -b.t. (thomas@nomad.astro.psu.edu 852 * -b.t. (thomas@nomad.astro.psu.edu
858 */ 853 *
859 854 * Tue Dec 19 15:34:00 CET 2006 elmex: changed the function to ignore op
855 * because the check-inventory semantic essentially only applies when
856 * something is above the inventory checker.
857 * The semantic prior this change was: trigger if something has moved on or off
858 * and has a matching item. Imagine what happens if someone steps on the inventory
859 * checker with a matching item, has it, activates the connection, throws the item
860 * away, and then leaves the inventory checker. That would've caused an always-enabled
861 * state in the inventory checker. This won't happen anymore now.
862 *
863 */
860void 864void
861check_inv (object *op, object *trig) 865check_inv (object *op, object *trig)
862{ 866{
863 object *match; 867 trig->value = 0; // deactivate if none of the following conditions apply
864 868
865 if (op->type != PLAYER) 869 if (object *pl = trig->ms ().player ())
866 return; 870 {
867 match = check_inv_recursive (op, trig); 871 object *match = check_inv_recursive (pl, trig);
868 if (match && trig->last_sp)
869 {
870 if (trig->last_heal)
871 decrease_ob (match);
872 use_trigger (trig);
873 }
874 else if (!match && !trig->last_sp)
875 use_trigger (trig);
876}
877 872
878 873 if (match && trig->last_sp) // match == having
879/* This does a minimal check of the button link consistency for object
880 * map. All it really does it much sure the object id link that is set
881 * matches what the object has.
882 */
883void
884verify_button_links (const mapstruct *map)
885{
886 oblinkpt *obp;
887 objectlink *ol;
888
889 if (!map)
890 return;
891
892 for (obp = map->buttons; obp; obp = obp->next)
893 {
894 for (ol = obp->link; ol; ol = ol->next)
895 { 874 {
896 if (ol->id != ol->ob->count) 875 if (trig->last_heal)
897 LOG (llevError, "verify_button_links: object %s on list is corrupt (%d!=%d)\n", &ol->ob->name, ol->id, ol->ob->count); 876 decrease_ob (match);
877
878 trig->value = 1;
898 } 879 }
880 else if (!match && !trig->last_sp) // match == not having
881 trig->value = 1;
899 } 882 }
883
884 push_button (trig);
900} 885}
886

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines