OSDN Git Service

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