OSDN Git Service

[Refactor] #37353 射撃処理を cmd1.c から shoot.c へ分離。
[hengband/hengband.git] / src / cmd-zaprod.c
1 #include "angband.h"
2
3 /*!
4  * @brief \83\8d\83b\83h\82Ì\8cø\89Ê\82ð\94­\93®\82·\82é
5  * @param sval \83I\83u\83W\83F\83N\83g\82Ìsval
6  * @param dir \94­\93®\96Ú\95W\82Ì\95û\8cüID
7  * @param use_charge \83`\83\83\81[\83W\82ð\8fÁ\94ï\82µ\82½\82©\82Ç\82¤\82©\82ð\95Ô\82·\8eQ\8fÆ\83|\83C\83\93\83^
8  * @param powerful \8b­\97Í\94­\93®\8fã\82Ì\8f\88\97\9d\82È\82ç\82ÎTRUE
9  * @param magic \96\82\93¹\8bï\8fp\8fã\82Ì\8f\88\97\9d\82È\82ç\82ÎTRUE
10  * @return \94­\93®\82É\82æ\82è\8cø\89Ê\93à\97e\82ª\8am\92è\82µ\82½\82È\82ç\82ÎTRUE\82ð\95Ô\82·
11  */
12 int rod_effect(OBJECT_SUBTYPE_VALUE sval, int dir, bool *use_charge, bool powerful, bool magic)
13 {
14         int ident = FALSE;
15         int lev = powerful ? p_ptr->lev * 2 : p_ptr->lev;
16         int detect_rad = powerful ? DETECT_RAD_DEFAULT * 3 / 2 : DETECT_RAD_DEFAULT;
17         int rad = powerful ? 3 : 2;
18
19         /* Unused */
20         (void)magic;
21
22         /* Analyze the rod */
23         switch (sval)
24         {
25         case SV_ROD_DETECT_TRAP:
26         {
27                 if (detect_traps(detect_rad, (bool)(dir ? FALSE : TRUE))) ident = TRUE;
28                 break;
29         }
30
31         case SV_ROD_DETECT_DOOR:
32         {
33                 if (detect_doors(detect_rad)) ident = TRUE;
34                 if (detect_stairs(detect_rad)) ident = TRUE;
35                 break;
36         }
37
38         case SV_ROD_IDENTIFY:
39         {
40                 if (powerful) {
41                         if (!identify_fully(FALSE)) *use_charge = FALSE;
42                 }
43                 else {
44                         if (!ident_spell(FALSE)) *use_charge = FALSE;
45                 }
46                 ident = TRUE;
47                 break;
48         }
49
50         case SV_ROD_RECALL:
51         {
52                 if (!word_of_recall()) *use_charge = FALSE;
53                 ident = TRUE;
54                 break;
55         }
56
57         case SV_ROD_ILLUMINATION:
58         {
59                 if (lite_area(damroll(2, 8), (powerful ? 4 : 2))) ident = TRUE;
60                 break;
61         }
62
63         case SV_ROD_MAPPING:
64         {
65                 map_area(powerful ? DETECT_RAD_MAP * 3 / 2 : DETECT_RAD_MAP);
66                 ident = TRUE;
67                 break;
68         }
69
70         case SV_ROD_DETECTION:
71         {
72                 detect_all(detect_rad);
73                 ident = TRUE;
74                 break;
75         }
76
77         case SV_ROD_PROBING:
78         {
79                 probing();
80                 ident = TRUE;
81                 break;
82         }
83
84         case SV_ROD_CURING:
85         {
86                 if (set_blind(0)) ident = TRUE;
87                 if (set_poisoned(0)) ident = TRUE;
88                 if (set_confused(0)) ident = TRUE;
89                 if (set_stun(0)) ident = TRUE;
90                 if (set_cut(0)) ident = TRUE;
91                 if (set_image(0)) ident = TRUE;
92                 if (set_shero(0, TRUE)) ident = TRUE;
93                 break;
94         }
95
96         case SV_ROD_HEALING:
97         {
98                 if (hp_player(powerful ? 750 : 500)) ident = TRUE;
99                 if (set_stun(0)) ident = TRUE;
100                 if (set_cut(0)) ident = TRUE;
101                 if (set_shero(0, TRUE)) ident = TRUE;
102                 break;
103         }
104
105         case SV_ROD_RESTORATION:
106         {
107                 if (restore_level()) ident = TRUE;
108                 if (do_res_stat(A_STR)) ident = TRUE;
109                 if (do_res_stat(A_INT)) ident = TRUE;
110                 if (do_res_stat(A_WIS)) ident = TRUE;
111                 if (do_res_stat(A_DEX)) ident = TRUE;
112                 if (do_res_stat(A_CON)) ident = TRUE;
113                 if (do_res_stat(A_CHR)) ident = TRUE;
114                 break;
115         }
116
117         case SV_ROD_SPEED:
118         {
119                 if (set_fast(randint1(30) + (powerful ? 30 : 15), FALSE)) ident = TRUE;
120                 break;
121         }
122
123         case SV_ROD_PESTICIDE:
124         {
125                 if (dispel_monsters(powerful ? 8 : 4)) ident = TRUE;
126                 break;
127         }
128
129         case SV_ROD_TELEPORT_AWAY:
130         {
131                 int distance = MAX_SIGHT * (powerful ? 8 : 5);
132                 if (teleport_monster(dir, distance)) ident = TRUE;
133                 break;
134         }
135
136         case SV_ROD_DISARMING:
137         {
138                 if (disarm_trap(dir)) ident = TRUE;
139                 if (powerful && disarm_traps_touch()) ident = TRUE;
140                 break;
141         }
142
143         case SV_ROD_LITE:
144         {
145                 HIT_POINT dam = damroll((powerful ? 12 : 6), 8);
146                 msg_print(_("\90Â\82­\8bP\82­\8cõ\90ü\82ª\95ú\82½\82ê\82½\81B", "A line of blue shimmering light appears."));
147                 (void)lite_line(dir, dam);
148                 ident = TRUE;
149                 break;
150         }
151
152         case SV_ROD_SLEEP_MONSTER:
153         {
154                 if (sleep_monster(dir, lev)) ident = TRUE;
155                 break;
156         }
157
158         case SV_ROD_SLOW_MONSTER:
159         {
160                 if (slow_monster(dir, lev)) ident = TRUE;
161                 break;
162         }
163
164         case SV_ROD_HYPODYNAMIA:
165         {
166                 if (hypodynamic_bolt(dir, 70 + 3 * lev / 2)) ident = TRUE;
167                 break;
168         }
169
170         case SV_ROD_POLYMORPH:
171         {
172                 if (poly_monster(dir, lev)) ident = TRUE;
173                 break;
174         }
175
176         case SV_ROD_ACID_BOLT:
177         {
178                 fire_bolt_or_beam(10, GF_ACID, dir, damroll(6 + lev / 7, 8));
179                 ident = TRUE;
180                 break;
181         }
182
183         case SV_ROD_ELEC_BOLT:
184         {
185                 fire_bolt_or_beam(10, GF_ELEC, dir, damroll(4 + lev / 9, 8));
186                 ident = TRUE;
187                 break;
188         }
189
190         case SV_ROD_FIRE_BOLT:
191         {
192                 fire_bolt_or_beam(10, GF_FIRE, dir, damroll(7 + lev / 6, 8));
193                 ident = TRUE;
194                 break;
195         }
196
197         case SV_ROD_COLD_BOLT:
198         {
199                 fire_bolt_or_beam(10, GF_COLD, dir, damroll(5 + lev / 8, 8));
200                 ident = TRUE;
201                 break;
202         }
203
204         case SV_ROD_ACID_BALL:
205         {
206                 fire_ball(GF_ACID, dir, 60 + lev, rad);
207                 ident = TRUE;
208                 break;
209         }
210
211         case SV_ROD_ELEC_BALL:
212         {
213                 fire_ball(GF_ELEC, dir, 40 + lev, rad);
214                 ident = TRUE;
215                 break;
216         }
217
218         case SV_ROD_FIRE_BALL:
219         {
220                 fire_ball(GF_FIRE, dir, 70 + lev, rad);
221                 ident = TRUE;
222                 break;
223         }
224
225         case SV_ROD_COLD_BALL:
226         {
227                 fire_ball(GF_COLD, dir, 50 + lev, rad);
228                 ident = TRUE;
229                 break;
230         }
231
232         case SV_ROD_HAVOC:
233         {
234                 call_chaos();
235                 ident = TRUE;
236                 break;
237         }
238
239         case SV_ROD_STONE_TO_MUD:
240         {
241                 HIT_POINT dam = powerful ? 40 + randint1(60) : 20 + randint1(30);
242                 if (wall_to_mud(dir, dam)) ident = TRUE;
243                 break;
244         }
245
246         case SV_ROD_AGGRAVATE:
247         {
248                 aggravate_monsters(0);
249                 ident = TRUE;
250                 break;
251         }
252         }
253         return ident;
254 }
255
256 /*!
257 * @brief \83\8d\83b\83h\82ð\8eg\82¤\83R\83}\83\93\83h\82Ì\83T\83u\83\8b\81[\83`\83\93 /
258 * Activate (zap) a Rod
259 * @param item \8eg\82¤\83I\83u\83W\83F\83N\83g\82Ì\8f\8a\8e\9d\95iID
260 * @return \82È\82µ
261 * @details
262 * <pre>
263 * Unstack fully charged rods as needed.
264 * Hack -- rods of perception/genocide can be "cancelled"
265 * All rods can be cancelled at the "Direction?" prompt
266 * pvals are defined for each rod in k_info. -LM-
267 * </pre>
268 */
269 void do_cmd_zap_rod_aux(int item)
270 {
271         int ident, chance, lev, fail;
272         int dir = 0;
273         object_type *o_ptr;
274         bool success;
275
276         /* Hack -- let perception get aborted */
277         bool use_charge = TRUE;
278
279         object_kind *k_ptr;
280
281         /* Get the item (in the pack) */
282         if (item >= 0)
283         {
284                 o_ptr = &inventory[item];
285         }
286
287         /* Get the item (on the floor) */
288         else
289         {
290                 o_ptr = &o_list[0 - item];
291         }
292
293
294         /* Mega-Hack -- refuse to zap a pile from the ground */
295         if ((item < 0) && (o_ptr->number > 1))
296         {
297                 msg_print(_("\82Ü\82¸\82Í\83\8d\83b\83h\82ð\8fE\82í\82È\82¯\82ê\82Î\81B", "You must first pick up the rods."));
298                 return;
299         }
300
301
302         /* Get a direction (unless KNOWN not to need it) */
303         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)) ||
304                 !object_is_aware(o_ptr))
305         {
306                 /* Get a direction, allow cancel */
307                 if (!get_aim_dir(&dir)) return;
308         }
309
310
311         /* Take a turn */
312         p_ptr->energy_use = 100;
313
314         /* Extract the item level */
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 (world_player)
330         {
331                 if (flush_failure) flush();
332                 msg_print(_("\8e~\82Ü\82Á\82½\8e\9e\82Ì\92\86\82Å\82Í\82¤\82Ü\82­\93­\82©\82È\82¢\82æ\82¤\82¾\81B", "Nothing happen. Maybe this rod is freezing too."));
333                 sound(SOUND_FAIL);
334                 return;
335         }
336
337         if (p_ptr->pclass == CLASS_BERSERKER) success = FALSE;
338         else if (chance > fail)
339         {
340                 if (randint0(chance * 2) < fail) success = FALSE;
341                 else success = TRUE;
342         }
343         else
344         {
345                 if (randint0(fail * 2) < chance) success = TRUE;
346                 else success = FALSE;
347         }
348
349         /* Roll for usage */
350         if (!success)
351         {
352                 if (flush_failure) flush();
353                 msg_print(_("\82¤\82Ü\82­\83\8d\83b\83h\82ð\8eg\82¦\82È\82©\82Á\82½\81B", "You failed to use the rod properly."));
354                 sound(SOUND_FAIL);
355                 return;
356         }
357
358         k_ptr = &k_info[o_ptr->k_idx];
359
360         /* A single rod is still charging */
361         if ((o_ptr->number == 1) && (o_ptr->timeout))
362         {
363                 if (flush_failure) flush();
364                 msg_print(_("\82±\82Ì\83\8d\83b\83h\82Í\82Ü\82¾\96\82\97Í\82ð\8f[\93U\82µ\82Ä\82¢\82é\8dÅ\92\86\82¾\81B", "The rod is still charging."));
365                 return;
366         }
367         /* A stack of rods lacks enough energy. */
368         else if ((o_ptr->number > 1) && (o_ptr->timeout > k_ptr->pval * (o_ptr->number - 1)))
369         {
370                 if (flush_failure) flush();
371                 msg_print(_("\82»\82Ì\83\8d\83b\83h\82Í\82Ü\82¾\8f[\93U\92\86\82Å\82·\81B", "The rods are all still charging."));
372                 return;
373         }
374
375         /* Sound */
376         sound(SOUND_ZAP);
377
378         ident = rod_effect(o_ptr->sval, dir, &use_charge, FALSE, FALSE);
379
380         /* Increase the timeout by the rod kind's pval. -LM- */
381         if (use_charge) o_ptr->timeout += k_ptr->pval;
382
383         /* Combine / Reorder the pack (later) */
384         p_ptr->notice |= (PN_COMBINE | PN_REORDER);
385
386         if (!(object_is_aware(o_ptr)))
387         {
388                 chg_virtue(V_PATIENCE, -1);
389                 chg_virtue(V_CHANCE, 1);
390                 chg_virtue(V_KNOWLEDGE, -1);
391         }
392
393         /* Tried the object */
394         object_tried(o_ptr);
395
396         /* Successfully determined the object function */
397         if (ident && !object_is_aware(o_ptr))
398         {
399                 object_aware(o_ptr);
400                 gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev);
401         }
402
403         /* Window stuff */
404         p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
405 }
406
407 /*!
408 * @brief \83\8d\83b\83h\82ð\8eg\82¤\83R\83}\83\93\83h\82Ì\83\81\83C\83\93\83\8b\81[\83`\83\93 /
409 * @return \82È\82µ
410 */
411 void do_cmd_zap_rod(void)
412 {
413         OBJECT_IDX item;
414         cptr q, s;
415
416         if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN))
417         {
418                 set_action(ACTION_NONE);
419         }
420
421         /* Restrict choices to rods */
422         item_tester_tval = TV_ROD;
423
424         /* Get an item */
425         q = _("\82Ç\82Ì\83\8d\83b\83h\82ð\90U\82è\82Ü\82·\82©? ", "Zap which rod? ");
426         s = _("\8eg\82¦\82é\83\8d\83b\83h\82ª\82È\82¢\81B", "You have no rod to zap.");
427
428         if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
429
430         /* Zap the rod */
431         do_cmd_zap_rod_aux(item);
432 }