OSDN Git Service

79b1dea8f1d04a5fb0d3ad5505c2dfc347f10bef
[hengbandforosx/hengbandosx.git] / src / cmd-item / cmd-zaprod.cpp
1 #include "cmd-item/cmd-zaprod.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 "main/sound-definitions-table.h"
8 #include "main/sound-of-music.h"
9 #include "object-enchant/special-object-flags.h"
10 #include "object/item-use-flags.h"
11 #include "object/object-info.h"
12 #include "object/object-kind.h"
13 #include "perception/object-perception.h"
14 #include "player/attack-defense-types.h"
15 #include "player-info/avatar.h"
16 #include "player-status/player-energy.h"
17 #include "player/player-class.h"
18 #include "player/special-defense-types.h"
19 #include "spell-kind/spells-beam.h"
20 #include "spell-kind/spells-detection.h"
21 #include "spell-kind/spells-floor.h"
22 #include "spell-kind/spells-launcher.h"
23 #include "spell-kind/spells-lite.h"
24 #include "spell-kind/spells-neighbor.h"
25 #include "spell-kind/spells-perception.h"
26 #include "spell-kind/spells-random.h"
27 #include "spell-kind/spells-sight.h"
28 #include "spell-kind/spells-specific-bolt.h"
29 #include "spell-kind/spells-teleport.h"
30 #include "spell-kind/spells-world.h"
31 #include "spell/spell-types.h"
32 #include "spell/spells-status.h"
33 #include "status/action-setter.h"
34 #include "status/buff-setter.h"
35 #include "status/experience.h"
36 #include "status/shape-changer.h"
37 #include "sv-definition/sv-other-types.h"
38 #include "sv-definition/sv-rod-types.h"
39 #include "system/object-type-definition.h"
40 #include "system/player-type-definition.h"
41 #include "target/target-getter.h"
42 #include "term/screen-processor.h"
43 #include "util/bit-flags-calculator.h"
44 #include "view/display-messages.h"
45
46 /*!
47  * @brief ロッドの効果を発動する
48  * @param creature_ptr プレーヤーへの参照ポインタ
49  * @param sval オブジェクトのsval
50  * @param dir 発動目標の方向ID
51  * @param use_charge チャージを消費したかどうかを返す参照ポインタ
52  * @param powerful 強力発動上の処理ならばTRUE
53  * @param magic 魔道具術上の処理ならばTRUE
54  * @return 発動により効果内容が確定したならばTRUEを返す
55  */
56 int rod_effect(player_type *creature_ptr, OBJECT_SUBTYPE_VALUE sval, DIRECTION dir, bool *use_charge, bool powerful, bool magic)
57 {
58     int ident = FALSE;
59     PLAYER_LEVEL lev = powerful ? creature_ptr->lev * 2 : creature_ptr->lev;
60     POSITION detect_rad = powerful ? DETECT_RAD_DEFAULT * 3 / 2 : DETECT_RAD_DEFAULT;
61     POSITION rad = powerful ? 3 : 2;
62
63     /* Unused */
64     (void)magic;
65
66     /* Analyze the rod */
67     switch (sval) {
68     case SV_ROD_DETECT_TRAP: {
69         if (detect_traps(creature_ptr, detect_rad, (bool)(dir ? FALSE : TRUE)))
70             ident = TRUE;
71         break;
72     }
73
74     case SV_ROD_DETECT_DOOR: {
75         if (detect_doors(creature_ptr, detect_rad))
76             ident = TRUE;
77         if (detect_stairs(creature_ptr, detect_rad))
78             ident = TRUE;
79         break;
80     }
81
82     case SV_ROD_IDENTIFY: {
83         if (powerful) {
84             if (!identify_fully(creature_ptr, FALSE, TV_NONE))
85                 *use_charge = FALSE;
86         } else {
87             if (!ident_spell(creature_ptr, FALSE, TV_NONE))
88                 *use_charge = FALSE;
89         }
90         ident = TRUE;
91         break;
92     }
93
94     case SV_ROD_RECALL: {
95         if (!recall_player(creature_ptr, randint0(21) + 15))
96             *use_charge = FALSE;
97         ident = TRUE;
98         break;
99     }
100
101     case SV_ROD_ILLUMINATION: {
102         if (lite_area(creature_ptr, damroll(2, 8), (powerful ? 4 : 2)))
103             ident = TRUE;
104         break;
105     }
106
107     case SV_ROD_MAPPING: {
108         map_area(creature_ptr, powerful ? DETECT_RAD_MAP * 3 / 2 : DETECT_RAD_MAP);
109         ident = TRUE;
110         break;
111     }
112
113     case SV_ROD_DETECTION: {
114         detect_all(creature_ptr, detect_rad);
115         ident = TRUE;
116         break;
117     }
118
119     case SV_ROD_PROBING: {
120         probing(creature_ptr);
121         ident = TRUE;
122         break;
123     }
124
125     case SV_ROD_CURING: {
126         if (true_healing(creature_ptr, 0))
127             ident = TRUE;
128         if (set_shero(creature_ptr, 0, TRUE))
129             ident = TRUE;
130         break;
131     }
132
133     case SV_ROD_HEALING: {
134         if (cure_critical_wounds(creature_ptr, powerful ? 750 : 500))
135             ident = TRUE;
136         break;
137     }
138
139     case SV_ROD_RESTORATION: {
140         if (restore_level(creature_ptr))
141             ident = TRUE;
142         if (restore_all_status(creature_ptr))
143             ident = TRUE;
144         break;
145     }
146
147     case SV_ROD_SPEED: {
148         if (set_fast(creature_ptr, randint1(30) + (powerful ? 30 : 15), FALSE))
149             ident = TRUE;
150         break;
151     }
152
153     case SV_ROD_PESTICIDE: {
154         if (dispel_monsters(creature_ptr, powerful ? 8 : 4))
155             ident = TRUE;
156         break;
157     }
158
159     case SV_ROD_TELEPORT_AWAY: {
160         int distance = MAX_SIGHT * (powerful ? 8 : 5);
161         if (teleport_monster(creature_ptr, dir, distance))
162             ident = TRUE;
163         break;
164     }
165
166     case SV_ROD_DISARMING: {
167         if (disarm_trap(creature_ptr, dir))
168             ident = TRUE;
169         if (powerful && disarm_traps_touch(creature_ptr))
170             ident = TRUE;
171         break;
172     }
173
174     case SV_ROD_LITE: {
175         HIT_POINT dam = damroll((powerful ? 12 : 6), 8);
176         msg_print(_("青く輝く光線が放たれた。", "A line of blue shimmering light appears."));
177         (void)lite_line(creature_ptr, dir, dam);
178         ident = TRUE;
179         break;
180     }
181
182     case SV_ROD_SLEEP_MONSTER: {
183         if (sleep_monster(creature_ptr, dir, lev))
184             ident = TRUE;
185         break;
186     }
187
188     case SV_ROD_SLOW_MONSTER: {
189         if (slow_monster(creature_ptr, dir, lev))
190             ident = TRUE;
191         break;
192     }
193
194     case SV_ROD_HYPODYNAMIA: {
195         if (hypodynamic_bolt(creature_ptr, dir, 70 + 3 * lev / 2))
196             ident = TRUE;
197         break;
198     }
199
200     case SV_ROD_POLYMORPH: {
201         if (poly_monster(creature_ptr, dir, lev))
202             ident = TRUE;
203         break;
204     }
205
206     case SV_ROD_ACID_BOLT: {
207         fire_bolt_or_beam(creature_ptr, 10, GF_ACID, dir, damroll(6 + lev / 7, 8));
208         ident = TRUE;
209         break;
210     }
211
212     case SV_ROD_ELEC_BOLT: {
213         fire_bolt_or_beam(creature_ptr, 10, GF_ELEC, dir, damroll(4 + lev / 9, 8));
214         ident = TRUE;
215         break;
216     }
217
218     case SV_ROD_FIRE_BOLT: {
219         fire_bolt_or_beam(creature_ptr, 10, GF_FIRE, dir, damroll(7 + lev / 6, 8));
220         ident = TRUE;
221         break;
222     }
223
224     case SV_ROD_COLD_BOLT: {
225         fire_bolt_or_beam(creature_ptr, 10, GF_COLD, dir, damroll(5 + lev / 8, 8));
226         ident = TRUE;
227         break;
228     }
229
230     case SV_ROD_ACID_BALL: {
231         fire_ball(creature_ptr, GF_ACID, dir, 60 + lev, rad);
232         ident = TRUE;
233         break;
234     }
235
236     case SV_ROD_ELEC_BALL: {
237         fire_ball(creature_ptr, GF_ELEC, dir, 40 + lev, rad);
238         ident = TRUE;
239         break;
240     }
241
242     case SV_ROD_FIRE_BALL: {
243         fire_ball(creature_ptr, GF_FIRE, dir, 70 + lev, rad);
244         ident = TRUE;
245         break;
246     }
247
248     case SV_ROD_COLD_BALL: {
249         fire_ball(creature_ptr, GF_COLD, dir, 50 + lev, rad);
250         ident = TRUE;
251         break;
252     }
253
254     case SV_ROD_HAVOC: {
255         call_chaos(creature_ptr);
256         ident = TRUE;
257         break;
258     }
259
260     case SV_ROD_STONE_TO_MUD: {
261         HIT_POINT dam = powerful ? 40 + randint1(60) : 20 + randint1(30);
262         if (wall_to_mud(creature_ptr, dir, dam))
263             ident = TRUE;
264         break;
265     }
266
267     case SV_ROD_AGGRAVATE: {
268         aggravate_monsters(creature_ptr, 0);
269         ident = TRUE;
270         break;
271     }
272     }
273     return ident;
274 }
275
276 /*!
277  * @brief ロッドを使うコマンドのサブルーチン /
278  * Activate (zap) a Rod
279  * @param creature_ptr プレーヤーへの参照ポインタ
280  * @param item 使うオブジェクトの所持品ID
281  * @return なし
282  * @details
283  * <pre>
284  * Unstack fully charged rods as needed.
285  * Hack -- rods of perception/genocide can be "cancelled"
286  * All rods can be cancelled at the "Direction?" prompt
287  * pvals are defined for each rod in k_info. -LM-
288  * </pre>
289  */
290 void exe_zap_rod(player_type *creature_ptr, INVENTORY_IDX item)
291 {
292     int ident, chance, lev, fail;
293     DIRECTION dir = 0;
294     object_type *o_ptr;
295     bool success;
296
297     /* Hack -- let perception get aborted */
298     bool use_charge = TRUE;
299
300     object_kind *k_ptr;
301
302     o_ptr = ref_item(creature_ptr, item);
303
304     /* Mega-Hack -- refuse to zap a pile from the ground */
305     if ((item < 0) && (o_ptr->number > 1)) {
306         msg_print(_("まずはロッドを拾わなければ。", "You must first pick up the rods."));
307         return;
308     }
309
310     /* Get a direction (unless KNOWN not to need it) */
311     if (((o_ptr->sval >= SV_ROD_MIN_DIRECTION) && (o_ptr->sval != SV_ROD_HAVOC) && (o_ptr->sval != SV_ROD_AGGRAVATE) && (o_ptr->sval != SV_ROD_PESTICIDE))
312         || !object_is_aware(o_ptr)) {
313         /* Get a direction, allow cancel */
314         if (!get_aim_dir(creature_ptr, &dir))
315             return;
316     }
317
318     PlayerEnergy(creature_ptr).set_player_turn_energy(100);
319
320     lev = k_info[o_ptr->k_idx].level;
321
322     /* Base chance of success */
323     chance = creature_ptr->skill_dev;
324
325     /* Confusion hurts skill */
326     if (creature_ptr->confused)
327         chance = chance / 2;
328
329     fail = lev + 5;
330     if (chance > fail)
331         fail -= (chance - fail) * 2;
332     else
333         chance -= (fail - chance) * 2;
334     if (fail < USE_DEVICE)
335         fail = USE_DEVICE;
336     if (chance < USE_DEVICE)
337         chance = USE_DEVICE;
338
339     if (cmd_limit_time_walk(creature_ptr))
340         return;
341
342     if (creature_ptr->pclass == CLASS_BERSERKER)
343         success = FALSE;
344     else if (chance > fail) {
345         if (randint0(chance * 2) < fail)
346             success = FALSE;
347         else
348             success = TRUE;
349     } else {
350         if (randint0(fail * 2) < chance)
351             success = TRUE;
352         else
353             success = FALSE;
354     }
355
356     /* Roll for usage */
357     if (!success) {
358         if (flush_failure)
359             flush();
360         msg_print(_("うまくロッドを使えなかった。", "You failed to use the rod properly."));
361         sound(SOUND_FAIL);
362         return;
363     }
364
365     k_ptr = &k_info[o_ptr->k_idx];
366
367     /* A single rod is still charging */
368     if ((o_ptr->number == 1) && (o_ptr->timeout)) {
369         if (flush_failure)
370             flush();
371         msg_print(_("このロッドはまだ魔力を充填している最中だ。", "The rod is still charging."));
372         return;
373     }
374     /* A stack of rods lacks enough energy. */
375     else if ((o_ptr->number > 1) && (o_ptr->timeout > k_ptr->pval * (o_ptr->number - 1))) {
376         if (flush_failure)
377             flush();
378         msg_print(_("そのロッドはまだ充填中です。", "The rods are all still charging."));
379         return;
380     }
381
382     sound(SOUND_ZAP);
383
384     ident = rod_effect(creature_ptr, o_ptr->sval, dir, &use_charge, FALSE, FALSE);
385
386     /* Increase the timeout by the rod kind's pval. -LM- */
387     if (use_charge)
388         o_ptr->timeout += k_ptr->pval;
389     creature_ptr->update |= (PU_COMBINE | PU_REORDER);
390
391     if (!(object_is_aware(o_ptr))) {
392         chg_virtue(creature_ptr, V_PATIENCE, -1);
393         chg_virtue(creature_ptr, V_CHANCE, 1);
394         chg_virtue(creature_ptr, V_KNOWLEDGE, -1);
395     }
396
397     /* Tried the object */
398     object_tried(o_ptr);
399
400     /* Successfully determined the object function */
401     if (ident && !object_is_aware(o_ptr)) {
402         object_aware(creature_ptr, o_ptr);
403         gain_exp(creature_ptr, (lev + (creature_ptr->lev >> 1)) / creature_ptr->lev);
404     }
405
406     set_bits(creature_ptr->window_flags, PW_INVEN | PW_EQUIP | PW_PLAYER | PW_FLOOR_ITEM_LIST);
407 }
408
409 /*!
410  * @brief ロッドを使うコマンドのメインルーチン /
411  * @param creature_ptr プレーヤーへの参照ポインタ
412  * @return なし
413  */
414 void do_cmd_zap_rod(player_type *creature_ptr)
415 {
416     OBJECT_IDX item;
417     concptr q, s;
418
419     if (creature_ptr->wild_mode) {
420         return;
421     }
422
423     if (cmd_limit_arena(creature_ptr))
424         return;
425
426     if (creature_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) {
427         set_action(creature_ptr, ACTION_NONE);
428     }
429
430     q = _("どのロッドを振りますか? ", "Zap which rod? ");
431     s = _("使えるロッドがない。", "You have no rod to zap.");
432
433     if (!choose_object(creature_ptr, &item, q, s, (USE_INVEN | USE_FLOOR), TV_ROD))
434         return;
435
436     /* Zap the rod */
437     exe_zap_rod(creature_ptr, item);
438 }