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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines