OSDN Git Service

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