OSDN Git Service

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