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.118 by root, Fri Jan 27 22:00:40 2012 UTC vs.
Revision 1.127 by root, Sun Nov 18 15:19:48 2018 UTC

1/* 1/*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG. 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (©) 2017,2018 Marc Alexander Lehmann / the Deliantra team
4 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 5 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team 6 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992 Frank Tore Johansen 7 * Copyright (©) 1992 Frank Tore Johansen
7 * 8 *
8 * Deliantra is free software: you can redistribute it and/or modify it under 9 * Deliantra is free software: you can redistribute it and/or modify it under
9 * the terms of the Affero GNU General Public License as published by the 10 * the terms of the Affero GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your 11 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version. 12 * option) any later version.
12 * 13 *
13 * This program is distributed in the hope that it will be useful, 14 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 17 * GNU General Public License for more details.
17 * 18 *
18 * You should have received a copy of the Affero GNU General Public License 19 * You should have received a copy of the Affero GNU General Public License
19 * and the GNU General Public License along with this program. If not, see 20 * and the GNU General Public License along with this program. If not, see
20 * <http://www.gnu.org/licenses/>. 21 * <http://www.gnu.org/licenses/>.
21 * 22 *
22 * The authors can be reached via e-mail to <support@deliantra.net> 23 * The authors can be reached via e-mail to <support@deliantra.net>
23 */ 24 */
24 25
25/* 26/*
26 * Routines that is executed from objects based on their speed have been 27 * Routines that is executed from objects based on their speed have been
28 */ 29 */
29#include <global.h> 30#include <global.h>
30#include <spells.h> 31#include <spells.h>
31#include <sproto.h> 32#include <sproto.h>
32 33
33/* The following removes doors. The functions check to see if similar 34/* The following removes doors. The functions check to see if similar
34 * doors are next to the one that is being removed, and if so, set it 35 * doors are next to the one that is being removed, and if so, set it
35 * so those will be removed shortly (in a cascade like fashion.) 36 * so those will be removed shortly (in a cascade like fashion.)
36 */ 37 */
37void 38void
38remove_door (object *op) 39remove_door (object *op)
69 int i; 70 int i;
70 object *tmp; 71 object *tmp;
71 72
72 for (i = 1; i < 9; i += 2) 73 for (i = 1; i < 9; i += 2)
73 { 74 {
74 tmp = present (LOCKED_DOOR, op->map, op->x + freearr_x[i], op->y + freearr_y[i]); 75 tmp = present (LOCKED_DOOR, op->map, op->x + DIRX (i), op->y + DIRY (i));
75 if (tmp && tmp->slaying == op->slaying) 76 if (tmp && tmp->slaying == op->slaying)
76 { /* same key both doors */ 77 { /* same key both doors */
77 tmp->set_speed (0.1f); 78 tmp->set_speed (0.1f);
78 tmp->speed_left = -0.2f; 79 tmp->speed_left = -0.2f;
79 } 80 }
237static void 238static void
238move_gate (object *op) 239move_gate (object *op)
239{ /* 1 = going down, 0 = going up */ 240{ /* 1 = going down, 0 = going up */
240 object *tmp; 241 object *tmp;
241 242
242 if (op->stats.wc < 0 || (int) op->stats.wc >= NUM_ANIMATIONS (op)) 243 if (uint32_t (op->stats.wc) >= op->anim_frames ())
243 { 244 {
244 LOG (llevError, "%s: gate error: animation was %d, max=%d\n", op->debug_desc (), op->stats.wc, NUM_ANIMATIONS (op)); 245 LOG (llevError, "%s: gate error: animation was %d, max=%d\n", op->debug_desc (), op->stats.wc, op->anim_frames ());
245 op->stats.wc = 0; 246 op->stats.wc = 0;
246 } 247 }
247 248
248 /* We're going down */
249 if (op->value) 249 if (op->value)
250 { 250 {
251 /* We're going down */
251 if (--op->stats.wc <= 0) 252 if (--op->stats.wc <= 0)
252 { /* Reached bottom, let's stop */ 253 { /* Reached bottom, let's stop */
253 op->stats.wc = 0; 254 op->stats.wc = 0;
254 if (op->arch->has_active_speed ()) 255 if (op->arch->has_active_speed ())
255 op->value = 0; 256 op->value = 0;
256 else 257 else
257 op->set_speed (0); 258 op->set_speed (0);
258 } 259 }
259 260
260 if ((int) op->stats.wc < (NUM_ANIMATIONS (op) / 2 + 1)) 261 if (op->stats.wc < op->anim_frames () / 2 + 1)
261 { 262 {
262 op->move_block = 0; 263 op->move_block = 0;
263 op->clr_flag (FLAG_BLOCKSVIEW); 264 op->clr_flag (FLAG_BLOCKSVIEW);
264 update_all_los (op->map, op->x, op->y); 265 update_all_los (op->map, op->x, op->y);
265 } 266 }
266
267 SET_ANIMATION (op, op->stats.wc);
268 update_object (op, UP_OBJ_CHANGE);
269 return;
270 }
271
272 /* We're going up */
273
274 /* First, lets see if we are already at the top */
275 if ((unsigned char) op->stats.wc == (NUM_ANIMATIONS (op) - 1))
276 {
277 /* Check to make sure that only non pickable and non rollable
278 * objects are above the gate. If so, we finish closing the gate,
279 * otherwise, we fall through to the code below which should lower
280 * the gate slightly.
281 */
282
283 for (tmp = op->above; tmp; tmp = tmp->above)
284 if (!tmp->flag [FLAG_NO_PICK] || tmp->flag [FLAG_CAN_ROLL] || tmp->flag [FLAG_ALIVE])
285 break;
286
287 if (!tmp)
288 {
289 if (op->arch->has_active_speed ())
290 op->value = 1;
291 else
292 op->set_speed (0);
293
294 return;
295 }
296 }
297
298 if (op->stats.food)
299 { /* The gate is going temporarily down */
300 if (--op->stats.wc <= 0)
301 { /* Gone all the way down? */
302 op->stats.food = 0; /* Then let's try again */
303 op->stats.wc = 0;
304 }
305 } 267 }
306 else 268 else
307 { /* The gate is still going up */ 269 {
308 op->stats.wc++; 270 /* We're going up */
309 271
310 if (op->stats.wc >= NUM_ANIMATIONS (op)) 272 /* First, lets see if we are already at the top */
311 op->stats.wc = NUM_ANIMATIONS (op) - 1; 273 if (op->stats.wc == op->anim_frames () - 1)
312
313 /* If there is something on top of the gate, we try to roll it off.
314 * If a player/monster, we don't roll, we just hit them with damage
315 */ 274 {
316 if (op->stats.wc >= NUM_ANIMATIONS (op) / 2) 275 /* Check to make sure that only non pickable and non rollable
317 { 276 * objects are above the gate. If so, we finish closing the gate,
318 /* Halfway or further, check blocks */ 277 * otherwise, we fall through to the code below which should lower
319 /* First, get the top object on the square. */ 278 * the gate slightly.
320 for (tmp = op->above; tmp && tmp->above; tmp = tmp->above)
321 ; 279 */
322 280
323 if (tmp)
324 {
325 if (tmp->flag [FLAG_ALIVE])
326 {
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"));
329
330 if (tmp->type == PLAYER)
331 new_draw_info_format (NDI_UNIQUE, 0, tmp, "You are crushed by the %s!", &op->name);
332 }
333 /* If the object is not alive, and the object either can
334 * be picked up or the object rolls, move the object
335 * off the gate.
336 */
337 else if (!tmp->flag [FLAG_ALIVE] && (!tmp->flag [FLAG_NO_PICK] || tmp->flag [FLAG_CAN_ROLL]))
338 {
339 /* If it has speed, it should move itself, otherwise: */
340 int i = find_free_spot (tmp, op->map, op->x, op->y, 1, SIZEOFFREE1 + 1);
341
342 /* If there is a free spot, move the object someplace */
343 if (i > 0)
344 {
345 mapxy pos (tmp);
346 pos.move (i);
347 if (pos.normalise ())
348 tmp->move_to (pos);
349 }
350 }
351 }
352
353 /* See if there is still anything blocking the gate */
354 for (tmp = op->above; tmp; tmp = tmp->above) 281 for (tmp = op->above; tmp; tmp = tmp->above)
355 if (!tmp->flag [FLAG_NO_PICK] || tmp->flag [FLAG_CAN_ROLL] || tmp->flag [FLAG_ALIVE]) 282 if (!tmp->flag [FLAG_NO_PICK] || tmp->flag [FLAG_CAN_ROLL] || tmp->flag [FLAG_ALIVE])
356 break; 283 break;
357 284
358 /* IF there is, start putting the gate down */
359 if (tmp) 285 if (!tmp)
286 {
287 if (op->arch->has_active_speed ())
288 op->value = 1;
289 else
290 op->set_speed (0);
291
292 return;
293 }
294 }
295
296 if (op->stats.food)
297 { /* The gate is going temporarily down */
298 if (--op->stats.wc <= 0)
299 { /* Gone all the way down? */
300 op->stats.food = 0; /* Then let's try again */
301 op->stats.wc = 0;
302 }
303 }
304 else
305 { /* The gate is still going up */
306 op->stats.wc++;
307 min_it (op->stats.wc, op->anim_frames () - 1);
308
309 /* If there is something on top of the gate, we try to roll it off.
310 * If a player/monster, we don't roll, we just hit them with damage
311 */
312 if (op->stats.wc >= op->anim_frames () / 2)
313 {
314 /* Halfway or further, check blocks */
315 /* First, get the top object on the square. */
316 for (tmp = op->above; tmp && tmp->above; tmp = tmp->above)
317 ;
318
319 if (tmp)
320 {
321 if (tmp->flag [FLAG_ALIVE])
322 {
323 hit_player (tmp, random_roll (0, op->stats.dam, tmp, PREFER_LOW), op, AT_PHYSICAL, 1);
324 op->play_sound (sound_find ("blocked_gate"));
325
326 if (tmp->type == PLAYER)
327 new_draw_info_format (NDI_UNIQUE, 0, tmp, "You are crushed by the %s!", &op->name);
328 }
329 /* If the object is not alive, and the object either can
330 * be picked up or the object rolls, move the object
331 * off the gate.
332 */
333 else if (!tmp->flag [FLAG_ALIVE] && (!tmp->flag [FLAG_NO_PICK] || tmp->flag [FLAG_CAN_ROLL]))
334 {
335 /* If it has speed, it should move itself, otherwise: */
336 int i = find_free_spot (tmp, op->map, op->x, op->y, 1, SIZEOFFREE1 + 1);
337
338 /* If there is a free spot, move the object someplace */
339 if (i > 0)
340 {
341 mapxy pos (tmp);
342 pos.move (i);
343 if (pos.normalise ())
344 tmp->move_to (pos);
345 }
346 }
347 }
348
349 /* See if there is still anything blocking the gate */
350 for (tmp = op->above; tmp; tmp = tmp->above)
351 if (!tmp->flag [FLAG_NO_PICK] || tmp->flag [FLAG_CAN_ROLL] || tmp->flag [FLAG_ALIVE])
352 break;
353
354 /* IF there is, start putting the gate down */
355 if (tmp)
360 op->stats.food = 1; 356 op->stats.food = 1;
361 else 357 else
362 { 358 {
363 op->move_block = MOVE_ALL; 359 op->move_block = MOVE_ALL;
364 360
365 if (!op->arch->stats.ac) 361 if (!op->arch->stats.ac)
366 op->set_flag (FLAG_BLOCKSVIEW); 362 op->set_flag (FLAG_BLOCKSVIEW);
363
367 update_all_los (op->map, op->x, op->y); 364 update_all_los (op->map, op->x, op->y);
368 } 365 }
369 } /* gate is halfway up */ 366 } /* gate is halfway up */
370
371 SET_ANIMATION (op, op->stats.wc);
372 update_object (op, UP_OBJ_CHANGE);
373 } /* gate is going up */ 367 } /* gate is going up */
368 }
369
370 op->update_anim_frame (op->stats.wc);
374} 371}
375 372
376/* hp : how long door is open/closed 373/* hp : how long door is open/closed
377 * maxhp : initial value for hp 374 * maxhp : initial value for hp
378 * sp : 1 = open, 0 = close 375 * sp : 1 = open, 0 = close
469} 466}
470 467
471void 468void
472animate_trigger (object *op) 469animate_trigger (object *op)
473{ 470{
474 if ((unsigned char) ++op->stats.wc >= NUM_ANIMATIONS (op)) 471 if (uint32_t (++op->stats.wc) >= op->anim_frames ())
475 { 472 {
476 op->stats.wc = 0; 473 op->stats.wc = 0;
477 check_trigger (op, NULL); 474 check_trigger (op, NULL);
478 } 475 }
479 else 476 else
480 { 477 op->update_anim_frame (op->stats.wc);
481 SET_ANIMATION (op, op->stats.wc);
482 update_object (op, UP_OBJ_FACE);
483 }
484} 478}
485 479
486static void 480static void
487move_hole (object *op) 481move_hole (object *op)
488{ /* 1 = opening, 0 = closing */ 482{ /* 1 = opening, 0 = closing */
489 if (op->value) 483 if (op->value)
490 { /* We're opening */ 484 {
485 /* We're opening */
486 op->stats.wc--;
491 if (--op->stats.wc <= 0) 487 if (op->stats.wc <= 0)
492 { /* Opened, let's stop */ 488 { /* Opened, let's stop */
493 op->stats.wc = 0; 489 op->stats.wc = 0;
494 op->set_speed (0); 490 op->set_speed (0);
495 491
496 /* Hard coding this makes sense for holes I suppose */ 492 /* Hard coding this makes sense for holes I suppose */
499 { 495 {
500 next = tmp->above; 496 next = tmp->above;
501 move_apply (op, tmp, tmp); 497 move_apply (op, tmp, tmp);
502 } 498 }
503 } 499 }
504 500 }
505 SET_ANIMATION (op, op->stats.wc); 501 else
506 update_object (op, UP_OBJ_CHANGE);
507 return;
508 } 502 {
509
510 /* We're closing */ 503 /* We're closing */
511 op->move_on = 0; 504 op->move_on = 0;
512 505
513 op->stats.wc++; 506 op->stats.wc++;
514 if (op->stats.wc >= NUM_ANIMATIONS (op)) 507 if (op->stats.wc >= op->anim_frames ())
515 op->stats.wc = NUM_ANIMATIONS (op) - 1; 508 {
516 509 op->stats.wc = op->anim_frames () - 1;
517 SET_ANIMATION (op, op->stats.wc);
518 update_object (op, UP_OBJ_CHANGE);
519 if (op->stats.wc == (NUM_ANIMATIONS (op) - 1))
520 op->set_speed (0); /* closed, let's stop */ 510 op->set_speed (0); /* closed, let's stop */
511 }
512 }
513
514 op->update_anim_frame (op->stats.wc);
521} 515}
522 516
523 517
524/* stop_item() returns a pointer to the stopped object. The stopped object 518/* stop_item() returns a pointer to the stopped object. The stopped object
525 * may or may not have been removed from maps or inventories. It will not 519 * may or may not have been removed from maps or inventories. It will not
609 op->stats.grace = 0; 603 op->stats.grace = 0;
610 op->level = 0; 604 op->level = 0;
611 op->face = op->arch->face; 605 op->face = op->arch->face;
612 op->owner = 0; 606 op->owner = 0;
613 607
608 op->clr_flag (FLAG_NO_PICK); /* fire_bow makes arrows NO_PICK so monsters (or anything else) don't pick them mid-flight */
609
614 update_object (op, UP_OBJ_CHANGE); 610 update_object (op, UP_OBJ_CHANGE);
615 611
616 return op; 612 return op;
617} 613}
618 614
689 * about 17 squares. Tune as needed. 685 * about 17 squares. Tune as needed.
690 */ 686 */
691 op->set_speed (op->speed - 0.05); 687 op->set_speed (op->speed - 0.05);
692 688
693 /* if the arrow is moving too slow.. stop it. 0.5 was chosen as lower 689 /* if the arrow is moving too slow.. stop it. 0.5 was chosen as lower
694 values look rediculous. */ 690 values look ridiculous. */
695 if (op->speed < (op->type == ARROW ? 0.5 : MIN_ACTIVE_SPEED)) 691 if (op->speed < (op->type == ARROW ? 0.5 : MIN_ACTIVE_SPEED))
696 { 692 {
697 stop_arrow (op); 693 stop_arrow (op);
698 return; 694 return;
699 } 695 }
713 if (pos->flags () & P_IS_ALIVE) 709 if (pos->flags () & P_IS_ALIVE)
714 { 710 {
715 object *tmp; 711 object *tmp;
716 712
717 for (tmp = pos->bot; tmp; tmp = tmp->above) 713 for (tmp = pos->bot; tmp; tmp = tmp->above)
718 if (tmp->flag [FLAG_ALIVE]) 714 if (tmp->flag [FLAG_ALIVE] && tmp != op->owner)
719 break; 715 {
720
721 /* Not really fair, but don't let monsters hit themselves with 716 /* Not really fair, but don't let monsters hit themselves with
722 * their own arrow - this can be because they fire it then 717 * their own arrow - this can be because they fire it then
723 * move into it. 718 * move into it.
724 */ 719 */
725 if (tmp && tmp != op->owner) 720
726 {
727 /* Found living object, but it is reflecting the missile. Update 721 /* Found living object, but it is reflecting the missile. Update
728 * as below. (Note that for living creatures there is a small 722 * as below. (Note that for living creatures there is a small
729 * chance that reflect_missile fails.) 723 * chance that reflect_missile fails.)
730 */ 724 */
731 if (tmp->flag [FLAG_REFL_MISSILE] && (rndm (0, 99)) < (90 - op->level / 10)) 725 if (tmp->flag [FLAG_REFL_MISSILE] && (rndm (0, 99)) < (90 - op->level / 10))
732 { 726 {
733 op->direction = absdir (op->direction + 4); 727 op->direction = absdir (op->direction + 4);
734 update_turn_face (op); 728 update_turn_face (op);
735 was_reflected = 1; /* skip normal movement calculations */ 729 was_reflected = 1; /* skip normal movement calculations */
736 } 730 }
737 else 731 else
738 { 732 {
739 /* Attack the object. */ 733 /* Attack the object. */
740 op = hit_with_arrow (op, tmp); 734 op = hit_with_arrow (op, tmp);
741 735
742 if (!op) 736 if (!op)
743 return; 737 return;
744 } 738 }
745 } /* if this is not hitting its owner */ 739
746 } /* if there is something alive on this space */ 740 break;
741 }
742 }
747 743
748 if (OB_TYPE_MOVE_BLOCK (op, pos->move_block)) 744 if (OB_TYPE_MOVE_BLOCK (op, pos->move_block))
749 { 745 {
750 int retry = 0; 746 int retry = 0;
751 747
1032 /* Determine direction only once so we do the right thing */ 1028 /* Determine direction only once so we do the right thing */
1033 // why is it the right thing, though? 1029 // why is it the right thing, though?
1034 if (!dir) 1030 if (!dir)
1035 dir = op->stats.sp ? op->stats.sp : rndm (1, 8); 1031 dir = op->stats.sp ? op->stats.sp : rndm (1, 8);
1036 1032
1037 sint16 nx = op->x + freearr_x[dir]; 1033 sint16 nx = op->x + DIRX (dir);
1038 sint16 ny = op->y + freearr_y[dir]; 1034 sint16 ny = op->y + DIRY (dir);
1039 maptile *m = op->map; 1035 maptile *m = op->map;
1040 if (get_map_flags (m, &m, nx, ny, &nx, &ny) & P_OUT_OF_MAP) 1036 if (get_map_flags (m, &m, nx, ny, &nx, &ny) & P_OUT_OF_MAP)
1041 { 1037 {
1042 LOG (llevError, "move_player_mover: Trying to push player off the map! map=%s (%d, %d)\n", &m->path, op->x, op->y); 1038 LOG (llevError, "move_player_mover: Trying to push player off the map! map=%s (%d, %d)\n", &m->path, op->x, op->y);
1043 return; 1039 return;
1129 break; 1125 break;
1130 } 1126 }
1131 } 1127 }
1132} 1128}
1133 1129
1134/* move_creator (by peterm) 1130/* move_creator (by peterm)
1135 * it has the creator object create it's other_arch right on top of it. 1131 * it has the creator object create it's other_arch right on top of it.
1136 * connected: what will trigger it 1132 * connected: what will trigger it
1137 * hp: how many times it may create before stopping 1133 * hp: how many times it may create before stopping
1138 * lifesave: if set, it'll never disappear but will go on creating 1134 * lifesave: if set, it'll never disappear but will go on creating
1139 * everytime it's triggered 1135 * everytime it's triggered

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines