OSDN Git Service

Merge pull request #2335 from sikabane-works/release/3.0.0Alpha54
[hengbandforosx/hengbandosx.git] / src / spell-kind / spells-fetcher.cpp
1 #include "spell-kind/spells-fetcher.h"
2 #include "core/player-redraw-types.h"
3 #include "core/player-update-types.h"
4 #include "core/stuff-handler.h"
5 #include "flavor/flavor-describer.h"
6 #include "flavor/object-flavor-types.h"
7 #include "floor/cave.h"
8 #include "floor/geometry.h"
9 #include "grid/feature-flag-types.h"
10 #include "grid/grid.h"
11 #include "monster-race/monster-race.h"
12 #include "monster-race/race-flags7.h"
13 #include "monster/monster-describer.h"
14 #include "monster/monster-status-setter.h"
15 #include "monster/monster-update.h"
16 #include "system/floor-type-definition.h"
17 #include "system/grid-type-definition.h"
18 #include "system/monster-race-definition.h"
19 #include "system/monster-type-definition.h"
20 #include "system/object-type-definition.h"
21 #include "system/player-type-definition.h"
22 #include "target/projection-path-calculator.h"
23 #include "target/target-checker.h"
24 #include "target/target-setter.h"
25 #include "target/target-types.h"
26 #include "timed-effect/player-hallucination.h"
27 #include "timed-effect/timed-effects.h"
28 #include "util/bit-flags-calculator.h"
29 #include "view/display-messages.h"
30
31 /*!
32  * @brief アイテム引き寄せ処理 /
33  * Fetch an item (teleport it right underneath the caster)
34  * @param player_ptr プレイヤーへの参照ポインタ
35  * @param dir 魔法の発動方向
36  * @param wgt 許容重量
37  * @param require_los 射線の通りを要求するならばTRUE
38  */
39 void fetch_item(PlayerType *player_ptr, DIRECTION dir, WEIGHT wgt, bool require_los)
40 {
41     grid_type *g_ptr;
42     ObjectType *o_ptr;
43     GAME_TEXT o_name[MAX_NLEN];
44
45     if (!player_ptr->current_floor_ptr->grid_array[player_ptr->y][player_ptr->x].o_idx_list.empty()) {
46         msg_print(_("自分の足の下にある物は取れません。", "You can't fetch when you're already standing on something."));
47         return;
48     }
49
50     POSITION ty, tx;
51     if (dir == 5 && target_okay(player_ptr)) {
52         tx = target_col;
53         ty = target_row;
54
55         if (distance(player_ptr->y, player_ptr->x, ty, tx) > get_max_range(player_ptr)) {
56             msg_print(_("そんなに遠くにある物は取れません!", "You can't fetch something that far away!"));
57             return;
58         }
59
60         g_ptr = &player_ptr->current_floor_ptr->grid_array[ty][tx];
61         if (g_ptr->o_idx_list.empty()) {
62             msg_print(_("そこには何もありません。", "There is no object there."));
63             return;
64         }
65
66         if (g_ptr->is_icky()) {
67             msg_print(_("アイテムがコントロールを外れて落ちた。", "The item slips from your control."));
68             return;
69         }
70
71         if (require_los) {
72             if (!player_has_los_bold(player_ptr, ty, tx)) {
73                 msg_print(_("そこはあなたの視界に入っていません。", "You have no direct line of sight to that location."));
74                 return;
75             } else if (!projectable(player_ptr, player_ptr->y, player_ptr->x, ty, tx)) {
76                 msg_print(_("そこは壁の向こうです。", "You have no direct line of sight to that location."));
77                 return;
78             }
79         }
80     } else {
81         ty = player_ptr->y;
82         tx = player_ptr->x;
83         bool is_first_loop = true;
84         g_ptr = &player_ptr->current_floor_ptr->grid_array[ty][tx];
85         while (is_first_loop || g_ptr->o_idx_list.empty()) {
86             is_first_loop = false;
87             ty += ddy[dir];
88             tx += ddx[dir];
89             g_ptr = &player_ptr->current_floor_ptr->grid_array[ty][tx];
90
91             if ((distance(player_ptr->y, player_ptr->x, ty, tx) > get_max_range(player_ptr)) || !cave_has_flag_bold(player_ptr->current_floor_ptr, ty, tx, FloorFeatureType::PROJECT)) {
92                 return;
93             }
94         }
95     }
96
97     o_ptr = &player_ptr->current_floor_ptr->o_list[g_ptr->o_idx_list.front()];
98     if (o_ptr->weight > wgt) {
99         msg_print(_("そのアイテムは重過ぎます。", "The object is too heavy."));
100         return;
101     }
102
103     OBJECT_IDX i = g_ptr->o_idx_list.front();
104     g_ptr->o_idx_list.pop_front();
105     player_ptr->current_floor_ptr->grid_array[player_ptr->y][player_ptr->x].o_idx_list.add(player_ptr->current_floor_ptr, i); /* 'move' it */
106
107     o_ptr->iy = player_ptr->y;
108     o_ptr->ix = player_ptr->x;
109
110     describe_flavor(player_ptr, o_name, o_ptr, OD_NAME_ONLY);
111     msg_format(_("%^sがあなたの足元に飛んできた。", "%^s flies through the air to your feet."), o_name);
112
113     note_spot(player_ptr, player_ptr->y, player_ptr->x);
114     player_ptr->redraw |= PR_MAP;
115 }
116
117 bool fetch_monster(PlayerType *player_ptr)
118 {
119     monster_type *m_ptr;
120     MONSTER_IDX m_idx;
121     GAME_TEXT m_name[MAX_NLEN];
122     int i;
123     int path_n;
124     uint16_t path_g[512];
125     POSITION ty, tx;
126
127     if (!target_set(player_ptr, TARGET_KILL)) {
128         return false;
129     }
130
131     m_idx = player_ptr->current_floor_ptr->grid_array[target_row][target_col].m_idx;
132     if (!m_idx) {
133         return false;
134     }
135     if (m_idx == player_ptr->riding) {
136         return false;
137     }
138     if (!player_has_los_bold(player_ptr, target_row, target_col)) {
139         return false;
140     }
141     if (!projectable(player_ptr, player_ptr->y, player_ptr->x, target_row, target_col)) {
142         return false;
143     }
144
145     m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
146     monster_desc(player_ptr, m_name, m_ptr, 0);
147     msg_format(_("%sを引き戻した。", "You pull back %s."), m_name);
148     path_n = projection_path(player_ptr, path_g, get_max_range(player_ptr), target_row, target_col, player_ptr->y, player_ptr->x, 0);
149     ty = target_row, tx = target_col;
150     for (i = 1; i < path_n; i++) {
151         POSITION ny = get_grid_y(path_g[i]);
152         POSITION nx = get_grid_x(path_g[i]);
153         auto *g_ptr = &player_ptr->current_floor_ptr->grid_array[ny][nx];
154
155         if (in_bounds(player_ptr->current_floor_ptr, ny, nx) && is_cave_empty_bold(player_ptr, ny, nx) && !g_ptr->is_object() && !pattern_tile(player_ptr->current_floor_ptr, ny, nx)) {
156             ty = ny;
157             tx = nx;
158         }
159     }
160
161     player_ptr->current_floor_ptr->grid_array[target_row][target_col].m_idx = 0;
162     player_ptr->current_floor_ptr->grid_array[ty][tx].m_idx = m_idx;
163     m_ptr->fy = ty;
164     m_ptr->fx = tx;
165     (void)set_monster_csleep(player_ptr, m_idx, 0);
166     update_monster(player_ptr, m_idx, true);
167     lite_spot(player_ptr, target_row, target_col);
168     lite_spot(player_ptr, ty, tx);
169     if (r_info[m_ptr->r_idx].flags7 & (RF7_LITE_MASK | RF7_DARK_MASK)) {
170         player_ptr->update |= (PU_MON_LITE);
171     }
172
173     if (m_ptr->ml) {
174         if (!player_ptr->effects()->hallucination()->is_hallucinated()) {
175             monster_race_track(player_ptr, m_ptr->ap_r_idx);
176         }
177
178         health_track(player_ptr, m_idx);
179     }
180
181     return true;
182 }