OSDN Git Service

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