OSDN Git Service

[Refactor] #37353 行動パワー消費処理を take_turn() で再定義 / Redefine take_turn() for consumption...
[hengband/hengband.git] / src / cmd-usestaff.c
1 #include "angband.h"\r
2 #include "projection.h"\r
3 #include "spells-summon.h"\r
4 #include "avatar.h"\r
5 #include "player-status.h"\r
6 \r
7 \r
8 \r
9 /*!\r
10 * @brief 杖の効果を発動する\r
11 * @param sval オブジェクトのsval\r
12 * @param use_charge 使用回数を消費したかどうかを返す参照ポインタ\r
13 * @param powerful 強力発動上の処理ならばTRUE\r
14 * @param magic 魔道具術上の処理ならばTRUE\r
15 * @param known 判明済ならばTRUE\r
16 * @return 発動により効果内容が確定したならばTRUEを返す\r
17 */\r
18 int staff_effect(OBJECT_SUBTYPE_VALUE sval, bool *use_charge, bool powerful, bool magic, bool known)\r
19 {\r
20         int k;\r
21         int ident = FALSE;\r
22         PLAYER_LEVEL lev = powerful ? p_ptr->lev * 2 : p_ptr->lev;\r
23         POSITION detect_rad = powerful ? DETECT_RAD_DEFAULT * 3 / 2 : DETECT_RAD_DEFAULT;\r
24 \r
25         /* Analyze the staff */\r
26         switch (sval)\r
27         {\r
28                 case SV_STAFF_DARKNESS:\r
29                 {\r
30                         if (!(p_ptr->resist_blind) && !(p_ptr->resist_dark))\r
31                         {\r
32                                 if (set_blind(p_ptr->blind + 3 + randint1(5))) ident = TRUE;\r
33                         }\r
34                         if (unlite_area(10, (powerful ? 6 : 3))) ident = TRUE;\r
35                         break;\r
36                 }\r
37 \r
38                 case SV_STAFF_SLOWNESS:\r
39                 {\r
40                         if (set_slow(p_ptr->slow + randint1(30) + 15, FALSE)) ident = TRUE;\r
41                         break;\r
42                 }\r
43 \r
44                 case SV_STAFF_HASTE_MONSTERS:\r
45                 {\r
46                         if (speed_monsters()) ident = TRUE;\r
47                         break;\r
48                 }\r
49 \r
50                 case SV_STAFF_SUMMONING:\r
51                 {\r
52                         const int times = randint1(powerful ? 8 : 4);\r
53                         for (k = 0; k < times; k++)\r
54                         {\r
55                                 if (summon_specific(0, p_ptr->y, p_ptr->x, dun_level, 0, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0'))\r
56                                 {\r
57                                         ident = TRUE;\r
58                                 }\r
59                         }\r
60                         break;\r
61                 }\r
62 \r
63                 case SV_STAFF_TELEPORTATION:\r
64                 {\r
65                         teleport_player((powerful ? 150 : 100), 0L);\r
66                         ident = TRUE;\r
67                         break;\r
68                 }\r
69 \r
70                 case SV_STAFF_IDENTIFY:\r
71                 {\r
72                         if (powerful) {\r
73                                 if (!identify_fully(FALSE)) *use_charge = FALSE;\r
74                         }\r
75                         else {\r
76                                 if (!ident_spell(FALSE)) *use_charge = FALSE;\r
77                         }\r
78                         ident = TRUE;\r
79                         break;\r
80                 }\r
81 \r
82                 case SV_STAFF_REMOVE_CURSE:\r
83                 {\r
84                         bool result = powerful ? remove_all_curse() : remove_curse();\r
85                         if (result)\r
86                         {\r
87                                 ident = TRUE;\r
88                         }\r
89                         break;\r
90                 }\r
91 \r
92                 case SV_STAFF_STARLITE:\r
93                         ident = starlight(magic);\r
94                         break;\r
95 \r
96                 case SV_STAFF_LITE:\r
97                 {\r
98                         if (lite_area(damroll(2, 8), (powerful ? 4 : 2))) ident = TRUE;\r
99                         break;\r
100                 }\r
101 \r
102                 case SV_STAFF_MAPPING:\r
103                 {\r
104                         map_area(powerful ? DETECT_RAD_MAP * 3 / 2 : DETECT_RAD_MAP);\r
105                         ident = TRUE;\r
106                         break;\r
107                 }\r
108 \r
109                 case SV_STAFF_DETECT_GOLD:\r
110                 {\r
111                         if (detect_treasure(detect_rad)) ident = TRUE;\r
112                         if (detect_objects_gold(detect_rad)) ident = TRUE;\r
113                         break;\r
114                 }\r
115 \r
116                 case SV_STAFF_DETECT_ITEM:\r
117                 {\r
118                         if (detect_objects_normal(detect_rad)) ident = TRUE;\r
119                         break;\r
120                 }\r
121 \r
122                 case SV_STAFF_DETECT_TRAP:\r
123                 {\r
124                         if (detect_traps(detect_rad, known)) ident = TRUE;\r
125                         break;\r
126                 }\r
127 \r
128                 case SV_STAFF_DETECT_DOOR:\r
129                 {\r
130                         if (detect_doors(detect_rad)) ident = TRUE;\r
131                         if (detect_stairs(detect_rad)) ident = TRUE;\r
132                         break;\r
133                 }\r
134 \r
135                 case SV_STAFF_DETECT_INVIS:\r
136                 {\r
137                         if (detect_monsters_invis(detect_rad)) ident = TRUE;\r
138                         break;\r
139                 }\r
140 \r
141                 case SV_STAFF_DETECT_EVIL:\r
142                 {\r
143                         if (detect_monsters_evil(detect_rad)) ident = TRUE;\r
144                         break;\r
145                 }\r
146 \r
147                 case SV_STAFF_CURE_LIGHT:\r
148                 {\r
149                         ident = cure_light_wounds((powerful ? 4 : 2), 8);\r
150                         break;\r
151                 }\r
152 \r
153                 case SV_STAFF_CURING:\r
154                 {\r
155                         ident = true_healing(0);\r
156                         if (set_shero(0, TRUE)) ident = TRUE;\r
157                         break;\r
158                 }\r
159 \r
160                 case SV_STAFF_HEALING:\r
161                 {\r
162                         if (cure_critical_wounds(powerful ? 500 : 300)) ident = TRUE;\r
163                         break;\r
164                 }\r
165 \r
166                 case SV_STAFF_THE_MAGI:\r
167                 {\r
168                         if (do_res_stat(A_INT)) ident = TRUE;\r
169                         ident |= restore_mana(FALSE);\r
170                         if (set_shero(0, TRUE)) ident = TRUE;\r
171                         break;\r
172                 }\r
173 \r
174                 case SV_STAFF_SLEEP_MONSTERS:\r
175                 {\r
176                         if (sleep_monsters(lev)) ident = TRUE;\r
177                         break;\r
178                 }\r
179 \r
180                 case SV_STAFF_SLOW_MONSTERS:\r
181                 {\r
182                         if (slow_monsters(lev)) ident = TRUE;\r
183                         break;\r
184                 }\r
185 \r
186                 case SV_STAFF_SPEED:\r
187                 {\r
188                         if (set_fast(randint1(30) + (powerful ? 30 : 15), FALSE)) ident = TRUE;\r
189                         break;\r
190                 }\r
191 \r
192                 case SV_STAFF_PROBING:\r
193                 {\r
194                         ident = probing();\r
195                         break;\r
196                 }\r
197 \r
198                 case SV_STAFF_DISPEL_EVIL:\r
199                 {\r
200                         ident = dispel_evil(powerful ? 120 : 80);\r
201                         break;\r
202                 }\r
203 \r
204                 case SV_STAFF_POWER:\r
205                 {\r
206                         ident = dispel_monsters(powerful ? 225 : 150) ;\r
207                         break;\r
208                 }\r
209 \r
210                 case SV_STAFF_HOLINESS:\r
211                 {\r
212                         ident = cleansing_nova(p_ptr, magic, powerful);\r
213                         break;\r
214                 }\r
215 \r
216                 case SV_STAFF_GENOCIDE:\r
217                 {\r
218                         ident = symbol_genocide((magic ? lev + 50 : 200), TRUE);\r
219                         break;\r
220                 }\r
221 \r
222                 case SV_STAFF_EARTHQUAKES:\r
223                 {\r
224                         if (earthquake(p_ptr->y, p_ptr->x, (powerful ? 15 : 10)))\r
225                                 ident = TRUE;\r
226                         else\r
227                                 msg_print(_("ダンジョンが揺れた。", "The dungeon trembles."));\r
228 \r
229                         break;\r
230                 }\r
231 \r
232                 case SV_STAFF_DESTRUCTION:\r
233                 {\r
234                         ident = destroy_area(p_ptr->y, p_ptr->x, (powerful ? 18 : 13) + randint0(5), FALSE);\r
235                         break;\r
236                 }\r
237 \r
238                 case SV_STAFF_ANIMATE_DEAD:\r
239                 {\r
240                         ident = animate_dead(0, p_ptr->y, p_ptr->x);\r
241                         break;\r
242                 }\r
243 \r
244                 case SV_STAFF_MSTORM:\r
245                 {\r
246                         ident = unleash_mana_storm(p_ptr, powerful);\r
247                         break;\r
248                 }\r
249 \r
250                 case SV_STAFF_NOTHING:\r
251                 {\r
252                         msg_print(_("何も起らなかった。", "Nothing happen."));\r
253                         if (prace_is_(RACE_SKELETON) || prace_is_(RACE_GOLEM) ||\r
254                                 prace_is_(RACE_ZOMBIE) || prace_is_(RACE_SPECTRE))\r
255                                 msg_print(_("もったいない事をしたような気がする。食べ物は大切にしなくては。", "What a waste.  It's your food!"));\r
256                         break;\r
257                 }\r
258         }\r
259         return ident;\r
260 }\r
261 \r
262 /*!\r
263  * @brief 杖を使うコマンドのサブルーチン /\r
264  * Use a staff.                 -RAK-\r
265  * @param item 使うオブジェクトの所持品ID\r
266  * @return なし\r
267  * @details\r
268  * One charge of one staff disappears.\r
269  * Hack -- staffs of identify can be "cancelled".\r
270  */\r
271 void do_cmd_use_staff_aux(INVENTORY_IDX item)\r
272 {\r
273         int         ident, chance, lev;\r
274         object_type *o_ptr;\r
275 \r
276 \r
277         /* Hack -- let staffs of identify get aborted */\r
278         bool use_charge = TRUE;\r
279 \r
280 \r
281         /* Get the item (in the pack) */\r
282         if (item >= 0)\r
283         {\r
284                 o_ptr = &inventory[item];\r
285         }\r
286 \r
287         /* Get the item (on the floor) */\r
288         else\r
289         {\r
290                 o_ptr = &o_list[0 - item];\r
291         }\r
292 \r
293 \r
294         /* Mega-Hack -- refuse to use a pile from the ground */\r
295         if ((item < 0) && (o_ptr->number > 1))\r
296         {\r
297                 msg_print(_("まずは杖を拾わなければ。", "You must first pick up the staffs."));\r
298                 return;\r
299         }\r
300 \r
301 \r
302         take_turn(p_ptr, 100);;\r
303 \r
304         /* Extract the item level */\r
305         lev = k_info[o_ptr->k_idx].level;\r
306         if (lev > 50) lev = 50 + (lev - 50) / 2;\r
307 \r
308         /* Base chance of success */\r
309         chance = p_ptr->skill_dev;\r
310 \r
311         /* Confusion hurts skill */\r
312         if (p_ptr->confused) chance = chance / 2;\r
313 \r
314         /* Hight level objects are harder */\r
315         chance = chance - lev;\r
316 \r
317         /* Give everyone a (slight) chance */\r
318         if ((chance < USE_DEVICE) && one_in_(USE_DEVICE - chance + 1))\r
319         {\r
320                 chance = USE_DEVICE;\r
321         }\r
322 \r
323         if (cmd_limit_time_walk(p_ptr)) return;\r
324 \r
325         /* Roll for usage */\r
326         if ((chance < USE_DEVICE) || (randint1(chance) < USE_DEVICE) || (p_ptr->pclass == CLASS_BERSERKER))\r
327         {\r
328                 if (flush_failure) flush();\r
329                 msg_print(_("杖をうまく使えなかった。", "You failed to use the staff properly."));\r
330                 sound(SOUND_FAIL);\r
331                 return;\r
332         }\r
333 \r
334         /* Notice empty staffs */\r
335         if (o_ptr->pval <= 0)\r
336         {\r
337                 if (flush_failure) flush();\r
338                 msg_print(_("この杖にはもう魔力が残っていない。", "The staff has no charges left."));\r
339                 o_ptr->ident |= (IDENT_EMPTY);\r
340                 p_ptr->update |= (PU_COMBINE | PU_REORDER);\r
341                 p_ptr->window |= (PW_INVEN);\r
342 \r
343                 return;\r
344         }\r
345 \r
346 \r
347         sound(SOUND_ZAP);\r
348 \r
349         ident = staff_effect(o_ptr->sval, &use_charge, FALSE, FALSE, object_is_aware(o_ptr));\r
350 \r
351         if (!(object_is_aware(o_ptr)))\r
352         {\r
353                 chg_virtue(V_PATIENCE, -1);\r
354                 chg_virtue(V_CHANCE, 1);\r
355                 chg_virtue(V_KNOWLEDGE, -1);\r
356         }\r
357         p_ptr->update |= (PU_COMBINE | PU_REORDER);\r
358 \r
359         /* Tried the item */\r
360         object_tried(o_ptr);\r
361 \r
362         /* An identification was made */\r
363         if (ident && !object_is_aware(o_ptr))\r
364         {\r
365                 object_aware(o_ptr);\r
366                 gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev);\r
367         }\r
368 \r
369         p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);\r
370 \r
371 \r
372         /* Hack -- some uses are "free" */\r
373         if (!use_charge) return;\r
374 \r
375 \r
376         /* Use a single charge */\r
377         o_ptr->pval--;\r
378 \r
379         /* XXX Hack -- unstack if necessary */\r
380         if ((item >= 0) && (o_ptr->number > 1))\r
381         {\r
382                 object_type forge;\r
383                 object_type *q_ptr;\r
384                 q_ptr = &forge;\r
385 \r
386                 /* Obtain a local object */\r
387                 object_copy(q_ptr, o_ptr);\r
388 \r
389                 /* Modify quantity */\r
390                 q_ptr->number = 1;\r
391 \r
392                 /* Restore the charges */\r
393                 o_ptr->pval++;\r
394 \r
395                 /* Unstack the used item */\r
396                 o_ptr->number--;\r
397                 p_ptr->total_weight -= q_ptr->weight;\r
398                 item = inven_carry(q_ptr);\r
399 \r
400                 msg_print(_("杖をまとめなおした。", "You unstack your staff."));\r
401         }\r
402 \r
403         /* Describe charges in the pack */\r
404         if (item >= 0)\r
405         {\r
406                 inven_item_charges(item);\r
407         }\r
408 \r
409         /* Describe charges on the floor */\r
410         else\r
411         {\r
412                 floor_item_charges(0 - item);\r
413         }\r
414 }\r
415 \r
416 /*!\r
417 * @brief 杖を使うコマンドのメインルーチン /\r
418 * @return なし\r
419 */\r
420 void do_cmd_use_staff(void)\r
421 {\r
422         OBJECT_IDX item;\r
423         concptr q, s;\r
424 \r
425         if (p_ptr->wild_mode)\r
426         {\r
427                 return;\r
428         }\r
429 \r
430         if (cmd_limit_arena(p_ptr)) return;\r
431 \r
432         if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN))\r
433         {\r
434                 set_action(ACTION_NONE);\r
435         }\r
436 \r
437         /* Restrict choices to wands */\r
438         item_tester_tval = TV_STAFF;\r
439 \r
440         q = _("どの杖を使いますか? ", "Use which staff? ");\r
441         s = _("使える杖がない。", "You have no staff to use.");\r
442 \r
443         if (!choose_object(&item, q, s, (USE_INVEN | USE_FLOOR))) return;\r
444 \r
445         do_cmd_use_staff_aux(item);\r
446 }\r