OSDN Git Service

[Refactor] #40575 Separated select_racial_power() from do_cmd_racial_power()
[hengband/hengband.git] / src / cmd-action / cmd-racial.c
1 #include "cmd-action/cmd-racial.h"
2 #include "action/action-limited.h"
3 #include "action/mutation-execution.h"
4 #include "core/asking-player.h"
5 #include "core/player-redraw-types.h"
6 #include "core/player-update-types.h"
7 #include "core/window-redrawer.h"
8 #include "game-option/text-display-options.h"
9 #include "io/command-repeater.h"
10 #include "io/input-key-requester.h"
11 #include "main/sound-of-music.h"
12 #include "mutation/mutation-flag-types.h"
13 #include "player/attack-defense-types.h"
14 #include "player/player-damage.h"
15 #include "player/special-defense-types.h"
16 #include "racial/class-racial-switcher.h"
17 #include "racial/mutation-racial-selector.h"
18 #include "racial/race-racial-switcher.h"
19 #include "racial/racial-switcher.h"
20 #include "racial/racial-util.h"
21 #include "status/action-setter.h"
22 #include "term/screen-processor.h"
23 #include "util/int-char-converter.h"
24
25 static bool input_racial_technique_selection(player_type *creature_ptr, rc_type *rc_ptr)
26 {
27     switch (rc_ptr->choice) {
28     case '0':
29         screen_load();
30         free_turn(creature_ptr);
31         return TRUE;
32     case '8':
33     case 'k':
34     case 'K':
35         rc_ptr->menu_line += (rc_ptr->num - 1);
36         return FALSE;
37     case '2':
38     case 'j':
39     case 'J':
40         rc_ptr->menu_line++;
41         return FALSE;
42     case '6':
43     case 'l':
44     case 'L':
45     case '4':
46     case 'h':
47     case 'H':
48         if (rc_ptr->menu_line > 18)
49             rc_ptr->menu_line -= 18;
50         else if (rc_ptr->menu_line + 18 <= rc_ptr->num)
51             rc_ptr->menu_line += 18;
52
53         return FALSE;
54     case 'x':
55     case 'X':
56     case '\r':
57         rc_ptr->command_code = rc_ptr->menu_line - 1;
58         rc_ptr->ask = FALSE;
59         return FALSE;
60     default:
61         return FALSE;
62     }
63 }
64
65 static void display_racial_list(rc_type *rc_ptr, char *dummy)
66 {
67     strcpy(dummy, "");
68     rc_ptr->redraw = TRUE;
69     if (!use_menu)
70         screen_save();
71
72     if (rc_ptr->num < 18) {
73         prt(_("                            Lv   MP 失率", "                            Lv Cost Fail"), 1, 0);
74         return;
75     }
76
77     prt(_("                            Lv   MP 失率                            Lv   MP 失率",
78             "                            Lv Cost Fail                            Lv Cost Fail"),
79         1, 0);
80 }
81
82 static void select_racial_power(player_type *creature_ptr, rc_type *rc_ptr)
83 {
84     char dummy[80];
85     display_racial_list(rc_ptr, dummy);
86     byte y = 2;
87     byte x = 0;
88     int ctr = 0;
89     while (ctr < rc_ptr->num) {
90         TERM_LEN x1 = ((ctr < 18) ? x : x + 40);
91         TERM_LEN y1 = ((ctr < 18) ? y + ctr : y + ctr - 18);
92         if (use_menu) {
93             if (ctr == (rc_ptr->menu_line - 1))
94                 strcpy(dummy, _(" 》 ", " >  "));
95             else
96                 strcpy(dummy, "    ");
97         } else {
98             char letter;
99             if (ctr < 26)
100                 letter = I2A(ctr);
101             else
102                 letter = '0' + ctr - 26;
103
104             sprintf(dummy, " %c) ", letter);
105         }
106
107         strcat(dummy,
108             format("%-23.23s %2d %4d %3d%%", rc_ptr->power_desc[ctr].racial_name, rc_ptr->power_desc[ctr].min_level, rc_ptr->power_desc[ctr].cost,
109                 100 - racial_chance(creature_ptr, &rc_ptr->power_desc[ctr])));
110         prt(dummy, y1, x1);
111         ctr++;
112     }
113 }
114
115 /*!
116  * @brief レイシャル・パワーコマンドのメインルーチン / Allow user to choose a power (racial / mutation) to activate
117  * @param creature_ptr プレーヤーへの参照ポインタ
118  * @return なし
119  */
120 void do_cmd_racial_power(player_type *creature_ptr)
121 {
122     if (creature_ptr->wild_mode)
123         return;
124
125     if (cmd_limit_confused(creature_ptr)) {
126         free_turn(creature_ptr);
127         return;
128     }
129
130     if (creature_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN))
131         set_action(creature_ptr, ACTION_NONE);
132
133     rc_type tmp_rc;
134     rc_type *rc_ptr = initialize_rc_type(creature_ptr, &tmp_rc);
135     switch_class_racial(creature_ptr, rc_ptr);
136     if (creature_ptr->mimic_form)
137         switch_mimic_racial(creature_ptr, rc_ptr);
138     else
139         switch_race_racial(creature_ptr, rc_ptr);
140
141     select_mutation_racial(creature_ptr, rc_ptr);
142     rc_ptr->flag = FALSE;
143     rc_ptr->redraw = FALSE;
144
145     (void)strnfmt(rc_ptr->out_val, 78,
146         _("(特殊能力 %c-%c, *'で一覧, ESCで中断) どの特殊能力を使いますか?", "(Powers %c-%c, *=List, ESC=exit) Use which power? "), I2A(0),
147         (rc_ptr->num <= 26) ? I2A(rc_ptr->num - 1) : '0' + rc_ptr->num - 27);
148
149     if (!repeat_pull(&rc_ptr->command_code) || rc_ptr->command_code < 0 || rc_ptr->command_code >= rc_ptr->num) {
150         if (use_menu)
151             screen_save();
152
153         rc_ptr->choice = (always_show_list || use_menu) ? ESCAPE : 1;
154         while (!rc_ptr->flag) {
155             if (rc_ptr->choice == ESCAPE)
156                 rc_ptr->choice = ' ';
157             else if (!get_com(rc_ptr->out_val, &rc_ptr->choice, FALSE))
158                 break;
159
160             if (use_menu && rc_ptr->choice != ' ') {
161                 if (input_racial_technique_selection(creature_ptr, rc_ptr))
162                     return;
163
164                 if (rc_ptr->menu_line > rc_ptr->num)
165                     rc_ptr->menu_line -= rc_ptr->num;
166             }
167
168             if ((rc_ptr->choice == ' ') || (rc_ptr->choice == '*') || (rc_ptr->choice == '?') || (use_menu && rc_ptr->ask)) {
169                 if (!rc_ptr->redraw || use_menu) {
170                     select_racial_power(creature_ptr, rc_ptr);
171                 } else {
172                     rc_ptr->redraw = FALSE;
173                     screen_load();
174                 }
175
176                 continue;
177             }
178
179             if (!use_menu) {
180                 if (rc_ptr->choice == '\r' && rc_ptr->num == 1)
181                     rc_ptr->choice = 'a';
182
183                 if (isalpha(rc_ptr->choice)) {
184                     rc_ptr->ask = (isupper(rc_ptr->choice));
185                     if (rc_ptr->ask)
186                         rc_ptr->choice = (char)tolower(rc_ptr->choice);
187
188                     rc_ptr->command_code = (islower(rc_ptr->choice) ? A2I(rc_ptr->choice) : -1);
189                 } else {
190                     rc_ptr->ask = FALSE;
191                     rc_ptr->command_code = rc_ptr->choice - '0' + 26;
192                 }
193             }
194
195             if ((rc_ptr->command_code < 0) || (rc_ptr->command_code >= rc_ptr->num)) {
196                 bell();
197                 continue;
198             }
199
200             if (rc_ptr->ask) {
201                 char tmp_val[160];
202                 (void)strnfmt(tmp_val, 78, _("%sを使いますか? ", "Use %s? "), rc_ptr->power_desc[rc_ptr->command_code].racial_name);
203                 if (!get_check(tmp_val))
204                     continue;
205             }
206
207             rc_ptr->flag = TRUE;
208         }
209
210         if (rc_ptr->redraw)
211             screen_load();
212
213         if (!rc_ptr->flag) {
214             free_turn(creature_ptr);
215             return;
216         }
217
218         repeat_push(rc_ptr->command_code);
219     }
220
221     switch (racial_aux(creature_ptr, &rc_ptr->power_desc[rc_ptr->command_code])) {
222     case 1:
223         if (rc_ptr->power_desc[rc_ptr->command_code].number < 0)
224             rc_ptr->cast = exe_racial_power(creature_ptr, rc_ptr->power_desc[rc_ptr->command_code].number);
225         else
226             rc_ptr->cast = exe_mutation_power(creature_ptr, rc_ptr->power_desc[rc_ptr->command_code].number);
227
228         break;
229     case 0:
230         rc_ptr->cast = FALSE;
231         break;
232     case -1:
233         rc_ptr->cast = TRUE;
234         break;
235     }
236
237     if (!rc_ptr->cast) {
238         free_turn(creature_ptr);
239         return;
240     }
241
242     int racial_cost = rc_ptr->power_desc[rc_ptr->command_code].racial_cost;
243     if (racial_cost == 0)
244         return;
245
246     int actual_racial_cost = racial_cost / 2 + randint1(racial_cost / 2);
247     if (creature_ptr->csp >= actual_racial_cost) {
248         creature_ptr->csp -= actual_racial_cost;    
249     } else {
250         actual_racial_cost -= creature_ptr->csp;
251         creature_ptr->csp = 0;
252         take_hit(creature_ptr, DAMAGE_USELIFE, actual_racial_cost, _("過度の集中", "concentrating too hard"), -1);
253     }
254
255     creature_ptr->redraw |= PR_HP | PR_MANA;
256     creature_ptr->window |= PW_PLAYER | PW_SPELL;
257 }