OSDN Git Service

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