OSDN Git Service

[Refactor] enum spells-typeをenum class AttributeTypeに置換
[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-use/zapwand-execution.h"
14 #include "object/item-tester-hooker.h"
15 #include "object/item-use-flags.h"
16 #include "object/object-info.h"
17 #include "object/object-kind.h"
18 #include "perception/object-perception.h"
19 #include "player-base/player-class.h"
20 #include "player-info/class-info.h"
21 #include "player-info/samurai-data-type.h"
22 #include "player-status/player-energy.h"
23 #include "player/attack-defense-types.h"
24 #include "player/special-defense-types.h"
25 #include "spell-kind/spells-beam.h"
26 #include "spell-kind/spells-charm.h"
27 #include "spell-kind/spells-launcher.h"
28 #include "spell-kind/spells-lite.h"
29 #include "spell-kind/spells-neighbor.h"
30 #include "spell-kind/spells-specific-bolt.h"
31 #include "spell-kind/spells-teleport.h"
32 #include "effect/attribute-types.h"
33 #include "spell/spells-status.h"
34 #include "status/action-setter.h"
35 #include "status/experience.h"
36 #include "sv-definition/sv-wand-types.h"
37 #include "system/object-type-definition.h"
38 #include "system/player-type-definition.h"
39 #include "target/target-getter.h"
40 #include "term/screen-processor.h"
41 #include "util/bit-flags-calculator.h"
42 #include "view/display-messages.h"
43 #include "view/object-describer.h"
44
45 /*!
46  * @brief 魔法棒の効果を発動する
47  * @param player_ptr プレイヤーへの参照ポインタ
48  * @param sval オブジェクトのsval
49  * @param dir 発動の方向ID
50  * @param powerful 強力発動上の処理ならばTRUE
51  * @param magic 魔道具術上の処理ならばTRUE
52  * @return 発動により効果内容が確定したならばTRUEを返す
53  */
54 bool wand_effect(player_type *player_ptr, OBJECT_SUBTYPE_VALUE sval, DIRECTION dir, bool powerful, bool magic)
55 {
56     bool ident = false;
57     PLAYER_LEVEL lev = powerful ? player_ptr->lev * 2 : player_ptr->lev;
58     POSITION rad = powerful ? 3 : 2;
59
60     /* XXX Hack -- Wand of wonder can do anything before it */
61     if (sval == SV_WAND_WONDER) {
62         int vir = virtue_number(player_ptr, V_CHANCE);
63         sval = (OBJECT_SUBTYPE_VALUE)randint0(SV_WAND_WONDER);
64
65         if (vir) {
66             if (player_ptr->virtues[vir - 1] > 0) {
67                 while (randint1(300) < player_ptr->virtues[vir - 1])
68                     sval++;
69                 if (sval > SV_WAND_COLD_BALL)
70                     sval = randint0(4) + SV_WAND_ACID_BALL;
71             } else {
72                 while (randint1(300) < (0 - player_ptr->virtues[vir - 1]))
73                     sval--;
74                 if (sval < SV_WAND_HEAL_MONSTER)
75                     sval = randint0(3) + SV_WAND_HEAL_MONSTER;
76             }
77         }
78         if (sval < SV_WAND_TELEPORT_AWAY)
79             chg_virtue(player_ptr, V_CHANCE, 1);
80     }
81
82     /* Analyze the wand */
83     switch (sval) {
84     case SV_WAND_HEAL_MONSTER: {
85         HIT_POINT dam = damroll((powerful ? 20 : 10), 10);
86         if (heal_monster(player_ptr, dir, dam))
87             ident = true;
88         break;
89     }
90
91     case SV_WAND_HASTE_MONSTER: {
92         if (speed_monster(player_ptr, dir, lev))
93             ident = true;
94         break;
95     }
96
97     case SV_WAND_CLONE_MONSTER: {
98         if (clone_monster(player_ptr, dir))
99             ident = true;
100         break;
101     }
102
103     case SV_WAND_TELEPORT_AWAY: {
104         int distance = MAX_SIGHT * (powerful ? 8 : 5);
105         if (teleport_monster(player_ptr, dir, distance))
106             ident = true;
107         break;
108     }
109
110     case SV_WAND_DISARMING: {
111         if (disarm_trap(player_ptr, dir))
112             ident = true;
113         if (powerful && disarm_traps_touch(player_ptr))
114             ident = true;
115         break;
116     }
117
118     case SV_WAND_TRAP_DOOR_DEST: {
119         if (destroy_door(player_ptr, dir))
120             ident = true;
121         if (powerful && destroy_doors_touch(player_ptr))
122             ident = true;
123         break;
124     }
125
126     case SV_WAND_STONE_TO_MUD: {
127         HIT_POINT dam = powerful ? 40 + randint1(60) : 20 + randint1(30);
128         if (wall_to_mud(player_ptr, dir, dam))
129             ident = true;
130         break;
131     }
132
133     case SV_WAND_LITE: {
134         HIT_POINT dam = damroll((powerful ? 12 : 6), 8);
135         msg_print(_("青く輝く光線が放たれた。", "A line of blue shimmering light appears."));
136         (void)lite_line(player_ptr, dir, dam);
137         ident = true;
138         break;
139     }
140
141     case SV_WAND_SLEEP_MONSTER: {
142         if (sleep_monster(player_ptr, dir, lev))
143             ident = true;
144         break;
145     }
146
147     case SV_WAND_SLOW_MONSTER: {
148         if (slow_monster(player_ptr, dir, lev))
149             ident = true;
150         break;
151     }
152
153     case SV_WAND_CONFUSE_MONSTER: {
154         if (confuse_monster(player_ptr, dir, lev))
155             ident = true;
156         break;
157     }
158
159     case SV_WAND_FEAR_MONSTER: {
160         if (fear_monster(player_ptr, dir, lev))
161             ident = true;
162         break;
163     }
164
165     case SV_WAND_HYPODYNAMIA: {
166         if (hypodynamic_bolt(player_ptr, dir, 80 + lev))
167             ident = true;
168         break;
169     }
170
171     case SV_WAND_POLYMORPH: {
172         if (poly_monster(player_ptr, dir, lev))
173             ident = true;
174         break;
175     }
176
177     case SV_WAND_STINKING_CLOUD: {
178         fire_ball(player_ptr, AttributeType::POIS, dir, 12 + lev / 4, rad);
179         ident = true;
180         break;
181     }
182
183     case SV_WAND_MAGIC_MISSILE: {
184         fire_bolt_or_beam(player_ptr, 20, AttributeType::MISSILE, dir, damroll(2 + lev / 10, 6));
185         ident = true;
186         break;
187     }
188
189     case SV_WAND_ACID_BOLT: {
190         fire_bolt_or_beam(player_ptr, 20, AttributeType::ACID, dir, damroll(6 + lev / 7, 8));
191         ident = true;
192         break;
193     }
194
195     case SV_WAND_CHARM_MONSTER: {
196         if (charm_monster(player_ptr, dir, std::max<short>(20, lev)))
197             ident = true;
198         break;
199     }
200
201     case SV_WAND_FIRE_BOLT: {
202         fire_bolt_or_beam(player_ptr, 20, AttributeType::FIRE, dir, damroll(7 + lev / 6, 8));
203         ident = true;
204         break;
205     }
206
207     case SV_WAND_COLD_BOLT: {
208         fire_bolt_or_beam(player_ptr, 20, AttributeType::COLD, dir, damroll(5 + lev / 8, 8));
209         ident = true;
210         break;
211     }
212
213     case SV_WAND_ACID_BALL: {
214         fire_ball(player_ptr, AttributeType::ACID, dir, 60 + 3 * lev / 4, rad);
215         ident = true;
216         break;
217     }
218
219     case SV_WAND_ELEC_BALL: {
220         fire_ball(player_ptr, AttributeType::ELEC, dir, 40 + 3 * lev / 4, rad);
221         ident = true;
222         break;
223     }
224
225     case SV_WAND_FIRE_BALL: {
226         fire_ball(player_ptr, AttributeType::FIRE, dir, 70 + 3 * lev / 4, rad);
227         ident = true;
228         break;
229     }
230
231     case SV_WAND_COLD_BALL: {
232         fire_ball(player_ptr, AttributeType::COLD, dir, 50 + 3 * lev / 4, rad);
233         ident = true;
234         break;
235     }
236
237     case SV_WAND_WONDER: {
238         msg_print(_("おっと、謎の魔法棒を始動させた。", "Oops.  Wand of wonder activated."));
239         break;
240     }
241
242     case SV_WAND_DRAGON_FIRE: {
243         fire_breath(player_ptr, AttributeType::FIRE, dir, (powerful ? 300 : 200), 3);
244         ident = true;
245         break;
246     }
247
248     case SV_WAND_DRAGON_COLD: {
249         fire_breath(player_ptr, AttributeType::COLD, dir, (powerful ? 270 : 180), 3);
250         ident = true;
251         break;
252     }
253
254     case SV_WAND_DRAGON_BREATH: {
255         HIT_POINT dam;
256         AttributeType typ;
257
258         switch (randint1(5)) {
259         case 1:
260             dam = 240;
261             typ = AttributeType::ACID;
262             break;
263         case 2:
264             dam = 210;
265             typ = AttributeType::ELEC;
266             break;
267         case 3:
268             dam = 240;
269             typ = AttributeType::FIRE;
270             break;
271         case 4:
272             dam = 210;
273             typ = AttributeType::COLD;
274             break;
275         default:
276             dam = 180;
277             typ = AttributeType::POIS;
278             break;
279         }
280
281         if (powerful)
282             dam = (dam * 3) / 2;
283
284         fire_breath(player_ptr, typ, dir, dam, 3);
285
286         ident = true;
287         break;
288     }
289
290     case SV_WAND_DISINTEGRATE: {
291         fire_ball(player_ptr, AttributeType::DISINTEGRATE, dir, 200 + randint1(lev * 2), rad);
292         ident = true;
293         break;
294     }
295
296     case SV_WAND_ROCKETS: {
297         msg_print(_("ロケットを発射した!", "You launch a rocket!"));
298         fire_rocket(player_ptr, AttributeType::ROCKET, dir, 250 + lev * 3, rad);
299         ident = true;
300         break;
301     }
302
303     case SV_WAND_STRIKING: {
304         fire_bolt(player_ptr, AttributeType::METEOR, dir, damroll(15 + lev / 3, 13));
305         ident = true;
306         break;
307     }
308
309     case SV_WAND_GENOCIDE: {
310         fire_ball_hide(player_ptr, AttributeType::GENOCIDE, dir, magic ? lev + 50 : 250, 0);
311         ident = true;
312         break;
313     }
314     }
315     return ident;
316 }
317
318 /*!
319  * @brief 魔法棒を使うコマンドのメインルーチン /
320  */
321 void do_cmd_aim_wand(player_type *player_ptr)
322 {
323     OBJECT_IDX item;
324     concptr q, s;
325
326     if (player_ptr->wild_mode)
327         return;
328     if (cmd_limit_arena(player_ptr))
329         return;
330     PlayerClass(player_ptr).break_samurai_stance({ SamuraiStance::MUSOU, SamuraiStance::KOUKIJIN });
331
332     q = _("どの魔法棒で狙いますか? ", "Aim which wand? ");
333     s = _("使える魔法棒がない。", "You have no wand to aim.");
334     if (!choose_object(player_ptr, &item, q, s, (USE_INVEN | USE_FLOOR), TvalItemTester(ItemKindType::WAND)))
335         return;
336
337     ObjectZapWandEntity(player_ptr).execute(item);
338 }