OSDN Git Service

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