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

Comparing deliantra/server/server/time.C (file contents):
Revision 1.65 by root, Mon Aug 27 05:40:57 2007 UTC vs.
Revision 1.95 by root, Mon Oct 26 11:31:39 2009 UTC

1/* 1/*
2 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG. 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team 4 * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team 5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen 6 * Copyright (©) 1992,2007 Frank Tore Johansen
7 * 7 *
8 * Crossfire TRT is free software: you can redistribute it and/or modify 8 * Deliantra is free software: you can redistribute it and/or modify it under
9 * it under the terms of the GNU General Public License as published by 9 * the terms of the Affero GNU General Public License as published by the
10 * the Free Software Foundation, either version 3 of the License, or 10 * Free Software Foundation, either version 3 of the License, or (at your
11 * (at your option) any later version. 11 * option) any later version.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the Affero GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * and the GNU General Public License along with this program. If not, see
20 * <http://www.gnu.org/licenses/>.
20 * 21 *
21 * The authors can be reached via e-mail to <crossfire@schmorp.de> 22 * The authors can be reached via e-mail to <support@deliantra.net>
22 */ 23 */
23 24
24/* 25/*
25 * Routines that is executed from objects based on their speed have been 26 * Routines that is executed from objects based on their speed have been
26 * collected in this file. 27 * collected in this file.
34 * so those will be removed shortly (in a cascade like fashion.) 35 * so those will be removed shortly (in a cascade like fashion.)
35 */ 36 */
36void 37void
37remove_door (object *op) 38remove_door (object *op)
38{ 39{
40 for (int i = 1; i < SIZEOFFREE1 + 1; i += 2)
41 {
42 object *tmp;
43 mapxy pos (op);
44 pos.move (i);
45 if (pos.normalise ()
46 && (tmp = present (DOOR, pos.m, pos.x, pos.y)))
47 {
48 tmp->set_speed (0.1f);
49 tmp->speed_left = -0.2f;
50 }
51 }
52
53 if (op->other_arch)
54 {
55 object *tmp = arch_to_object (op->other_arch);
56 tmp->x = op->x;
57 tmp->y = op->y;
58 tmp->map = op->map;
59 tmp->level = op->level;
60 insert_ob_in_map (tmp, op->map, op, 0);
61 }
62
63 op->drop_and_destroy ();
64}
65
66void
67remove_door2 (object *op)
68{
39 int i; 69 int i;
40 object *tmp; 70 object *tmp;
41 71
42 for (i = 1; i < 9; i += 2) 72 for (i = 1; i < 9; i += 2)
73 {
43 if ((tmp = present (DOOR, op->map, op->x + freearr_x[i], op->y + freearr_y[i])) != NULL) 74 tmp = present (LOCKED_DOOR, op->map, op->x + freearr_x[i], op->y + freearr_y[i]);
44 { 75 if (tmp && tmp->slaying == op->slaying)
76 { /* same key both doors */
45 tmp->set_speed (0.1f); 77 tmp->set_speed (0.1f);
46 tmp->speed_left = -0.2f; 78 tmp->speed_left = -0.2f;
47 } 79 }
80 }
48 81
49 if (op->other_arch) 82 if (op->other_arch)
50 { 83 {
51 tmp = arch_to_object (op->other_arch); 84 tmp = arch_to_object (op->other_arch);
52 tmp->x = op->x; 85 tmp->x = op->x;
54 tmp->map = op->map; 87 tmp->map = op->map;
55 tmp->level = op->level; 88 tmp->level = op->level;
56 insert_ob_in_map (tmp, op->map, op, 0); 89 insert_ob_in_map (tmp, op->map, op, 0);
57 } 90 }
58 91
59 op->destroy (); 92 op->drop_and_destroy ();
60}
61
62void
63remove_door2 (object *op)
64{
65 int i;
66 object *tmp;
67
68 for (i = 1; i < 9; i += 2)
69 {
70 tmp = present (LOCKED_DOOR, op->map, op->x + freearr_x[i], op->y + freearr_y[i]);
71 if (tmp && tmp->slaying == op->slaying)
72 { /* same key both doors */
73 tmp->set_speed (0.1f);
74 tmp->speed_left = -0.2f;
75 }
76 }
77
78 if (op->other_arch)
79 {
80 tmp = arch_to_object (op->other_arch);
81 tmp->x = op->x;
82 tmp->y = op->y;
83 tmp->map = op->map;
84 tmp->level = op->level;
85 insert_ob_in_map (tmp, op->map, op, 0);
86 }
87
88 op->destroy ();
89} 93}
90 94
91void 95void
92generate_monster (object *gen) 96generate_monster (object *gen)
93{ 97{
95 return; 99 return;
96 100
97 if (GENERATE_SPEED (gen) && rndm (0, GENERATE_SPEED (gen) - 1)) 101 if (GENERATE_SPEED (gen) && rndm (0, GENERATE_SPEED (gen) - 1))
98 return; 102 return;
99 103
104 // sleeping generators won't generate, this will make monsters like
105 // centipedes not generate more centipedes when being asleep.
106 if (gen->flag [FLAG_SLEEP])
107 return;
108
100 object *op; 109 object *op;
101 int i; 110 int dir;
102 111
103 if (QUERY_FLAG (gen, FLAG_CONTENT_ON_GEN)) 112 if (QUERY_FLAG (gen, FLAG_CONTENT_ON_GEN))
104 { 113 {
105 // either copy one item from the inventory... 114 // either copy one item from the inventory...
106 if (!gen->inv) 115 if (!gen->inv)
110 int index = 0; 119 int index = 0;
111 for (object *tmp = gen->inv; tmp; tmp = tmp->below) 120 for (object *tmp = gen->inv; tmp; tmp = tmp->below)
112 if (!rndm (++index)) 121 if (!rndm (++index))
113 op = tmp; 122 op = tmp;
114 123
115 i = find_free_spot (op, gen->map, gen->x, gen->y, 1, 9); 124 dir = find_free_spot (op, gen->map, gen->x, gen->y, 1, SIZEOFFREE1 + 1);
116 if (i < 0) 125 if (dir < 0)
117 return; 126 return;
118 127
119 op = object_create_clone (op); 128 op = op->deep_clone ();
120 129
121 CLEAR_FLAG (op, FLAG_IS_A_TEMPLATE); 130 CLEAR_FLAG (op, FLAG_IS_A_TEMPLATE);
122 unflag_inv (op, FLAG_IS_A_TEMPLATE); 131 unflag_inv (op, FLAG_IS_A_TEMPLATE);
123 } 132 }
124 else if (gen->other_arch) 133 else if (gen->other_arch)
125 { 134 {
126 // ...or use other_arch 135 // ...or use other_arch
127 i = find_free_spot (gen->other_arch, gen->map, gen->x, gen->y, 1, 9); 136 dir = find_free_spot (gen->other_arch, gen->map, gen->x, gen->y, 1, SIZEOFFREE1 + 1);
128 if (i < 0) 137 if (dir < 0)
129 return; 138 return;
130 139
131 op = arch_to_object (gen->other_arch); 140 op = arch_to_object (gen->other_arch);
132 } 141 }
133 else 142 else
134 return; 143 return;
135 144
136 op->expand_tail (); 145 op->expand_tail ();
137 146
138 if (insert_ob_in_map_at (op, gen->map, gen, 0, gen->x + freearr_x[i], gen->y + freearr_y[i])) 147 mapxy pos (gen); pos.move (dir);
148
149 if (pos.insert (op, gen))
139 { 150 {
140 if (rndm (0, 9)) 151 if (rndm (0, 9))
141 generate_artifact (op, gen->map->difficulty); 152 generate_artifact (op, gen->map->difficulty);
142 153
143 if (op->has_random_items ()) 154 if (op->has_random_items ())
295 } 306 }
296 else 307 else
297 { /* The gate is still going up */ 308 { /* The gate is still going up */
298 op->stats.wc++; 309 op->stats.wc++;
299 310
300 if ((int) op->stats.wc >= (NUM_ANIMATIONS (op))) 311 if (op->stats.wc >= NUM_ANIMATIONS (op))
301 op->stats.wc = (signed char) NUM_ANIMATIONS (op) - 1; 312 op->stats.wc = NUM_ANIMATIONS (op) - 1;
302 313
303 /* If there is something on top of the gate, we try to roll it off. 314 /* If there is something on top of the gate, we try to roll it off.
304 * If a player/monster, we don't roll, we just hit them with damage 315 * If a player/monster, we don't roll, we just hit them with damage
305 */ 316 */
306 if ((int) op->stats.wc >= NUM_ANIMATIONS (op) / 2) 317 if (op->stats.wc >= NUM_ANIMATIONS (op) / 2)
307 { 318 {
308 /* Halfway or further, check blocks */ 319 /* Halfway or further, check blocks */
309 /* First, get the top object on the square. */ 320 /* First, get the top object on the square. */
310 for (tmp = op->above; tmp && tmp->above; tmp = tmp->above) 321 for (tmp = op->above; tmp && tmp->above; tmp = tmp->above)
311 ; 322 ;
325 * off the gate. 336 * off the gate.
326 */ 337 */
327 else if (!QUERY_FLAG (tmp, FLAG_ALIVE) && (!QUERY_FLAG (tmp, FLAG_NO_PICK) || QUERY_FLAG (tmp, FLAG_CAN_ROLL))) 338 else if (!QUERY_FLAG (tmp, FLAG_ALIVE) && (!QUERY_FLAG (tmp, FLAG_NO_PICK) || QUERY_FLAG (tmp, FLAG_CAN_ROLL)))
328 { 339 {
329 /* If it has speed, it should move itself, otherwise: */ 340 /* If it has speed, it should move itself, otherwise: */
330 int i = find_free_spot (tmp, op->map, op->x, op->y, 1, 9); 341 int i = find_free_spot (tmp, op->map, op->x, op->y, 1, SIZEOFFREE1 + 1);
331 342
332 /* If there is a free spot, move the object someplace */ 343 /* If there is a free spot, move the object someplace */
333 if (i != -1) 344 if (i > 0)
334 { 345 {
346 mapxy pos (tmp);
347 pos.move (i);
348 if (pos.normalise ())
335 tmp->remove (); 349 tmp->move_to (pos);
336 tmp->x += freearr_x[i], tmp->y += freearr_y[i];
337 insert_ob_in_map (tmp, op->map, op, 0);
338 } 350 }
339 } 351 }
340 } 352 }
341 353
342 /* See if there is still anything blocking the gate */ 354 /* See if there is still anything blocking the gate */
403 int last = op->value; 415 int last = op->value;
404 int detected; 416 int detected;
405 417
406 detected = 0; 418 detected = 0;
407 419
408 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp && !detected; tmp = tmp->above) 420 for (tmp = op->ms ().bot; tmp && !detected; tmp = tmp->above)
409 { 421 {
410 object *tmp2; 422 object *tmp2;
411 423
412 if (op->stats.hp) 424 if (op->stats.hp)
413 { 425 {
431 if (op->stats.sp == 1) 443 if (op->stats.sp == 1)
432 { 444 {
433 if (detected && last == 0) 445 if (detected && last == 0)
434 { 446 {
435 op->value = 1; 447 op->value = 1;
436 push_button (op); 448 push_button (op, tmp);
437 } 449 }
438 450
439 if (!detected && last == 1) 451 if (!detected && last == 1)
440 { 452 {
441 op->value = 0; 453 op->value = 0;
442 push_button (op); 454 push_button (op, tmp);
443 } 455 }
444 } 456 }
445 else 457 else
446 { /* in this case, we unset buttons */ 458 { /* in this case, we unset buttons */
447 if (detected && last == 1) 459 if (detected && last == 1)
448 { 460 {
449 op->value = 0; 461 op->value = 0;
450 push_button (op); 462 push_button (op, tmp);
451 } 463 }
452 464
453 if (!detected && last == 0) 465 if (!detected && last == 0)
454 { 466 {
455 op->value = 1; 467 op->value = 1;
456 push_button (op); 468 push_button (op, tmp);
457 } 469 }
458 } 470 }
459} 471}
460
461 472
462void 473void
463animate_trigger (object *op) 474animate_trigger (object *op)
464{ 475{
465 if ((unsigned char) ++op->stats.wc >= NUM_ANIMATIONS (op)) 476 if ((unsigned char) ++op->stats.wc >= NUM_ANIMATIONS (op))
475} 486}
476 487
477void 488void
478move_hole (object *op) 489move_hole (object *op)
479{ /* 1 = opening, 0 = closing */ 490{ /* 1 = opening, 0 = closing */
480 object *next, *tmp;
481
482 if (op->value) 491 if (op->value)
483 { /* We're opening */ 492 { /* We're opening */
484 if (--op->stats.wc <= 0) 493 if (--op->stats.wc <= 0)
485 { /* Opened, let's stop */ 494 { /* Opened, let's stop */
486 op->stats.wc = 0; 495 op->stats.wc = 0;
487 op->set_speed (0); 496 op->set_speed (0);
488 497
489 /* Hard coding this makes sense for holes I suppose */ 498 /* Hard coding this makes sense for holes I suppose */
490 op->move_on = MOVE_WALK; 499 op->move_on = MOVE_WALK;
491 for (tmp = op->above; tmp != NULL; tmp = next) 500 for (object *next, *tmp = op->above; tmp; tmp = next)
492 { 501 {
493 next = tmp->above; 502 next = tmp->above;
494 move_apply (op, tmp, tmp); 503 move_apply (op, tmp, tmp);
495 } 504 }
496 } 505 }
497 506
498 SET_ANIMATION (op, op->stats.wc); 507 SET_ANIMATION (op, op->stats.wc);
499 update_object (op, UP_OBJ_FACE); 508 update_object (op, UP_OBJ_FACE);
500 return; 509 return;
501 } 510 }
511
502 /* We're closing */ 512 /* We're closing */
503 op->move_on = 0; 513 op->move_on = 0;
504 514
505 op->stats.wc++; 515 op->stats.wc++;
506 if ((int) op->stats.wc >= NUM_ANIMATIONS (op)) 516 if ((int) op->stats.wc >= NUM_ANIMATIONS (op))
537 { 547 {
538 object *payload = op->inv; 548 object *payload = op->inv;
539 549
540 if (payload == NULL) 550 if (payload == NULL)
541 return NULL; 551 return NULL;
552
542 payload->remove (); 553 payload->remove ();
543 op->destroy (); 554 op->destroy ();
544 return payload; 555 return payload;
545 } 556 }
546 557
589 600
590 // restore original wc, dam, attacktype and slaying 601 // restore original wc, dam, attacktype and slaying
591 op->stats.wc = op->stats.sp; 602 op->stats.wc = op->stats.sp;
592 op->stats.dam = op->stats.hp; 603 op->stats.dam = op->stats.hp;
593 op->attacktype = op->stats.grace; 604 op->attacktype = op->stats.grace;
605 op->slaying = op->custom_name;
594 606
595 if (op->spellarg)
596 {
597 op->slaying = op->spellarg;
598 free (op->spellarg);
599 op->spellarg = 0;
600 }
601 else
602 op->slaying = 0;
603
604 /* Reset these to zero, so that object::can_merge will work properly */ 607 /* Reset these to defaults, so that object::can_merge will work properly */
605 op->spellarg = NULL; 608 op->custom_name = 0;
606 op->stats.sp = 0; 609 op->stats.sp = 0;
607 op->stats.hp = 0; 610 op->stats.hp = 0;
608 op->stats.grace = 0; 611 op->stats.grace = 0;
609 op->level = 0; 612 op->level = 0;
610 op->face = op->arch->face; 613 op->face = op->arch->face;
611 op->owner = NULL; /* So that stopped arrows will be saved */ 614 op->owner = 0;
615
612 update_object (op, UP_OBJ_CHANGE); 616 update_object (op, UP_OBJ_CHANGE);
617
613 return op; 618 return op;
614} 619}
615 620
616/* stop_arrow() - what to do when a non-living flying object 621/* stop_arrow() - what to do when a non-living flying object
617 * has to stop. Sept 96 - I added in thrown object code in 622 * has to stop. Sept 96 - I added in thrown object code in
626 if (INVOKE_OBJECT (STOP, op)) 631 if (INVOKE_OBJECT (STOP, op))
627 return; 632 return;
628 633
629 if (op->inv) 634 if (op->inv)
630 { 635 {
636 // replace this by straightforward drop to ground?
631 object *payload = op->inv; 637 object *payload = op->inv;
632 638
633 payload->remove ();
634 payload->owner = 0; 639 payload->owner = 0;
635 insert_ob_in_map (payload, op->map, payload, 0); 640 insert_ob_in_map (payload, op->map, payload, 0);
636 op->destroy (); 641 op->destroy ();
637 } 642 }
638 else 643 else
647/* Move an arrow along its course. op is the arrow or thrown object. 652/* Move an arrow along its course. op is the arrow or thrown object.
648 */ 653 */
649void 654void
650move_arrow (object *op) 655move_arrow (object *op)
651{ 656{
652 object *tmp;
653 sint16 new_x, new_y;
654 int was_reflected, mflags; 657 int was_reflected;
655 maptile *m;
656 658
657 if (op->map == NULL) 659 if (!op->map)
658 { 660 {
659 LOG (llevError, "BUG: Arrow had no map.\n"); 661 LOG (llevError, "BUG: Arrow had no map.\n");
660 op->destroy (); 662 op->destroy ();
661 return; 663 return;
662 } 664 }
670 * is if the player throws a bomb - the bomb explodes on its own, 672 * is if the player throws a bomb - the bomb explodes on its own,
671 * but this object sticks around. We could handle the cleanup in the 673 * but this object sticks around. We could handle the cleanup in the
672 * bomb code, but there are potential other cases where that could happen, 674 * bomb code, but there are potential other cases where that could happen,
673 * and it is easy enough to clean it up here. 675 * and it is easy enough to clean it up here.
674 */ 676 */
675 if (op->inv == NULL) 677 if (!op->inv)
676 { 678 {
677 op->destroy (); 679 op->destroy ();
678 return; 680 return;
679 } 681 }
680 682
692 stop_arrow (op); 694 stop_arrow (op);
693 return; 695 return;
694 } 696 }
695 697
696 /* Calculate target map square */ 698 /* Calculate target map square */
697 new_x = op->x + DIRX (op);
698 new_y = op->y + DIRY (op);
699 was_reflected = 0; 699 was_reflected = 0;
700 700
701 m = op->map; 701 mapxy pos (op); pos.move (op->direction);
702 mflags = get_map_flags (m, &m, new_x, new_y, &new_x, &new_y);
703 702
704 if (mflags & P_OUT_OF_MAP) 703 if (!pos.normalise ())
705 { 704 {
706 stop_arrow (op); 705 stop_arrow (op);
707 return; 706 return;
708 } 707 }
709 708
710 /* only need to look for living creatures if this flag is set */ 709 /* only need to look for living creatures if this flag is set */
711 if (mflags & P_IS_ALIVE) 710 if (pos->flags () & P_IS_ALIVE)
712 { 711 {
713 for (tmp = GET_MAP_OB (m, new_x, new_y); tmp != NULL; tmp = tmp->above) 712 object *tmp;
713
714 for (tmp = pos->bot; tmp; tmp = tmp->above)
714 if (QUERY_FLAG (tmp, FLAG_ALIVE)) 715 if (QUERY_FLAG (tmp, FLAG_ALIVE))
715 break; 716 break;
716 717
717 /* Not really fair, but don't let monsters hit themselves with 718 /* Not really fair, but don't let monsters hit themselves with
718 * their own arrow - this can be because they fire it then 719 * their own arrow - this can be because they fire it then
741 return; 742 return;
742 } 743 }
743 } /* if this is not hitting its owner */ 744 } /* if this is not hitting its owner */
744 } /* if there is something alive on this space */ 745 } /* if there is something alive on this space */
745 746
746 if (OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, new_x, new_y))) 747 if (OB_TYPE_MOVE_BLOCK (op, pos->move_block))
747 { 748 {
748 int retry = 0; 749 int retry = 0;
749 750
750 /* if the object doesn't reflect, stop the arrow from moving 751 /* if the object doesn't reflect, stop the arrow from moving
751 * note that this code will now catch cases where a monster is 752 * note that this code will now catch cases where a monster is
764 if (op->direction & 1) 765 if (op->direction & 1)
765 { 766 {
766 op->direction = absdir (op->direction + 4); 767 op->direction = absdir (op->direction + 4);
767 retry = 1; 768 retry = 1;
768 } 769 }
770
769 /* There were two blocks with identical code - 771 /* There were two blocks with identical code -
770 * use this retry here to make this one block 772 * use this retry here to make this one block
771 * that did the same thing. 773 * that did the same thing.
772 */ 774 */
773 while (retry < 2) 775 while (retry < 2)
774 { 776 {
775 int left, right, mflags;
776 maptile *m1;
777 sint16 x1, y1;
778
779 retry++; 777 retry++;
780 778
781 /* Need to check for P_OUT_OF_MAP: if the arrow is tavelling 779 /* Need to check for P_OUT_OF_MAP: if the arrow is travelling
782 * over a corner in a tiled map, it is possible that 780 * over a corner in a tiled map, it is possible that
783 * op->direction is within an adjacent map but either 781 * op->direction is within an adjacent map but either
784 * op->direction-1 or op->direction+1 does not exist. 782 * op->direction-1 or op->direction+1 does not exist.
785 */ 783 */
786 mflags = get_map_flags (op->map, &m1, op->x + freearr_x[absdir (op->direction - 1)], 784 mapxy pos1 (pos); pos1.move (absdir (op->direction - 1));
787 op->y + freearr_y[absdir (op->direction - 1)], &x1, &y1); 785 bool left = pos1.normalise () && OB_TYPE_MOVE_BLOCK (op, pos1->move_block);
788 left = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK (op, (GET_MAP_MOVE_BLOCK (m1, x1, y1)));
789 786
790 mflags = get_map_flags (op->map, &m1, op->x + freearr_x[absdir (op->direction + 1)], 787 mapxy pos2 (pos); pos2.move (absdir (op->direction + 1));
791 op->y + freearr_y[absdir (op->direction + 1)], &x1, &y1); 788 bool right = pos2.normalise () && OB_TYPE_MOVE_BLOCK (op, pos2->move_block);
792 right = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK (op, (GET_MAP_MOVE_BLOCK (m1, x1, y1)));
793 789
794 if (left == right) 790 if (left == right)
795 op->direction = absdir (op->direction + 4); 791 op->direction = absdir (op->direction + 4);
796 else if (left) 792 else if (left)
797 op->direction = absdir (op->direction + 2); 793 op->direction = absdir (op->direction + 2);
798 else if (right) 794 else if (right)
799 op->direction = absdir (op->direction - 2); 795 op->direction = absdir (op->direction - 2);
800 796
801 mflags = get_map_flags (op->map, &m1, op->x + DIRX (op), op->y + DIRY (op), &x1, &y1);
802
803 /* If this space is not out of the map and not blocked, valid space - 797 /* If this space is not out of the map and not blocked, valid space -
804 * don't need to retry again. 798 * don't need to retry again.
805 */ 799 */
806 if (!(mflags & P_OUT_OF_MAP) && !OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m1, x1, y1))) 800 mapxy pos3 (pos); pos3.move (op->direction);
801 if (pos3.normalise () && !OB_TYPE_MOVE_BLOCK (op, pos3->move_block))
807 break; 802 break;
808
809 } 803 }
804
810 /* Couldn't find a direction to move the arrow to - just 805 /* Couldn't find a direction to move the arrow to - just
811 * top it from moving. 806 * stop it from moving.
812 */ 807 */
813 if (retry == 2) 808 if (retry == 2)
814 { 809 {
815 stop_arrow (op); 810 stop_arrow (op);
816 return; 811 return;
817 } 812 }
813
818 /* update object image for new facing */ 814 /* update object image for new facing */
819 /* many thrown objects *don't* have more than one face */ 815 /* many thrown objects *don't* have more than one face */
820 if (GET_ANIM_ID (op)) 816 if (op->has_anim ())
821 SET_ANIMATION (op, op->direction); 817 op->set_anim_frame (op->direction);
822 } /* object is reflected */ 818 } /* object is reflected */
823 } /* object ran into a wall */ 819 } /* object ran into a wall */
824
825 /* Move the arrow. */
826 op->remove ();
827 op->x = new_x;
828 op->y = new_y;
829 820
830 /* decrease the speed as it flies. 0.05 means a standard bow will shoot 821 /* decrease the speed as it flies. 0.05 means a standard bow will shoot
831 * about 17 squares. Tune as needed. 822 * about 17 squares. Tune as needed.
832 */ 823 */
833 op->speed -= 0.05; 824 op->speed -= 0.05;
834 insert_ob_in_map (op, m, op, 0);
835}
836 825
837/* This routine doesnt seem to work for "inanimate" objects that 826 /* Move the arrow. */
838 * are being carried, ie a held torch leaps from your hands!. 827 op->move_to (pos);
839 * Modified this routine to allow held objects. b.t. */ 828}
840 829
841void 830void
842change_object (object *op) 831change_object (object *op)
843{ /* Doesn`t handle linked objs yet */ 832{ /* Doesn`t handle linked objs yet */
844 int i, j; 833 int i, j;
845 834
846 if (op->other_arch == NULL) 835 if (!op->other_arch)
847 { 836 {
848 LOG (llevError, "Change object (%s) without other_arch error.\n", &op->name); 837 LOG (llevError, "Change object (%s) without other_arch error.\n", op->debug_desc ());
849 return; 838 return;
850 } 839 }
851 840
852 /* In non-living items only change when food value is 0 */ 841 /* In non-living items only change when food value is 0 */
853 if (!QUERY_FLAG (op, FLAG_ALIVE)) 842 if (!QUERY_FLAG (op, FLAG_ALIVE))
854 { 843 {
855 if (op->stats.food-- > 0) 844 if (op->stats.food-- > 0)
856 return; 845 return;
846
847 op->stats.food = 1; /* so 1 other_arch is made */
848 }
849
850 object *env = op->env;
851
852 op->remove ();
853 for (i = 0; i < op->stats.food; i++)
854 {
855 object *tmp = arch_to_object (op->other_arch);
856
857 tmp->stats.hp = op->stats.hp; /* The only variable it keeps. */
858
859 if (env)
860 env->insert (tmp);
857 else 861 else
858 op->stats.food = 1; /* so 1 other_arch is made */
859 }
860
861 object *pl = op->in_player ();
862 object *env = op->env;
863
864 op->remove ();
865 for (i = 0; i < NROFNEWOBJS (op); i++)
866 {
867 object *tmp = arch_to_object (op->other_arch);
868
869 if (op->type == LAMP)
870 tmp->stats.food = op->stats.food - 1;
871
872 tmp->stats.hp = op->stats.hp; /* The only variable it keeps. */
873 if (env)
874 {
875 tmp->x = env->x, tmp->y = env->y;
876 tmp = insert_ob_in_ob (tmp, env);
877
878 /* If this object is the players inventory, we need to tell the
879 * client of the change. Insert_ob_in_map takes care of the
880 * updating the client, so we don't need to do that below.
881 */
882 if (pl)
883 {
884 esrv_del_item (pl->contr, op->count);
885 esrv_send_item (pl, tmp);
886 }
887 }
888 else
889 { 862 {
890 j = find_first_free_spot (tmp, op->map, op->x, op->y); 863 j = find_first_free_spot (tmp, op->map, op->x, op->y);
891 if (j == -1) /* No free spot */ 864 if (j < 0) /* No free spot */
892 tmp->destroy (); 865 tmp->destroy ();
893 else 866 else
894 { 867 {
895 tmp->x = op->x + freearr_x[j], tmp->y = op->y + freearr_y[j]; 868 mapxy pos (op); pos.move (j);
896 insert_ob_in_map (tmp, op->map, op, 0); 869
870 if (pos.normalise ())
871 pos.insert (tmp, op);
897 } 872 }
898 } 873 }
899 } 874 }
900 875
901 op->destroy (); 876 op->destroy ();
957 else 932 else
958 { 933 {
959 /* Random teleporter */ 934 /* Random teleporter */
960 if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (tmp))) 935 if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (tmp)))
961 return; 936 return;
937
962 teleport (head, TELEPORTER, tmp); 938 teleport (head, TELEPORTER, tmp);
963 } 939 }
964} 940}
965 941
966/* This object will teleport someone to a different map 942/* This object will teleport someone to a different map
1186 { 1162 {
1187 creator->stats.hp = -1; 1163 creator->stats.hp = -1;
1188 return; 1164 return;
1189 } 1165 }
1190 1166
1191 if (creator->inv != NULL) 1167 if (creator->inv)
1192 { 1168 {
1193 object *ob; 1169 object *ob;
1194 int i; 1170 int i;
1195 object *ob_to_copy; 1171 object *ob_to_copy;
1196 1172
1201 if (rndm (0, i) == 0) 1177 if (rndm (0, i) == 0)
1202 { 1178 {
1203 ob_to_copy = ob; 1179 ob_to_copy = ob;
1204 } 1180 }
1205 } 1181 }
1206 new_ob = object_create_clone (ob_to_copy); 1182 new_ob = ob_to_copy->deep_clone ();
1207 CLEAR_FLAG (new_ob, FLAG_IS_A_TEMPLATE); 1183 CLEAR_FLAG (new_ob, FLAG_IS_A_TEMPLATE);
1208 unflag_inv (new_ob, FLAG_IS_A_TEMPLATE); 1184 unflag_inv (new_ob, FLAG_IS_A_TEMPLATE);
1209 } 1185 }
1210 else 1186 else
1211 { 1187 {
1212 if (creator->other_arch == NULL) 1188 if (!creator->other_arch)
1213 { 1189 {
1214 LOG (llevError, "move_creator: Creator doesn't have other arch set: %s (%s, %d, %d)\n", 1190 LOG (llevError, "move_creator: Creator doesn't have other arch set: %s (%s, %d, %d)\n",
1215 &creator->name, &creator->map->path, creator->x, creator->y); 1191 &creator->name, &creator->map->path, creator->x, creator->y);
1216 return; 1192 return;
1217 } 1193 }
1219 new_ob = object_create_arch (creator->other_arch); 1195 new_ob = object_create_arch (creator->other_arch);
1220 fix_generated_item (new_ob, creator, 0, 0, GT_MINIMAL); 1196 fix_generated_item (new_ob, creator, 0, 0, GT_MINIMAL);
1221 } 1197 }
1222 1198
1223 /* Make sure this multipart object fits */ 1199 /* Make sure this multipart object fits */
1224 if (new_ob->arch->more && ob_blocked (new_ob, creator->map, creator->x, creator->y)) 1200 if (new_ob->arch->more && new_ob->blocked (creator->map, creator->x, creator->y))
1225 { 1201 {
1226 new_ob->destroy (); 1202 new_ob->destroy ();
1227 return; 1203 return;
1228 } 1204 }
1229 1205
1234 insert_ob_in_map_at (new_ob, creator->map, creator, 0, creator->x, creator->y); 1210 insert_ob_in_map_at (new_ob, creator->map, creator, 0, creator->x, creator->y);
1235 if (QUERY_FLAG (new_ob, FLAG_FREED)) 1211 if (QUERY_FLAG (new_ob, FLAG_FREED))
1236 return; 1212 return;
1237 1213
1238 if (creator->slaying) 1214 if (creator->slaying)
1239 {
1240 new_ob->name = new_ob->title = creator->slaying; 1215 new_ob->name = new_ob->title = creator->slaying;
1241 }
1242} 1216}
1243 1217
1244/* move_marker --peterm@soda.csua.berkeley.edu 1218/* move_marker --peterm@soda.csua.berkeley.edu
1245 when moved, a marker will search for a player sitting above 1219 when moved, a marker will search for a player sitting above
1246 it, and insert an invisible, weightless force into him 1220 it, and insert an invisible, weightless force into him
1256 { 1230 {
1257 /* remove an old force with a slaying field == op->name */ 1231 /* remove an old force with a slaying field == op->name */
1258 if (object *force = tmp->force_find (op->name)) 1232 if (object *force = tmp->force_find (op->name))
1259 force->destroy (); 1233 force->destroy ();
1260 1234
1261 if (!tmp->force_find (op->slaying)) 1235 if (op->slaying && !tmp->force_find (op->slaying))
1262 { 1236 {
1263 tmp->force_add (op->slaying, op->stats.food); 1237 tmp->force_add (op->slaying, op->stats.food);
1264 1238
1265 if (op->msg) 1239 if (op->msg)
1266 new_draw_info (NDI_UNIQUE | NDI_NAVY, 0, tmp, op->msg); 1240 new_draw_info (NDI_UNIQUE | NDI_NAVY, 0, tmp, op->msg);
1278 } 1252 }
1279 } 1253 }
1280 } 1254 }
1281} 1255}
1282 1256
1257// mapscript objects activate themselves (only) then their timer fires
1258// TODO: maybe they should simply trigger the link like any other object?
1259void
1260move_mapscript (object *op)
1261{
1262 op->set_speed (0);
1263 cfperl_mapscript_activate (op, true, op, 0);
1264}
1265
1266void move_lamp (object *op)
1267{
1268 // if the lamp/torch is off, we should disable it.
1269 if (!op->glow_radius)
1270 {
1271 op->set_speed (0);
1272 return;
1273 }
1274 else
1275 {
1276 // check whether the face might need to be updated
1277 // (currently this is needed to have already switched on torches
1278 // on maps, as they just set the glow_radius in the archetype)
1279 if (op->other_arch
1280 && (
1281 (op->flag [FLAG_ANIMATE] != op->other_arch->flag [FLAG_ANIMATE])
1282 || (op->flag [FLAG_ANIMATE]
1283 ? (op->animation_id != op->other_arch->animation_id)
1284 : (op->face != op->other_arch->face))
1285 ))
1286 get_animation_from_arch (op, op->other_arch);
1287 }
1288
1289 // lamps and torches on maps don't use up their fuel
1290 if (op->is_on_map ())
1291 return;
1292
1293 if (op->stats.food > 0)
1294 {
1295 op->stats.food--;
1296 return;
1297 }
1298
1299 apply_lamp (op, false);
1300}
1301
1283void 1302void
1284process_object (object *op) 1303process_object (object *op)
1285{ 1304{
1286 if (expect_false (QUERY_FLAG (op, FLAG_IS_A_TEMPLATE))) 1305 if (expect_false (QUERY_FLAG (op, FLAG_IS_A_TEMPLATE)))
1287 return; 1306 return;
1320 { 1339 {
1321 if (QUERY_FLAG (op, FLAG_APPLIED)) 1340 if (QUERY_FLAG (op, FLAG_APPLIED))
1322 remove_force (op); 1341 remove_force (op);
1323 else 1342 else
1324 { 1343 {
1325 /* If necessary, delete the item from the players inventory */ 1344 op->remove (); // TODO: really necessary?
1326 object *pl = op->in_player ();
1327
1328 if (pl)
1329 esrv_del_item (pl->contr, op->count);
1330
1331 op->remove ();
1332 1345
1333 if (QUERY_FLAG (op, FLAG_SEE_ANYWHERE)) 1346 if (QUERY_FLAG (op, FLAG_SEE_ANYWHERE))
1334 make_sure_not_seen (op); 1347 make_sure_not_seen (op);
1335 1348
1336 op->destroy (); 1349 op->drop_and_destroy ();
1337 } 1350 }
1338 1351
1339 return; 1352 return;
1340 } 1353 }
1341 } 1354 }
1465 1478
1466 case PLAYER: 1479 case PLAYER:
1467 // players have their own speed-management, so undo the --speed_left 1480 // players have their own speed-management, so undo the --speed_left
1468 ++op->speed_left; 1481 ++op->speed_left;
1469 break; 1482 break;
1470 }
1471}
1472 1483
1484 case MAPSCRIPT:
1485 move_mapscript (op);
1486 break;
1487
1488 case LAMP:
1489 case TORCH:
1490 move_lamp (op);
1491 break;
1492 }
1493}
1494

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines