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.2 by root, Tue Aug 29 08:01:35 2006 UTC vs.
Revision 1.20 by root, Tue Dec 26 08:54:58 2006 UTC

1/*
2 * static char *rcsid_button_c =
3 * "$Id: button.C,v 1.2 2006/08/29 08:01:35 root Exp $";
4 */
5
6/* 1/*
7 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
8 3
9 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
10 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
21 16
22 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
23 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 20
26 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>
27*/ 22*/
28 23
29#include <global.h> 24#include <global.h>
30#include <funcpoint.h> 25#include <funcpoint.h>
31 26
32/* 27/*
33 * This code is no longer highly inefficient 8) 28 * This code is no longer highly inefficient 8)
34 */ 29 */
35 30
36/* 31/*
32 * elmex:
33 * This function takes a objectlink list with all the objects are going to be activated.
34 * state is a true/false flag that will actiavte objects that have FLAG_ACTIVATE_ON_PUSH/RELEASE set.
35 * The source argument can be 0 or the source object for this activation.
36 */
37void
38activate_connection_link (objectlink * ol, bool state, object *source = 0)
39{
40 for (; ol; ol = ol->next)
41 {
42 if (!ol->ob)
43 {
44 LOG (llevError, "Internal error in activate_connection_link.\n");
45 continue;
46 }
47
48 /* a button link object can become freed when the map is saving. As
49 * a map is saved, objects are removed and freed, and if an object is
50 * on top of a button, this function is eventually called. If a map
51 * is getting moved out of memory, the status of buttons and levers
52 * probably isn't important - it will get sorted out when the map is
53 * re-loaded. As such, just exit this function if that is the case.
54 */
55
56 if (QUERY_FLAG (ol->ob, FLAG_FREED))
57 return;
58
59 object *tmp = ol->ob;
60
61 /* if the criteria isn't appropriate, don't do anything */
62 if (state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_PUSH))
63 continue;
64 if (!state && !QUERY_FLAG (tmp, FLAG_ACTIVATE_ON_RELEASE))
65 continue;
66
67 switch (tmp->type)
68 {
69 case GATE:
70 case HOLE:
71 tmp->value = tmp->stats.maxsp ? !state : state;
72 tmp->set_speed (0.5);
73 break;
74
75 case CF_HANDLE:
76 SET_ANIMATION (tmp, (tmp->value = tmp->stats.maxsp ? !state : state));
77 update_object (tmp, UP_OBJ_FACE);
78 break;
79
80 case SIGN:
81 if (!tmp->stats.food || tmp->last_eat < tmp->stats.food)
82 {
83 new_info_map (NDI_UNIQUE | NDI_NAVY, tmp->map, tmp->msg);
84 if (tmp->stats.food)
85 tmp->last_eat++;
86 }
87 break;
88
89 case ALTAR:
90 tmp->value = 1;
91 SET_ANIMATION (tmp, tmp->value);
92 update_object (tmp, UP_OBJ_FACE);
93 break;
94
95 case BUTTON:
96 case PEDESTAL:
97 tmp->value = state;
98 SET_ANIMATION (tmp, tmp->value);
99 update_object (tmp, UP_OBJ_FACE);
100 break;
101
102 case MOOD_FLOOR:
103 do_mood_floor (tmp, source);
104 break;
105
106 case TIMED_GATE:
107 tmp->set_speed (tmp->arch->clone.speed);
108 tmp->value = tmp->arch->clone.value;
109 tmp->stats.sp = 1;
110 tmp->stats.hp = tmp->stats.maxhp;
111 /* Handle multipart gates. We copy the value for the other parts
112 * from the head - this ensures that the data will consistent
113 */
114 for (tmp = tmp->more; tmp; tmp = tmp->more)
115 {
116 tmp->value = tmp->head->value;
117 tmp->stats.sp = tmp->head->stats.sp;
118 tmp->stats.hp = tmp->head->stats.hp;
119 tmp->set_speed (tmp->head->speed);
120 }
121 break;
122
123 case DIRECTOR:
124 case FIREWALL:
125 if (!QUERY_FLAG (tmp, FLAG_ANIMATE) && tmp->type == FIREWALL)
126 move_firewall (tmp);
127 else
128 {
129 if ((tmp->stats.sp += tmp->stats.maxsp) > 8) /* next direction */
130 tmp->stats.sp = ((tmp->stats.sp - 1) % 8) + 1;
131 animate_turning (tmp);
132 }
133 break;
134
135 case TELEPORTER:
136 move_teleporter (tmp);
137 break;
138
139 case CREATOR:
140 move_creator (tmp);
141 break;
142
143 case TRIGGER_MARKER:
144 move_marker (tmp);
145 break;
146
147 case DUPLICATOR:
148 move_duplicator (tmp);
149 break;
150 }
151 }
152}
153
154/*
155 * elmex:
156 * This is the new push_button function, it got split up so that
157 * you can activate connections without a button now!
158 * old but still valid comment:
159 *
37 * Push the specified object. This can affect other buttons/gates/handles 160 * Push the specified object. This can affect other buttons/gates/handles
38 * altars/pedestals/holes in the whole map. 161 * altars/pedestals/holes in the whole map.
39 * Changed the routine to loop through _all_ objects. 162 * Changed the routine to loop through _all_ objects.
40 * Better hurry with that linked list... 163 * Better hurry with that linked list...
41 */ 164 *
42 165 */
166void
43void push_button(object *op) { 167push_button (object *op)
44 object *tmp; 168{
45 objectlink *ol; 169 oblinkpt *obp = get_button_links (op);
46 170
47/* LOG(llevDebug, "push_button: %s (%d)\n", op->name, op->count); */ 171 if (!obp)
48 for (ol = get_button_links(op); ol; ol = ol->next) { 172 return;
49 if (!ol->ob || ol->ob->count != ol->id) {
50 LOG(llevError, "Internal error in push_button (%s).\n", op->name);
51 continue;
52 }
53 /* a button link object can become freed when the map is saving. As
54 * a map is saved, objects are removed and freed, and if an object is
55 * on top of a button, this function is eventually called. If a map
56 * is getting moved out of memory, the status of buttons and levers
57 * probably isn't important - it will get sorted out when the map is
58 * re-loaded. As such, just exit this function if that is the case.
59 */
60
61 if (QUERY_FLAG(ol->ob, FLAG_FREED)) return;
62 tmp = ol->ob;
63 173
64 /* if the criteria isn't appropriate, don't do anything */ 174 if (INVOKE_MAP (TRIGGER, op->map, ARG_INT64 (obp->value), ARG_INT (op->value)))
65 if (op->value && !QUERY_FLAG(tmp, FLAG_ACTIVATE_ON_PUSH)) continue; 175 return;
66 if (!op->value && !QUERY_FLAG(tmp, FLAG_ACTIVATE_ON_RELEASE)) continue;
67 176
68 switch(tmp->type) { 177 activate_connection_link (obp->link, op->value, op);
178}
69 179
70 case GATE: 180/*
71 case HOLE: 181 * elmex:
72 tmp->value=tmp->stats.maxsp?!op->value:op->value; 182 * This activates a connection, similar to push_button (object *op) but it takes
73 tmp->speed=0.5; 183 * only a map, a connection value and a true or false flag that indicated whether
74 update_ob_speed(tmp); 184 * the connection was 'state' or 'released'. So that you can activate objects
75 break; 185 * who have FLAG_ACTIVATE_ON_PUSH/RELEASE set properly.
186 *
187 */
188void
189activate_connection (maptile *map, long connection, bool state)
190{
191 if (INVOKE_MAP (TRIGGER, map, ARG_INT64 (connection), ARG_INT (state)))
192 return;
76 193
77 case CF_HANDLE: 194 oblinkpt *obp = get_connection_links (map, connection);
78 SET_ANIMATION(tmp, (tmp->value=tmp->stats.maxsp?!op->value:op->value));
79 update_object(tmp,UP_OBJ_FACE);
80 break;
81 195
82 case SIGN: 196 if (obp)
83 if (!tmp->stats.food || tmp->last_eat < tmp->stats.food) { 197 activate_connection_link (obp->link, state);
84 new_info_map(NDI_UNIQUE | NDI_NAVY,tmp->map,tmp->msg);
85 if (tmp->stats.food) tmp->last_eat++;
86 }
87 break;
88
89 case ALTAR:
90 tmp->value = 1;
91 SET_ANIMATION(tmp, tmp->value);
92 update_object(tmp,UP_OBJ_FACE);
93 break;
94
95 case BUTTON:
96 case PEDESTAL:
97 tmp->value=op->value;
98 SET_ANIMATION(tmp, tmp->value);
99 update_object(tmp,UP_OBJ_FACE);
100 break;
101
102 case MOOD_FLOOR:
103 do_mood_floor(tmp, op);
104 break;
105
106 case TIMED_GATE:
107 tmp->speed = tmp->arch->clone.speed;
108 update_ob_speed(tmp); /* original values */
109 tmp->value = tmp->arch->clone.value;
110 tmp->stats.sp = 1;
111 tmp->stats.hp = tmp->stats.maxhp;
112 /* Handle multipart gates. We copy the value for the other parts
113 * from the head - this ensures that the data will consistent
114 */
115 for (tmp=tmp->more; tmp!=NULL; tmp=tmp->more) {
116 tmp->speed = tmp->head->speed;
117 tmp->value = tmp->head->value;
118 tmp->stats.sp = tmp->head->stats.sp;
119 tmp->stats.hp = tmp->head->stats.hp;
120 update_ob_speed(tmp);
121 }
122 break;
123
124 case DIRECTOR:
125 case FIREWALL:
126 if(!QUERY_FLAG(tmp,FLAG_ANIMATE)&&tmp->type==FIREWALL) move_firewall(tmp);
127 else {
128 if ((tmp->stats.sp += tmp->stats.maxsp) > 8) /* next direction */
129 tmp->stats.sp = ((tmp->stats.sp-1)%8)+1;
130 animate_turning(tmp);
131 }
132 break;
133
134 case TELEPORTER:
135 move_teleporter(tmp);
136 break;
137
138 case CREATOR:
139 move_creator(tmp);
140 break;
141
142 case TRIGGER_MARKER:
143 move_marker(tmp);
144 break;
145
146 case DUPLICATOR:
147 move_duplicator(tmp);
148 break;
149 }
150 }
151} 198}
152 199
153/* 200/*
154 * Updates everything connected with the button op. 201 * Updates everything connected with the button op.
155 * After changing the state of a button, this function must be called 202 * After changing the state of a button, this function must be called
156 * to make sure that all gates and other buttons connected to the 203 * to make sure that all gates and other buttons connected to the
157 * button reacts to the (eventual) change of state. 204 * button reacts to the (eventual) change of state.
158 */ 205 */
159 206void
160void update_button(object *op) { 207update_button (object *op)
208{
161 object *ab,*tmp,*head; 209 object *ab, *tmp, *head;
162 int tot,any_down=0, old_value=op->value; 210 int tot, any_down = 0, old_value = op->value;
211 oblinkpt *obp = 0;
163 objectlink *ol; 212 objectlink *ol;
164 213
214 obp = get_button_links (op);
165 /* LOG(llevDebug, "update_button: %s (%d)\n", op->name, op->count); */ 215 /* LOG(llevDebug, "update_button: %s (%d)\n", op->name, op->count); */
216 if (obp)
166 for (ol = get_button_links(op); ol; ol = ol->next) { 217 for (ol = obp->link; ol; ol = ol->next)
167 if (!ol->ob || ol->ob->count != ol->id) { 218 {
219 if (!ol->ob)
220 {
168 LOG(llevDebug, "Internal error in update_button (%s).\n", op->name); 221 LOG (llevDebug, "Internal error in update_button (%s).\n", &op->name);
169 continue; 222 continue;
170 } 223 }
224
171 tmp = ol->ob; 225 tmp = ol->ob;
172 if (tmp->type==BUTTON) { 226 if (tmp->type == BUTTON)
227 {
173 for(ab=tmp->above,tot=0;ab!=NULL;ab=ab->above) 228 for (ab = tmp->above, tot = 0; ab != NULL; ab = ab->above)
174 /* Bug? The pedestal code below looks for the head of 229 /* Bug? The pedestal code below looks for the head of
175 * the object, this bit doesn't. I'd think we should check 230 * the object, this bit doesn't. I'd think we should check
176 * for head here also. Maybe it also makese sense to 231 * for head here also. Maybe it also makese sense to
177 * make the for ab=tmp->above loop common, and alter 232 * make the for ab=tmp->above loop common, and alter
178 * behaviour based on object within that loop? 233 * behaviour based on object within that loop?
179 */ 234 */
180 235
181 /* Basically, if the move_type matches that on what the 236 /* Basically, if the move_type matches that on what the
182 * button wants, we count it. The second check is so that 237 * button wants, we count it. The second check is so that
183 * objects don't move (swords, etc) will count. Note that 238 * objects don't move (swords, etc) will count. Note that
184 * this means that more work is needed to make buttons 239 * this means that more work is needed to make buttons
185 * that are only triggered by flying objects. 240 * that are only triggered by flying objects.
186 */ 241 */
187 if ((ab->move_type & tmp->move_on) || ab->move_type==0 ) 242 if ((ab->move_type & tmp->move_on) || ab->move_type == 0)
188 tot+=ab->weight*(ab->nrof?ab->nrof:1)+ab->carrying; 243 tot += ab->weight * (ab->nrof ? ab->nrof : 1) + ab->carrying;
189 244
190 tmp->value=(tot>=tmp->weight)?1:0; 245 tmp->value = (tot >= tmp->weight) ? 1 : 0;
191 if(tmp->value) 246 if (tmp->value)
192 any_down=1; 247 any_down = 1;
248 }
193 } else if (tmp->type == PEDESTAL) { 249 else if (tmp->type == PEDESTAL)
250 {
194 tmp->value = 0; 251 tmp->value = 0;
195 for(ab=tmp->above; ab!=NULL; ab=ab->above) { 252 for (ab = tmp->above; ab != NULL; ab = ab->above)
253 {
196 head = ab->head ? ab->head : ab; 254 head = ab->head ? ab->head : ab;
197 /* Same note regarding move_type for buttons above apply here. */ 255 /* Same note regarding move_type for buttons above apply here. */
198 if ( ((head->move_type & tmp->move_on) || ab->move_type==0) && 256 if (((head->move_type & tmp->move_on) || ab->move_type == 0) &&
199 (head->race==tmp->slaying || 257 (head->race == tmp->slaying ||
200 ((head->type==SPECIAL_KEY) && (head->slaying==tmp->slaying)) || 258 ((head->type == SPECIAL_KEY) && (head->slaying == tmp->slaying)) ||
201 (!strcmp (tmp->slaying, "player") && 259 (!strcmp (tmp->slaying, "player") && head->type == PLAYER)))
202 head->type == PLAYER)))
203 tmp->value = 1; 260 tmp->value = 1;
204 } 261 }
205 if(tmp->value) 262 if (tmp->value)
206 any_down=1; 263 any_down = 1;
207 } 264 }
208 } 265 }
209 if(any_down) /* If any other buttons were down, force this to remain down */ 266 if (any_down) /* If any other buttons were down, force this to remain down */
210 op->value=1; 267 op->value = 1;
211 268
212 /* If this button hasn't changed, don't do anything */ 269 /* If this button hasn't changed, don't do anything */
213 if (op->value != old_value) { 270 if (op->value != old_value)
271 {
214 SET_ANIMATION(op, op->value); 272 SET_ANIMATION (op, op->value);
215 update_object(op, UP_OBJ_FACE); 273 update_object (op, UP_OBJ_FACE);
216 push_button(op); /* Make all other buttons the same */ 274 push_button (op); /* Make all other buttons the same */
217 } 275 }
218} 276}
219 277
220/* 278/*
221 * Updates every button on the map (by calling update_button() for them). 279 * Updates every button on the map (by calling update_button() for them).
222 */ 280 */
223 281
224void update_buttons(mapstruct *m) { 282void
283update_buttons (maptile *m)
284{
225 objectlink *ol; 285 objectlink *ol;
226 oblinkpt *obp; 286 oblinkpt *obp;
287
227 for (obp = m->buttons; obp; obp = obp->next) 288 for (obp = m->buttons; obp; obp = obp->next)
228 for (ol = obp->link; ol; ol = ol->next) { 289 for (ol = obp->link; ol; ol = ol->next)
229 if (!ol->ob || ol->ob->count != ol->id) { 290 {
291 if (!ol->ob)
292 {
230 LOG(llevError, "Internal error in update_button (%s (%dx%d):%d, connected %ld).\n", 293 LOG (llevError, "Internal error in update_button (%s (%dx%d), connected %ld).\n",
231 ol->ob?ol->ob->name:"null", 294 ol->ob ? (const char *) ol->ob->name : "null", ol->ob ? ol->ob->x : -1, ol->ob ? ol->ob->y : -1, obp->value);
232 ol->ob?ol->ob->x:-1,
233 ol->ob?ol->ob->y:-1,
234 ol->id,
235 obp->value);
236 continue; 295 continue;
296 }
297
298 if (ol->ob->type == BUTTON || ol->ob->type == PEDESTAL)
299 {
300 update_button (ol->ob);
301 break;
302 }
237 } 303 }
238 if (ol->ob->type==BUTTON || ol->ob->type==PEDESTAL)
239 {
240 update_button(ol->ob);
241 break;
242 }
243 }
244} 304}
245 305
306void
246void use_trigger(object *op) 307use_trigger (object *op)
247{ 308{
248 309
249 /* Toggle value */ 310 /* Toggle value */
250 op->value = !op->value; 311 op->value = !op->value;
251 push_button(op); 312 push_button (op);
252} 313}
253 314
254/* 315/*
255 * Note: animate_object should be used instead of this, 316 * Note: animate_object should be used instead of this,
256 * but it can't handle animations in the 8 directions 317 * but it can't handle animations in the 8 directions
257 */ 318 */
258 319
320void
259void animate_turning(object *op) /* only one part objects */ 321animate_turning (object *op) /* only one part objects */
260{ 322{
261 if (++op->state >= NUM_ANIMATIONS(op)/8) 323 if (++op->state >= NUM_ANIMATIONS (op) / 8)
262 op->state=0; 324 op->state = 0;
263 SET_ANIMATION(op, (op->stats.sp-1) * NUM_ANIMATIONS(op) / 8 + 325 SET_ANIMATION (op, (op->stats.sp - 1) * NUM_ANIMATIONS (op) / 8 + op->state);
264 op->state);
265 update_object(op,UP_OBJ_FACE); 326 update_object (op, UP_OBJ_FACE);
266} 327}
267 328
268#define ARCH_SACRIFICE(xyz) ((xyz)->slaying) 329#define ARCH_SACRIFICE(xyz) ((xyz)->slaying)
269#define NROF_SACRIFICE(xyz) ((uint32)(xyz)->stats.food) 330#define NROF_SACRIFICE(xyz) ((uint32)(xyz)->stats.food)
270 331
276 * 337 *
277 * 0.93.4: Linked objects (ie, objects that are connected) can not be 338 * 0.93.4: Linked objects (ie, objects that are connected) can not be
278 * sacrificed. This fixes a bug of trying to put multiple altars/related 339 * sacrificed. This fixes a bug of trying to put multiple altars/related
279 * objects on the same space that take the same sacrifice. 340 * objects on the same space that take the same sacrifice.
280 */ 341 */
281 342
343int
282int check_altar_sacrifice (const object *altar, const object *sacrifice) 344check_altar_sacrifice (const object *altar, const object *sacrifice)
283{ 345{
284 if ( ! QUERY_FLAG (sacrifice, FLAG_ALIVE) 346 if (!QUERY_FLAG (sacrifice, FLAG_ALIVE) && !QUERY_FLAG (sacrifice, FLAG_IS_LINKED) && sacrifice->type != PLAYER)
285 && ! QUERY_FLAG (sacrifice, FLAG_IS_LINKED)
286 && sacrifice->type != PLAYER)
287 { 347 {
288 if ((ARCH_SACRIFICE(altar) == sacrifice->arch->name || 348 if ((ARCH_SACRIFICE (altar) == sacrifice->arch->name ||
289 ARCH_SACRIFICE(altar) == sacrifice->name || 349 ARCH_SACRIFICE (altar) == sacrifice->name ||
290 ARCH_SACRIFICE(altar) == sacrifice->slaying || 350 ARCH_SACRIFICE (altar) == sacrifice->slaying ||
291 (!strcmp(ARCH_SACRIFICE(altar),query_base_name(sacrifice,0)))) 351 (!strcmp (ARCH_SACRIFICE (altar), query_base_name (sacrifice, 0))))
292 && NROF_SACRIFICE(altar) <= (sacrifice->nrof?sacrifice->nrof:1)) 352 && NROF_SACRIFICE (altar) <= (sacrifice->nrof ? sacrifice->nrof : 1))
293 return 1; 353 return 1;
354
294 if (strcmp (ARCH_SACRIFICE(altar), "money") == 0 355 if (strcmp (ARCH_SACRIFICE (altar), "money") == 0
295 && sacrifice->type == MONEY
296 && sacrifice->nrof * sacrifice->value >= NROF_SACRIFICE(altar)) 356 && sacrifice->type == MONEY && sacrifice->nrof * sacrifice->value >= NROF_SACRIFICE (altar))
297 return 1; 357 return 1;
298 } 358 }
359
299 return 0; 360 return 0;
300} 361}
301
302 362
303/* 363/*
304 * operate_altar checks if sacrifice was accepted and removes sacrificed 364 * operate_altar checks if sacrifice was accepted and removes sacrificed
305 * objects. If sacrifice was succeed return 1 else 0. Might be better to 365 * objects. If sacrifice was succeed return 1 else 0. Might be better to
306 * call check_altar_sacrifice (above) than depend on the return value, 366 * call check_altar_sacrifice (above) than depend on the return value,
307 * since operate_altar will remove the sacrifice also. 367 * since operate_altar will remove the sacrifice also.
308 * 368 *
309 * If this function returns 1, '*sacrifice' is modified to point to the 369 * If this function returns 1, '*sacrifice' is modified to point to the
310 * remaining sacrifice, or is set to NULL if the sacrifice was used up. 370 * remaining sacrifice, or is set to NULL if the sacrifice was used up.
311 */ 371 */
312 372int
313int operate_altar (object *altar, object **sacrifice) 373operate_altar (object *altar, object **sacrifice)
314{ 374{
315
316 if ( ! altar->map) { 375 if (!altar->map)
376 {
317 LOG (llevError, "BUG: operate_altar(): altar has no map\n"); 377 LOG (llevError, "BUG: operate_altar(): altar has no map\n");
318 return 0; 378 return 0;
319 } 379 }
320 380
321 if (!altar->slaying || altar->value) 381 if (!altar->slaying || altar->value)
322 return 0; 382 return 0;
323 383
324 if ( ! check_altar_sacrifice (altar, *sacrifice)) 384 if (!check_altar_sacrifice (altar, *sacrifice))
325 return 0; 385 return 0;
326 386
327 /* check_altar_sacrifice should have already verified that enough money 387 /* check_altar_sacrifice should have already verified that enough money
328 * has been dropped. 388 * has been dropped.
329 */ 389 */
330 if (!strcmp(ARCH_SACRIFICE(altar), "money")) { 390 if (!strcmp (ARCH_SACRIFICE (altar), "money"))
391 {
331 int number=NROF_SACRIFICE(altar) / (*sacrifice)->value; 392 int number = NROF_SACRIFICE (altar) / (*sacrifice)->value;
332 393
333 /* Round up any sacrifices. Altars don't make change either */ 394 /* Round up any sacrifices. Altars don't make change either */
334 if (NROF_SACRIFICE(altar) % (*sacrifice)->value) number++; 395 if (NROF_SACRIFICE (altar) % (*sacrifice)->value)
396 number++;
397
335 *sacrifice = decrease_ob_nr (*sacrifice, number); 398 *sacrifice = decrease_ob_nr (*sacrifice, number);
336 } 399 }
337 else 400 else
338 *sacrifice = decrease_ob_nr (*sacrifice, NROF_SACRIFICE(altar)); 401 *sacrifice = decrease_ob_nr (*sacrifice, NROF_SACRIFICE (altar));
339 402
340 if (altar->msg) 403 if (altar->msg)
341 new_info_map(NDI_BLACK, altar->map, altar->msg); 404 new_info_map (NDI_BLACK, altar->map, altar->msg);
405
342 return 1; 406 return 1;
343} 407}
344 408
409void
345void trigger_move (object *op, int state) /* 1 down and 0 up */ 410trigger_move (object *op, int state) /* 1 down and 0 up */
346{ 411{
347 op->stats.wc = state; 412 op->stats.wc = state;
348 if (state) { 413 if (state)
414 {
349 use_trigger(op); 415 use_trigger (op);
350 if (op->stats.exp > 0) /* check sanity */ 416 op->set_speed (op->stats.exp > 0 ? 1. / op->stats.exp : 1.);
351 op->speed = 1.0 / op->stats.exp;
352 else
353 op->speed = 1.0;
354 update_ob_speed(op);
355 op->speed_left = -1; 417 op->speed_left = -1;
356 } else { 418 }
419 else
420 {
357 use_trigger(op); 421 use_trigger (op);
358 op->speed = 0; 422 op->set_speed (0);
359 update_ob_speed(op);
360 } 423 }
361} 424}
362 425
363 426
364/* 427/*
371 * 434 *
372 * TRIGGER: Returns 1 if handle could be moved, 0 if not. 435 * TRIGGER: Returns 1 if handle could be moved, 0 if not.
373 * 436 *
374 * TRIGGER_BUTTON, TRIGGER_PEDESTAL: Returns 0. 437 * TRIGGER_BUTTON, TRIGGER_PEDESTAL: Returns 0.
375 */ 438 */
439int
376int check_trigger (object *op, object *cause) 440check_trigger (object *op, object *cause)
377{ 441{
378 object *tmp; 442 object *tmp;
379 int push = 0, tot = 0; 443 int push = 0, tot = 0;
380 int in_movement = op->stats.wc || op->speed; 444 int in_movement = op->stats.wc || op->speed;
381 445
382 switch (op->type) { 446 switch (op->type)
447 {
383 case TRIGGER_BUTTON: 448 case TRIGGER_BUTTON:
384 if (op->weight > 0) { 449 if (op->weight > 0)
450 {
385 if (cause) { 451 if (cause)
452 {
386 for (tmp = op->above; tmp; tmp = tmp->above) 453 for (tmp = op->above; tmp; tmp = tmp->above)
387 /* Comment reproduced from update_buttons(): */ 454 /* Comment reproduced from update_buttons(): */
388 /* Basically, if the move_type matches that on what the 455 /* Basically, if the move_type matches that on what the
389 * button wants, we count it. The second check is so that 456 * button wants, we count it. The second check is so that
390 * objects that don't move (swords, etc) will count. Note that 457 * objects that don't move (swords, etc) will count. Note that
391 * this means that more work is needed to make buttons 458 * this means that more work is needed to make buttons
392 * that are only triggered by flying objects. 459 * that are only triggered by flying objects.
393 */ 460 */
394 461
395 if ((tmp->move_type & op->move_on) || tmp->move_type==0) { 462 if ((tmp->move_type & op->move_on) || tmp->move_type == 0)
463 {
396 tot += tmp->weight * (tmp->nrof ? tmp->nrof : 1) 464 tot += tmp->weight * (tmp->nrof ? tmp->nrof : 1) + tmp->carrying;
397 + tmp->carrying;
398 } 465 }
399 if (tot >= op->weight) 466 if (tot >= op->weight)
400 push = 1; 467 push = 1;
401 if (op->stats.ac == push) 468 if (op->stats.ac == push)
402 return 0; 469 return 0;
403 op->stats.ac = push; 470 op->stats.ac = push;
404 if (NUM_ANIMATIONS(op) > 1) { 471 if (NUM_ANIMATIONS (op) > 1)
472 {
405 SET_ANIMATION (op, push); 473 SET_ANIMATION (op, push);
406 update_object (op, UP_OBJ_FACE); 474 update_object (op, UP_OBJ_FACE);
407 } 475 }
408 if (in_movement || ! push) 476 if (in_movement || !push)
409 return 0; 477 return 0;
410 } 478 }
411 trigger_move (op, push); 479 trigger_move (op, push);
412 } 480 }
413 return 0; 481 return 0;
414 482
415 case TRIGGER_PEDESTAL: 483 case TRIGGER_PEDESTAL:
416 if (cause) { 484 if (cause)
485 {
417 for (tmp = op->above; tmp; tmp = tmp->above) { 486 for (tmp = op->above; tmp; tmp = tmp->above)
487 {
418 object *head = tmp->head ? tmp->head : tmp; 488 object *head = tmp->head ? tmp->head : tmp;
419 489
420 /* See comment in TRIGGER_BUTTON about move_types */ 490 /* See comment in TRIGGER_BUTTON about move_types */
421 if (((head->move_type & op->move_on) || head->move_type==0) 491 if (((head->move_type & op->move_on) || head->move_type == 0)
422 && (head->race==op->slaying ||
423 (!strcmp (op->slaying, "player") && head->type == PLAYER))) { 492 && (head->race == op->slaying || (!strcmp (op->slaying, "player") && head->type == PLAYER)))
493 {
424 push = 1; 494 push = 1;
425 break; 495 break;
426 } 496 }
427 } 497 }
428 if (op->stats.ac == push) 498 if (op->stats.ac == push)
429 return 0; 499 return 0;
430 op->stats.ac = push; 500 op->stats.ac = push;
431 if (NUM_ANIMATIONS(op) > 1) { 501 if (NUM_ANIMATIONS (op) > 1)
502 {
432 SET_ANIMATION (op, push); 503 SET_ANIMATION (op, push);
433 update_object (op, UP_OBJ_FACE); 504 update_object (op, UP_OBJ_FACE);
434 } 505 }
435 update_object(op,UP_OBJ_FACE); 506 update_object (op, UP_OBJ_FACE);
436 if (in_movement || ! push) 507 if (in_movement || !push)
437 return 0; 508 return 0;
438 } 509 }
439 trigger_move (op, push); 510 trigger_move (op, push);
440 return 0; 511 return 0;
441 512
442 case TRIGGER_ALTAR: 513 case TRIGGER_ALTAR:
443 if (cause) { 514 if (cause)
515 {
444 if (in_movement) 516 if (in_movement)
445 return 0; 517 return 0;
446 if (operate_altar (op, &cause)) { 518 if (operate_altar (op, &cause))
519 {
447 if (NUM_ANIMATIONS(op) > 1) { 520 if (NUM_ANIMATIONS (op) > 1)
521 {
448 SET_ANIMATION (op, 1); 522 SET_ANIMATION (op, 1);
449 update_object(op, UP_OBJ_FACE); 523 update_object (op, UP_OBJ_FACE);
450 } 524 }
451 if (op->last_sp >= 0) { 525 if (op->last_sp >= 0)
526 {
452 trigger_move (op, 1); 527 trigger_move (op, 1);
453 if (op->last_sp > 0) 528 if (op->last_sp > 0)
454 op->last_sp = -op->last_sp; 529 op->last_sp = -op->last_sp;
455 } 530 }
456 else { 531 else
532 {
457 /* for trigger altar with last_sp, the ON/OFF 533 /* for trigger altar with last_sp, the ON/OFF
458 * status (-> +/- value) is "simulated": 534 * status (-> +/- value) is "simulated":
459 */ 535 */
460 op->value = !op->value; 536 op->value = !op->value;
461 trigger_move (op, 1); 537 trigger_move (op, 1);
462 op->last_sp = -op->last_sp; 538 op->last_sp = -op->last_sp;
463 op->value = !op->value; 539 op->value = !op->value;
464 } 540 }
465 return cause == NULL; 541 return cause == NULL;
466 } else {
467 return 0;
468 } 542 }
469 } else { 543 else
470 if (NUM_ANIMATIONS(op) > 1) {
471 SET_ANIMATION (op, 0);
472 update_object(op, UP_OBJ_FACE);
473 } 544 {
474 545 return 0;
475 /* If trigger_altar has "last_sp > 0" set on the map,
476 * it will push the connected value only once per sacrifice.
477 * Otherwise (default), the connected value will be
478 * pushed twice: First by sacrifice, second by reset! -AV
479 */
480 if (!op->last_sp)
481 trigger_move (op, 0);
482 else {
483 op->stats.wc = 0;
484 op->value = !op->value;
485 op->speed = 0;
486 update_ob_speed(op);
487 } 546 }
488 } 547 }
548 else
549 {
550 if (NUM_ANIMATIONS (op) > 1)
551 {
552 SET_ANIMATION (op, 0);
553 update_object (op, UP_OBJ_FACE);
554 }
555
556 /* If trigger_altar has "last_sp > 0" set on the map,
557 * it will push the connected value only once per sacrifice.
558 * Otherwise (default), the connected value will be
559 * pushed twice: First by sacrifice, second by reset! -AV
560 */
561 if (!op->last_sp)
562 trigger_move (op, 0);
563 else
564 {
565 op->stats.wc = 0;
566 op->value = !op->value;
567 op->set_speed (0);
568 }
569 }
489 return 0; 570 return 0;
490 571
491 case TRIGGER: 572 case TRIGGER:
492 if (cause) { 573 if (cause)
574 {
493 if (in_movement) 575 if (in_movement)
494 return 0; 576 return 0;
577
495 push = 1; 578 push = 1;
496 } 579 }
580
497 if (NUM_ANIMATIONS(op) > 1) { 581 if (NUM_ANIMATIONS (op) > 1)
582 {
498 SET_ANIMATION (op, push); 583 SET_ANIMATION (op, push);
499 update_object(op, UP_OBJ_FACE); 584 update_object (op, UP_OBJ_FACE);
500 } 585 }
586
501 trigger_move (op, push); 587 trigger_move (op, push);
502 return 1; 588 return 1;
503 589
504 default: 590 default:
505 LOG(llevDebug, "Unknown trigger type: %s (%d)\n", op->name, op->type); 591 LOG (llevDebug, "Unknown trigger type: %s (%d)\n", &op->name, op->type);
506 return 0; 592 return 0;
507 } 593 }
508} 594}
509 595
596void
510void add_button_link(object *button, mapstruct *map, int connected) { 597add_button_link (object *button, maptile *map, int connected)
598{
511 oblinkpt *obp; 599 oblinkpt *obp;
512 objectlink *ol = get_objectlink(); 600 objectlink *ol = get_objectlink ();
513 601
514 if (!map) { 602 if (!map)
603 {
515 LOG(llevError, "Tried to add button-link without map.\n"); 604 LOG (llevError, "Tried to add button-link without map.\n");
516 return; 605 return;
517 } 606 }
607
518 if (!editor) button->path_attuned = connected; /* peterm: I need this so I can rebuild 608 button->path_attuned = connected; /* peterm: I need this so I can rebuild
519 a connected map from a template map. */ 609 a connected map from a template map. */
520/* LOG(llevDebug,"adding button %s (%d)\n", button->name, connected);*/
521 610
522 SET_FLAG(button,FLAG_IS_LINKED); 611 SET_FLAG (button, FLAG_IS_LINKED);
523 612
524 ol->ob = button; 613 ol->ob = button;
525 ol->id = button->count;
526 614
527 for (obp = map->buttons; obp && obp->value != connected; obp = obp->next); 615 for (obp = map->buttons; obp && obp->value != connected; obp = obp->next)
616 ;
528 617
529 if (obp) { 618 if (obp)
619 {
530 ol->next = obp->link; 620 ol->next = obp->link;
531 obp->link = ol; 621 obp->link = ol;
622 }
532 } else { 623 else
624 {
533 obp = get_objectlinkpt(); 625 obp = get_objectlinkpt ();
534 obp->value = connected; 626 obp->value = connected;
535 627
536 obp->next = map->buttons; 628 obp->next = map->buttons;
537 map->buttons = obp; 629 map->buttons = obp;
538 obp->link = ol; 630 obp->link = ol;
539 } 631 }
540} 632}
541 633
542/* 634/*
543 * Remove the object from the linked lists of buttons in the map. 635 * Remove the object from the linked lists of buttons in the map.
544 * This is only needed by editors. 636 * This is only needed by editors.
545 */ 637 */
546 638
639void
547void remove_button_link(object *op) { 640remove_button_link (object *op)
641{
548 oblinkpt *obp; 642 oblinkpt *obp;
549 objectlink **olp, *ol; 643 objectlink **olp, *ol;
550 644
551 if (op->map == NULL) { 645 if (op->map == NULL)
646 {
552 LOG(llevError, "remove_button_link() in object without map.\n"); 647 LOG (llevError, "remove_button_link() in object without map.\n");
553 return; 648 return;
554 } 649 }
650
555 if (!QUERY_FLAG(op,FLAG_IS_LINKED)) { 651 if (!QUERY_FLAG (op, FLAG_IS_LINKED))
652 {
556 LOG(llevError, "remove_button_linked() in unlinked object.\n"); 653 LOG (llevError, "remove_button_linked() in unlinked object.\n");
557 return; 654 return;
558 } 655 }
656
559 for (obp = op->map->buttons; obp; obp = obp->next) 657 for (obp = op->map->buttons; obp; obp = obp->next)
560 for (olp = &obp->link; (ol = *olp); olp = &ol->next) 658 for (olp = &obp->link; (ol = *olp); olp = &ol->next)
561 if (ol->ob == op) { 659 if (ol->ob == op)
660 {
661
562/* LOG(llevDebug, "Removed link %d in button %s and map %s.\n", 662/* LOG(llevDebug, "Removed link %d in button %s and map %s.\n",
563 obp->value, op->name, op->map->path); 663 obp->value, op->name, op->map->path);
564*/ 664*/
565 *olp = ol->next; 665 *olp = ol->next;
566 free(ol); 666 delete ol;
567 return; 667 return;
568 } 668 }
669
569 LOG(llevError, "remove_button_linked(): couldn't find object.\n"); 670 LOG (llevError, "remove_button_linked(): couldn't find object.\n");
570 CLEAR_FLAG(op,FLAG_IS_LINKED); 671 CLEAR_FLAG (op, FLAG_IS_LINKED);
571} 672}
572 673
674/*
675 * Gets the objectlink for this connection from the map.
676 */
677oblinkpt *
678get_connection_links (maptile *map, long connection)
679{
680 for (oblinkpt * obp = map->buttons; obp; obp = obp->next)
681 if (obp->value == connection)
682 return obp;
683
684 return 0;
685}
686
573/* 687/*
574 * Return the first objectlink in the objects linked to this one 688 * Return the first objectlink in the objects linked to this one
575 */ 689 */
576 690
691oblinkpt *
577objectlink *get_button_links(const object *button) { 692get_button_links (const object *button)
693{
578 oblinkpt *obp; 694 oblinkpt *obp;
579 objectlink *ol; 695 objectlink *ol;
580 696
581 if (!button->map) 697 if (!button->map)
582 return NULL; 698 return NULL;
699
583 for (obp = button->map->buttons; obp; obp = obp->next) 700 for (obp = button->map->buttons; obp; obp = obp->next)
584 for (ol = obp->link; ol; ol = ol->next) 701 for (ol = obp->link; ol; ol = ol->next)
585 if (ol->ob == button && ol->id == button->count) 702 if (ol->ob == button)
586 return obp->link; 703 return obp;
704
587 return NULL; 705 return NULL;
588} 706}
589 707
590/* 708/*
591 * Made as a separate function to increase efficiency 709 * Made as a separate function to increase efficiency
592 */ 710 */
593 711
712int
594int get_button_value(const object *button) { 713get_button_value (const object *button)
714{
595 oblinkpt *obp; 715 oblinkpt *obp;
596 objectlink *ol; 716 objectlink *ol;
597 717
598 if (!button->map) 718 if (!button->map)
599 return 0; 719 return 0;
600 for (obp = button->map->buttons; obp; obp = obp->next) 720 for (obp = button->map->buttons; obp; obp = obp->next)
601 for (ol = obp->link; ol; ol = ol->next) 721 for (ol = obp->link; ol; ol = ol->next)
602 if (ol->ob == button && ol->id == button->count) 722 if (ol->ob == button)
603 return obp->value; 723 return obp->value;
604 return 0; 724 return 0;
605} 725}
606 726
607/* This routine makes monsters who are 727/* This routine makes monsters who are
610 * If floor is to be triggered must have 730 * If floor is to be triggered must have
611 * a speed of zero (default is 1 for all 731 * a speed of zero (default is 1 for all
612 * but the charm floor type). 732 * but the charm floor type).
613 * by b.t. thomas@nomad.astro.psu.edu 733 * by b.t. thomas@nomad.astro.psu.edu
614 */ 734 */
615 735
736void
616void do_mood_floor(object *op, object *op2) { 737do_mood_floor (object *op, object *source)
738{
617 object *tmp; 739 object *tmp;
618 object *tmp2; 740 object *tmp2;
619 741
742 if (!source)
743 source = op;
744
620 for (tmp = GET_MAP_OB(op->map, op->x, op->y); tmp; tmp=tmp->above) 745 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp; tmp = tmp->above)
621 if (QUERY_FLAG(tmp, FLAG_MONSTER)) break; 746 if (QUERY_FLAG (tmp, FLAG_MONSTER))
747 break;
622 748
623 /* doesn't effect players, and if there is a player on this space, won't also 749 /* doesn't effect players, and if there is a player on this space, won't also
624 * be a monster here. 750 * be a monster here.
625 */ 751 */
626 if (!tmp || tmp->type == PLAYER) return; 752 if (!tmp || tmp->type == PLAYER)
753 return;
627 754
628 switch(op->last_sp) { 755 switch (op->last_sp)
756 {
629 case 0: /* furious--make all monsters mad */ 757 case 0: /* furious--make all monsters mad */
630 if(QUERY_FLAG(tmp, FLAG_UNAGGRESSIVE))
631 CLEAR_FLAG(tmp, FLAG_UNAGGRESSIVE);
632 if(QUERY_FLAG(tmp, FLAG_FRIENDLY)) {
633 CLEAR_FLAG(tmp, FLAG_FRIENDLY);
634 remove_friendly_object(tmp);
635 tmp->attack_movement = 0;
636 /* lots of checks here, but want to make sure we don't
637 * dereference a null value
638 */
639 if (tmp->type == GOLEM && tmp->owner && tmp->owner->type==PLAYER &&
640 tmp->owner->contr->ranges[range_golem]==tmp) {
641 tmp->owner->contr->ranges[range_golem]=NULL;
642 tmp->owner->contr->golem_count = 0;
643 }
644 tmp->owner = 0;
645 }
646 break;
647 case 1: /* angry -- get neutral monsters mad */
648 if(QUERY_FLAG(tmp, FLAG_UNAGGRESSIVE)&& 758 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE))
649 !QUERY_FLAG(tmp, FLAG_FRIENDLY))
650 CLEAR_FLAG(tmp, FLAG_UNAGGRESSIVE); 759 CLEAR_FLAG (tmp, FLAG_UNAGGRESSIVE);
760 if (QUERY_FLAG (tmp, FLAG_FRIENDLY))
761 {
762 CLEAR_FLAG (tmp, FLAG_FRIENDLY);
763 remove_friendly_object (tmp);
764 tmp->attack_movement = 0;
765 /* lots of checks here, but want to make sure we don't
766 * dereference a null value
767 */
768 if (tmp->type == GOLEM && tmp->owner && tmp->owner->type == PLAYER && tmp->owner->contr->ranges[range_golem] == tmp)
769 tmp->owner->contr->ranges[range_golem] = 0;
770
771 tmp->owner = 0;
772 }
651 break; 773 break;
774 case 1: /* angry -- get neutral monsters mad */
775 if (QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (tmp, FLAG_FRIENDLY))
776 CLEAR_FLAG (tmp, FLAG_UNAGGRESSIVE);
777 break;
652 case 2: /* calm -- pacify unfriendly monsters */ 778 case 2: /* calm -- pacify unfriendly monsters */
653 if(!QUERY_FLAG(tmp, FLAG_UNAGGRESSIVE)) 779 if (!QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE))
654 SET_FLAG(tmp, FLAG_UNAGGRESSIVE); 780 SET_FLAG (tmp, FLAG_UNAGGRESSIVE);
781 break;
782 case 3: /* make all monsters fall asleep */
783 if (!QUERY_FLAG (tmp, FLAG_SLEEP))
784 SET_FLAG (tmp, FLAG_SLEEP);
785 break;
786 case 4: /* charm all monsters */
787 if (op == source)
788 break; /* only if 'connected' */
789
790 for (tmp2 = GET_MAP_OB (source->map, source->x, source->y); /* finding an owner */
791 tmp2->type != PLAYER; tmp2 = tmp2->above)
792 if (tmp2->above == NULL)
655 break; 793 break;
656 case 3: /* make all monsters fall asleep */
657 if(!QUERY_FLAG(tmp, FLAG_SLEEP))
658 SET_FLAG(tmp, FLAG_SLEEP);
659 break;
660 case 4: /* charm all monsters */
661 794
662 if(op == op2) break; /* only if 'connected' */
663
664 for(tmp2=get_map_ob(op2->map,op2->x,op2->y); /* finding an owner */
665 tmp2->type!=PLAYER;tmp2=tmp2->above)
666 if(tmp2->above==NULL) break;
667
668 if (tmp2->type != PLAYER) 795 if (tmp2->type != PLAYER)
669 break; 796 break;
670 set_owner(tmp,tmp2); 797
798 tmp->set_owner (tmp2);
671 SET_FLAG(tmp,FLAG_MONSTER); 799 SET_FLAG (tmp, FLAG_MONSTER);
800
672 tmp->stats.exp = 0; 801 tmp->stats.exp = 0;
673 SET_FLAG(tmp, FLAG_FRIENDLY); 802 SET_FLAG (tmp, FLAG_FRIENDLY);
803
674 add_friendly_object (tmp); 804 add_friendly_object (tmp);
675 tmp->attack_movement = PETMOVE; 805 tmp->attack_movement = PETMOVE;
676 break; 806 break;
677 807
678 default: 808 default:
679 break; 809 break;
680
681 } 810 }
682} 811}
683 812
684/* this function returns the object it matches, or NULL if non. 813/* this function returns the object it matches, or NULL if non.
685 * It will descend through containers to find the object. 814 * It will descend through containers to find the object.
686 * slaying = match object slaying flag 815 * slaying = match object slaying flag
687 * race = match object archetype name flag 816 * race = match object archetype name flag
688 * hp = match object type (excpt type '0'== PLAYER) 817 * hp = match object type (excpt type '0'== PLAYER)
689 */ 818 */
690 819object *
691object * check_inv_recursive(object *op, const object *trig) 820check_inv_recursive (object *op, const object *trig)
692{ 821{
693 object *tmp,*ret=NULL; 822 object *tmp, *ret = NULL;
694 823
695 /* First check the object itself. */ 824 /* First check the object itself. */
696 if((trig->stats.hp && (op->type == trig->stats.hp)) 825 if ((trig->stats.hp && (op->type == trig->stats.hp))
697 || (trig->slaying && (op->slaying == trig->slaying)) 826 || (trig->slaying && (op->slaying == trig->slaying))
698 || (trig->race && (op->arch->name == trig->race))) 827 || (trig->race && (op->arch->name == trig->race)))
699 return op; 828 return op;
700 829
701 for(tmp=op->inv; tmp; tmp=tmp->below) { 830 for (tmp = op->inv; tmp; tmp = tmp->below)
831 {
702 if (tmp->inv) { 832 if (tmp->inv)
833 {
703 ret=check_inv_recursive(tmp, trig); 834 ret = check_inv_recursive (tmp, trig);
835 if (ret)
704 if (ret) return ret; 836 return ret;
705 } 837 }
706 else if((trig->stats.hp && (tmp->type == trig->stats.hp)) 838 else if ((trig->stats.hp && (tmp->type == trig->stats.hp))
707 || (trig->slaying && (tmp->slaying == trig->slaying)) 839 || (trig->slaying && (tmp->slaying == trig->slaying))
708 || (trig->race && (tmp->arch->name == trig->race))) 840 || (trig->race && (tmp->arch->name == trig->race)))
709 return tmp; 841 return tmp;
710 } 842 }
711 return NULL; 843 return NULL;
712} 844}
713 845
714/* check_inv(), a function to search the inventory, 846/* check_inv(), a function to search the inventory,
715 * of a player and then based on a set of conditions, 847 * of a player and then based on a set of conditions,
716 * the square will activate connected items. 848 * the square will activate connected items.
717 * Monsters can't trigger this square (for now) 849 * Monsters can't trigger this square (for now)
718 * Values are: last_sp = 1/0 obj/no obj triggers 850 * Values are: last_sp = 1/0 obj/no obj triggers
719 * last_heal = 1/0 remove/dont remove obj if triggered 851 * last_heal = 1/0 remove/dont remove obj if triggered
720 * -b.t. (thomas@nomad.astro.psu.edu 852 * -b.t. (thomas@nomad.astro.psu.edu
721 */ 853 *
722 854 * Tue Dec 19 15:34:00 CET 2006 elmex: changed the function to ignore op
855 * because the check-inventory semantic essentially only applies when
856 * something is above the inventory checker.
857 * The semantic prior this change was: trigger if something has moved on or off
858 * and has a matching item. Imagine what happens if someone steps on the inventory
859 * checker with a matching item, has it, activates the connection, throws the item
860 * away, and then leaves the inventory checker. That would've caused an always-enabled
861 * state in the inventory checker. This won't happen anymore now.
862 *
863 */
864void
723void check_inv (object *op, object *trig) { 865check_inv (object *op, object *trig)
724object *match; 866{
867 trig->value = 0; // deactivate if none of the following conditions apply
725 868
726 if(op->type != PLAYER) return; 869 if (object *pl = trig->ms ().player ())
870 {
727 match = check_inv_recursive(op,trig); 871 object *match = check_inv_recursive (pl, trig);
872
728 if (match && trig->last_sp) { 873 if (match && trig->last_sp) // match == having
874 {
729 if(trig->last_heal) 875 if (trig->last_heal)
730 decrease_ob(match); 876 decrease_ob (match);
731 use_trigger(trig);
732 }
733 else if (!match && !trig->last_sp)
734 use_trigger(trig);
735}
736 877
737 878 trig->value = 1;
738/* This does a minimal check of the button link consistency for object
739 * map. All it really does it much sure the object id link that is set
740 * matches what the object has.
741 */
742void verify_button_links(const mapstruct *map) {
743 oblinkpt *obp;
744 objectlink *ol;
745
746 if (!map) return;
747
748 for (obp = map->buttons; obp; obp = obp->next) {
749 for (ol=obp->link; ol; ol=ol->next) {
750 if (ol->id!=ol->ob->count)
751 LOG(llevError,"verify_button_links: object %s on list is corrupt (%d!=%d)\n",ol->ob->name, ol->id, ol->ob->count);
752 } 879 }
880 else if (!match && !trig->last_sp) // match == not having
881 trig->value = 1;
753 } 882 }
883
884 push_button (trig);
754} 885}
886

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines