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.18 by root, Thu Dec 21 01:33:49 2006 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
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
45{ 39{
46 object *tmp = 0; 40 object *tmp = 0;
47 41
48 for (; ol; ol = ol->next) 42 for (; ol; ol = ol->next)
49 { 43 {
50 if (!ol->ob || ol->ob->count != ol->id) 44 if (!ol->ob)
51 { 45 {
52 LOG (llevError, "Internal error in activate_connection_link (%ld).\n", ol->id); 46 LOG (llevError, "Internal error in activate_connection_link.\n");
53 continue; 47 continue;
54 } 48 }
49
55 /* a button link object can become freed when the map is saving. As 50 /* 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 51 * 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 52 * 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 53 * 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 54 * probably isn't important - it will get sorted out when the map is
193 * the connection was 'state' or 'released'. So that you can activate objects 188 * the connection was 'state' or 'released'. So that you can activate objects
194 * who have FLAG_ACTIVATE_ON_PUSH/RELEASE set properly. 189 * who have FLAG_ACTIVATE_ON_PUSH/RELEASE set properly.
195 * 190 *
196 */ 191 */
197void 192void
198activate_connection (mapstruct *map, long connection, bool state) 193activate_connection (maptile *map, long connection, bool state)
199{ 194{
200 if (INVOKE_MAP (TRIGGER, map, ARG_INT64 (connection), ARG_INT (state))) 195 if (INVOKE_MAP (TRIGGER, map, ARG_INT64 (connection), ARG_INT (state)))
201 return; 196 return;
202 197
203 oblinkpt *obp = get_connection_links (map, connection); 198 oblinkpt *obp = get_connection_links (map, connection);
210 * Updates everything connected with the button op. 205 * Updates everything connected with the button op.
211 * After changing the state of a button, this function must be called 206 * 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 207 * to make sure that all gates and other buttons connected to the
213 * button reacts to the (eventual) change of state. 208 * button reacts to the (eventual) change of state.
214 */ 209 */
215
216void 210void
217update_button (object *op) 211update_button (object *op)
218{ 212{
219 object *ab, *tmp, *head; 213 object *ab, *tmp, *head;
220 int tot, any_down = 0, old_value = op->value; 214 int tot, any_down = 0, old_value = op->value;
224 obp = get_button_links (op); 218 obp = get_button_links (op);
225 /* LOG(llevDebug, "update_button: %s (%d)\n", op->name, op->count); */ 219 /* LOG(llevDebug, "update_button: %s (%d)\n", op->name, op->count); */
226 if (obp) 220 if (obp)
227 for (ol = obp->link; ol; ol = ol->next) 221 for (ol = obp->link; ol; ol = ol->next)
228 { 222 {
229 if (!ol->ob || ol->ob->count != ol->id) 223 if (!ol->ob)
230 { 224 {
231 LOG (llevDebug, "Internal error in update_button (%s).\n", &op->name); 225 LOG (llevDebug, "Internal error in update_button (%s).\n", &op->name);
232 continue; 226 continue;
233 } 227 }
228
234 tmp = ol->ob; 229 tmp = ol->ob;
235 if (tmp->type == BUTTON) 230 if (tmp->type == BUTTON)
236 { 231 {
237 for (ab = tmp->above, tot = 0; ab != NULL; ab = ab->above) 232 for (ab = tmp->above, tot = 0; ab != NULL; ab = ab->above)
238 /* Bug? The pedestal code below looks for the head of 233 /* Bug? The pedestal code below looks for the head of
287/* 282/*
288 * Updates every button on the map (by calling update_button() for them). 283 * Updates every button on the map (by calling update_button() for them).
289 */ 284 */
290 285
291void 286void
292update_buttons (mapstruct *m) 287update_buttons (maptile *m)
293{ 288{
294 objectlink *ol; 289 objectlink *ol;
295 oblinkpt *obp; 290 oblinkpt *obp;
296 291
297 for (obp = m->buttons; obp; obp = obp->next) 292 for (obp = m->buttons; obp; obp = obp->next)
298 for (ol = obp->link; ol; ol = ol->next) 293 for (ol = obp->link; ol; ol = ol->next)
299 { 294 {
300 if (!ol->ob || ol->ob->count != ol->id) 295 if (!ol->ob)
301 { 296 {
302 LOG (llevError, "Internal error in update_button (%s (%dx%d):%d, connected %ld).\n", 297 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); 298 ol->ob ? (const char *) ol->ob->name : "null", ol->ob ? ol->ob->x : -1, ol->ob ? ol->ob->y : -1, obp->value);
304 continue; 299 continue;
305 } 300 }
301
306 if (ol->ob->type == BUTTON || ol->ob->type == PEDESTAL) 302 if (ol->ob->type == BUTTON || ol->ob->type == PEDESTAL)
307 { 303 {
308 update_button (ol->ob); 304 update_button (ol->ob);
309 break; 305 break;
310 } 306 }
357 ARCH_SACRIFICE (altar) == sacrifice->name || 353 ARCH_SACRIFICE (altar) == sacrifice->name ||
358 ARCH_SACRIFICE (altar) == sacrifice->slaying || 354 ARCH_SACRIFICE (altar) == sacrifice->slaying ||
359 (!strcmp (ARCH_SACRIFICE (altar), query_base_name (sacrifice, 0)))) 355 (!strcmp (ARCH_SACRIFICE (altar), query_base_name (sacrifice, 0))))
360 && NROF_SACRIFICE (altar) <= (sacrifice->nrof ? sacrifice->nrof : 1)) 356 && NROF_SACRIFICE (altar) <= (sacrifice->nrof ? sacrifice->nrof : 1))
361 return 1; 357 return 1;
358
362 if (strcmp (ARCH_SACRIFICE (altar), "money") == 0 359 if (strcmp (ARCH_SACRIFICE (altar), "money") == 0
363 && sacrifice->type == MONEY && sacrifice->nrof * sacrifice->value >= NROF_SACRIFICE (altar)) 360 && sacrifice->type == MONEY && sacrifice->nrof * sacrifice->value >= NROF_SACRIFICE (altar))
364 return 1; 361 return 1;
365 } 362 }
363
366 return 0; 364 return 0;
367} 365}
368
369 366
370/* 367/*
371 * operate_altar checks if sacrifice was accepted and removes sacrificed 368 * operate_altar checks if sacrifice was accepted and removes sacrificed
372 * objects. If sacrifice was succeed return 1 else 0. Might be better to 369 * 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, 370 * call check_altar_sacrifice (above) than depend on the return value,
374 * since operate_altar will remove the sacrifice also. 371 * since operate_altar will remove the sacrifice also.
375 * 372 *
376 * If this function returns 1, '*sacrifice' is modified to point to the 373 * 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. 374 * remaining sacrifice, or is set to NULL if the sacrifice was used up.
378 */ 375 */
379
380int 376int
381operate_altar (object *altar, object **sacrifice) 377operate_altar (object *altar, object **sacrifice)
382{ 378{
383
384 if (!altar->map) 379 if (!altar->map)
385 { 380 {
386 LOG (llevError, "BUG: operate_altar(): altar has no map\n"); 381 LOG (llevError, "BUG: operate_altar(): altar has no map\n");
387 return 0; 382 return 0;
388 } 383 }
401 int number = NROF_SACRIFICE (altar) / (*sacrifice)->value; 396 int number = NROF_SACRIFICE (altar) / (*sacrifice)->value;
402 397
403 /* Round up any sacrifices. Altars don't make change either */ 398 /* Round up any sacrifices. Altars don't make change either */
404 if (NROF_SACRIFICE (altar) % (*sacrifice)->value) 399 if (NROF_SACRIFICE (altar) % (*sacrifice)->value)
405 number++; 400 number++;
401
406 *sacrifice = decrease_ob_nr (*sacrifice, number); 402 *sacrifice = decrease_ob_nr (*sacrifice, number);
407 } 403 }
408 else 404 else
409 *sacrifice = decrease_ob_nr (*sacrifice, NROF_SACRIFICE (altar)); 405 *sacrifice = decrease_ob_nr (*sacrifice, NROF_SACRIFICE (altar));
410 406
411 if (altar->msg) 407 if (altar->msg)
412 new_info_map (NDI_BLACK, altar->map, altar->msg); 408 new_info_map (NDI_BLACK, altar->map, altar->msg);
409
413 return 1; 410 return 1;
414} 411}
415 412
416void 413void
417trigger_move (object *op, int state) /* 1 down and 0 up */ 414trigger_move (object *op, int state) /* 1 down and 0 up */
602 return 0; 599 return 0;
603 } 600 }
604} 601}
605 602
606void 603void
607add_button_link (object *button, mapstruct *map, int connected) 604add_button_link (object *button, maptile *map, int connected)
608{ 605{
609 oblinkpt *obp; 606 oblinkpt *obp;
610 objectlink *ol = get_objectlink (); 607 objectlink *ol = get_objectlink ();
611 608
612 if (!map) 609 if (!map)
621/* LOG(llevDebug,"adding button %s (%d)\n", button->name, connected);*/ 618/* LOG(llevDebug,"adding button %s (%d)\n", button->name, connected);*/
622 619
623 SET_FLAG (button, FLAG_IS_LINKED); 620 SET_FLAG (button, FLAG_IS_LINKED);
624 621
625 ol->ob = button; 622 ol->ob = button;
626 ol->id = button->count;
627 623
628 for (obp = map->buttons; obp && obp->value != connected; obp = obp->next); 624 for (obp = map->buttons; obp && obp->value != connected; obp = obp->next);
629 625
630 if (obp) 626 if (obp)
631 { 627 {
657 if (op->map == NULL) 653 if (op->map == NULL)
658 { 654 {
659 LOG (llevError, "remove_button_link() in object without map.\n"); 655 LOG (llevError, "remove_button_link() in object without map.\n");
660 return; 656 return;
661 } 657 }
658
662 if (!QUERY_FLAG (op, FLAG_IS_LINKED)) 659 if (!QUERY_FLAG (op, FLAG_IS_LINKED))
663 { 660 {
664 LOG (llevError, "remove_button_linked() in unlinked object.\n"); 661 LOG (llevError, "remove_button_linked() in unlinked object.\n");
665 return; 662 return;
666 } 663 }
664
667 for (obp = op->map->buttons; obp; obp = obp->next) 665 for (obp = op->map->buttons; obp; obp = obp->next)
668 for (olp = &obp->link; (ol = *olp); olp = &ol->next) 666 for (olp = &obp->link; (ol = *olp); olp = &ol->next)
669 if (ol->ob == op) 667 if (ol->ob == op)
670 { 668 {
671 669
672/* LOG(llevDebug, "Removed link %d in button %s and map %s.\n", 670/* LOG(llevDebug, "Removed link %d in button %s and map %s.\n",
673 obp->value, op->name, op->map->path); 671 obp->value, op->name, op->map->path);
674*/ 672*/
675 *olp = ol->next; 673 *olp = ol->next;
676 free (ol); 674 delete ol;
677 return; 675 return;
678 } 676 }
677
679 LOG (llevError, "remove_button_linked(): couldn't find object.\n"); 678 LOG (llevError, "remove_button_linked(): couldn't find object.\n");
680 CLEAR_FLAG (op, FLAG_IS_LINKED); 679 CLEAR_FLAG (op, FLAG_IS_LINKED);
681} 680}
682 681
683/* 682/*
684 * Gets the objectlink for this connection from the map. 683 * Gets the objectlink for this connection from the map.
685 */ 684 */
686oblinkpt * 685oblinkpt *
687get_connection_links (mapstruct *map, long connection) 686get_connection_links (maptile *map, long connection)
688{ 687{
689 for (oblinkpt * obp = map->buttons; obp; obp = obp->next) 688 for (oblinkpt * obp = map->buttons; obp; obp = obp->next)
690 if (obp->value == connection) 689 if (obp->value == connection)
691 return obp; 690 return obp;
691
692 return 0; 692 return 0;
693} 693}
694 694
695/* 695/*
696 * Return the first objectlink in the objects linked to this one 696 * Return the first objectlink in the objects linked to this one
702 oblinkpt *obp; 702 oblinkpt *obp;
703 objectlink *ol; 703 objectlink *ol;
704 704
705 if (!button->map) 705 if (!button->map)
706 return NULL; 706 return NULL;
707
707 for (obp = button->map->buttons; obp; obp = obp->next) 708 for (obp = button->map->buttons; obp; obp = obp->next)
708 for (ol = obp->link; ol; ol = ol->next) 709 for (ol = obp->link; ol; ol = ol->next)
709 if (ol->ob == button && ol->id == button->count) 710 if (ol->ob == button)
710 return obp; 711 return obp;
712
711 return NULL; 713 return NULL;
712} 714}
713 715
714/* 716/*
715 * Made as a separate function to increase efficiency 717 * Made as a separate function to increase efficiency
723 725
724 if (!button->map) 726 if (!button->map)
725 return 0; 727 return 0;
726 for (obp = button->map->buttons; obp; obp = obp->next) 728 for (obp = button->map->buttons; obp; obp = obp->next)
727 for (ol = obp->link; ol; ol = ol->next) 729 for (ol = obp->link; ol; ol = ol->next)
728 if (ol->ob == button && ol->id == button->count) 730 if (ol->ob == button)
729 return obp->value; 731 return obp->value;
730 return 0; 732 return 0;
731} 733}
732 734
733/* This routine makes monsters who are 735/* This routine makes monsters who are
770 tmp->attack_movement = 0; 772 tmp->attack_movement = 0;
771 /* lots of checks here, but want to make sure we don't 773 /* lots of checks here, but want to make sure we don't
772 * dereference a null value 774 * dereference a null value
773 */ 775 */
774 if (tmp->type == GOLEM && tmp->owner && tmp->owner->type == PLAYER && tmp->owner->contr->ranges[range_golem] == tmp) 776 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; 777 tmp->owner->contr->ranges[range_golem] = 0;
777 tmp->owner->contr->golem_count = 0; 778
778 }
779 tmp->owner = 0; 779 tmp->owner = 0;
780 } 780 }
781 break; 781 break;
782 case 1: /* angry -- get neutral monsters mad */ 782 case 1: /* angry -- get neutral monsters mad */
783 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (tmp, FLAG_FRIENDLY)) 783 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (tmp, FLAG_FRIENDLY))
793 break; 793 break;
794 case 4: /* charm all monsters */ 794 case 4: /* charm all monsters */
795 if (op == source) 795 if (op == source)
796 break; /* only if 'connected' */ 796 break; /* only if 'connected' */
797 797
798 for (tmp2 = get_map_ob (source->map, source->x, source->y); /* finding an owner */ 798 for (tmp2 = GET_MAP_OB (source->map, source->x, source->y); /* finding an owner */
799 tmp2->type != PLAYER; tmp2 = tmp2->above) 799 tmp2->type != PLAYER; tmp2 = tmp2->above)
800 if (tmp2->above == NULL) 800 if (tmp2->above == NULL)
801 break; 801 break;
802 802
803 if (tmp2->type != PLAYER) 803 if (tmp2->type != PLAYER)
804 break; 804 break;
805
805 set_owner (tmp, tmp2); 806 tmp->set_owner (tmp2);
806 SET_FLAG (tmp, FLAG_MONSTER); 807 SET_FLAG (tmp, FLAG_MONSTER);
808
807 tmp->stats.exp = 0; 809 tmp->stats.exp = 0;
808 SET_FLAG (tmp, FLAG_FRIENDLY); 810 SET_FLAG (tmp, FLAG_FRIENDLY);
811
809 add_friendly_object (tmp); 812 add_friendly_object (tmp);
810 tmp->attack_movement = PETMOVE; 813 tmp->attack_movement = PETMOVE;
811 break; 814 break;
812 815
813 default: 816 default:
819 * It will descend through containers to find the object. 822 * It will descend through containers to find the object.
820 * slaying = match object slaying flag 823 * slaying = match object slaying flag
821 * race = match object archetype name flag 824 * race = match object archetype name flag
822 * hp = match object type (excpt type '0'== PLAYER) 825 * hp = match object type (excpt type '0'== PLAYER)
823 */ 826 */
824
825object * 827object *
826check_inv_recursive (object *op, const object *trig) 828check_inv_recursive (object *op, const object *trig)
827{ 829{
828 object *tmp, *ret = NULL; 830 object *tmp, *ret = NULL;
829 831
830 /* First check the object itself. */ 832 /* First check the object itself. */
831 if ((trig->stats.hp && (op->type == trig->stats.hp)) 833 if ((trig->stats.hp && (op->type == trig->stats.hp))
832 || (trig->slaying && (op->slaying == trig->slaying)) || (trig->race && (op->arch->name == trig->race))) 834 || (trig->slaying && (op->slaying == trig->slaying))
835 || (trig->race && (op->arch->name == trig->race)))
833 return op; 836 return op;
834 837
835 for (tmp = op->inv; tmp; tmp = tmp->below) 838 for (tmp = op->inv; tmp; tmp = tmp->below)
836 { 839 {
837 if (tmp->inv) 840 if (tmp->inv)
839 ret = check_inv_recursive (tmp, trig); 842 ret = check_inv_recursive (tmp, trig);
840 if (ret) 843 if (ret)
841 return ret; 844 return ret;
842 } 845 }
843 else if ((trig->stats.hp && (tmp->type == trig->stats.hp)) 846 else if ((trig->stats.hp && (tmp->type == trig->stats.hp))
844 || (trig->slaying && (tmp->slaying == trig->slaying)) || (trig->race && (tmp->arch->name == trig->race))) 847 || (trig->slaying && (tmp->slaying == trig->slaying))
848 || (trig->race && (tmp->arch->name == trig->race)))
845 return tmp; 849 return tmp;
846 } 850 }
847 return NULL; 851 return NULL;
848} 852}
849 853
852 * the square will activate connected items. 856 * the square will activate connected items.
853 * Monsters can't trigger this square (for now) 857 * Monsters can't trigger this square (for now)
854 * Values are: last_sp = 1/0 obj/no obj triggers 858 * Values are: last_sp = 1/0 obj/no obj triggers
855 * last_heal = 1/0 remove/dont remove obj if triggered 859 * last_heal = 1/0 remove/dont remove obj if triggered
856 * -b.t. (thomas@nomad.astro.psu.edu 860 * -b.t. (thomas@nomad.astro.psu.edu
857 */ 861 *
858 862 * Tue Dec 19 15:34:00 CET 2006 elmex: changed the function to ignore op
863 * because the check-inventory semantic essentially only applies when
864 * something is above the inventory checker.
865 * The semantic prior this change was: trigger if something has moved on or off
866 * and has a matching item. Imagine what happens if someone steps on the inventory
867 * checker with a matching item, has it, activates the connection, throws the item
868 * away, and then leaves the inventory checker. That would've caused an always-enabled
869 * state in the inventory checker. This won't happen anymore now.
870 *
871 */
859void 872void
860check_inv (object *op, object *trig) 873check_inv (object *op, object *trig)
861{ 874{
862 object *match; 875 trig->value = 0; // deactivate if none of the following conditions apply
863 876
864 if (op->type != PLAYER) 877 if (object *pl = trig->ms ().player ())
865 return; 878 {
866 match = check_inv_recursive (op, trig); 879 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 880
877 881 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 { 882 {
895 if (ol->id != ol->ob->count) 883 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); 884 decrease_ob (match);
885
886 trig->value = 1;
897 } 887 }
888 else if (!match && !trig->last_sp) // match == not having
889 trig->value = 1;
898 } 890 }
891
892 push_button (trig);
899} 893}
894

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines