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.60 by root, Thu Jul 5 08:10:30 2007 UTC vs.
Revision 1.72 by root, Thu Nov 8 19:43:29 2007 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 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
9 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or 10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version. 11 * (at your 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,
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 GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * 20 *
21 * The authors can be reached via e-mail to <crossfire@schmorp.de> 21 * The authors can be reached via e-mail to <support@deliantra.net>
22 */ 22 */
23 23
24/* 24/*
25 * Routines that is executed from objects based on their speed have been 25 * Routines that is executed from objects based on their speed have been
26 * collected in this file. 26 * collected in this file.
34 * so those will be removed shortly (in a cascade like fashion.) 34 * so those will be removed shortly (in a cascade like fashion.)
35 */ 35 */
36void 36void
37remove_door (object *op) 37remove_door (object *op)
38{ 38{
39 for (int i = 1; i < SIZEOFFREE1 + 1; i += 2)
40 {
41 object *tmp;
42 mapxy pos (op);
43 pos.move (i);
44 if (pos.normalise ()
45 && (tmp = present (DOOR, pos.m, pos.x, pos.y)))
46 {
47 tmp->set_speed (0.1f);
48 tmp->speed_left = -0.2f;
49 }
50 }
51
52 if (op->other_arch)
53 {
54 object *tmp = arch_to_object (op->other_arch);
55 tmp->x = op->x;
56 tmp->y = op->y;
57 tmp->map = op->map;
58 tmp->level = op->level;
59 insert_ob_in_map (tmp, op->map, op, 0);
60 }
61
62 op->destroy ();
63}
64
65void
66remove_door2 (object *op)
67{
39 int i; 68 int i;
40 object *tmp; 69 object *tmp;
41 70
42 for (i = 1; i < 9; i += 2) 71 for (i = 1; i < 9; i += 2)
72 {
43 if ((tmp = present (DOOR, op->map, op->x + freearr_x[i], op->y + freearr_y[i])) != NULL) 73 tmp = present (LOCKED_DOOR, op->map, op->x + freearr_x[i], op->y + freearr_y[i]);
44 { 74 if (tmp && tmp->slaying == op->slaying)
75 { /* same key both doors */
45 tmp->set_speed (0.1f); 76 tmp->set_speed (0.1f);
46 tmp->speed_left = -0.2f; 77 tmp->speed_left = -0.2f;
47 } 78 }
79 }
48 80
49 if (op->other_arch) 81 if (op->other_arch)
50 { 82 {
51 tmp = arch_to_object (op->other_arch); 83 tmp = arch_to_object (op->other_arch);
52 tmp->x = op->x; 84 tmp->x = op->x;
58 90
59 op->destroy (); 91 op->destroy ();
60} 92}
61 93
62void 94void
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}
90
91void
92generate_monster (object *gen) 95generate_monster (object *gen)
93{ 96{
94 if (!gen->map) 97 if (!gen->map)
95 return; 98 return;
96 99
97 if (GENERATE_SPEED (gen) && rndm (0, GENERATE_SPEED (gen) - 1)) 100 if (GENERATE_SPEED (gen) && rndm (0, GENERATE_SPEED (gen) - 1))
98 return; 101 return;
99 102
100 object *op; 103 object *op;
104 int dir;
101 105
102 if (QUERY_FLAG (gen, FLAG_CONTENT_ON_GEN)) 106 if (QUERY_FLAG (gen, FLAG_CONTENT_ON_GEN))
103 { 107 {
104 // either copy one item from the inventory... 108 // either copy one item from the inventory...
105 if (!gen->inv) 109 if (!gen->inv)
109 int index = 0; 113 int index = 0;
110 for (object *tmp = gen->inv; tmp; tmp = tmp->below) 114 for (object *tmp = gen->inv; tmp; tmp = tmp->below)
111 if (!rndm (++index)) 115 if (!rndm (++index))
112 op = tmp; 116 op = tmp;
113 117
118 dir = find_free_spot (op, gen->map, gen->x, gen->y, 1, SIZEOFFREE1 + 1);
119 if (dir < 0)
120 return;
121
114 op = object_create_clone (op); 122 op = object_create_clone (op);
115 123
116 CLEAR_FLAG (op, FLAG_IS_A_TEMPLATE); 124 CLEAR_FLAG (op, FLAG_IS_A_TEMPLATE);
117 unflag_inv (op, FLAG_IS_A_TEMPLATE); 125 unflag_inv (op, FLAG_IS_A_TEMPLATE);
118 } 126 }
119 else if (gen->other_arch) 127 else if (gen->other_arch)
120 { 128 {
121 // ...or use other_arch 129 // ...or use other_arch
130 dir = find_free_spot (gen->other_arch, gen->map, gen->x, gen->y, 1, SIZEOFFREE1 + 1);
131 if (dir < 0)
132 return;
133
122 op = arch_to_object (gen->other_arch); 134 op = arch_to_object (gen->other_arch);
123 } 135 }
124 else 136 else
125 return; 137 return;
126 138
127 op->expand_tail (); 139 op->expand_tail ();
128 140
129 int i = find_free_spot (op, gen->map, gen->x, gen->y, 1, 9); 141 mapxy pos (gen); pos.move (dir);
130 if (i >= 0) 142
143 if (pos.insert (op, gen))
131 { 144 {
132 if (insert_ob_in_map_at (op, gen->map, gen, 0, gen->x + freearr_x[i], gen->y + freearr_y[i]))
133 {
134 if (rndm (0, 9)) 145 if (rndm (0, 9))
135 generate_artifact (op, gen->map->difficulty); 146 generate_artifact (op, gen->map->difficulty);
136 147
137 if (op->has_random_items ()) 148 if (op->has_random_items ())
138 create_treasure (op->randomitems, op, GT_APPLY, gen->map->difficulty); 149 create_treasure (op->randomitems, op, GT_APPLY, gen->map->difficulty);
139 150
140 return; 151 return;
141 }
142 } 152 }
143 153
144 op->destroy (); 154 op->destroy ();
145} 155}
146 156
147void 157void
148remove_force (object *op) 158remove_force (object *op)
149{ 159{
150 fprintf (stderr, "duration %s %d\n", &op->name, op->duration);//D
151 if (--op->duration > 0) 160 if (--op->duration > 0)
152 return; 161 return;
153 162
154 if (op->env) 163 if (op->env)
155 switch (op->subtype) 164 switch (op->subtype)
264 * objects are above the gate. If so, we finish closing the gate, 273 * objects are above the gate. If so, we finish closing the gate,
265 * otherwise, we fall through to the code below which should lower 274 * otherwise, we fall through to the code below which should lower
266 * the gate slightly. 275 * the gate slightly.
267 */ 276 */
268 277
269 for (tmp = op->above; tmp != NULL; tmp = tmp->above) 278 for (tmp = op->above; tmp; tmp = tmp->above)
270 if (!QUERY_FLAG (tmp, FLAG_NO_PICK) || QUERY_FLAG (tmp, FLAG_CAN_ROLL) || QUERY_FLAG (tmp, FLAG_ALIVE)) 279 if (!QUERY_FLAG (tmp, FLAG_NO_PICK) || QUERY_FLAG (tmp, FLAG_CAN_ROLL) || QUERY_FLAG (tmp, FLAG_ALIVE))
271 break; 280 break;
272 281
273 if (tmp == NULL) 282 if (!tmp)
274 { 283 {
275 if (op->arch->speed) 284 if (op->arch->speed)
276 op->value = 1; 285 op->value = 1;
277 else 286 else
278 op->set_speed (0); 287 op->set_speed (0);
291 } 300 }
292 else 301 else
293 { /* The gate is still going up */ 302 { /* The gate is still going up */
294 op->stats.wc++; 303 op->stats.wc++;
295 304
296 if ((int) op->stats.wc >= (NUM_ANIMATIONS (op))) 305 if (op->stats.wc >= NUM_ANIMATIONS (op))
297 op->stats.wc = (signed char) NUM_ANIMATIONS (op) - 1; 306 op->stats.wc = NUM_ANIMATIONS (op) - 1;
298 307
299 /* If there is something on top of the gate, we try to roll it off. 308 /* If there is something on top of the gate, we try to roll it off.
300 * If a player/monster, we don't roll, we just hit them with damage 309 * If a player/monster, we don't roll, we just hit them with damage
301 */ 310 */
302 if ((int) op->stats.wc >= NUM_ANIMATIONS (op) / 2) 311 if (op->stats.wc >= NUM_ANIMATIONS (op) / 2)
303 { 312 {
304 /* Halfway or further, check blocks */ 313 /* Halfway or further, check blocks */
305 /* First, get the top object on the square. */ 314 /* First, get the top object on the square. */
306 for (tmp = op->above; tmp && tmp->above; tmp = tmp->above) 315 for (tmp = op->above; tmp && tmp->above; tmp = tmp->above)
307 ; 316 ;
309 if (tmp) 318 if (tmp)
310 { 319 {
311 if (QUERY_FLAG (tmp, FLAG_ALIVE)) 320 if (QUERY_FLAG (tmp, FLAG_ALIVE))
312 { 321 {
313 hit_player (tmp, random_roll (0, op->stats.dam, tmp, PREFER_LOW), op, AT_PHYSICAL, 1); 322 hit_player (tmp, random_roll (0, op->stats.dam, tmp, PREFER_LOW), op, AT_PHYSICAL, 1);
323 op->play_sound (sound_find ("blocked_gate"));
314 324
315 if (tmp->type == PLAYER) 325 if (tmp->type == PLAYER)
316 new_draw_info_format (NDI_UNIQUE, 0, tmp, "You are crushed by the %s!", &op->name); 326 new_draw_info_format (NDI_UNIQUE, 0, tmp, "You are crushed by the %s!", &op->name);
317 } 327 }
318 else
319 /* If the object is not alive, and the object either can 328 /* If the object is not alive, and the object either can
320 * be picked up or the object rolls, move the object 329 * be picked up or the object rolls, move the object
321 * off the gate. 330 * off the gate.
322 */ 331 */
323 if (!QUERY_FLAG (tmp, FLAG_ALIVE) && (!QUERY_FLAG (tmp, FLAG_NO_PICK) || QUERY_FLAG (tmp, FLAG_CAN_ROLL))) 332 else if (!QUERY_FLAG (tmp, FLAG_ALIVE) && (!QUERY_FLAG (tmp, FLAG_NO_PICK) || QUERY_FLAG (tmp, FLAG_CAN_ROLL)))
324 { 333 {
325 /* If it has speed, it should move itself, otherwise: */ 334 /* If it has speed, it should move itself, otherwise: */
326 int i = find_free_spot (tmp, op->map, op->x, op->y, 1, 9); 335 int i = find_free_spot (tmp, op->map, op->x, op->y, 1, SIZEOFFREE1 + 1);
327 336
328 /* If there is a free spot, move the object someplace */ 337 /* If there is a free spot, move the object someplace */
329 if (i != -1) 338 if (i > 0)
330 { 339 {
340 mapxy pos (tmp);
341 pos.move (i);
342 if (pos.normalise ())
331 tmp->remove (); 343 tmp->move_to (pos);
332 tmp->x += freearr_x[i], tmp->y += freearr_y[i];
333 insert_ob_in_map (tmp, op->map, op, 0);
334 } 344 }
335 } 345 }
336 } 346 }
337 347
338 /* See if there is still anything blocking the gate */ 348 /* See if there is still anything blocking the gate */
339 for (tmp = op->above; tmp != NULL; tmp = tmp->above) 349 for (tmp = op->above; tmp; tmp = tmp->above)
340 if (!QUERY_FLAG (tmp, FLAG_NO_PICK) || QUERY_FLAG (tmp, FLAG_CAN_ROLL) || QUERY_FLAG (tmp, FLAG_ALIVE)) 350 if (!QUERY_FLAG (tmp, FLAG_NO_PICK) || QUERY_FLAG (tmp, FLAG_CAN_ROLL) || QUERY_FLAG (tmp, FLAG_ALIVE))
341 break; 351 break;
342 352
343 /* IF there is, start putting the gate down */ 353 /* IF there is, start putting the gate down */
344 if (tmp) 354 if (tmp)
345 {
346 op->stats.food = 1; 355 op->stats.food = 1;
347 }
348 else 356 else
349 { 357 {
350 op->move_block = MOVE_ALL; 358 op->move_block = MOVE_ALL;
359
351 if (!op->arch->stats.ac) 360 if (!op->arch->stats.ac)
352 SET_FLAG (op, FLAG_BLOCKSVIEW); 361 SET_FLAG (op, FLAG_BLOCKSVIEW);
353 update_all_los (op->map, op->x, op->y); 362 update_all_los (op->map, op->x, op->y);
354 } 363 }
355 } /* gate is halfway up */ 364 } /* gate is halfway up */
369 int v = op->value; 378 int v = op->value;
370 379
371 if (op->stats.sp) 380 if (op->stats.sp)
372 { 381 {
373 move_gate (op); 382 move_gate (op);
383
374 if (op->value != v) /* change direction ? */ 384 if (op->value != v) /* change direction ? */
375 op->stats.sp = 0; 385 op->stats.sp = 0;
376 return; 386 return;
377 } 387 }
388
378 if (--op->stats.hp <= 0) 389 if (--op->stats.hp <= 0)
379 { /* keep gate down */ 390 { /* keep gate down */
380 move_gate (op); 391 move_gate (op);
392
381 if (op->value != v) 393 if (op->value != v)
382 op->set_speed (0); 394 op->set_speed (0);
383 } 395 }
384} 396}
385 397
397 int last = op->value; 409 int last = op->value;
398 int detected; 410 int detected;
399 411
400 detected = 0; 412 detected = 0;
401 413
402 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp != NULL && !detected; tmp = tmp->above) 414 for (tmp = op->ms ().bot; tmp && !detected; tmp = tmp->above)
403 { 415 {
404 object *tmp2; 416 object *tmp2;
405 417
406 if (op->stats.hp) 418 if (op->stats.hp)
407 { 419 {
427 if (detected && last == 0) 439 if (detected && last == 0)
428 { 440 {
429 op->value = 1; 441 op->value = 1;
430 push_button (op); 442 push_button (op);
431 } 443 }
444
432 if (!detected && last == 1) 445 if (!detected && last == 1)
433 { 446 {
434 op->value = 0; 447 op->value = 0;
435 push_button (op); 448 push_button (op);
436 } 449 }
440 if (detected && last == 1) 453 if (detected && last == 1)
441 { 454 {
442 op->value = 0; 455 op->value = 0;
443 push_button (op); 456 push_button (op);
444 } 457 }
458
445 if (!detected && last == 0) 459 if (!detected && last == 0)
446 { 460 {
447 op->value = 1; 461 op->value = 1;
448 push_button (op); 462 push_button (op);
449 } 463 }
450 } 464 }
451} 465}
452
453 466
454void 467void
455animate_trigger (object *op) 468animate_trigger (object *op)
456{ 469{
457 if ((unsigned char) ++op->stats.wc >= NUM_ANIMATIONS (op)) 470 if ((unsigned char) ++op->stats.wc >= NUM_ANIMATIONS (op))
489 502
490 SET_ANIMATION (op, op->stats.wc); 503 SET_ANIMATION (op, op->stats.wc);
491 update_object (op, UP_OBJ_FACE); 504 update_object (op, UP_OBJ_FACE);
492 return; 505 return;
493 } 506 }
507
494 /* We're closing */ 508 /* We're closing */
495 op->move_on = 0; 509 op->move_on = 0;
496 510
497 op->stats.wc++; 511 op->stats.wc++;
498 if ((int) op->stats.wc >= NUM_ANIMATIONS (op)) 512 if ((int) op->stats.wc >= NUM_ANIMATIONS (op))
639/* Move an arrow along its course. op is the arrow or thrown object. 653/* Move an arrow along its course. op is the arrow or thrown object.
640 */ 654 */
641void 655void
642move_arrow (object *op) 656move_arrow (object *op)
643{ 657{
644 object *tmp;
645 sint16 new_x, new_y;
646 int was_reflected, mflags; 658 int was_reflected;
647 maptile *m;
648 659
649 if (op->map == NULL) 660 if (!op->map)
650 { 661 {
651 LOG (llevError, "BUG: Arrow had no map.\n"); 662 LOG (llevError, "BUG: Arrow had no map.\n");
652 op->destroy (); 663 op->destroy ();
653 return; 664 return;
654 } 665 }
684 stop_arrow (op); 695 stop_arrow (op);
685 return; 696 return;
686 } 697 }
687 698
688 /* Calculate target map square */ 699 /* Calculate target map square */
689 new_x = op->x + DIRX (op);
690 new_y = op->y + DIRY (op);
691 was_reflected = 0; 700 was_reflected = 0;
692 701
693 m = op->map; 702 mapxy pos (op); pos.move (op->direction);
694 mflags = get_map_flags (m, &m, new_x, new_y, &new_x, &new_y);
695 703
696 if (mflags & P_OUT_OF_MAP) 704 if (!pos.normalise ())
697 { 705 {
698 stop_arrow (op); 706 stop_arrow (op);
699 return; 707 return;
700 } 708 }
701 709
702 /* only need to look for living creatures if this flag is set */ 710 /* only need to look for living creatures if this flag is set */
703 if (mflags & P_IS_ALIVE) 711 if (pos->flags () & P_IS_ALIVE)
704 { 712 {
705 for (tmp = GET_MAP_OB (m, new_x, new_y); tmp != NULL; tmp = tmp->above) 713 object *tmp;
714
715 for (tmp = pos->bot; tmp; tmp = tmp->above)
706 if (QUERY_FLAG (tmp, FLAG_ALIVE)) 716 if (QUERY_FLAG (tmp, FLAG_ALIVE))
707 break; 717 break;
708 718
709 /* Not really fair, but don't let monsters hit themselves with 719 /* Not really fair, but don't let monsters hit themselves with
710 * their own arrow - this can be because they fire it then 720 * their own arrow - this can be because they fire it then
733 return; 743 return;
734 } 744 }
735 } /* if this is not hitting its owner */ 745 } /* if this is not hitting its owner */
736 } /* if there is something alive on this space */ 746 } /* if there is something alive on this space */
737 747
738 if (OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, new_x, new_y))) 748 if (OB_TYPE_MOVE_BLOCK (op, pos->move_block))
739 { 749 {
740 int retry = 0; 750 int retry = 0;
741 751
742 /* if the object doesn't reflect, stop the arrow from moving 752 /* if the object doesn't reflect, stop the arrow from moving
743 * note that this code will now catch cases where a monster is 753 * note that this code will now catch cases where a monster is
756 if (op->direction & 1) 766 if (op->direction & 1)
757 { 767 {
758 op->direction = absdir (op->direction + 4); 768 op->direction = absdir (op->direction + 4);
759 retry = 1; 769 retry = 1;
760 } 770 }
771
761 /* There were two blocks with identical code - 772 /* There were two blocks with identical code -
762 * use this retry here to make this one block 773 * use this retry here to make this one block
763 * that did the same thing. 774 * that did the same thing.
764 */ 775 */
765 while (retry < 2) 776 while (retry < 2)
766 { 777 {
767 int left, right, mflags;
768 maptile *m1;
769 sint16 x1, y1;
770
771 retry++; 778 retry++;
772 779
773 /* Need to check for P_OUT_OF_MAP: if the arrow is tavelling 780 /* Need to check for P_OUT_OF_MAP: if the arrow is travelling
774 * over a corner in a tiled map, it is possible that 781 * over a corner in a tiled map, it is possible that
775 * op->direction is within an adjacent map but either 782 * op->direction is within an adjacent map but either
776 * op->direction-1 or op->direction+1 does not exist. 783 * op->direction-1 or op->direction+1 does not exist.
777 */ 784 */
778 mflags = get_map_flags (op->map, &m1, op->x + freearr_x[absdir (op->direction - 1)], 785 mapxy pos1 (pos); pos1.move (absdir (op->direction - 1));
779 op->y + freearr_y[absdir (op->direction - 1)], &x1, &y1); 786 bool left = pos1.normalise () && OB_TYPE_MOVE_BLOCK (op, pos1->move_block);
780 left = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK (op, (GET_MAP_MOVE_BLOCK (m1, x1, y1)));
781 787
782 mflags = get_map_flags (op->map, &m1, op->x + freearr_x[absdir (op->direction + 1)], 788 mapxy pos2 (pos); pos2.move (absdir (op->direction + 1));
783 op->y + freearr_y[absdir (op->direction + 1)], &x1, &y1); 789 bool right = pos2.normalise () && OB_TYPE_MOVE_BLOCK (op, pos2->move_block);
784 right = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK (op, (GET_MAP_MOVE_BLOCK (m1, x1, y1)));
785 790
786 if (left == right) 791 if (left == right)
787 op->direction = absdir (op->direction + 4); 792 op->direction = absdir (op->direction + 4);
788 else if (left) 793 else if (left)
789 op->direction = absdir (op->direction + 2); 794 op->direction = absdir (op->direction + 2);
790 else if (right) 795 else if (right)
791 op->direction = absdir (op->direction - 2); 796 op->direction = absdir (op->direction - 2);
792 797
793 mflags = get_map_flags (op->map, &m1, op->x + DIRX (op), op->y + DIRY (op), &x1, &y1);
794
795 /* If this space is not out of the map and not blocked, valid space - 798 /* If this space is not out of the map and not blocked, valid space -
796 * don't need to retry again. 799 * don't need to retry again.
797 */ 800 */
798 if (!(mflags & P_OUT_OF_MAP) && !OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m1, x1, y1))) 801 mapxy pos3 (pos); pos3.move (op->direction);
802 if (pos3.normalise () && !OB_TYPE_MOVE_BLOCK (op, pos3->move_block))
799 break; 803 break;
800
801 } 804 }
805
802 /* Couldn't find a direction to move the arrow to - just 806 /* Couldn't find a direction to move the arrow to - just
803 * top it from moving. 807 * stop it from moving.
804 */ 808 */
805 if (retry == 2) 809 if (retry == 2)
806 { 810 {
807 stop_arrow (op); 811 stop_arrow (op);
808 return; 812 return;
809 } 813 }
814
810 /* update object image for new facing */ 815 /* update object image for new facing */
811 /* many thrown objects *don't* have more than one face */ 816 /* many thrown objects *don't* have more than one face */
812 if (GET_ANIM_ID (op)) 817 if (GET_ANIM_ID (op))
813 SET_ANIMATION (op, op->direction); 818 SET_ANIMATION (op, op->direction);
814 } /* object is reflected */ 819 } /* object is reflected */
815 } /* object ran into a wall */ 820 } /* object ran into a wall */
816 821
817 /* Move the arrow. */
818 op->remove ();
819 op->x = new_x;
820 op->y = new_y;
821
822 /* decrease the speed as it flies. 0.05 means a standard bow will shoot 822 /* decrease the speed as it flies. 0.05 means a standard bow will shoot
823 * about 17 squares. Tune as needed. 823 * about 17 squares. Tune as needed.
824 */ 824 */
825 op->speed -= 0.05; 825 op->speed -= 0.05;
826 insert_ob_in_map (op, m, op, 0);
827}
828 826
829/* This routine doesnt seem to work for "inanimate" objects that 827 /* Move the arrow. */
830 * are being carried, ie a held torch leaps from your hands!. 828 op->move_to (pos);
831 * Modified this routine to allow held objects. b.t. */ 829}
832 830
833void 831void
834change_object (object *op) 832change_object (object *op)
835{ /* Doesn`t handle linked objs yet */ 833{ /* Doesn`t handle linked objs yet */
836 int i, j; 834 int i, j;
837 835
838 if (op->other_arch == NULL) 836 if (!op->other_arch)
839 { 837 {
840 LOG (llevError, "Change object (%s) without other_arch error.\n", &op->name); 838 LOG (llevError, "Change object (%s) without other_arch error.\n", op->debug_desc ());
841 return; 839 return;
842 } 840 }
843 841
844 /* In non-living items only change when food value is 0 */ 842 /* In non-living items only change when food value is 0 */
845 if (!QUERY_FLAG (op, FLAG_ALIVE)) 843 if (!QUERY_FLAG (op, FLAG_ALIVE))
846 { 844 {
847 if (op->stats.food-- > 0) 845 if (op->stats.food-- > 0)
848 return; 846 return;
849 else 847
850 op->stats.food = 1; /* so 1 other_arch is made */ 848 op->stats.food = 1; /* so 1 other_arch is made */
851 } 849 }
852 850
853 object *pl = op->in_player ();
854 object *env = op->env; 851 object *env = op->env;
855 852
856 op->remove (); 853 op->remove ();
857 for (i = 0; i < NROFNEWOBJS (op); i++) 854 for (i = 0; i < op->stats.food; i++)
858 { 855 {
859 object *tmp = arch_to_object (op->other_arch); 856 object *tmp = arch_to_object (op->other_arch);
860 857
861 if (op->type == LAMP) 858 if (op->type == LAMP)
862 tmp->stats.food = op->stats.food - 1; 859 tmp->stats.food = op->stats.food - 1;
863 860
864 tmp->stats.hp = op->stats.hp; /* The only variable it keeps. */ 861 tmp->stats.hp = op->stats.hp; /* The only variable it keeps. */
865 if (env) 862 if (env)
866 { 863 {
867 tmp->x = env->x, tmp->y = env->y;
868 tmp = insert_ob_in_ob (tmp, env); 864 tmp = env->insert (tmp);
869 865
870 /* If this object is the players inventory, we need to tell the 866 /* If this object is the players inventory, we need to tell the
871 * client of the change. Insert_ob_in_map takes care of the 867 * client of the change. Insert_ob_in_map takes care of the
872 * updating the client, so we don't need to do that below. 868 * updating the client, so we don't need to do that below.
873 */ 869 */
874 if (pl) 870 if (object *pl = op->in_player ())
875 { 871 {
876 esrv_del_item (pl->contr, op->count); 872 esrv_del_item (pl->contr, op->count);
877 esrv_send_item (pl, tmp); 873 esrv_send_item (pl, tmp);
878 } 874 }
879 } 875 }
880 else 876 else
881 { 877 {
882 j = find_first_free_spot (tmp, op->map, op->x, op->y); 878 j = find_first_free_spot (tmp, op->map, op->x, op->y);
883 if (j == -1) /* No free spot */ 879 if (j < 0) /* No free spot */
884 tmp->destroy (); 880 tmp->destroy ();
885 else 881 else
886 { 882 {
887 tmp->x = op->x + freearr_x[j], tmp->y = op->y + freearr_y[j]; 883 mapxy pos (op); pos.move (j);
888 insert_ob_in_map (tmp, op->map, op, 0); 884
885 if (pos.normalise ())
886 pos.insert (tmp, op);
889 } 887 }
890 } 888 }
891 } 889 }
892 890
893 op->destroy (); 891 op->destroy ();
1167 * has to make sure that there is in fact space for the object. 1165 * has to make sure that there is in fact space for the object.
1168 * It should really do this for small objects also, but there is 1166 * It should really do this for small objects also, but there is
1169 * more concern with large objects, most notably a part being placed 1167 * more concern with large objects, most notably a part being placed
1170 * outside of the map which would cause the server to crash 1168 * outside of the map which would cause the server to crash
1171*/ 1169*/
1172
1173void 1170void
1174move_creator (object *creator) 1171move_creator (object *creator)
1175{ 1172{
1176 object *new_ob; 1173 object *new_ob;
1177 1174
1212 new_ob = object_create_arch (creator->other_arch); 1209 new_ob = object_create_arch (creator->other_arch);
1213 fix_generated_item (new_ob, creator, 0, 0, GT_MINIMAL); 1210 fix_generated_item (new_ob, creator, 0, 0, GT_MINIMAL);
1214 } 1211 }
1215 1212
1216 /* Make sure this multipart object fits */ 1213 /* Make sure this multipart object fits */
1217 if (new_ob->arch->more && ob_blocked (new_ob, creator->map, creator->x, creator->y)) 1214 if (new_ob->arch->more && new_ob->blocked (creator->map, creator->x, creator->y))
1218 { 1215 {
1219 new_ob->destroy (); 1216 new_ob->destroy ();
1220 return; 1217 return;
1221 } 1218 }
1219
1220 // for now lets try to identify everything generated here, it mostly
1221 // happens automated, so this will at least fix many identify-experience holes
1222 SET_FLAG (new_ob, FLAG_IDENTIFIED);
1222 1223
1223 insert_ob_in_map_at (new_ob, creator->map, creator, 0, creator->x, creator->y); 1224 insert_ob_in_map_at (new_ob, creator->map, creator, 0, creator->x, creator->y);
1224 if (QUERY_FLAG (new_ob, FLAG_FREED)) 1225 if (QUERY_FLAG (new_ob, FLAG_FREED))
1225 return; 1226 return;
1226 1227
1310 if (QUERY_FLAG (op, FLAG_APPLIED)) 1311 if (QUERY_FLAG (op, FLAG_APPLIED))
1311 remove_force (op); 1312 remove_force (op);
1312 else 1313 else
1313 { 1314 {
1314 /* If necessary, delete the item from the players inventory */ 1315 /* If necessary, delete the item from the players inventory */
1315 object *pl = op->in_player (); 1316 if (object *pl = op->in_player ())
1316
1317 if (pl)
1318 esrv_del_item (pl->contr, op->count); 1317 esrv_del_item (pl->contr, op->count);
1319 1318
1320 op->remove (); 1319 op->remove ();
1321 1320
1322 if (QUERY_FLAG (op, FLAG_SEE_ANYWHERE)) 1321 if (QUERY_FLAG (op, FLAG_SEE_ANYWHERE))

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines