OSDN Git Service

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