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.3 by elmex, Tue Aug 29 17:29:27 2006 UTC vs.
Revision 1.19 by root, Mon Dec 25 11:25:49 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines