OSDN Git Service

[Refactor] #2122 PlayerType::confused を削除し、TimedEffects::Confusion 側に処理を全て移した
[hengbandforosx/hengbandosx.git] / src / target / target-getter.cpp
1 #include "target/target-getter.h"
2 #include "core/asking-player.h"
3 #include "effect/spells-effect-util.h"
4 #include "floor/geometry.h"
5 #include "game-option/input-options.h"
6 #include "io/command-repeater.h"
7 #include "io/input-key-requester.h"
8 #include "main/sound-of-music.h"
9 #include "monster-race/monster-race.h"
10 #include "monster-race/race-flags1.h"
11 #include "monster/monster-describer.h"
12 #include "monster/monster-status.h"
13 #include "system/floor-type-definition.h"
14 #include "system/monster-race-definition.h"
15 #include "system/monster-type-definition.h"
16 #include "system/player-type-definition.h"
17 #include "target/target-checker.h"
18 #include "target/target-setter.h"
19 #include "target/target-types.h"
20 #include "timed-effect/player-confusion.h"
21 #include "timed-effect/timed-effects.h"
22 #include "view/display-messages.h"
23
24 /*
25  * Get an "aiming direction" from the user.
26  *
27  * The "dir" is loaded with 1,2,3,4,6,7,8,9 for "actual direction", and
28  * "0" for "current target", and "-1" for "entry aborted".
29  *
30  * Note that "Force Target", if set, will pre-empt user interaction,
31  * if there is a usable target already set.
32  *
33  * Note that confusion over-rides any (explicit?) user choice.
34  */
35 bool get_aim_dir(PlayerType *player_ptr, DIRECTION *dp)
36 {
37     DIRECTION dir = command_dir;
38     if (use_old_target && target_okay(player_ptr)) {
39         dir = 5;
40     }
41
42     COMMAND_CODE code;
43     if (repeat_pull(&code)) {
44         if (!(code == 5 && !target_okay(player_ptr))) {
45             dir = (DIRECTION)code;
46         }
47     }
48
49     *dp = (DIRECTION)code;
50     char command;
51     while (!dir) {
52         concptr p;
53         if (!target_okay(player_ptr)) {
54             p = _("方向 ('*'でターゲット選択, ESCで中断)? ", "Direction ('*' to choose a target, Escape to cancel)? ");
55         } else {
56             p = _("方向 ('5'でターゲットへ, '*'でターゲット再選択, ESCで中断)? ", "Direction ('5' for target, '*' to re-target, Escape to cancel)? ");
57         }
58
59         if (!get_com(p, &command, true)) {
60             break;
61         }
62
63         if (use_menu && (command == '\r')) {
64             command = 't';
65         }
66
67         switch (command) {
68         case 'T':
69         case 't':
70         case '.':
71         case '5':
72         case '0':
73             dir = 5;
74             break;
75         case '*':
76         case ' ':
77         case '\r':
78             if (target_set(player_ptr, TARGET_KILL)) {
79                 dir = 5;
80             }
81
82             break;
83         default:
84             dir = get_keymap_dir(command);
85             break;
86         }
87
88         if ((dir == 5) && !target_okay(player_ptr)) {
89             dir = 0;
90         }
91
92         if (!dir) {
93             bell();
94         }
95     }
96
97     if (!dir) {
98         project_length = 0;
99         return false;
100     }
101
102     command_dir = dir;
103     if (player_ptr->effects()->confusion()->is_confused()) {
104         dir = ddd[randint0(8)];
105     }
106
107     if (command_dir != dir) {
108         msg_print(_("あなたは混乱している。", "You are confused."));
109     }
110
111     *dp = dir;
112     repeat_push((COMMAND_CODE)command_dir);
113     return true;
114 }
115
116 bool get_direction(PlayerType *player_ptr, DIRECTION *dp, bool allow_under, bool with_steed)
117 {
118     DIRECTION dir = command_dir;
119     COMMAND_CODE code;
120     if (repeat_pull(&code)) {
121         dir = (DIRECTION)code;
122     }
123
124     *dp = (DIRECTION)code;
125     concptr prompt = allow_under ? _("方向 ('.'足元, ESCで中断)? ", "Direction ('.' at feet, Escape to cancel)? ")
126                                  : _("方向 (ESCで中断)? ", "Direction (Escape to cancel)? ");
127
128     while (!dir) {
129         char ch;
130         if (!get_com(prompt, &ch, true)) {
131             break;
132         }
133
134         if ((allow_under) && ((ch == '5') || (ch == '-') || (ch == '.'))) {
135             dir = 5;
136             continue;
137         }
138
139         dir = get_keymap_dir(ch);
140         if (!dir) {
141             bell();
142         }
143     }
144
145     if ((dir == 5) && (!allow_under)) {
146         dir = 0;
147     }
148
149     if (!dir) {
150         return false;
151     }
152
153     command_dir = dir;
154     auto is_confused = player_ptr->effects()->confusion()->is_confused();
155     if (is_confused) {
156         if (randint0(100) < 75) {
157             dir = ddd[randint0(8)];
158         }
159     } else if (player_ptr->riding && with_steed) {
160         auto *m_ptr = &player_ptr->current_floor_ptr->m_list[player_ptr->riding];
161         auto *r_ptr = &r_info[m_ptr->r_idx];
162         if (monster_confused_remaining(m_ptr)) {
163             if (randint0(100) < 75) {
164                 dir = ddd[randint0(8)];
165             }
166         } else if (r_ptr->behavior_flags.has(MonsterBehaviorType::RAND_MOVE_50) && r_ptr->behavior_flags.has(MonsterBehaviorType::RAND_MOVE_25) && (randint0(100) < 50)) {
167             dir = ddd[randint0(8)];
168         } else if (r_ptr->behavior_flags.has(MonsterBehaviorType::RAND_MOVE_50) && (randint0(100) < 25)) {
169             dir = ddd[randint0(8)];
170         }
171     }
172
173     if (command_dir != dir) {
174         if (is_confused) {
175             msg_print(_("あなたは混乱している。", "You are confused."));
176         } else {
177             GAME_TEXT m_name[MAX_NLEN];
178             auto *m_ptr = &player_ptr->current_floor_ptr->m_list[player_ptr->riding];
179
180             monster_desc(player_ptr, m_name, m_ptr, 0);
181             if (monster_confused_remaining(m_ptr)) {
182                 msg_format(_("%sは混乱している。", "%^s is confused."), m_name);
183             } else {
184                 msg_format(_("%sは思い通りに動いてくれない。", "You cannot control %s."), m_name);
185             }
186         }
187     }
188
189     *dp = dir;
190     repeat_push((COMMAND_CODE)command_dir);
191     return true;
192 }
193
194 /*
195  * @brief 進行方向を指定する(騎乗対象の混乱の影響を受ける) / Request a "movement" direction (1,2,3,4,6,7,8,9) from the user,
196  * and place it into "command_dir", unless we already have one.
197  *
198  * This function should be used for all "repeatable" commands, such as
199  * run, walk, open, close, bash, disarm, spike, tunnel, etc, as well
200  * as all commands which must reference a grid adjacent to the player,
201  * and which may not reference the grid under the player.  Note that,
202  * for example, it is no longer possible to "disarm" or "open" chests
203  * in the same grid as the player.
204  *
205  * Direction "5" is illegal and will (cleanly) abort the command.
206  *
207  * This function tracks and uses the "global direction", and uses
208  * that as the "desired direction", to which "confusion" is applied.
209  */
210 bool get_rep_dir(PlayerType *player_ptr, DIRECTION *dp, bool under)
211 {
212     DIRECTION dir = command_dir;
213     COMMAND_CODE code;
214     if (repeat_pull(&code)) {
215         dir = (DIRECTION)code;
216     }
217
218     *dp = (DIRECTION)code;
219     concptr prompt = under ? _("方向 ('.'足元, ESCで中断)? ", "Direction ('.' at feet, Escape to cancel)? ") : _("方向 (ESCで中断)? ", "Direction (Escape to cancel)? ");
220     while (!dir) {
221         char ch;
222         if (!get_com(prompt, &ch, true)) {
223             break;
224         }
225
226         if ((under) && ((ch == '5') || (ch == '-') || (ch == '.'))) {
227             dir = 5;
228             continue;
229         }
230
231         dir = get_keymap_dir(ch);
232         if (!dir) {
233             bell();
234         }
235     }
236
237     if ((dir == 5) && (!under)) {
238         dir = 0;
239     }
240
241     if (!dir) {
242         return false;
243     }
244
245     command_dir = dir;
246     auto is_confused = player_ptr->effects()->confusion()->is_confused();
247     if (is_confused) {
248         if (randint0(100) < 75) {
249             dir = ddd[randint0(8)];
250         }
251     } else if (player_ptr->riding) {
252         auto *m_ptr = &player_ptr->current_floor_ptr->m_list[player_ptr->riding];
253         auto *r_ptr = &r_info[m_ptr->r_idx];
254         if (monster_confused_remaining(m_ptr)) {
255             if (randint0(100) < 75) {
256                 dir = ddd[randint0(8)];
257             }
258         } else if (r_ptr->behavior_flags.has_all_of({ MonsterBehaviorType::RAND_MOVE_50, MonsterBehaviorType::RAND_MOVE_25 }) && (randint0(100) < 50)) {
259             dir = ddd[randint0(8)];
260         } else if (r_ptr->behavior_flags.has(MonsterBehaviorType::RAND_MOVE_50) && (randint0(100) < 25)) {
261             dir = ddd[randint0(8)];
262         }
263     }
264
265     if (command_dir != dir) {
266         if (is_confused) {
267             msg_print(_("あなたは混乱している。", "You are confused."));
268         } else {
269             GAME_TEXT m_name[MAX_NLEN];
270             auto *m_ptr = &player_ptr->current_floor_ptr->m_list[player_ptr->riding];
271             monster_desc(player_ptr, m_name, m_ptr, 0);
272             if (monster_confused_remaining(m_ptr)) {
273                 msg_format(_("%sは混乱している。", "%^s is confused."), m_name);
274             } else {
275                 msg_format(_("%sは思い通りに動いてくれない。", "You cannot control %s."), m_name);
276             }
277         }
278     }
279
280     *dp = dir;
281     repeat_push((COMMAND_CODE)command_dir);
282     return true;
283 }