OSDN Git Service

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