ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/button.C
(Generate patch)

Comparing deliantra/server/common/button.C (file contents):
Revision 1.2 by root, Tue Aug 29 08:01:35 2006 UTC vs.
Revision 1.18 by root, Thu Dec 21 01:33:49 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines