OSDN Git Service

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