OSDN Git Service

[Refactor] #39068 choose_object() の item_tester_tval グローバル参照をローカル引数に収める.(一部バグを起こしている可...
[hengband/hengband.git] / src / cmd-zapwand.c
index 3e7e3a0..01cf109 100644 (file)
@@ -1,5 +1,18 @@
 #include "angband.h"
-
+#include "util.h"
+
+#include "avatar.h"
+#include "spells.h"
+#include "spells-status.h"
+#include "player-status.h"
+#include "player-effects.h"
+#include "player-class.h"
+#include "objectkind.h"
+#include "object-hook.h"
+#include "cmd-basic.h"
+#include "floor.h"
+#include "targeting.h"
+#include "view-mainwindow.h"
 
 /*!
 * @brief 魔法棒の効果を発動する
@@ -9,9 +22,9 @@
 * @param magic 魔道具術上の処理ならばTRUE
 * @return 発動により効果内容が確定したならばTRUEを返す
 */
-int wand_effect(OBJECT_SUBTYPE_VALUE sval, DIRECTION dir, bool powerful, bool magic)
+bool wand_effect(OBJECT_SUBTYPE_VALUE sval, DIRECTION dir, bool powerful, bool magic)
 {
-       int ident = FALSE;
+       bool ident = FALSE;
        PLAYER_LEVEL lev = powerful ? p_ptr->lev * 2 : p_ptr->lev;
        POSITION rad = powerful ? 3 : 2;
 
@@ -41,253 +54,253 @@ int wand_effect(OBJECT_SUBTYPE_VALUE sval, DIRECTION dir, bool powerful, bool ma
        /* 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_HEAL_MONSTER:
+               {
+                       HIT_POINT dam = damroll((powerful ? 20 : 10), 10);
+                       if (heal_monster(dir, dam)) ident = TRUE;
+                       break;
+               }
 
-       case SV_WAND_DISARMING:
-       {
-               if (disarm_trap(dir)) ident = TRUE;
-               if (powerful && disarm_traps_touch()) ident = TRUE;
-               break;
-       }
+               case SV_WAND_HASTE_MONSTER:
+               {
+                       if (speed_monster(dir, lev)) 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_CLONE_MONSTER:
+               {
+                       if (clone_monster(dir)) 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_TELEPORT_AWAY:
+               {
+                       int distance = MAX_SIGHT * (powerful ? 8 : 5);
+                       if (teleport_monster(dir, distance)) ident = TRUE;
+                       break;
+               }
 
-       case SV_WAND_LITE:
-       {
-               HIT_POINT dam = damroll((powerful ? 12 : 6), 8);
-               msg_print(_("青く輝く光線が放たれた。", "A line of blue shimmering light appears."));
-               (void)lite_line(dir, dam);
-               ident = TRUE;
-               break;
-       }
+               case SV_WAND_DISARMING:
+               {
+                       if (disarm_trap(dir)) ident = TRUE;
+                       if (powerful && disarm_traps_touch()) ident = TRUE;
+                       break;
+               }
 
-       case SV_WAND_SLEEP_MONSTER:
-       {
-               if (sleep_monster(dir, lev)) 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_SLOW_MONSTER:
-       {
-               if (slow_monster(dir, lev)) 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_CONFUSE_MONSTER:
-       {
-               if (confuse_monster(dir, lev)) ident = TRUE;
-               break;
-       }
+               case SV_WAND_LITE:
+               {
+                       HIT_POINT dam = damroll((powerful ? 12 : 6), 8);
+                       msg_print(_("青く輝く光線が放たれた。", "A line of blue shimmering light appears."));
+                       (void)lite_line(dir, dam);
+                       ident = TRUE;
+                       break;
+               }
 
-       case SV_WAND_FEAR_MONSTER:
-       {
-               if (fear_monster(dir, lev)) ident = TRUE;
-               break;
-       }
+               case SV_WAND_SLEEP_MONSTER:
+               {
+                       if (sleep_monster(dir, lev)) ident = TRUE;
+                       break;
+               }
 
-       case SV_WAND_HYPODYNAMIA:
-       {
-               if (hypodynamic_bolt(dir, 80 + lev)) ident = TRUE;
-               break;
-       }
+               case SV_WAND_SLOW_MONSTER:
+               {
+                       if (slow_monster(dir, lev)) ident = TRUE;
+                       break;
+               }
 
-       case SV_WAND_POLYMORPH:
-       {
-               if (poly_monster(dir, lev)) ident = TRUE;
-               break;
-       }
+               case SV_WAND_CONFUSE_MONSTER:
+               {
+                       if (confuse_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_FEAR_MONSTER:
+               {
+                       if (fear_monster(dir, lev)) 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_HYPODYNAMIA:
+               {
+                       if (hypodynamic_bolt(dir, 80 + lev)) 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_POLYMORPH:
+               {
+                       if (poly_monster(dir, lev)) ident = TRUE;
+                       break;
+               }
 
-       case SV_WAND_CHARM_MONSTER:
-       {
-               if (charm_monster(dir, MAX(20, lev)))
+               case SV_WAND_STINKING_CLOUD:
+               {
+                       fire_ball(GF_POIS, dir, 12 + lev / 4, rad);
                        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;
-       }
+                       break;
+               }
 
-       case SV_WAND_ELEC_BALL:
-       {
-               fire_ball(GF_ELEC, dir, 40 + 3 * 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_FIRE_BALL:
-       {
-               fire_ball(GF_FIRE, dir, 70 + 3 * lev / 4, rad);
-               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_COLD_BALL:
-       {
-               fire_ball(GF_COLD, dir, 50 + 3 * lev / 4, rad);
-               ident = TRUE;
-               break;
-       }
+               case SV_WAND_CHARM_MONSTER:
+               {
+                       if (charm_monster(dir, MAX(20, lev)))
+                               ident = TRUE;
+                       break;
+               }
 
-       case SV_WAND_WONDER:
-       {
-               msg_print(_("おっと、謎の魔法棒を始動させた。", "Oops.  Wand of wonder activated."));
-               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_DRAGON_FIRE:
-       {
-               fire_breath(GF_FIRE, dir, (powerful ? 300 : 200), 3);
-               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_DRAGON_COLD:
-       {
-               fire_breath(GF_COLD, dir, (powerful ? 270 : 180), 3);
-               ident = TRUE;
-               break;
-       }
+               case SV_WAND_ACID_BALL:
+               {
+                       fire_ball(GF_ACID, dir, 60 + 3 * lev / 4, rad);
+                       ident = TRUE;
+                       break;
+               }
 
-       case SV_WAND_DRAGON_BREATH:
-       {
-               HIT_POINT dam;
-               EFFECT_ID typ;
+               case SV_WAND_ELEC_BALL:
+               {
+                       fire_ball(GF_ELEC, dir, 40 + 3 * lev / 4, rad);
+                       ident = TRUE;
+                       break;
+               }
 
-               switch (randint1(5))
+               case SV_WAND_FIRE_BALL:
                {
-               case 1:
-                       dam = 240;
-                       typ = GF_ACID;
+                       fire_ball(GF_FIRE, dir, 70 + 3 * lev / 4, rad);
+                       ident = TRUE;
                        break;
-               case 2:
-                       dam = 210;
-                       typ = GF_ELEC;
+               }
+
+               case SV_WAND_COLD_BALL:
+               {
+                       fire_ball(GF_COLD, dir, 50 + 3 * lev / 4, rad);
+                       ident = TRUE;
                        break;
-               case 3:
-                       dam = 240;
-                       typ = GF_FIRE;
+               }
+
+               case SV_WAND_WONDER:
+               {
+                       msg_print(_("おっと、謎の魔法棒を始動させた。", "Oops.  Wand of wonder activated."));
                        break;
-               case 4:
-                       dam = 210;
-                       typ = GF_COLD;
+               }
+
+               case SV_WAND_DRAGON_FIRE:
+               {
+                       fire_breath(GF_FIRE, dir, (powerful ? 300 : 200), 3);
+                       ident = TRUE;
                        break;
-               default:
-                       dam = 180;
-                       typ = GF_POIS;
+               }
+
+               case SV_WAND_DRAGON_COLD:
+               {
+                       fire_breath(GF_COLD, dir, (powerful ? 270 : 180), 3);
+                       ident = TRUE;
                        break;
                }
 
-               if (powerful) dam = (dam * 3) / 2;
+               case SV_WAND_DRAGON_BREATH:
+               {
+                       HIT_POINT dam;
+                       EFFECT_ID typ;
 
-               fire_breath(typ, dir, dam, 3);
+                       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;
+                       }
 
-               ident = TRUE;
-               break;
-       }
+                       if (powerful) dam = (dam * 3) / 2;
 
-       case SV_WAND_DISINTEGRATE:
-       {
-               fire_ball(GF_DISINTEGRATE, dir, 200 + randint1(lev * 2), rad);
-               ident = TRUE;
-               break;
-       }
+                       fire_breath(typ, dir, dam, 3);
 
-       case SV_WAND_ROCKETS:
-       {
-               msg_print(_("ロケットを発射した!", "You launch a rocket!"));
-               fire_rocket(GF_ROCKET, dir, 250 + lev * 3, rad);
-               ident = TRUE;
-               break;
-       }
+                       ident = TRUE;
+                       break;
+               }
 
-       case SV_WAND_STRIKING:
-       {
-               fire_bolt(GF_METEOR, dir, damroll(15 + lev / 3, 13));
-               ident = TRUE;
-               break;
-       }
+               case SV_WAND_DISINTEGRATE:
+               {
+                       fire_ball(GF_DISINTEGRATE, dir, 200 + randint1(lev * 2), rad);
+                       ident = TRUE;
+                       break;
+               }
 
-       case SV_WAND_GENOCIDE:
-       {
-               fire_ball_hide(GF_GENOCIDE, dir, magic ? lev + 50 : 250, 0);
-               ident = TRUE;
-               break;
-       }
+               case SV_WAND_ROCKETS:
+               {
+                       msg_print(_("ロケットを発射した!", "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;
 }
@@ -303,7 +316,7 @@ int wand_effect(OBJECT_SUBTYPE_VALUE sval, DIRECTION dir, bool powerful, bool ma
 * 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
+* There are no wands which can "destroy" themselves, in the p_ptr->inventory_list
 * 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.
@@ -315,20 +328,22 @@ int wand_effect(OBJECT_SUBTYPE_VALUE sval, DIRECTION dir, bool powerful, bool ma
 */
 void do_cmd_aim_wand_aux(INVENTORY_IDX item)
 {
-       int         lev, ident, chance, dir;
+       DEPTH lev;
+       int ident, chance;
+       DIRECTION dir;
        object_type *o_ptr;
        bool old_target_pet = target_pet;
 
        /* Get the item (in the pack) */
        if (item >= 0)
        {
-               o_ptr = &inventory[item];
+               o_ptr = &p_ptr->inventory_list[item];
        }
 
        /* Get the item (on the floor) */
        else
        {
-               o_ptr = &o_list[0 - item];
+               o_ptr = &current_floor_ptr->o_list[0 - item];
        }
 
        /* Mega-Hack -- refuse to aim a pile from the ground */
@@ -350,7 +365,7 @@ void do_cmd_aim_wand_aux(INVENTORY_IDX item)
        }
        target_pet = old_target_pet;
 
-       p_ptr->energy_use = 100;
+       take_turn(p_ptr, 100);
 
        /* Get the level */
        lev = k_info[o_ptr->k_idx].level;
@@ -371,13 +386,7 @@ void do_cmd_aim_wand_aux(INVENTORY_IDX item)
                chance = USE_DEVICE;
        }
 
-       if (world_player)
-       {
-               if (flush_failure) flush();
-               msg_print(_("止まった時の中ではうまく働かないようだ。", "Nothing happen. Maybe this wand is freezing too."));
-               sound(SOUND_FAIL);
-               return;
-       }
+       if (cmd_limit_time_walk(p_ptr)) return;
 
        /* Roll for usage */
        if ((chance < USE_DEVICE) || (randint1(chance) < USE_DEVICE) || (p_ptr->pclass == CLASS_BERSERKER))
@@ -394,9 +403,7 @@ void do_cmd_aim_wand_aux(INVENTORY_IDX item)
                if (flush_failure) flush();
                msg_print(_("この魔法棒にはもう魔力が残っていない。", "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->update |= (PU_COMBINE | PU_REORDER);
                p_ptr->window |= (PW_INVEN);
 
                return;
@@ -405,9 +412,7 @@ void do_cmd_aim_wand_aux(INVENTORY_IDX item)
        sound(SOUND_ZAP);
 
        ident = wand_effect(o_ptr->sval, dir, FALSE, FALSE);
-
-       /* Combine / Reorder the pack (later) */
-       p_ptr->notice |= (PN_COMBINE | PN_REORDER);
+       p_ptr->update |= (PU_COMBINE | PU_REORDER);
 
        if (!(object_is_aware(o_ptr)))
        {
@@ -452,22 +457,18 @@ void do_cmd_aim_wand_aux(INVENTORY_IDX item)
 void do_cmd_aim_wand(void)
 {
        OBJECT_IDX item;
-       cptr    q, s;
-
-       /* Restrict choices to wands */
-       item_tester_tval = TV_WAND;
+       concptr q, s;
 
+       if (p_ptr->wild_mode) return;
+       if (cmd_limit_arena(p_ptr)) return;
        if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN))
        {
                set_action(ACTION_NONE);
        }
 
-       /* Get an item */
        q = _("どの魔法棒で狙いますか? ", "Aim which wand? ");
        s = _("使える魔法棒がない。", "You have no wand to aim.");
+       if (!choose_object(&item, q, s, (USE_INVEN | USE_FLOOR), TV_WAND)) return;
 
-       if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
-
-       /* Aim the wand */
        do_cmd_aim_wand_aux(item);
 }