From 90c7ac75ede2629a23b5a6f29eabee7a9516739c Mon Sep 17 00:00:00 2001 From: Deskull Date: Sat, 8 Sep 2018 20:31:13 +0900 Subject: [PATCH] =?utf8?q?[Refactor]=20#37353=E3=80=80cmd6.c=E3=82=92cmd-m?= =?utf8?q?agiceat.c=E3=81=AB=E6=94=B9=E5=90=8D=E3=81=97=E3=81=A4=E3=81=A4?= =?utf8?q?=E6=95=B4=E7=90=86=E3=80=82=20/=20Refactor=20to=20rename=20cmd6.?= =?utf8?q?c=20to=20cmd-magiceat.c.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- Hengband_vcs2015/Hengband/Hengband.vcxproj | 3 +- Hengband_vcs2015/Hengband/Hengband.vcxproj.filters | 9 +- src/cmd-activate.c | 418 ++++++++++++++++++ src/cmd-activate.h | 4 + src/{cmd6.c => cmd-magiceat.c} | 253 ----------- src/cmd-magiceat.h | 1 + src/cmd-zaprod.c | 432 +++++++++++++++++++ src/cmd-zaprod.h | 3 + src/cmd-zapwand.c | 476 +++++++++++++++++++++ src/cmd-zapwand.h | 3 + src/cmd3.c | 188 ++++++++ src/dungeon.c | 1 + src/externs.h | 11 +- src/racial.c | 1 + src/spells2.c | 69 +++ src/store.c | 1 + 16 files changed, 1609 insertions(+), 264 deletions(-) create mode 100644 src/cmd-activate.c create mode 100644 src/cmd-activate.h rename src/{cmd6.c => cmd-magiceat.c} (77%) create mode 100644 src/cmd-magiceat.h create mode 100644 src/cmd-zaprod.c create mode 100644 src/cmd-zaprod.h create mode 100644 src/cmd-zapwand.c create mode 100644 src/cmd-zapwand.h diff --git a/Hengband_vcs2015/Hengband/Hengband.vcxproj b/Hengband_vcs2015/Hengband/Hengband.vcxproj index 190d9d718..2793217b1 100644 --- a/Hengband_vcs2015/Hengband/Hengband.vcxproj +++ b/Hengband_vcs2015/Hengband/Hengband.vcxproj @@ -145,6 +145,7 @@ + CppCode @@ -154,7 +155,7 @@ - + diff --git a/Hengband_vcs2015/Hengband/Hengband.vcxproj.filters b/Hengband_vcs2015/Hengband/Hengband.vcxproj.filters index 18583e14f..70401f87a 100644 --- a/Hengband_vcs2015/Hengband/Hengband.vcxproj.filters +++ b/Hengband_vcs2015/Hengband/Hengband.vcxproj.filters @@ -34,9 +34,6 @@ Source - - Source - Source @@ -232,6 +229,9 @@ Source + + Source + @@ -325,6 +325,9 @@ Header + + Header + diff --git a/src/cmd-activate.c b/src/cmd-activate.c new file mode 100644 index 000000000..11f5b84fa --- /dev/null +++ b/src/cmd-activate.c @@ -0,0 +1,418 @@ +/*! +* @file cmd-activate.c +* @brief プレイヤーの発動コマンド実装 +* @date 2018/09/07 +* @details +* cmd6.cより分離。 +*/ + +#include "angband.h" + +/*! +* @brief ペット入りモンスターボールをソートするための比較関数 +* @param u 所持品配列の参照ポインタ +* @param v 未使用 +* @param a 所持品ID1 +* @param b 所持品ID2 +* @return 1の方が大であればTRUE +*/ +static bool ang_sort_comp_pet(vptr u, vptr v, int a, int b) +{ + u16b *who = (u16b*)(u); + + int w1 = who[a]; + int w2 = who[b]; + + monster_type *m_ptr1 = &m_list[w1]; + monster_type *m_ptr2 = &m_list[w2]; + monster_race *r_ptr1 = &r_info[m_ptr1->r_idx]; + monster_race *r_ptr2 = &r_info[m_ptr2->r_idx]; + + /* Unused */ + (void)v; + + if (m_ptr1->nickname && !m_ptr2->nickname) return TRUE; + if (m_ptr2->nickname && !m_ptr1->nickname) return FALSE; + + if ((r_ptr1->flags1 & RF1_UNIQUE) && !(r_ptr2->flags1 & RF1_UNIQUE)) return TRUE; + if ((r_ptr2->flags1 & RF1_UNIQUE) && !(r_ptr1->flags1 & RF1_UNIQUE)) return FALSE; + + if (r_ptr1->level > r_ptr2->level) return TRUE; + if (r_ptr2->level > r_ptr1->level) return FALSE; + + if (m_ptr1->hp > m_ptr2->hp) return TRUE; + if (m_ptr2->hp > m_ptr1->hp) return FALSE; + + return w1 <= w2; +} + +/*! +* @brief オブジェクトをプレイヤーが魔道具として発動できるかを判定する / +* Hook to determine if an object is activatable +* @param o_ptr 判定したいオブジェクトの構造体参照ポインタ +* @return 魔道具として発動可能ならばTRUEを返す +*/ +static bool item_tester_hook_activate(object_type *o_ptr) +{ + u32b flgs[TR_FLAG_SIZE]; + + /* Not known */ + if (!object_is_known(o_ptr)) return (FALSE); + + /* Extract the flags */ + object_flags(o_ptr, flgs); + + /* Check activation flag */ + if (have_flag(flgs, TR_ACTIVATE)) return (TRUE); + + /* Assume not */ + return (FALSE); +} + +/*! + * @brief 装備を発動するコマンドのサブルーチン / + * Activate a wielded object. Wielded objects never stack. + * And even if they did, activatable objects never stack. + * @param item 発動するオブジェクトの所持品ID + * @return なし + * @details + *
+ * Currently, only (some) artifacts, and Dragon Scale Mail, can be activated.
+ * But one could, for example, easily make an activatable "Ring of Plasma".
+ * Note that it always takes a turn to activate an artifact, even if
+ * the user hits "escape" at the "direction" prompt.
+ * 
+ */ +void do_cmd_activate_aux(int item) +{ + int dir, lev, chance, fail; + object_type *o_ptr; + bool success; + + + /* Get the item (in the pack) */ + if (item >= 0) + { + o_ptr = &inventory[item]; + } + + /* Get the item (on the floor) */ + else + { + o_ptr = &o_list[0 - item]; + } + + /* Take a turn */ + p_ptr->energy_use = 100; + + /* Extract the item level */ + lev = k_info[o_ptr->k_idx].level; + + /* Hack -- use artifact level instead */ + if (object_is_fixed_artifact(o_ptr)) lev = a_info[o_ptr->name1].level; + else if (object_is_random_artifact(o_ptr)) + { + const activation_type* const act_ptr = find_activation_info(o_ptr); + if (act_ptr) { + lev = act_ptr->level; + } + } + else if (((o_ptr->tval == TV_RING) || (o_ptr->tval == TV_AMULET)) && o_ptr->name2) lev = e_info[o_ptr->name2].level; + + /* Base chance of success */ + chance = p_ptr->skill_dev; + + /* Confusion hurts skill */ + if (p_ptr->confused) chance = chance / 2; + + fail = lev+5; + if (chance > fail) fail -= (chance - fail)*2; + else chance -= (fail - chance)*2; + if (fail < USE_DEVICE) fail = USE_DEVICE; + if (chance < USE_DEVICE) chance = USE_DEVICE; + + if (world_player) + { + if (flush_failure) flush(); + msg_print(_("止まった時の中ではうまく働かないようだ。", "It shows no reaction.")); + sound(SOUND_FAIL); + return; + } + + if (p_ptr->pclass == CLASS_BERSERKER) success = FALSE; + else if (chance > fail) + { + if (randint0(chance*2) < fail) success = FALSE; + else success = TRUE; + } + else + { + if (randint0(fail*2) < chance) success = TRUE; + else success = FALSE; + } + + /* Roll for usage */ + if (!success) + { + if (flush_failure) flush(); + msg_print(_("うまく始動させることができなかった。", "You failed to activate it properly.")); + sound(SOUND_FAIL); + return; + } + + /* Check the recharge */ + if (o_ptr->timeout) + { + msg_print(_("それは微かに音を立て、輝き、消えた...", "It whines, glows and fades...")); + return; + } + + /* Some lights need enough fuel for activation */ + if (!o_ptr->xtra4 && (o_ptr->tval == TV_FLASK) && + ((o_ptr->sval == SV_LITE_TORCH) || (o_ptr->sval == SV_LITE_LANTERN))) + { + msg_print(_("燃料がない。", "It has no fuel.")); + p_ptr->energy_use = 0; + return; + } + + /* Activate the artifact */ + msg_print(_("始動させた...", "You activate it...")); + + /* Sound */ + sound(SOUND_ZAP); + + /* Activate object */ + if (activation_index(o_ptr)) + { + (void)activate_random_artifact(o_ptr); + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP); + + /* Success */ + return; + } + + /* Special items */ + else if (o_ptr->tval == TV_WHISTLE) + { + if (music_singing_any()) stop_singing(); + if (hex_spelling_any()) stop_hex_spell_all(); + +#if 0 + if (object_is_cursed(o_ptr)) + { + msg_print(_("カン高い音が響き渡った。", "You produce a shrill whistling sound.")); + aggravate_monsters(0); + } + else +#endif + { + IDX pet_ctr, i; + IDX *who; + int max_pet = 0; + u16b dummy_why; + + /* Allocate the "who" array */ + C_MAKE(who, max_m_idx, IDX); + + /* Process the monsters (backwards) */ + for (pet_ctr = m_max - 1; pet_ctr >= 1; pet_ctr--) + { + if (is_pet(&m_list[pet_ctr]) && (p_ptr->riding != pet_ctr)) + who[max_pet++] = pet_ctr; + } + + /* Select the sort method */ + ang_sort_comp = ang_sort_comp_pet; + ang_sort_swap = ang_sort_swap_hook; + + ang_sort(who, &dummy_why, max_pet); + + /* Process the monsters (backwards) */ + for (i = 0; i < max_pet; i++) + { + pet_ctr = who[i]; + teleport_monster_to(pet_ctr, p_ptr->y, p_ptr->x, 100, TELEPORT_PASSIVE); + } + + /* Free the "who" array */ + C_KILL(who, max_m_idx, IDX); + } + o_ptr->timeout = 100+randint1(100); + return; + } + else if (o_ptr->tval == TV_CAPTURE) + { + if(!o_ptr->pval) + { + bool old_target_pet = target_pet; + target_pet = TRUE; + if (!get_aim_dir(&dir)) + { + target_pet = old_target_pet; + return; + } + target_pet = old_target_pet; + + if(fire_ball(GF_CAPTURE, dir, 0, 0)) + { + o_ptr->pval = (PARAMETER_VALUE)cap_mon; + o_ptr->xtra3 = (XTRA8)cap_mspeed; + o_ptr->xtra4 = (XTRA16)cap_hp; + o_ptr->xtra5 = (XTRA16)cap_maxhp; + if (cap_nickname) + { + cptr t; + char *s; + char buf[80] = ""; + + if (o_ptr->inscription) + strcpy(buf, quark_str(o_ptr->inscription)); + s = buf; + for (s = buf;*s && (*s != '#'); s++) + { +#ifdef JP + if (iskanji(*s)) s++; +#endif + } + *s = '#'; + s++; +#ifdef JP + /*nothing*/ +#else + *s++ = '\''; +#endif + t = quark_str(cap_nickname); + while (*t) + { + *s = *t; + s++; + t++; + } +#ifdef JP + /*nothing*/ +#else + *s++ = '\''; +#endif + *s = '\0'; + o_ptr->inscription = quark_add(buf); + } + } + } + else + { + success = FALSE; + if (!get_rep_dir2(&dir)) return; + if (monster_can_enter(p_ptr->y + ddy[dir], p_ptr->x + ddx[dir], &r_info[o_ptr->pval], 0)) + { + if (place_monster_aux(0, p_ptr->y + ddy[dir], p_ptr->x + ddx[dir], o_ptr->pval, (PM_FORCE_PET | PM_NO_KAGE))) + { + if (o_ptr->xtra3) m_list[hack_m_idx_ii].mspeed = o_ptr->xtra3; + if (o_ptr->xtra5) m_list[hack_m_idx_ii].max_maxhp = o_ptr->xtra5; + if (o_ptr->xtra4) m_list[hack_m_idx_ii].hp = o_ptr->xtra4; + m_list[hack_m_idx_ii].maxhp = m_list[hack_m_idx_ii].max_maxhp; + if (o_ptr->inscription) + { + char buf[80]; + cptr t; +#ifndef JP + bool quote = FALSE; +#endif + + t = quark_str(o_ptr->inscription); + for (t = quark_str(o_ptr->inscription);*t && (*t != '#'); t++) + { +#ifdef JP + if (iskanji(*t)) t++; +#endif + } + if (*t) + { + char *s = buf; + t++; +#ifdef JP + /* nothing */ +#else + if (*t =='\'') + { + t++; + quote = TRUE; + } +#endif + while(*t) + { + *s = *t; + t++; + s++; + } +#ifdef JP + /* nothing */ +#else + if (quote && *(s-1) =='\'') + s--; +#endif + *s = '\0'; + m_list[hack_m_idx_ii].nickname = quark_add(buf); + t = quark_str(o_ptr->inscription); + s = buf; + while(*t && (*t != '#')) + { + *s = *t; + t++; + s++; + } + *s = '\0'; + o_ptr->inscription = quark_add(buf); + } + } + o_ptr->pval = 0; + o_ptr->xtra3 = 0; + o_ptr->xtra4 = 0; + o_ptr->xtra5 = 0; + success = TRUE; + } + } + if (!success) + msg_print(_("おっと、解放に失敗した。", "Oops. You failed to release your pet.")); + } + calc_android_exp(); + return; + } + + /* Mistake */ + msg_print(_("おっと、このアイテムは始動できない。", "Oops. That object cannot be activated.")); +} + +/*! + * @brief 装備を発動するコマンドのメインルーチン / + * @return なし + */ +void do_cmd_activate(void) +{ + OBJECT_IDX item; + cptr q, s; + + + if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) + { + set_action(ACTION_NONE); + } + + item_tester_no_ryoute = TRUE; + /* Prepare the hook */ + item_tester_hook = item_tester_hook_activate; + + /* Get an item */ + q = _("どのアイテムを始動させますか? ", "Activate which item? "); + s = _("始動できるアイテムを装備していない。", "You have nothing to activate."); + + if (!get_item(&item, q, s, (USE_EQUIP))) return; + + /* Activate the item */ + do_cmd_activate_aux(item); +} + + + diff --git a/src/cmd-activate.h b/src/cmd-activate.h new file mode 100644 index 000000000..2f01fece3 --- /dev/null +++ b/src/cmd-activate.h @@ -0,0 +1,4 @@ +extern void do_cmd_activate(void); +extern void do_cmd_activate_aux(int item); + + diff --git a/src/cmd6.c b/src/cmd-magiceat.c similarity index 77% rename from src/cmd6.c rename to src/cmd-magiceat.c index 223e195ed..00e398b80 100644 --- a/src/cmd6.c +++ b/src/cmd-magiceat.c @@ -53,265 +53,12 @@ */ #include "angband.h" -#include "selfinfo.h" -#include "cmd-activate.h" -#include "cmd-eat.h" -#include "cmd-quaff.h" -#include "cmd-read.h" #include "cmd-usestaff.h" #include "cmd-zaprod.h" #include "cmd-zapwand.h" /*! - * @brief 『一つの指輪』の効果処理 / - * Hack -- activate the ring of power - * @param dir 発動の方向ID - * @return なし - */ -void ring_of_power(int dir) -{ - /* Pick a random effect */ - switch (randint1(10)) - { - case 1: - case 2: - { - /* Message */ - msg_print(_("あなたは悪性のオーラに包み込まれた。", "You are surrounded by a malignant aura.")); - sound(SOUND_EVIL); - - /* Decrease all stats (permanently) */ - (void)dec_stat(A_STR, 50, TRUE); - (void)dec_stat(A_INT, 50, TRUE); - (void)dec_stat(A_WIS, 50, TRUE); - (void)dec_stat(A_DEX, 50, TRUE); - (void)dec_stat(A_CON, 50, TRUE); - (void)dec_stat(A_CHR, 50, TRUE); - - /* Lose some experience (permanently) */ - p_ptr->exp -= (p_ptr->exp / 4); - p_ptr->max_exp -= (p_ptr->exp / 4); - check_experience(); - - break; - } - - case 3: - { - /* Message */ - msg_print(_("あなたは強力なオーラに包み込まれた。", "You are surrounded by a powerful aura.")); - - /* Dispel monsters */ - dispel_monsters(1000); - - break; - } - - case 4: - case 5: - case 6: - { - /* Mana Ball */ - fire_ball(GF_MANA, dir, 600, 3); - - break; - } - - case 7: - case 8: - case 9: - case 10: - { - /* Mana Bolt */ - fire_bolt(GF_MANA, dir, 500); - - break; - } - } -} - -/*! - * @brief オブジェクトをプレイヤーが簡易使用コマンドで利用できるかを判定する / - * Hook to determine if an object is useable - * @param o_ptr 判定したいオブジェクトの構造体参照ポインタ - * @return 利用可能ならばTRUEを返す - */ -static bool item_tester_hook_use(object_type *o_ptr) -{ - u32b flgs[TR_FLAG_SIZE]; - - /* Ammo */ - if (o_ptr->tval == p_ptr->tval_ammo) - return (TRUE); - - /* Useable object */ - switch (o_ptr->tval) - { - case TV_SPIKE: - case TV_STAFF: - case TV_WAND: - case TV_ROD: - case TV_SCROLL: - case TV_POTION: - case TV_FOOD: - { - return (TRUE); - } - - default: - { - int i; - - /* Not known */ - if (!object_is_known(o_ptr)) return (FALSE); - - /* HACK - only items from the equipment can be activated */ - for (i = INVEN_RARM; i < INVEN_TOTAL; i++) - { - if (&inventory[i] == o_ptr) - { - /* Extract the flags */ - object_flags(o_ptr, flgs); - - /* Check activation flag */ - if (have_flag(flgs, TR_ACTIVATE)) return (TRUE); - } - } - } - } - - /* Assume not */ - return (FALSE); -} - - -/*! - * @brief アイテムを汎用的に「使う」コマンドのメインルーチン / - * Use an item - * @return なし - * @details - * XXX - Add actions for other item types - */ -void do_cmd_use(void) -{ - OBJECT_IDX item; - object_type *o_ptr; - cptr q, s; - - if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) - { - set_action(ACTION_NONE); - } - - item_tester_no_ryoute = TRUE; - /* Prepare the hook */ - item_tester_hook = item_tester_hook_use; - - /* Get an item */ - q = _("どれを使いますか?", "Use which item? "); - s = _("使えるものがありません。", "You have nothing to use."); - - if (!get_item(&item, q, s, (USE_INVEN | USE_EQUIP | USE_FLOOR))) return; - - /* Get the item (in the pack) */ - if (item >= 0) - { - o_ptr = &inventory[item]; - } - /* Get the item (on the floor) */ - else - { - o_ptr = &o_list[0 - item]; - } - - switch (o_ptr->tval) - { - /* Spike a door */ - case TV_SPIKE: - { - do_cmd_spike(); - break; - } - - /* Eat some food */ - case TV_FOOD: - { - do_cmd_eat_food_aux(item); - break; - } - - /* Aim a wand */ - case TV_WAND: - { - do_cmd_aim_wand_aux(item); - break; - } - - /* Use a staff */ - case TV_STAFF: - { - do_cmd_use_staff_aux(item); - break; - } - - /* Zap a rod */ - case TV_ROD: - { - do_cmd_zap_rod_aux(item); - break; - } - - /* Quaff a potion */ - case TV_POTION: - { - do_cmd_quaff_potion_aux(item); - break; - } - - /* Read a scroll */ - case TV_SCROLL: - { - /* Check some conditions */ - if (p_ptr->blind) - { - msg_print(_("目が見えない。", "You can't see anything.")); - return; - } - if (no_lite()) - { - msg_print(_("明かりがないので、暗くて読めない。", "You have no light to read by.")); - return; - } - if (p_ptr->confused) - { - msg_print(_("混乱していて読めない!", "You are too confused!")); - return; - } - - do_cmd_read_scroll_aux(item, TRUE); - break; - } - - /* Fire ammo */ - case TV_SHOT: - case TV_ARROW: - case TV_BOLT: - { - do_cmd_fire_aux(item, &inventory[INVEN_BOW]); - break; - } - - /* Activate an artifact */ - default: - { - do_cmd_activate_aux(item); - break; - } - } -} - -/*! * @brief 魔道具術師の取り込んだ魔力一覧から選択/閲覧する / * @param only_browse 閲覧するだけならばTRUE * @return 選択した魔力のID、キャンセルならば-1を返す diff --git a/src/cmd-magiceat.h b/src/cmd-magiceat.h new file mode 100644 index 000000000..6ef036388 --- /dev/null +++ b/src/cmd-magiceat.h @@ -0,0 +1 @@ +extern bool do_cmd_magic_eater(bool only_browse, bool powerful); diff --git a/src/cmd-zaprod.c b/src/cmd-zaprod.c new file mode 100644 index 000000000..89c4cb30c --- /dev/null +++ b/src/cmd-zaprod.c @@ -0,0 +1,432 @@ +#include "angband.h" + +/*! + * @brief ƒƒbƒh‚ÌŒø‰Ê‚ð”­“®‚·‚é + * @param sval ƒIƒuƒWƒFƒNƒg‚Ìsval + * @param dir ”­“®–Ú•W‚Ì•ûŒüID + * @param use_charge ƒ`ƒƒ[ƒW‚ðÁ”‚½‚©‚Ç‚¤‚©‚ð•Ô‚·ŽQÆƒ|ƒCƒ“ƒ^ + * @param powerful ‹­—Í”­“®ã‚̏ˆ—‚È‚ç‚ÎTRUE + * @param magic –‚“¹‹ïpã‚̏ˆ—‚È‚ç‚ÎTRUE + * @return ”­“®‚É‚æ‚èŒø‰Ê“à—e‚ªŠm’肵‚½‚È‚ç‚ÎTRUE‚ð•Ô‚· + */ +int rod_effect(OBJECT_SUBTYPE_VALUE sval, int dir, bool *use_charge, bool powerful, bool magic) +{ + int ident = FALSE; + int lev = powerful ? p_ptr->lev * 2 : p_ptr->lev; + int detect_rad = powerful ? DETECT_RAD_DEFAULT * 3 / 2 : DETECT_RAD_DEFAULT; + int rad = powerful ? 3 : 2; + + /* Unused */ + (void)magic; + + /* Analyze the rod */ + switch (sval) + { + case SV_ROD_DETECT_TRAP: + { + if (detect_traps(detect_rad, (bool)(dir ? FALSE : TRUE))) ident = TRUE; + break; + } + + case SV_ROD_DETECT_DOOR: + { + if (detect_doors(detect_rad)) ident = TRUE; + if (detect_stairs(detect_rad)) ident = TRUE; + break; + } + + case SV_ROD_IDENTIFY: + { + if (powerful) { + if (!identify_fully(FALSE)) *use_charge = FALSE; + } + else { + if (!ident_spell(FALSE)) *use_charge = FALSE; + } + ident = TRUE; + break; + } + + case SV_ROD_RECALL: + { + if (!word_of_recall()) *use_charge = FALSE; + ident = TRUE; + break; + } + + case SV_ROD_ILLUMINATION: + { + if (lite_area(damroll(2, 8), (powerful ? 4 : 2))) ident = TRUE; + break; + } + + case SV_ROD_MAPPING: + { + map_area(powerful ? DETECT_RAD_MAP * 3 / 2 : DETECT_RAD_MAP); + ident = TRUE; + break; + } + + case SV_ROD_DETECTION: + { + detect_all(detect_rad); + ident = TRUE; + break; + } + + case SV_ROD_PROBING: + { + probing(); + ident = TRUE; + break; + } + + case SV_ROD_CURING: + { + if (set_blind(0)) ident = TRUE; + if (set_poisoned(0)) ident = TRUE; + if (set_confused(0)) ident = TRUE; + if (set_stun(0)) ident = TRUE; + if (set_cut(0)) ident = TRUE; + if (set_image(0)) ident = TRUE; + if (set_shero(0, TRUE)) ident = TRUE; + break; + } + + case SV_ROD_HEALING: + { + if (hp_player(powerful ? 750 : 500)) ident = TRUE; + if (set_stun(0)) ident = TRUE; + if (set_cut(0)) ident = TRUE; + if (set_shero(0, TRUE)) ident = TRUE; + break; + } + + case SV_ROD_RESTORATION: + { + if (restore_level()) ident = TRUE; + if (do_res_stat(A_STR)) ident = TRUE; + if (do_res_stat(A_INT)) ident = TRUE; + if (do_res_stat(A_WIS)) ident = TRUE; + if (do_res_stat(A_DEX)) ident = TRUE; + if (do_res_stat(A_CON)) ident = TRUE; + if (do_res_stat(A_CHR)) ident = TRUE; + break; + } + + case SV_ROD_SPEED: + { + if (set_fast(randint1(30) + (powerful ? 30 : 15), FALSE)) ident = TRUE; + break; + } + + case SV_ROD_PESTICIDE: + { + if (dispel_monsters(powerful ? 8 : 4)) ident = TRUE; + break; + } + + case SV_ROD_TELEPORT_AWAY: + { + int distance = MAX_SIGHT * (powerful ? 8 : 5); + if (teleport_monster(dir, distance)) ident = TRUE; + break; + } + + case SV_ROD_DISARMING: + { + if (disarm_trap(dir)) ident = TRUE; + if (powerful && disarm_traps_touch()) ident = TRUE; + break; + } + + case SV_ROD_LITE: + { + HIT_POINT dam = damroll((powerful ? 12 : 6), 8); + msg_print(_("Â‚­‹P‚­Œõü‚ª•ú‚½‚ꂽB", "A line of blue shimmering light appears.")); + (void)lite_line(dir, dam); + ident = TRUE; + break; + } + + case SV_ROD_SLEEP_MONSTER: + { + if (sleep_monster(dir, lev)) ident = TRUE; + break; + } + + case SV_ROD_SLOW_MONSTER: + { + if (slow_monster(dir, lev)) ident = TRUE; + break; + } + + case SV_ROD_HYPODYNAMIA: + { + if (hypodynamic_bolt(dir, 70 + 3 * lev / 2)) ident = TRUE; + break; + } + + case SV_ROD_POLYMORPH: + { + if (poly_monster(dir, lev)) ident = TRUE; + break; + } + + case SV_ROD_ACID_BOLT: + { + fire_bolt_or_beam(10, GF_ACID, dir, damroll(6 + lev / 7, 8)); + ident = TRUE; + break; + } + + case SV_ROD_ELEC_BOLT: + { + fire_bolt_or_beam(10, GF_ELEC, dir, damroll(4 + lev / 9, 8)); + ident = TRUE; + break; + } + + case SV_ROD_FIRE_BOLT: + { + fire_bolt_or_beam(10, GF_FIRE, dir, damroll(7 + lev / 6, 8)); + ident = TRUE; + break; + } + + case SV_ROD_COLD_BOLT: + { + fire_bolt_or_beam(10, GF_COLD, dir, damroll(5 + lev / 8, 8)); + ident = TRUE; + break; + } + + case SV_ROD_ACID_BALL: + { + fire_ball(GF_ACID, dir, 60 + lev, rad); + ident = TRUE; + break; + } + + case SV_ROD_ELEC_BALL: + { + fire_ball(GF_ELEC, dir, 40 + lev, rad); + ident = TRUE; + break; + } + + case SV_ROD_FIRE_BALL: + { + fire_ball(GF_FIRE, dir, 70 + lev, rad); + ident = TRUE; + break; + } + + case SV_ROD_COLD_BALL: + { + fire_ball(GF_COLD, dir, 50 + lev, rad); + ident = TRUE; + break; + } + + case SV_ROD_HAVOC: + { + call_chaos(); + ident = TRUE; + break; + } + + case SV_ROD_STONE_TO_MUD: + { + HIT_POINT dam = powerful ? 40 + randint1(60) : 20 + randint1(30); + if (wall_to_mud(dir, dam)) ident = TRUE; + break; + } + + case SV_ROD_AGGRAVATE: + { + aggravate_monsters(0); + ident = TRUE; + break; + } + } + return ident; +} + +/*! +* @brief ƒƒbƒh‚ðŽg‚¤ƒRƒ}ƒ“ƒh‚̃Tƒuƒ‹[ƒ`ƒ“ / +* Activate (zap) a Rod +* @param item Žg‚¤ƒIƒuƒWƒFƒNƒg‚̏ŠŽ•iID +* @return ‚È‚µ +* @details +*
+* Unstack fully charged rods as needed.
+* Hack -- rods of perception/genocide can be "cancelled"
+* All rods can be cancelled at the "Direction?" prompt
+* pvals are defined for each rod in k_info. -LM-
+* 
+*/ +void do_cmd_zap_rod_aux(int item) +{ + int ident, chance, lev, fail; + int dir = 0; + object_type *o_ptr; + bool success; + + /* Hack -- let perception get aborted */ + bool use_charge = TRUE; + + object_kind *k_ptr; + + /* Get the item (in the pack) */ + if (item >= 0) + { + o_ptr = &inventory[item]; + } + + /* Get the item (on the floor) */ + else + { + o_ptr = &o_list[0 - item]; + } + + + /* Mega-Hack -- refuse to zap a pile from the ground */ + if ((item < 0) && (o_ptr->number > 1)) + { + msg_print(_("‚Ü‚¸‚̓ƒbƒh‚ðE‚í‚È‚¯‚ê‚΁B", "You must first pick up the rods.")); + return; + } + + + /* Get a direction (unless KNOWN not to need it) */ + if (((o_ptr->sval >= SV_ROD_MIN_DIRECTION) && (o_ptr->sval != SV_ROD_HAVOC) && (o_ptr->sval != SV_ROD_AGGRAVATE) && (o_ptr->sval != SV_ROD_PESTICIDE)) || + !object_is_aware(o_ptr)) + { + /* Get a direction, allow cancel */ + if (!get_aim_dir(&dir)) return; + } + + + /* Take a turn */ + p_ptr->energy_use = 100; + + /* Extract the item level */ + lev = k_info[o_ptr->k_idx].level; + + /* Base chance of success */ + chance = p_ptr->skill_dev; + + /* Confusion hurts skill */ + if (p_ptr->confused) chance = chance / 2; + + fail = lev + 5; + if (chance > fail) fail -= (chance - fail) * 2; + else chance -= (fail - chance) * 2; + if (fail < USE_DEVICE) fail = USE_DEVICE; + if (chance < USE_DEVICE) chance = USE_DEVICE; + + if (world_player) + { + if (flush_failure) flush(); + msg_print(_("Ž~‚Ü‚Á‚½Žž‚Ì’†‚Å‚Í‚¤‚Ü‚­“­‚©‚È‚¢‚悤‚¾B", "Nothing happen. Maybe this rod is freezing too.")); + sound(SOUND_FAIL); + return; + } + + if (p_ptr->pclass == CLASS_BERSERKER) success = FALSE; + else if (chance > fail) + { + if (randint0(chance * 2) < fail) success = FALSE; + else success = TRUE; + } + else + { + if (randint0(fail * 2) < chance) success = TRUE; + else success = FALSE; + } + + /* Roll for usage */ + if (!success) + { + if (flush_failure) flush(); + msg_print(_("‚¤‚Ü‚­ƒƒbƒh‚ðŽg‚¦‚È‚©‚Á‚½B", "You failed to use the rod properly.")); + sound(SOUND_FAIL); + return; + } + + k_ptr = &k_info[o_ptr->k_idx]; + + /* A single rod is still charging */ + if ((o_ptr->number == 1) && (o_ptr->timeout)) + { + if (flush_failure) flush(); + msg_print(_("‚±‚̃ƒbƒh‚Í‚Ü‚¾–‚—Í‚ð[“U‚µ‚Ä‚¢‚éÅ’†‚¾B", "The rod is still charging.")); + return; + } + /* A stack of rods lacks enough energy. */ + else if ((o_ptr->number > 1) && (o_ptr->timeout > k_ptr->pval * (o_ptr->number - 1))) + { + if (flush_failure) flush(); + msg_print(_("‚»‚̃ƒbƒh‚Í‚Ü‚¾[“U’†‚Å‚·B", "The rods are all still charging.")); + return; + } + + /* Sound */ + sound(SOUND_ZAP); + + ident = rod_effect(o_ptr->sval, dir, &use_charge, FALSE, FALSE); + + /* Increase the timeout by the rod kind's pval. -LM- */ + if (use_charge) o_ptr->timeout += k_ptr->pval; + + /* Combine / Reorder the pack (later) */ + p_ptr->notice |= (PN_COMBINE | PN_REORDER); + + if (!(object_is_aware(o_ptr))) + { + chg_virtue(V_PATIENCE, -1); + chg_virtue(V_CHANCE, 1); + chg_virtue(V_KNOWLEDGE, -1); + } + + /* Tried the object */ + object_tried(o_ptr); + + /* Successfully determined the object function */ + if (ident && !object_is_aware(o_ptr)) + { + object_aware(o_ptr); + gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev); + } + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); +} + +/*! +* @brief ƒƒbƒh‚ðŽg‚¤ƒRƒ}ƒ“ƒh‚̃ƒCƒ“ƒ‹[ƒ`ƒ“ / +* @return ‚È‚µ +*/ +void do_cmd_zap_rod(void) +{ + OBJECT_IDX item; + cptr q, s; + + if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) + { + set_action(ACTION_NONE); + } + + /* Restrict choices to rods */ + item_tester_tval = TV_ROD; + + /* Get an item */ + q = _("‚ǂ̃ƒbƒh‚ðU‚è‚Ü‚·‚©? ", "Zap which rod? "); + s = _("Žg‚¦‚郍ƒbƒh‚ª‚È‚¢B", "You have no rod to zap."); + + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; + + /* Zap the rod */ + do_cmd_zap_rod_aux(item); +} diff --git a/src/cmd-zaprod.h b/src/cmd-zaprod.h new file mode 100644 index 000000000..a2de8caf2 --- /dev/null +++ b/src/cmd-zaprod.h @@ -0,0 +1,3 @@ +extern int rod_effect(OBJECT_SUBTYPE_VALUE sval, int dir, bool *use_charge, bool powerful, bool magic); +extern void do_cmd_zap_rod_aux(int item); +extern void do_cmd_zap_rod(void); diff --git a/src/cmd-zapwand.c b/src/cmd-zapwand.c new file mode 100644 index 000000000..fd6e8af75 --- /dev/null +++ b/src/cmd-zapwand.c @@ -0,0 +1,476 @@ +#include "angband.h" + + +/*! +* @brief –‚–@–_‚ÌŒø‰Ê‚ð”­“®‚·‚é +* @param sval ƒIƒuƒWƒFƒNƒg‚Ìsval +* @param dir ”­“®‚Ì•ûŒüID +* @param powerful ‹­—Í”­“®ã‚̏ˆ—‚È‚ç‚ÎTRUE +* @param magic –‚“¹‹ïpã‚̏ˆ—‚È‚ç‚ÎTRUE +* @return ”­“®‚É‚æ‚èŒø‰Ê“à—e‚ªŠm’肵‚½‚È‚ç‚ÎTRUE‚ð•Ô‚· +*/ +int wand_effect(OBJECT_SUBTYPE_VALUE sval, int dir, bool powerful, bool magic) +{ + int ident = FALSE; + int lev = powerful ? p_ptr->lev * 2 : p_ptr->lev; + int rad = powerful ? 3 : 2; + + /* XXX Hack -- Wand of wonder can do anything before it */ + if (sval == SV_WAND_WONDER) + { + int vir = virtue_number(V_CHANCE); + sval = (OBJECT_SUBTYPE_VALUE)randint0(SV_WAND_WONDER); + + if (vir) + { + if (p_ptr->virtues[vir - 1] > 0) + { + while (randint1(300) < p_ptr->virtues[vir - 1]) sval++; + if (sval > SV_WAND_COLD_BALL) sval = randint0(4) + SV_WAND_ACID_BALL; + } + else + { + while (randint1(300) < (0 - p_ptr->virtues[vir - 1])) sval--; + if (sval < SV_WAND_HEAL_MONSTER) sval = randint0(3) + SV_WAND_HEAL_MONSTER; + } + } + if (sval < SV_WAND_TELEPORT_AWAY) + chg_virtue(V_CHANCE, 1); + } + + /* Analyze the wand */ + switch (sval) + { + case SV_WAND_HEAL_MONSTER: + { + HIT_POINT dam = damroll((powerful ? 20 : 10), 10); + if (heal_monster(dir, dam)) ident = TRUE; + break; + } + + case SV_WAND_HASTE_MONSTER: + { + if (speed_monster(dir, lev)) ident = TRUE; + break; + } + + case SV_WAND_CLONE_MONSTER: + { + if (clone_monster(dir)) ident = TRUE; + break; + } + + case SV_WAND_TELEPORT_AWAY: + { + int distance = MAX_SIGHT * (powerful ? 8 : 5); + if (teleport_monster(dir, distance)) ident = TRUE; + break; + } + + case SV_WAND_DISARMING: + { + if (disarm_trap(dir)) ident = TRUE; + if (powerful && disarm_traps_touch()) ident = TRUE; + break; + } + + case SV_WAND_TRAP_DOOR_DEST: + { + if (destroy_door(dir)) ident = TRUE; + if (powerful && destroy_doors_touch()) ident = TRUE; + break; + } + + case SV_WAND_STONE_TO_MUD: + { + HIT_POINT dam = powerful ? 40 + randint1(60) : 20 + randint1(30); + if (wall_to_mud(dir, dam)) ident = TRUE; + break; + } + + case SV_WAND_LITE: + { + HIT_POINT dam = damroll((powerful ? 12 : 6), 8); + msg_print(_("Â‚­‹P‚­Œõü‚ª•ú‚½‚ꂽB", "A line of blue shimmering light appears.")); + (void)lite_line(dir, dam); + ident = TRUE; + break; + } + + case SV_WAND_SLEEP_MONSTER: + { + if (sleep_monster(dir, lev)) ident = TRUE; + break; + } + + case SV_WAND_SLOW_MONSTER: + { + if (slow_monster(dir, lev)) ident = TRUE; + break; + } + + case SV_WAND_CONFUSE_MONSTER: + { + if (confuse_monster(dir, lev)) ident = TRUE; + break; + } + + case SV_WAND_FEAR_MONSTER: + { + if (fear_monster(dir, lev)) ident = TRUE; + break; + } + + case SV_WAND_HYPODYNAMIA: + { + if (hypodynamic_bolt(dir, 80 + lev)) ident = TRUE; + break; + } + + case SV_WAND_POLYMORPH: + { + if (poly_monster(dir, lev)) ident = TRUE; + break; + } + + case SV_WAND_STINKING_CLOUD: + { + fire_ball(GF_POIS, dir, 12 + lev / 4, rad); + ident = TRUE; + break; + } + + case SV_WAND_MAGIC_MISSILE: + { + fire_bolt_or_beam(20, GF_MISSILE, dir, damroll(2 + lev / 10, 6)); + ident = TRUE; + break; + } + + case SV_WAND_ACID_BOLT: + { + fire_bolt_or_beam(20, GF_ACID, dir, damroll(6 + lev / 7, 8)); + ident = TRUE; + break; + } + + case SV_WAND_CHARM_MONSTER: + { + if (charm_monster(dir, MAX(20, lev))) + ident = TRUE; + break; + } + + case SV_WAND_FIRE_BOLT: + { + fire_bolt_or_beam(20, GF_FIRE, dir, damroll(7 + lev / 6, 8)); + ident = TRUE; + break; + } + + case SV_WAND_COLD_BOLT: + { + fire_bolt_or_beam(20, GF_COLD, dir, damroll(5 + lev / 8, 8)); + ident = TRUE; + break; + } + + case SV_WAND_ACID_BALL: + { + fire_ball(GF_ACID, dir, 60 + 3 * lev / 4, rad); + ident = TRUE; + break; + } + + case SV_WAND_ELEC_BALL: + { + fire_ball(GF_ELEC, dir, 40 + 3 * lev / 4, rad); + ident = TRUE; + break; + } + + case SV_WAND_FIRE_BALL: + { + fire_ball(GF_FIRE, dir, 70 + 3 * lev / 4, rad); + ident = TRUE; + break; + } + + case SV_WAND_COLD_BALL: + { + fire_ball(GF_COLD, dir, 50 + 3 * lev / 4, rad); + ident = TRUE; + break; + } + + case SV_WAND_WONDER: + { + msg_print(_("‚¨‚Á‚ƁA“ä‚Ì–‚–@–_‚ðŽn“®‚³‚¹‚½B", "Oops. Wand of wonder activated.")); + break; + } + + case SV_WAND_DRAGON_FIRE: + { + fire_breath(GF_FIRE, dir, (powerful ? 300 : 200), 3); + ident = TRUE; + break; + } + + case SV_WAND_DRAGON_COLD: + { + fire_breath(GF_COLD, dir, (powerful ? 270 : 180), 3); + ident = TRUE; + break; + } + + case SV_WAND_DRAGON_BREATH: + { + HIT_POINT dam; + int typ; + + switch (randint1(5)) + { + case 1: + dam = 240; + typ = GF_ACID; + break; + case 2: + dam = 210; + typ = GF_ELEC; + break; + case 3: + dam = 240; + typ = GF_FIRE; + break; + case 4: + dam = 210; + typ = GF_COLD; + break; + default: + dam = 180; + typ = GF_POIS; + break; + } + + if (powerful) dam = (dam * 3) / 2; + + fire_ball(typ, dir, dam, -3); + + ident = TRUE; + break; + } + + case SV_WAND_DISINTEGRATE: + { + fire_ball(GF_DISINTEGRATE, dir, 200 + randint1(lev * 2), rad); + ident = TRUE; + break; + } + + case SV_WAND_ROCKETS: + { + msg_print(_("ƒƒPƒbƒg‚ð”­ŽË‚µ‚½I", "You launch a rocket!")); + fire_rocket(GF_ROCKET, dir, 250 + lev * 3, rad); + ident = TRUE; + break; + } + + case SV_WAND_STRIKING: + { + fire_bolt(GF_METEOR, dir, damroll(15 + lev / 3, 13)); + ident = TRUE; + break; + } + + case SV_WAND_GENOCIDE: + { + fire_ball_hide(GF_GENOCIDE, dir, magic ? lev + 50 : 250, 0); + ident = TRUE; + break; + } + } + return ident; +} + +/*! +* @brief –‚–@–_‚ðŽg‚¤ƒRƒ}ƒ“ƒh‚̃Tƒuƒ‹[ƒ`ƒ“ / +* Aim a wand (from the pack or floor). +* @param item Žg‚¤ƒIƒuƒWƒFƒNƒg‚̏ŠŽ•iID +* @return ‚È‚µ +* @details +*
+* Use a single charge from a single item.
+* Handle "unstacking" in a logical manner.
+* For simplicity, you cannot use a stack of items from the
+* ground.  This would require too much nasty code.
+* There are no wands which can "destroy" themselves, in the inventory
+* or on the ground, so we can ignore this possibility.  Note that this
+* required giving "wand of wonder" the ability to ignore destruction
+* by electric balls.
+* All wands can be "cancelled" at the "Direction?" prompt for free.
+* Note that the basic "bolt" wands do slightly less damage than the
+* basic "bolt" rods, but the basic "ball" wands do the same damage
+* as the basic "ball" rods.
+* 
+*/ +void do_cmd_aim_wand_aux(int item) +{ + int lev, ident, chance, dir; + object_type *o_ptr; + bool old_target_pet = target_pet; + + /* Get the item (in the pack) */ + if (item >= 0) + { + o_ptr = &inventory[item]; + } + + /* Get the item (on the floor) */ + else + { + o_ptr = &o_list[0 - item]; + } + + /* Mega-Hack -- refuse to aim a pile from the ground */ + if ((item < 0) && (o_ptr->number > 1)) + { + msg_print(_("‚Ü‚¸‚Í–‚–@–_‚ðE‚í‚È‚¯‚ê‚΁B", "You must first pick up the wands.")); + return; + } + + + /* Allow direction to be cancelled for free */ + if (object_is_aware(o_ptr) && (o_ptr->sval == SV_WAND_HEAL_MONSTER + || o_ptr->sval == SV_WAND_HASTE_MONSTER)) + target_pet = TRUE; + if (!get_aim_dir(&dir)) + { + target_pet = old_target_pet; + return; + } + target_pet = old_target_pet; + + /* Take a turn */ + p_ptr->energy_use = 100; + + /* Get the level */ + lev = k_info[o_ptr->k_idx].level; + if (lev > 50) lev = 50 + (lev - 50) / 2; + + /* Base chance of success */ + chance = p_ptr->skill_dev; + + /* Confusion hurts skill */ + if (p_ptr->confused) chance = chance / 2; + + /* Hight level objects are harder */ + chance = chance - lev; + + /* Give everyone a (slight) chance */ + if ((chance < USE_DEVICE) && one_in_(USE_DEVICE - chance + 1)) + { + chance = USE_DEVICE; + } + + if (world_player) + { + if (flush_failure) flush(); + msg_print(_("Ž~‚Ü‚Á‚½Žž‚Ì’†‚Å‚Í‚¤‚Ü‚­“­‚©‚È‚¢‚悤‚¾B", "Nothing happen. Maybe this wand is freezing too.")); + sound(SOUND_FAIL); + return; + } + + /* Roll for usage */ + if ((chance < USE_DEVICE) || (randint1(chance) < USE_DEVICE) || (p_ptr->pclass == CLASS_BERSERKER)) + { + if (flush_failure) flush(); + msg_print(_("–‚–@–_‚ð‚¤‚Ü‚­Žg‚¦‚È‚©‚Á‚½B", "You failed to use the wand properly.")); + sound(SOUND_FAIL); + return; + } + + /* The wand is already empty! */ + if (o_ptr->pval <= 0) + { + if (flush_failure) flush(); + msg_print(_("‚±‚Ì–‚–@–_‚É‚Í‚à‚¤–‚—Í‚ªŽc‚Á‚Ä‚¢‚È‚¢B", "The wand has no charges left.")); + o_ptr->ident |= (IDENT_EMPTY); + + /* Combine / Reorder the pack (later) */ + p_ptr->notice |= (PN_COMBINE | PN_REORDER); + p_ptr->window |= (PW_INVEN); + + return; + } + + /* Sound */ + sound(SOUND_ZAP); + + ident = wand_effect(o_ptr->sval, dir, FALSE, FALSE); + + /* Combine / Reorder the pack (later) */ + p_ptr->notice |= (PN_COMBINE | PN_REORDER); + + if (!(object_is_aware(o_ptr))) + { + chg_virtue(V_PATIENCE, -1); + chg_virtue(V_CHANCE, 1); + chg_virtue(V_KNOWLEDGE, -1); + } + + /* Mark it as tried */ + object_tried(o_ptr); + + /* Apply identification */ + if (ident && !object_is_aware(o_ptr)) + { + object_aware(o_ptr); + gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev); + } + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + + + /* Use a single charge */ + o_ptr->pval--; + + /* Describe the charges in the pack */ + if (item >= 0) + { + inven_item_charges(item); + } + + /* Describe the charges on the floor */ + else + { + floor_item_charges(0 - item); + } +} + +/*! +* @brief –‚–@–_‚ðŽg‚¤ƒRƒ}ƒ“ƒh‚̃ƒCƒ“ƒ‹[ƒ`ƒ“ / +* @return ‚È‚µ +*/ +void do_cmd_aim_wand(void) +{ + OBJECT_IDX item; + cptr q, s; + + /* Restrict choices to wands */ + item_tester_tval = TV_WAND; + + if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) + { + set_action(ACTION_NONE); + } + + /* Get an item */ + q = _("‚Ç‚Ì–‚–@–_‚Å‘_‚¢‚Ü‚·‚©? ", "Aim which wand? "); + s = _("Žg‚¦‚é–‚–@–_‚ª‚È‚¢B", "You have no wand to aim."); + + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; + + /* Aim the wand */ + do_cmd_aim_wand_aux(item); +} diff --git a/src/cmd-zapwand.h b/src/cmd-zapwand.h new file mode 100644 index 000000000..261efa5d2 --- /dev/null +++ b/src/cmd-zapwand.h @@ -0,0 +1,3 @@ +extern int wand_effect(OBJECT_SUBTYPE_VALUE sval, int dir, bool powerful, bool magic); +extern void do_cmd_aim_wand_aux(int item); +extern void do_cmd_aim_wand(void); diff --git a/src/cmd3.c b/src/cmd3.c index a80147b6c..cd1a67e0d 100644 --- a/src/cmd3.c +++ b/src/cmd3.c @@ -12,6 +12,14 @@ #include "angband.h" +#include "selfinfo.h" +#include "cmd-activate.h" +#include "cmd-eat.h" +#include "cmd-quaff.h" +#include "cmd-read.h" +#include "cmd-usestaff.h" +#include "cmd-zaprod.h" +#include "cmd-zapwand.h" @@ -2053,3 +2061,183 @@ void do_cmd_query_symbol(void) } +/*! +* @brief オブジェクトをプレイヤーが簡易使用コマンドで利用できるかを判定する / +* Hook to determine if an object is useable +* @param o_ptr 判定したいオブジェクトの構造体参照ポインタ +* @return 利用可能ならばTRUEを返す +*/ +static bool item_tester_hook_use(object_type *o_ptr) +{ + u32b flgs[TR_FLAG_SIZE]; + + /* Ammo */ + if (o_ptr->tval == p_ptr->tval_ammo) + return (TRUE); + + /* Useable object */ + switch (o_ptr->tval) + { + case TV_SPIKE: + case TV_STAFF: + case TV_WAND: + case TV_ROD: + case TV_SCROLL: + case TV_POTION: + case TV_FOOD: + { + return (TRUE); + } + + default: + { + int i; + + /* Not known */ + if (!object_is_known(o_ptr)) return (FALSE); + + /* HACK - only items from the equipment can be activated */ + for (i = INVEN_RARM; i < INVEN_TOTAL; i++) + { + if (&inventory[i] == o_ptr) + { + /* Extract the flags */ + object_flags(o_ptr, flgs); + + /* Check activation flag */ + if (have_flag(flgs, TR_ACTIVATE)) return (TRUE); + } + } + } + } + + /* Assume not */ + return (FALSE); +} + + +/*! + * @brief アイテムを汎用的に「使う」コマンドのメインルーチン / + * Use an item + * @return なし + * @details + * XXX - Add actions for other item types + */ +void do_cmd_use(void) +{ + OBJECT_IDX item; + object_type *o_ptr; + cptr q, s; + + if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) + { + set_action(ACTION_NONE); + } + + item_tester_no_ryoute = TRUE; + /* Prepare the hook */ + item_tester_hook = item_tester_hook_use; + + /* Get an item */ + q = _("どれを使いますか?", "Use which item? "); + s = _("使えるものがありません。", "You have nothing to use."); + + if (!get_item(&item, q, s, (USE_INVEN | USE_EQUIP | USE_FLOOR))) return; + + /* Get the item (in the pack) */ + if (item >= 0) + { + o_ptr = &inventory[item]; + } + /* Get the item (on the floor) */ + else + { + o_ptr = &o_list[0 - item]; + } + + switch (o_ptr->tval) + { + /* Spike a door */ + case TV_SPIKE: + { + do_cmd_spike(); + break; + } + + /* Eat some food */ + case TV_FOOD: + { + do_cmd_eat_food_aux(item); + break; + } + + /* Aim a wand */ + case TV_WAND: + { + do_cmd_aim_wand_aux(item); + break; + } + + /* Use a staff */ + case TV_STAFF: + { + do_cmd_use_staff_aux(item); + break; + } + + /* Zap a rod */ + case TV_ROD: + { + do_cmd_zap_rod_aux(item); + break; + } + + /* Quaff a potion */ + case TV_POTION: + { + do_cmd_quaff_potion_aux(item); + break; + } + + /* Read a scroll */ + case TV_SCROLL: + { + /* Check some conditions */ + if (p_ptr->blind) + { + msg_print(_("目が見えない。", "You can't see anything.")); + return; + } + if (no_lite()) + { + msg_print(_("明かりがないので、暗くて読めない。", "You have no light to read by.")); + return; + } + if (p_ptr->confused) + { + msg_print(_("混乱していて読めない!", "You are too confused!")); + return; + } + + do_cmd_read_scroll_aux(item, TRUE); + break; + } + + /* Fire ammo */ + case TV_SHOT: + case TV_ARROW: + case TV_BOLT: + { + do_cmd_fire_aux(item, &inventory[INVEN_BOW]); + break; + } + + /* Activate an artifact */ + default: + { + do_cmd_activate_aux(item); + break; + } + } +} + diff --git a/src/dungeon.c b/src/dungeon.c index b3e6fdca8..f24b3f4d0 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -13,6 +13,7 @@ #include "angband.h" #include "cmd-activate.h" #include "cmd-eat.h" +#include "cmd-magiceat.h" #include "cmd-quaff.h" #include "cmd-read.h" #include "cmd-usestaff.h" diff --git a/src/externs.h b/src/externs.h index a6114e54e..94459594a 100644 --- a/src/externs.h +++ b/src/externs.h @@ -758,6 +758,7 @@ extern void do_cmd_query_symbol(void); extern void kamaenaoshi(int item); extern bool ang_sort_comp_hook(vptr u, vptr v, int a, int b); extern void ang_sort_swap_hook(vptr u, vptr v, int a, int b); +extern void do_cmd_use(void); /* cmd4.c */ #ifndef JP @@ -803,13 +804,6 @@ extern int calculate_upkeep(void); extern void do_cmd_pet_dismiss(void); extern void do_cmd_pet(void); -/* cmd6.c */ -extern void do_cmd_rerate_aux(void); -extern void do_cmd_rerate(bool display); -extern void ring_of_power(int dir); -extern void do_cmd_use(void); -extern bool do_cmd_magic_eater(bool only_browse, bool powerful); - /* do-spell.c */ extern void stop_singing(void); extern cptr do_spell(REALM_IDX realm, SPELL_IDX spell, BIT_FLAGS mode); @@ -1202,6 +1196,7 @@ extern void discharge_minion(void); extern bool kawarimi(bool success); extern bool rush_attack(bool *mdeath); extern void remove_all_mirrors(bool explode); +extern void ring_of_power(int dir); /* spells3.c */ extern bool teleport_away(MONSTER_IDX m_idx, int dis, BIT_FLAGS mode); @@ -1721,6 +1716,8 @@ extern void spoil_random_artifact(cptr fname); /* wizard2.c */ extern void strip_name(char *buf, KIND_OBJECT_IDX k_idx); +extern void do_cmd_rerate_aux(void); +extern void do_cmd_rerate(bool display); /* avatar.c */ extern bool compare_virtue(int type, int num, int tekitou); diff --git a/src/racial.c b/src/racial.c index b0eccfbec..113209e24 100644 --- a/src/racial.c +++ b/src/racial.c @@ -11,6 +11,7 @@ */ #include "angband.h" +#include "cmd-magiceat.h" #include "cmd-zapwand.h" /*! diff --git a/src/spells2.c b/src/spells2.c index 975e3ff47..1cbf7ba22 100644 --- a/src/spells2.c +++ b/src/spells2.c @@ -4253,3 +4253,72 @@ void remove_all_mirrors(bool explode) } } } + +/*! + * @brief 『一つの指輪』の効果処理 / + * Hack -- activate the ring of power + * @param dir 発動の方向ID + * @return なし + */ +void ring_of_power(int dir) +{ + /* Pick a random effect */ + switch (randint1(10)) + { + case 1: + case 2: + { + /* Message */ + msg_print(_("あなたは悪性のオーラに包み込まれた。", "You are surrounded by a malignant aura.")); + sound(SOUND_EVIL); + + /* Decrease all stats (permanently) */ + (void)dec_stat(A_STR, 50, TRUE); + (void)dec_stat(A_INT, 50, TRUE); + (void)dec_stat(A_WIS, 50, TRUE); + (void)dec_stat(A_DEX, 50, TRUE); + (void)dec_stat(A_CON, 50, TRUE); + (void)dec_stat(A_CHR, 50, TRUE); + + /* Lose some experience (permanently) */ + p_ptr->exp -= (p_ptr->exp / 4); + p_ptr->max_exp -= (p_ptr->exp / 4); + check_experience(); + + break; + } + + case 3: + { + /* Message */ + msg_print(_("あなたは強力なオーラに包み込まれた。", "You are surrounded by a powerful aura.")); + + /* Dispel monsters */ + dispel_monsters(1000); + + break; + } + + case 4: + case 5: + case 6: + { + /* Mana Ball */ + fire_ball(GF_MANA, dir, 600, 3); + + break; + } + + case 7: + case 8: + case 9: + case 10: + { + /* Mana Bolt */ + fire_bolt(GF_MANA, dir, 500); + + break; + } + } +} + diff --git a/src/store.c b/src/store.c index 25b2e3d71..cb8330061 100644 --- a/src/store.c +++ b/src/store.c @@ -12,6 +12,7 @@ #include "angband.h" #include "cmd-zapwand.h" +#include "cmd-magiceat.h" #define MIN_STOCK 12 -- 2.11.0