OSDN Git Service

[Refactor] #37353 癒し系の効果をtrue_healing()にまとめる。
[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 (true_healing(0)) ident = TRUE;
87                 if (set_shero(0, TRUE)) ident = TRUE;
88                 break;
89         }
90
91         case SV_ROD_HEALING:
92         {
93                 if(cure_critical_wounds(powerful ? 750 : 500)) ident = TRUE;
94                 break;
95         }
96
97         case SV_ROD_RESTORATION:
98         {
99                 if(restore_level()) ident = TRUE;
100                 if(restore_all_status()) ident = TRUE;
101                 break;
102         }
103
104         case SV_ROD_SPEED:
105         {
106                 if (set_fast(randint1(30) + (powerful ? 30 : 15), FALSE)) ident = TRUE;
107                 break;
108         }
109
110         case SV_ROD_PESTICIDE:
111         {
112                 if (dispel_monsters(powerful ? 8 : 4)) ident = TRUE;
113                 break;
114         }
115
116         case SV_ROD_TELEPORT_AWAY:
117         {
118                 int distance = MAX_SIGHT * (powerful ? 8 : 5);
119                 if (teleport_monster(dir, distance)) ident = TRUE;
120                 break;
121         }
122
123         case SV_ROD_DISARMING:
124         {
125                 if (disarm_trap(dir)) ident = TRUE;
126                 if (powerful && disarm_traps_touch()) ident = TRUE;
127                 break;
128         }
129
130         case SV_ROD_LITE:
131         {
132                 HIT_POINT dam = damroll((powerful ? 12 : 6), 8);
133                 msg_print(_("\90Â\82­\8bP\82­\8cõ\90ü\82ª\95ú\82½\82ê\82½\81B", "A line of blue shimmering light appears."));
134                 (void)lite_line(dir, dam);
135                 ident = TRUE;
136                 break;
137         }
138
139         case SV_ROD_SLEEP_MONSTER:
140         {
141                 if (sleep_monster(dir, lev)) ident = TRUE;
142                 break;
143         }
144
145         case SV_ROD_SLOW_MONSTER:
146         {
147                 if (slow_monster(dir, lev)) ident = TRUE;
148                 break;
149         }
150
151         case SV_ROD_HYPODYNAMIA:
152         {
153                 if (hypodynamic_bolt(dir, 70 + 3 * lev / 2)) ident = TRUE;
154                 break;
155         }
156
157         case SV_ROD_POLYMORPH:
158         {
159                 if (poly_monster(dir, lev)) ident = TRUE;
160                 break;
161         }
162
163         case SV_ROD_ACID_BOLT:
164         {
165                 fire_bolt_or_beam(10, GF_ACID, dir, damroll(6 + lev / 7, 8));
166                 ident = TRUE;
167                 break;
168         }
169
170         case SV_ROD_ELEC_BOLT:
171         {
172                 fire_bolt_or_beam(10, GF_ELEC, dir, damroll(4 + lev / 9, 8));
173                 ident = TRUE;
174                 break;
175         }
176
177         case SV_ROD_FIRE_BOLT:
178         {
179                 fire_bolt_or_beam(10, GF_FIRE, dir, damroll(7 + lev / 6, 8));
180                 ident = TRUE;
181                 break;
182         }
183
184         case SV_ROD_COLD_BOLT:
185         {
186                 fire_bolt_or_beam(10, GF_COLD, dir, damroll(5 + lev / 8, 8));
187                 ident = TRUE;
188                 break;
189         }
190
191         case SV_ROD_ACID_BALL:
192         {
193                 fire_ball(GF_ACID, dir, 60 + lev, rad);
194                 ident = TRUE;
195                 break;
196         }
197
198         case SV_ROD_ELEC_BALL:
199         {
200                 fire_ball(GF_ELEC, dir, 40 + lev, rad);
201                 ident = TRUE;
202                 break;
203         }
204
205         case SV_ROD_FIRE_BALL:
206         {
207                 fire_ball(GF_FIRE, dir, 70 + lev, rad);
208                 ident = TRUE;
209                 break;
210         }
211
212         case SV_ROD_COLD_BALL:
213         {
214                 fire_ball(GF_COLD, dir, 50 + lev, rad);
215                 ident = TRUE;
216                 break;
217         }
218
219         case SV_ROD_HAVOC:
220         {
221                 call_chaos();
222                 ident = TRUE;
223                 break;
224         }
225
226         case SV_ROD_STONE_TO_MUD:
227         {
228                 HIT_POINT dam = powerful ? 40 + randint1(60) : 20 + randint1(30);
229                 if (wall_to_mud(dir, dam)) ident = TRUE;
230                 break;
231         }
232
233         case SV_ROD_AGGRAVATE:
234         {
235                 aggravate_monsters(0);
236                 ident = TRUE;
237                 break;
238         }
239         }
240         return ident;
241 }
242
243 /*!
244 * @brief \83\8d\83b\83h\82ð\8eg\82¤\83R\83}\83\93\83h\82Ì\83T\83u\83\8b\81[\83`\83\93 /
245 * Activate (zap) a Rod
246 * @param item \8eg\82¤\83I\83u\83W\83F\83N\83g\82Ì\8f\8a\8e\9d\95iID
247 * @return \82È\82µ
248 * @details
249 * <pre>
250 * Unstack fully charged rods as needed.
251 * Hack -- rods of perception/genocide can be "cancelled"
252 * All rods can be cancelled at the "Direction?" prompt
253 * pvals are defined for each rod in k_info. -LM-
254 * </pre>
255 */
256 void do_cmd_zap_rod_aux(int item)
257 {
258         int ident, chance, lev, fail;
259         int dir = 0;
260         object_type *o_ptr;
261         bool success;
262
263         /* Hack -- let perception get aborted */
264         bool use_charge = TRUE;
265
266         object_kind *k_ptr;
267
268         /* Get the item (in the pack) */
269         if (item >= 0)
270         {
271                 o_ptr = &inventory[item];
272         }
273
274         /* Get the item (on the floor) */
275         else
276         {
277                 o_ptr = &o_list[0 - item];
278         }
279
280
281         /* Mega-Hack -- refuse to zap a pile from the ground */
282         if ((item < 0) && (o_ptr->number > 1))
283         {
284                 msg_print(_("\82Ü\82¸\82Í\83\8d\83b\83h\82ð\8fE\82í\82È\82¯\82ê\82Î\81B", "You must first pick up the rods."));
285                 return;
286         }
287
288
289         /* Get a direction (unless KNOWN not to need it) */
290         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)) ||
291                 !object_is_aware(o_ptr))
292         {
293                 /* Get a direction, allow cancel */
294                 if (!get_aim_dir(&dir)) return;
295         }
296
297
298         /* Take a turn */
299         p_ptr->energy_use = 100;
300
301         /* Extract the item level */
302         lev = k_info[o_ptr->k_idx].level;
303
304         /* Base chance of success */
305         chance = p_ptr->skill_dev;
306
307         /* Confusion hurts skill */
308         if (p_ptr->confused) chance = chance / 2;
309
310         fail = lev + 5;
311         if (chance > fail) fail -= (chance - fail) * 2;
312         else chance -= (fail - chance) * 2;
313         if (fail < USE_DEVICE) fail = USE_DEVICE;
314         if (chance < USE_DEVICE) chance = USE_DEVICE;
315
316         if (world_player)
317         {
318                 if (flush_failure) flush();
319                 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."));
320                 sound(SOUND_FAIL);
321                 return;
322         }
323
324         if (p_ptr->pclass == CLASS_BERSERKER) success = FALSE;
325         else if (chance > fail)
326         {
327                 if (randint0(chance * 2) < fail) success = FALSE;
328                 else success = TRUE;
329         }
330         else
331         {
332                 if (randint0(fail * 2) < chance) success = TRUE;
333                 else success = FALSE;
334         }
335
336         /* Roll for usage */
337         if (!success)
338         {
339                 if (flush_failure) flush();
340                 msg_print(_("\82¤\82Ü\82­\83\8d\83b\83h\82ð\8eg\82¦\82È\82©\82Á\82½\81B", "You failed to use the rod properly."));
341                 sound(SOUND_FAIL);
342                 return;
343         }
344
345         k_ptr = &k_info[o_ptr->k_idx];
346
347         /* A single rod is still charging */
348         if ((o_ptr->number == 1) && (o_ptr->timeout))
349         {
350                 if (flush_failure) flush();
351                 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."));
352                 return;
353         }
354         /* A stack of rods lacks enough energy. */
355         else if ((o_ptr->number > 1) && (o_ptr->timeout > k_ptr->pval * (o_ptr->number - 1)))
356         {
357                 if (flush_failure) flush();
358                 msg_print(_("\82»\82Ì\83\8d\83b\83h\82Í\82Ü\82¾\8f[\93U\92\86\82Å\82·\81B", "The rods are all still charging."));
359                 return;
360         }
361
362         /* Sound */
363         sound(SOUND_ZAP);
364
365         ident = rod_effect(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
370         /* Combine / Reorder the pack (later) */
371         p_ptr->notice |= (PN_COMBINE | PN_REORDER);
372
373         if (!(object_is_aware(o_ptr)))
374         {
375                 chg_virtue(V_PATIENCE, -1);
376                 chg_virtue(V_CHANCE, 1);
377                 chg_virtue(V_KNOWLEDGE, -1);
378         }
379
380         /* Tried the object */
381         object_tried(o_ptr);
382
383         /* Successfully determined the object function */
384         if (ident && !object_is_aware(o_ptr))
385         {
386                 object_aware(o_ptr);
387                 gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev);
388         }
389
390         /* Window stuff */
391         p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
392 }
393
394 /*!
395 * @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 /
396 * @return \82È\82µ
397 */
398 void do_cmd_zap_rod(void)
399 {
400         OBJECT_IDX item;
401         cptr q, s;
402
403         if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN))
404         {
405                 set_action(ACTION_NONE);
406         }
407
408         /* Restrict choices to rods */
409         item_tester_tval = TV_ROD;
410
411         /* Get an item */
412         q = _("\82Ç\82Ì\83\8d\83b\83h\82ð\90U\82è\82Ü\82·\82©? ", "Zap which rod? ");
413         s = _("\8eg\82¦\82é\83\8d\83b\83h\82ª\82È\82¢\81B", "You have no rod to zap.");
414
415         if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
416
417         /* Zap the rod */
418         do_cmd_zap_rod_aux(item);
419 }