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.16 by elmex, Tue Dec 19 15:30:01 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);
224 obp = get_button_links (op); 219 obp = get_button_links (op);
225 /* LOG(llevDebug, "update_button: %s (%d)\n", op->name, op->count); */ 220 /* LOG(llevDebug, "update_button: %s (%d)\n", op->name, op->count); */
226 if (obp) 221 if (obp)
227 for (ol = obp->link; ol; ol = ol->next) 222 for (ol = obp->link; ol; ol = ol->next)
228 { 223 {
229 if (!ol->ob || ol->ob->count != ol->id) 224 if (!ol->ob)
230 { 225 {
231 LOG (llevDebug, "Internal error in update_button (%s).\n", &op->name); 226 LOG (llevDebug, "Internal error in update_button (%s).\n", &op->name);
232 continue; 227 continue;
233 } 228 }
229
234 tmp = ol->ob; 230 tmp = ol->ob;
235 if (tmp->type == BUTTON) 231 if (tmp->type == BUTTON)
236 { 232 {
237 for (ab = tmp->above, tot = 0; ab != NULL; ab = ab->above) 233 for (ab = tmp->above, tot = 0; ab != NULL; ab = ab->above)
238 /* Bug? The pedestal code below looks for the head of 234 /* Bug? The pedestal code below looks for the head of
287/* 283/*
288 * Updates every button on the map (by calling update_button() for them). 284 * Updates every button on the map (by calling update_button() for them).
289 */ 285 */
290 286
291void 287void
292update_buttons (mapstruct *m) 288update_buttons (maptile *m)
293{ 289{
294 objectlink *ol; 290 objectlink *ol;
295 oblinkpt *obp; 291 oblinkpt *obp;
296 292
297 for (obp = m->buttons; obp; obp = obp->next) 293 for (obp = m->buttons; obp; obp = obp->next)
298 for (ol = obp->link; ol; ol = ol->next) 294 for (ol = obp->link; ol; ol = ol->next)
299 { 295 {
300 if (!ol->ob || ol->ob->count != ol->id) 296 if (!ol->ob)
301 { 297 {
302 LOG (llevError, "Internal error in update_button (%s (%dx%d):%d, connected %ld).\n", 298 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); 299 ol->ob ? (const char *) ol->ob->name : "null", ol->ob ? ol->ob->x : -1, ol->ob ? ol->ob->y : -1, obp->value);
304 continue; 300 continue;
305 } 301 }
302
306 if (ol->ob->type == BUTTON || ol->ob->type == PEDESTAL) 303 if (ol->ob->type == BUTTON || ol->ob->type == PEDESTAL)
307 { 304 {
308 update_button (ol->ob); 305 update_button (ol->ob);
309 break; 306 break;
310 } 307 }
601 return 0; 598 return 0;
602 } 599 }
603} 600}
604 601
605void 602void
606add_button_link (object *button, mapstruct *map, int connected) 603add_button_link (object *button, maptile *map, int connected)
607{ 604{
608 oblinkpt *obp; 605 oblinkpt *obp;
609 objectlink *ol = get_objectlink (); 606 objectlink *ol = get_objectlink ();
610 607
611 if (!map) 608 if (!map)
620/* LOG(llevDebug,"adding button %s (%d)\n", button->name, connected);*/ 617/* LOG(llevDebug,"adding button %s (%d)\n", button->name, connected);*/
621 618
622 SET_FLAG (button, FLAG_IS_LINKED); 619 SET_FLAG (button, FLAG_IS_LINKED);
623 620
624 ol->ob = button; 621 ol->ob = button;
625 ol->id = button->count;
626 622
627 for (obp = map->buttons; obp && obp->value != connected; obp = obp->next); 623 for (obp = map->buttons; obp && obp->value != connected; obp = obp->next);
628 624
629 if (obp) 625 if (obp)
630 { 626 {
656 if (op->map == NULL) 652 if (op->map == NULL)
657 { 653 {
658 LOG (llevError, "remove_button_link() in object without map.\n"); 654 LOG (llevError, "remove_button_link() in object without map.\n");
659 return; 655 return;
660 } 656 }
657
661 if (!QUERY_FLAG (op, FLAG_IS_LINKED)) 658 if (!QUERY_FLAG (op, FLAG_IS_LINKED))
662 { 659 {
663 LOG (llevError, "remove_button_linked() in unlinked object.\n"); 660 LOG (llevError, "remove_button_linked() in unlinked object.\n");
664 return; 661 return;
665 } 662 }
663
666 for (obp = op->map->buttons; obp; obp = obp->next) 664 for (obp = op->map->buttons; obp; obp = obp->next)
667 for (olp = &obp->link; (ol = *olp); olp = &ol->next) 665 for (olp = &obp->link; (ol = *olp); olp = &ol->next)
668 if (ol->ob == op) 666 if (ol->ob == op)
669 { 667 {
670 668
671/* LOG(llevDebug, "Removed link %d in button %s and map %s.\n", 669/* LOG(llevDebug, "Removed link %d in button %s and map %s.\n",
672 obp->value, op->name, op->map->path); 670 obp->value, op->name, op->map->path);
673*/ 671*/
674 *olp = ol->next; 672 *olp = ol->next;
675 free (ol); 673 delete ol;
676 return; 674 return;
677 } 675 }
676
678 LOG (llevError, "remove_button_linked(): couldn't find object.\n"); 677 LOG (llevError, "remove_button_linked(): couldn't find object.\n");
679 CLEAR_FLAG (op, FLAG_IS_LINKED); 678 CLEAR_FLAG (op, FLAG_IS_LINKED);
680} 679}
681 680
682/* 681/*
683 * Gets the objectlink for this connection from the map. 682 * Gets the objectlink for this connection from the map.
684 */ 683 */
685oblinkpt * 684oblinkpt *
686get_connection_links (mapstruct *map, long connection) 685get_connection_links (maptile *map, long connection)
687{ 686{
688 for (oblinkpt * obp = map->buttons; obp; obp = obp->next) 687 for (oblinkpt * obp = map->buttons; obp; obp = obp->next)
689 if (obp->value == connection) 688 if (obp->value == connection)
690 return obp; 689 return obp;
690
691 return 0; 691 return 0;
692} 692}
693 693
694/* 694/*
695 * Return the first objectlink in the objects linked to this one 695 * Return the first objectlink in the objects linked to this one
701 oblinkpt *obp; 701 oblinkpt *obp;
702 objectlink *ol; 702 objectlink *ol;
703 703
704 if (!button->map) 704 if (!button->map)
705 return NULL; 705 return NULL;
706
706 for (obp = button->map->buttons; obp; obp = obp->next) 707 for (obp = button->map->buttons; obp; obp = obp->next)
707 for (ol = obp->link; ol; ol = ol->next) 708 for (ol = obp->link; ol; ol = ol->next)
708 if (ol->ob == button && ol->id == button->count) 709 if (ol->ob == button)
709 return obp; 710 return obp;
711
710 return NULL; 712 return NULL;
711} 713}
712 714
713/* 715/*
714 * Made as a separate function to increase efficiency 716 * Made as a separate function to increase efficiency
722 724
723 if (!button->map) 725 if (!button->map)
724 return 0; 726 return 0;
725 for (obp = button->map->buttons; obp; obp = obp->next) 727 for (obp = button->map->buttons; obp; obp = obp->next)
726 for (ol = obp->link; ol; ol = ol->next) 728 for (ol = obp->link; ol; ol = ol->next)
727 if (ol->ob == button && ol->id == button->count) 729 if (ol->ob == button)
728 return obp->value; 730 return obp->value;
729 return 0; 731 return 0;
730} 732}
731 733
732/* This routine makes monsters who are 734/* This routine makes monsters who are
769 tmp->attack_movement = 0; 771 tmp->attack_movement = 0;
770 /* lots of checks here, but want to make sure we don't 772 /* lots of checks here, but want to make sure we don't
771 * dereference a null value 773 * dereference a null value
772 */ 774 */
773 if (tmp->type == GOLEM && tmp->owner && tmp->owner->type == PLAYER && tmp->owner->contr->ranges[range_golem] == tmp) 775 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; 776 tmp->owner->contr->ranges[range_golem] = 0;
776 tmp->owner->contr->golem_count = 0; 777
777 }
778 tmp->owner = 0; 778 tmp->owner = 0;
779 } 779 }
780 break; 780 break;
781 case 1: /* angry -- get neutral monsters mad */ 781 case 1: /* angry -- get neutral monsters mad */
782 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (tmp, FLAG_FRIENDLY)) 782 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (tmp, FLAG_FRIENDLY))
799 if (tmp2->above == NULL) 799 if (tmp2->above == NULL)
800 break; 800 break;
801 801
802 if (tmp2->type != PLAYER) 802 if (tmp2->type != PLAYER)
803 break; 803 break;
804 set_owner (tmp, tmp2); 804 tmp->set_owner (tmp2);
805 SET_FLAG (tmp, FLAG_MONSTER); 805 SET_FLAG (tmp, FLAG_MONSTER);
806 tmp->stats.exp = 0; 806 tmp->stats.exp = 0;
807 SET_FLAG (tmp, FLAG_FRIENDLY); 807 SET_FLAG (tmp, FLAG_FRIENDLY);
808 add_friendly_object (tmp); 808 add_friendly_object (tmp);
809 tmp->attack_movement = PETMOVE; 809 tmp->attack_movement = PETMOVE;
826{ 826{
827 object *tmp, *ret = NULL; 827 object *tmp, *ret = NULL;
828 828
829 /* First check the object itself. */ 829 /* First check the object itself. */
830 if ((trig->stats.hp && (op->type == trig->stats.hp)) 830 if ((trig->stats.hp && (op->type == trig->stats.hp))
831 || (trig->slaying && (op->slaying == trig->slaying)) || (trig->race && (op->arch->name == trig->race))) 831 || (trig->slaying && (op->slaying == trig->slaying))
832 || (trig->race && (op->arch->name == trig->race)))
832 return op; 833 return op;
833 834
834 for (tmp = op->inv; tmp; tmp = tmp->below) 835 for (tmp = op->inv; tmp; tmp = tmp->below)
835 { 836 {
836 if (tmp->inv) 837 if (tmp->inv)
838 ret = check_inv_recursive (tmp, trig); 839 ret = check_inv_recursive (tmp, trig);
839 if (ret) 840 if (ret)
840 return ret; 841 return ret;
841 } 842 }
842 else if ((trig->stats.hp && (tmp->type == trig->stats.hp)) 843 else if ((trig->stats.hp && (tmp->type == trig->stats.hp))
843 || (trig->slaying && (tmp->slaying == trig->slaying)) || (trig->race && (tmp->arch->name == trig->race))) 844 || (trig->slaying && (tmp->slaying == trig->slaying))
845 || (trig->race && (tmp->arch->name == trig->race)))
844 return tmp; 846 return tmp;
845 } 847 }
846 return NULL; 848 return NULL;
847} 849}
848 850
851 * the square will activate connected items. 853 * the square will activate connected items.
852 * Monsters can't trigger this square (for now) 854 * Monsters can't trigger this square (for now)
853 * Values are: last_sp = 1/0 obj/no obj triggers 855 * Values are: last_sp = 1/0 obj/no obj triggers
854 * last_heal = 1/0 remove/dont remove obj if triggered 856 * last_heal = 1/0 remove/dont remove obj if triggered
855 * -b.t. (thomas@nomad.astro.psu.edu 857 * -b.t. (thomas@nomad.astro.psu.edu
858 *
859 * Tue Dec 19 15:34:00 CET 2006 elmex: changed the function to ignore op
860 * because the check-inventory semantic essentially only applies when
861 * something is above the inventory checker.
862 * The semantic prior this change was: trigger if something has moved on or off
863 * and has a matching item. Imagine what happens if someone steps on the inventory
864 * checker with a matching item, has it, activates the connection, throws the item
865 * away, and then leaves the inventory checker. That would've caused an always-enabled
866 * state in the inventory checker. This won't happen anymore now.
867 *
856 */ 868 */
857 869
858void 870void
859check_inv (object *op, object *trig) 871check_inv (object *op, object *trig)
860{ 872{
861 object *match; 873 object *match = 0;
862 874
875 trig->value = 0; // deactivate if none of the following conditions apply
876
877 for (object *tmp = trig->above; tmp; tmp = tmp->above)
863 if (op->type != PLAYER) 878 if (tmp->type == PLAYER)
864 return;
865 match = check_inv_recursive (op, trig);
866 if (match && trig->last_sp)
867 { 879 {
880 object *match = check_inv_recursive (tmp, trig);
881
882 if (match && trig->last_sp) // match == having
883 {
868 if (trig->last_heal) 884 if (trig->last_heal)
869 decrease_ob (match); 885 decrease_ob (match);
870 use_trigger (trig);
871 }
872 else if (!match && !trig->last_sp)
873 use_trigger (trig);
874}
875 886
876 887 trig->value = 1;
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 {
894 if (ol->id != ol->ob->count)
895 LOG (llevError, "verify_button_links: object %s on list is corrupt (%d!=%d)\n", &ol->ob->name, ol->id, ol->ob->count);
896 } 888 }
889 else if (!match && !trig->last_sp) // match == not having
890 trig->value = 1;
891
892 break;
897 } 893 }
894
895 push_button (trig);
898} 896}
897

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines