OSDN Git Service

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