… | |
… | |
35 | * 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. |
36 | */ |
36 | */ |
37 | void |
37 | void |
38 | activate_connection_link (objectlink * ol, bool state, object *source = 0) |
38 | activate_connection_link (objectlink * ol, bool state, object *source = 0) |
39 | { |
39 | { |
40 | object *tmp = 0; |
|
|
41 | |
|
|
42 | for (; ol; ol = ol->next) |
40 | for (; ol; ol = ol->next) |
43 | { |
41 | { |
44 | if (!ol->ob) |
42 | if (!ol->ob) |
45 | { |
43 | { |
46 | LOG (llevError, "Internal error in activate_connection_link.\n"); |
44 | LOG (llevError, "Internal error in activate_connection_link.\n"); |
… | |
… | |
55 | * 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. |
56 | */ |
54 | */ |
57 | |
55 | |
58 | if (QUERY_FLAG (ol->ob, FLAG_FREED)) |
56 | if (QUERY_FLAG (ol->ob, FLAG_FREED)) |
59 | return; |
57 | return; |
|
|
58 | |
60 | tmp = ol->ob; |
59 | object *tmp = ol->ob; |
61 | |
60 | |
62 | /* if the criteria isn't appropriate, don't do anything */ |
61 | /* if the criteria isn't appropriate, don't do anything */ |
63 | if (state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_PUSH)) |
62 | if (state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_PUSH)) |
64 | continue; |
63 | continue; |
65 | if (!state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_RELEASE)) |
64 | if (!state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_RELEASE)) |
66 | continue; |
65 | continue; |
67 | |
66 | |
68 | switch (tmp->type) |
67 | switch (tmp->type) |
69 | { |
68 | { |
70 | case GATE: |
69 | case GATE: |
71 | case HOLE: |
70 | case HOLE: |
72 | tmp->value = tmp->stats.maxsp ? !state : state; |
71 | tmp->value = tmp->stats.maxsp ? !state : state; |
73 | tmp->speed = 0.5; |
72 | tmp->speed = 0.5; |
74 | update_ob_speed (tmp); |
73 | update_ob_speed (tmp); |
75 | break; |
74 | break; |
76 | |
75 | |
77 | case CF_HANDLE: |
76 | case CF_HANDLE: |
78 | SET_ANIMATION (tmp, (tmp->value = tmp->stats.maxsp ? !state : state)); |
77 | SET_ANIMATION (tmp, (tmp->value = tmp->stats.maxsp ? !state : state)); |
79 | update_object (tmp, UP_OBJ_FACE); |
78 | update_object (tmp, UP_OBJ_FACE); |
80 | break; |
79 | break; |
81 | |
80 | |
82 | case SIGN: |
81 | case SIGN: |
83 | if (!tmp->stats.food || tmp->last_eat < tmp->stats.food) |
82 | if (!tmp->stats.food || tmp->last_eat < tmp->stats.food) |
84 | { |
83 | { |
85 | new_info_map (NDI_UNIQUE | NDI_NAVY, tmp->map, tmp->msg); |
84 | new_info_map (NDI_UNIQUE | NDI_NAVY, tmp->map, tmp->msg); |
86 | if (tmp->stats.food) |
85 | if (tmp->stats.food) |
87 | tmp->last_eat++; |
86 | tmp->last_eat++; |
88 | } |
87 | } |
89 | break; |
88 | break; |
90 | |
89 | |
91 | case ALTAR: |
90 | case ALTAR: |
92 | tmp->value = 1; |
91 | tmp->value = 1; |
93 | SET_ANIMATION (tmp, tmp->value); |
92 | SET_ANIMATION (tmp, tmp->value); |
94 | update_object (tmp, UP_OBJ_FACE); |
93 | update_object (tmp, UP_OBJ_FACE); |
95 | break; |
94 | break; |
96 | |
95 | |
97 | case BUTTON: |
96 | case BUTTON: |
98 | case PEDESTAL: |
97 | case PEDESTAL: |
99 | tmp->value = state; |
98 | tmp->value = state; |
100 | SET_ANIMATION (tmp, tmp->value); |
99 | SET_ANIMATION (tmp, tmp->value); |
101 | update_object (tmp, UP_OBJ_FACE); |
100 | update_object (tmp, UP_OBJ_FACE); |
102 | break; |
101 | break; |
103 | |
102 | |
104 | case MOOD_FLOOR: |
103 | case MOOD_FLOOR: |
105 | do_mood_floor (tmp, source); |
104 | do_mood_floor (tmp, source); |
106 | break; |
105 | break; |
107 | |
106 | |
108 | case TIMED_GATE: |
107 | case TIMED_GATE: |
109 | tmp->speed = tmp->arch->clone.speed; |
108 | tmp->speed = tmp->arch->clone.speed; |
110 | update_ob_speed (tmp); /* original values */ |
109 | update_ob_speed (tmp); /* original values */ |
111 | tmp->value = tmp->arch->clone.value; |
110 | tmp->value = tmp->arch->clone.value; |
112 | tmp->stats.sp = 1; |
111 | tmp->stats.sp = 1; |
113 | tmp->stats.hp = tmp->stats.maxhp; |
112 | tmp->stats.hp = tmp->stats.maxhp; |
114 | /* Handle multipart gates. We copy the value for the other parts |
113 | /* Handle multipart gates. We copy the value for the other parts |
115 | * from the head - this ensures that the data will consistent |
114 | * from the head - this ensures that the data will consistent |
116 | */ |
115 | */ |
117 | for (tmp = tmp->more; tmp != NULL; tmp = tmp->more) |
116 | for (tmp = tmp->more; tmp != NULL; tmp = tmp->more) |
118 | { |
117 | { |
119 | tmp->speed = tmp->head->speed; |
118 | tmp->speed = tmp->head->speed; |
120 | tmp->value = tmp->head->value; |
119 | tmp->value = tmp->head->value; |
121 | tmp->stats.sp = tmp->head->stats.sp; |
120 | tmp->stats.sp = tmp->head->stats.sp; |
122 | tmp->stats.hp = tmp->head->stats.hp; |
121 | tmp->stats.hp = tmp->head->stats.hp; |
123 | update_ob_speed (tmp); |
122 | update_ob_speed (tmp); |
124 | } |
123 | } |
125 | break; |
124 | break; |
126 | |
125 | |
127 | case DIRECTOR: |
126 | case DIRECTOR: |
128 | case FIREWALL: |
127 | case FIREWALL: |
129 | if (!QUERY_FLAG (tmp, FLAG_ANIMATE) && tmp->type == FIREWALL) |
128 | if (!QUERY_FLAG (tmp, FLAG_ANIMATE) && tmp->type == FIREWALL) |
130 | move_firewall (tmp); |
129 | move_firewall (tmp); |
131 | else |
130 | else |
132 | { |
131 | { |
133 | if ((tmp->stats.sp += tmp->stats.maxsp) > 8) /* next direction */ |
132 | if ((tmp->stats.sp += tmp->stats.maxsp) > 8) /* next direction */ |
134 | tmp->stats.sp = ((tmp->stats.sp - 1) % 8) + 1; |
133 | tmp->stats.sp = ((tmp->stats.sp - 1) % 8) + 1; |
135 | animate_turning (tmp); |
134 | animate_turning (tmp); |
136 | } |
135 | } |
137 | break; |
136 | break; |
138 | |
137 | |
139 | case TELEPORTER: |
138 | case TELEPORTER: |
140 | move_teleporter (tmp); |
139 | move_teleporter (tmp); |
141 | break; |
140 | break; |
142 | |
141 | |
143 | case CREATOR: |
142 | case CREATOR: |
144 | move_creator (tmp); |
143 | move_creator (tmp); |
145 | break; |
144 | break; |
146 | |
145 | |
147 | case TRIGGER_MARKER: |
146 | case TRIGGER_MARKER: |
148 | move_marker (tmp); |
147 | move_marker (tmp); |
149 | break; |
148 | break; |
150 | |
149 | |
151 | case DUPLICATOR: |
150 | case DUPLICATOR: |
152 | move_duplicator (tmp); |
151 | move_duplicator (tmp); |
153 | break; |
152 | break; |
154 | } |
153 | } |
155 | } |
154 | } |
156 | } |
155 | } |
157 | |
156 | |
158 | /* |
157 | /* |
… | |
… | |
205 | * Updates everything connected with the button op. |
204 | * Updates everything connected with the button op. |
206 | * After changing the state of a button, this function must be called |
205 | * After changing the state of a button, this function must be called |
207 | * to make sure that all gates and other buttons connected to the |
206 | * to make sure that all gates and other buttons connected to the |
208 | * button reacts to the (eventual) change of state. |
207 | * button reacts to the (eventual) change of state. |
209 | */ |
208 | */ |
210 | |
|
|
211 | void |
209 | void |
212 | update_button (object *op) |
210 | update_button (object *op) |
213 | { |
211 | { |
214 | object *ab, *tmp, *head; |
212 | object *ab, *tmp, *head; |
215 | int tot, any_down = 0, old_value = op->value; |
213 | int tot, any_down = 0, old_value = op->value; |
… | |
… | |
354 | ARCH_SACRIFICE (altar) == sacrifice->name || |
352 | ARCH_SACRIFICE (altar) == sacrifice->name || |
355 | ARCH_SACRIFICE (altar) == sacrifice->slaying || |
353 | ARCH_SACRIFICE (altar) == sacrifice->slaying || |
356 | (!strcmp (ARCH_SACRIFICE (altar), query_base_name (sacrifice, 0)))) |
354 | (!strcmp (ARCH_SACRIFICE (altar), query_base_name (sacrifice, 0)))) |
357 | && NROF_SACRIFICE (altar) <= (sacrifice->nrof ? sacrifice->nrof : 1)) |
355 | && NROF_SACRIFICE (altar) <= (sacrifice->nrof ? sacrifice->nrof : 1)) |
358 | return 1; |
356 | return 1; |
|
|
357 | |
359 | if (strcmp (ARCH_SACRIFICE (altar), "money") == 0 |
358 | if (strcmp (ARCH_SACRIFICE (altar), "money") == 0 |
360 | && sacrifice->type == MONEY && sacrifice->nrof * sacrifice->value >= NROF_SACRIFICE (altar)) |
359 | && sacrifice->type == MONEY && sacrifice->nrof * sacrifice->value >= NROF_SACRIFICE (altar)) |
361 | return 1; |
360 | return 1; |
362 | } |
361 | } |
|
|
362 | |
363 | return 0; |
363 | return 0; |
364 | } |
364 | } |
365 | |
365 | |
366 | /* |
366 | /* |
367 | * operate_altar checks if sacrifice was accepted and removes sacrificed |
367 | * operate_altar checks if sacrifice was accepted and removes sacrificed |
… | |
… | |
608 | if (!map) |
608 | if (!map) |
609 | { |
609 | { |
610 | LOG (llevError, "Tried to add button-link without map.\n"); |
610 | LOG (llevError, "Tried to add button-link without map.\n"); |
611 | return; |
611 | return; |
612 | } |
612 | } |
613 | if (!editor) |
613 | |
614 | button->path_attuned = connected; /* peterm: I need this so I can rebuild |
614 | button->path_attuned = connected; /* peterm: I need this so I can rebuild |
615 | a connected map from a template map. */ |
615 | a connected map from a template map. */ |
616 | |
|
|
617 | /* LOG(llevDebug,"adding button %s (%d)\n", button->name, connected);*/ |
|
|
618 | |
616 | |
619 | SET_FLAG (button, FLAG_IS_LINKED); |
617 | SET_FLAG (button, FLAG_IS_LINKED); |
620 | |
618 | |
621 | ol->ob = button; |
619 | ol->ob = button; |
622 | |
620 | |
623 | for (obp = map->buttons; obp && obp->value != connected; obp = obp->next); |
621 | for (obp = map->buttons; obp && obp->value != connected; obp = obp->next) |
|
|
622 | ; |
624 | |
623 | |
625 | if (obp) |
624 | if (obp) |
626 | { |
625 | { |
627 | ol->next = obp->link; |
626 | ol->next = obp->link; |
628 | obp->link = ol; |
627 | obp->link = ol; |
… | |
… | |
771 | tmp->attack_movement = 0; |
770 | tmp->attack_movement = 0; |
772 | /* lots of checks here, but want to make sure we don't |
771 | /* lots of checks here, but want to make sure we don't |
773 | * dereference a null value |
772 | * dereference a null value |
774 | */ |
773 | */ |
775 | if (tmp->type == GOLEM && tmp->owner && tmp->owner->type == PLAYER && tmp->owner->contr->ranges[range_golem] == tmp) |
774 | if (tmp->type == GOLEM && tmp->owner && tmp->owner->type == PLAYER && tmp->owner->contr->ranges[range_golem] == tmp) |
776 | { |
|
|
777 | tmp->owner->contr->ranges[range_golem] = NULL; |
775 | tmp->owner->contr->ranges[range_golem] = 0; |
778 | tmp->owner->contr->golem_count = 0; |
776 | |
779 | } |
|
|
780 | tmp->owner = 0; |
777 | tmp->owner = 0; |
781 | } |
778 | } |
782 | break; |
779 | break; |
783 | case 1: /* angry -- get neutral monsters mad */ |
780 | case 1: /* angry -- get neutral monsters mad */ |
784 | if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (tmp, FLAG_FRIENDLY)) |
781 | if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (tmp, FLAG_FRIENDLY)) |
… | |
… | |
794 | break; |
791 | break; |
795 | case 4: /* charm all monsters */ |
792 | case 4: /* charm all monsters */ |
796 | if (op == source) |
793 | if (op == source) |
797 | break; /* only if 'connected' */ |
794 | break; /* only if 'connected' */ |
798 | |
795 | |
799 | for (tmp2 = get_map_ob (source->map, source->x, source->y); /* finding an owner */ |
796 | for (tmp2 = GET_MAP_OB (source->map, source->x, source->y); /* finding an owner */ |
800 | tmp2->type != PLAYER; tmp2 = tmp2->above) |
797 | tmp2->type != PLAYER; tmp2 = tmp2->above) |
801 | if (tmp2->above == NULL) |
798 | if (tmp2->above == NULL) |
802 | break; |
799 | break; |
803 | |
800 | |
804 | if (tmp2->type != PLAYER) |
801 | if (tmp2->type != PLAYER) |
805 | break; |
802 | break; |
|
|
803 | |
806 | set_owner (tmp, tmp2); |
804 | tmp->set_owner (tmp2); |
807 | SET_FLAG (tmp, FLAG_MONSTER); |
805 | SET_FLAG (tmp, FLAG_MONSTER); |
|
|
806 | |
808 | tmp->stats.exp = 0; |
807 | tmp->stats.exp = 0; |
809 | SET_FLAG (tmp, FLAG_FRIENDLY); |
808 | SET_FLAG (tmp, FLAG_FRIENDLY); |
|
|
809 | |
810 | add_friendly_object (tmp); |
810 | add_friendly_object (tmp); |
811 | tmp->attack_movement = PETMOVE; |
811 | tmp->attack_movement = PETMOVE; |
812 | break; |
812 | break; |
813 | |
813 | |
814 | default: |
814 | default: |
… | |
… | |
820 | * It will descend through containers to find the object. |
820 | * It will descend through containers to find the object. |
821 | * slaying = match object slaying flag |
821 | * slaying = match object slaying flag |
822 | * race = match object archetype name flag |
822 | * race = match object archetype name flag |
823 | * hp = match object type (excpt type '0'== PLAYER) |
823 | * hp = match object type (excpt type '0'== PLAYER) |
824 | */ |
824 | */ |
825 | |
|
|
826 | object * |
825 | object * |
827 | check_inv_recursive (object *op, const object *trig) |
826 | check_inv_recursive (object *op, const object *trig) |
828 | { |
827 | { |
829 | object *tmp, *ret = NULL; |
828 | object *tmp, *ret = NULL; |
830 | |
829 | |
831 | /* First check the object itself. */ |
830 | /* First check the object itself. */ |
832 | if ((trig->stats.hp && (op->type == trig->stats.hp)) |
831 | if ((trig->stats.hp && (op->type == trig->stats.hp)) |
833 | || (trig->slaying && (op->slaying == trig->slaying)) || (trig->race && (op->arch->name == trig->race))) |
832 | || (trig->slaying && (op->slaying == trig->slaying)) |
|
|
833 | || (trig->race && (op->arch->name == trig->race))) |
834 | return op; |
834 | return op; |
835 | |
835 | |
836 | for (tmp = op->inv; tmp; tmp = tmp->below) |
836 | for (tmp = op->inv; tmp; tmp = tmp->below) |
837 | { |
837 | { |
838 | if (tmp->inv) |
838 | if (tmp->inv) |
… | |
… | |
840 | ret = check_inv_recursive (tmp, trig); |
840 | ret = check_inv_recursive (tmp, trig); |
841 | if (ret) |
841 | if (ret) |
842 | return ret; |
842 | return ret; |
843 | } |
843 | } |
844 | else if ((trig->stats.hp && (tmp->type == trig->stats.hp)) |
844 | else if ((trig->stats.hp && (tmp->type == trig->stats.hp)) |
845 | || (trig->slaying && (tmp->slaying == trig->slaying)) || (trig->race && (tmp->arch->name == trig->race))) |
845 | || (trig->slaying && (tmp->slaying == trig->slaying)) |
|
|
846 | || (trig->race && (tmp->arch->name == trig->race))) |
846 | return tmp; |
847 | return tmp; |
847 | } |
848 | } |
848 | return NULL; |
849 | return NULL; |
849 | } |
850 | } |
850 | |
851 | |
… | |
… | |
853 | * the square will activate connected items. |
854 | * the square will activate connected items. |
854 | * Monsters can't trigger this square (for now) |
855 | * Monsters can't trigger this square (for now) |
855 | * Values are: last_sp = 1/0 obj/no obj triggers |
856 | * Values are: last_sp = 1/0 obj/no obj triggers |
856 | * last_heal = 1/0 remove/dont remove obj if triggered |
857 | * last_heal = 1/0 remove/dont remove obj if triggered |
857 | * -b.t. (thomas@nomad.astro.psu.edu |
858 | * -b.t. (thomas@nomad.astro.psu.edu |
858 | */ |
859 | * |
859 | |
860 | * Tue Dec 19 15:34:00 CET 2006 elmex: changed the function to ignore op |
|
|
861 | * because the check-inventory semantic essentially only applies when |
|
|
862 | * something is above the inventory checker. |
|
|
863 | * The semantic prior this change was: trigger if something has moved on or off |
|
|
864 | * and has a matching item. Imagine what happens if someone steps on the inventory |
|
|
865 | * checker with a matching item, has it, activates the connection, throws the item |
|
|
866 | * away, and then leaves the inventory checker. That would've caused an always-enabled |
|
|
867 | * state in the inventory checker. This won't happen anymore now. |
|
|
868 | * |
|
|
869 | */ |
860 | void |
870 | void |
861 | check_inv (object *op, object *trig) |
871 | check_inv (object *op, object *trig) |
862 | { |
872 | { |
863 | object *match; |
873 | trig->value = 0; // deactivate if none of the following conditions apply |
864 | |
874 | |
865 | if (op->type != PLAYER) |
875 | if (object *pl = trig->ms ().player ()) |
866 | return; |
876 | { |
867 | match = check_inv_recursive (op, trig); |
877 | object *match = check_inv_recursive (pl, trig); |
868 | if (match && trig->last_sp) |
878 | |
869 | { |
879 | if (match && trig->last_sp) // match == having |
|
|
880 | { |
870 | if (trig->last_heal) |
881 | if (trig->last_heal) |
871 | decrease_ob (match); |
882 | decrease_ob (match); |
872 | use_trigger (trig); |
|
|
873 | } |
|
|
874 | else if (!match && !trig->last_sp) |
|
|
875 | use_trigger (trig); |
|
|
876 | } |
|
|
877 | |
883 | |
|
|
884 | trig->value = 1; |
|
|
885 | } |
|
|
886 | else if (!match && !trig->last_sp) // match == not having |
|
|
887 | trig->value = 1; |
|
|
888 | } |
|
|
889 | |
|
|
890 | push_button (trig); |
|
|
891 | } |
|
|
892 | |