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.19 by root, Mon Dec 25 11:25:49 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->speed = 0.5;
79 update_ob_speed (tmp); 73 update_ob_speed (tmp);
80 break; 74 break;
81 75
82 case CF_HANDLE: 76 case CF_HANDLE:
83 SET_ANIMATION (tmp, (tmp->value = tmp->stats.maxsp ? !state : state)); 77 SET_ANIMATION (tmp, (tmp->value = tmp->stats.maxsp ? !state : state));
84 update_object (tmp, UP_OBJ_FACE); 78 update_object (tmp, UP_OBJ_FACE);
85 break; 79 break;
86 80
87 case SIGN: 81 case SIGN:
88 if (!tmp->stats.food || tmp->last_eat < tmp->stats.food) 82 if (!tmp->stats.food || tmp->last_eat < tmp->stats.food)
89 { 83 {
90 new_info_map (NDI_UNIQUE | NDI_NAVY, tmp->map, tmp->msg); 84 new_info_map (NDI_UNIQUE | NDI_NAVY, tmp->map, tmp->msg);
91 if (tmp->stats.food) 85 if (tmp->stats.food)
92 tmp->last_eat++; 86 tmp->last_eat++;
93 } 87 }
94 break; 88 break;
95 89
96 case ALTAR: 90 case ALTAR:
97 tmp->value = 1; 91 tmp->value = 1;
98 SET_ANIMATION (tmp, tmp->value); 92 SET_ANIMATION (tmp, tmp->value);
99 update_object (tmp, UP_OBJ_FACE); 93 update_object (tmp, UP_OBJ_FACE);
100 break; 94 break;
101 95
102 case BUTTON: 96 case BUTTON:
103 case PEDESTAL: 97 case PEDESTAL:
104 tmp->value = state; 98 tmp->value = state;
105 SET_ANIMATION (tmp, tmp->value); 99 SET_ANIMATION (tmp, tmp->value);
106 update_object (tmp, UP_OBJ_FACE); 100 update_object (tmp, UP_OBJ_FACE);
107 break; 101 break;
108 102
109 case MOOD_FLOOR: 103 case MOOD_FLOOR:
110 do_mood_floor (tmp, source); 104 do_mood_floor (tmp, source);
111 break; 105 break;
112 106
113 case TIMED_GATE: 107 case TIMED_GATE:
114 tmp->speed = tmp->arch->clone.speed; 108 tmp->speed = tmp->arch->clone.speed;
115 update_ob_speed (tmp); /* original values */ 109 update_ob_speed (tmp); /* original values */
116 tmp->value = tmp->arch->clone.value; 110 tmp->value = tmp->arch->clone.value;
117 tmp->stats.sp = 1; 111 tmp->stats.sp = 1;
118 tmp->stats.hp = tmp->stats.maxhp; 112 tmp->stats.hp = tmp->stats.maxhp;
119 /* Handle multipart gates. We copy the value for the other parts 113 /* Handle multipart gates. We copy the value for the other parts
120 * from the head - this ensures that the data will consistent 114 * from the head - this ensures that the data will consistent
121 */ 115 */
122 for (tmp = tmp->more; tmp != NULL; tmp = tmp->more) 116 for (tmp = tmp->more; tmp != NULL; tmp = tmp->more)
123 { 117 {
124 tmp->speed = tmp->head->speed; 118 tmp->speed = tmp->head->speed;
125 tmp->value = tmp->head->value; 119 tmp->value = tmp->head->value;
126 tmp->stats.sp = tmp->head->stats.sp; 120 tmp->stats.sp = tmp->head->stats.sp;
127 tmp->stats.hp = tmp->head->stats.hp; 121 tmp->stats.hp = tmp->head->stats.hp;
128 update_ob_speed (tmp); 122 update_ob_speed (tmp);
129 } 123 }
130 break; 124 break;
131 125
132 case DIRECTOR: 126 case DIRECTOR:
133 case FIREWALL: 127 case FIREWALL:
134 if (!QUERY_FLAG (tmp, FLAG_ANIMATE) && tmp->type == FIREWALL) 128 if (!QUERY_FLAG (tmp, FLAG_ANIMATE) && tmp->type == FIREWALL)
135 move_firewall (tmp); 129 move_firewall (tmp);
136 else 130 else
137 { 131 {
138 if ((tmp->stats.sp += tmp->stats.maxsp) > 8) /* next direction */ 132 if ((tmp->stats.sp += tmp->stats.maxsp) > 8) /* next direction */
139 tmp->stats.sp = ((tmp->stats.sp - 1) % 8) + 1; 133 tmp->stats.sp = ((tmp->stats.sp - 1) % 8) + 1;
140 animate_turning (tmp); 134 animate_turning (tmp);
141 } 135 }
142 break; 136 break;
143 137
144 case TELEPORTER: 138 case TELEPORTER:
145 move_teleporter (tmp); 139 move_teleporter (tmp);
146 break; 140 break;
147 141
148 case CREATOR: 142 case CREATOR:
149 move_creator (tmp); 143 move_creator (tmp);
150 break; 144 break;
151 145
152 case TRIGGER_MARKER: 146 case TRIGGER_MARKER:
153 move_marker (tmp); 147 move_marker (tmp);
154 break; 148 break;
155 149
156 case DUPLICATOR: 150 case DUPLICATOR:
157 move_duplicator (tmp); 151 move_duplicator (tmp);
158 break; 152 break;
159 } 153 }
160 } 154 }
161} 155}
162 156
163/* 157/*
193 * the connection was 'state' or 'released'. So that you can activate objects 187 * the connection was 'state' or 'released'. So that you can activate objects
194 * who have FLAG_ACTIVATE_ON_PUSH/RELEASE set properly. 188 * who have FLAG_ACTIVATE_ON_PUSH/RELEASE set properly.
195 * 189 *
196 */ 190 */
197void 191void
198activate_connection (mapstruct *map, long connection, bool state) 192activate_connection (maptile *map, long connection, bool state)
199{ 193{
200 if (INVOKE_MAP (TRIGGER, map, ARG_INT64 (connection), ARG_INT (state))) 194 if (INVOKE_MAP (TRIGGER, map, ARG_INT64 (connection), ARG_INT (state)))
201 return; 195 return;
202 196
203 oblinkpt *obp = get_connection_links (map, connection); 197 oblinkpt *obp = get_connection_links (map, connection);
210 * Updates everything connected with the button op. 204 * Updates everything connected with the button op.
211 * After changing the state of a button, this function must be called 205 * 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 206 * to make sure that all gates and other buttons connected to the
213 * button reacts to the (eventual) change of state. 207 * button reacts to the (eventual) change of state.
214 */ 208 */
215
216void 209void
217update_button (object *op) 210update_button (object *op)
218{ 211{
219 object *ab, *tmp, *head; 212 object *ab, *tmp, *head;
220 int tot, any_down = 0, old_value = op->value; 213 int tot, any_down = 0, old_value = op->value;
224 obp = get_button_links (op); 217 obp = get_button_links (op);
225 /* LOG(llevDebug, "update_button: %s (%d)\n", op->name, op->count); */ 218 /* LOG(llevDebug, "update_button: %s (%d)\n", op->name, op->count); */
226 if (obp) 219 if (obp)
227 for (ol = obp->link; ol; ol = ol->next) 220 for (ol = obp->link; ol; ol = ol->next)
228 { 221 {
229 if (!ol->ob || ol->ob->count != ol->id) 222 if (!ol->ob)
230 { 223 {
231 LOG (llevDebug, "Internal error in update_button (%s).\n", &op->name); 224 LOG (llevDebug, "Internal error in update_button (%s).\n", &op->name);
232 continue; 225 continue;
233 } 226 }
227
234 tmp = ol->ob; 228 tmp = ol->ob;
235 if (tmp->type == BUTTON) 229 if (tmp->type == BUTTON)
236 { 230 {
237 for (ab = tmp->above, tot = 0; ab != NULL; ab = ab->above) 231 for (ab = tmp->above, tot = 0; ab != NULL; ab = ab->above)
238 /* Bug? The pedestal code below looks for the head of 232 /* Bug? The pedestal code below looks for the head of
287/* 281/*
288 * Updates every button on the map (by calling update_button() for them). 282 * Updates every button on the map (by calling update_button() for them).
289 */ 283 */
290 284
291void 285void
292update_buttons (mapstruct *m) 286update_buttons (maptile *m)
293{ 287{
294 objectlink *ol; 288 objectlink *ol;
295 oblinkpt *obp; 289 oblinkpt *obp;
296 290
297 for (obp = m->buttons; obp; obp = obp->next) 291 for (obp = m->buttons; obp; obp = obp->next)
298 for (ol = obp->link; ol; ol = ol->next) 292 for (ol = obp->link; ol; ol = ol->next)
299 { 293 {
300 if (!ol->ob || ol->ob->count != ol->id) 294 if (!ol->ob)
301 { 295 {
302 LOG (llevError, "Internal error in update_button (%s (%dx%d):%d, connected %ld).\n", 296 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); 297 ol->ob ? (const char *) ol->ob->name : "null", ol->ob ? ol->ob->x : -1, ol->ob ? ol->ob->y : -1, obp->value);
304 continue; 298 continue;
305 } 299 }
300
306 if (ol->ob->type == BUTTON || ol->ob->type == PEDESTAL) 301 if (ol->ob->type == BUTTON || ol->ob->type == PEDESTAL)
307 { 302 {
308 update_button (ol->ob); 303 update_button (ol->ob);
309 break; 304 break;
310 } 305 }
357 ARCH_SACRIFICE (altar) == sacrifice->name || 352 ARCH_SACRIFICE (altar) == sacrifice->name ||
358 ARCH_SACRIFICE (altar) == sacrifice->slaying || 353 ARCH_SACRIFICE (altar) == sacrifice->slaying ||
359 (!strcmp (ARCH_SACRIFICE (altar), query_base_name (sacrifice, 0)))) 354 (!strcmp (ARCH_SACRIFICE (altar), query_base_name (sacrifice, 0))))
360 && NROF_SACRIFICE (altar) <= (sacrifice->nrof ? sacrifice->nrof : 1)) 355 && NROF_SACRIFICE (altar) <= (sacrifice->nrof ? sacrifice->nrof : 1))
361 return 1; 356 return 1;
357
362 if (strcmp (ARCH_SACRIFICE (altar), "money") == 0 358 if (strcmp (ARCH_SACRIFICE (altar), "money") == 0
363 && sacrifice->type == MONEY && sacrifice->nrof * sacrifice->value >= NROF_SACRIFICE (altar)) 359 && sacrifice->type == MONEY && sacrifice->nrof * sacrifice->value >= NROF_SACRIFICE (altar))
364 return 1; 360 return 1;
365 } 361 }
362
366 return 0; 363 return 0;
367} 364}
368
369 365
370/* 366/*
371 * operate_altar checks if sacrifice was accepted and removes sacrificed 367 * operate_altar checks if sacrifice was accepted and removes sacrificed
372 * objects. If sacrifice was succeed return 1 else 0. Might be better to 368 * 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, 369 * call check_altar_sacrifice (above) than depend on the return value,
374 * since operate_altar will remove the sacrifice also. 370 * since operate_altar will remove the sacrifice also.
375 * 371 *
376 * If this function returns 1, '*sacrifice' is modified to point to the 372 * 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. 373 * remaining sacrifice, or is set to NULL if the sacrifice was used up.
378 */ 374 */
379
380int 375int
381operate_altar (object *altar, object **sacrifice) 376operate_altar (object *altar, object **sacrifice)
382{ 377{
383
384 if (!altar->map) 378 if (!altar->map)
385 { 379 {
386 LOG (llevError, "BUG: operate_altar(): altar has no map\n"); 380 LOG (llevError, "BUG: operate_altar(): altar has no map\n");
387 return 0; 381 return 0;
388 } 382 }
401 int number = NROF_SACRIFICE (altar) / (*sacrifice)->value; 395 int number = NROF_SACRIFICE (altar) / (*sacrifice)->value;
402 396
403 /* Round up any sacrifices. Altars don't make change either */ 397 /* Round up any sacrifices. Altars don't make change either */
404 if (NROF_SACRIFICE (altar) % (*sacrifice)->value) 398 if (NROF_SACRIFICE (altar) % (*sacrifice)->value)
405 number++; 399 number++;
400
406 *sacrifice = decrease_ob_nr (*sacrifice, number); 401 *sacrifice = decrease_ob_nr (*sacrifice, number);
407 } 402 }
408 else 403 else
409 *sacrifice = decrease_ob_nr (*sacrifice, NROF_SACRIFICE (altar)); 404 *sacrifice = decrease_ob_nr (*sacrifice, NROF_SACRIFICE (altar));
410 405
411 if (altar->msg) 406 if (altar->msg)
412 new_info_map (NDI_BLACK, altar->map, altar->msg); 407 new_info_map (NDI_BLACK, altar->map, altar->msg);
408
413 return 1; 409 return 1;
414} 410}
415 411
416void 412void
417trigger_move (object *op, int state) /* 1 down and 0 up */ 413trigger_move (object *op, int state) /* 1 down and 0 up */
602 return 0; 598 return 0;
603 } 599 }
604} 600}
605 601
606void 602void
607add_button_link (object *button, mapstruct *map, int connected) 603add_button_link (object *button, maptile *map, int connected)
608{ 604{
609 oblinkpt *obp; 605 oblinkpt *obp;
610 objectlink *ol = get_objectlink (); 606 objectlink *ol = get_objectlink ();
611 607
612 if (!map) 608 if (!map)
613 { 609 {
614 LOG (llevError, "Tried to add button-link without map.\n"); 610 LOG (llevError, "Tried to add button-link without map.\n");
615 return; 611 return;
616 } 612 }
617 if (!editor) 613
618 button->path_attuned = connected; /* peterm: I need this so I can rebuild 614 button->path_attuned = connected; /* peterm: I need this so I can rebuild
619 a connected map from a template map. */ 615 a connected map from a template map. */
620
621/* LOG(llevDebug,"adding button %s (%d)\n", button->name, connected);*/
622 616
623 SET_FLAG (button, FLAG_IS_LINKED); 617 SET_FLAG (button, FLAG_IS_LINKED);
624 618
625 ol->ob = button; 619 ol->ob = button;
626 ol->id = button->count;
627 620
628 for (obp = map->buttons; obp && obp->value != connected; obp = obp->next); 621 for (obp = map->buttons; obp && obp->value != connected; obp = obp->next)
622 ;
629 623
630 if (obp) 624 if (obp)
631 { 625 {
632 ol->next = obp->link; 626 ol->next = obp->link;
633 obp->link = ol; 627 obp->link = ol;
657 if (op->map == NULL) 651 if (op->map == NULL)
658 { 652 {
659 LOG (llevError, "remove_button_link() in object without map.\n"); 653 LOG (llevError, "remove_button_link() in object without map.\n");
660 return; 654 return;
661 } 655 }
656
662 if (!QUERY_FLAG (op, FLAG_IS_LINKED)) 657 if (!QUERY_FLAG (op, FLAG_IS_LINKED))
663 { 658 {
664 LOG (llevError, "remove_button_linked() in unlinked object.\n"); 659 LOG (llevError, "remove_button_linked() in unlinked object.\n");
665 return; 660 return;
666 } 661 }
662
667 for (obp = op->map->buttons; obp; obp = obp->next) 663 for (obp = op->map->buttons; obp; obp = obp->next)
668 for (olp = &obp->link; (ol = *olp); olp = &ol->next) 664 for (olp = &obp->link; (ol = *olp); olp = &ol->next)
669 if (ol->ob == op) 665 if (ol->ob == op)
670 { 666 {
671 667
672/* LOG(llevDebug, "Removed link %d in button %s and map %s.\n", 668/* LOG(llevDebug, "Removed link %d in button %s and map %s.\n",
673 obp->value, op->name, op->map->path); 669 obp->value, op->name, op->map->path);
674*/ 670*/
675 *olp = ol->next; 671 *olp = ol->next;
676 free (ol); 672 delete ol;
677 return; 673 return;
678 } 674 }
675
679 LOG (llevError, "remove_button_linked(): couldn't find object.\n"); 676 LOG (llevError, "remove_button_linked(): couldn't find object.\n");
680 CLEAR_FLAG (op, FLAG_IS_LINKED); 677 CLEAR_FLAG (op, FLAG_IS_LINKED);
681} 678}
682 679
683/* 680/*
684 * Gets the objectlink for this connection from the map. 681 * Gets the objectlink for this connection from the map.
685 */ 682 */
686oblinkpt * 683oblinkpt *
687get_connection_links (mapstruct *map, long connection) 684get_connection_links (maptile *map, long connection)
688{ 685{
689 for (oblinkpt * obp = map->buttons; obp; obp = obp->next) 686 for (oblinkpt * obp = map->buttons; obp; obp = obp->next)
690 if (obp->value == connection) 687 if (obp->value == connection)
691 return obp; 688 return obp;
689
692 return 0; 690 return 0;
693} 691}
694 692
695/* 693/*
696 * Return the first objectlink in the objects linked to this one 694 * Return the first objectlink in the objects linked to this one
702 oblinkpt *obp; 700 oblinkpt *obp;
703 objectlink *ol; 701 objectlink *ol;
704 702
705 if (!button->map) 703 if (!button->map)
706 return NULL; 704 return NULL;
705
707 for (obp = button->map->buttons; obp; obp = obp->next) 706 for (obp = button->map->buttons; obp; obp = obp->next)
708 for (ol = obp->link; ol; ol = ol->next) 707 for (ol = obp->link; ol; ol = ol->next)
709 if (ol->ob == button && ol->id == button->count) 708 if (ol->ob == button)
710 return obp; 709 return obp;
710
711 return NULL; 711 return NULL;
712} 712}
713 713
714/* 714/*
715 * Made as a separate function to increase efficiency 715 * Made as a separate function to increase efficiency
723 723
724 if (!button->map) 724 if (!button->map)
725 return 0; 725 return 0;
726 for (obp = button->map->buttons; obp; obp = obp->next) 726 for (obp = button->map->buttons; obp; obp = obp->next)
727 for (ol = obp->link; ol; ol = ol->next) 727 for (ol = obp->link; ol; ol = ol->next)
728 if (ol->ob == button && ol->id == button->count) 728 if (ol->ob == button)
729 return obp->value; 729 return obp->value;
730 return 0; 730 return 0;
731} 731}
732 732
733/* This routine makes monsters who are 733/* This routine makes monsters who are
758 if (!tmp || tmp->type == PLAYER) 758 if (!tmp || tmp->type == PLAYER)
759 return; 759 return;
760 760
761 switch (op->last_sp) 761 switch (op->last_sp)
762 { 762 {
763 case 0: /* furious--make all monsters mad */ 763 case 0: /* furious--make all monsters mad */
764 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE)) 764 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE))
765 CLEAR_FLAG (tmp, FLAG_UNAGGRESSIVE); 765 CLEAR_FLAG (tmp, FLAG_UNAGGRESSIVE);
766 if (QUERY_FLAG (tmp, FLAG_FRIENDLY)) 766 if (QUERY_FLAG (tmp, FLAG_FRIENDLY))
767 { 767 {
768 CLEAR_FLAG (tmp, FLAG_FRIENDLY); 768 CLEAR_FLAG (tmp, FLAG_FRIENDLY);
769 remove_friendly_object (tmp); 769 remove_friendly_object (tmp);
770 tmp->attack_movement = 0; 770 tmp->attack_movement = 0;
771 /* lots of checks here, but want to make sure we don't 771 /* lots of checks here, but want to make sure we don't
772 * dereference a null value 772 * dereference a null value
773 */ 773 */
774 if (tmp->type == GOLEM && tmp->owner && tmp->owner->type == PLAYER && tmp->owner->contr->ranges[range_golem] == tmp) 774 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; 775 tmp->owner->contr->ranges[range_golem] = 0;
777 tmp->owner->contr->golem_count = 0; 776
778 }
779 tmp->owner = 0; 777 tmp->owner = 0;
780 } 778 }
779 break;
780 case 1: /* angry -- get neutral monsters mad */
781 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (tmp, FLAG_FRIENDLY))
782 CLEAR_FLAG (tmp, FLAG_UNAGGRESSIVE);
783 break;
784 case 2: /* calm -- pacify unfriendly monsters */
785 if (!QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE))
786 SET_FLAG (tmp, FLAG_UNAGGRESSIVE);
787 break;
788 case 3: /* make all monsters fall asleep */
789 if (!QUERY_FLAG (tmp, FLAG_SLEEP))
790 SET_FLAG (tmp, FLAG_SLEEP);
791 break;
792 case 4: /* charm all monsters */
793 if (op == source)
794 break; /* only if 'connected' */
795
796 for (tmp2 = GET_MAP_OB (source->map, source->x, source->y); /* finding an owner */
797 tmp2->type != PLAYER; tmp2 = tmp2->above)
798 if (tmp2->above == NULL)
799 break;
800
801 if (tmp2->type != PLAYER)
781 break; 802 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 803
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); 804 tmp->set_owner (tmp2);
806 SET_FLAG (tmp, FLAG_MONSTER); 805 SET_FLAG (tmp, FLAG_MONSTER);
806
807 tmp->stats.exp = 0; 807 tmp->stats.exp = 0;
808 SET_FLAG (tmp, FLAG_FRIENDLY); 808 SET_FLAG (tmp, FLAG_FRIENDLY);
809
809 add_friendly_object (tmp); 810 add_friendly_object (tmp);
810 tmp->attack_movement = PETMOVE; 811 tmp->attack_movement = PETMOVE;
811 break; 812 break;
812 813
813 default: 814 default:
814 break; 815 break;
815
816 } 816 }
817} 817}
818 818
819/* this function returns the object it matches, or NULL if non. 819/* this function returns the object it matches, or NULL if non.
820 * It will descend through containers to find the object. 820 * It will descend through containers to find the object.
821 * slaying = match object slaying flag 821 * slaying = match object slaying flag
822 * race = match object archetype name flag 822 * race = match object archetype name flag
823 * hp = match object type (excpt type '0'== PLAYER) 823 * hp = match object type (excpt type '0'== PLAYER)
824 */ 824 */
825
826object * 825object *
827check_inv_recursive (object *op, const object *trig) 826check_inv_recursive (object *op, const object *trig)
828{ 827{
829 object *tmp, *ret = NULL; 828 object *tmp, *ret = NULL;
830 829
831 /* First check the object itself. */ 830 /* First check the object itself. */
832 if ((trig->stats.hp && (op->type == trig->stats.hp)) 831 if ((trig->stats.hp && (op->type == trig->stats.hp))
833 || (trig->slaying && (op->slaying == trig->slaying)) || (trig->race && (op->arch->name == trig->race))) 832 || (trig->slaying && (op->slaying == trig->slaying))
833 || (trig->race && (op->arch->name == trig->race)))
834 return op; 834 return op;
835 835
836 for (tmp = op->inv; tmp; tmp = tmp->below) 836 for (tmp = op->inv; tmp; tmp = tmp->below)
837 { 837 {
838 if (tmp->inv) 838 if (tmp->inv)
840 ret = check_inv_recursive (tmp, trig); 840 ret = check_inv_recursive (tmp, trig);
841 if (ret) 841 if (ret)
842 return ret; 842 return ret;
843 } 843 }
844 else if ((trig->stats.hp && (tmp->type == trig->stats.hp)) 844 else if ((trig->stats.hp && (tmp->type == trig->stats.hp))
845 || (trig->slaying && (tmp->slaying == trig->slaying)) || (trig->race && (tmp->arch->name == trig->race))) 845 || (trig->slaying && (tmp->slaying == trig->slaying))
846 || (trig->race && (tmp->arch->name == trig->race)))
846 return tmp; 847 return tmp;
847 } 848 }
848 return NULL; 849 return NULL;
849} 850}
850 851
853 * the square will activate connected items. 854 * the square will activate connected items.
854 * Monsters can't trigger this square (for now) 855 * Monsters can't trigger this square (for now)
855 * Values are: last_sp = 1/0 obj/no obj triggers 856 * Values are: last_sp = 1/0 obj/no obj triggers
856 * last_heal = 1/0 remove/dont remove obj if triggered 857 * last_heal = 1/0 remove/dont remove obj if triggered
857 * -b.t. (thomas@nomad.astro.psu.edu 858 * -b.t. (thomas@nomad.astro.psu.edu
858 */ 859 *
859 860 * Tue Dec 19 15:34:00 CET 2006 elmex: changed the function to ignore op
861 * because the check-inventory semantic essentially only applies when
862 * something is above the inventory checker.
863 * The semantic prior this change was: trigger if something has moved on or off
864 * and has a matching item. Imagine what happens if someone steps on the inventory
865 * checker with a matching item, has it, activates the connection, throws the item
866 * away, and then leaves the inventory checker. That would've caused an always-enabled
867 * state in the inventory checker. This won't happen anymore now.
868 *
869 */
860void 870void
861check_inv (object *op, object *trig) 871check_inv (object *op, object *trig)
862{ 872{
863 object *match; 873 trig->value = 0; // deactivate if none of the following conditions apply
864 874
865 if (op->type != PLAYER) 875 if (object *pl = trig->ms ().player ())
866 return; 876 {
867 match = check_inv_recursive (op, trig); 877 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 878
878 879 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 { 880 {
896 if (ol->id != ol->ob->count) 881 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); 882 decrease_ob (match);
883
884 trig->value = 1;
898 } 885 }
886 else if (!match && !trig->last_sp) // match == not having
887 trig->value = 1;
899 } 888 }
889
890 push_button (trig);
900} 891}
892

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines