avatar.h avatar.c \
\
birth.c bldg.c cave.c chest.c chest.h chuukei.c \
- cmd1.c cmd2.c cmd4.c cmd5.c cmd-activate.c cmd-activate.h cmd-eat.c cmd-eat.h \
+ cmd1.c cmd2.c cmd4.c cmd-activate.c cmd-activate.h cmd-eat.c cmd-eat.h \
cmd-item.c cmd-item.h cmd-magiceat.c cmd-magiceat.h cmd-pet.c cmd-pet.h \
cmd-quaff.c cmd-quaff.h cmd-read.c cmd-read.h cmd-spell.c cmd-spell.h \
cmd-usestaff.c cmd-usestaff.h cmd-zaprod.c cmd-zaprod.h cmd-zapwand.c \
#include "mutation.h"
#include "quest.h"
#include "artifact.h"
+#include "cmd-spell.h"
/*!
* ループ中で / hack as in leave_store in store.c
/* Increment the equip counter by hand */
equip_cnt++;
-#ifdef JP
-#define STR_WIELD_RARM "%s(%c)を右手に装備した。"
-#define STR_WIELD_LARM "%s(%c)を左手に装備した。"
-#define STR_WIELD_ARMS "%s(%c)を両手で構えた。"
-#else
-#define STR_WIELD_RARM "You are wielding %s (%c) in your right hand."
-#define STR_WIELD_LARM "You are wielding %s (%c) in your left hand."
-#define STR_WIELD_ARMS "You are wielding %s (%c) with both hands."
-#endif
+#define STR_WIELD_RARM _("%s(%c)を右手に装備した。", "You are wielding %s (%c) in your right hand.")
+#define STR_WIELD_LARM _("%s(%c)を左手に装備した。", "You are wielding %s (%c) in your left hand.")
+#define STR_WIELD_ARMS _("%s(%c)を両手で構えた。", "You are wielding %s (%c) with both hands.")
/* Where is the item now */
switch (slot)
#include "realm-song.h"\r
#include "realm-sorcery.h"\r
#include "realm-trump.h"\r
+#include "angband.h"\r
+#include "avatar.h"\r
+#include "player-status.h"\r
+#include "object-hook.h"\r
\r
/*!\r
* @brief\r
\r
return NULL;\r
}\r
+\r
+\r
+/*!\r
+ * @brief 領域魔法の閲覧、学習、使用選択するインターフェイス処理\r
+ * Allow user to choose a spell/prayer from the given book.\r
+ * @param sn 選択した魔法IDを返す参照ポインタ\r
+ * @param prompt 魔法を利用する際の動詞表記\r
+ * @param sval 魔道書のsval\r
+ * @param learned 閲覧/使用選択ならばTRUE、学習処理ならFALSE\r
+ * @param use_realm 魔法領域ID\r
+ * @return\r
+ * <pre>\r
+ * If a valid spell is chosen, saves it in '*sn' and returns TRUE\r
+ * If the user hits escape, returns FALSE, and set '*sn' to -1\r
+ * If there are no legal choices, returns FALSE, and sets '*sn' to -2\r
+ * The "prompt" should be "cast", "recite", or "study"\r
+ * The "known" should be TRUE for cast/pray, FALSE for study\r
+ * </pre>\r
+ */\r
+static int get_spell(SPELL_IDX *sn, concptr prompt, OBJECT_SUBTYPE_VALUE sval, bool learned, REALM_IDX use_realm)\r
+{\r
+ int i;\r
+ SPELL_IDX spell = -1;\r
+ int num = 0;\r
+ int ask = TRUE;\r
+ MANA_POINT need_mana;\r
+ SPELL_IDX spells[64];\r
+ bool flag, redraw, okay;\r
+ char choice;\r
+ const magic_type *s_ptr;\r
+ char out_val[160];\r
+ concptr p;\r
+ COMMAND_CODE code;\r
+#ifdef JP\r
+ char jverb_buf[128];\r
+#endif\r
+ int menu_line = (use_menu ? 1 : 0);\r
+\r
+ /* Get the spell, if available */\r
+ if (repeat_pull(&code))\r
+ {\r
+ *sn = (SPELL_IDX)code;\r
+ /* Verify the spell */\r
+ if (spell_okay(*sn, learned, FALSE, use_realm))\r
+ {\r
+ /* Success */\r
+ return (TRUE);\r
+ }\r
+ }\r
+\r
+ p = spell_category_name(mp_ptr->spell_book);\r
+\r
+ /* Extract spells */\r
+ for (spell = 0; spell < 32; spell++)\r
+ {\r
+ /* Check for this spell */\r
+ if ((fake_spell_flags[sval] & (1L << spell)))\r
+ {\r
+ /* Collect this spell */\r
+ spells[num++] = spell;\r
+ }\r
+ }\r
+\r
+ /* Assume no usable spells */\r
+ okay = FALSE;\r
+\r
+ /* Assume no spells available */\r
+ (*sn) = -2;\r
+\r
+ /* Check for "okay" spells */\r
+ for (i = 0; i < num; i++)\r
+ {\r
+ /* Look for "okay" spells */\r
+ if (spell_okay(spells[i], learned, FALSE, use_realm)) okay = TRUE;\r
+ }\r
+\r
+ /* No "okay" spells */\r
+ if (!okay) return (FALSE);\r
+ if (((use_realm) != p_ptr->realm1) && ((use_realm) != p_ptr->realm2) && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE)) return FALSE;\r
+ if (((p_ptr->pclass == CLASS_SORCERER) || (p_ptr->pclass == CLASS_RED_MAGE)) && !is_magic(use_realm)) return FALSE;\r
+ if ((p_ptr->pclass == CLASS_RED_MAGE) && ((use_realm) != REALM_ARCANE) && (sval > 1)) return FALSE;\r
+\r
+ /* Assume cancelled */\r
+ *sn = (-1);\r
+\r
+ /* Nothing chosen yet */\r
+ flag = FALSE;\r
+\r
+ /* No redraw yet */\r
+ redraw = FALSE;\r
+\r
+ p_ptr->window |= (PW_SPELL);\r
+ handle_stuff();\r
+\r
+ /* Build a prompt (accept all spells) */\r
+#ifdef JP\r
+ jverb(prompt, jverb_buf, JVERB_AND);\r
+ (void)strnfmt(out_val, 78, "(%^s:%c-%c, '*'で一覧, ESCで中断) どの%sを%^sますか? ",\r
+ p, I2A(0), I2A(num - 1), p, jverb_buf);\r
+#else\r
+ (void)strnfmt(out_val, 78, "(%^ss %c-%c, *=List, ESC=exit) %^s which %s? ",\r
+ p, I2A(0), I2A(num - 1), prompt, p);\r
+#endif\r
+\r
+ /* Get a spell from the user */\r
+\r
+ choice = (always_show_list || use_menu) ? ESCAPE : 1;\r
+ while (!flag)\r
+ {\r
+ if (choice == ESCAPE) choice = ' ';\r
+ else if (!get_com(out_val, &choice, TRUE))break;\r
+\r
+ if (use_menu && choice != ' ')\r
+ {\r
+ switch (choice)\r
+ {\r
+ case '0':\r
+ {\r
+ screen_load();\r
+ return FALSE;\r
+ }\r
+\r
+ case '8':\r
+ case 'k':\r
+ case 'K':\r
+ {\r
+ menu_line += (num - 1);\r
+ break;\r
+ }\r
+\r
+ case '2':\r
+ case 'j':\r
+ case 'J':\r
+ {\r
+ menu_line++;\r
+ break;\r
+ }\r
+\r
+ case 'x':\r
+ case 'X':\r
+ case '\r':\r
+ case '\n':\r
+ {\r
+ i = menu_line - 1;\r
+ ask = FALSE;\r
+ break;\r
+ }\r
+ }\r
+ if (menu_line > num) menu_line -= num;\r
+ /* Display a list of spells */\r
+ print_spells(menu_line, spells, num, 1, 15, use_realm);\r
+ if (ask) continue;\r
+ }\r
+ else\r
+ {\r
+ /* Request redraw */\r
+ if ((choice == ' ') || (choice == '*') || (choice == '?'))\r
+ {\r
+ /* Show the list */\r
+ if (!redraw)\r
+ {\r
+ /* Show list */\r
+ redraw = TRUE;\r
+ screen_save();\r
+\r
+ /* Display a list of spells */\r
+ print_spells(menu_line, spells, num, 1, 15, use_realm);\r
+ }\r
+\r
+ /* Hide the list */\r
+ else\r
+ {\r
+ if (use_menu) continue;\r
+\r
+ /* Hide list */\r
+ redraw = FALSE;\r
+ screen_load();\r
+ }\r
+\r
+ /* Redo asking */\r
+ continue;\r
+ }\r
+\r
+\r
+ /* Note verify */\r
+ ask = (isupper(choice));\r
+\r
+ /* Lowercase */\r
+ if (ask) choice = (char)tolower(choice);\r
+\r
+ /* Extract request */\r
+ i = (islower(choice) ? A2I(choice) : -1);\r
+ }\r
+\r
+ /* Totally Illegal */\r
+ if ((i < 0) || (i >= num))\r
+ {\r
+ bell();\r
+ continue;\r
+ }\r
+\r
+ /* Save the spell index */\r
+ spell = spells[i];\r
+\r
+ /* Require "okay" spells */\r
+ if (!spell_okay(spell, learned, FALSE, use_realm))\r
+ {\r
+ bell();\r
+#ifdef JP\r
+ msg_format("その%sを%sことはできません。", p, prompt);\r
+#else\r
+ msg_format("You may not %s that %s.", prompt, p);\r
+#endif\r
+\r
+ continue;\r
+ }\r
+\r
+ /* Verify it */\r
+ if (ask)\r
+ {\r
+ char tmp_val[160];\r
+\r
+ /* Access the spell */\r
+ if (!is_magic(use_realm))\r
+ {\r
+ s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell];\r
+ }\r
+ else\r
+ {\r
+ s_ptr = &mp_ptr->info[use_realm - 1][spell];\r
+ }\r
+\r
+ /* Extract mana consumption rate */\r
+ if (use_realm == REALM_HISSATSU)\r
+ {\r
+ need_mana = s_ptr->smana;\r
+ }\r
+ else\r
+ {\r
+ need_mana = mod_need_mana(s_ptr->smana, spell, use_realm);\r
+ }\r
+\r
+ /* Prompt */\r
+#ifdef JP\r
+ jverb(prompt, jverb_buf, JVERB_AND);\r
+ /* 英日切り替え機能に対応 */\r
+ (void)strnfmt(tmp_val, 78, "%s(MP%d, 失敗率%d%%)を%sますか? ",\r
+ do_spell(use_realm, spell, SPELL_NAME), need_mana,\r
+ spell_chance(spell, use_realm), jverb_buf);\r
+#else\r
+ (void)strnfmt(tmp_val, 78, "%^s %s (%d mana, %d%% fail)? ",\r
+ prompt, do_spell(use_realm, spell, SPELL_NAME), need_mana,\r
+ spell_chance(spell, use_realm));\r
+#endif\r
+\r
+\r
+ /* Belay that order */\r
+ if (!get_check(tmp_val)) continue;\r
+ }\r
+\r
+ /* Stop the loop */\r
+ flag = TRUE;\r
+ }\r
+\r
+ if (redraw) screen_load();\r
+\r
+ p_ptr->window |= (PW_SPELL);\r
+ handle_stuff();\r
+\r
+ /* Abort if needed */\r
+ if (!flag) return FALSE;\r
+\r
+ /* Save the choice */\r
+ (*sn) = spell;\r
+\r
+ repeat_push((COMMAND_CODE)spell);\r
+\r
+ /* Success */\r
+ return TRUE;\r
+}\r
+\r
+/*!\r
+ * @brief プレイヤーの職業が練気術師の時、領域魔法と練気術を切り換える処理のインターフェイス\r
+ * @param browse_only 魔法と技能の閲覧を行うならばTRUE\r
+ * @return 魔道書を一冊も持っていないならTRUEを返す\r
+ */\r
+static void confirm_use_force(bool browse_only)\r
+{\r
+ char which;\r
+ COMMAND_CODE code;\r
+\r
+ /* Get the item index */\r
+ if (repeat_pull(&code) && (code == INVEN_FORCE))\r
+ {\r
+ browse_only ? do_cmd_mind_browse() : do_cmd_mind();\r
+ return;\r
+ }\r
+\r
+ /* Show the prompt */\r
+ prt(_("('w'練気術, ESC) 'w'かESCを押してください。 ", "(w for the Force, ESC) Hit 'w' or ESC. "), 0, 0);\r
+\r
+ while (1)\r
+ {\r
+ /* Get a key */\r
+ which = inkey();\r
+\r
+ if (which == ESCAPE) break;\r
+ else if (which == 'w')\r
+ {\r
+ repeat_push(INVEN_FORCE);\r
+ break;\r
+ }\r
+ }\r
+\r
+ /* Clear the prompt line */\r
+ prt("", 0, 0);\r
+\r
+ if (which == 'w')\r
+ {\r
+ browse_only ? do_cmd_mind_browse() : do_cmd_mind();\r
+ }\r
+}\r
+\r
+\r
+/*!\r
+ * @brief プレイヤーの魔法と技能を閲覧するコマンドのメインルーチン /\r
+ * Peruse the spells/prayers in a book\r
+ * @return なし\r
+ * @details\r
+ * <pre>\r
+ * Note that *all* spells in the book are listed\r
+ *\r
+ * Note that browsing is allowed while confused or blind,\r
+ * and in the dark, primarily to allow browsing in stores.\r
+ * </pre>\r
+ */\r
+void do_cmd_browse(void)\r
+{\r
+ OBJECT_IDX item;\r
+ OBJECT_SUBTYPE_VALUE sval;\r
+ REALM_IDX use_realm = 0;\r
+ int j, line;\r
+ SPELL_IDX spell = -1;\r
+ int num = 0;\r
+\r
+ SPELL_IDX spells[64];\r
+ char temp[62 * 4];\r
+\r
+ object_type *o_ptr;\r
+\r
+ concptr q, s;\r
+\r
+ /* Warriors are illiterate */\r
+ if (!(p_ptr->realm1 || p_ptr->realm2) && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE))\r
+ {\r
+ msg_print(_("本を読むことができない!", "You cannot read books!"));\r
+ return;\r
+ }\r
+\r
+ if (p_ptr->special_defense & KATA_MUSOU)\r
+ {\r
+ set_action(ACTION_NONE);\r
+ }\r
+\r
+ if (p_ptr->pclass == CLASS_FORCETRAINER)\r
+ {\r
+ if (player_has_no_spellbooks())\r
+ {\r
+ confirm_use_force(TRUE);\r
+ return;\r
+ }\r
+ }\r
+\r
+ /* Restrict choices to "useful" books */\r
+ if (p_ptr->realm2 == REALM_NONE) item_tester_tval = mp_ptr->spell_book;\r
+ else item_tester_hook = item_tester_learn_spell;\r
+\r
+ q = _("どの本を読みますか? ", "Browse which book? ");\r
+ s = _("読める本がない。", "You have no books that you can read.");\r
+\r
+ o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR | (p_ptr->pclass == CLASS_FORCETRAINER ? USE_FORCE : 0)));\r
+ if (!o_ptr)\r
+ {\r
+ if (item == INVEN_FORCE) /* the_force */\r
+ {\r
+ do_cmd_mind_browse();\r
+ return;\r
+ }\r
+ return;\r
+ }\r
+\r
+ /* Access the item's sval */\r
+ sval = o_ptr->sval;\r
+\r
+ use_realm = tval2realm(o_ptr->tval);\r
+\r
+ /* Track the object kind */\r
+ object_kind_track(o_ptr->k_idx);\r
+ handle_stuff();\r
+\r
+ /* Extract spells */\r
+ for (spell = 0; spell < 32; spell++)\r
+ {\r
+ /* Check for this spell */\r
+ if ((fake_spell_flags[sval] & (1L << spell)))\r
+ {\r
+ /* Collect this spell */\r
+ spells[num++] = spell;\r
+ }\r
+ }\r
+\r
+ screen_save();\r
+ prt("", 0, 0);\r
+\r
+ /* Keep browsing spells. Exit browsing on cancel. */\r
+ while (TRUE)\r
+ {\r
+ /* Ask for a spell, allow cancel */\r
+ if (!get_spell(&spell, _("読む", "browse"), o_ptr->sval, TRUE, use_realm))\r
+ {\r
+ /* If cancelled, leave immediately. */\r
+ if (spell == -1) break;\r
+\r
+ /* Display a list of spells */\r
+ print_spells(0, spells, num, 1, 15, use_realm);\r
+\r
+ /* Notify that there's nothing to see, and wait. */\r
+ if (use_realm == REALM_HISSATSU)\r
+ prt(_("読める技がない。", "No techniques to browse."), 0, 0);\r
+ else\r
+ prt(_("読める呪文がない。", "No spells to browse."), 0, 0);\r
+ (void)inkey();\r
+\r
+ screen_load();\r
+\r
+ return;\r
+ }\r
+\r
+ /* Clear lines, position cursor (really should use strlen here) */\r
+ Term_erase(14, 14, 255);\r
+ Term_erase(14, 13, 255);\r
+ Term_erase(14, 12, 255);\r
+ Term_erase(14, 11, 255);\r
+\r
+ roff_to_buf(do_spell(use_realm, spell, SPELL_DESC), 62, temp, sizeof(temp));\r
+\r
+ for (j = 0, line = 11; temp[j]; j += 1 + strlen(&temp[j]))\r
+ {\r
+ prt(&temp[j], line, 15);\r
+ line++;\r
+ }\r
+ }\r
+ screen_load();\r
+}\r
+\r
+/*!\r
+ * @brief プレイヤーの第二魔法領域を変更する /\r
+ * @param next_realm 変更先の魔法領域ID\r
+ * @return なし\r
+ */\r
+static void change_realm2(CHARACTER_IDX next_realm)\r
+{\r
+ int i, j = 0;\r
+ char tmp[80];\r
+\r
+ for (i = 0; i < 64; i++)\r
+ {\r
+ p_ptr->spell_order[j] = p_ptr->spell_order[i];\r
+ if (p_ptr->spell_order[i] < 32) j++;\r
+ }\r
+ for (; j < 64; j++)\r
+ p_ptr->spell_order[j] = 99;\r
+\r
+ for (i = 32; i < 64; i++)\r
+ {\r
+ p_ptr->spell_exp[i] = SPELL_EXP_UNSKILLED;\r
+ }\r
+ p_ptr->spell_learned2 = 0L;\r
+ p_ptr->spell_worked2 = 0L;\r
+ p_ptr->spell_forgotten2 = 0L;\r
+\r
+ sprintf(tmp, _("魔法の領域を%sから%sに変更した。", "change magic realm from %s to %s."), realm_names[p_ptr->realm2], realm_names[next_realm]);\r
+ do_cmd_write_nikki(NIKKI_BUNSHOU, 0, tmp);\r
+ p_ptr->old_realm |= 1 << (p_ptr->realm2 - 1);\r
+ p_ptr->realm2 = next_realm;\r
+\r
+ p_ptr->update |= (PU_REORDER);\r
+ p_ptr->update |= (PU_SPELLS);\r
+ handle_stuff();\r
+\r
+ /* Load an autopick preference file */\r
+ autopick_load_pref(FALSE);\r
+}\r
+\r
+\r
+/*!\r
+ * @brief 魔法を学習するコマンドのメインルーチン /\r
+ * Study a book to gain a new spell/prayer\r
+ * @return なし\r
+ */\r
+void do_cmd_study(void)\r
+{\r
+ int i;\r
+ OBJECT_IDX item;\r
+ OBJECT_SUBTYPE_VALUE sval;\r
+ int increment = 0;\r
+ bool learned = FALSE;\r
+\r
+ /* Spells of realm2 will have an increment of +32 */\r
+ SPELL_IDX spell = -1;\r
+\r
+ concptr p = spell_category_name(mp_ptr->spell_book);\r
+\r
+ object_type *o_ptr;\r
+\r
+ concptr q, s;\r
+\r
+ if (!p_ptr->realm1)\r
+ {\r
+ msg_print(_("本を読むことができない!", "You cannot read books!"));\r
+ return;\r
+ }\r
+\r
+ if (p_ptr->blind || no_lite())\r
+ {\r
+ msg_print(_("目が見えない!", "You cannot see!"));\r
+ return;\r
+ }\r
+\r
+ if (p_ptr->confused)\r
+ {\r
+ msg_print(_("混乱していて読めない!", "You are too confused!"));\r
+ return;\r
+ }\r
+\r
+ if (!(p_ptr->new_spells))\r
+ {\r
+ msg_format(_("新しい%sを覚えることはできない!", "You cannot learn any new %ss!"), p);\r
+ return;\r
+ }\r
+\r
+ if (p_ptr->special_defense & KATA_MUSOU)\r
+ {\r
+ set_action(ACTION_NONE);\r
+ }\r
+\r
+#ifdef JP\r
+ if (p_ptr->new_spells < 10) {\r
+ msg_format("あと %d つの%sを学べる。", p_ptr->new_spells, p);\r
+ }\r
+ else {\r
+ msg_format("あと %d 個の%sを学べる。", p_ptr->new_spells, p);\r
+ }\r
+#else\r
+ msg_format("You can learn %d new %s%s.", p_ptr->new_spells, p,\r
+ (p_ptr->new_spells == 1 ? "" : "s"));\r
+#endif\r
+\r
+ msg_print(NULL);\r
+\r
+\r
+ /* Restrict choices to "useful" books */\r
+ if (p_ptr->realm2 == REALM_NONE) item_tester_tval = mp_ptr->spell_book;\r
+ else item_tester_hook = item_tester_learn_spell;\r
+\r
+ q = _("どの本から学びますか? ", "Study which book? ");\r
+ s = _("読める本がない。", "You have no books that you can read.");\r
+\r
+ o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR));\r
+ if (!o_ptr) return;\r
+\r
+ /* Access the item's sval */\r
+ sval = o_ptr->sval;\r
+\r
+ if (o_ptr->tval == REALM2_BOOK) increment = 32;\r
+ else if (o_ptr->tval != REALM1_BOOK)\r
+ {\r
+ if (!get_check(_("本当に魔法の領域を変更しますか?", "Really, change magic realm? "))) return;\r
+ change_realm2(tval2realm(o_ptr->tval));\r
+ increment = 32;\r
+ }\r
+\r
+ /* Track the object kind */\r
+ object_kind_track(o_ptr->k_idx);\r
+ handle_stuff();\r
+\r
+ /* Mage -- Learn a selected spell */\r
+ if (mp_ptr->spell_book != TV_LIFE_BOOK)\r
+ {\r
+ /* Ask for a spell, allow cancel */\r
+ if (!get_spell(&spell, _("学ぶ", "study"), sval, FALSE, o_ptr->tval - TV_LIFE_BOOK + 1) && (spell == -1)) return;\r
+ }\r
+\r
+ /* Priest -- Learn a random prayer */\r
+ else\r
+ {\r
+ int k = 0;\r
+ int gift = -1;\r
+\r
+ /* Extract spells */\r
+ for (spell = 0; spell < 32; spell++)\r
+ {\r
+ /* Check spells in the book */\r
+ if ((fake_spell_flags[sval] & (1L << spell)))\r
+ {\r
+ /* Skip non "okay" prayers */\r
+ if (!spell_okay(spell, FALSE, TRUE,\r
+ (increment ? p_ptr->realm2 : p_ptr->realm1))) continue;\r
+\r
+ /* Hack -- Prepare the randomizer */\r
+ k++;\r
+\r
+ /* Hack -- Apply the randomizer */\r
+ if (one_in_(k)) gift = spell;\r
+ }\r
+ }\r
+\r
+ /* Accept gift */\r
+ spell = gift;\r
+ }\r
+\r
+ /* Nothing to study */\r
+ if (spell < 0)\r
+ {\r
+ msg_format(_("その本には学ぶべき%sがない。", "You cannot learn any %ss in that book."), p);\r
+\r
+ /* Abort */\r
+ return;\r
+ }\r
+\r
+ if (increment) spell += increment;\r
+\r
+ /* Learn the spell */\r
+ if (spell < 32)\r
+ {\r
+ if (p_ptr->spell_learned1 & (1L << spell)) learned = TRUE;\r
+ else p_ptr->spell_learned1 |= (1L << spell);\r
+ }\r
+ else\r
+ {\r
+ if (p_ptr->spell_learned2 & (1L << (spell - 32))) learned = TRUE;\r
+ else p_ptr->spell_learned2 |= (1L << (spell - 32));\r
+ }\r
+\r
+ if (learned)\r
+ {\r
+ int max_exp = (spell < 32) ? SPELL_EXP_MASTER : SPELL_EXP_EXPERT;\r
+ int old_exp = p_ptr->spell_exp[spell];\r
+ int new_rank = EXP_LEVEL_UNSKILLED;\r
+ concptr name = do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME);\r
+\r
+ if (old_exp >= max_exp)\r
+ {\r
+ msg_format(_("その%sは完全に使いこなせるので学ぶ必要はない。", "You don't need to study this %s anymore."), p);\r
+ return;\r
+ }\r
+#ifdef JP\r
+ if (!get_check(format("%sの%sをさらに学びます。よろしいですか?", name, p)))\r
+#else\r
+ if (!get_check(format("You will study a %s of %s again. Are you sure? ", p, name)))\r
+#endif\r
+ {\r
+ return;\r
+ }\r
+ else if (old_exp >= SPELL_EXP_EXPERT)\r
+ {\r
+ p_ptr->spell_exp[spell] = SPELL_EXP_MASTER;\r
+ new_rank = EXP_LEVEL_MASTER;\r
+ }\r
+ else if (old_exp >= SPELL_EXP_SKILLED)\r
+ {\r
+ if (spell >= 32) p_ptr->spell_exp[spell] = SPELL_EXP_EXPERT;\r
+ else p_ptr->spell_exp[spell] += SPELL_EXP_EXPERT - SPELL_EXP_SKILLED;\r
+ new_rank = EXP_LEVEL_EXPERT;\r
+ }\r
+ else if (old_exp >= SPELL_EXP_BEGINNER)\r
+ {\r
+ p_ptr->spell_exp[spell] = SPELL_EXP_SKILLED + (old_exp - SPELL_EXP_BEGINNER) * 2 / 3;\r
+ new_rank = EXP_LEVEL_SKILLED;\r
+ }\r
+ else\r
+ {\r
+ p_ptr->spell_exp[spell] = SPELL_EXP_BEGINNER + old_exp / 3;\r
+ new_rank = EXP_LEVEL_BEGINNER;\r
+ }\r
+ msg_format(_("%sの熟練度が%sに上がった。", "Your proficiency of %s is now %s rank."), name, exp_level_str[new_rank]);\r
+ }\r
+ else\r
+ {\r
+ /* Find the next open entry in "p_ptr->spell_order[]" */\r
+ for (i = 0; i < 64; i++)\r
+ {\r
+ /* Stop at the first empty space */\r
+ if (p_ptr->spell_order[i] == 99) break;\r
+ }\r
+\r
+ /* Add the spell to the known list */\r
+ p_ptr->spell_order[i++] = spell;\r
+\r
+ /* Mention the result */\r
+#ifdef JP\r
+ /* 英日切り替え機能に対応 */\r
+ if (mp_ptr->spell_book == TV_MUSIC_BOOK)\r
+ {\r
+ msg_format("%sを学んだ。",\r
+ do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME));\r
+ }\r
+ else\r
+ {\r
+ msg_format("%sの%sを学んだ。",\r
+ do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME), p);\r
+ }\r
+#else\r
+ msg_format("You have learned the %s of %s.",\r
+ p, do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME));\r
+#endif\r
+ }\r
+\r
+ p_ptr->energy_use = 100;\r
+\r
+ switch (mp_ptr->spell_book)\r
+ {\r
+ case TV_LIFE_BOOK:\r
+ chg_virtue(V_FAITH, 1);\r
+ break;\r
+ case TV_DEATH_BOOK:\r
+ chg_virtue(V_UNLIFE, 1);\r
+ break;\r
+ case TV_NATURE_BOOK:\r
+ chg_virtue(V_NATURE, 1);\r
+ break;\r
+ default:\r
+ chg_virtue(V_KNOWLEDGE, 1);\r
+ break;\r
+ }\r
+\r
+ sound(SOUND_STUDY);\r
+\r
+ /* One less spell available */\r
+ p_ptr->learned_spells++;\r
+\r
+ /* Update Study */\r
+ p_ptr->update |= (PU_SPELLS);\r
+ update_creature(p_ptr);\r
+\r
+ /* Redraw object recall */\r
+ p_ptr->window |= (PW_OBJECT);\r
+}\r
+\r
+\r
+/*!\r
+ * @brief 魔法を詠唱するコマンドのメインルーチン /\r
+ * Cast a spell\r
+ * @return なし\r
+ */\r
+void do_cmd_cast(void)\r
+{\r
+ OBJECT_IDX item;\r
+ OBJECT_SUBTYPE_VALUE sval;\r
+ SPELL_IDX spell;\r
+ REALM_IDX realm;\r
+ int chance;\r
+ int increment = 0;\r
+ REALM_IDX use_realm;\r
+ MANA_POINT need_mana;\r
+\r
+ concptr prayer;\r
+ object_type *o_ptr;\r
+ const magic_type *s_ptr;\r
+ concptr q, s;\r
+\r
+ bool over_exerted = FALSE;\r
+\r
+ /* Require spell ability */\r
+ if (!p_ptr->realm1 && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE))\r
+ {\r
+ msg_print(_("呪文を唱えられない!", "You cannot cast spells!"));\r
+ return;\r
+ }\r
+\r
+ /* Require lite */\r
+ if (p_ptr->blind || no_lite())\r
+ {\r
+ if (p_ptr->pclass == CLASS_FORCETRAINER) confirm_use_force(FALSE);\r
+ else\r
+ {\r
+ msg_print(_("目が見えない!", "You cannot see!"));\r
+ flush();\r
+ }\r
+ return;\r
+ }\r
+\r
+ /* Not when confused */\r
+ if (p_ptr->confused)\r
+ {\r
+ msg_print(_("混乱していて唱えられない!", "You are too confused!"));\r
+ flush();\r
+ return;\r
+ }\r
+\r
+ /* Hex */\r
+ if (p_ptr->realm1 == REALM_HEX)\r
+ {\r
+ if (hex_spell_fully())\r
+ {\r
+ bool flag = FALSE;\r
+ msg_print(_("これ以上新しい呪文を詠唱することはできない。", "Can not spell new spells more."));\r
+ flush();\r
+ if (p_ptr->lev >= 35) flag = stop_hex_spell();\r
+ if (!flag) return;\r
+ }\r
+ }\r
+\r
+ if (p_ptr->pclass == CLASS_FORCETRAINER)\r
+ {\r
+ if (player_has_no_spellbooks())\r
+ {\r
+ confirm_use_force(FALSE);\r
+ return;\r
+ }\r
+ }\r
+\r
+ prayer = spell_category_name(mp_ptr->spell_book);\r
+\r
+ /* Restrict choices to spell books */\r
+ item_tester_tval = mp_ptr->spell_book;\r
+\r
+ q = _("どの呪文書を使いますか? ", "Use which book? ");\r
+ s = _("呪文書がない!", "You have no spell books!");\r
+\r
+ o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR | (p_ptr->pclass == CLASS_FORCETRAINER ? USE_FORCE : 0)));\r
+ if (!o_ptr)\r
+ {\r
+ if (item == INVEN_FORCE) /* the_force */\r
+ {\r
+ do_cmd_mind();\r
+ return;\r
+ }\r
+ return;\r
+ }\r
+\r
+ /* Access the item's sval */\r
+ sval = o_ptr->sval;\r
+\r
+ if ((p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE) && (o_ptr->tval == REALM2_BOOK)) increment = 32;\r
+\r
+ /* Track the object kind */\r
+ object_kind_track(o_ptr->k_idx);\r
+ handle_stuff();\r
+\r
+ if ((p_ptr->pclass == CLASS_SORCERER) || (p_ptr->pclass == CLASS_RED_MAGE))\r
+ realm = o_ptr->tval - TV_LIFE_BOOK + 1;\r
+ else if (increment) realm = p_ptr->realm2;\r
+ else realm = p_ptr->realm1;\r
+\r
+ /* Ask for a spell */\r
+#ifdef JP\r
+ if (!get_spell(&spell, ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "詠唱する" : (mp_ptr->spell_book == TV_MUSIC_BOOK) ? "歌う" : "唱える"),\r
+ sval, TRUE, realm))\r
+ {\r
+ if (spell == -2) msg_format("その本には知っている%sがない。", prayer);\r
+ return;\r
+ }\r
+#else\r
+ if (!get_spell(&spell, ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "recite" : "cast"),\r
+ sval, TRUE, realm))\r
+ {\r
+ if (spell == -2)\r
+ msg_format("You don't know any %ss in that book.", prayer);\r
+ return;\r
+ }\r
+#endif\r
+\r
+\r
+ use_realm = tval2realm(o_ptr->tval);\r
+\r
+ /* Hex */\r
+ if (use_realm == REALM_HEX)\r
+ {\r
+ if (hex_spelling(spell))\r
+ {\r
+ msg_print(_("その呪文はすでに詠唱中だ。", "You are already casting it."));\r
+ return;\r
+ }\r
+ }\r
+\r
+ if (!is_magic(use_realm))\r
+ {\r
+ s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell];\r
+ }\r
+ else\r
+ {\r
+ s_ptr = &mp_ptr->info[realm - 1][spell];\r
+ }\r
+\r
+ /* Extract mana consumption rate */\r
+ need_mana = mod_need_mana(s_ptr->smana, spell, realm);\r
+\r
+ /* Verify "dangerous" spells */\r
+ if (need_mana > p_ptr->csp)\r
+ {\r
+ if (flush_failure) flush();\r
+\r
+ /* Warning */\r
+#ifdef JP\r
+ msg_format("その%sを%sのに十分なマジックポイントがない。", prayer,\r
+ ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "詠唱する" : (mp_ptr->spell_book == TV_LIFE_BOOK) ? "歌う" : "唱える"));\r
+#else\r
+ msg_format("You do not have enough mana to %s this %s.",\r
+ ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "recite" : "cast"),\r
+ prayer);\r
+#endif\r
+\r
+\r
+ if (!over_exert) return;\r
+\r
+ /* Verify */\r
+ if (!get_check_strict(_("それでも挑戦しますか? ", "Attempt it anyway? "), CHECK_OKAY_CANCEL)) return;\r
+ }\r
+\r
+ /* Spell failure chance */\r
+ chance = spell_chance(spell, use_realm);\r
+\r
+ /* Sufficient mana */\r
+ if (need_mana <= p_ptr->csp)\r
+ {\r
+ /* Use some mana */\r
+ p_ptr->csp -= need_mana;\r
+ }\r
+ else over_exerted = TRUE;\r
+ p_ptr->redraw |= (PR_MANA);\r
+\r
+ /* Failed spell */\r
+ if (randint0(100) < chance)\r
+ {\r
+ if (flush_failure) flush();\r
+\r
+ msg_format(_("%sをうまく唱えられなかった!", "You failed to get the %s off!"), prayer);\r
+ sound(SOUND_FAIL);\r
+\r
+ switch (realm)\r
+ {\r
+ case REALM_LIFE:\r
+ if (randint1(100) < chance) chg_virtue(V_VITALITY, -1);\r
+ break;\r
+ case REALM_DEATH:\r
+ if (randint1(100) < chance) chg_virtue(V_UNLIFE, -1);\r
+ break;\r
+ case REALM_NATURE:\r
+ if (randint1(100) < chance) chg_virtue(V_NATURE, -1);\r
+ break;\r
+ case REALM_DAEMON:\r
+ if (randint1(100) < chance) chg_virtue(V_JUSTICE, 1);\r
+ break;\r
+ case REALM_CRUSADE:\r
+ if (randint1(100) < chance) chg_virtue(V_JUSTICE, -1);\r
+ break;\r
+ case REALM_HEX:\r
+ if (randint1(100) < chance) chg_virtue(V_COMPASSION, -1);\r
+ break;\r
+ default:\r
+ if (randint1(100) < chance) chg_virtue(V_KNOWLEDGE, -1);\r
+ break;\r
+ }\r
+\r
+ /* Failure casting may activate some side effect */\r
+ do_spell(realm, spell, SPELL_FAIL);\r
+\r
+\r
+ if ((o_ptr->tval == TV_CHAOS_BOOK) && (randint1(100) < spell))\r
+ {\r
+ msg_print(_("カオス的な効果を発生した!", "You produce a chaotic effect!"));\r
+ wild_magic(spell);\r
+ }\r
+ else if ((o_ptr->tval == TV_DEATH_BOOK) && (randint1(100) < spell))\r
+ {\r
+ if ((sval == 3) && one_in_(2))\r
+ {\r
+ sanity_blast(0, TRUE);\r
+ }\r
+ else\r
+ {\r
+ msg_print(_("痛い!", "It hurts!"));\r
+ take_hit(DAMAGE_LOSELIFE, damroll(o_ptr->sval + 1, 6), _("暗黒魔法の逆流", "a miscast Death spell"), -1);\r
+\r
+ if ((spell > 15) && one_in_(6) && !p_ptr->hold_exp)\r
+ lose_exp(spell * 250);\r
+ }\r
+ }\r
+ else if ((o_ptr->tval == TV_MUSIC_BOOK) && (randint1(200) < spell))\r
+ {\r
+ msg_print(_("いやな音が響いた", "An infernal sound echoed."));\r
+ aggravate_monsters(0);\r
+ }\r
+ if (randint1(100) >= chance)\r
+ chg_virtue(V_CHANCE, -1);\r
+ }\r
+\r
+ /* Process spell */\r
+ else\r
+ {\r
+ /* Canceled spells cost neither a turn nor mana */\r
+ if (!do_spell(realm, spell, SPELL_CAST)) return;\r
+\r
+ if (randint1(100) < chance)\r
+ chg_virtue(V_CHANCE, 1);\r
+\r
+ /* A spell was cast */\r
+ if (!(increment ?\r
+ (p_ptr->spell_worked2 & (1L << spell)) :\r
+ (p_ptr->spell_worked1 & (1L << spell)))\r
+ && (p_ptr->pclass != CLASS_SORCERER)\r
+ && (p_ptr->pclass != CLASS_RED_MAGE))\r
+ {\r
+ int e = s_ptr->sexp;\r
+\r
+ /* The spell worked */\r
+ if (realm == p_ptr->realm1)\r
+ {\r
+ p_ptr->spell_worked1 |= (1L << spell);\r
+ }\r
+ else\r
+ {\r
+ p_ptr->spell_worked2 |= (1L << spell);\r
+ }\r
+\r
+ /* Gain experience */\r
+ gain_exp(e * s_ptr->slevel);\r
+\r
+ /* Redraw object recall */\r
+ p_ptr->window |= (PW_OBJECT);\r
+\r
+ switch (realm)\r
+ {\r
+ case REALM_LIFE:\r
+ chg_virtue(V_TEMPERANCE, 1);\r
+ chg_virtue(V_COMPASSION, 1);\r
+ chg_virtue(V_VITALITY, 1);\r
+ chg_virtue(V_DILIGENCE, 1);\r
+ break;\r
+ case REALM_DEATH:\r
+ chg_virtue(V_UNLIFE, 1);\r
+ chg_virtue(V_JUSTICE, -1);\r
+ chg_virtue(V_FAITH, -1);\r
+ chg_virtue(V_VITALITY, -1);\r
+ break;\r
+ case REALM_DAEMON:\r
+ chg_virtue(V_JUSTICE, -1);\r
+ chg_virtue(V_FAITH, -1);\r
+ chg_virtue(V_HONOUR, -1);\r
+ chg_virtue(V_TEMPERANCE, -1);\r
+ break;\r
+ case REALM_CRUSADE:\r
+ chg_virtue(V_FAITH, 1);\r
+ chg_virtue(V_JUSTICE, 1);\r
+ chg_virtue(V_SACRIFICE, 1);\r
+ chg_virtue(V_HONOUR, 1);\r
+ break;\r
+ case REALM_NATURE:\r
+ chg_virtue(V_NATURE, 1);\r
+ chg_virtue(V_HARMONY, 1);\r
+ break;\r
+ case REALM_HEX:\r
+ chg_virtue(V_JUSTICE, -1);\r
+ chg_virtue(V_FAITH, -1);\r
+ chg_virtue(V_HONOUR, -1);\r
+ chg_virtue(V_COMPASSION, -1);\r
+ break;\r
+ default:\r
+ chg_virtue(V_KNOWLEDGE, 1);\r
+ break;\r
+ }\r
+ }\r
+ switch (realm)\r
+ {\r
+ case REALM_LIFE:\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_TEMPERANCE, 1);\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_COMPASSION, 1);\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_VITALITY, 1);\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_DILIGENCE, 1);\r
+ break;\r
+ case REALM_DEATH:\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_UNLIFE, 1);\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1);\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_VITALITY, -1);\r
+ break;\r
+ case REALM_DAEMON:\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1);\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, -1);\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_TEMPERANCE, -1);\r
+ break;\r
+ case REALM_CRUSADE:\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, 1);\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, 1);\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_SACRIFICE, 1);\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, 1);\r
+ break;\r
+ case REALM_NATURE:\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_NATURE, 1);\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HARMONY, 1);\r
+ break;\r
+ case REALM_HEX:\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1);\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, -1);\r
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_COMPASSION, -1);\r
+ break;\r
+ }\r
+ if (mp_ptr->spell_xtra & MAGIC_GAIN_EXP)\r
+ {\r
+ s16b cur_exp = p_ptr->spell_exp[(increment ? 32 : 0) + spell];\r
+ s16b exp_gain = 0;\r
+\r
+ if (cur_exp < SPELL_EXP_BEGINNER)\r
+ exp_gain += 60;\r
+ else if (cur_exp < SPELL_EXP_SKILLED)\r
+ {\r
+ if ((dun_level > 4) && ((dun_level + 10) > p_ptr->lev))\r
+ exp_gain = 8;\r
+ }\r
+ else if (cur_exp < SPELL_EXP_EXPERT)\r
+ {\r
+ if (((dun_level + 5) > p_ptr->lev) && ((dun_level + 5) > s_ptr->slevel))\r
+ exp_gain = 2;\r
+ }\r
+ else if ((cur_exp < SPELL_EXP_MASTER) && !increment)\r
+ {\r
+ if (((dun_level + 5) > p_ptr->lev) && (dun_level > s_ptr->slevel))\r
+ exp_gain = 1;\r
+ }\r
+ p_ptr->spell_exp[(increment ? 32 : 0) + spell] += exp_gain;\r
+ }\r
+ }\r
+\r
+ p_ptr->energy_use = 100;\r
+\r
+\r
+ /* Over-exert the player */\r
+ if (over_exerted)\r
+ {\r
+ int oops = need_mana;\r
+\r
+ /* No mana left */\r
+ p_ptr->csp = 0;\r
+ p_ptr->csp_frac = 0;\r
+\r
+ msg_print(_("精神を集中しすぎて気を失ってしまった!", "You faint from the effort!"));\r
+\r
+ /* Hack -- Bypass free action */\r
+ (void)set_paralyzed(p_ptr->paralyzed + randint1(5 * oops + 1));\r
+\r
+ switch (realm)\r
+ {\r
+ case REALM_LIFE:\r
+ chg_virtue(V_VITALITY, -10);\r
+ break;\r
+ case REALM_DEATH:\r
+ chg_virtue(V_UNLIFE, -10);\r
+ break;\r
+ case REALM_DAEMON:\r
+ chg_virtue(V_JUSTICE, 10);\r
+ break;\r
+ case REALM_NATURE:\r
+ chg_virtue(V_NATURE, -10);\r
+ break;\r
+ case REALM_CRUSADE:\r
+ chg_virtue(V_JUSTICE, -10);\r
+ break;\r
+ case REALM_HEX:\r
+ chg_virtue(V_COMPASSION, 10);\r
+ break;\r
+ default:\r
+ chg_virtue(V_KNOWLEDGE, -10);\r
+ break;\r
+ }\r
+\r
+ /* Damage CON (possibly permanently) */\r
+ if (randint0(100) < 50)\r
+ {\r
+ bool perm = (randint0(100) < 25);\r
+\r
+ msg_print(_("体を悪くしてしまった!", "You have damaged your health!"));\r
+\r
+ /* Reduce constitution */\r
+ (void)dec_stat(A_CON, 15 + randint1(10), perm);\r
+ }\r
+ }\r
+\r
+ p_ptr->window |= (PW_PLAYER);\r
+ p_ptr->window |= (PW_SPELL);\r
+}\r
extern concptr info_radius(POSITION rad);\r
extern concptr info_weight(WEIGHT weight);\r
\r
+/* cmd5.c */\r
+extern void do_cmd_browse(void);\r
+extern void do_cmd_study(void);\r
+extern void do_cmd_cast(void);\r
+++ /dev/null
-/*!
- * @file cmd5.c
- * @brief プレイヤーの魔法に関するコマンドの実装 / Spell/Prayer commands
- * @date 2014/01/02
- * @author
- * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
- *
- * This software may be copied and distributed for educational, research,
- * and not for profit purposes provided that this copyright and statement
- * are included in all such copies. Other copyrights may also apply.
- */
-
-
-#include "angband.h"
-#include "avatar.h"
-#include "player-status.h"
-#include "object-hook.h"
-
-/*!
- * @brief 領域魔法に応じて技能の名称を返す。
- * @param tval 魔法書のtval
- * @return 領域魔法の技能名称を保管した文字列ポインタ
- */
-concptr spell_category_name(OBJECT_TYPE_VALUE tval)
-{
- switch (tval)
- {
- case TV_HISSATSU_BOOK:
- return _("必殺技", "art");
- case TV_LIFE_BOOK:
- return _("祈り", "prayer");
- case TV_MUSIC_BOOK:
- return _("歌", "song");
- default:
- return _("呪文", "spell");
- }
-}
-
-/*!
- * @brief 領域魔法の閲覧、学習、使用選択するインターフェイス処理
- * Allow user to choose a spell/prayer from the given book.
- * @param sn 選択した魔法IDを返す参照ポインタ
- * @param prompt 魔法を利用する際の動詞表記
- * @param sval 魔道書のsval
- * @param learned 閲覧/使用選択ならばTRUE、学習処理ならFALSE
- * @param use_realm 魔法領域ID
- * @return
- * <pre>
- * If a valid spell is chosen, saves it in '*sn' and returns TRUE
- * If the user hits escape, returns FALSE, and set '*sn' to -1
- * If there are no legal choices, returns FALSE, and sets '*sn' to -2
- * The "prompt" should be "cast", "recite", or "study"
- * The "known" should be TRUE for cast/pray, FALSE for study
- * </pre>
- */
-static int get_spell(SPELL_IDX *sn, concptr prompt, OBJECT_SUBTYPE_VALUE sval, bool learned, REALM_IDX use_realm)
-{
- int i;
- SPELL_IDX spell = -1;
- int num = 0;
- int ask = TRUE;
- MANA_POINT need_mana;
- SPELL_IDX spells[64];
- bool flag, redraw, okay;
- char choice;
- const magic_type *s_ptr;
- char out_val[160];
- concptr p;
- COMMAND_CODE code;
-#ifdef JP
- char jverb_buf[128];
-#endif
- int menu_line = (use_menu ? 1 : 0);
-
- /* Get the spell, if available */
- if (repeat_pull(&code))
- {
- *sn = (SPELL_IDX)code;
- /* Verify the spell */
- if (spell_okay(*sn, learned, FALSE, use_realm))
- {
- /* Success */
- return (TRUE);
- }
- }
-
- p = spell_category_name(mp_ptr->spell_book);
-
- /* Extract spells */
- for (spell = 0; spell < 32; spell++)
- {
- /* Check for this spell */
- if ((fake_spell_flags[sval] & (1L << spell)))
- {
- /* Collect this spell */
- spells[num++] = spell;
- }
- }
-
- /* Assume no usable spells */
- okay = FALSE;
-
- /* Assume no spells available */
- (*sn) = -2;
-
- /* Check for "okay" spells */
- for (i = 0; i < num; i++)
- {
- /* Look for "okay" spells */
- if (spell_okay(spells[i], learned, FALSE, use_realm)) okay = TRUE;
- }
-
- /* No "okay" spells */
- if (!okay) return (FALSE);
- if (((use_realm) != p_ptr->realm1) && ((use_realm) != p_ptr->realm2) && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE)) return FALSE;
- if (((p_ptr->pclass == CLASS_SORCERER) || (p_ptr->pclass == CLASS_RED_MAGE)) && !is_magic(use_realm)) return FALSE;
- if ((p_ptr->pclass == CLASS_RED_MAGE) && ((use_realm) != REALM_ARCANE) && (sval > 1)) return FALSE;
-
- /* Assume cancelled */
- *sn = (-1);
-
- /* Nothing chosen yet */
- flag = FALSE;
-
- /* No redraw yet */
- redraw = FALSE;
-
- p_ptr->window |= (PW_SPELL);
- handle_stuff();
-
- /* Build a prompt (accept all spells) */
-#ifdef JP
- jverb( prompt, jverb_buf, JVERB_AND );
- (void) strnfmt(out_val, 78, "(%^s:%c-%c, '*'で一覧, ESCで中断) どの%sを%^sますか? ",
- p, I2A(0), I2A(num - 1), p, jverb_buf );
-#else
- (void)strnfmt(out_val, 78, "(%^ss %c-%c, *=List, ESC=exit) %^s which %s? ",
- p, I2A(0), I2A(num - 1), prompt, p);
-#endif
-
- /* Get a spell from the user */
-
- 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':
- {
- 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;
- /* Display a list of spells */
- print_spells(menu_line, spells, num, 1, 15, use_realm);
- if (ask) continue;
- }
- else
- {
- /* Request redraw */
- if ((choice == ' ') || (choice == '*') || (choice == '?'))
- {
- /* Show the list */
- if (!redraw)
- {
- /* Show list */
- redraw = TRUE;
- screen_save();
-
- /* Display a list of spells */
- print_spells(menu_line, spells, num, 1, 15, use_realm);
- }
-
- /* Hide the list */
- else
- {
- if (use_menu) continue;
-
- /* Hide list */
- redraw = FALSE;
- screen_load();
- }
-
- /* Redo asking */
- continue;
- }
-
-
- /* Note verify */
- ask = (isupper(choice));
-
- /* Lowercase */
- if (ask) choice = (char)tolower(choice);
-
- /* Extract request */
- i = (islower(choice) ? A2I(choice) : -1);
- }
-
- /* Totally Illegal */
- if ((i < 0) || (i >= num))
- {
- bell();
- continue;
- }
-
- /* Save the spell index */
- spell = spells[i];
-
- /* Require "okay" spells */
- if (!spell_okay(spell, learned, FALSE, use_realm))
- {
- bell();
-#ifdef JP
- msg_format("その%sを%sことはできません。", p, prompt);
-#else
- msg_format("You may not %s that %s.", prompt, p);
-#endif
-
- continue;
- }
-
- /* Verify it */
- if (ask)
- {
- char tmp_val[160];
-
- /* Access the spell */
- if (!is_magic(use_realm))
- {
- s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell];
- }
- else
- {
- s_ptr = &mp_ptr->info[use_realm - 1][spell];
- }
-
- /* Extract mana consumption rate */
- if (use_realm == REALM_HISSATSU)
- {
- need_mana = s_ptr->smana;
- }
- else
- {
- need_mana = mod_need_mana(s_ptr->smana, spell, use_realm);
- }
-
- /* Prompt */
-#ifdef JP
- jverb( prompt, jverb_buf, JVERB_AND );
- /* 英日切り替え機能に対応 */
- (void) strnfmt(tmp_val, 78, "%s(MP%d, 失敗率%d%%)を%sますか? ",
- do_spell(use_realm, spell, SPELL_NAME), need_mana,
- spell_chance(spell, use_realm),jverb_buf);
-#else
- (void)strnfmt(tmp_val, 78, "%^s %s (%d mana, %d%% fail)? ",
- prompt, do_spell(use_realm, spell, SPELL_NAME), need_mana,
- spell_chance(spell, use_realm));
-#endif
-
-
- /* Belay that order */
- if (!get_check(tmp_val)) continue;
- }
-
- /* Stop the loop */
- flag = TRUE;
- }
-
- if (redraw) screen_load();
-
- p_ptr->window |= (PW_SPELL);
- handle_stuff();
-
- /* Abort if needed */
- if (!flag) return FALSE;
-
- /* Save the choice */
- (*sn) = spell;
-
- repeat_push((COMMAND_CODE)spell);
-
- /* Success */
- return TRUE;
-}
-
-/*!
- * @brief プレイヤーの職業が練気術師の時、領域魔法と練気術を切り換える処理のインターフェイス
- * @param browse_only 魔法と技能の閲覧を行うならばTRUE
- * @return 魔道書を一冊も持っていないならTRUEを返す
- */
-static void confirm_use_force(bool browse_only)
-{
- char which;
- COMMAND_CODE code;
-
- /* Get the item index */
- if (repeat_pull(&code) && (code == INVEN_FORCE))
- {
- browse_only ? do_cmd_mind_browse() : do_cmd_mind();
- return;
- }
-
- /* Show the prompt */
- prt(_("('w'練気術, ESC) 'w'かESCを押してください。 ", "(w for the Force, ESC) Hit 'w' or ESC. "), 0, 0);
-
- while (1)
- {
- /* Get a key */
- which = inkey();
-
- if (which == ESCAPE) break;
- else if (which == 'w')
- {
- repeat_push(INVEN_FORCE);
- break;
- }
- }
-
- /* Clear the prompt line */
- prt("", 0, 0);
-
- if (which == 'w')
- {
- browse_only ? do_cmd_mind_browse() : do_cmd_mind();
- }
-}
-
-
-/*!
- * @brief プレイヤーの魔法と技能を閲覧するコマンドのメインルーチン /
- * Peruse the spells/prayers in a book
- * @return なし
- * @details
- * <pre>
- * Note that *all* spells in the book are listed
- *
- * Note that browsing is allowed while confused or blind,
- * and in the dark, primarily to allow browsing in stores.
- * </pre>
- */
-void do_cmd_browse(void)
-{
- OBJECT_IDX item;
- OBJECT_SUBTYPE_VALUE sval;
- REALM_IDX use_realm = 0;
- int j, line;
- SPELL_IDX spell = -1;
- int num = 0;
-
- SPELL_IDX spells[64];
- char temp[62*4];
-
- object_type *o_ptr;
-
- concptr q, s;
-
- /* Warriors are illiterate */
- if (!(p_ptr->realm1 || p_ptr->realm2) && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE))
- {
- msg_print(_("本を読むことができない!", "You cannot read books!"));
- return;
- }
-
- if (p_ptr->special_defense & KATA_MUSOU)
- {
- set_action(ACTION_NONE);
- }
-
- if (p_ptr->pclass == CLASS_FORCETRAINER)
- {
- if (player_has_no_spellbooks())
- {
- confirm_use_force(TRUE);
- return;
- }
- }
-
- /* Restrict choices to "useful" books */
- if (p_ptr->realm2 == REALM_NONE) item_tester_tval = mp_ptr->spell_book;
- else item_tester_hook = item_tester_learn_spell;
-
- q = _("どの本を読みますか? ", "Browse which book? ");
- s = _("読める本がない。", "You have no books that you can read.");
-
- o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR | (p_ptr->pclass == CLASS_FORCETRAINER ? USE_FORCE : 0)));
- if (!o_ptr)
- {
- if (item == INVEN_FORCE) /* the_force */
- {
- do_cmd_mind_browse();
- return;
- }
- return;
- }
-
- /* Access the item's sval */
- sval = o_ptr->sval;
-
- use_realm = tval2realm(o_ptr->tval);
-
- /* Track the object kind */
- object_kind_track(o_ptr->k_idx);
- handle_stuff();
-
- /* Extract spells */
- for (spell = 0; spell < 32; spell++)
- {
- /* Check for this spell */
- if ((fake_spell_flags[sval] & (1L << spell)))
- {
- /* Collect this spell */
- spells[num++] = spell;
- }
- }
-
- screen_save();
- prt("", 0, 0);
-
- /* Keep browsing spells. Exit browsing on cancel. */
- while(TRUE)
- {
- /* Ask for a spell, allow cancel */
- if (!get_spell(&spell, _("読む", "browse"), o_ptr->sval, TRUE, use_realm))
- {
- /* If cancelled, leave immediately. */
- if (spell == -1) break;
-
- /* Display a list of spells */
- print_spells(0, spells, num, 1, 15, use_realm);
-
- /* Notify that there's nothing to see, and wait. */
- if (use_realm == REALM_HISSATSU)
- prt(_("読める技がない。", "No techniques to browse."), 0, 0);
- else
- prt(_("読める呪文がない。", "No spells to browse."), 0, 0);
- (void)inkey();
-
- screen_load();
-
- return;
- }
-
- /* Clear lines, position cursor (really should use strlen here) */
- Term_erase(14, 14, 255);
- Term_erase(14, 13, 255);
- Term_erase(14, 12, 255);
- Term_erase(14, 11, 255);
-
- roff_to_buf(do_spell(use_realm, spell, SPELL_DESC), 62, temp, sizeof(temp));
-
- for (j = 0, line = 11; temp[j]; j += 1 + strlen(&temp[j]))
- {
- prt(&temp[j], line, 15);
- line++;
- }
- }
- screen_load();
-}
-
-/*!
- * @brief プレイヤーの第二魔法領域を変更する /
- * @param next_realm 変更先の魔法領域ID
- * @return なし
- */
-static void change_realm2(CHARACTER_IDX next_realm)
-{
- int i, j = 0;
- char tmp[80];
-
- for (i = 0; i < 64; i++)
- {
- p_ptr->spell_order[j] = p_ptr->spell_order[i];
- if (p_ptr->spell_order[i] < 32) j++;
- }
- for (; j < 64; j++)
- p_ptr->spell_order[j] = 99;
-
- for (i = 32; i < 64; i++)
- {
- p_ptr->spell_exp[i] = SPELL_EXP_UNSKILLED;
- }
- p_ptr->spell_learned2 = 0L;
- p_ptr->spell_worked2 = 0L;
- p_ptr->spell_forgotten2 = 0L;
-
- sprintf(tmp,_("魔法の領域を%sから%sに変更した。", "change magic realm from %s to %s."), realm_names[p_ptr->realm2], realm_names[next_realm]);
- do_cmd_write_nikki(NIKKI_BUNSHOU, 0, tmp);
- p_ptr->old_realm |= 1 << (p_ptr->realm2-1);
- p_ptr->realm2 = next_realm;
-
- p_ptr->update |= (PU_REORDER);
- p_ptr->update |= (PU_SPELLS);
- handle_stuff();
-
- /* Load an autopick preference file */
- autopick_load_pref(FALSE);
-}
-
-
-/*!
- * @brief 魔法を学習するコマンドのメインルーチン /
- * Study a book to gain a new spell/prayer
- * @return なし
- */
-void do_cmd_study(void)
-{
- int i;
- OBJECT_IDX item;
- OBJECT_SUBTYPE_VALUE sval;
- int increment = 0;
- bool learned = FALSE;
-
- /* Spells of realm2 will have an increment of +32 */
- SPELL_IDX spell = -1;
-
- concptr p = spell_category_name(mp_ptr->spell_book);
-
- object_type *o_ptr;
-
- concptr q, s;
-
- if (!p_ptr->realm1)
- {
- msg_print(_("本を読むことができない!", "You cannot read books!"));
- return;
- }
-
- if (p_ptr->blind || no_lite())
- {
- msg_print(_("目が見えない!", "You cannot see!"));
- return;
- }
-
- if (p_ptr->confused)
- {
- msg_print(_("混乱していて読めない!", "You are too confused!"));
- return;
- }
-
- if (!(p_ptr->new_spells))
- {
- msg_format(_("新しい%sを覚えることはできない!", "You cannot learn any new %ss!"), p);
- return;
- }
-
- if (p_ptr->special_defense & KATA_MUSOU)
- {
- set_action(ACTION_NONE);
- }
-
-#ifdef JP
- if( p_ptr->new_spells < 10 ){
- msg_format("あと %d つの%sを学べる。", p_ptr->new_spells, p);
- }else{
- msg_format("あと %d 個の%sを学べる。", p_ptr->new_spells, p);
- }
-#else
- msg_format("You can learn %d new %s%s.", p_ptr->new_spells, p,
- (p_ptr->new_spells == 1?"":"s"));
-#endif
-
- msg_print(NULL);
-
-
- /* Restrict choices to "useful" books */
- if (p_ptr->realm2 == REALM_NONE) item_tester_tval = mp_ptr->spell_book;
- else item_tester_hook = item_tester_learn_spell;
-
- q = _("どの本から学びますか? ", "Study which book? ");
- s = _("読める本がない。", "You have no books that you can read.");
-
- o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR));
- if (!o_ptr) return;
-
- /* Access the item's sval */
- sval = o_ptr->sval;
-
- if (o_ptr->tval == REALM2_BOOK) increment = 32;
- else if (o_ptr->tval != REALM1_BOOK)
- {
- if (!get_check(_("本当に魔法の領域を変更しますか?", "Really, change magic realm? "))) return;
- change_realm2(tval2realm(o_ptr->tval));
- increment = 32;
- }
-
- /* Track the object kind */
- object_kind_track(o_ptr->k_idx);
- handle_stuff();
-
- /* Mage -- Learn a selected spell */
- if (mp_ptr->spell_book != TV_LIFE_BOOK)
- {
- /* Ask for a spell, allow cancel */
- if (!get_spell(&spell, _("学ぶ", "study"), sval, FALSE, o_ptr->tval - TV_LIFE_BOOK + 1) && (spell == -1)) return;
- }
-
- /* Priest -- Learn a random prayer */
- else
- {
- int k = 0;
- int gift = -1;
-
- /* Extract spells */
- for (spell = 0; spell < 32; spell++)
- {
- /* Check spells in the book */
- if ((fake_spell_flags[sval] & (1L << spell)))
- {
- /* Skip non "okay" prayers */
- if (!spell_okay(spell, FALSE, TRUE,
- (increment ? p_ptr->realm2 : p_ptr->realm1))) continue;
-
- /* Hack -- Prepare the randomizer */
- k++;
-
- /* Hack -- Apply the randomizer */
- if (one_in_(k)) gift = spell;
- }
- }
-
- /* Accept gift */
- spell = gift;
- }
-
- /* Nothing to study */
- if (spell < 0)
- {
- msg_format(_("その本には学ぶべき%sがない。", "You cannot learn any %ss in that book."), p);
-
- /* Abort */
- return;
- }
-
- if (increment) spell += increment;
-
- /* Learn the spell */
- if (spell < 32)
- {
- if (p_ptr->spell_learned1 & (1L << spell)) learned = TRUE;
- else p_ptr->spell_learned1 |= (1L << spell);
- }
- else
- {
- if (p_ptr->spell_learned2 & (1L << (spell - 32))) learned = TRUE;
- else p_ptr->spell_learned2 |= (1L << (spell - 32));
- }
-
- if (learned)
- {
- int max_exp = (spell < 32) ? SPELL_EXP_MASTER : SPELL_EXP_EXPERT;
- int old_exp = p_ptr->spell_exp[spell];
- int new_rank = EXP_LEVEL_UNSKILLED;
- concptr name = do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell%32, SPELL_NAME);
-
- if (old_exp >= max_exp)
- {
- msg_format(_("その%sは完全に使いこなせるので学ぶ必要はない。", "You don't need to study this %s anymore."), p);
- return;
- }
-#ifdef JP
- if (!get_check(format("%sの%sをさらに学びます。よろしいですか?", name, p)))
-#else
- if (!get_check(format("You will study a %s of %s again. Are you sure? ", p, name)))
-#endif
- {
- return;
- }
- else if (old_exp >= SPELL_EXP_EXPERT)
- {
- p_ptr->spell_exp[spell] = SPELL_EXP_MASTER;
- new_rank = EXP_LEVEL_MASTER;
- }
- else if (old_exp >= SPELL_EXP_SKILLED)
- {
- if (spell >= 32) p_ptr->spell_exp[spell] = SPELL_EXP_EXPERT;
- else p_ptr->spell_exp[spell] += SPELL_EXP_EXPERT - SPELL_EXP_SKILLED;
- new_rank = EXP_LEVEL_EXPERT;
- }
- else if (old_exp >= SPELL_EXP_BEGINNER)
- {
- p_ptr->spell_exp[spell] = SPELL_EXP_SKILLED + (old_exp - SPELL_EXP_BEGINNER) * 2 / 3;
- new_rank = EXP_LEVEL_SKILLED;
- }
- else
- {
- p_ptr->spell_exp[spell] = SPELL_EXP_BEGINNER + old_exp / 3;
- new_rank = EXP_LEVEL_BEGINNER;
- }
- msg_format(_("%sの熟練度が%sに上がった。", "Your proficiency of %s is now %s rank."), name, exp_level_str[new_rank]);
- }
- else
- {
- /* Find the next open entry in "p_ptr->spell_order[]" */
- for (i = 0; i < 64; i++)
- {
- /* Stop at the first empty space */
- if (p_ptr->spell_order[i] == 99) break;
- }
-
- /* Add the spell to the known list */
- p_ptr->spell_order[i++] = spell;
-
- /* Mention the result */
-#ifdef JP
- /* 英日切り替え機能に対応 */
- if (mp_ptr->spell_book == TV_MUSIC_BOOK)
- {
- msg_format("%sを学んだ。",
- do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME));
- }
- else
- {
- msg_format("%sの%sを学んだ。",
- do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME) ,p);
- }
-#else
- msg_format("You have learned the %s of %s.",
- p, do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME));
-#endif
- }
-
- p_ptr->energy_use = 100;
-
- switch (mp_ptr->spell_book)
- {
- case TV_LIFE_BOOK:
- chg_virtue(V_FAITH, 1);
- break;
- case TV_DEATH_BOOK:
- chg_virtue(V_UNLIFE, 1);
- break;
- case TV_NATURE_BOOK:
- chg_virtue(V_NATURE, 1);
- break;
- default:
- chg_virtue(V_KNOWLEDGE, 1);
- break;
- }
-
- sound(SOUND_STUDY);
-
- /* One less spell available */
- p_ptr->learned_spells++;
-
- /* Update Study */
- p_ptr->update |= (PU_SPELLS);
- update_creature(p_ptr);
-
- /* Redraw object recall */
- p_ptr->window |= (PW_OBJECT);
-}
-
-
-/*!
- * @brief 魔法を詠唱するコマンドのメインルーチン /
- * Cast a spell
- * @return なし
- */
-void do_cmd_cast(void)
-{
- OBJECT_IDX item;
- OBJECT_SUBTYPE_VALUE sval;
- SPELL_IDX spell;
- REALM_IDX realm;
- int chance;
- int increment = 0;
- REALM_IDX use_realm;
- MANA_POINT need_mana;
-
- concptr prayer;
- object_type *o_ptr;
- const magic_type *s_ptr;
- concptr q, s;
-
- bool over_exerted = FALSE;
-
- /* Require spell ability */
- if (!p_ptr->realm1 && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE))
- {
- msg_print(_("呪文を唱えられない!", "You cannot cast spells!"));
- return;
- }
-
- /* Require lite */
- if (p_ptr->blind || no_lite())
- {
- if (p_ptr->pclass == CLASS_FORCETRAINER) confirm_use_force(FALSE);
- else
- {
- msg_print(_("目が見えない!", "You cannot see!"));
- flush();
- }
- return;
- }
-
- /* Not when confused */
- if (p_ptr->confused)
- {
- msg_print(_("混乱していて唱えられない!", "You are too confused!"));
- flush();
- return;
- }
-
- /* Hex */
- if (p_ptr->realm1 == REALM_HEX)
- {
- if (hex_spell_fully())
- {
- bool flag = FALSE;
- msg_print(_("これ以上新しい呪文を詠唱することはできない。", "Can not spell new spells more."));
- flush();
- if (p_ptr->lev >= 35) flag = stop_hex_spell();
- if (!flag) return;
- }
- }
-
- if (p_ptr->pclass == CLASS_FORCETRAINER)
- {
- if (player_has_no_spellbooks())
- {
- confirm_use_force(FALSE);
- return;
- }
- }
-
- prayer = spell_category_name(mp_ptr->spell_book);
-
- /* Restrict choices to spell books */
- item_tester_tval = mp_ptr->spell_book;
-
- q = _("どの呪文書を使いますか? ", "Use which book? ");
- s = _("呪文書がない!", "You have no spell books!");
-
- o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR | (p_ptr->pclass == CLASS_FORCETRAINER ? USE_FORCE : 0)));
- if (!o_ptr)
- {
- if (item == INVEN_FORCE) /* the_force */
- {
- do_cmd_mind();
- return;
- }
- return;
- }
-
- /* Access the item's sval */
- sval = o_ptr->sval;
-
- if ((p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE) && (o_ptr->tval == REALM2_BOOK)) increment = 32;
-
- /* Track the object kind */
- object_kind_track(o_ptr->k_idx);
- handle_stuff();
-
- if ((p_ptr->pclass == CLASS_SORCERER) || (p_ptr->pclass == CLASS_RED_MAGE))
- realm = o_ptr->tval - TV_LIFE_BOOK + 1;
- else if (increment) realm = p_ptr->realm2;
- else realm = p_ptr->realm1;
-
- /* Ask for a spell */
-#ifdef JP
- if (!get_spell(&spell, ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "詠唱する" : (mp_ptr->spell_book == TV_MUSIC_BOOK) ? "歌う" : "唱える"),
- sval, TRUE, realm))
- {
- if (spell == -2) msg_format("その本には知っている%sがない。", prayer);
- return;
- }
-#else
- if (!get_spell(&spell, ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "recite" : "cast"),
- sval, TRUE, realm))
- {
- if (spell == -2)
- msg_format("You don't know any %ss in that book.", prayer);
- return;
- }
-#endif
-
-
- use_realm = tval2realm(o_ptr->tval);
-
- /* Hex */
- if (use_realm == REALM_HEX)
- {
- if (hex_spelling(spell))
- {
- msg_print(_("その呪文はすでに詠唱中だ。", "You are already casting it."));
- return;
- }
- }
-
- if (!is_magic(use_realm))
- {
- s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell];
- }
- else
- {
- s_ptr = &mp_ptr->info[realm - 1][spell];
- }
-
- /* Extract mana consumption rate */
- need_mana = mod_need_mana(s_ptr->smana, spell, realm);
-
- /* Verify "dangerous" spells */
- if (need_mana > p_ptr->csp)
- {
- if (flush_failure) flush();
-
- /* Warning */
-#ifdef JP
- msg_format("その%sを%sのに十分なマジックポイントがない。",prayer,
- ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "詠唱する" : (mp_ptr->spell_book == TV_LIFE_BOOK) ? "歌う" : "唱える"));
-#else
- msg_format("You do not have enough mana to %s this %s.",
- ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "recite" : "cast"),
- prayer);
-#endif
-
-
- if (!over_exert) return;
-
- /* Verify */
- if (!get_check_strict(_("それでも挑戦しますか? ", "Attempt it anyway? "), CHECK_OKAY_CANCEL)) return;
- }
-
- /* Spell failure chance */
- chance = spell_chance(spell, use_realm);
-
- /* Sufficient mana */
- if (need_mana <= p_ptr->csp)
- {
- /* Use some mana */
- p_ptr->csp -= need_mana;
- }
- else over_exerted = TRUE;
- p_ptr->redraw |= (PR_MANA);
-
- /* Failed spell */
- if (randint0(100) < chance)
- {
- if (flush_failure) flush();
-
- msg_format(_("%sをうまく唱えられなかった!", "You failed to get the %s off!"), prayer);
- sound(SOUND_FAIL);
-
- switch (realm)
- {
- case REALM_LIFE:
- if (randint1(100) < chance) chg_virtue(V_VITALITY, -1);
- break;
- case REALM_DEATH:
- if (randint1(100) < chance) chg_virtue(V_UNLIFE, -1);
- break;
- case REALM_NATURE:
- if (randint1(100) < chance) chg_virtue(V_NATURE, -1);
- break;
- case REALM_DAEMON:
- if (randint1(100) < chance) chg_virtue(V_JUSTICE, 1);
- break;
- case REALM_CRUSADE:
- if (randint1(100) < chance) chg_virtue(V_JUSTICE, -1);
- break;
- case REALM_HEX:
- if (randint1(100) < chance) chg_virtue(V_COMPASSION, -1);
- break;
- default:
- if (randint1(100) < chance) chg_virtue(V_KNOWLEDGE, -1);
- break;
- }
-
- /* Failure casting may activate some side effect */
- do_spell(realm, spell, SPELL_FAIL);
-
-
- if ((o_ptr->tval == TV_CHAOS_BOOK) && (randint1(100) < spell))
- {
- msg_print(_("カオス的な効果を発生した!", "You produce a chaotic effect!"));
- wild_magic(spell);
- }
- else if ((o_ptr->tval == TV_DEATH_BOOK) && (randint1(100) < spell))
- {
- if ((sval == 3) && one_in_(2))
- {
- sanity_blast(0, TRUE);
- }
- else
- {
- msg_print(_("痛い!", "It hurts!"));
- take_hit(DAMAGE_LOSELIFE, damroll(o_ptr->sval + 1, 6), _("暗黒魔法の逆流", "a miscast Death spell"), -1);
-
- if ((spell > 15) && one_in_(6) && !p_ptr->hold_exp)
- lose_exp(spell * 250);
- }
- }
- else if ((o_ptr->tval == TV_MUSIC_BOOK) && (randint1(200) < spell))
- {
- msg_print(_("いやな音が響いた", "An infernal sound echoed."));
- aggravate_monsters(0);
- }
- if (randint1(100) >= chance)
- chg_virtue(V_CHANCE,-1);
- }
-
- /* Process spell */
- else
- {
- /* Canceled spells cost neither a turn nor mana */
- if (!do_spell(realm, spell, SPELL_CAST)) return;
-
- if (randint1(100) < chance)
- chg_virtue(V_CHANCE,1);
-
- /* A spell was cast */
- if (!(increment ?
- (p_ptr->spell_worked2 & (1L << spell)) :
- (p_ptr->spell_worked1 & (1L << spell)))
- && (p_ptr->pclass != CLASS_SORCERER)
- && (p_ptr->pclass != CLASS_RED_MAGE))
- {
- int e = s_ptr->sexp;
-
- /* The spell worked */
- if (realm == p_ptr->realm1)
- {
- p_ptr->spell_worked1 |= (1L << spell);
- }
- else
- {
- p_ptr->spell_worked2 |= (1L << spell);
- }
-
- /* Gain experience */
- gain_exp(e * s_ptr->slevel);
-
- /* Redraw object recall */
- p_ptr->window |= (PW_OBJECT);
-
- switch (realm)
- {
- case REALM_LIFE:
- chg_virtue(V_TEMPERANCE, 1);
- chg_virtue(V_COMPASSION, 1);
- chg_virtue(V_VITALITY, 1);
- chg_virtue(V_DILIGENCE, 1);
- break;
- case REALM_DEATH:
- chg_virtue(V_UNLIFE, 1);
- chg_virtue(V_JUSTICE, -1);
- chg_virtue(V_FAITH, -1);
- chg_virtue(V_VITALITY, -1);
- break;
- case REALM_DAEMON:
- chg_virtue(V_JUSTICE, -1);
- chg_virtue(V_FAITH, -1);
- chg_virtue(V_HONOUR, -1);
- chg_virtue(V_TEMPERANCE, -1);
- break;
- case REALM_CRUSADE:
- chg_virtue(V_FAITH, 1);
- chg_virtue(V_JUSTICE, 1);
- chg_virtue(V_SACRIFICE, 1);
- chg_virtue(V_HONOUR, 1);
- break;
- case REALM_NATURE:
- chg_virtue(V_NATURE, 1);
- chg_virtue(V_HARMONY, 1);
- break;
- case REALM_HEX:
- chg_virtue(V_JUSTICE, -1);
- chg_virtue(V_FAITH, -1);
- chg_virtue(V_HONOUR, -1);
- chg_virtue(V_COMPASSION, -1);
- break;
- default:
- chg_virtue(V_KNOWLEDGE, 1);
- break;
- }
- }
- switch (realm)
- {
- case REALM_LIFE:
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_TEMPERANCE, 1);
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_COMPASSION, 1);
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_VITALITY, 1);
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_DILIGENCE, 1);
- break;
- case REALM_DEATH:
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_UNLIFE, 1);
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1);
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_VITALITY, -1);
- break;
- case REALM_DAEMON:
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1);
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, -1);
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_TEMPERANCE, -1);
- break;
- case REALM_CRUSADE:
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, 1);
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, 1);
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_SACRIFICE, 1);
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, 1);
- break;
- case REALM_NATURE:
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_NATURE, 1);
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HARMONY, 1);
- break;
- case REALM_HEX:
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1);
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, -1);
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_COMPASSION, -1);
- break;
- }
- if (mp_ptr->spell_xtra & MAGIC_GAIN_EXP)
- {
- s16b cur_exp = p_ptr->spell_exp[(increment ? 32 : 0)+spell];
- s16b exp_gain = 0;
-
- if (cur_exp < SPELL_EXP_BEGINNER)
- exp_gain += 60;
- else if (cur_exp < SPELL_EXP_SKILLED)
- {
- if ((dun_level > 4) && ((dun_level + 10) > p_ptr->lev))
- exp_gain = 8;
- }
- else if (cur_exp < SPELL_EXP_EXPERT)
- {
- if (((dun_level + 5) > p_ptr->lev) && ((dun_level + 5) > s_ptr->slevel))
- exp_gain = 2;
- }
- else if ((cur_exp < SPELL_EXP_MASTER) && !increment)
- {
- if (((dun_level + 5) > p_ptr->lev) && (dun_level > s_ptr->slevel))
- exp_gain = 1;
- }
- p_ptr->spell_exp[(increment ? 32 : 0) + spell] += exp_gain;
- }
- }
-
- p_ptr->energy_use = 100;
-
-
- /* Over-exert the player */
- if(over_exerted)
- {
- int oops = need_mana;
-
- /* No mana left */
- p_ptr->csp = 0;
- p_ptr->csp_frac = 0;
-
- msg_print(_("精神を集中しすぎて気を失ってしまった!", "You faint from the effort!"));
-
- /* Hack -- Bypass free action */
- (void)set_paralyzed(p_ptr->paralyzed + randint1(5 * oops + 1));
-
- switch (realm)
- {
- case REALM_LIFE:
- chg_virtue(V_VITALITY, -10);
- break;
- case REALM_DEATH:
- chg_virtue(V_UNLIFE, -10);
- break;
- case REALM_DAEMON:
- chg_virtue(V_JUSTICE, 10);
- break;
- case REALM_NATURE:
- chg_virtue(V_NATURE, -10);
- break;
- case REALM_CRUSADE:
- chg_virtue(V_JUSTICE, -10);
- break;
- case REALM_HEX:
- chg_virtue(V_COMPASSION, 10);
- break;
- default:
- chg_virtue(V_KNOWLEDGE, -10);
- break;
- }
-
- /* Damage CON (possibly permanently) */
- if (randint0(100) < 50)
- {
- bool perm = (randint0(100) < 25);
-
- msg_print(_("体を悪くしてしまった!", "You have damaged your health!"));
-
- /* Reduce constitution */
- (void)dec_stat(A_CON, 15 + randint1(10), perm);
- }
- }
-
- p_ptr->window |= (PW_PLAYER);
- p_ptr->window |= (PW_SPELL);
-}
#include "artifact.h"
#include "avatar.h"
#include "player-status.h"
+#include "cmd-spell.h"
static bool load = TRUE; /*!<ロード処理中の分岐フラグ*/
static int wild_regen = 20; /*!<広域マップ移動時の自然回復処理カウンタ(広域マップ1マス毎に20回処理を基本とする)*/
extern void do_cmd_checkquest(void);
extern void do_cmd_time(void);
-/* cmd5.c */
-extern concptr spell_category_name(OBJECT_TYPE_VALUE tval);
-extern void do_cmd_browse(void);
-extern void do_cmd_study(void);
-extern void do_cmd_cast(void);
-
/* cmd-spell.c */
extern void stop_singing(void);
extern concptr do_spell(REALM_IDX realm, SPELL_IDX spell, BIT_FLAGS mode);
extern int project_length;
extern bool binding_field(HIT_POINT dam);
extern void seal_of_mirror(HIT_POINT dam);
+extern concptr spell_category_name(OBJECT_TYPE_VALUE tval);
/* spells2.c */
extern void message_pain(MONSTER_IDX m_idx, HIT_POINT dam);
#include "angband.h"
-#include "artifact.h"
#include "player-status.h"
+
+#include "artifact.h"
#include "avatar.h"
/*
#include "player-status.h"
#include "spells-status.h"
#include "spells-object.h"
+#include "cmd-spell.h"
/*!
* @brief 魔法系コマンドを実行できるかの判定を返す
}
return;
}
-
+
+
+
+/*!
+ * @brief 領域魔法に応じて技能の名称を返す。
+ * @param tval 魔法書のtval
+ * @return 領域魔法の技能名称を保管した文字列ポインタ
+ */
+concptr spell_category_name(OBJECT_TYPE_VALUE tval)
+{
+ switch (tval)
+ {
+ case TV_HISSATSU_BOOK:
+ return _("必殺技", "art");
+ case TV_LIFE_BOOK:
+ return _("祈り", "prayer");
+ case TV_MUSIC_BOOK:
+ return _("歌", "song");
+ default:
+ return _("呪文", "spell");
+ }
+}
+
#include "cmd-magiceat.h"
#include "store.h"
#include "avatar.h"
+#include "cmd-spell.h"
#define MIN_STOCK 12