OSDN Git Service

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