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.58 by root, Sat Jun 30 03:00:55 2007 UTC vs.
Revision 1.86 by elmex, Tue Jan 13 12:07:42 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 it 8 * Deliantra is free software: you can redistribute it and/or modify
9 * under the terms of the GNU General Public License as published by the Free 9 * it under the terms of the GNU General Public License as published by
10 * Software Foundation; either version 2 of the License, or (at your option) 10 * the Free Software Foundation, either version 3 of the License, or
11 * 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, but 13 * This program is distributed in the hope that it will be useful,
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * 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 along 18 * You should have received a copy of the GNU General Public License
19 * with Crossfire TRT; if not, write to the Free Software Foundation, Inc. 51 19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * 20 *
22 * 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>
23 */ 22 */
24 23
25/* 24/*
26 * 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
27 * collected in this file. 26 * collected in this file.
35 * so those will be removed shortly (in a cascade like fashion.) 34 * so those will be removed shortly (in a cascade like fashion.)
36 */ 35 */
37void 36void
38remove_door (object *op) 37remove_door (object *op)
39{ 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->drop_and_destroy ();
63}
64
65void
66remove_door2 (object *op)
67{
40 int i; 68 int i;
41 object *tmp; 69 object *tmp;
42 70
43 for (i = 1; i < 9; i += 2) 71 for (i = 1; i < 9; i += 2)
72 {
44 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]);
45 { 74 if (tmp && tmp->slaying == op->slaying)
75 { /* same key both doors */
46 tmp->set_speed (0.1f); 76 tmp->set_speed (0.1f);
47 tmp->speed_left = -0.2f; 77 tmp->speed_left = -0.2f;
48 } 78 }
79 }
49 80
50 if (op->other_arch) 81 if (op->other_arch)
51 { 82 {
52 tmp = arch_to_object (op->other_arch); 83 tmp = arch_to_object (op->other_arch);
53 tmp->x = op->x; 84 tmp->x = op->x;
55 tmp->map = op->map; 86 tmp->map = op->map;
56 tmp->level = op->level; 87 tmp->level = op->level;
57 insert_ob_in_map (tmp, op->map, op, 0); 88 insert_ob_in_map (tmp, op->map, op, 0);
58 } 89 }
59 90
60 op->destroy (); 91 op->drop_and_destroy ();
61}
62
63void
64remove_door2 (object *op)
65{
66 int i;
67 object *tmp;
68
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 tmp->set_speed (0.1f);
75 tmp->speed_left = -0.2f;
76 }
77 }
78
79 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
89 op->destroy ();
90} 92}
91 93
92void 94void
93generate_monster (object *gen) 95generate_monster (object *gen)
94{ 96{
96 return; 98 return;
97 99
98 if (GENERATE_SPEED (gen) && rndm (0, GENERATE_SPEED (gen) - 1)) 100 if (GENERATE_SPEED (gen) && rndm (0, GENERATE_SPEED (gen) - 1))
99 return; 101 return;
100 102
103 // sleeping generators won't generate, this will make monsters like
104 // centipedes not generate more centipedes when being asleep.
105 if (gen->flag [FLAG_SLEEP])
106 return;
107
101 object *op; 108 object *op;
109 int dir;
102 110
103 if (QUERY_FLAG (gen, FLAG_CONTENT_ON_GEN)) 111 if (QUERY_FLAG (gen, FLAG_CONTENT_ON_GEN))
104 { 112 {
105 // either copy one item from the inventory... 113 // either copy one item from the inventory...
106 if (!gen->inv) 114 if (!gen->inv)
110 int index = 0; 118 int index = 0;
111 for (object *tmp = gen->inv; tmp; tmp = tmp->below) 119 for (object *tmp = gen->inv; tmp; tmp = tmp->below)
112 if (!rndm (++index)) 120 if (!rndm (++index))
113 op = tmp; 121 op = tmp;
114 122
115 op = object_create_clone (op); 123 dir = find_free_spot (op, gen->map, gen->x, gen->y, 1, SIZEOFFREE1 + 1);
124 if (dir < 0)
125 return;
126
127 op = op->deep_clone ();
116 128
117 CLEAR_FLAG (op, FLAG_IS_A_TEMPLATE); 129 CLEAR_FLAG (op, FLAG_IS_A_TEMPLATE);
118 unflag_inv (op, FLAG_IS_A_TEMPLATE); 130 unflag_inv (op, FLAG_IS_A_TEMPLATE);
119 } 131 }
120 else if (gen->other_arch) 132 else if (gen->other_arch)
121 { 133 {
122 // ...or use other_arch 134 // ...or use other_arch
135 dir = find_free_spot (gen->other_arch, gen->map, gen->x, gen->y, 1, SIZEOFFREE1 + 1);
136 if (dir < 0)
137 return;
138
123 op = arch_to_object (gen->other_arch); 139 op = arch_to_object (gen->other_arch);
124 } 140 }
125 else 141 else
126 return; 142 return;
127 143
128 op->expand_tail (); 144 op->expand_tail ();
129 145
130 int i = find_free_spot (op, gen->map, gen->x, gen->y, 1, 9); 146 mapxy pos (gen); pos.move (dir);
131 if (i >= 0) 147
148 if (pos.insert (op, gen))
132 { 149 {
133 if (insert_ob_in_map_at (op, gen->map, gen, 0, gen->x + freearr_x[i], gen->y + freearr_y[i]))
134 {
135 if (rndm (0, 9)) 150 if (rndm (0, 9))
136 generate_artifact (op, gen->map->difficulty); 151 generate_artifact (op, gen->map->difficulty);
137 152
138 if (op->has_random_items ()) 153 if (op->has_random_items ())
139 create_treasure (op->randomitems, op, GT_APPLY, gen->map->difficulty); 154 create_treasure (op->randomitems, op, GT_APPLY, gen->map->difficulty);
140 155
141 return; 156 return;
142 }
143 } 157 }
144 158
145 op->destroy (); 159 op->destroy ();
146} 160}
147 161
264 * objects are above the gate. If so, we finish closing the gate, 278 * objects are above the gate. If so, we finish closing the gate,
265 * otherwise, we fall through to the code below which should lower 279 * otherwise, we fall through to the code below which should lower
266 * the gate slightly. 280 * the gate slightly.
267 */ 281 */
268 282
269 for (tmp = op->above; tmp != NULL; tmp = tmp->above) 283 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)) 284 if (!QUERY_FLAG (tmp, FLAG_NO_PICK) || QUERY_FLAG (tmp, FLAG_CAN_ROLL) || QUERY_FLAG (tmp, FLAG_ALIVE))
271 break; 285 break;
272 286
273 if (tmp == NULL) 287 if (!tmp)
274 { 288 {
275 if (op->arch->speed) 289 if (op->arch->speed)
276 op->value = 1; 290 op->value = 1;
277 else 291 else
278 op->set_speed (0); 292 op->set_speed (0);
291 } 305 }
292 else 306 else
293 { /* The gate is still going up */ 307 { /* The gate is still going up */
294 op->stats.wc++; 308 op->stats.wc++;
295 309
296 if ((int) op->stats.wc >= (NUM_ANIMATIONS (op))) 310 if (op->stats.wc >= NUM_ANIMATIONS (op))
297 op->stats.wc = (signed char) NUM_ANIMATIONS (op) - 1; 311 op->stats.wc = NUM_ANIMATIONS (op) - 1;
298 312
299 /* If there is something on top of the gate, we try to roll it off. 313 /* 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 314 * If a player/monster, we don't roll, we just hit them with damage
301 */ 315 */
302 if ((int) op->stats.wc >= NUM_ANIMATIONS (op) / 2) 316 if (op->stats.wc >= NUM_ANIMATIONS (op) / 2)
303 { 317 {
304 /* Halfway or further, check blocks */ 318 /* Halfway or further, check blocks */
305 /* First, get the top object on the square. */ 319 /* First, get the top object on the square. */
306 for (tmp = op->above; tmp && tmp->above; tmp = tmp->above) 320 for (tmp = op->above; tmp && tmp->above; tmp = tmp->above)
307 ; 321 ;
309 if (tmp) 323 if (tmp)
310 { 324 {
311 if (QUERY_FLAG (tmp, FLAG_ALIVE)) 325 if (QUERY_FLAG (tmp, FLAG_ALIVE))
312 { 326 {
313 hit_player (tmp, random_roll (0, op->stats.dam, tmp, PREFER_LOW), op, AT_PHYSICAL, 1); 327 hit_player (tmp, random_roll (0, op->stats.dam, tmp, PREFER_LOW), op, AT_PHYSICAL, 1);
328 op->play_sound (sound_find ("blocked_gate"));
314 329
315 if (tmp->type == PLAYER) 330 if (tmp->type == PLAYER)
316 new_draw_info_format (NDI_UNIQUE, 0, tmp, "You are crushed by the %s!", &op->name); 331 new_draw_info_format (NDI_UNIQUE, 0, tmp, "You are crushed by the %s!", &op->name);
317 } 332 }
318 else
319 /* If the object is not alive, and the object either can 333 /* If the object is not alive, and the object either can
320 * be picked up or the object rolls, move the object 334 * be picked up or the object rolls, move the object
321 * off the gate. 335 * off the gate.
322 */ 336 */
323 if (!QUERY_FLAG (tmp, FLAG_ALIVE) && (!QUERY_FLAG (tmp, FLAG_NO_PICK) || QUERY_FLAG (tmp, FLAG_CAN_ROLL))) 337 else if (!QUERY_FLAG (tmp, FLAG_ALIVE) && (!QUERY_FLAG (tmp, FLAG_NO_PICK) || QUERY_FLAG (tmp, FLAG_CAN_ROLL)))
324 { 338 {
325 /* If it has speed, it should move itself, otherwise: */ 339 /* If it has speed, it should move itself, otherwise: */
326 int i = find_free_spot (tmp, op->map, op->x, op->y, 1, 9); 340 int i = find_free_spot (tmp, op->map, op->x, op->y, 1, SIZEOFFREE1 + 1);
327 341
328 /* If there is a free spot, move the object someplace */ 342 /* If there is a free spot, move the object someplace */
329 if (i != -1) 343 if (i > 0)
330 { 344 {
345 mapxy pos (tmp);
346 pos.move (i);
347 if (pos.normalise ())
331 tmp->remove (); 348 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 } 349 }
335 } 350 }
336 } 351 }
337 352
338 /* See if there is still anything blocking the gate */ 353 /* See if there is still anything blocking the gate */
339 for (tmp = op->above; tmp != NULL; tmp = tmp->above) 354 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)) 355 if (!QUERY_FLAG (tmp, FLAG_NO_PICK) || QUERY_FLAG (tmp, FLAG_CAN_ROLL) || QUERY_FLAG (tmp, FLAG_ALIVE))
341 break; 356 break;
342 357
343 /* IF there is, start putting the gate down */ 358 /* IF there is, start putting the gate down */
344 if (tmp) 359 if (tmp)
345 {
346 op->stats.food = 1; 360 op->stats.food = 1;
347 }
348 else 361 else
349 { 362 {
350 op->move_block = MOVE_ALL; 363 op->move_block = MOVE_ALL;
364
351 if (!op->arch->stats.ac) 365 if (!op->arch->stats.ac)
352 SET_FLAG (op, FLAG_BLOCKSVIEW); 366 SET_FLAG (op, FLAG_BLOCKSVIEW);
353 update_all_los (op->map, op->x, op->y); 367 update_all_los (op->map, op->x, op->y);
354 } 368 }
355 } /* gate is halfway up */ 369 } /* gate is halfway up */
369 int v = op->value; 383 int v = op->value;
370 384
371 if (op->stats.sp) 385 if (op->stats.sp)
372 { 386 {
373 move_gate (op); 387 move_gate (op);
388
374 if (op->value != v) /* change direction ? */ 389 if (op->value != v) /* change direction ? */
375 op->stats.sp = 0; 390 op->stats.sp = 0;
376 return; 391 return;
377 } 392 }
393
378 if (--op->stats.hp <= 0) 394 if (--op->stats.hp <= 0)
379 { /* keep gate down */ 395 { /* keep gate down */
380 move_gate (op); 396 move_gate (op);
397
381 if (op->value != v) 398 if (op->value != v)
382 op->set_speed (0); 399 op->set_speed (0);
383 } 400 }
384} 401}
385 402
397 int last = op->value; 414 int last = op->value;
398 int detected; 415 int detected;
399 416
400 detected = 0; 417 detected = 0;
401 418
402 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp != NULL && !detected; tmp = tmp->above) 419 for (tmp = op->ms ().bot; tmp && !detected; tmp = tmp->above)
403 { 420 {
404 object *tmp2; 421 object *tmp2;
405 422
406 if (op->stats.hp) 423 if (op->stats.hp)
407 { 424 {
425 if (op->stats.sp == 1) 442 if (op->stats.sp == 1)
426 { 443 {
427 if (detected && last == 0) 444 if (detected && last == 0)
428 { 445 {
429 op->value = 1; 446 op->value = 1;
430 push_button (op); 447 push_button (op, tmp);
431 } 448 }
449
432 if (!detected && last == 1) 450 if (!detected && last == 1)
433 { 451 {
434 op->value = 0; 452 op->value = 0;
435 push_button (op); 453 push_button (op, tmp);
436 } 454 }
437 } 455 }
438 else 456 else
439 { /* in this case, we unset buttons */ 457 { /* in this case, we unset buttons */
440 if (detected && last == 1) 458 if (detected && last == 1)
441 { 459 {
442 op->value = 0; 460 op->value = 0;
443 push_button (op); 461 push_button (op, tmp);
444 } 462 }
463
445 if (!detected && last == 0) 464 if (!detected && last == 0)
446 { 465 {
447 op->value = 1; 466 op->value = 1;
448 push_button (op); 467 push_button (op, tmp);
449 } 468 }
450 } 469 }
451} 470}
452
453 471
454void 472void
455animate_trigger (object *op) 473animate_trigger (object *op)
456{ 474{
457 if ((unsigned char) ++op->stats.wc >= NUM_ANIMATIONS (op)) 475 if ((unsigned char) ++op->stats.wc >= NUM_ANIMATIONS (op))
467} 485}
468 486
469void 487void
470move_hole (object *op) 488move_hole (object *op)
471{ /* 1 = opening, 0 = closing */ 489{ /* 1 = opening, 0 = closing */
472 object *next, *tmp;
473
474 if (op->value) 490 if (op->value)
475 { /* We're opening */ 491 { /* We're opening */
476 if (--op->stats.wc <= 0) 492 if (--op->stats.wc <= 0)
477 { /* Opened, let's stop */ 493 { /* Opened, let's stop */
478 op->stats.wc = 0; 494 op->stats.wc = 0;
479 op->set_speed (0); 495 op->set_speed (0);
480 496
481 /* Hard coding this makes sense for holes I suppose */ 497 /* Hard coding this makes sense for holes I suppose */
482 op->move_on = MOVE_WALK; 498 op->move_on = MOVE_WALK;
483 for (tmp = op->above; tmp != NULL; tmp = next) 499 for (object *next, *tmp = op->above; tmp; tmp = next)
484 { 500 {
485 next = tmp->above; 501 next = tmp->above;
486 move_apply (op, tmp, tmp); 502 move_apply (op, tmp, tmp);
487 } 503 }
488 } 504 }
489 505
490 SET_ANIMATION (op, op->stats.wc); 506 SET_ANIMATION (op, op->stats.wc);
491 update_object (op, UP_OBJ_FACE); 507 update_object (op, UP_OBJ_FACE);
492 return; 508 return;
493 } 509 }
510
494 /* We're closing */ 511 /* We're closing */
495 op->move_on = 0; 512 op->move_on = 0;
496 513
497 op->stats.wc++; 514 op->stats.wc++;
498 if ((int) op->stats.wc >= NUM_ANIMATIONS (op)) 515 if ((int) op->stats.wc >= NUM_ANIMATIONS (op))
529 { 546 {
530 object *payload = op->inv; 547 object *payload = op->inv;
531 548
532 if (payload == NULL) 549 if (payload == NULL)
533 return NULL; 550 return NULL;
551
534 payload->remove (); 552 payload->remove ();
535 op->destroy (); 553 op->destroy ();
536 return payload; 554 return payload;
537 } 555 }
538 556
618 if (INVOKE_OBJECT (STOP, op)) 636 if (INVOKE_OBJECT (STOP, op))
619 return; 637 return;
620 638
621 if (op->inv) 639 if (op->inv)
622 { 640 {
641 // replace this by straightforward drop to ground?
623 object *payload = op->inv; 642 object *payload = op->inv;
624 643
625 payload->remove ();
626 payload->owner = 0; 644 payload->owner = 0;
627 insert_ob_in_map (payload, op->map, payload, 0); 645 insert_ob_in_map (payload, op->map, payload, 0);
628 op->destroy (); 646 op->destroy ();
629 } 647 }
630 else 648 else
639/* Move an arrow along its course. op is the arrow or thrown object. 657/* Move an arrow along its course. op is the arrow or thrown object.
640 */ 658 */
641void 659void
642move_arrow (object *op) 660move_arrow (object *op)
643{ 661{
644 object *tmp;
645 sint16 new_x, new_y;
646 int was_reflected, mflags; 662 int was_reflected;
647 maptile *m;
648 663
649 if (op->map == NULL) 664 if (!op->map)
650 { 665 {
651 LOG (llevError, "BUG: Arrow had no map.\n"); 666 LOG (llevError, "BUG: Arrow had no map.\n");
652 op->destroy (); 667 op->destroy ();
653 return; 668 return;
654 } 669 }
662 * is if the player throws a bomb - the bomb explodes on its own, 677 * is if the player throws a bomb - the bomb explodes on its own,
663 * but this object sticks around. We could handle the cleanup in the 678 * but this object sticks around. We could handle the cleanup in the
664 * bomb code, but there are potential other cases where that could happen, 679 * bomb code, but there are potential other cases where that could happen,
665 * and it is easy enough to clean it up here. 680 * and it is easy enough to clean it up here.
666 */ 681 */
667 if (op->inv == NULL) 682 if (!op->inv)
668 { 683 {
669 op->destroy (); 684 op->destroy ();
670 return; 685 return;
671 } 686 }
672 687
684 stop_arrow (op); 699 stop_arrow (op);
685 return; 700 return;
686 } 701 }
687 702
688 /* Calculate target map square */ 703 /* Calculate target map square */
689 new_x = op->x + DIRX (op);
690 new_y = op->y + DIRY (op);
691 was_reflected = 0; 704 was_reflected = 0;
692 705
693 m = op->map; 706 mapxy pos (op); pos.move (op->direction);
694 mflags = get_map_flags (m, &m, new_x, new_y, &new_x, &new_y);
695 707
696 if (mflags & P_OUT_OF_MAP) 708 if (!pos.normalise ())
697 { 709 {
698 stop_arrow (op); 710 stop_arrow (op);
699 return; 711 return;
700 } 712 }
701 713
702 /* only need to look for living creatures if this flag is set */ 714 /* only need to look for living creatures if this flag is set */
703 if (mflags & P_IS_ALIVE) 715 if (pos->flags () & P_IS_ALIVE)
704 { 716 {
705 for (tmp = GET_MAP_OB (m, new_x, new_y); tmp != NULL; tmp = tmp->above) 717 object *tmp;
718
719 for (tmp = pos->bot; tmp; tmp = tmp->above)
706 if (QUERY_FLAG (tmp, FLAG_ALIVE)) 720 if (QUERY_FLAG (tmp, FLAG_ALIVE))
707 break; 721 break;
708 722
709 /* Not really fair, but don't let monsters hit themselves with 723 /* Not really fair, but don't let monsters hit themselves with
710 * their own arrow - this can be because they fire it then 724 * their own arrow - this can be because they fire it then
733 return; 747 return;
734 } 748 }
735 } /* if this is not hitting its owner */ 749 } /* if this is not hitting its owner */
736 } /* if there is something alive on this space */ 750 } /* if there is something alive on this space */
737 751
738 if (OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, new_x, new_y))) 752 if (OB_TYPE_MOVE_BLOCK (op, pos->move_block))
739 { 753 {
740 int retry = 0; 754 int retry = 0;
741 755
742 /* if the object doesn't reflect, stop the arrow from moving 756 /* if the object doesn't reflect, stop the arrow from moving
743 * note that this code will now catch cases where a monster is 757 * note that this code will now catch cases where a monster is
756 if (op->direction & 1) 770 if (op->direction & 1)
757 { 771 {
758 op->direction = absdir (op->direction + 4); 772 op->direction = absdir (op->direction + 4);
759 retry = 1; 773 retry = 1;
760 } 774 }
775
761 /* There were two blocks with identical code - 776 /* There were two blocks with identical code -
762 * use this retry here to make this one block 777 * use this retry here to make this one block
763 * that did the same thing. 778 * that did the same thing.
764 */ 779 */
765 while (retry < 2) 780 while (retry < 2)
766 { 781 {
767 int left, right, mflags;
768 maptile *m1;
769 sint16 x1, y1;
770
771 retry++; 782 retry++;
772 783
773 /* Need to check for P_OUT_OF_MAP: if the arrow is tavelling 784 /* 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 785 * over a corner in a tiled map, it is possible that
775 * op->direction is within an adjacent map but either 786 * op->direction is within an adjacent map but either
776 * op->direction-1 or op->direction+1 does not exist. 787 * op->direction-1 or op->direction+1 does not exist.
777 */ 788 */
778 mflags = get_map_flags (op->map, &m1, op->x + freearr_x[absdir (op->direction - 1)], 789 mapxy pos1 (pos); pos1.move (absdir (op->direction - 1));
779 op->y + freearr_y[absdir (op->direction - 1)], &x1, &y1); 790 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 791
782 mflags = get_map_flags (op->map, &m1, op->x + freearr_x[absdir (op->direction + 1)], 792 mapxy pos2 (pos); pos2.move (absdir (op->direction + 1));
783 op->y + freearr_y[absdir (op->direction + 1)], &x1, &y1); 793 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 794
786 if (left == right) 795 if (left == right)
787 op->direction = absdir (op->direction + 4); 796 op->direction = absdir (op->direction + 4);
788 else if (left) 797 else if (left)
789 op->direction = absdir (op->direction + 2); 798 op->direction = absdir (op->direction + 2);
790 else if (right) 799 else if (right)
791 op->direction = absdir (op->direction - 2); 800 op->direction = absdir (op->direction - 2);
792 801
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 - 802 /* If this space is not out of the map and not blocked, valid space -
796 * don't need to retry again. 803 * don't need to retry again.
797 */ 804 */
798 if (!(mflags & P_OUT_OF_MAP) && !OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m1, x1, y1))) 805 mapxy pos3 (pos); pos3.move (op->direction);
806 if (pos3.normalise () && !OB_TYPE_MOVE_BLOCK (op, pos3->move_block))
799 break; 807 break;
800
801 } 808 }
809
802 /* Couldn't find a direction to move the arrow to - just 810 /* Couldn't find a direction to move the arrow to - just
803 * top it from moving. 811 * stop it from moving.
804 */ 812 */
805 if (retry == 2) 813 if (retry == 2)
806 { 814 {
807 stop_arrow (op); 815 stop_arrow (op);
808 return; 816 return;
809 } 817 }
818
810 /* update object image for new facing */ 819 /* update object image for new facing */
811 /* many thrown objects *don't* have more than one face */ 820 /* many thrown objects *don't* have more than one face */
812 if (GET_ANIM_ID (op)) 821 if (GET_ANIM_ID (op))
813 SET_ANIMATION (op, op->direction); 822 SET_ANIMATION (op, op->direction);
814 } /* object is reflected */ 823 } /* object is reflected */
815 } /* object ran into a wall */ 824 } /* object ran into a wall */
816 825
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 826 /* decrease the speed as it flies. 0.05 means a standard bow will shoot
823 * about 17 squares. Tune as needed. 827 * about 17 squares. Tune as needed.
824 */ 828 */
825 op->speed -= 0.05; 829 op->speed -= 0.05;
826 insert_ob_in_map (op, m, op, 0);
827}
828 830
829/* This routine doesnt seem to work for "inanimate" objects that 831 /* Move the arrow. */
830 * are being carried, ie a held torch leaps from your hands!. 832 op->move_to (pos);
831 * Modified this routine to allow held objects. b.t. */ 833}
832 834
833void 835void
834change_object (object *op) 836change_object (object *op)
835{ /* Doesn`t handle linked objs yet */ 837{ /* Doesn`t handle linked objs yet */
836 int i, j; 838 int i, j;
837 839
838 if (op->other_arch == NULL) 840 if (!op->other_arch)
839 { 841 {
840 LOG (llevError, "Change object (%s) without other_arch error.\n", &op->name); 842 LOG (llevError, "Change object (%s) without other_arch error.\n", op->debug_desc ());
841 return; 843 return;
842 } 844 }
843 845
844 /* In non-living items only change when food value is 0 */ 846 /* In non-living items only change when food value is 0 */
845 if (!QUERY_FLAG (op, FLAG_ALIVE)) 847 if (!QUERY_FLAG (op, FLAG_ALIVE))
846 { 848 {
847 if (op->stats.food-- > 0) 849 if (op->stats.food-- > 0)
848 return; 850 return;
851
852 op->stats.food = 1; /* so 1 other_arch is made */
853 }
854
855 object *env = op->env;
856
857 op->remove ();
858 for (i = 0; i < op->stats.food; i++)
859 {
860 object *tmp = arch_to_object (op->other_arch);
861
862 tmp->stats.hp = op->stats.hp; /* The only variable it keeps. */
863
864 if (env)
865 env->insert (tmp);
849 else 866 else
850 op->stats.food = 1; /* so 1 other_arch is made */
851 }
852
853 object *pl = op->in_player ();
854 object *env = op->env;
855
856 op->remove ();
857 for (i = 0; i < NROFNEWOBJS (op); i++)
858 {
859 object *tmp = arch_to_object (op->other_arch);
860
861 if (op->type == LAMP)
862 tmp->stats.food = op->stats.food - 1;
863
864 tmp->stats.hp = op->stats.hp; /* The only variable it keeps. */
865 if (env)
866 {
867 tmp->x = env->x, tmp->y = env->y;
868 tmp = insert_ob_in_ob (tmp, env);
869
870 /* 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
872 * updating the client, so we don't need to do that below.
873 */
874 if (pl)
875 {
876 esrv_del_item (pl->contr, op->count);
877 esrv_send_item (pl, tmp);
878 }
879 }
880 else
881 { 867 {
882 j = find_first_free_spot (tmp, op->map, op->x, op->y); 868 j = find_first_free_spot (tmp, op->map, op->x, op->y);
883 if (j == -1) /* No free spot */ 869 if (j < 0) /* No free spot */
884 tmp->destroy (); 870 tmp->destroy ();
885 else 871 else
886 { 872 {
887 tmp->x = op->x + freearr_x[j], tmp->y = op->y + freearr_y[j]; 873 mapxy pos (op); pos.move (j);
888 insert_ob_in_map (tmp, op->map, op, 0); 874
875 if (pos.normalise ())
876 pos.insert (tmp, op);
889 } 877 }
890 } 878 }
891 } 879 }
892 880
893 op->destroy (); 881 op->destroy ();
949 else 937 else
950 { 938 {
951 /* Random teleporter */ 939 /* Random teleporter */
952 if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (tmp))) 940 if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (tmp)))
953 return; 941 return;
942
954 teleport (head, TELEPORTER, tmp); 943 teleport (head, TELEPORTER, tmp);
955 } 944 }
956} 945}
957 946
958/* This object will teleport someone to a different map 947/* This object will teleport someone to a different map
1167 * has to make sure that there is in fact space for the object. 1156 * 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 1157 * It should really do this for small objects also, but there is
1169 * more concern with large objects, most notably a part being placed 1158 * more concern with large objects, most notably a part being placed
1170 * outside of the map which would cause the server to crash 1159 * outside of the map which would cause the server to crash
1171*/ 1160*/
1172
1173void 1161void
1174move_creator (object *creator) 1162move_creator (object *creator)
1175{ 1163{
1176 object *new_ob; 1164 object *new_ob;
1177 1165
1179 { 1167 {
1180 creator->stats.hp = -1; 1168 creator->stats.hp = -1;
1181 return; 1169 return;
1182 } 1170 }
1183 1171
1184 if (creator->inv != NULL) 1172 if (creator->inv)
1185 { 1173 {
1186 object *ob; 1174 object *ob;
1187 int i; 1175 int i;
1188 object *ob_to_copy; 1176 object *ob_to_copy;
1189 1177
1194 if (rndm (0, i) == 0) 1182 if (rndm (0, i) == 0)
1195 { 1183 {
1196 ob_to_copy = ob; 1184 ob_to_copy = ob;
1197 } 1185 }
1198 } 1186 }
1199 new_ob = object_create_clone (ob_to_copy); 1187 new_ob = ob_to_copy->deep_clone ();
1200 CLEAR_FLAG (new_ob, FLAG_IS_A_TEMPLATE); 1188 CLEAR_FLAG (new_ob, FLAG_IS_A_TEMPLATE);
1201 unflag_inv (new_ob, FLAG_IS_A_TEMPLATE); 1189 unflag_inv (new_ob, FLAG_IS_A_TEMPLATE);
1202 } 1190 }
1203 else 1191 else
1204 { 1192 {
1205 if (creator->other_arch == NULL) 1193 if (!creator->other_arch)
1206 { 1194 {
1207 LOG (llevError, "move_creator: Creator doesn't have other arch set: %s (%s, %d, %d)\n", 1195 LOG (llevError, "move_creator: Creator doesn't have other arch set: %s (%s, %d, %d)\n",
1208 &creator->name, &creator->map->path, creator->x, creator->y); 1196 &creator->name, &creator->map->path, creator->x, creator->y);
1209 return; 1197 return;
1210 } 1198 }
1212 new_ob = object_create_arch (creator->other_arch); 1200 new_ob = object_create_arch (creator->other_arch);
1213 fix_generated_item (new_ob, creator, 0, 0, GT_MINIMAL); 1201 fix_generated_item (new_ob, creator, 0, 0, GT_MINIMAL);
1214 } 1202 }
1215 1203
1216 /* Make sure this multipart object fits */ 1204 /* Make sure this multipart object fits */
1217 if (new_ob->arch->more && ob_blocked (new_ob, creator->map, creator->x, creator->y)) 1205 if (new_ob->arch->more && new_ob->blocked (creator->map, creator->x, creator->y))
1218 { 1206 {
1219 new_ob->destroy (); 1207 new_ob->destroy ();
1220 return; 1208 return;
1221 } 1209 }
1210
1211 // for now lets try to identify everything generated here, it mostly
1212 // happens automated, so this will at least fix many identify-experience holes
1213 SET_FLAG (new_ob, FLAG_IDENTIFIED);
1222 1214
1223 insert_ob_in_map_at (new_ob, creator->map, creator, 0, creator->x, creator->y); 1215 insert_ob_in_map_at (new_ob, creator->map, creator, 0, creator->x, creator->y);
1224 if (QUERY_FLAG (new_ob, FLAG_FREED)) 1216 if (QUERY_FLAG (new_ob, FLAG_FREED))
1225 return; 1217 return;
1226 1218
1227 if (creator->slaying) 1219 if (creator->slaying)
1228 {
1229 new_ob->name = new_ob->title = creator->slaying; 1220 new_ob->name = new_ob->title = creator->slaying;
1230 }
1231} 1221}
1232 1222
1233/* move_marker --peterm@soda.csua.berkeley.edu 1223/* move_marker --peterm@soda.csua.berkeley.edu
1234 when moved, a marker will search for a player sitting above 1224 when moved, a marker will search for a player sitting above
1235 it, and insert an invisible, weightless force into him 1225 it, and insert an invisible, weightless force into him
1241void 1231void
1242move_marker (object *op) 1232move_marker (object *op)
1243{ 1233{
1244 if (object *tmp = op->ms ().player ()) 1234 if (object *tmp = op->ms ().player ())
1245 { 1235 {
1246 object *tmp2;
1247
1248 /* remove an old force with a slaying field == op->name */ 1236 /* remove an old force with a slaying field == op->name */
1249 for (tmp2 = tmp->inv; tmp2; tmp2 = tmp2->below) 1237 if (object *force = tmp->force_find (op->name))
1250 if (tmp2->type == FORCE && tmp2->slaying && tmp2->slaying == op->name) 1238 force->destroy ();
1239
1240 if (!tmp->force_find (op->slaying))
1251 { 1241 {
1252 tmp2->destroy (); 1242 tmp->force_add (op->slaying, op->stats.food);
1253 break;
1254 }
1255 1243
1256 /* cycle through his inventory to look for the MARK we want to
1257 * place
1258 */
1259 for (tmp2 = tmp->inv; tmp2; tmp2 = tmp2->below)
1260 if (tmp2->type == FORCE && tmp2->slaying && tmp2->slaying == op->slaying)
1261 break;
1262
1263 /* if we didn't find our own MARK */
1264 if (!tmp2)
1265 {
1266 object *force = get_archetype (FORCE_NAME);
1267
1268 if (op->stats.food)
1269 {
1270 force->set_speed (0.01);
1271 force->speed_left = -op->stats.food;
1272 }
1273 else
1274 force->set_speed (0);
1275
1276 /* put in the lock code */
1277 force->slaying = op->slaying;
1278
1279 if (op->lore)
1280 force->lore = op->lore;
1281
1282 insert_ob_in_ob (force, tmp);
1283 if (op->msg) 1244 if (op->msg)
1284 new_draw_info (NDI_UNIQUE | NDI_NAVY, 0, tmp, op->msg); 1245 new_draw_info (NDI_UNIQUE | NDI_NAVY, 0, tmp, op->msg);
1285 1246
1286 if (op->stats.hp > 0) 1247 if (op->stats.hp > 0)
1287 { 1248 {
1288 op->stats.hp--; 1249 op->stats.hp--;
1250
1289 if (op->stats.hp == 0) 1251 if (op->stats.hp == 0)
1290 { 1252 {
1291 /* marker expires--granted mark number limit */ 1253 /* marker expires--granted mark number limit */
1292 op->destroy (); 1254 op->destroy ();
1293 return; 1255 return;
1295 } 1257 }
1296 } 1258 }
1297 } 1259 }
1298} 1260}
1299 1261
1262// mapscript objects activate themselves (only) then their timer fires
1263// TODO: maybe they should simply trigger the link like any other object?
1264void
1265move_mapscript (object *op)
1266{
1267 op->set_speed (0);
1268 cfperl_mapscript_activate (op, true, op, 0);
1269}
1270
1271void move_lamp (object *op)
1272{
1273 // if the lamp/torch is off, we should disable it.
1274 if (!op->glow_radius)
1275 {
1276 op->set_speed (0);
1277 return;
1278 }
1279 else
1280 {
1281 // check whether the face might needs to be updated
1282 // (currently this is needed to have already switched on torches
1283 // on maps, as they just set the glow_radius in the archetype)
1284 if (op->other_arch
1285 && (
1286 op->flag [FLAG_ANIMATE]
1287 ? (op->animation_id != op->other_arch->animation_id)
1288 : (op->face != op->other_arch->face)
1289 ))
1290 get_animation_from_arch (op, op->other_arch);
1291 }
1292
1293 // lamps and torches auf maps don't use up their fuel
1294 if (op->is_on_map ())
1295 return;
1296
1297 if (op->stats.food > 0)
1298 {
1299 op->stats.food--;
1300 return;
1301 }
1302
1303 apply_lamp (op, false);
1304}
1305
1300void 1306void
1301process_object (object *op) 1307process_object (object *op)
1302{ 1308{
1303 if (expect_false (QUERY_FLAG (op, FLAG_IS_A_TEMPLATE))) 1309 if (expect_false (QUERY_FLAG (op, FLAG_IS_A_TEMPLATE)))
1304 return; 1310 return;
1337 { 1343 {
1338 if (QUERY_FLAG (op, FLAG_APPLIED)) 1344 if (QUERY_FLAG (op, FLAG_APPLIED))
1339 remove_force (op); 1345 remove_force (op);
1340 else 1346 else
1341 { 1347 {
1342 /* If necessary, delete the item from the players inventory */ 1348 op->remove (); // TODO: really necessary?
1343 object *pl = op->in_player ();
1344
1345 if (pl)
1346 esrv_del_item (pl->contr, op->count);
1347
1348 op->remove ();
1349 1349
1350 if (QUERY_FLAG (op, FLAG_SEE_ANYWHERE)) 1350 if (QUERY_FLAG (op, FLAG_SEE_ANYWHERE))
1351 make_sure_not_seen (op); 1351 make_sure_not_seen (op);
1352 1352
1353 op->destroy (); 1353 op->drop_and_destroy ();
1354 } 1354 }
1355 1355
1356 return; 1356 return;
1357 } 1357 }
1358 } 1358 }
1482 1482
1483 case PLAYER: 1483 case PLAYER:
1484 // players have their own speed-management, so undo the --speed_left 1484 // players have their own speed-management, so undo the --speed_left
1485 ++op->speed_left; 1485 ++op->speed_left;
1486 break; 1486 break;
1487 }
1488}
1489 1487
1488 case MAPSCRIPT:
1489 move_mapscript (op);
1490 break;
1491
1492 case LAMP:
1493 case TORCH:
1494 move_lamp (op);
1495 break;
1496 }
1497}
1498

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines