OSDN Git Service

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