OSDN Git Service

[Refactor] #40571 Moved targeting.c/h from io/ to target/
[hengband/hengband.git] / src / cmd-item / cmd-zapwand.c
1 #include "cmd-item/cmd-zapwand.h"
2 #include "action/action-limited.h"
3 #include "core/player-update-types.h"
4 #include "core/window-redrawer.h"
5 #include "floor/floor-object.h"
6 #include "floor/floor.h"
7 #include "game-option/disturbance-options.h"
8 #include "game-option/input-options.h"
9 #include "inventory/player-inventory.h"
10 #include "main/sound-definitions-table.h"
11 #include "main/sound-of-music.h"
12 #include "object-enchant/special-object-flags.h"
13 #include "object/item-use-flags.h"
14 #include "object/object-info.h"
15 #include "object/object-kind.h"
16 #include "perception/object-perception.h"
17 #include "player/attack-defense-types.h"
18 #include "player/avatar.h"
19 #include "player/player-class.h"
20 #include "player/player-status.h"
21 #include "player/special-defense-types.h"
22 #include "spell-kind/spells-beam.h"
23 #include "spell-kind/spells-charm.h"
24 #include "spell-kind/spells-launcher.h"
25 #include "spell-kind/spells-lite.h"
26 #include "spell-kind/spells-neighbor.h"
27 #include "spell-kind/spells-specific-bolt.h"
28 #include "spell-kind/spells-teleport.h"
29 #include "spell/spell-types.h"
30 #include "spell/spells-status.h"
31 #include "status/action-setter.h"
32 #include "status/experience.h"
33 #include "sv-definition/sv-wand-types.h"
34 #include "target/targeting.h"
35 #include "term/screen-processor.h"
36 #include "view/display-messages.h"
37 #include "view/object-describer.h"
38
39 /*!
40  * @brief 魔法棒の効果を発動する
41  * @param creature_ptr プレーヤーへの参照ポインタ
42  * @param sval オブジェクトのsval
43  * @param dir 発動の方向ID
44  * @param powerful 強力発動上の処理ならばTRUE
45  * @param magic 魔道具術上の処理ならばTRUE
46  * @return 発動により効果内容が確定したならばTRUEを返す
47  */
48 bool wand_effect(player_type *creature_ptr, OBJECT_SUBTYPE_VALUE sval, DIRECTION dir, bool powerful, bool magic)
49 {
50     bool ident = FALSE;
51     PLAYER_LEVEL lev = powerful ? creature_ptr->lev * 2 : creature_ptr->lev;
52     POSITION rad = powerful ? 3 : 2;
53
54     /* XXX Hack -- Wand of wonder can do anything before it */
55     if (sval == SV_WAND_WONDER) {
56         int vir = virtue_number(creature_ptr, V_CHANCE);
57         sval = (OBJECT_SUBTYPE_VALUE)randint0(SV_WAND_WONDER);
58
59         if (vir) {
60             if (creature_ptr->virtues[vir - 1] > 0) {
61                 while (randint1(300) < creature_ptr->virtues[vir - 1])
62                     sval++;
63                 if (sval > SV_WAND_COLD_BALL)
64                     sval = randint0(4) + SV_WAND_ACID_BALL;
65             } else {
66                 while (randint1(300) < (0 - creature_ptr->virtues[vir - 1]))
67                     sval--;
68                 if (sval < SV_WAND_HEAL_MONSTER)
69                     sval = randint0(3) + SV_WAND_HEAL_MONSTER;
70             }
71         }
72         if (sval < SV_WAND_TELEPORT_AWAY)
73             chg_virtue(creature_ptr, V_CHANCE, 1);
74     }
75
76     /* Analyze the wand */
77     switch (sval) {
78     case SV_WAND_HEAL_MONSTER: {
79         HIT_POINT dam = damroll((powerful ? 20 : 10), 10);
80         if (heal_monster(creature_ptr, dir, dam))
81             ident = TRUE;
82         break;
83     }
84
85     case SV_WAND_HASTE_MONSTER: {
86         if (speed_monster(creature_ptr, dir, lev))
87             ident = TRUE;
88         break;
89     }
90
91     case SV_WAND_CLONE_MONSTER: {
92         if (clone_monster(creature_ptr, dir))
93             ident = TRUE;
94         break;
95     }
96
97     case SV_WAND_TELEPORT_AWAY: {
98         int distance = MAX_SIGHT * (powerful ? 8 : 5);
99         if (teleport_monster(creature_ptr, dir, distance))
100             ident = TRUE;
101         break;
102     }
103
104     case SV_WAND_DISARMING: {
105         if (disarm_trap(creature_ptr, dir))
106             ident = TRUE;
107         if (powerful && disarm_traps_touch(creature_ptr))
108             ident = TRUE;
109         break;
110     }
111
112     case SV_WAND_TRAP_DOOR_DEST: {
113         if (destroy_door(creature_ptr, dir))
114             ident = TRUE;
115         if (powerful && destroy_doors_touch(creature_ptr))
116             ident = TRUE;
117         break;
118     }
119
120     case SV_WAND_STONE_TO_MUD: {
121         HIT_POINT dam = powerful ? 40 + randint1(60) : 20 + randint1(30);
122         if (wall_to_mud(creature_ptr, dir, dam))
123             ident = TRUE;
124         break;
125     }
126
127     case SV_WAND_LITE: {
128         HIT_POINT dam = damroll((powerful ? 12 : 6), 8);
129         msg_print(_("青く輝く光線が放たれた。", "A line of blue shimmering light appears."));
130         (void)lite_line(creature_ptr, dir, dam);
131         ident = TRUE;
132         break;
133     }
134
135     case SV_WAND_SLEEP_MONSTER: {
136         if (sleep_monster(creature_ptr, dir, lev))
137             ident = TRUE;
138         break;
139     }
140
141     case SV_WAND_SLOW_MONSTER: {
142         if (slow_monster(creature_ptr, dir, lev))
143             ident = TRUE;
144         break;
145     }
146
147     case SV_WAND_CONFUSE_MONSTER: {
148         if (confuse_monster(creature_ptr, dir, lev))
149             ident = TRUE;
150         break;
151     }
152
153     case SV_WAND_FEAR_MONSTER: {
154         if (fear_monster(creature_ptr, dir, lev))
155             ident = TRUE;
156         break;
157     }
158
159     case SV_WAND_HYPODYNAMIA: {
160         if (hypodynamic_bolt(creature_ptr, dir, 80 + lev))
161             ident = TRUE;
162         break;
163     }
164
165     case SV_WAND_POLYMORPH: {
166         if (poly_monster(creature_ptr, dir, lev))
167             ident = TRUE;
168         break;
169     }
170
171     case SV_WAND_STINKING_CLOUD: {
172         fire_ball(creature_ptr, GF_POIS, dir, 12 + lev / 4, rad);
173         ident = TRUE;
174         break;
175     }
176
177     case SV_WAND_MAGIC_MISSILE: {
178         fire_bolt_or_beam(creature_ptr, 20, GF_MISSILE, dir, damroll(2 + lev / 10, 6));
179         ident = TRUE;
180         break;
181     }
182
183     case SV_WAND_ACID_BOLT: {
184         fire_bolt_or_beam(creature_ptr, 20, GF_ACID, dir, damroll(6 + lev / 7, 8));
185         ident = TRUE;
186         break;
187     }
188
189     case SV_WAND_CHARM_MONSTER: {
190         if (charm_monster(creature_ptr, dir, MAX(20, lev)))
191             ident = TRUE;
192         break;
193     }
194
195     case SV_WAND_FIRE_BOLT: {
196         fire_bolt_or_beam(creature_ptr, 20, GF_FIRE, dir, damroll(7 + lev / 6, 8));
197         ident = TRUE;
198         break;
199     }
200
201     case SV_WAND_COLD_BOLT: {
202         fire_bolt_or_beam(creature_ptr, 20, GF_COLD, dir, damroll(5 + lev / 8, 8));
203         ident = TRUE;
204         break;
205     }
206
207     case SV_WAND_ACID_BALL: {
208         fire_ball(creature_ptr, GF_ACID, dir, 60 + 3 * lev / 4, rad);
209         ident = TRUE;
210         break;
211     }
212
213     case SV_WAND_ELEC_BALL: {
214         fire_ball(creature_ptr, GF_ELEC, dir, 40 + 3 * lev / 4, rad);
215         ident = TRUE;
216         break;
217     }
218
219     case SV_WAND_FIRE_BALL: {
220         fire_ball(creature_ptr, GF_FIRE, dir, 70 + 3 * lev / 4, rad);
221         ident = TRUE;
222         break;
223     }
224
225     case SV_WAND_COLD_BALL: {
226         fire_ball(creature_ptr, GF_COLD, dir, 50 + 3 * lev / 4, rad);
227         ident = TRUE;
228         break;
229     }
230
231     case SV_WAND_WONDER: {
232         msg_print(_("おっと、謎の魔法棒を始動させた。", "Oops.  Wand of wonder activated."));
233         break;
234     }
235
236     case SV_WAND_DRAGON_FIRE: {
237         fire_breath(creature_ptr, GF_FIRE, dir, (powerful ? 300 : 200), 3);
238         ident = TRUE;
239         break;
240     }
241
242     case SV_WAND_DRAGON_COLD: {
243         fire_breath(creature_ptr, GF_COLD, dir, (powerful ? 270 : 180), 3);
244         ident = TRUE;
245         break;
246     }
247
248     case SV_WAND_DRAGON_BREATH: {
249         HIT_POINT dam;
250         EFFECT_ID typ;
251
252         switch (randint1(5)) {
253         case 1:
254             dam = 240;
255             typ = GF_ACID;
256             break;
257         case 2:
258             dam = 210;
259             typ = GF_ELEC;
260             break;
261         case 3:
262             dam = 240;
263             typ = GF_FIRE;
264             break;
265         case 4:
266             dam = 210;
267             typ = GF_COLD;
268             break;
269         default:
270             dam = 180;
271             typ = GF_POIS;
272             break;
273         }
274
275         if (powerful)
276             dam = (dam * 3) / 2;
277
278         fire_breath(creature_ptr, typ, dir, dam, 3);
279
280         ident = TRUE;
281         break;
282     }
283
284     case SV_WAND_DISINTEGRATE: {
285         fire_ball(creature_ptr, GF_DISINTEGRATE, dir, 200 + randint1(lev * 2), rad);
286         ident = TRUE;
287         break;
288     }
289
290     case SV_WAND_ROCKETS: {
291         msg_print(_("ロケットを発射した!", "You launch a rocket!"));
292         fire_rocket(creature_ptr, GF_ROCKET, dir, 250 + lev * 3, rad);
293         ident = TRUE;
294         break;
295     }
296
297     case SV_WAND_STRIKING: {
298         fire_bolt(creature_ptr, GF_METEOR, dir, damroll(15 + lev / 3, 13));
299         ident = TRUE;
300         break;
301     }
302
303     case SV_WAND_GENOCIDE: {
304         fire_ball_hide(creature_ptr, GF_GENOCIDE, dir, magic ? lev + 50 : 250, 0);
305         ident = TRUE;
306         break;
307     }
308     }
309     return ident;
310 }
311
312 /*!
313  * @brief 魔法棒を使うコマンドのサブルーチン /
314  * Aim a wand (from the pack or floor).
315  * @param item 使うオブジェクトの所持品ID
316  * @return なし
317  * @details
318  * <pre>
319  * Use a single charge from a single item.
320  * Handle "unstacking" in a logical manner.
321  * For simplicity, you cannot use a stack of items from the
322  * ground.  This would require too much nasty code.
323  * There are no wands which can "destroy" themselves, in the inventory
324  * or on the ground, so we can ignore this possibility.  Note that this
325  * required giving "wand of wonder" the ability to ignore destruction
326  * by electric balls.
327  * All wands can be "cancelled" at the "Direction?" prompt for free.
328  * Note that the basic "bolt" wands do slightly less damage than the
329  * basic "bolt" rods, but the basic "ball" wands do the same damage
330  * as the basic "ball" rods.
331  * </pre>
332  */
333 void exe_aim_wand(player_type *creature_ptr, INVENTORY_IDX item)
334 {
335     DEPTH lev;
336     int ident, chance;
337     DIRECTION dir;
338     object_type *o_ptr;
339     bool old_target_pet = target_pet;
340
341     o_ptr = ref_item(creature_ptr, item);
342
343     /* Mega-Hack -- refuse to aim a pile from the ground */
344     if ((item < 0) && (o_ptr->number > 1)) {
345         msg_print(_("まずは魔法棒を拾わなければ。", "You must first pick up the wands."));
346         return;
347     }
348
349     /* Allow direction to be cancelled for free */
350     if (object_is_aware(o_ptr) && (o_ptr->sval == SV_WAND_HEAL_MONSTER || o_ptr->sval == SV_WAND_HASTE_MONSTER))
351         target_pet = TRUE;
352     if (!get_aim_dir(creature_ptr, &dir)) {
353         target_pet = old_target_pet;
354         return;
355     }
356     target_pet = old_target_pet;
357
358     take_turn(creature_ptr, 100);
359
360     /* Get the level */
361     lev = k_info[o_ptr->k_idx].level;
362     if (lev > 50)
363         lev = 50 + (lev - 50) / 2;
364
365     /* Base chance of success */
366     chance = creature_ptr->skill_dev;
367
368     /* Confusion hurts skill */
369     if (creature_ptr->confused)
370         chance = chance / 2;
371
372     /* Hight level objects are harder */
373     chance = chance - lev;
374
375     /* Give everyone a (slight) chance */
376     if ((chance < USE_DEVICE) && one_in_(USE_DEVICE - chance + 1)) {
377         chance = USE_DEVICE;
378     }
379
380     if (cmd_limit_time_walk(creature_ptr))
381         return;
382
383     /* Roll for usage */
384     if ((chance < USE_DEVICE) || (randint1(chance) < USE_DEVICE) || (creature_ptr->pclass == CLASS_BERSERKER)) {
385         if (flush_failure)
386             flush();
387         msg_print(_("魔法棒をうまく使えなかった。", "You failed to use the wand properly."));
388         sound(SOUND_FAIL);
389         return;
390     }
391
392     /* The wand is already empty! */
393     if (o_ptr->pval <= 0) {
394         if (flush_failure)
395             flush();
396         msg_print(_("この魔法棒にはもう魔力が残っていない。", "The wand has no charges left."));
397         o_ptr->ident |= (IDENT_EMPTY);
398         creature_ptr->update |= (PU_COMBINE | PU_REORDER);
399         creature_ptr->window |= (PW_INVEN);
400
401         return;
402     }
403
404     sound(SOUND_ZAP);
405
406     ident = wand_effect(creature_ptr, o_ptr->sval, dir, FALSE, FALSE);
407
408     /*
409      * Temporarily remove the flags for updating the inventory so
410      * gain_exp() does not reorder the inventory before the charge
411      * is deducted from the wand.
412      */
413     BIT_FLAGS inventory_flags = (PU_COMBINE | PU_REORDER | (creature_ptr->update & PU_AUTODESTROY));
414     creature_ptr->update &= ~(PU_COMBINE | PU_REORDER | PU_AUTODESTROY);
415
416     if (!(object_is_aware(o_ptr))) {
417         chg_virtue(creature_ptr, V_PATIENCE, -1);
418         chg_virtue(creature_ptr, V_CHANCE, 1);
419         chg_virtue(creature_ptr, V_KNOWLEDGE, -1);
420     }
421
422     /* Mark it as tried */
423     object_tried(o_ptr);
424
425     /* Apply identification */
426     if (ident && !object_is_aware(o_ptr)) {
427         object_aware(creature_ptr, o_ptr);
428         gain_exp(creature_ptr, (lev + (creature_ptr->lev >> 1)) / creature_ptr->lev);
429     }
430
431     creature_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
432     creature_ptr->update |= inventory_flags;
433
434     /* Use a single charge */
435     o_ptr->pval--;
436
437     if (item >= 0) {
438         inven_item_charges(creature_ptr, item);
439         return;
440     }
441
442     floor_item_charges(creature_ptr->current_floor_ptr, 0 - item);
443 }
444
445 /*!
446  * @brief 魔法棒を使うコマンドのメインルーチン /
447  * @return なし
448  */
449 void do_cmd_aim_wand(player_type *creature_ptr)
450 {
451     OBJECT_IDX item;
452     concptr q, s;
453
454     if (creature_ptr->wild_mode)
455         return;
456     if (cmd_limit_arena(creature_ptr))
457         return;
458     if (creature_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) {
459         set_action(creature_ptr, ACTION_NONE);
460     }
461
462     q = _("どの魔法棒で狙いますか? ", "Aim which wand? ");
463     s = _("使える魔法棒がない。", "You have no wand to aim.");
464     if (!choose_object(creature_ptr, &item, q, s, (USE_INVEN | USE_FLOOR), TV_WAND))
465         return;
466
467     exe_aim_wand(creature_ptr, item);
468 }