OSDN Git Service

Revert "Revert "Merge branch 'master' of git.osdn.net:/gitroot/hengband/hengband""
[hengband/hengband.git] / src / mind / mind-power-getter.c
diff --git a/src/mind/mind-power-getter.c b/src/mind/mind-power-getter.c
new file mode 100644 (file)
index 0000000..53a416e
--- /dev/null
@@ -0,0 +1,292 @@
+#include "mind/mind-power-getter.h"
+#include "core/asking-player.h"
+#include "core/window-redrawer.h"
+#include "core/stuff-handler.h"
+#include "game-option/text-display-options.h"
+#include "inventory/inventory-slot-types.h"
+#include "io/command-repeater.h"
+#include "io/input-key-requester.h"
+#include "main/sound-of-music.h"
+#include "mind/mind-explanations-table.h"
+#include "mind/mind-force-trainer.h"
+#include "mind/mind-info.h"
+#include "mind/mind-types.h"
+#include "player/player-class.h"
+#include "term/screen-processor.h"
+#include "util/int-char-converter.h"
+#include "player/player-status-table.h"
+
+/*!
+ * @brief 使用可能な特殊技能を選択する /
+ * Allow user to choose a mindcrafter power.
+ * @param sn 選択した特殊技能ID、キャンセルの場合-1、不正な選択の場合-2を返す
+ * @param only_browse 一覧を見るだけの場合TRUEを返す
+ * @return 発動可能な魔法を選択した場合TRUE、キャンセル処理か不正な選択が行われた場合FALSEを返す。
+ * @details
+ * If a valid spell is chosen, saves it in '*sn' and returns TRUE\n
+ * If the user hits escape, returns FALSE, and set '*sn' to -1\n
+ * If there are no legal choices, returns FALSE, and sets '*sn' to -2\n
+ *\n
+ * The "prompt" should be "cast", "recite", or "study"\n
+ * The "known" should be TRUE for cast/pray, FALSE for study\n
+ *\n
+ * nb: This function has a (trivial) display bug which will be obvious\n
+ * when you run it. It's probably easy to fix but I haven't tried,\n
+ * sorry.\n
+ */
+bool get_mind_power(player_type *caster_ptr, SPELL_IDX *sn, bool only_browse)
+{
+    SPELL_IDX i;
+    int num = 0;
+    TERM_LEN y = 1;
+    TERM_LEN x = 10;
+    PERCENTAGE minfail = 0;
+    PLAYER_LEVEL plev = caster_ptr->lev;
+    PERCENTAGE chance = 0;
+    int ask = TRUE;
+    char choice;
+    char out_val[160];
+    char comment[80];
+    concptr p;
+    COMMAND_CODE code;
+    mind_type spell;
+    const mind_power *mind_ptr;
+    bool flag, redraw;
+    int use_mind;
+    int menu_line = (use_menu ? 1 : 0);
+
+    switch (caster_ptr->pclass) {
+    case CLASS_MINDCRAFTER: {
+        use_mind = MIND_MINDCRAFTER;
+        p = _("超能力", "mindcraft");
+        break;
+    }
+    case CLASS_FORCETRAINER: {
+        use_mind = MIND_KI;
+        p = _("練気術", "Force");
+        break;
+    }
+    case CLASS_BERSERKER: {
+        use_mind = MIND_BERSERKER;
+        p = _("技", "brutal power");
+        break;
+    }
+    case CLASS_MIRROR_MASTER: {
+        use_mind = MIND_MIRROR_MASTER;
+        p = _("鏡魔法", "magic");
+        break;
+    }
+    case CLASS_NINJA: {
+        use_mind = MIND_NINJUTSU;
+        p = _("忍術", "ninjutsu");
+        break;
+    }
+    default: {
+        use_mind = 0;
+        p = _("超能力", "mindcraft");
+        break;
+    }
+    }
+
+    mind_ptr = &mind_powers[use_mind];
+    *sn = -1;
+    if (repeat_pull(&code)) {
+        *sn = (SPELL_IDX)code;
+        if (*sn == INVEN_FORCE)
+            repeat_pull(&code);
+
+        *sn = (SPELL_IDX)code;
+        if (mind_ptr->info[*sn].min_lev <= plev)
+            return TRUE;
+    }
+
+    flag = FALSE;
+    redraw = FALSE;
+
+    for (i = 0; i < MAX_MIND_POWERS; i++)
+        if (mind_ptr->info[i].min_lev <= plev)
+            num++;
+
+    if (only_browse)
+        (void)strnfmt(out_val, 78, _("(%^s %c-%c, '*'で一覧, ESC) どの%sについて知りますか?", "(%^ss %c-%c, *=List, ESC=exit) Use which %s? "), p, I2A(0),
+            I2A(num - 1), p);
+    else
+        (void)strnfmt(
+            out_val, 78, _("(%^s %c-%c, '*'で一覧, ESC) どの%sを使いますか?", "(%^ss %c-%c, *=List, ESC=exit) Use which %s? "), p, I2A(0), I2A(num - 1), p);
+
+    if (use_menu && !only_browse)
+        screen_save();
+
+    choice = (always_show_list || use_menu) ? ESCAPE : 1;
+    while (!flag) {
+        if (choice == ESCAPE)
+            choice = ' ';
+        else if (!get_com(out_val, &choice, TRUE))
+            break;
+
+        if (use_menu && choice != ' ') {
+            switch (choice) {
+            case '0': {
+                if (!only_browse)
+                    screen_load();
+
+                return FALSE;
+            }
+            case '8':
+            case 'k':
+            case 'K': {
+                menu_line += (num - 1);
+                break;
+            }
+            case '2':
+            case 'j':
+            case 'J': {
+                menu_line++;
+                break;
+            }
+            case 'x':
+            case 'X':
+            case '\r':
+            case '\n': {
+                i = menu_line - 1;
+                ask = FALSE;
+                break;
+            }
+            }
+
+            if (menu_line > num)
+                menu_line -= num;
+        }
+
+        if ((choice == ' ') || (choice == '*') || (choice == '?') || (use_menu && ask)) {
+            if (!redraw || use_menu) {
+                char psi_desc[80];
+                bool has_weapon[2];
+                redraw = TRUE;
+                if (!only_browse && !use_menu)
+                    screen_save();
+
+                prt("", y, x);
+                put_str(_("名前", "Name"), y, x + 5);
+                put_str(format(_("Lv   %s   失率 効果", "Lv   %s   Fail Info"), ((use_mind == MIND_BERSERKER) || (use_mind == MIND_NINJUTSU)) ? "HP" : "MP"), y,
+                    x + 35);
+                has_weapon[0] = has_melee_weapon(caster_ptr, INVEN_RARM);
+                has_weapon[1] = has_melee_weapon(caster_ptr, INVEN_LARM);
+                for (i = 0; i < MAX_MIND_POWERS; i++) {
+                    int mana_cost;
+                    spell = mind_ptr->info[i];
+                    if (spell.min_lev > plev)
+                        break;
+
+                    chance = spell.fail;
+                    mana_cost = spell.mana_cost;
+                    if (chance) {
+                        chance -= 3 * (plev - spell.min_lev);
+                        chance -= 3 * (adj_mag_stat[caster_ptr->stat_ind[mp_ptr->spell_stat]] - 1);
+                        if (use_mind == MIND_KI) {
+                            if (heavy_armor(caster_ptr))
+                                chance += 20;
+
+                            if (caster_ptr->icky_wield[0])
+                                chance += 20;
+                            else if (has_weapon[0])
+
+                                chance += 10;
+                            if (caster_ptr->icky_wield[1])
+                                chance += 20;
+                            else if (has_weapon[1])
+                                chance += 10;
+
+                            if (i == 5) {
+                                int j;
+                                for (j = 0; j < get_current_ki(caster_ptr) / 50; j++)
+                                    mana_cost += (j + 1) * 3 / 2;
+                            }
+                        }
+
+                        if ((use_mind != MIND_BERSERKER) && (use_mind != MIND_NINJUTSU) && (mana_cost > caster_ptr->csp))
+                            chance += 5 * (mana_cost - caster_ptr->csp);
+
+                        chance += caster_ptr->to_m_chance;
+                        minfail = adj_mag_fail[caster_ptr->stat_ind[mp_ptr->spell_stat]];
+                        if (chance < minfail)
+                            chance = minfail;
+
+                        if (caster_ptr->stun > 50)
+                            chance += 25;
+                        else if (caster_ptr->stun)
+                            chance += 15;
+
+                        if (use_mind == MIND_KI) {
+                            if (heavy_armor(caster_ptr))
+                                chance += 5;
+                            if (caster_ptr->icky_wield[0])
+                                chance += 5;
+                            if (caster_ptr->icky_wield[1])
+                                chance += 5;
+                        }
+
+                        if (chance > 95)
+                            chance = 95;
+                    }
+
+                    mindcraft_info(caster_ptr, comment, use_mind, i);
+                    if (use_menu) {
+                        if (i == (menu_line - 1))
+                            strcpy(psi_desc, _("  》 ", "  >  "));
+                        else
+                            strcpy(psi_desc, "     ");
+                    } else
+                        sprintf(psi_desc, "  %c) ", I2A(i));
+
+                    strcat(psi_desc,
+                        format("%-30s%2d %4d%s %3d%%%s", spell.name, spell.min_lev, mana_cost,
+                            (((use_mind == MIND_MINDCRAFTER) && (i == 13)) ? _("~", "~ ") : "  "), chance, comment));
+                    prt(psi_desc, y + i + 1, x);
+                }
+
+                prt("", y + i + 1, x);
+            } else if (!only_browse) {
+                redraw = FALSE;
+                screen_load();
+            }
+
+            continue;
+        }
+
+        if (!use_menu) {
+            ask = isupper(choice);
+            if (ask)
+                choice = (char)tolower(choice);
+
+            i = (islower(choice) ? A2I(choice) : -1);
+        }
+
+        if ((i < 0) || (i >= num)) {
+            bell();
+            continue;
+        }
+
+        spell = mind_ptr->info[i];
+        if (ask) {
+            char tmp_val[160];
+            (void)strnfmt(tmp_val, 78, _("%sを使いますか?", "Use %s? "), spell.name);
+            if (!get_check(tmp_val))
+                continue;
+        }
+
+        flag = TRUE;
+    }
+
+    if (redraw && !only_browse)
+        screen_load();
+
+    caster_ptr->window |= PW_SPELL;
+    handle_stuff(caster_ptr);
+    if (!flag)
+        return FALSE;
+
+    *sn = i;
+    repeat_push((COMMAND_CODE)i);
+    return TRUE;
+}