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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines