OSDN Git Service

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