1 #include "blue-magic/learnt-power-getter.h"
2 #include "blue-magic/blue-magic-checker.h"
3 #include "blue-magic/learnt-info.h"
4 #include "core/asking-player.h"
5 #include "core/stuff-handler.h"
6 #include "core/window-redrawer.h"
7 #include "game-option/text-display-options.h"
8 #include "io/command-repeater.h"
9 #include "io/input-key-acceptor.h"
10 #include "io/input-key-requester.h"
11 #include "main/sound-of-music.h"
12 #include "mind/mind-blue-mage.h"
13 #include "mspell/monster-power-table.h"
14 #include "realm/realm-types.h"
15 #include "spell/spell-info.h"
16 #include "term/screen-processor.h"
17 #include "util/int-char-converter.h"
18 #include "view/display-messages.h"
19 #include "player/player-status-table.h"
21 typedef struct learnt_magic_type {
30 int blue_magics[MAX_MONSPELLS];
45 static learnt_magic_type *initialize_lenat_magic_type(player_type *caster_ptr, learnt_magic_type *lm_ptr)
47 lm_ptr->blue_magic_num = 0;
51 lm_ptr->plev = caster_ptr->lev;
58 lm_ptr->menu_line = use_menu ? 1 : 0;
60 lm_ptr->redraw = FALSE;
66 * @param sn 選択したモンスター攻撃ID
67 * @return 発動可能な魔法を選択した場合TRUE、処理続行の場合FALSE
69 static bool check_blue_magic_cancel(SPELL_IDX *sn)
73 if (!repeat_pull(&code))
76 *sn = (SPELL_IDX)code;
80 static bool select_blue_magic_kind_menu(learnt_magic_type *lm_ptr)
82 while (lm_ptr->mode == 0) {
83 prt(format(_(" %s ボルト", " %s bolt"), (lm_ptr->menu_line == 1) ? _("》", "> ") : " "), 2, 14);
84 prt(format(_(" %s ボール", " %s ball"), (lm_ptr->menu_line == 2) ? _("》", "> ") : " "), 3, 14);
85 prt(format(_(" %s ブレス", " %s breath"), (lm_ptr->menu_line == 3) ? _("》", "> ") : " "), 4, 14);
86 prt(format(_(" %s 召喚", " %s sommoning"), (lm_ptr->menu_line == 4) ? _("》", "> ") : " "), 5, 14);
87 prt(format(_(" %s その他", " %s others"), (lm_ptr->menu_line == 5) ? _("》", "> ") : " "), 6, 14);
88 prt(_("どの種類の魔法を使いますか?", "use which type of magic? "), 0, 0);
90 lm_ptr->choice = inkey();
91 switch (lm_ptr->choice) {
105 lm_ptr->menu_line += 4;
110 lm_ptr->mode = lm_ptr->menu_line;
114 if (lm_ptr->menu_line > 5)
115 lm_ptr->menu_line -= 5;
121 static bool select_blue_magic_kind_command(learnt_magic_type *lm_ptr)
123 sprintf(lm_ptr->comment, _("[A]ボルト, [B]ボール, [C]ブレス, [D]召喚, [E]その他:", "[A] bolt, [B] ball, [C] breath, [D] summoning, [E] others:"));
126 if (!get_com(lm_ptr->comment, &ch, TRUE))
129 if (ch == 'A' || ch == 'a') {
134 if (ch == 'B' || ch == 'b') {
139 if (ch == 'C' || ch == 'c') {
144 if (ch == 'D' || ch == 'd') {
149 if (ch == 'E' || ch == 'e') {
158 static bool check_blue_magic_kind(learnt_magic_type *lm_ptr)
161 return select_blue_magic_kind_command(lm_ptr);
164 if (!select_blue_magic_kind_menu(lm_ptr))
171 static bool sweep_learnt_spells(player_type *caster_ptr, learnt_magic_type *lm_ptr)
173 set_rf_masks(&lm_ptr->f4, &lm_ptr->f5, &lm_ptr->f6, lm_ptr->mode);
174 for (lm_ptr->blue_magic_num = 0, lm_ptr->count = 0; lm_ptr->blue_magic_num < 32; lm_ptr->blue_magic_num++)
175 if ((0x00000001 << lm_ptr->blue_magic_num) & lm_ptr->f4)
176 lm_ptr->blue_magics[lm_ptr->count++] = lm_ptr->blue_magic_num;
178 for (; lm_ptr->blue_magic_num < 64; lm_ptr->blue_magic_num++)
179 if ((0x00000001 << (lm_ptr->blue_magic_num - 32)) & lm_ptr->f5)
180 lm_ptr->blue_magics[lm_ptr->count++] = lm_ptr->blue_magic_num;
182 for (; lm_ptr->blue_magic_num < 96; lm_ptr->blue_magic_num++)
183 if ((0x00000001 << (lm_ptr->blue_magic_num - 64)) & lm_ptr->f6)
184 lm_ptr->blue_magics[lm_ptr->count++] = lm_ptr->blue_magic_num;
186 for (lm_ptr->blue_magic_num = 0; lm_ptr->blue_magic_num < lm_ptr->count; lm_ptr->blue_magic_num++) {
187 if (caster_ptr->magic_num2[lm_ptr->blue_magics[lm_ptr->blue_magic_num]] == 0)
191 lm_ptr->menu_line = lm_ptr->blue_magic_num + 1;
196 if (lm_ptr->blue_magic_num == lm_ptr->count) {
197 msg_print(_("その種類の魔法は覚えていない!", "You don't know any spell of this type."));
201 (void)strnfmt(lm_ptr->out_val, 78, _("(%c-%c, '*'で一覧, ESC) どの%sを唱えますか?", "(%c-%c, *=List, ESC=exit) Use which %s? "), I2A(0),
202 I2A(lm_ptr->count - 1), _("魔法", "magic"));
206 static bool switch_blue_magic_choice(player_type *caster_ptr, learnt_magic_type *lm_ptr)
208 switch (lm_ptr->choice) {
216 lm_ptr->menu_line += (lm_ptr->count - 1);
217 if (lm_ptr->menu_line > lm_ptr->count)
218 lm_ptr->menu_line -= lm_ptr->count;
219 } while (!caster_ptr->magic_num2[lm_ptr->blue_magics[lm_ptr->menu_line - 1]]);
226 if (lm_ptr->menu_line > lm_ptr->count)
227 lm_ptr->menu_line -= lm_ptr->count;
228 } while (!caster_ptr->magic_num2[lm_ptr->blue_magics[lm_ptr->menu_line - 1]]);
233 lm_ptr->menu_line = lm_ptr->count;
234 while (!caster_ptr->magic_num2[lm_ptr->blue_magics[lm_ptr->menu_line - 1]])
241 lm_ptr->menu_line = 1;
242 while (!caster_ptr->magic_num2[lm_ptr->blue_magics[lm_ptr->menu_line - 1]])
249 lm_ptr->blue_magic_num = lm_ptr->menu_line - 1;
257 static void calculate_blue_magic_success_probability(player_type *caster_ptr, learnt_magic_type *lm_ptr)
259 lm_ptr->chance = lm_ptr->spell.fail;
260 if (lm_ptr->plev > lm_ptr->spell.level)
261 lm_ptr->chance -= 3 * (lm_ptr->plev - lm_ptr->spell.level);
263 lm_ptr->chance += (lm_ptr->spell.level - lm_ptr->plev);
265 lm_ptr->chance -= 3 * (adj_mag_stat[caster_ptr->stat_ind[A_INT]] - 1);
266 lm_ptr->chance = mod_spell_chance_1(caster_ptr, lm_ptr->chance);
267 lm_ptr->need_mana = mod_need_mana(caster_ptr, monster_powers[lm_ptr->blue_magics[lm_ptr->blue_magic_num]].smana, 0, REALM_NONE);
268 if (lm_ptr->need_mana > caster_ptr->csp)
269 lm_ptr->chance += 5 * (lm_ptr->need_mana - caster_ptr->csp);
271 PERCENTAGE minfail = adj_mag_fail[caster_ptr->stat_ind[A_INT]];
272 if (lm_ptr->chance < minfail)
273 lm_ptr->chance = minfail;
275 if (caster_ptr->stun > 50)
276 lm_ptr->chance += 25;
277 else if (caster_ptr->stun)
278 lm_ptr->chance += 15;
280 if (lm_ptr->chance > 95)
283 lm_ptr->chance = mod_spell_chance_2(caster_ptr, lm_ptr->chance);
286 static void close_blue_magic_name(learnt_magic_type *lm_ptr)
289 sprintf(lm_ptr->psi_desc, " %c)", I2A(lm_ptr->blue_magic_num));
293 if (lm_ptr->blue_magic_num == (lm_ptr->menu_line - 1))
294 strcpy(lm_ptr->psi_desc, _(" 》", " > "));
296 strcpy(lm_ptr->psi_desc, " ");
299 static void describe_blue_magic_name(player_type *caster_ptr, learnt_magic_type *lm_ptr)
301 prt("", lm_ptr->y, lm_ptr->x);
302 put_str(_("名前", "Name"), lm_ptr->y, lm_ptr->x + 5);
303 put_str(_("MP 失率 効果", "SP Fail Info"), lm_ptr->y, lm_ptr->x + 33);
304 for (lm_ptr->blue_magic_num = 0; lm_ptr->blue_magic_num < lm_ptr->count; lm_ptr->blue_magic_num++) {
305 prt("", lm_ptr->y + lm_ptr->blue_magic_num + 1, lm_ptr->x);
306 if (!caster_ptr->magic_num2[lm_ptr->blue_magics[lm_ptr->blue_magic_num]])
309 lm_ptr->spell = monster_powers[lm_ptr->blue_magics[lm_ptr->blue_magic_num]];
310 calculate_blue_magic_success_probability(caster_ptr, lm_ptr);
311 learnt_info(caster_ptr, lm_ptr->comment, lm_ptr->blue_magics[lm_ptr->blue_magic_num]);
312 close_blue_magic_name(lm_ptr);
313 strcat(lm_ptr->psi_desc, format(" %-26s %3d %3d%%%s", lm_ptr->spell.name, lm_ptr->need_mana, lm_ptr->chance, lm_ptr->comment));
314 prt(lm_ptr->psi_desc, lm_ptr->y + lm_ptr->blue_magic_num + 1, lm_ptr->x);
318 static bool blue_magic_key_input(player_type *caster_ptr, learnt_magic_type *lm_ptr)
320 if ((lm_ptr->choice != ' ') && (lm_ptr->choice != '*') && (lm_ptr->choice != '?') && (!use_menu || (lm_ptr->ask == 0)))
323 if (lm_ptr->redraw && !use_menu) {
324 lm_ptr->redraw = FALSE;
329 lm_ptr->redraw = TRUE;
333 describe_blue_magic_name(caster_ptr, lm_ptr);
335 prt("", lm_ptr->y + lm_ptr->blue_magic_num + 1, lm_ptr->x);
340 static void convert_lower_blue_magic_selection(learnt_magic_type *lm_ptr)
345 lm_ptr->ask = isupper(lm_ptr->choice);
347 lm_ptr->choice = (char)tolower(lm_ptr->choice);
349 lm_ptr->blue_magic_num = islower(lm_ptr->choice) ? A2I(lm_ptr->choice) : -1;
352 static bool ask_cast_blue_magic(learnt_magic_type *lm_ptr)
354 if (lm_ptr->ask == 0)
358 (void)strnfmt(tmp_val, 78, _("%sの魔法を唱えますか?", "Use %s? "), monster_powers[lm_ptr->blue_magics[lm_ptr->blue_magic_num]].name);
359 return get_check(tmp_val);
362 static bool select_learnt_spells(player_type *caster_ptr, learnt_magic_type *lm_ptr)
364 while (!lm_ptr->flag) {
365 if (lm_ptr->choice == ESCAPE)
366 lm_ptr->choice = ' ';
367 else if (!get_com(lm_ptr->out_val, &lm_ptr->choice, TRUE))
370 if (use_menu && (lm_ptr->choice != ' ') && !switch_blue_magic_choice(caster_ptr, lm_ptr))
373 if (blue_magic_key_input(caster_ptr, lm_ptr))
376 convert_lower_blue_magic_selection(lm_ptr);
377 if ((lm_ptr->blue_magic_num < 0) || (lm_ptr->blue_magic_num >= lm_ptr->count) || !caster_ptr->magic_num2[lm_ptr->blue_magics[lm_ptr->blue_magic_num]]) {
382 lm_ptr->spell = monster_powers[lm_ptr->blue_magics[lm_ptr->blue_magic_num]];
383 if (!ask_cast_blue_magic(lm_ptr))
393 * @brief 使用可能な青魔法を選択する /
394 * Allow user to choose a imitation.
395 * @param caster_ptr プレーヤーへの参照ポインタ
396 * @param sn 選択したモンスター攻撃ID、キャンセルの場合-1、不正な選択の場合-2を返す
397 * @return 発動可能な魔法を選択した場合TRUE、キャンセル処理か不正な選択が行われた場合FALSEを返す。
399 * If a valid spell is chosen, saves it in '*sn' and returns TRUE\n
400 * If the user hits escape, returns FALSE, and set '*sn' to -1\n
401 * If there are no legal choices, returns FALSE, and sets '*sn' to -2\n
403 * The "prompt" should be "cast", "recite", or "study"\n
404 * The "known" should be TRUE for cast/pray, FALSE for study\n
406 * nb: This function has a (trivial) display bug which will be obvious\n
407 * when you run it. It's probably easy to fix but I haven't tried,\n
410 bool get_learned_power(player_type *caster_ptr, SPELL_IDX *sn)
412 learnt_magic_type tmp_magic;
413 learnt_magic_type *lm_ptr = initialize_lenat_magic_type(caster_ptr, &tmp_magic);
414 if (check_blue_magic_cancel(sn))
417 if (!check_blue_magic_kind(lm_ptr) || !sweep_learnt_spells(caster_ptr, lm_ptr))
423 lm_ptr->choice = (always_show_list || use_menu) ? ESCAPE : 1;
424 if (!select_learnt_spells(caster_ptr, lm_ptr))
430 caster_ptr->window |= PW_SPELL;
431 handle_stuff(caster_ptr);
436 *sn = lm_ptr->blue_magics[lm_ptr->blue_magic_num];
437 repeat_push((COMMAND_CODE)lm_ptr->blue_magics[lm_ptr->blue_magic_num]);