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.8 by root, Mon Sep 11 20:28:37 2006 UTC vs.
Revision 1.24 by elmex, Tue Jan 9 16:38:23 2007 UTC

1
2/*
3 * static char *rcsid_button_c =
4 * "$Id: button.C,v 1.8 2006/09/11 20:28:37 root Exp $";
5 */
6
7/* 1/*
8 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
9 3
4 Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
10 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 5 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
11 Copyright (C) 1992 Frank Tore Johansen 6 Copyright (C) 1992 Frank Tore Johansen
12 7
13 This program is free software; you can redistribute it and/or modify 8 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by 9 it under the terms of the GNU General Public License as published by
22 17
23 You should have received a copy of the GNU General Public License 18 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software 19 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 21
27 The authors can be reached via e-mail at crossfire-devel@real-time.com 22 The authors can be reached via e-mail at <crossfire@schmorp.de>
28*/ 23*/
29 24
30#include <global.h> 25#include <global.h>
31#include <funcpoint.h> 26#include <funcpoint.h>
32 27
41 * The source argument can be 0 or the source object for this activation. 36 * The source argument can be 0 or the source object for this activation.
42 */ 37 */
43void 38void
44activate_connection_link (objectlink * ol, bool state, object *source = 0) 39activate_connection_link (objectlink * ol, bool state, object *source = 0)
45{ 40{
46 object *tmp = 0;
47
48 for (; ol; ol = ol->next) 41 for (; ol; ol = ol->next)
49 { 42 {
50 if (!ol->ob || ol->ob->count != ol->id) 43 if (!ol->ob)
51 { 44 {
52 LOG (llevError, "Internal error in activate_connection_link (%ld).\n", ol->id); 45 LOG (llevError, "Internal error in activate_connection_link.\n");
53 continue; 46 continue;
54 } 47 }
48
55 /* a button link object can become freed when the map is saving. As 49 /* 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 50 * 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 51 * 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 52 * 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 53 * 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. 54 * re-loaded. As such, just exit this function if that is the case.
61 */ 55 */
62 56
63 if (QUERY_FLAG (ol->ob, FLAG_FREED)) 57 if (QUERY_FLAG (ol->ob, FLAG_FREED))
64 return; 58 return;
59
65 tmp = ol->ob; 60 object *tmp = ol->ob;
66 61
67 /* if the criteria isn't appropriate, don't do anything */ 62 /* if the criteria isn't appropriate, don't do anything */
68 if (state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_PUSH)) 63 if (state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_PUSH))
69 continue; 64 continue;
70 if (!state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_RELEASE)) 65 if (!state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_RELEASE))
71 continue; 66 continue;
72 67
73 switch (tmp->type) 68 switch (tmp->type)
74 { 69 {
75 case GATE: 70 case GATE:
76 case HOLE: 71 case HOLE:
77 tmp->value = tmp->stats.maxsp ? !state : state; 72 tmp->value = tmp->stats.maxsp ? !state : state;
78 tmp->speed = 0.5; 73 tmp->set_speed (0.5);
79 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->set_speed (tmp->arch->clone.speed);
115 update_ob_speed (tmp); /* original values */
116 tmp->value = tmp->arch->clone.value; 109 tmp->value = tmp->arch->clone.value;
117 tmp->stats.sp = 1; 110 tmp->stats.sp = 1;
118 tmp->stats.hp = tmp->stats.maxhp; 111 tmp->stats.hp = tmp->stats.maxhp;
119 /* Handle multipart gates. We copy the value for the other parts 112 /* Handle multipart gates. We copy the value for the other parts
120 * from the head - this ensures that the data will consistent 113 * from the head - this ensures that the data will consistent
121 */ 114 */
122 for (tmp = tmp->more; tmp != NULL; tmp = tmp->more) 115 for (tmp = tmp->more; tmp; tmp = tmp->more)
123 { 116 {
124 tmp->speed = tmp->head->speed;
125 tmp->value = tmp->head->value; 117 tmp->value = tmp->head->value;
126 tmp->stats.sp = tmp->head->stats.sp; 118 tmp->stats.sp = tmp->head->stats.sp;
127 tmp->stats.hp = tmp->head->stats.hp; 119 tmp->stats.hp = tmp->head->stats.hp;
128 update_ob_speed (tmp); 120 tmp->set_speed (tmp->head->speed);
129 } 121 }
130 break; 122 break;
131 123
132 case DIRECTOR: 124 case DIRECTOR:
133 case FIREWALL: 125 case FIREWALL:
134 if (!QUERY_FLAG (tmp, FLAG_ANIMATE) && tmp->type == FIREWALL) 126 if (!QUERY_FLAG (tmp, FLAG_ANIMATE) && tmp->type == FIREWALL)
135 move_firewall (tmp); 127 move_firewall (tmp);
136 else 128 else
137 { 129 {
138 if ((tmp->stats.sp += tmp->stats.maxsp) > 8) /* next direction */ 130 if ((tmp->stats.sp += tmp->stats.maxsp) > 8) /* next direction */
139 tmp->stats.sp = ((tmp->stats.sp - 1) % 8) + 1; 131 tmp->stats.sp = ((tmp->stats.sp - 1) % 8) + 1;
140 animate_turning (tmp); 132 animate_turning (tmp);
141 } 133 }
142 break; 134 break;
143 135
144 case TELEPORTER: 136 case TELEPORTER:
145 move_teleporter (tmp); 137 move_teleporter (tmp);
146 break; 138 break;
147 139
148 case CREATOR: 140 case CREATOR:
149 move_creator (tmp); 141 move_creator (tmp);
150 break; 142 break;
151 143
152 case TRIGGER_MARKER: 144 case TRIGGER_MARKER:
153 move_marker (tmp); 145 move_marker (tmp);
154 break; 146 break;
155 147
156 case DUPLICATOR: 148 case DUPLICATOR:
157 move_duplicator (tmp); 149 move_duplicator (tmp);
158 break; 150 break;
159 } 151 }
160 } 152 }
161} 153}
162 154
163/* 155/*
193 * the connection was 'state' or 'released'. So that you can activate objects 185 * the connection was 'state' or 'released'. So that you can activate objects
194 * who have FLAG_ACTIVATE_ON_PUSH/RELEASE set properly. 186 * who have FLAG_ACTIVATE_ON_PUSH/RELEASE set properly.
195 * 187 *
196 */ 188 */
197void 189void
198activate_connection (mapstruct *map, long connection, bool state) 190activate_connection (maptile *map, long connection, bool state)
199{ 191{
200 if (INVOKE_MAP (TRIGGER, map, ARG_INT64 (connection), ARG_INT (state))) 192 if (INVOKE_MAP (TRIGGER, map, ARG_INT64 (connection), ARG_INT (state)))
201 return; 193 return;
202 194
203 oblinkpt *obp = get_connection_links (map, connection); 195 oblinkpt *obp = get_connection_links (map, connection);
210 * Updates everything connected with the button op. 202 * Updates everything connected with the button op.
211 * After changing the state of a button, this function must be called 203 * 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 204 * to make sure that all gates and other buttons connected to the
213 * button reacts to the (eventual) change of state. 205 * button reacts to the (eventual) change of state.
214 */ 206 */
215
216void 207void
217update_button (object *op) 208update_button (object *op)
218{ 209{
219 object *ab, *tmp, *head; 210 object *ab, *tmp, *head;
220 int tot, any_down = 0, old_value = op->value; 211 int tot, any_down = 0, old_value = op->value;
224 obp = get_button_links (op); 215 obp = get_button_links (op);
225 /* LOG(llevDebug, "update_button: %s (%d)\n", op->name, op->count); */ 216 /* LOG(llevDebug, "update_button: %s (%d)\n", op->name, op->count); */
226 if (obp) 217 if (obp)
227 for (ol = obp->link; ol; ol = ol->next) 218 for (ol = obp->link; ol; ol = ol->next)
228 { 219 {
229 if (!ol->ob || ol->ob->count != ol->id) 220 if (!ol->ob)
230 { 221 {
231 LOG (llevDebug, "Internal error in update_button (%s).\n", &op->name); 222 LOG (llevDebug, "Internal error in update_button (%s).\n", &op->name);
232 continue; 223 continue;
233 } 224 }
225
234 tmp = ol->ob; 226 tmp = ol->ob;
235 if (tmp->type == BUTTON) 227 if (tmp->type == BUTTON)
236 { 228 {
237 for (ab = tmp->above, tot = 0; ab != NULL; ab = ab->above) 229 for (ab = tmp->above, tot = 0; ab != NULL; ab = ab->above)
238 /* Bug? The pedestal code below looks for the head of 230 /* Bug? The pedestal code below looks for the head of
282 update_object (op, UP_OBJ_FACE); 274 update_object (op, UP_OBJ_FACE);
283 push_button (op); /* Make all other buttons the same */ 275 push_button (op); /* Make all other buttons the same */
284 } 276 }
285} 277}
286 278
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 279void
315use_trigger (object *op) 280use_trigger (object *op)
316{ 281{
317
318 /* Toggle value */ 282 /* Toggle value */
319 op->value = !op->value; 283 op->value = !op->value;
320 push_button (op); 284 push_button (op);
321} 285}
322 286
323/* 287/*
324 * Note: animate_object should be used instead of this, 288 * Note: animate_object should be used instead of this,
325 * but it can't handle animations in the 8 directions 289 * but it can't handle animations in the 8 directions
326 */ 290 */
327
328void 291void
329animate_turning (object *op) /* only one part objects */ 292animate_turning (object *op) /* only one part objects */
330{ 293{
331 if (++op->state >= NUM_ANIMATIONS (op) / 8) 294 if (++op->state >= NUM_ANIMATIONS (op) / 8)
332 op->state = 0; 295 op->state = 0;
357 ARCH_SACRIFICE (altar) == sacrifice->name || 320 ARCH_SACRIFICE (altar) == sacrifice->name ||
358 ARCH_SACRIFICE (altar) == sacrifice->slaying || 321 ARCH_SACRIFICE (altar) == sacrifice->slaying ||
359 (!strcmp (ARCH_SACRIFICE (altar), query_base_name (sacrifice, 0)))) 322 (!strcmp (ARCH_SACRIFICE (altar), query_base_name (sacrifice, 0))))
360 && NROF_SACRIFICE (altar) <= (sacrifice->nrof ? sacrifice->nrof : 1)) 323 && NROF_SACRIFICE (altar) <= (sacrifice->nrof ? sacrifice->nrof : 1))
361 return 1; 324 return 1;
325
362 if (strcmp (ARCH_SACRIFICE (altar), "money") == 0 326 if (strcmp (ARCH_SACRIFICE (altar), "money") == 0
363 && sacrifice->type == MONEY && sacrifice->nrof * sacrifice->value >= NROF_SACRIFICE (altar)) 327 && sacrifice->type == MONEY && sacrifice->nrof * sacrifice->value >= NROF_SACRIFICE (altar))
364 return 1; 328 return 1;
365 } 329 }
330
366 return 0; 331 return 0;
367} 332}
368
369 333
370/* 334/*
371 * operate_altar checks if sacrifice was accepted and removes sacrificed 335 * operate_altar checks if sacrifice was accepted and removes sacrificed
372 * objects. If sacrifice was succeed return 1 else 0. Might be better to 336 * 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, 337 * call check_altar_sacrifice (above) than depend on the return value,
374 * since operate_altar will remove the sacrifice also. 338 * since operate_altar will remove the sacrifice also.
375 * 339 *
376 * If this function returns 1, '*sacrifice' is modified to point to the 340 * 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. 341 * remaining sacrifice, or is set to NULL if the sacrifice was used up.
378 */ 342 */
379
380int 343int
381operate_altar (object *altar, object **sacrifice) 344operate_altar (object *altar, object **sacrifice)
382{ 345{
383
384 if (!altar->map) 346 if (!altar->map)
385 { 347 {
386 LOG (llevError, "BUG: operate_altar(): altar has no map\n"); 348 LOG (llevError, "BUG: operate_altar(): altar has no map\n");
387 return 0; 349 return 0;
388 } 350 }
401 int number = NROF_SACRIFICE (altar) / (*sacrifice)->value; 363 int number = NROF_SACRIFICE (altar) / (*sacrifice)->value;
402 364
403 /* Round up any sacrifices. Altars don't make change either */ 365 /* Round up any sacrifices. Altars don't make change either */
404 if (NROF_SACRIFICE (altar) % (*sacrifice)->value) 366 if (NROF_SACRIFICE (altar) % (*sacrifice)->value)
405 number++; 367 number++;
368
406 *sacrifice = decrease_ob_nr (*sacrifice, number); 369 *sacrifice = decrease_ob_nr (*sacrifice, number);
407 } 370 }
408 else 371 else
409 *sacrifice = decrease_ob_nr (*sacrifice, NROF_SACRIFICE (altar)); 372 *sacrifice = decrease_ob_nr (*sacrifice, NROF_SACRIFICE (altar));
410 373
411 if (altar->msg) 374 if (altar->msg)
412 new_info_map (NDI_BLACK, altar->map, altar->msg); 375 new_info_map (NDI_BLACK, altar->map, altar->msg);
376
413 return 1; 377 return 1;
414} 378}
415 379
416void 380void
417trigger_move (object *op, int state) /* 1 down and 0 up */ 381trigger_move (object *op, int state) /* 1 down and 0 up */
418{ 382{
419 op->stats.wc = state; 383 op->stats.wc = state;
420 if (state) 384 if (state)
421 { 385 {
422 use_trigger (op); 386 use_trigger (op);
423 if (op->stats.exp > 0) /* check sanity */ 387 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; 388 op->speed_left = -1;
429 } 389 }
430 else 390 else
431 { 391 {
432 use_trigger (op); 392 use_trigger (op);
433 op->speed = 0; 393 op->set_speed (0);
434 update_ob_speed (op);
435 } 394 }
436} 395}
437 396
438 397
439/* 398/*
574 trigger_move (op, 0); 533 trigger_move (op, 0);
575 else 534 else
576 { 535 {
577 op->stats.wc = 0; 536 op->stats.wc = 0;
578 op->value = !op->value; 537 op->value = !op->value;
579 op->speed = 0; 538 op->set_speed (0);
580 update_ob_speed (op);
581 } 539 }
582 } 540 }
583 return 0; 541 return 0;
584 542
585 case TRIGGER: 543 case TRIGGER:
586 if (cause) 544 if (cause)
587 { 545 {
588 if (in_movement) 546 if (in_movement)
589 return 0; 547 return 0;
548
590 push = 1; 549 push = 1;
591 } 550 }
551
592 if (NUM_ANIMATIONS (op) > 1) 552 if (NUM_ANIMATIONS (op) > 1)
593 { 553 {
594 SET_ANIMATION (op, push); 554 SET_ANIMATION (op, push);
595 update_object (op, UP_OBJ_FACE); 555 update_object (op, UP_OBJ_FACE);
596 } 556 }
557
597 trigger_move (op, push); 558 trigger_move (op, push);
598 return 1; 559 return 1;
599 560
600 default: 561 default:
601 LOG (llevDebug, "Unknown trigger type: %s (%d)\n", &op->name, op->type); 562 LOG (llevDebug, "Unknown trigger type: %s (%d)\n", &op->name, op->type);
602 return 0; 563 return 0;
603 } 564 }
604} 565}
605 566
606void 567void
607add_button_link (object *button, mapstruct *map, int connected) 568add_button_link (object *button, maptile *map, int connected)
608{ 569{
609 oblinkpt *obp; 570 oblinkpt *obp;
610 objectlink *ol = get_objectlink (); 571 objectlink *ol = get_objectlink ();
611 572
612 if (!map) 573 if (!map)
613 { 574 {
614 LOG (llevError, "Tried to add button-link without map.\n"); 575 LOG (llevError, "Tried to add button-link without map.\n");
615 return; 576 return;
616 } 577 }
617 if (!editor) 578
618 button->path_attuned = connected; /* peterm: I need this so I can rebuild 579 button->path_attuned = connected; /* peterm: I need this so I can rebuild
619 a connected map from a template map. */ 580 a connected map from a template map. */
620
621/* LOG(llevDebug,"adding button %s (%d)\n", button->name, connected);*/
622 581
623 SET_FLAG (button, FLAG_IS_LINKED); 582 SET_FLAG (button, FLAG_IS_LINKED);
624 583
625 ol->ob = button; 584 ol->ob = button;
626 ol->id = button->count;
627 585
628 for (obp = map->buttons; obp && obp->value != connected; obp = obp->next); 586 for (obp = map->buttons; obp && obp->value != connected; obp = obp->next)
587 ;
629 588
630 if (obp) 589 if (obp)
631 { 590 {
632 ol->next = obp->link; 591 ol->next = obp->link;
633 obp->link = ol; 592 obp->link = ol;
657 if (op->map == NULL) 616 if (op->map == NULL)
658 { 617 {
659 LOG (llevError, "remove_button_link() in object without map.\n"); 618 LOG (llevError, "remove_button_link() in object without map.\n");
660 return; 619 return;
661 } 620 }
621
662 if (!QUERY_FLAG (op, FLAG_IS_LINKED)) 622 if (!QUERY_FLAG (op, FLAG_IS_LINKED))
663 { 623 {
664 LOG (llevError, "remove_button_linked() in unlinked object.\n"); 624 LOG (llevError, "remove_button_linked() in unlinked object.\n");
665 return; 625 return;
666 } 626 }
627
667 for (obp = op->map->buttons; obp; obp = obp->next) 628 for (obp = op->map->buttons; obp; obp = obp->next)
668 for (olp = &obp->link; (ol = *olp); olp = &ol->next) 629 for (olp = &obp->link; (ol = *olp); olp = &ol->next)
669 if (ol->ob == op) 630 if (ol->ob == op)
670 { 631 {
671 632
672/* LOG(llevDebug, "Removed link %d in button %s and map %s.\n", 633/* LOG(llevDebug, "Removed link %d in button %s and map %s.\n",
673 obp->value, op->name, op->map->path); 634 obp->value, op->name, op->map->path);
674*/ 635*/
675 *olp = ol->next; 636 *olp = ol->next;
676 free (ol); 637 delete ol;
677 return; 638 return;
678 } 639 }
640
679 LOG (llevError, "remove_button_linked(): couldn't find object.\n"); 641 LOG (llevError, "remove_button_linked(): couldn't find object.\n");
680 CLEAR_FLAG (op, FLAG_IS_LINKED); 642 CLEAR_FLAG (op, FLAG_IS_LINKED);
681} 643}
682 644
683/* 645/*
684 * Gets the objectlink for this connection from the map. 646 * Gets the objectlink for this connection from the map.
685 */ 647 */
686oblinkpt * 648oblinkpt *
687get_connection_links (mapstruct *map, long connection) 649get_connection_links (maptile *map, long connection)
688{ 650{
689 for (oblinkpt * obp = map->buttons; obp; obp = obp->next) 651 for (oblinkpt * obp = map->buttons; obp; obp = obp->next)
690 if (obp->value == connection) 652 if (obp->value == connection)
691 return obp; 653 return obp;
654
692 return 0; 655 return 0;
693} 656}
694 657
695/* 658/*
696 * Return the first objectlink in the objects linked to this one 659 * Return the first objectlink in the objects linked to this one
702 oblinkpt *obp; 665 oblinkpt *obp;
703 objectlink *ol; 666 objectlink *ol;
704 667
705 if (!button->map) 668 if (!button->map)
706 return NULL; 669 return NULL;
670
707 for (obp = button->map->buttons; obp; obp = obp->next) 671 for (obp = button->map->buttons; obp; obp = obp->next)
708 for (ol = obp->link; ol; ol = ol->next) 672 for (ol = obp->link; ol; ol = ol->next)
709 if (ol->ob == button && ol->id == button->count) 673 if (ol->ob == button)
710 return obp; 674 return obp;
675
711 return NULL; 676 return NULL;
712} 677}
713 678
714/* 679/*
715 * Made as a separate function to increase efficiency 680 * Made as a separate function to increase efficiency
723 688
724 if (!button->map) 689 if (!button->map)
725 return 0; 690 return 0;
726 for (obp = button->map->buttons; obp; obp = obp->next) 691 for (obp = button->map->buttons; obp; obp = obp->next)
727 for (ol = obp->link; ol; ol = ol->next) 692 for (ol = obp->link; ol; ol = ol->next)
728 if (ol->ob == button && ol->id == button->count) 693 if (ol->ob == button)
729 return obp->value; 694 return obp->value;
730 return 0; 695 return 0;
731} 696}
732 697
733/* This routine makes monsters who are 698/* This routine makes monsters who are
770 tmp->attack_movement = 0; 735 tmp->attack_movement = 0;
771 /* lots of checks here, but want to make sure we don't 736 /* lots of checks here, but want to make sure we don't
772 * dereference a null value 737 * dereference a null value
773 */ 738 */
774 if (tmp->type == GOLEM && tmp->owner && tmp->owner->type == PLAYER && tmp->owner->contr->ranges[range_golem] == tmp) 739 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; 740 tmp->owner->contr->ranges[range_golem] = 0;
777 tmp->owner->contr->golem_count = 0; 741
778 }
779 tmp->owner = 0; 742 tmp->owner = 0;
780 } 743 }
781 break; 744 break;
782 case 1: /* angry -- get neutral monsters mad */ 745 case 1: /* angry -- get neutral monsters mad */
783 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (tmp, FLAG_FRIENDLY)) 746 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (tmp, FLAG_FRIENDLY))
793 break; 756 break;
794 case 4: /* charm all monsters */ 757 case 4: /* charm all monsters */
795 if (op == source) 758 if (op == source)
796 break; /* only if 'connected' */ 759 break; /* only if 'connected' */
797 760
798 for (tmp2 = get_map_ob (source->map, source->x, source->y); /* finding an owner */ 761 for (tmp2 = GET_MAP_OB (source->map, source->x, source->y); /* finding an owner */
799 tmp2->type != PLAYER; tmp2 = tmp2->above) 762 tmp2->type != PLAYER; tmp2 = tmp2->above)
800 if (tmp2->above == NULL) 763 if (tmp2->above == NULL)
801 break; 764 break;
802 765
803 if (tmp2->type != PLAYER) 766 if (tmp2->type != PLAYER)
804 break; 767 break;
768
805 set_owner (tmp, tmp2); 769 tmp->set_owner (tmp2);
806 SET_FLAG (tmp, FLAG_MONSTER); 770 SET_FLAG (tmp, FLAG_MONSTER);
771
807 tmp->stats.exp = 0; 772 tmp->stats.exp = 0;
808 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:
819 * It will descend through containers to find the object. 784 * It will descend through containers to find the object.
820 * slaying = match object slaying flag 785 * slaying = match object slaying flag
821 * race = match object archetype name flag 786 * race = match object archetype name flag
822 * hp = match object type (excpt type '0'== PLAYER) 787 * hp = match object type (excpt type '0'== PLAYER)
823 */ 788 */
824
825object * 789object *
826check_inv_recursive (object *op, const object *trig) 790check_inv_recursive (object *op, const object *trig)
827{ 791{
828 object *tmp, *ret = NULL; 792 object *tmp, *ret = NULL;
829 793
830 /* First check the object itself. */ 794 /* First check the object itself. */
831 if ((trig->stats.hp && (op->type == trig->stats.hp)) 795 if ((trig->stats.hp && (op->type == trig->stats.hp))
832 || (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)))
833 return op; 798 return op;
834 799
835 for (tmp = op->inv; tmp; tmp = tmp->below) 800 for (tmp = op->inv; tmp; tmp = tmp->below)
836 { 801 {
837 if (tmp->inv) 802 if (tmp->inv)
839 ret = check_inv_recursive (tmp, trig); 804 ret = check_inv_recursive (tmp, trig);
840 if (ret) 805 if (ret)
841 return ret; 806 return ret;
842 } 807 }
843 else if ((trig->stats.hp && (tmp->type == trig->stats.hp)) 808 else if ((trig->stats.hp && (tmp->type == trig->stats.hp))
844 || (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)))
845 return tmp; 811 return tmp;
846 } 812 }
847 return NULL; 813 return NULL;
848} 814}
849 815
852 * the square will activate connected items. 818 * the square will activate connected items.
853 * Monsters can't trigger this square (for now) 819 * Monsters can't trigger this square (for now)
854 * Values are: last_sp = 1/0 obj/no obj triggers 820 * Values are: last_sp = 1/0 obj/no obj triggers
855 * last_heal = 1/0 remove/dont remove obj if triggered 821 * last_heal = 1/0 remove/dont remove obj if triggered
856 * -b.t. (thomas@nomad.astro.psu.edu 822 * -b.t. (thomas@nomad.astro.psu.edu
857 */ 823 *
858 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 */
859void 834void
860check_inv (object *op, object *trig) 835check_inv (object *op, object *trig)
861{ 836{
862 object *match; 837 sint32 prev_state = trig->value;
838 trig->value = 0; // deactivate if none of the following conditions apply
863 839
864 if (op->type != PLAYER) 840 if (object *pl = trig->ms ().player ())
865 return; 841 {
866 match = check_inv_recursive (op, trig); 842 object *match = check_inv_recursive (pl, trig);
867 if (match && trig->last_sp)
868 {
869 if (trig->last_heal)
870 decrease_ob (match);
871 use_trigger (trig);
872 }
873 else if (!match && !trig->last_sp)
874 use_trigger (trig);
875}
876 843
877 844 if (match && trig->last_sp) // match == having
878/* This does a minimal check of the button link consistency for object
879 * map. All it really does it much sure the object id link that is set
880 * matches what the object has.
881 */
882void
883verify_button_links (const mapstruct *map)
884{
885 oblinkpt *obp;
886 objectlink *ol;
887
888 if (!map)
889 return;
890
891 for (obp = map->buttons; obp; obp = obp->next)
892 {
893 for (ol = obp->link; ol; ol = ol->next)
894 { 845 {
895 if (ol->id != ol->ob->count) 846 if (trig->last_heal)
896 LOG (llevError, "verify_button_links: object %s on list is corrupt (%d!=%d)\n", &ol->ob->name, ol->id, ol->ob->count); 847 decrease_ob (match);
848
849 trig->value = 1;
897 } 850 }
851 else if (!match && !trig->last_sp) // match == not having
852 trig->value = 1;
898 } 853 }
854
855 if (prev_state != trig->value)
856 push_button (trig);
899} 857}
858

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines