OSDN Git Service

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