OSDN Git Service

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