ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/time.C
Revision: 1.48
Committed: Sat May 12 21:56:35 2007 UTC (17 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.47: +3 -5 lines
Log Message:
lots of speed logic changes

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.34 * CrossFire, A Multiplayer game
3     *
4     * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
5     * Copyright (C) 2002 Mark Wedel & Crossfire Development Team
6     * Copyright (C) 1992 Frank Tore Johansen
7     *
8     * This program is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation; either version 2 of the License, or
11     * (at your option) any later version.
12     *
13     * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17     *
18     * You should have received a copy of the GNU General Public License
19     * along with this program; if not, write to the Free Software
20     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21     *
22     * The authors can be reached via e-mail at <crossfire@schmorp.de>
23     */
24 elmex 1.1
25     /*
26     * Routines that is executed from objects based on their speed have been
27     * collected in this file.
28     */
29     #include <global.h>
30     #include <spells.h>
31 root 1.28 #include <sproto.h>
32 elmex 1.1
33     /* The following removes doors. The functions check to see if similar
34     * doors are next to the one that is being removed, and if so, set it
35     * so those will be removed shortly (in a cascade like fashion.)
36     */
37 root 1.9 void
38     remove_door (object *op)
39     {
40 elmex 1.1 int i;
41     object *tmp;
42 root 1.9
43     for (i = 1; i < 9; i += 2)
44     if ((tmp = present (DOOR, op->map, op->x + freearr_x[i], op->y + freearr_y[i])) != NULL)
45     {
46 root 1.26 tmp->set_speed (0.1);
47 root 1.9 tmp->speed_left = -0.2;
48     }
49    
50     if (op->other_arch)
51     {
52     tmp = arch_to_object (op->other_arch);
53     tmp->x = op->x;
54     tmp->y = op->y;
55     tmp->map = op->map;
56     tmp->level = op->level;
57     insert_ob_in_map (tmp, op->map, op, 0);
58     }
59 root 1.17
60     op->destroy ();
61 elmex 1.1 }
62    
63 root 1.9 void
64     remove_door2 (object *op)
65     {
66 elmex 1.1 int i;
67     object *tmp;
68 root 1.9
69     for (i = 1; i < 9; i += 2)
70     {
71     tmp = present (LOCKED_DOOR, op->map, op->x + freearr_x[i], op->y + freearr_y[i]);
72     if (tmp && tmp->slaying == op->slaying)
73     { /* same key both doors */
74 root 1.26 tmp->set_speed (0.1);
75 root 1.9 tmp->speed_left = -0.2;
76     }
77     }
78 root 1.27
79 root 1.9 if (op->other_arch)
80     {
81     tmp = arch_to_object (op->other_arch);
82     tmp->x = op->x;
83     tmp->y = op->y;
84     tmp->map = op->map;
85     tmp->level = op->level;
86     insert_ob_in_map (tmp, op->map, op, 0);
87     }
88 root 1.17
89     op->destroy ();
90 elmex 1.1 }
91    
92 root 1.45 void
93     generate_monster (object *gen)
94 root 1.9 {
95 root 1.45 if (!gen->map)
96     return;
97    
98     if (GENERATE_SPEED (gen) && rndm (0, GENERATE_SPEED (gen) - 1))
99     return;
100    
101     object *op;
102    
103     if (QUERY_FLAG (gen, FLAG_CONTENT_ON_GEN))
104     {
105     // either copy one item form the inventory...
106     if (!gen->inv)
107     return;
108    
109     // first select one item from the inventory
110     int index = 0;
111     for (object *tmp = gen->inv; tmp; tmp = tmp->below)
112     if (!rndm (++index))
113     op = tmp;
114    
115     op = object_create_clone (op);
116    
117     CLEAR_FLAG (op, FLAG_IS_A_TEMPLATE);
118     unflag_inv (op, FLAG_IS_A_TEMPLATE);
119     }
120     else
121     {
122     // ...or use other_arch
123     if (archetype *at = gen->other_arch)
124     op = arch_to_object (at);
125     else
126     return;
127     }
128    
129 root 1.44 op->expand_tail ();
130 root 1.9
131 root 1.44 int i = find_free_spot (op, gen->map, gen->x, gen->y, 1, 9);
132     if (i >= 0)
133 root 1.9 {
134 root 1.44 if (insert_ob_in_map_at (op, gen->map, gen, 0, gen->x + freearr_x[i], gen->y + freearr_y[i]))
135     {
136     if (rndm (0, 9))
137     generate_artifact (op, gen->map->difficulty);
138 root 1.43
139 root 1.44 if (op->has_random_items ())
140     create_treasure (op->randomitems, op, GT_APPLY, gen->map->difficulty);
141 root 1.43
142 root 1.44 return;
143     }
144 elmex 1.1 }
145 root 1.43
146 root 1.44 op->destroy ();
147 root 1.9 }
148    
149     void
150     remove_force (object *op)
151     {
152     if (--op->duration > 0)
153     return;
154 elmex 1.1
155 root 1.25 if (op->env)
156     switch (op->subtype)
157     {
158     case FORCE_CONFUSION:
159     CLEAR_FLAG (op->env, FLAG_CONFUSED);
160     new_draw_info (NDI_UNIQUE, 0, op->env, "You regain your senses.\n");
161 root 1.6
162 root 1.25 default:
163     CLEAR_FLAG (op, FLAG_APPLIED);
164     change_abil (op->env, op);
165     op->env->update_stats ();
166     }
167 root 1.17
168     op->destroy ();
169 elmex 1.1 }
170    
171 root 1.9 void
172     remove_blindness (object *op)
173     {
174     if (--op->stats.food > 0)
175 elmex 1.1 return;
176 root 1.17
177 root 1.9 CLEAR_FLAG (op, FLAG_APPLIED);
178 root 1.17
179 root 1.27 if (op->env)
180 root 1.9 {
181     change_abil (op->env, op);
182 root 1.23 op->env->update_stats ();
183 root 1.9 }
184 root 1.17
185     op->destroy ();
186 elmex 1.1 }
187    
188 root 1.9 void
189     poison_more (object *op)
190     {
191     if (op->env == NULL || !QUERY_FLAG (op->env, FLAG_ALIVE) || op->env->stats.hp < 0)
192     {
193 root 1.17 op->destroy ();
194 root 1.9 return;
195     }
196 root 1.17
197 root 1.9 if (op->stats.food == 1)
198     {
199 root 1.38 /* need to unapply the object before update_stats is called, else fix_player
200 root 1.9 * will not do anything.
201     */
202     if (op->env->type == PLAYER)
203     {
204     CLEAR_FLAG (op, FLAG_APPLIED);
205 root 1.23 op->env->update_stats ();
206 root 1.9 new_draw_info (NDI_UNIQUE, 0, op->env, "You feel much better now.");
207     }
208 root 1.17
209     op->destroy ();
210 root 1.9 return;
211     }
212 root 1.17
213 root 1.9 if (op->env->type == PLAYER)
214     {
215     op->env->stats.food--;
216     new_draw_info (NDI_UNIQUE, 0, op->env, "You feel very sick...");
217 elmex 1.1 }
218 elmex 1.32
219     hit_player (op->env, op->stats.dam, op, AT_INTERNAL, 1);
220 elmex 1.1 }
221    
222    
223 root 1.9 void
224     move_gate (object *op)
225 root 1.46 { /* 1 = going down, 0 = going up */
226 root 1.9 object *tmp;
227    
228     if (op->stats.wc < 0 || (int) op->stats.wc >= NUM_ANIMATIONS (op))
229     {
230     LOG (llevError, "Gate error: animation was %d, max=%d\n", op->stats.wc, NUM_ANIMATIONS (op));
231     op->stats.wc = 0;
232     }
233    
234     /* We're going down */
235     if (op->value)
236     {
237     if (--op->stats.wc <= 0)
238     { /* Reached bottom, let's stop */
239     op->stats.wc = 0;
240     if (op->arch->clone.speed)
241     op->value = 0;
242     else
243 root 1.26 op->set_speed (0);
244 root 1.6 }
245 root 1.26
246 root 1.9 if ((int) op->stats.wc < (NUM_ANIMATIONS (op) / 2 + 1))
247     {
248     op->move_block = 0;
249     CLEAR_FLAG (op, FLAG_BLOCKSVIEW);
250     update_all_los (op->map, op->x, op->y);
251     }
252 root 1.26
253 root 1.9 SET_ANIMATION (op, op->stats.wc);
254     update_object (op, UP_OBJ_CHANGE);
255     return;
256 elmex 1.1 }
257    
258 root 1.9 /* We're going up */
259 elmex 1.1
260 root 1.9 /* First, lets see if we are already at the top */
261     if ((unsigned char) op->stats.wc == (NUM_ANIMATIONS (op) - 1))
262     {
263 elmex 1.1
264 root 1.9 /* Check to make sure that only non pickable and non rollable
265     * objects are above the gate. If so, we finish closing the gate,
266     * otherwise, we fall through to the code below which should lower
267     * the gate slightly.
268     */
269    
270     for (tmp = op->above; tmp != NULL; tmp = tmp->above)
271     if (!QUERY_FLAG (tmp, FLAG_NO_PICK) || QUERY_FLAG (tmp, FLAG_CAN_ROLL) || QUERY_FLAG (tmp, FLAG_ALIVE))
272     break;
273 root 1.6
274 root 1.9 if (tmp == NULL)
275     {
276     if (op->arch->clone.speed)
277     op->value = 1;
278     else
279 root 1.26 op->set_speed (0);
280    
281 root 1.9 return;
282     }
283     }
284    
285     if (op->stats.food)
286     { /* The gate is going temporarily down */
287     if (--op->stats.wc <= 0)
288     { /* Gone all the way down? */
289     op->stats.food = 0; /* Then let's try again */
290     op->stats.wc = 0;
291 root 1.6 }
292 elmex 1.1 }
293 root 1.9 else
294     { /* The gate is still going up */
295     op->stats.wc++;
296 elmex 1.1
297 root 1.9 if ((int) op->stats.wc >= (NUM_ANIMATIONS (op)))
298     op->stats.wc = (signed char) NUM_ANIMATIONS (op) - 1;
299    
300     /* If there is something on top of the gate, we try to roll it off.
301     * If a player/monster, we don't roll, we just hit them with damage
302     */
303     if ((int) op->stats.wc >= NUM_ANIMATIONS (op) / 2)
304     {
305     /* Halfway or further, check blocks */
306     /* First, get the top object on the square. */
307 root 1.46 for (tmp = op->above; tmp && tmp->above; tmp = tmp->above)
308     ;
309 root 1.9
310 root 1.46 if (tmp)
311 root 1.9 {
312     if (QUERY_FLAG (tmp, FLAG_ALIVE))
313     {
314 root 1.46 hit_player (tmp, random_roll (0, op->stats.dam, tmp, PREFER_LOW), op, AT_PHYSICAL, 1);
315    
316 root 1.9 if (tmp->type == PLAYER)
317     new_draw_info_format (NDI_UNIQUE, 0, tmp, "You are crushed by the %s!", &op->name);
318     }
319     else
320     /* If the object is not alive, and the object either can
321     * be picked up or the object rolls, move the object
322     * off the gate.
323     */
324     if (!QUERY_FLAG (tmp, FLAG_ALIVE) && (!QUERY_FLAG (tmp, FLAG_NO_PICK) || QUERY_FLAG (tmp, FLAG_CAN_ROLL)))
325     {
326     /* If it has speed, it should move itself, otherwise: */
327     int i = find_free_spot (tmp, op->map, op->x, op->y, 1, 9);
328    
329     /* If there is a free spot, move the object someplace */
330     if (i != -1)
331     {
332 root 1.16 tmp->remove ();
333 root 1.9 tmp->x += freearr_x[i], tmp->y += freearr_y[i];
334     insert_ob_in_map (tmp, op->map, op, 0);
335 root 1.6 }
336     }
337     }
338    
339 root 1.9 /* See if there is still anything blocking the gate */
340     for (tmp = op->above; tmp != NULL; tmp = tmp->above)
341     if (!QUERY_FLAG (tmp, FLAG_NO_PICK) || QUERY_FLAG (tmp, FLAG_CAN_ROLL) || QUERY_FLAG (tmp, FLAG_ALIVE))
342     break;
343    
344     /* IF there is, start putting the gate down */
345     if (tmp)
346     {
347     op->stats.food = 1;
348     }
349     else
350     {
351     op->move_block = MOVE_ALL;
352     if (!op->arch->clone.stats.ac)
353     SET_FLAG (op, FLAG_BLOCKSVIEW);
354     update_all_los (op->map, op->x, op->y);
355     }
356     } /* gate is halfway up */
357    
358     SET_ANIMATION (op, op->stats.wc);
359     update_object (op, UP_OBJ_CHANGE);
360     } /* gate is going up */
361 elmex 1.1 }
362    
363     /* hp : how long door is open/closed
364     * maxhp : initial value for hp
365     * sp : 1 = open, 0 = close
366     */
367 root 1.9 void
368     move_timed_gate (object *op)
369 elmex 1.1 {
370     int v = op->value;
371    
372 root 1.9 if (op->stats.sp)
373     {
374     move_gate (op);
375     if (op->value != v) /* change direction ? */
376     op->stats.sp = 0;
377     return;
378     }
379     if (--op->stats.hp <= 0)
380     { /* keep gate down */
381     move_gate (op);
382     if (op->value != v)
383 root 1.26 op->set_speed (0);
384 elmex 1.1 }
385     }
386    
387     /* slaying: name of the thing the detector is to look for
388     * speed: frequency of 'glances'
389     * connected: connected value of detector
390     * sp: 1 if detection sets buttons
391     * -1 if detection unsets buttons
392     */
393    
394 root 1.9 void
395     move_detector (object *op)
396 elmex 1.1 {
397 root 1.9 object *tmp;
398     int last = op->value;
399     int detected;
400    
401     detected = 0;
402    
403 root 1.20 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp != NULL && !detected; tmp = tmp->above)
404 root 1.9 {
405     object *tmp2;
406    
407     if (op->stats.hp)
408     {
409     for (tmp2 = tmp->inv; tmp2; tmp2 = tmp2->below)
410     {
411 root 1.37 if (op->slaying && op->slaying == tmp->name)
412 root 1.9 detected = 1;
413 root 1.37
414     if (tmp2->type == FORCE && tmp2->slaying && tmp2->slaying == op->slaying)
415 root 1.9 detected = 1;
416     }
417     }
418 root 1.37
419     if (op->slaying && op->slaying == tmp->name)
420     detected = 1;
421 root 1.9 else if (tmp->type == SPECIAL_KEY && tmp->slaying == op->slaying)
422     detected = 1;
423 elmex 1.1 }
424    
425 root 1.9 /* the detector sets the button if detection is found */
426     if (op->stats.sp == 1)
427     {
428     if (detected && last == 0)
429     {
430     op->value = 1;
431     push_button (op);
432 root 1.6 }
433 root 1.9 if (!detected && last == 1)
434     {
435     op->value = 0;
436     push_button (op);
437 root 1.6 }
438 elmex 1.1 }
439 root 1.9 else
440     { /* in this case, we unset buttons */
441     if (detected && last == 1)
442     {
443     op->value = 0;
444     push_button (op);
445 root 1.6 }
446 root 1.9 if (!detected && last == 0)
447     {
448     op->value = 1;
449     push_button (op);
450 root 1.6 }
451 elmex 1.1 }
452     }
453    
454    
455 root 1.9 void
456     animate_trigger (object *op)
457 elmex 1.1 {
458 root 1.9 if ((unsigned char) ++op->stats.wc >= NUM_ANIMATIONS (op))
459     {
460     op->stats.wc = 0;
461     check_trigger (op, NULL);
462     }
463     else
464     {
465     SET_ANIMATION (op, op->stats.wc);
466     update_object (op, UP_OBJ_FACE);
467     }
468 elmex 1.1 }
469    
470 root 1.9 void
471     move_hole (object *op)
472     { /* 1 = opening, 0 = closing */
473     object *next, *tmp;
474    
475     if (op->value)
476     { /* We're opening */
477     if (--op->stats.wc <= 0)
478     { /* Opened, let's stop */
479     op->stats.wc = 0;
480 root 1.26 op->set_speed (0);
481 root 1.9
482     /* Hard coding this makes sense for holes I suppose */
483     op->move_on = MOVE_WALK;
484     for (tmp = op->above; tmp != NULL; tmp = next)
485     {
486     next = tmp->above;
487     move_apply (op, tmp, tmp);
488 root 1.6 }
489     }
490 root 1.26
491 root 1.9 SET_ANIMATION (op, op->stats.wc);
492     update_object (op, UP_OBJ_FACE);
493     return;
494 elmex 1.1 }
495 root 1.9 /* We're closing */
496     op->move_on = 0;
497 elmex 1.1
498 root 1.9 op->stats.wc++;
499     if ((int) op->stats.wc >= NUM_ANIMATIONS (op))
500     op->stats.wc = NUM_ANIMATIONS (op) - 1;
501 root 1.26
502 root 1.9 SET_ANIMATION (op, op->stats.wc);
503     update_object (op, UP_OBJ_FACE);
504     if ((unsigned char) op->stats.wc == (NUM_ANIMATIONS (op) - 1))
505 root 1.26 op->set_speed (0); /* closed, let's stop */
506 elmex 1.1 }
507    
508    
509     /* stop_item() returns a pointer to the stopped object. The stopped object
510     * may or may not have been removed from maps or inventories. It will not
511     * have been merged with other items.
512     *
513     * This function assumes that only items on maps need special treatment.
514     *
515     * If the object can't be stopped, or it was destroyed while trying to stop
516     * it, NULL is returned.
517     *
518     * fix_stopped_item() should be used if the stopped item should be put on
519     * the map.
520     */
521 root 1.9 object *
522     stop_item (object *op)
523 elmex 1.1 {
524 root 1.9 if (op->map == NULL)
525     return op;
526 elmex 1.1
527 root 1.9 switch (op->type)
528 elmex 1.1 {
529 root 1.10 case THROWN_OBJ:
530     {
531     object *payload = op->inv;
532 root 1.9
533 root 1.10 if (payload == NULL)
534     return NULL;
535 root 1.16 payload->remove ();
536 root 1.17 op->destroy ();
537 root 1.10 return payload;
538     }
539 elmex 1.1
540 root 1.10 case ARROW:
541 elmex 1.29 if (op->has_active_speed ())
542 root 1.10 op = fix_stopped_arrow (op);
543     return op;
544 elmex 1.1
545 root 1.10 default:
546     return op;
547 elmex 1.1 }
548     }
549    
550     /* fix_stopped_item() - put stopped item where stop_item() had found it.
551     * Inserts item into the old map, or merges it if it already is on the map.
552     *
553     * 'map' must be the value of op->map before stop_item() was called.
554     */
555 root 1.9 void
556 root 1.13 fix_stopped_item (object *op, maptile *map, object *originator)
557 elmex 1.1 {
558 root 1.9 if (map == NULL)
559     return;
560 root 1.40
561 root 1.9 if (QUERY_FLAG (op, FLAG_REMOVED))
562     insert_ob_in_map (op, map, originator, 0);
563     else if (op->type == ARROW)
564     merge_ob (op, NULL); /* only some arrows actually need this */
565 elmex 1.1 }
566    
567 root 1.9 object *
568     fix_stopped_arrow (object *op)
569     {
570     if (rndm (0, 99) < op->stats.food)
571     {
572     /* Small chance of breaking */
573 root 1.17 op->destroy ();
574 root 1.9 return NULL;
575     }
576    
577 root 1.26 op->set_speed (0);
578 root 1.9 op->direction = 0;
579 root 1.47 op->move_on = 0;
580 root 1.9 op->move_type = 0;
581 root 1.47 op->skill = 0; // really?
582    
583     // restore original wc, dam, attacktype and slaying
584     op->stats.wc = op->stats.sp;
585     op->stats.dam = op->stats.hp;
586 root 1.9 op->attacktype = op->stats.grace;
587    
588 root 1.47 if (op->spellarg)
589 root 1.9 {
590     op->slaying = op->spellarg;
591     free (op->spellarg);
592 root 1.47 op->spellarg = 0;
593 root 1.9 }
594     else
595 root 1.47 op->slaying = 0;
596 root 1.9
597 root 1.18 /* Reset these to zero, so that object::can_merge will work properly */
598 root 1.9 op->spellarg = NULL;
599     op->stats.sp = 0;
600     op->stats.hp = 0;
601     op->stats.grace = 0;
602     op->level = 0;
603     op->face = op->arch->clone.face;
604     op->owner = NULL; /* So that stopped arrows will be saved */
605 root 1.40 update_object (op, UP_OBJ_CHANGE);
606 root 1.9 return op;
607 elmex 1.1 }
608    
609     /* stop_arrow() - what to do when a non-living flying object
610     * has to stop. Sept 96 - I added in thrown object code in
611     * here too. -b.t.
612     *
613     * Returns a pointer to the stopped object (which will have been removed
614     * from maps or inventories), or NULL if was destroyed.
615     */
616 root 1.9 static void
617     stop_arrow (object *op)
618 elmex 1.1 {
619 root 1.9 if (INVOKE_OBJECT (STOP, op))
620     return;
621    
622     if (op->inv)
623     {
624     object *payload = op->inv;
625 root 1.4
626 root 1.16 payload->remove ();
627 root 1.18 payload->owner = 0;
628 root 1.9 insert_ob_in_map (payload, op->map, payload, 0);
629 root 1.17 op->destroy ();
630 root 1.9 }
631     else
632     {
633     op = fix_stopped_arrow (op);
634 root 1.47
635 root 1.9 if (op)
636 root 1.47 merge_ob (op, 0);
637 elmex 1.1 }
638     }
639    
640     /* Move an arrow along its course. op is the arrow or thrown object.
641     */
642 root 1.9 void
643     move_arrow (object *op)
644     {
645     object *tmp;
646     sint16 new_x, new_y;
647     int was_reflected, mflags;
648 root 1.13 maptile *m;
649 root 1.9
650     if (op->map == NULL)
651     {
652     LOG (llevError, "BUG: Arrow had no map.\n");
653 root 1.17 op->destroy ();
654 root 1.9 return;
655 elmex 1.1 }
656    
657 root 1.9 /* we need to stop thrown objects at some point. Like here. */
658     if (op->type == THROWN_OBJ)
659     {
660     /* If the object that the THROWN_OBJ encapsulates disappears,
661     * we need to have this object go away also - otherwise, you get
662     * left over remnants on the map. Where this currently happens
663     * is if the player throws a bomb - the bomb explodes on its own,
664     * but this object sticks around. We could handle the cleanup in the
665     * bomb code, but there are potential other cases where that could happen,
666     * and it is easy enough to clean it up here.
667     */
668     if (op->inv == NULL)
669     {
670 root 1.17 op->destroy ();
671 root 1.9 return;
672 root 1.6 }
673 root 1.14
674 root 1.9 if (op->last_sp-- < 0)
675     {
676     stop_arrow (op);
677     return;
678 root 1.6 }
679 elmex 1.1 }
680    
681 root 1.9 /* if the arrow is moving too slow.. stop it. 0.5 was chosen as lower
682     values look rediculous. */
683     if (op->speed < 0.5 && op->type == ARROW)
684     {
685     stop_arrow (op);
686     return;
687 elmex 1.1 }
688    
689 root 1.9 /* Calculate target map square */
690     new_x = op->x + DIRX (op);
691     new_y = op->y + DIRY (op);
692     was_reflected = 0;
693 elmex 1.1
694 root 1.9 m = op->map;
695     mflags = get_map_flags (m, &m, new_x, new_y, &new_x, &new_y);
696 elmex 1.1
697 root 1.9 if (mflags & P_OUT_OF_MAP)
698     {
699     stop_arrow (op);
700     return;
701 elmex 1.1 }
702    
703 root 1.9 /* only need to look for living creatures if this flag is set */
704     if (mflags & P_IS_ALIVE)
705     {
706 root 1.20 for (tmp = GET_MAP_OB (m, new_x, new_y); tmp != NULL; tmp = tmp->above)
707 root 1.9 if (QUERY_FLAG (tmp, FLAG_ALIVE))
708     break;
709    
710     /* Not really fair, but don't let monsters hit themselves with
711     * their own arrow - this can be because they fire it then
712     * move into it.
713     */
714 root 1.14 if (tmp && tmp != op->owner)
715 root 1.9 {
716     /* Found living object, but it is reflecting the missile. Update
717     * as below. (Note that for living creatures there is a small
718     * chance that reflect_missile fails.)
719     */
720     if (QUERY_FLAG (tmp, FLAG_REFL_MISSILE) && (rndm (0, 99)) < (90 - op->level / 10))
721     {
722 root 1.39 int number = op->face;
723 root 1.9
724     op->direction = absdir (op->direction + 4);
725 root 1.41 update_turn_face (op);
726 root 1.9 was_reflected = 1; /* skip normal movement calculations */
727 root 1.6 }
728 root 1.9 else
729     {
730     /* Attack the object. */
731     op = hit_with_arrow (op, tmp);
732 root 1.14
733     if (!op)
734 root 1.9 return;
735     }
736     } /* if this is not hitting its owner */
737     } /* if there is something alive on this space */
738 root 1.6
739 root 1.9 if (OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, new_x, new_y)))
740     {
741     int retry = 0;
742    
743     /* if the object doesn't reflect, stop the arrow from moving
744     * note that this code will now catch cases where a monster is
745     * on a wall but has reflecting - the arrow won't reflect.
746     * Mapmakers shouldn't put monsters on top of wall in the first
747     * place, so I don't consider that a problem.
748     */
749     if (!QUERY_FLAG (op, FLAG_REFLECTING) || !(rndm (0, 19)))
750     {
751     stop_arrow (op);
752     return;
753     }
754     else
755     {
756     /* If one of the major directions (n,s,e,w), just reverse it */
757     if (op->direction & 1)
758     {
759     op->direction = absdir (op->direction + 4);
760     retry = 1;
761     }
762     /* There were two blocks with identical code -
763     * use this retry here to make this one block
764     * that did the same thing.
765     */
766     while (retry < 2)
767     {
768     int left, right, mflags;
769 root 1.13 maptile *m1;
770 root 1.9 sint16 x1, y1;
771    
772     retry++;
773    
774     /* Need to check for P_OUT_OF_MAP: if the arrow is tavelling
775     * over a corner in a tiled map, it is possible that
776     * op->direction is within an adjacent map but either
777     * op->direction-1 or op->direction+1 does not exist.
778     */
779     mflags = get_map_flags (op->map, &m1, op->x + freearr_x[absdir (op->direction - 1)],
780     op->y + freearr_y[absdir (op->direction - 1)], &x1, &y1);
781     left = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK (op, (GET_MAP_MOVE_BLOCK (m1, x1, y1)));
782    
783     mflags = get_map_flags (op->map, &m1, op->x + freearr_x[absdir (op->direction + 1)],
784     op->y + freearr_y[absdir (op->direction + 1)], &x1, &y1);
785     right = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK (op, (GET_MAP_MOVE_BLOCK (m1, x1, y1)));
786    
787     if (left == right)
788     op->direction = absdir (op->direction + 4);
789     else if (left)
790     op->direction = absdir (op->direction + 2);
791     else if (right)
792     op->direction = absdir (op->direction - 2);
793    
794     mflags = get_map_flags (op->map, &m1, op->x + DIRX (op), op->y + DIRY (op), &x1, &y1);
795    
796     /* If this space is not out of the map and not blocked, valid space -
797     * don't need to retry again.
798     */
799     if (!(mflags & P_OUT_OF_MAP) && !OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m1, x1, y1)))
800     break;
801 root 1.6
802     }
803 root 1.9 /* Couldn't find a direction to move the arrow to - just
804     * top it from moving.
805     */
806     if (retry == 2)
807     {
808     stop_arrow (op);
809     return;
810     }
811     /* update object image for new facing */
812     /* many thrown objects *don't* have more than one face */
813     if (GET_ANIM_ID (op))
814     SET_ANIMATION (op, op->direction);
815     } /* object is reflected */
816     } /* object ran into a wall */
817    
818     /* Move the arrow. */
819 root 1.16 op->remove ();
820 root 1.9 op->x = new_x;
821     op->y = new_y;
822    
823     /* decrease the speed as it flies. 0.05 means a standard bow will shoot
824     * about 17 squares. Tune as needed.
825     */
826     op->speed -= 0.05;
827     insert_ob_in_map (op, m, op, 0);
828 elmex 1.1 }
829    
830     /* This routine doesnt seem to work for "inanimate" objects that
831     * are being carried, ie a held torch leaps from your hands!.
832     * Modified this routine to allow held objects. b.t. */
833    
834 root 1.9 void
835     change_object (object *op)
836     { /* Doesn`t handle linked objs yet */
837     int i, j;
838    
839     if (op->other_arch == NULL)
840     {
841     LOG (llevError, "Change object (%s) without other_arch error.\n", &op->name);
842     return;
843     }
844    
845     /* In non-living items only change when food value is 0 */
846     if (!QUERY_FLAG (op, FLAG_ALIVE))
847     {
848     if (op->stats.food-- > 0)
849     return;
850     else
851     op->stats.food = 1; /* so 1 other_arch is made */
852     }
853 root 1.20
854     object *pl = op->in_player ();
855     object *env = op->env;
856    
857 root 1.16 op->remove ();
858 root 1.9 for (i = 0; i < NROFNEWOBJS (op); i++)
859     {
860 root 1.20 object *tmp = arch_to_object (op->other_arch);
861    
862 root 1.9 if (op->type == LAMP)
863     tmp->stats.food = op->stats.food - 1;
864 root 1.20
865 root 1.9 tmp->stats.hp = op->stats.hp; /* The only variable it keeps. */
866     if (env)
867     {
868     tmp->x = env->x, tmp->y = env->y;
869     tmp = insert_ob_in_ob (tmp, env);
870 root 1.20
871 root 1.9 /* If this object is the players inventory, we need to tell the
872     * client of the change. Insert_ob_in_map takes care of the
873     * updating the client, so we don't need to do that below.
874     */
875 root 1.20 if (pl)
876 root 1.9 {
877     esrv_del_item (pl->contr, op->count);
878     esrv_send_item (pl, tmp);
879     }
880     }
881     else
882     {
883     j = find_first_free_spot (tmp, op->map, op->x, op->y);
884     if (j == -1) /* No free spot */
885 root 1.17 tmp->destroy ();
886 root 1.9 else
887     {
888     tmp->x = op->x + freearr_x[j], tmp->y = op->y + freearr_y[j];
889     insert_ob_in_map (tmp, op->map, op, 0);
890     }
891     }
892     }
893 root 1.17
894     op->destroy ();
895 root 1.9 }
896    
897     void
898     move_teleporter (object *op)
899     {
900     object *tmp, *head = op;
901 elmex 1.1
902 root 1.9 /* if this is a multipart teleporter, handle the other parts
903     * The check for speed isn't strictly needed - basically, if
904     * there is an old multipart teleporter in which the other parts
905     * have speed, we don't really want to call it twice for the same
906     * function - in fact, as written below, part N would get called
907     * N times without the speed check.
908     */
909 elmex 1.29 if (op->more && !op->more->has_active_speed ())
910 root 1.9 move_teleporter (op->more);
911    
912     if (op->head)
913     head = op->head;
914    
915     for (tmp = op->above; tmp != NULL; tmp = tmp->above)
916     if (!QUERY_FLAG (tmp, FLAG_IS_FLOOR))
917     break;
918    
919     /* If nothing above us to move, nothing to do */
920     if (!tmp || QUERY_FLAG (tmp, FLAG_WIZPASS))
921 elmex 1.1 return;
922    
923 root 1.9 if (EXIT_PATH (head))
924     {
925     if (tmp->type == PLAYER)
926     {
927     if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (tmp)))
928     return;
929 root 1.3
930 root 1.28 tmp->enter_exit (head);
931 root 1.6 }
932 root 1.9 else
933     /* Currently only players can transfer maps */
934     return;
935 elmex 1.1 }
936 root 1.9 else if (EXIT_X (head) || EXIT_Y (head))
937     {
938     if (out_of_map (head->map, EXIT_X (head), EXIT_Y (head)))
939     {
940     LOG (llevError, "Removed illegal teleporter.\n");
941 root 1.17 head->destroy ();
942 root 1.9 return;
943 root 1.6 }
944 root 1.17
945 root 1.9 if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (tmp)))
946     return;
947 root 1.17
948 root 1.9 transfer_ob (tmp, EXIT_X (head), EXIT_Y (head), 0, head);
949 elmex 1.1 }
950 root 1.9 else
951     {
952     /* Random teleporter */
953     if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (tmp)))
954     return;
955     teleport (head, TELEPORTER, tmp);
956 elmex 1.1 }
957     }
958    
959    
960     /* This object will teleport someone to a different map
961     and will also apply changes to the player from its inventory.
962     This was invented for giving classes, but there's no reason it
963     can't be generalized.
964     */
965 root 1.9 void
966     move_player_changer (object *op)
967     {
968     object *player;
969     object *walk;
970    
971     if (!op->above || !EXIT_PATH (op))
972     return;
973    
974     /* This isn't all that great - means that the player_mover
975     * needs to be on top.
976     */
977     if (op->above->type == PLAYER)
978     {
979     if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (player)))
980 root 1.34 return;
981    
982 root 1.9 player = op->above;
983    
984 root 1.35 for (walk = op->inv; walk; walk = walk->below)
985 root 1.9 apply_changes_to_player (player, walk);
986    
987 root 1.23 player->update_stats ();
988 root 1.9
989     esrv_send_inventory (op->above, op->above);
990     esrv_update_item (UPD_FACE, op->above, op->above);
991    
992     /* update players death & WoR home-position */
993 root 1.35 if (*EXIT_PATH (op) == '/')
994 root 1.9 {
995 root 1.30 player->contr->savebed_map = EXIT_PATH (op);
996     player->contr->bed_x = EXIT_X (op);
997     player->contr->bed_y = EXIT_Y (op);
998 root 1.9 }
999     else
1000     LOG (llevDebug, "WARNING: destination '%s' in player_changer must be an absolute path!\n", &EXIT_PATH (op));
1001    
1002 root 1.28 op->above->enter_exit (op);
1003 elmex 1.1 }
1004     }
1005    
1006     /* firewalls fire other spells.
1007     * The direction of the wall is stored in op->stats.sp.
1008     * walls can have hp, so they can be torn down.
1009     */
1010 root 1.9 void
1011     move_firewall (object *op)
1012     {
1013     object *spell;
1014 elmex 1.1
1015 root 1.9 if (!op->map)
1016     return; /* dm has created a firewall in his inventory */
1017 elmex 1.1
1018 root 1.9 spell = op->inv;
1019 root 1.24
1020 root 1.9 if (!spell || spell->type != SPELL)
1021     spell = &op->other_arch->clone;
1022 root 1.24
1023 root 1.9 if (!spell)
1024     {
1025 root 1.28 LOG (llevError, "move_firewall: no spell specified (%s, %s, %d, %d)\n", &op->name, &op->map->name, op->x, op->y);
1026 root 1.9 return;
1027 elmex 1.1 }
1028    
1029 root 1.9 cast_spell (op, op, op->stats.sp ? op->stats.sp : rndm (1, 8), spell, NULL);
1030 elmex 1.1 }
1031    
1032     /* move_player_mover: this function takes a "player mover" as an
1033     * argument, and performs the function of a player mover, which is:
1034     *
1035     * a player mover finds any players that are sitting on it. It
1036     * moves them in the op->stats.sp direction. speed is how often it'll move.
1037     * If attacktype is nonzero it will paralyze the player. If lifesave is set,
1038     * it'll dissapear after hp+1 moves. If hp is set and attacktype is set,
1039     * it'll paralyze the victim for hp*his speed/op->speed
1040     */
1041 root 1.9 void
1042     move_player_mover (object *op)
1043     {
1044     object *victim, *nextmover;
1045     int dir = op->stats.sp;
1046     sint16 nx, ny;
1047 root 1.13 maptile *m;
1048 root 1.9
1049     /* Determine direction now for random movers so we do the right thing */
1050     if (!dir)
1051     dir = rndm (1, 8);
1052    
1053 root 1.20 for (victim = GET_MAP_OB (op->map, op->x, op->y); victim != NULL; victim = victim->above)
1054 root 1.9 {
1055     if (QUERY_FLAG (victim, FLAG_ALIVE) && !QUERY_FLAG (victim, FLAG_WIZPASS) &&
1056     (victim->move_type & op->move_type || !victim->move_type))
1057     {
1058    
1059     if (victim->head)
1060     victim = victim->head;
1061    
1062     if (QUERY_FLAG (op, FLAG_LIFESAVE) && op->stats.hp-- < 0)
1063     {
1064 root 1.16 op->remove ();
1065 root 1.9 return;
1066     }
1067 root 1.17
1068 root 1.9 nx = op->x + freearr_x[dir];
1069     ny = op->y + freearr_y[dir];
1070     m = op->map;
1071     if (get_map_flags (m, &m, nx, ny, &nx, &ny) & P_OUT_OF_MAP)
1072     {
1073 root 1.28 LOG (llevError, "move_player_mover: Trying to push player off the map! map=%s (%d, %d)\n", &m->path, op->x, op->y);
1074 root 1.9 return;
1075 root 1.6 }
1076 root 1.9
1077     if (should_director_abort (op, victim))
1078     return;
1079    
1080 root 1.20 for (nextmover = GET_MAP_OB (m, nx, ny); nextmover != NULL; nextmover = nextmover->above)
1081 root 1.9 {
1082     if (nextmover->type == PLAYERMOVER)
1083     nextmover->speed_left = -.99;
1084     if (QUERY_FLAG (nextmover, FLAG_ALIVE))
1085     {
1086     op->speed_left = -1.1; /* wait until the next thing gets out of the way */
1087 root 1.6 }
1088     }
1089    
1090 root 1.9 if (victim->type == PLAYER)
1091     {
1092     /* only level >=1 movers move people */
1093     if (op->level)
1094     {
1095     /* Following is a bit of hack. We need to make sure it
1096     * is cleared, otherwise the player will get stuck in
1097     * place. This can happen if the player used a spell to
1098     * get to this space.
1099     */
1100     victim->contr->fire_on = 0;
1101     victim->speed_left = -FABS (victim->speed);
1102     move_player (victim, dir);
1103 root 1.6 }
1104 root 1.9 else
1105     return;
1106 root 1.6 }
1107 root 1.9 else
1108     move_object (victim, dir);
1109 root 1.6
1110 root 1.9 if (!op->stats.maxsp && op->attacktype)
1111     op->stats.maxsp = 2;
1112 root 1.6
1113 root 1.9 if (op->attacktype)
1114     { /* flag to paralyze the player */
1115 root 1.6
1116 root 1.9 victim->speed_left = -FABS (op->stats.maxsp * victim->speed / op->speed);
1117     /* Not sure why, but for some chars on metalforge, they
1118     * would sometimes get -inf speed_left, and from the
1119     * description, it could only happen here, so just put
1120     * a lower sanity limit. My only guess is that the
1121     * mover has 0 speed.
1122     */
1123     if (victim->speed_left < -5.0)
1124     victim->speed_left = -5.0;
1125 root 1.6 }
1126     }
1127 elmex 1.1 }
1128     }
1129    
1130     /*
1131     * Will duplicate a specified object placed on top of it.
1132     * connected: what will trigger it.
1133     * level: multiplier. 0 to destroy.
1134     * other_arch: the object to look for and duplicate.
1135     */
1136    
1137 root 1.9 void
1138     move_duplicator (object *op)
1139     {
1140     object *tmp;
1141 elmex 1.1
1142 root 1.9 if (!op->other_arch)
1143     {
1144 root 1.28 LOG (llevInfo, "Duplicator with no other_arch! %d %d %s\n", op->x, op->y, op->map ? &op->map->path : "nullmap");
1145 root 1.9 return;
1146 elmex 1.1 }
1147    
1148 root 1.9 if (op->above == NULL)
1149     return;
1150 root 1.37
1151     for (tmp = op->above; tmp; tmp = tmp->above)
1152 root 1.9 {
1153 root 1.37 if (op->other_arch->name == tmp->arch->name)
1154 root 1.9 {
1155     if (op->level <= 0)
1156 root 1.17 tmp->destroy ();
1157 root 1.9 else
1158     {
1159     uint64 new_nrof = (uint64) tmp->nrof * op->level;
1160    
1161     if (new_nrof >= 1UL << 31)
1162     new_nrof = 1UL << 31;
1163 root 1.17
1164 root 1.9 tmp->nrof = new_nrof;
1165 root 1.6 }
1166 root 1.17
1167 root 1.9 break;
1168 root 1.6 }
1169 elmex 1.1 }
1170     }
1171    
1172     /* move_creator (by peterm)
1173     * it has the creator object create it's other_arch right on top of it.
1174     * connected: what will trigger it
1175     * hp: how many times it may create before stopping
1176     * lifesave: if set, it'll never disappear but will go on creating
1177     * everytime it's triggered
1178     * other_arch: the object to create
1179     * Note this can create large objects, however, in that case, it
1180     * has to make sure that there is in fact space for the object.
1181     * It should really do this for small objects also, but there is
1182     * more concern with large objects, most notably a part being placed
1183     * outside of the map which would cause the server to crash
1184     */
1185    
1186 root 1.9 void
1187     move_creator (object *creator)
1188     {
1189     object *new_ob;
1190 elmex 1.1
1191 root 1.9 if (!QUERY_FLAG (creator, FLAG_LIFESAVE) && --creator->stats.hp < 0)
1192     {
1193     creator->stats.hp = -1;
1194     return;
1195 elmex 1.1 }
1196    
1197 root 1.9 if (creator->inv != NULL)
1198     {
1199     object *ob;
1200     int i;
1201     object *ob_to_copy;
1202    
1203     /* select random object from inventory to copy */
1204     ob_to_copy = creator->inv;
1205     for (ob = creator->inv->below, i = 1; ob != NULL; ob = ob->below, i++)
1206     {
1207     if (rndm (0, i) == 0)
1208     {
1209     ob_to_copy = ob;
1210     }
1211     }
1212     new_ob = object_create_clone (ob_to_copy);
1213     CLEAR_FLAG (new_ob, FLAG_IS_A_TEMPLATE);
1214     unflag_inv (new_ob, FLAG_IS_A_TEMPLATE);
1215     }
1216     else
1217     {
1218     if (creator->other_arch == NULL)
1219     {
1220 root 1.28 LOG (llevError, "move_creator: Creator doesn't have other arch set: %s (%s, %d, %d)\n",
1221     &creator->name, &creator->map->path, creator->x, creator->y);
1222 root 1.9 return;
1223 root 1.6 }
1224 elmex 1.1
1225 root 1.9 new_ob = object_create_arch (creator->other_arch);
1226     fix_generated_item (new_ob, creator, 0, 0, GT_MINIMAL);
1227 elmex 1.1 }
1228    
1229 root 1.9 /* Make sure this multipart object fits */
1230     if (new_ob->arch->more && ob_blocked (new_ob, creator->map, creator->x, creator->y))
1231     {
1232 root 1.17 new_ob->destroy ();
1233 root 1.9 return;
1234 elmex 1.1 }
1235    
1236 root 1.9 insert_ob_in_map_at (new_ob, creator->map, creator, 0, creator->x, creator->y);
1237     if (QUERY_FLAG (new_ob, FLAG_FREED))
1238     return;
1239 elmex 1.1
1240 root 1.9 if (creator->slaying)
1241     {
1242     new_ob->name = new_ob->title = creator->slaying;
1243 elmex 1.1 }
1244     }
1245    
1246     /* move_marker --peterm@soda.csua.berkeley.edu
1247     when moved, a marker will search for a player sitting above
1248     it, and insert an invisible, weightless force into him
1249     with a specific code as the slaying field.
1250     At that time, it writes the contents of its own message
1251     field to the player. The marker will decrement hp to
1252     0 and then delete itself every time it grants a mark.
1253     unless hp was zero to start with, in which case it is infinite.*/
1254 root 1.9 void
1255     move_marker (object *op)
1256     {
1257 root 1.22 if (object *tmp = op->ms ().player ())
1258     {
1259     object *tmp2;
1260 root 1.9
1261 root 1.22 /* remove an old force with a slaying field == op->name */
1262     for (tmp2 = tmp->inv; tmp2; tmp2 = tmp2->below)
1263 root 1.36 if (tmp2->type == FORCE && tmp2->slaying && tmp2->slaying == op->name)
1264 root 1.22 {
1265     tmp2->destroy ();
1266     break;
1267     }
1268 root 1.9
1269 root 1.22 /* cycle through his inventory to look for the MARK we want to
1270     * place
1271     */
1272     for (tmp2 = tmp->inv; tmp2; tmp2 = tmp2->below)
1273 root 1.36 if (tmp2->type == FORCE && tmp2->slaying && tmp2->slaying == op->slaying)
1274 root 1.22 break;
1275 root 1.9
1276 root 1.22 /* if we didn't find our own MARK */
1277 root 1.36 if (!tmp2)
1278 root 1.22 {
1279     object *force = get_archetype (FORCE_NAME);
1280 root 1.9
1281 root 1.22 if (op->stats.food)
1282 root 1.9 {
1283 root 1.26 force->set_speed (0.01);
1284 root 1.22 force->speed_left = -op->stats.food;
1285 root 1.9 }
1286 root 1.26 else
1287     force->set_speed (0);
1288    
1289 root 1.22 /* put in the lock code */
1290     force->slaying = op->slaying;
1291    
1292     if (op->lore)
1293     force->lore = op->lore;
1294    
1295     insert_ob_in_ob (force, tmp);
1296     if (op->msg)
1297     new_draw_info (NDI_UNIQUE | NDI_NAVY, 0, tmp, op->msg);
1298 root 1.9
1299 root 1.22 if (op->stats.hp > 0)
1300 root 1.9 {
1301 root 1.22 op->stats.hp--;
1302     if (op->stats.hp == 0)
1303 root 1.9 {
1304 root 1.22 /* marker expires--granted mark number limit */
1305     op->destroy ();
1306     return;
1307 root 1.6 }
1308 root 1.22 }
1309     }
1310     }
1311 root 1.9 }
1312    
1313     int
1314     process_object (object *op)
1315     {
1316     if (QUERY_FLAG (op, FLAG_IS_A_TEMPLATE))
1317     return 0;
1318    
1319     if (INVOKE_OBJECT (TICK, op))
1320     return 0;
1321    
1322     if (QUERY_FLAG (op, FLAG_MONSTER))
1323     if (move_monster (op) || QUERY_FLAG (op, FLAG_FREED))
1324     return 1;
1325    
1326     if (QUERY_FLAG (op, FLAG_ANIMATE) && op->anim_speed == 0)
1327     {
1328 root 1.48 animate_object (op, op->contr ? op->facing : op->direction);
1329 root 1.9
1330     if (QUERY_FLAG (op, FLAG_SEE_ANYWHERE))
1331     make_sure_seen (op);
1332     }
1333 root 1.10
1334 root 1.9 if (QUERY_FLAG (op, FLAG_CHANGING) && !op->state)
1335     {
1336     change_object (op);
1337     return 1;
1338     }
1339 root 1.10
1340 root 1.9 if (QUERY_FLAG (op, FLAG_GENERATOR) && !QUERY_FLAG (op, FLAG_FRIENDLY))
1341     generate_monster (op);
1342    
1343     if (QUERY_FLAG (op, FLAG_IS_USED_UP) && --op->stats.food <= 0)
1344     {
1345     if (QUERY_FLAG (op, FLAG_APPLIED))
1346     remove_force (op);
1347     else
1348     {
1349 root 1.48 /* If necessary, delete the item from the players inventory */
1350 root 1.20 object *pl = op->in_player ();
1351 root 1.9
1352     if (pl)
1353     esrv_del_item (pl->contr, op->count);
1354 root 1.10
1355 root 1.16 op->remove ();
1356 root 1.10
1357 root 1.9 if (QUERY_FLAG (op, FLAG_SEE_ANYWHERE))
1358     make_sure_not_seen (op);
1359 root 1.10
1360 root 1.17 op->destroy ();
1361 root 1.6 }
1362 root 1.10
1363 root 1.9 return 1;
1364 elmex 1.1 }
1365 root 1.11
1366 root 1.9 switch (op->type)
1367     {
1368 root 1.10 case SPELL_EFFECT:
1369     move_spell_effect (op);
1370     return 1;
1371    
1372     case ROD:
1373     case HORN:
1374     regenerate_rod (op);
1375     return 1;
1376    
1377     case FORCE:
1378     case POTION_EFFECT:
1379     remove_force (op);
1380     return 1;
1381 elmex 1.1
1382 root 1.10 case BLINDNESS:
1383     remove_blindness (op);
1384     return 0;
1385    
1386     case POISONING:
1387     poison_more (op);
1388     return 0;
1389    
1390     case DISEASE:
1391     move_disease (op);
1392     return 0;
1393    
1394     case SYMPTOM:
1395     move_symptom (op);
1396     return 0;
1397    
1398     case THROWN_OBJ:
1399     case ARROW:
1400     move_arrow (op);
1401     return 0;
1402    
1403     case DOOR:
1404     remove_door (op);
1405     return 0;
1406    
1407     case LOCKED_DOOR:
1408     remove_door2 (op);
1409     return 0;
1410    
1411     case TELEPORTER:
1412     move_teleporter (op);
1413     return 0;
1414    
1415     case GOLEM:
1416     move_golem (op);
1417     return 0;
1418    
1419     case EARTHWALL:
1420     hit_player (op, 2, op, AT_PHYSICAL, 1);
1421     return 0;
1422    
1423     case FIREWALL:
1424     move_firewall (op);
1425     if (op->stats.maxsp)
1426     animate_turning (op);
1427     return 0;
1428    
1429     case MOOD_FLOOR:
1430     do_mood_floor (op);
1431     return 0;
1432    
1433     case GATE:
1434     move_gate (op);
1435     return 0;
1436    
1437     case TIMED_GATE:
1438     move_timed_gate (op);
1439     return 0;
1440    
1441     case TRIGGER:
1442     case TRIGGER_BUTTON:
1443     case TRIGGER_PEDESTAL:
1444     case TRIGGER_ALTAR:
1445     animate_trigger (op);
1446     return 0;
1447    
1448     case DETECTOR:
1449     move_detector (op);
1450    
1451     case DIRECTOR:
1452     if (op->stats.maxsp)
1453     animate_turning (op);
1454     return 0;
1455    
1456     case HOLE:
1457     move_hole (op);
1458     return 0;
1459    
1460     case DEEP_SWAMP:
1461     move_deep_swamp (op);
1462     return 0;
1463    
1464     case RUNE:
1465     case TRAP:
1466     move_rune (op);
1467     return 0;
1468    
1469     case PLAYERMOVER:
1470     move_player_mover (op);
1471     return 0;
1472    
1473     case CREATOR:
1474     move_creator (op);
1475     return 0;
1476    
1477     case MARKER:
1478     move_marker (op);
1479     return 0;
1480    
1481     case PLAYER_CHANGER:
1482     move_player_changer (op);
1483     return 0;
1484    
1485     case PEACEMAKER:
1486     move_peacemaker (op);
1487     return 0;
1488 elmex 1.1 }
1489    
1490 root 1.9 return 0;
1491 elmex 1.1 }
1492 root 1.48