OSDN Git Service

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