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.9 by root, Wed Sep 13 23:42:23 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.9 2006/09/13 23:42: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
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 366
369/* 367/*
370 * operate_altar checks if sacrifice was accepted and removes sacrificed 368 * operate_altar checks if sacrifice was accepted and removes sacrificed
601 return 0; 599 return 0;
602 } 600 }
603} 601}
604 602
605void 603void
606add_button_link (object *button, mapstruct *map, int connected) 604add_button_link (object *button, maptile *map, int connected)
607{ 605{
608 oblinkpt *obp; 606 oblinkpt *obp;
609 objectlink *ol = get_objectlink (); 607 objectlink *ol = get_objectlink ();
610 608
611 if (!map) 609 if (!map)
620/* LOG(llevDebug,"adding button %s (%d)\n", button->name, connected);*/ 618/* LOG(llevDebug,"adding button %s (%d)\n", button->name, connected);*/
621 619
622 SET_FLAG (button, FLAG_IS_LINKED); 620 SET_FLAG (button, FLAG_IS_LINKED);
623 621
624 ol->ob = button; 622 ol->ob = button;
625 ol->id = button->count;
626 623
627 for (obp = map->buttons; obp && obp->value != connected; obp = obp->next); 624 for (obp = map->buttons; obp && obp->value != connected; obp = obp->next);
628 625
629 if (obp) 626 if (obp)
630 { 627 {
656 if (op->map == NULL) 653 if (op->map == NULL)
657 { 654 {
658 LOG (llevError, "remove_button_link() in object without map.\n"); 655 LOG (llevError, "remove_button_link() in object without map.\n");
659 return; 656 return;
660 } 657 }
658
661 if (!QUERY_FLAG (op, FLAG_IS_LINKED)) 659 if (!QUERY_FLAG (op, FLAG_IS_LINKED))
662 { 660 {
663 LOG (llevError, "remove_button_linked() in unlinked object.\n"); 661 LOG (llevError, "remove_button_linked() in unlinked object.\n");
664 return; 662 return;
665 } 663 }
664
666 for (obp = op->map->buttons; obp; obp = obp->next) 665 for (obp = op->map->buttons; obp; obp = obp->next)
667 for (olp = &obp->link; (ol = *olp); olp = &ol->next) 666 for (olp = &obp->link; (ol = *olp); olp = &ol->next)
668 if (ol->ob == op) 667 if (ol->ob == op)
669 { 668 {
670 669
671/* 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",
672 obp->value, op->name, op->map->path); 671 obp->value, op->name, op->map->path);
673*/ 672*/
674 *olp = ol->next; 673 *olp = ol->next;
675 free (ol); 674 delete ol;
676 return; 675 return;
677 } 676 }
677
678 LOG (llevError, "remove_button_linked(): couldn't find object.\n"); 678 LOG (llevError, "remove_button_linked(): couldn't find object.\n");
679 CLEAR_FLAG (op, FLAG_IS_LINKED); 679 CLEAR_FLAG (op, FLAG_IS_LINKED);
680} 680}
681 681
682/* 682/*
683 * Gets the objectlink for this connection from the map. 683 * Gets the objectlink for this connection from the map.
684 */ 684 */
685oblinkpt * 685oblinkpt *
686get_connection_links (mapstruct *map, long connection) 686get_connection_links (maptile *map, long connection)
687{ 687{
688 for (oblinkpt * obp = map->buttons; obp; obp = obp->next) 688 for (oblinkpt * obp = map->buttons; obp; obp = obp->next)
689 if (obp->value == connection) 689 if (obp->value == connection)
690 return obp; 690 return obp;
691
691 return 0; 692 return 0;
692} 693}
693 694
694/* 695/*
695 * Return the first objectlink in the objects linked to this one 696 * Return the first objectlink in the objects linked to this one
701 oblinkpt *obp; 702 oblinkpt *obp;
702 objectlink *ol; 703 objectlink *ol;
703 704
704 if (!button->map) 705 if (!button->map)
705 return NULL; 706 return NULL;
707
706 for (obp = button->map->buttons; obp; obp = obp->next) 708 for (obp = button->map->buttons; obp; obp = obp->next)
707 for (ol = obp->link; ol; ol = ol->next) 709 for (ol = obp->link; ol; ol = ol->next)
708 if (ol->ob == button && ol->id == button->count) 710 if (ol->ob == button)
709 return obp; 711 return obp;
712
710 return NULL; 713 return NULL;
711} 714}
712 715
713/* 716/*
714 * Made as a separate function to increase efficiency 717 * Made as a separate function to increase efficiency
722 725
723 if (!button->map) 726 if (!button->map)
724 return 0; 727 return 0;
725 for (obp = button->map->buttons; obp; obp = obp->next) 728 for (obp = button->map->buttons; obp; obp = obp->next)
726 for (ol = obp->link; ol; ol = ol->next) 729 for (ol = obp->link; ol; ol = ol->next)
727 if (ol->ob == button && ol->id == button->count) 730 if (ol->ob == button)
728 return obp->value; 731 return obp->value;
729 return 0; 732 return 0;
730} 733}
731 734
732/* This routine makes monsters who are 735/* This routine makes monsters who are
769 tmp->attack_movement = 0; 772 tmp->attack_movement = 0;
770 /* 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
771 * dereference a null value 774 * dereference a null value
772 */ 775 */
773 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)
774 {
775 tmp->owner->contr->ranges[range_golem] = NULL; 777 tmp->owner->contr->ranges[range_golem] = 0;
776 tmp->owner->contr->golem_count = 0; 778
777 }
778 tmp->owner = 0; 779 tmp->owner = 0;
779 } 780 }
780 break; 781 break;
781 case 1: /* angry -- get neutral monsters mad */ 782 case 1: /* angry -- get neutral monsters mad */
782 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (tmp, FLAG_FRIENDLY)) 783 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (tmp, FLAG_FRIENDLY))
792 break; 793 break;
793 case 4: /* charm all monsters */ 794 case 4: /* charm all monsters */
794 if (op == source) 795 if (op == source)
795 break; /* only if 'connected' */ 796 break; /* only if 'connected' */
796 797
797 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 */
798 tmp2->type != PLAYER; tmp2 = tmp2->above) 799 tmp2->type != PLAYER; tmp2 = tmp2->above)
799 if (tmp2->above == NULL) 800 if (tmp2->above == NULL)
800 break; 801 break;
801 802
802 if (tmp2->type != PLAYER) 803 if (tmp2->type != PLAYER)
803 break; 804 break;
805
804 set_owner (tmp, tmp2); 806 tmp->set_owner (tmp2);
805 SET_FLAG (tmp, FLAG_MONSTER); 807 SET_FLAG (tmp, FLAG_MONSTER);
808
806 tmp->stats.exp = 0; 809 tmp->stats.exp = 0;
807 SET_FLAG (tmp, FLAG_FRIENDLY); 810 SET_FLAG (tmp, FLAG_FRIENDLY);
811
808 add_friendly_object (tmp); 812 add_friendly_object (tmp);
809 tmp->attack_movement = PETMOVE; 813 tmp->attack_movement = PETMOVE;
810 break; 814 break;
811 815
812 default: 816 default:
818 * It will descend through containers to find the object. 822 * It will descend through containers to find the object.
819 * slaying = match object slaying flag 823 * slaying = match object slaying flag
820 * race = match object archetype name flag 824 * race = match object archetype name flag
821 * hp = match object type (excpt type '0'== PLAYER) 825 * hp = match object type (excpt type '0'== PLAYER)
822 */ 826 */
823
824object * 827object *
825check_inv_recursive (object *op, const object *trig) 828check_inv_recursive (object *op, const object *trig)
826{ 829{
827 object *tmp, *ret = NULL; 830 object *tmp, *ret = NULL;
828 831
829 /* First check the object itself. */ 832 /* First check the object itself. */
830 if ((trig->stats.hp && (op->type == trig->stats.hp)) 833 if ((trig->stats.hp && (op->type == trig->stats.hp))
831 || (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)))
832 return op; 836 return op;
833 837
834 for (tmp = op->inv; tmp; tmp = tmp->below) 838 for (tmp = op->inv; tmp; tmp = tmp->below)
835 { 839 {
836 if (tmp->inv) 840 if (tmp->inv)
838 ret = check_inv_recursive (tmp, trig); 842 ret = check_inv_recursive (tmp, trig);
839 if (ret) 843 if (ret)
840 return ret; 844 return ret;
841 } 845 }
842 else if ((trig->stats.hp && (tmp->type == trig->stats.hp)) 846 else if ((trig->stats.hp && (tmp->type == trig->stats.hp))
843 || (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)))
844 return tmp; 849 return tmp;
845 } 850 }
846 return NULL; 851 return NULL;
847} 852}
848 853
851 * the square will activate connected items. 856 * the square will activate connected items.
852 * Monsters can't trigger this square (for now) 857 * Monsters can't trigger this square (for now)
853 * Values are: last_sp = 1/0 obj/no obj triggers 858 * Values are: last_sp = 1/0 obj/no obj triggers
854 * last_heal = 1/0 remove/dont remove obj if triggered 859 * last_heal = 1/0 remove/dont remove obj if triggered
855 * -b.t. (thomas@nomad.astro.psu.edu 860 * -b.t. (thomas@nomad.astro.psu.edu
856 */ 861 *
857 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 */
858void 872void
859check_inv (object *op, object *trig) 873check_inv (object *op, object *trig)
860{ 874{
861 object *match; 875 trig->value = 0; // deactivate if none of the following conditions apply
862 876
863 if (op->type != PLAYER) 877 if (object *pl = trig->ms ().player ())
864 return; 878 {
865 match = check_inv_recursive (op, trig); 879 object *match = check_inv_recursive (pl, trig);
866 if (match && trig->last_sp)
867 {
868 if (trig->last_heal)
869 decrease_ob (match);
870 use_trigger (trig);
871 }
872 else if (!match && !trig->last_sp)
873 use_trigger (trig);
874}
875 880
876 881 if (match && trig->last_sp) // match == having
877/* This does a minimal check of the button link consistency for object
878 * map. All it really does it much sure the object id link that is set
879 * matches what the object has.
880 */
881void
882verify_button_links (const mapstruct *map)
883{
884 oblinkpt *obp;
885 objectlink *ol;
886
887 if (!map)
888 return;
889
890 for (obp = map->buttons; obp; obp = obp->next)
891 {
892 for (ol = obp->link; ol; ol = ol->next)
893 { 882 {
894 if (ol->id != ol->ob->count) 883 if (trig->last_heal)
895 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;
896 } 887 }
888 else if (!match && !trig->last_sp) // match == not having
889 trig->value = 1;
897 } 890 }
891
892 push_button (trig);
898} 893}
894

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines