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 | */ |
37 | void |
38 | void |
38 | remove_door (object *op) |
39 | remove_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 | } |
… | |
… | |
609 | op->stats.grace = 0; |
610 | op->stats.grace = 0; |
610 | op->level = 0; |
611 | op->level = 0; |
611 | op->face = op->arch->face; |
612 | op->face = op->arch->face; |
612 | op->owner = 0; |
613 | op->owner = 0; |
613 | |
614 | |
|
|
615 | op->clr_flag (FLAG_NO_PICK); /* fire_bow makes arrows NO_PICK so monsters (or anything else) don't pick them mid-flight */ |
|
|
616 | |
614 | update_object (op, UP_OBJ_CHANGE); |
617 | update_object (op, UP_OBJ_CHANGE); |
615 | |
618 | |
616 | return op; |
619 | return op; |
617 | } |
620 | } |
618 | |
621 | |
… | |
… | |
689 | * about 17 squares. Tune as needed. |
692 | * about 17 squares. Tune as needed. |
690 | */ |
693 | */ |
691 | op->set_speed (op->speed - 0.05); |
694 | op->set_speed (op->speed - 0.05); |
692 | |
695 | |
693 | /* if the arrow is moving too slow.. stop it. 0.5 was chosen as lower |
696 | /* if the arrow is moving too slow.. stop it. 0.5 was chosen as lower |
694 | values look rediculous. */ |
697 | values look ridiculous. */ |
695 | if (op->speed < (op->type == ARROW ? 0.5 : MIN_ACTIVE_SPEED)) |
698 | if (op->speed < (op->type == ARROW ? 0.5 : MIN_ACTIVE_SPEED)) |
696 | { |
699 | { |
697 | stop_arrow (op); |
700 | stop_arrow (op); |
698 | return; |
701 | return; |
699 | } |
702 | } |
… | |
… | |
713 | if (pos->flags () & P_IS_ALIVE) |
716 | if (pos->flags () & P_IS_ALIVE) |
714 | { |
717 | { |
715 | object *tmp; |
718 | object *tmp; |
716 | |
719 | |
717 | for (tmp = pos->bot; tmp; tmp = tmp->above) |
720 | for (tmp = pos->bot; tmp; tmp = tmp->above) |
718 | if (tmp->flag [FLAG_ALIVE]) |
721 | if (tmp->flag [FLAG_ALIVE] && tmp != op->owner) |
719 | break; |
722 | { |
720 | |
|
|
721 | /* Not really fair, but don't let monsters hit themselves with |
723 | /* Not really fair, but don't let monsters hit themselves with |
722 | * their own arrow - this can be because they fire it then |
724 | * their own arrow - this can be because they fire it then |
723 | * move into it. |
725 | * move into it. |
724 | */ |
726 | */ |
725 | if (tmp && tmp != op->owner) |
727 | |
726 | { |
|
|
727 | /* Found living object, but it is reflecting the missile. Update |
728 | /* Found living object, but it is reflecting the missile. Update |
728 | * as below. (Note that for living creatures there is a small |
729 | * as below. (Note that for living creatures there is a small |
729 | * chance that reflect_missile fails.) |
730 | * chance that reflect_missile fails.) |
730 | */ |
731 | */ |
731 | if (tmp->flag [FLAG_REFL_MISSILE] && (rndm (0, 99)) < (90 - op->level / 10)) |
732 | if (tmp->flag [FLAG_REFL_MISSILE] && (rndm (0, 99)) < (90 - op->level / 10)) |
732 | { |
733 | { |
733 | op->direction = absdir (op->direction + 4); |
734 | op->direction = absdir (op->direction + 4); |
734 | update_turn_face (op); |
735 | update_turn_face (op); |
735 | was_reflected = 1; /* skip normal movement calculations */ |
736 | was_reflected = 1; /* skip normal movement calculations */ |
736 | } |
737 | } |
737 | else |
738 | else |
738 | { |
739 | { |
739 | /* Attack the object. */ |
740 | /* Attack the object. */ |
740 | op = hit_with_arrow (op, tmp); |
741 | op = hit_with_arrow (op, tmp); |
741 | |
742 | |
742 | if (!op) |
743 | if (!op) |
743 | return; |
744 | return; |
744 | } |
745 | } |
745 | } /* if this is not hitting its owner */ |
746 | |
746 | } /* if there is something alive on this space */ |
747 | break; |
|
|
748 | } |
|
|
749 | } |
747 | |
750 | |
748 | if (OB_TYPE_MOVE_BLOCK (op, pos->move_block)) |
751 | if (OB_TYPE_MOVE_BLOCK (op, pos->move_block)) |
749 | { |
752 | { |
750 | int retry = 0; |
753 | int retry = 0; |
751 | |
754 | |
… | |
… | |
1032 | /* Determine direction only once so we do the right thing */ |
1035 | /* Determine direction only once so we do the right thing */ |
1033 | // why is it the right thing, though? |
1036 | // why is it the right thing, though? |
1034 | if (!dir) |
1037 | if (!dir) |
1035 | dir = op->stats.sp ? op->stats.sp : rndm (1, 8); |
1038 | dir = op->stats.sp ? op->stats.sp : rndm (1, 8); |
1036 | |
1039 | |
1037 | sint16 nx = op->x + freearr_x[dir]; |
1040 | sint16 nx = op->x + DIRX (dir); |
1038 | sint16 ny = op->y + freearr_y[dir]; |
1041 | sint16 ny = op->y + DIRY (dir); |
1039 | maptile *m = op->map; |
1042 | maptile *m = op->map; |
1040 | if (get_map_flags (m, &m, nx, ny, &nx, &ny) & P_OUT_OF_MAP) |
1043 | if (get_map_flags (m, &m, nx, ny, &nx, &ny) & P_OUT_OF_MAP) |
1041 | { |
1044 | { |
1042 | LOG (llevError, "move_player_mover: Trying to push player off the map! map=%s (%d, %d)\n", &m->path, op->x, op->y); |
1045 | 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; |
1046 | return; |
… | |
… | |
1129 | break; |
1132 | break; |
1130 | } |
1133 | } |
1131 | } |
1134 | } |
1132 | } |
1135 | } |
1133 | |
1136 | |
1134 | /* move_creator (by peterm) |
1137 | /* move_creator (by peterm) |
1135 | * it has the creator object create it's other_arch right on top of it. |
1138 | * it has the creator object create it's other_arch right on top of it. |
1136 | * connected: what will trigger it |
1139 | * connected: what will trigger it |
1137 | * hp: how many times it may create before stopping |
1140 | * hp: how many times it may create before stopping |
1138 | * lifesave: if set, it'll never disappear but will go on creating |
1141 | * lifesave: if set, it'll never disappear but will go on creating |
1139 | * everytime it's triggered |
1142 | * everytime it's triggered |