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.21 by root, Sat Dec 30 10:16:10 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
282 update_object (op, UP_OBJ_FACE); 273 update_object (op, UP_OBJ_FACE);
283 push_button (op); /* Make all other buttons the same */ 274 push_button (op); /* Make all other buttons the same */
284 } 275 }
285} 276}
286 277
287/*
288 * Updates every button on the map (by calling update_button() for them).
289 */
290
291void
292update_buttons (mapstruct *m)
293{
294 objectlink *ol;
295 oblinkpt *obp;
296
297 for (obp = m->buttons; obp; obp = obp->next)
298 for (ol = obp->link; ol; ol = ol->next)
299 {
300 if (!ol->ob || ol->ob->count != ol->id)
301 {
302 LOG (llevError, "Internal error in update_button (%s (%dx%d):%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);
304 continue;
305 }
306 if (ol->ob->type == BUTTON || ol->ob->type == PEDESTAL)
307 {
308 update_button (ol->ob);
309 break;
310 }
311 }
312}
313
314void 278void
315use_trigger (object *op) 279use_trigger (object *op)
316{ 280{
317
318 /* Toggle value */ 281 /* Toggle value */
319 op->value = !op->value; 282 op->value = !op->value;
320 push_button (op); 283 push_button (op);
321} 284}
322 285
323/* 286/*
324 * Note: animate_object should be used instead of this, 287 * Note: animate_object should be used instead of this,
325 * but it can't handle animations in the 8 directions 288 * but it can't handle animations in the 8 directions
326 */ 289 */
327
328void 290void
329animate_turning (object *op) /* only one part objects */ 291animate_turning (object *op) /* only one part objects */
330{ 292{
331 if (++op->state >= NUM_ANIMATIONS (op) / 8) 293 if (++op->state >= NUM_ANIMATIONS (op) / 8)
332 op->state = 0; 294 op->state = 0;
357 ARCH_SACRIFICE (altar) == sacrifice->name || 319 ARCH_SACRIFICE (altar) == sacrifice->name ||
358 ARCH_SACRIFICE (altar) == sacrifice->slaying || 320 ARCH_SACRIFICE (altar) == sacrifice->slaying ||
359 (!strcmp (ARCH_SACRIFICE (altar), query_base_name (sacrifice, 0)))) 321 (!strcmp (ARCH_SACRIFICE (altar), query_base_name (sacrifice, 0))))
360 && NROF_SACRIFICE (altar) <= (sacrifice->nrof ? sacrifice->nrof : 1)) 322 && NROF_SACRIFICE (altar) <= (sacrifice->nrof ? sacrifice->nrof : 1))
361 return 1; 323 return 1;
324
362 if (strcmp (ARCH_SACRIFICE (altar), "money") == 0 325 if (strcmp (ARCH_SACRIFICE (altar), "money") == 0
363 && sacrifice->type == MONEY && sacrifice->nrof * sacrifice->value >= NROF_SACRIFICE (altar)) 326 && sacrifice->type == MONEY && sacrifice->nrof * sacrifice->value >= NROF_SACRIFICE (altar))
364 return 1; 327 return 1;
365 } 328 }
329
366 return 0; 330 return 0;
367} 331}
368
369 332
370/* 333/*
371 * operate_altar checks if sacrifice was accepted and removes sacrificed 334 * operate_altar checks if sacrifice was accepted and removes sacrificed
372 * objects. If sacrifice was succeed return 1 else 0. Might be better to 335 * 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, 336 * call check_altar_sacrifice (above) than depend on the return value,
374 * since operate_altar will remove the sacrifice also. 337 * since operate_altar will remove the sacrifice also.
375 * 338 *
376 * If this function returns 1, '*sacrifice' is modified to point to the 339 * 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. 340 * remaining sacrifice, or is set to NULL if the sacrifice was used up.
378 */ 341 */
379
380int 342int
381operate_altar (object *altar, object **sacrifice) 343operate_altar (object *altar, object **sacrifice)
382{ 344{
383
384 if (!altar->map) 345 if (!altar->map)
385 { 346 {
386 LOG (llevError, "BUG: operate_altar(): altar has no map\n"); 347 LOG (llevError, "BUG: operate_altar(): altar has no map\n");
387 return 0; 348 return 0;
388 } 349 }
401 int number = NROF_SACRIFICE (altar) / (*sacrifice)->value; 362 int number = NROF_SACRIFICE (altar) / (*sacrifice)->value;
402 363
403 /* Round up any sacrifices. Altars don't make change either */ 364 /* Round up any sacrifices. Altars don't make change either */
404 if (NROF_SACRIFICE (altar) % (*sacrifice)->value) 365 if (NROF_SACRIFICE (altar) % (*sacrifice)->value)
405 number++; 366 number++;
367
406 *sacrifice = decrease_ob_nr (*sacrifice, number); 368 *sacrifice = decrease_ob_nr (*sacrifice, number);
407 } 369 }
408 else 370 else
409 *sacrifice = decrease_ob_nr (*sacrifice, NROF_SACRIFICE (altar)); 371 *sacrifice = decrease_ob_nr (*sacrifice, NROF_SACRIFICE (altar));
410 372
411 if (altar->msg) 373 if (altar->msg)
412 new_info_map (NDI_BLACK, altar->map, altar->msg); 374 new_info_map (NDI_BLACK, altar->map, altar->msg);
375
413 return 1; 376 return 1;
414} 377}
415 378
416void 379void
417trigger_move (object *op, int state) /* 1 down and 0 up */ 380trigger_move (object *op, int state) /* 1 down and 0 up */
418{ 381{
419 op->stats.wc = state; 382 op->stats.wc = state;
420 if (state) 383 if (state)
421 { 384 {
422 use_trigger (op); 385 use_trigger (op);
423 if (op->stats.exp > 0) /* check sanity */ 386 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; 387 op->speed_left = -1;
429 } 388 }
430 else 389 else
431 { 390 {
432 use_trigger (op); 391 use_trigger (op);
433 op->speed = 0; 392 op->set_speed (0);
434 update_ob_speed (op);
435 } 393 }
436} 394}
437 395
438 396
439/* 397/*
574 trigger_move (op, 0); 532 trigger_move (op, 0);
575 else 533 else
576 { 534 {
577 op->stats.wc = 0; 535 op->stats.wc = 0;
578 op->value = !op->value; 536 op->value = !op->value;
579 op->speed = 0; 537 op->set_speed (0);
580 update_ob_speed (op);
581 } 538 }
582 } 539 }
583 return 0; 540 return 0;
584 541
585 case TRIGGER: 542 case TRIGGER:
586 if (cause) 543 if (cause)
587 { 544 {
588 if (in_movement) 545 if (in_movement)
589 return 0; 546 return 0;
547
590 push = 1; 548 push = 1;
591 } 549 }
550
592 if (NUM_ANIMATIONS (op) > 1) 551 if (NUM_ANIMATIONS (op) > 1)
593 { 552 {
594 SET_ANIMATION (op, push); 553 SET_ANIMATION (op, push);
595 update_object (op, UP_OBJ_FACE); 554 update_object (op, UP_OBJ_FACE);
596 } 555 }
556
597 trigger_move (op, push); 557 trigger_move (op, push);
598 return 1; 558 return 1;
599 559
600 default: 560 default:
601 LOG (llevDebug, "Unknown trigger type: %s (%d)\n", &op->name, op->type); 561 LOG (llevDebug, "Unknown trigger type: %s (%d)\n", &op->name, op->type);
602 return 0; 562 return 0;
603 } 563 }
604} 564}
605 565
606void 566void
607add_button_link (object *button, mapstruct *map, int connected) 567add_button_link (object *button, maptile *map, int connected)
608{ 568{
609 oblinkpt *obp; 569 oblinkpt *obp;
610 objectlink *ol = get_objectlink (); 570 objectlink *ol = get_objectlink ();
611 571
612 if (!map) 572 if (!map)
613 { 573 {
614 LOG (llevError, "Tried to add button-link without map.\n"); 574 LOG (llevError, "Tried to add button-link without map.\n");
615 return; 575 return;
616 } 576 }
617 if (!editor) 577
618 button->path_attuned = connected; /* peterm: I need this so I can rebuild 578 button->path_attuned = connected; /* peterm: I need this so I can rebuild
619 a connected map from a template map. */ 579 a connected map from a template map. */
620
621/* LOG(llevDebug,"adding button %s (%d)\n", button->name, connected);*/
622 580
623 SET_FLAG (button, FLAG_IS_LINKED); 581 SET_FLAG (button, FLAG_IS_LINKED);
624 582
625 ol->ob = button; 583 ol->ob = button;
626 ol->id = button->count;
627 584
628 for (obp = map->buttons; obp && obp->value != connected; obp = obp->next); 585 for (obp = map->buttons; obp && obp->value != connected; obp = obp->next)
586 ;
629 587
630 if (obp) 588 if (obp)
631 { 589 {
632 ol->next = obp->link; 590 ol->next = obp->link;
633 obp->link = ol; 591 obp->link = ol;
657 if (op->map == NULL) 615 if (op->map == NULL)
658 { 616 {
659 LOG (llevError, "remove_button_link() in object without map.\n"); 617 LOG (llevError, "remove_button_link() in object without map.\n");
660 return; 618 return;
661 } 619 }
620
662 if (!QUERY_FLAG (op, FLAG_IS_LINKED)) 621 if (!QUERY_FLAG (op, FLAG_IS_LINKED))
663 { 622 {
664 LOG (llevError, "remove_button_linked() in unlinked object.\n"); 623 LOG (llevError, "remove_button_linked() in unlinked object.\n");
665 return; 624 return;
666 } 625 }
626
667 for (obp = op->map->buttons; obp; obp = obp->next) 627 for (obp = op->map->buttons; obp; obp = obp->next)
668 for (olp = &obp->link; (ol = *olp); olp = &ol->next) 628 for (olp = &obp->link; (ol = *olp); olp = &ol->next)
669 if (ol->ob == op) 629 if (ol->ob == op)
670 { 630 {
671 631
672/* LOG(llevDebug, "Removed link %d in button %s and map %s.\n", 632/* LOG(llevDebug, "Removed link %d in button %s and map %s.\n",
673 obp->value, op->name, op->map->path); 633 obp->value, op->name, op->map->path);
674*/ 634*/
675 *olp = ol->next; 635 *olp = ol->next;
676 free (ol); 636 delete ol;
677 return; 637 return;
678 } 638 }
639
679 LOG (llevError, "remove_button_linked(): couldn't find object.\n"); 640 LOG (llevError, "remove_button_linked(): couldn't find object.\n");
680 CLEAR_FLAG (op, FLAG_IS_LINKED); 641 CLEAR_FLAG (op, FLAG_IS_LINKED);
681} 642}
682 643
683/* 644/*
684 * Gets the objectlink for this connection from the map. 645 * Gets the objectlink for this connection from the map.
685 */ 646 */
686oblinkpt * 647oblinkpt *
687get_connection_links (mapstruct *map, long connection) 648get_connection_links (maptile *map, long connection)
688{ 649{
689 for (oblinkpt * obp = map->buttons; obp; obp = obp->next) 650 for (oblinkpt * obp = map->buttons; obp; obp = obp->next)
690 if (obp->value == connection) 651 if (obp->value == connection)
691 return obp; 652 return obp;
653
692 return 0; 654 return 0;
693} 655}
694 656
695/* 657/*
696 * Return the first objectlink in the objects linked to this one 658 * Return the first objectlink in the objects linked to this one
702 oblinkpt *obp; 664 oblinkpt *obp;
703 objectlink *ol; 665 objectlink *ol;
704 666
705 if (!button->map) 667 if (!button->map)
706 return NULL; 668 return NULL;
669
707 for (obp = button->map->buttons; obp; obp = obp->next) 670 for (obp = button->map->buttons; obp; obp = obp->next)
708 for (ol = obp->link; ol; ol = ol->next) 671 for (ol = obp->link; ol; ol = ol->next)
709 if (ol->ob == button && ol->id == button->count) 672 if (ol->ob == button)
710 return obp; 673 return obp;
674
711 return NULL; 675 return NULL;
712} 676}
713 677
714/* 678/*
715 * Made as a separate function to increase efficiency 679 * Made as a separate function to increase efficiency
723 687
724 if (!button->map) 688 if (!button->map)
725 return 0; 689 return 0;
726 for (obp = button->map->buttons; obp; obp = obp->next) 690 for (obp = button->map->buttons; obp; obp = obp->next)
727 for (ol = obp->link; ol; ol = ol->next) 691 for (ol = obp->link; ol; ol = ol->next)
728 if (ol->ob == button && ol->id == button->count) 692 if (ol->ob == button)
729 return obp->value; 693 return obp->value;
730 return 0; 694 return 0;
731} 695}
732 696
733/* This routine makes monsters who are 697/* This routine makes monsters who are
758 if (!tmp || tmp->type == PLAYER) 722 if (!tmp || tmp->type == PLAYER)
759 return; 723 return;
760 724
761 switch (op->last_sp) 725 switch (op->last_sp)
762 { 726 {
763 case 0: /* furious--make all monsters mad */ 727 case 0: /* furious--make all monsters mad */
764 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE)) 728 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE))
765 CLEAR_FLAG (tmp, FLAG_UNAGGRESSIVE); 729 CLEAR_FLAG (tmp, FLAG_UNAGGRESSIVE);
766 if (QUERY_FLAG (tmp, FLAG_FRIENDLY)) 730 if (QUERY_FLAG (tmp, FLAG_FRIENDLY))
767 { 731 {
768 CLEAR_FLAG (tmp, FLAG_FRIENDLY); 732 CLEAR_FLAG (tmp, FLAG_FRIENDLY);
769 remove_friendly_object (tmp); 733 remove_friendly_object (tmp);
770 tmp->attack_movement = 0; 734 tmp->attack_movement = 0;
771 /* lots of checks here, but want to make sure we don't 735 /* lots of checks here, but want to make sure we don't
772 * dereference a null value 736 * dereference a null value
773 */ 737 */
774 if (tmp->type == GOLEM && tmp->owner && tmp->owner->type == PLAYER && tmp->owner->contr->ranges[range_golem] == tmp) 738 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; 739 tmp->owner->contr->ranges[range_golem] = 0;
777 tmp->owner->contr->golem_count = 0; 740
778 }
779 tmp->owner = 0; 741 tmp->owner = 0;
780 } 742 }
743 break;
744 case 1: /* angry -- get neutral monsters mad */
745 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (tmp, FLAG_FRIENDLY))
746 CLEAR_FLAG (tmp, FLAG_UNAGGRESSIVE);
747 break;
748 case 2: /* calm -- pacify unfriendly monsters */
749 if (!QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE))
750 SET_FLAG (tmp, FLAG_UNAGGRESSIVE);
751 break;
752 case 3: /* make all monsters fall asleep */
753 if (!QUERY_FLAG (tmp, FLAG_SLEEP))
754 SET_FLAG (tmp, FLAG_SLEEP);
755 break;
756 case 4: /* charm all monsters */
757 if (op == source)
758 break; /* only if 'connected' */
759
760 for (tmp2 = GET_MAP_OB (source->map, source->x, source->y); /* finding an owner */
761 tmp2->type != PLAYER; tmp2 = tmp2->above)
762 if (tmp2->above == NULL)
763 break;
764
765 if (tmp2->type != PLAYER)
781 break; 766 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 767
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); 768 tmp->set_owner (tmp2);
806 SET_FLAG (tmp, FLAG_MONSTER); 769 SET_FLAG (tmp, FLAG_MONSTER);
770
807 tmp->stats.exp = 0; 771 tmp->stats.exp = 0;
808 SET_FLAG (tmp, FLAG_FRIENDLY); 772 SET_FLAG (tmp, FLAG_FRIENDLY);
773
809 add_friendly_object (tmp); 774 add_friendly_object (tmp);
810 tmp->attack_movement = PETMOVE; 775 tmp->attack_movement = PETMOVE;
811 break; 776 break;
812 777
813 default: 778 default:
814 break; 779 break;
815
816 } 780 }
817} 781}
818 782
819/* this function returns the object it matches, or NULL if non. 783/* this function returns the object it matches, or NULL if non.
820 * It will descend through containers to find the object. 784 * It will descend through containers to find the object.
821 * slaying = match object slaying flag 785 * slaying = match object slaying flag
822 * race = match object archetype name flag 786 * race = match object archetype name flag
823 * hp = match object type (excpt type '0'== PLAYER) 787 * hp = match object type (excpt type '0'== PLAYER)
824 */ 788 */
825
826object * 789object *
827check_inv_recursive (object *op, const object *trig) 790check_inv_recursive (object *op, const object *trig)
828{ 791{
829 object *tmp, *ret = NULL; 792 object *tmp, *ret = NULL;
830 793
831 /* First check the object itself. */ 794 /* First check the object itself. */
832 if ((trig->stats.hp && (op->type == trig->stats.hp)) 795 if ((trig->stats.hp && (op->type == trig->stats.hp))
833 || (trig->slaying && (op->slaying == trig->slaying)) || (trig->race && (op->arch->name == trig->race))) 796 || (trig->slaying && (op->slaying == trig->slaying))
797 || (trig->race && (op->arch->name == trig->race)))
834 return op; 798 return op;
835 799
836 for (tmp = op->inv; tmp; tmp = tmp->below) 800 for (tmp = op->inv; tmp; tmp = tmp->below)
837 { 801 {
838 if (tmp->inv) 802 if (tmp->inv)
840 ret = check_inv_recursive (tmp, trig); 804 ret = check_inv_recursive (tmp, trig);
841 if (ret) 805 if (ret)
842 return ret; 806 return ret;
843 } 807 }
844 else if ((trig->stats.hp && (tmp->type == trig->stats.hp)) 808 else if ((trig->stats.hp && (tmp->type == trig->stats.hp))
845 || (trig->slaying && (tmp->slaying == trig->slaying)) || (trig->race && (tmp->arch->name == trig->race))) 809 || (trig->slaying && (tmp->slaying == trig->slaying))
810 || (trig->race && (tmp->arch->name == trig->race)))
846 return tmp; 811 return tmp;
847 } 812 }
848 return NULL; 813 return NULL;
849} 814}
850 815
853 * the square will activate connected items. 818 * the square will activate connected items.
854 * Monsters can't trigger this square (for now) 819 * Monsters can't trigger this square (for now)
855 * Values are: last_sp = 1/0 obj/no obj triggers 820 * Values are: last_sp = 1/0 obj/no obj triggers
856 * last_heal = 1/0 remove/dont remove obj if triggered 821 * last_heal = 1/0 remove/dont remove obj if triggered
857 * -b.t. (thomas@nomad.astro.psu.edu 822 * -b.t. (thomas@nomad.astro.psu.edu
858 */ 823 *
859 824 * Tue Dec 19 15:34:00 CET 2006 elmex: changed the function to ignore op
825 * because the check-inventory semantic essentially only applies when
826 * something is above the inventory checker.
827 * The semantic prior this change was: trigger if something has moved on or off
828 * and has a matching item. Imagine what happens if someone steps on the inventory
829 * checker with a matching item, has it, activates the connection, throws the item
830 * away, and then leaves the inventory checker. That would've caused an always-enabled
831 * state in the inventory checker. This won't happen anymore now.
832 *
833 */
860void 834void
861check_inv (object *op, object *trig) 835check_inv (object *op, object *trig)
862{ 836{
863 object *match; 837 trig->value = 0; // deactivate if none of the following conditions apply
864 838
865 if (op->type != PLAYER) 839 if (object *pl = trig->ms ().player ())
866 return; 840 {
867 match = check_inv_recursive (op, trig); 841 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 842
878 843 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 { 844 {
896 if (ol->id != ol->ob->count) 845 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); 846 decrease_ob (match);
847
848 trig->value = 1;
898 } 849 }
850 else if (!match && !trig->last_sp) // match == not having
851 trig->value = 1;
899 } 852 }
853
854 push_button (trig);
900} 855}
856

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines