OSDN Git Service

Merge branch 'master' of git.osdn.net:/gitroot/hengband/hengband
[hengband/hengband.git] / src / mind / mind-power-getter.c
1 #include "mind/mind-power-getter.h"
2 #include "core/asking-player.h"
3 #include "core/window-redrawer.h"
4 #include "core/stuff-handler.h"
5 #include "game-option/text-display-options.h"
6 #include "inventory/inventory-slot-types.h"
7 #include "io/command-repeater.h"
8 #include "io/input-key-requester.h"
9 #include "main/sound-of-music.h"
10 #include "mind/mind-explanations-table.h"
11 #include "mind/mind-force-trainer.h"
12 #include "mind/mind-info.h"
13 #include "mind/mind-types.h"
14 #include "player/player-class.h"
15 #include "term/screen-processor.h"
16 #include "util/int-char-converter.h"
17 #include "player/player-status-table.h"
18
19 /*!
20  * @brief 使用可能な特殊技能を選択する /
21  * Allow user to choose a mindcrafter power.
22  * @param sn 選択した特殊技能ID、キャンセルの場合-1、不正な選択の場合-2を返す
23  * @param only_browse 一覧を見るだけの場合TRUEを返す
24  * @return 発動可能な魔法を選択した場合TRUE、キャンセル処理か不正な選択が行われた場合FALSEを返す。
25  * @details
26  * If a valid spell is chosen, saves it in '*sn' and returns TRUE\n
27  * If the user hits escape, returns FALSE, and set '*sn' to -1\n
28  * If there are no legal choices, returns FALSE, and sets '*sn' to -2\n
29  *\n
30  * The "prompt" should be "cast", "recite", or "study"\n
31  * The "known" should be TRUE for cast/pray, FALSE for study\n
32  *\n
33  * nb: This function has a (trivial) display bug which will be obvious\n
34  * when you run it. It's probably easy to fix but I haven't tried,\n
35  * sorry.\n
36  */
37 bool get_mind_power(player_type *caster_ptr, SPELL_IDX *sn, bool only_browse)
38 {
39     SPELL_IDX i;
40     int num = 0;
41     TERM_LEN y = 1;
42     TERM_LEN x = 10;
43     PERCENTAGE minfail = 0;
44     PLAYER_LEVEL plev = caster_ptr->lev;
45     PERCENTAGE chance = 0;
46     int ask = TRUE;
47     char choice;
48     char out_val[160];
49     char comment[80];
50     concptr p;
51     COMMAND_CODE code;
52     mind_type spell;
53     const mind_power *mind_ptr;
54     bool flag, redraw;
55     int use_mind;
56     int menu_line = (use_menu ? 1 : 0);
57
58     switch (caster_ptr->pclass) {
59     case CLASS_MINDCRAFTER: {
60         use_mind = MIND_MINDCRAFTER;
61         p = _("超能力", "mindcraft");
62         break;
63     }
64     case CLASS_FORCETRAINER: {
65         use_mind = MIND_KI;
66         p = _("練気術", "Force");
67         break;
68     }
69     case CLASS_BERSERKER: {
70         use_mind = MIND_BERSERKER;
71         p = _("技", "brutal power");
72         break;
73     }
74     case CLASS_MIRROR_MASTER: {
75         use_mind = MIND_MIRROR_MASTER;
76         p = _("鏡魔法", "magic");
77         break;
78     }
79     case CLASS_NINJA: {
80         use_mind = MIND_NINJUTSU;
81         p = _("忍術", "ninjutsu");
82         break;
83     }
84     default: {
85         use_mind = 0;
86         p = _("超能力", "mindcraft");
87         break;
88     }
89     }
90
91     mind_ptr = &mind_powers[use_mind];
92     *sn = -1;
93     if (repeat_pull(&code)) {
94         *sn = (SPELL_IDX)code;
95         if (*sn == INVEN_FORCE)
96             repeat_pull(&code);
97
98         *sn = (SPELL_IDX)code;
99         if (mind_ptr->info[*sn].min_lev <= plev)
100             return TRUE;
101     }
102
103     flag = FALSE;
104     redraw = FALSE;
105
106     for (i = 0; i < MAX_MIND_POWERS; i++)
107         if (mind_ptr->info[i].min_lev <= plev)
108             num++;
109
110     if (only_browse)
111         (void)strnfmt(out_val, 78, _("(%^s %c-%c, '*'で一覧, ESC) どの%sについて知りますか?", "(%^ss %c-%c, *=List, ESC=exit) Use which %s? "), p, I2A(0),
112             I2A(num - 1), p);
113     else
114         (void)strnfmt(
115             out_val, 78, _("(%^s %c-%c, '*'で一覧, ESC) どの%sを使いますか?", "(%^ss %c-%c, *=List, ESC=exit) Use which %s? "), p, I2A(0), I2A(num - 1), p);
116
117     if (use_menu && !only_browse)
118         screen_save();
119
120     choice = (always_show_list || use_menu) ? ESCAPE : 1;
121     while (!flag) {
122         if (choice == ESCAPE)
123             choice = ' ';
124         else if (!get_com(out_val, &choice, TRUE))
125             break;
126
127         if (use_menu && choice != ' ') {
128             switch (choice) {
129             case '0': {
130                 if (!only_browse)
131                     screen_load();
132
133                 return FALSE;
134             }
135             case '8':
136             case 'k':
137             case 'K': {
138                 menu_line += (num - 1);
139                 break;
140             }
141             case '2':
142             case 'j':
143             case 'J': {
144                 menu_line++;
145                 break;
146             }
147             case 'x':
148             case 'X':
149             case '\r':
150             case '\n': {
151                 i = menu_line - 1;
152                 ask = FALSE;
153                 break;
154             }
155             }
156
157             if (menu_line > num)
158                 menu_line -= num;
159         }
160
161         if ((choice == ' ') || (choice == '*') || (choice == '?') || (use_menu && ask)) {
162             if (!redraw || use_menu) {
163                 char psi_desc[80];
164                 bool has_weapon[2];
165                 redraw = TRUE;
166                 if (!only_browse && !use_menu)
167                     screen_save();
168
169                 prt("", y, x);
170                 put_str(_("名前", "Name"), y, x + 5);
171                 put_str(format(_("Lv   %s   失率 効果", "Lv   %s   Fail Info"), ((use_mind == MIND_BERSERKER) || (use_mind == MIND_NINJUTSU)) ? "HP" : "MP"), y,
172                     x + 35);
173                 has_weapon[0] = has_melee_weapon(caster_ptr, INVEN_RARM);
174                 has_weapon[1] = has_melee_weapon(caster_ptr, INVEN_LARM);
175                 for (i = 0; i < MAX_MIND_POWERS; i++) {
176                     int mana_cost;
177                     spell = mind_ptr->info[i];
178                     if (spell.min_lev > plev)
179                         break;
180
181                     chance = spell.fail;
182                     mana_cost = spell.mana_cost;
183                     if (chance) {
184                         chance -= 3 * (plev - spell.min_lev);
185                         chance -= 3 * (adj_mag_stat[caster_ptr->stat_ind[mp_ptr->spell_stat]] - 1);
186                         if (use_mind == MIND_KI) {
187                             if (heavy_armor(caster_ptr))
188                                 chance += 20;
189
190                             if (caster_ptr->icky_wield[0])
191                                 chance += 20;
192                             else if (has_weapon[0])
193
194                                 chance += 10;
195                             if (caster_ptr->icky_wield[1])
196                                 chance += 20;
197                             else if (has_weapon[1])
198                                 chance += 10;
199
200                             if (i == 5) {
201                                 int j;
202                                 for (j = 0; j < get_current_ki(caster_ptr) / 50; j++)
203                                     mana_cost += (j + 1) * 3 / 2;
204                             }
205                         }
206
207                         if ((use_mind != MIND_BERSERKER) && (use_mind != MIND_NINJUTSU) && (mana_cost > caster_ptr->csp))
208                             chance += 5 * (mana_cost - caster_ptr->csp);
209
210                         chance += caster_ptr->to_m_chance;
211                         minfail = adj_mag_fail[caster_ptr->stat_ind[mp_ptr->spell_stat]];
212                         if (chance < minfail)
213                             chance = minfail;
214
215                         if (caster_ptr->stun > 50)
216                             chance += 25;
217                         else if (caster_ptr->stun)
218                             chance += 15;
219
220                         if (use_mind == MIND_KI) {
221                             if (heavy_armor(caster_ptr))
222                                 chance += 5;
223                             if (caster_ptr->icky_wield[0])
224                                 chance += 5;
225                             if (caster_ptr->icky_wield[1])
226                                 chance += 5;
227                         }
228
229                         if (chance > 95)
230                             chance = 95;
231                     }
232
233                     mindcraft_info(caster_ptr, comment, use_mind, i);
234                     if (use_menu) {
235                         if (i == (menu_line - 1))
236                             strcpy(psi_desc, _("  》 ", "  >  "));
237                         else
238                             strcpy(psi_desc, "     ");
239                     } else
240                         sprintf(psi_desc, "  %c) ", I2A(i));
241
242                     strcat(psi_desc,
243                         format("%-30s%2d %4d%s %3d%%%s", spell.name, spell.min_lev, mana_cost,
244                             (((use_mind == MIND_MINDCRAFTER) && (i == 13)) ? _("~", "~ ") : "  "), chance, comment));
245                     prt(psi_desc, y + i + 1, x);
246                 }
247
248                 prt("", y + i + 1, x);
249             } else if (!only_browse) {
250                 redraw = FALSE;
251                 screen_load();
252             }
253
254             continue;
255         }
256
257         if (!use_menu) {
258             ask = isupper(choice);
259             if (ask)
260                 choice = (char)tolower(choice);
261
262             i = (islower(choice) ? A2I(choice) : -1);
263         }
264
265         if ((i < 0) || (i >= num)) {
266             bell();
267             continue;
268         }
269
270         spell = mind_ptr->info[i];
271         if (ask) {
272             char tmp_val[160];
273             (void)strnfmt(tmp_val, 78, _("%sを使いますか?", "Use %s? "), spell.name);
274             if (!get_check(tmp_val))
275                 continue;
276         }
277
278         flag = TRUE;
279     }
280
281     if (redraw && !only_browse)
282         screen_load();
283
284     caster_ptr->window |= PW_SPELL;
285     handle_stuff(caster_ptr);
286     if (!flag)
287         return FALSE;
288
289     *sn = i;
290     repeat_push((COMMAND_CODE)i);
291     return TRUE;
292 }