OSDN Git Service

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