OSDN Git Service

[Refactor] #37353 rooms, grid, generate間のドア処理整理。 / Refactor between door process...
[hengband/hengband.git] / src / cmd-usestaff.c
1 #include "angband.h"\r
2 \r
3 \r
4 \r
5 /*!\r
6 * @brief 杖の効果を発動する\r
7 * @param sval オブジェクトのsval\r
8 * @param use_charge 使用回数を消費したかどうかを返す参照ポインタ\r
9 * @param powerful 強力発動上の処理ならばTRUE\r
10 * @param magic 魔道具術上の処理ならばTRUE\r
11 * @param known 判明済ならばTRUE\r
12 * @return 発動により効果内容が確定したならばTRUEを返す\r
13 */\r
14 int staff_effect(OBJECT_SUBTYPE_VALUE sval, bool *use_charge, bool powerful, bool magic, bool known)\r
15 {\r
16         int k;\r
17         int ident = FALSE;\r
18         int lev = powerful ? p_ptr->lev * 2 : p_ptr->lev;\r
19         int detect_rad = powerful ? DETECT_RAD_DEFAULT * 3 / 2 : DETECT_RAD_DEFAULT;\r
20 \r
21         /* Analyze the staff */\r
22         switch (sval)\r
23         {\r
24         case SV_STAFF_DARKNESS:\r
25         {\r
26                 if (!(p_ptr->resist_blind) && !(p_ptr->resist_dark))\r
27                 {\r
28                         if (set_blind(p_ptr->blind + 3 + randint1(5))) ident = TRUE;\r
29                 }\r
30                 if (unlite_area(10, (powerful ? 6 : 3))) ident = TRUE;\r
31                 break;\r
32         }\r
33 \r
34         case SV_STAFF_SLOWNESS:\r
35         {\r
36                 if (set_slow(p_ptr->slow + randint1(30) + 15, FALSE)) ident = TRUE;\r
37                 break;\r
38         }\r
39 \r
40         case SV_STAFF_HASTE_MONSTERS:\r
41         {\r
42                 if (speed_monsters()) ident = TRUE;\r
43                 break;\r
44         }\r
45 \r
46         case SV_STAFF_SUMMONING:\r
47         {\r
48                 const int times = randint1(powerful ? 8 : 4);\r
49                 for (k = 0; k < times; k++)\r
50                 {\r
51                         if (summon_specific(0, p_ptr->y, p_ptr->x, dun_level, 0, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET)))\r
52                         {\r
53                                 ident = TRUE;\r
54                         }\r
55                 }\r
56                 break;\r
57         }\r
58 \r
59         case SV_STAFF_TELEPORTATION:\r
60         {\r
61                 teleport_player((powerful ? 150 : 100), 0L);\r
62                 ident = TRUE;\r
63                 break;\r
64         }\r
65 \r
66         case SV_STAFF_IDENTIFY:\r
67         {\r
68                 if (powerful) {\r
69                         if (!identify_fully(FALSE)) *use_charge = FALSE;\r
70                 }\r
71                 else {\r
72                         if (!ident_spell(FALSE)) *use_charge = FALSE;\r
73                 }\r
74                 ident = TRUE;\r
75                 break;\r
76         }\r
77 \r
78         case SV_STAFF_REMOVE_CURSE:\r
79         {\r
80                 bool result = powerful ? remove_all_curse() : remove_curse();\r
81                 if (result)\r
82                 {\r
83                         if (magic)\r
84                         {\r
85                                 msg_print(_("誰かに見守られているような気がする。", "You feel as if someone is watching over you."));\r
86                         }\r
87                         else if (!p_ptr->blind)\r
88                         {\r
89                                 msg_print(_("杖は一瞬ブルーに輝いた...", "The staff glows blue for a moment..."));\r
90 \r
91                         }\r
92                         ident = TRUE;\r
93                 }\r
94                 break;\r
95         }\r
96 \r
97         case SV_STAFF_STARLITE:\r
98         {\r
99                 HIT_POINT num = damroll(5, 3);\r
100                 POSITION y = 0, x = 0;\r
101                 int attempts;\r
102 \r
103                 if (!p_ptr->blind && !magic)\r
104                 {\r
105                         msg_print(_("杖の先が明るく輝いた...", "The end of the staff glows brightly..."));\r
106                 }\r
107                 for (k = 0; k < num; k++)\r
108                 {\r
109                         attempts = 1000;\r
110 \r
111                         while (attempts--)\r
112                         {\r
113                                 scatter(&y, &x, p_ptr->y, p_ptr->x, 4, 0);\r
114 \r
115                                 if (!cave_have_flag_bold(y, x, FF_PROJECT)) continue;\r
116 \r
117                                 if (!player_bold(y, x)) break;\r
118                         }\r
119 \r
120                         project(0, 0, y, x, damroll(6 + lev / 8, 10), GF_LITE_WEAK,\r
121                                 (PROJECT_BEAM | PROJECT_THRU | PROJECT_GRID | PROJECT_KILL), -1);\r
122                 }\r
123                 ident = TRUE;\r
124                 break;\r
125         }\r
126 \r
127         case SV_STAFF_LITE:\r
128         {\r
129                 if (lite_area(damroll(2, 8), (powerful ? 4 : 2))) ident = TRUE;\r
130                 break;\r
131         }\r
132 \r
133         case SV_STAFF_MAPPING:\r
134         {\r
135                 map_area(powerful ? DETECT_RAD_MAP * 3 / 2 : DETECT_RAD_MAP);\r
136                 ident = TRUE;\r
137                 break;\r
138         }\r
139 \r
140         case SV_STAFF_DETECT_GOLD:\r
141         {\r
142                 if (detect_treasure(detect_rad)) ident = TRUE;\r
143                 if (detect_objects_gold(detect_rad)) ident = TRUE;\r
144                 break;\r
145         }\r
146 \r
147         case SV_STAFF_DETECT_ITEM:\r
148         {\r
149                 if (detect_objects_normal(detect_rad)) ident = TRUE;\r
150                 break;\r
151         }\r
152 \r
153         case SV_STAFF_DETECT_TRAP:\r
154         {\r
155                 if (detect_traps(detect_rad, known)) ident = TRUE;\r
156                 break;\r
157         }\r
158 \r
159         case SV_STAFF_DETECT_DOOR:\r
160         {\r
161                 if (detect_doors(detect_rad)) ident = TRUE;\r
162                 if (detect_stairs(detect_rad)) ident = TRUE;\r
163                 break;\r
164         }\r
165 \r
166         case SV_STAFF_DETECT_INVIS:\r
167         {\r
168                 if (detect_monsters_invis(detect_rad)) ident = TRUE;\r
169                 break;\r
170         }\r
171 \r
172         case SV_STAFF_DETECT_EVIL:\r
173         {\r
174                 if (detect_monsters_evil(detect_rad)) ident = TRUE;\r
175                 break;\r
176         }\r
177 \r
178         case SV_STAFF_CURE_LIGHT:\r
179         {\r
180                 if (hp_player(damroll((powerful ? 4 : 2), 8))) ident = TRUE;\r
181                 if (powerful) {\r
182                         if (set_blind(0)) ident = TRUE;\r
183                         if (set_poisoned(0)) ident = TRUE;\r
184                         if (set_cut(p_ptr->cut - 10)) ident = TRUE;\r
185                 }\r
186                 if (set_shero(0, TRUE)) ident = TRUE;\r
187                 break;\r
188         }\r
189 \r
190         case SV_STAFF_CURING:\r
191         {\r
192                 if (set_blind(0)) ident = TRUE;\r
193                 if (set_poisoned(0)) ident = TRUE;\r
194                 if (set_confused(0)) ident = TRUE;\r
195                 if (set_stun(0)) ident = TRUE;\r
196                 if (set_cut(0)) ident = TRUE;\r
197                 if (set_image(0)) ident = TRUE;\r
198                 if (set_shero(0, TRUE)) ident = TRUE;\r
199                 break;\r
200         }\r
201 \r
202         case SV_STAFF_HEALING:\r
203         {\r
204                 if (hp_player(powerful ? 500 : 300)) ident = TRUE;\r
205                 if (set_stun(0)) ident = TRUE;\r
206                 if (set_cut(0)) ident = TRUE;\r
207                 if (set_shero(0, TRUE)) ident = TRUE;\r
208                 break;\r
209         }\r
210 \r
211         case SV_STAFF_THE_MAGI:\r
212         {\r
213                 if (do_res_stat(A_INT)) ident = TRUE;\r
214                 if (p_ptr->csp < p_ptr->msp)\r
215                 {\r
216                         p_ptr->csp = p_ptr->msp;\r
217                         p_ptr->csp_frac = 0;\r
218                         ident = TRUE;\r
219                         msg_print(_("頭がハッキリとした。", "You feel your head clear."));\r
220 \r
221                         p_ptr->redraw |= (PR_MANA);\r
222                         p_ptr->window |= (PW_PLAYER);\r
223                         p_ptr->window |= (PW_SPELL);\r
224                 }\r
225                 if (set_shero(0, TRUE)) ident = TRUE;\r
226                 break;\r
227         }\r
228 \r
229         case SV_STAFF_SLEEP_MONSTERS:\r
230         {\r
231                 if (sleep_monsters(lev)) ident = TRUE;\r
232                 break;\r
233         }\r
234 \r
235         case SV_STAFF_SLOW_MONSTERS:\r
236         {\r
237                 if (slow_monsters(lev)) ident = TRUE;\r
238                 break;\r
239         }\r
240 \r
241         case SV_STAFF_SPEED:\r
242         {\r
243                 if (set_fast(randint1(30) + (powerful ? 30 : 15), FALSE)) ident = TRUE;\r
244                 break;\r
245         }\r
246 \r
247         case SV_STAFF_PROBING:\r
248         {\r
249                 probing();\r
250                 ident = TRUE;\r
251                 break;\r
252         }\r
253 \r
254         case SV_STAFF_DISPEL_EVIL:\r
255         {\r
256                 if (dispel_evil(powerful ? 120 : 80)) ident = TRUE;\r
257                 break;\r
258         }\r
259 \r
260         case SV_STAFF_POWER:\r
261         {\r
262                 if (dispel_monsters(powerful ? 225 : 150)) ident = TRUE;\r
263                 break;\r
264         }\r
265 \r
266         case SV_STAFF_HOLINESS:\r
267         {\r
268                 if (dispel_evil(powerful ? 225 : 150)) ident = TRUE;\r
269                 k = 3 * lev;\r
270                 if (set_protevil((magic ? 0 : p_ptr->protevil) + randint1(25) + k, FALSE)) ident = TRUE;\r
271                 if (set_poisoned(0)) ident = TRUE;\r
272                 if (set_afraid(0)) ident = TRUE;\r
273                 if (hp_player(50)) ident = TRUE;\r
274                 if (set_stun(0)) ident = TRUE;\r
275                 if (set_cut(0)) ident = TRUE;\r
276                 break;\r
277         }\r
278 \r
279         case SV_STAFF_GENOCIDE:\r
280         {\r
281                 (void)symbol_genocide((magic ? lev + 50 : 200), TRUE);\r
282                 ident = TRUE;\r
283                 break;\r
284         }\r
285 \r
286         case SV_STAFF_EARTHQUAKES:\r
287         {\r
288                 if (earthquake(p_ptr->y, p_ptr->x, (powerful ? 15 : 10)))\r
289                         ident = TRUE;\r
290                 else\r
291                         msg_print(_("ダンジョンが揺れた。", "The dungeon trembles."));\r
292 \r
293                 break;\r
294         }\r
295 \r
296         case SV_STAFF_DESTRUCTION:\r
297         {\r
298                 if (destroy_area(p_ptr->y, p_ptr->x, (powerful ? 18 : 13) + randint0(5), FALSE))\r
299                         ident = TRUE;\r
300 \r
301                 break;\r
302         }\r
303 \r
304         case SV_STAFF_ANIMATE_DEAD:\r
305         {\r
306                 if (animate_dead(0, p_ptr->y, p_ptr->x))\r
307                         ident = TRUE;\r
308 \r
309                 break;\r
310         }\r
311 \r
312         case SV_STAFF_MSTORM:\r
313         {\r
314                 msg_print(_("強力な魔力が敵を引き裂いた!", "Mighty magics rend your enemies!"));\r
315                 project(0, (powerful ? 7 : 5), p_ptr->y, p_ptr->x,\r
316                         (randint1(200) + (powerful ? 500 : 300)) * 2, GF_MANA, PROJECT_KILL | PROJECT_ITEM | PROJECT_GRID, -1);\r
317                 if ((p_ptr->pclass != CLASS_MAGE) && (p_ptr->pclass != CLASS_HIGH_MAGE) && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_MAGIC_EATER) && (p_ptr->pclass != CLASS_BLUE_MAGE))\r
318                 {\r
319                         (void)take_hit(DAMAGE_NOESCAPE, 50, _("コントロールし難い強力な魔力の解放", "unleashing magics too mighty to control"), -1);\r
320                 }\r
321                 ident = TRUE;\r
322 \r
323                 break;\r
324         }\r
325 \r
326         case SV_STAFF_NOTHING:\r
327         {\r
328                 msg_print(_("何も起らなかった。", "Nothing happen."));\r
329                 if (prace_is_(RACE_SKELETON) || prace_is_(RACE_GOLEM) ||\r
330                         prace_is_(RACE_ZOMBIE) || prace_is_(RACE_SPECTRE))\r
331                         msg_print(_("もったいない事をしたような気がする。食べ物は大切にしなくては。", "What a waste.  It's your food!"));\r
332                 break;\r
333         }\r
334         }\r
335         return ident;\r
336 }\r
337 \r
338 /*!\r
339  * @brief 杖を使うコマンドのサブルーチン /\r
340  * Use a staff.                 -RAK-\r
341  * @param item 使うオブジェクトの所持品ID\r
342  * @return なし\r
343  * @details\r
344  * One charge of one staff disappears.\r
345  * Hack -- staffs of identify can be "cancelled".\r
346  */\r
347 void do_cmd_use_staff_aux(int item)\r
348 {\r
349         int         ident, chance, lev;\r
350         object_type *o_ptr;\r
351 \r
352 \r
353         /* Hack -- let staffs of identify get aborted */\r
354         bool use_charge = TRUE;\r
355 \r
356 \r
357         /* Get the item (in the pack) */\r
358         if (item >= 0)\r
359         {\r
360                 o_ptr = &inventory[item];\r
361         }\r
362 \r
363         /* Get the item (on the floor) */\r
364         else\r
365         {\r
366                 o_ptr = &o_list[0 - item];\r
367         }\r
368 \r
369 \r
370         /* Mega-Hack -- refuse to use a pile from the ground */\r
371         if ((item < 0) && (o_ptr->number > 1))\r
372         {\r
373                 msg_print(_("まずは杖を拾わなければ。", "You must first pick up the staffs."));\r
374                 return;\r
375         }\r
376 \r
377 \r
378         /* Take a turn */\r
379         p_ptr->energy_use = 100;\r
380 \r
381         /* Extract the item level */\r
382         lev = k_info[o_ptr->k_idx].level;\r
383         if (lev > 50) lev = 50 + (lev - 50) / 2;\r
384 \r
385         /* Base chance of success */\r
386         chance = p_ptr->skill_dev;\r
387 \r
388         /* Confusion hurts skill */\r
389         if (p_ptr->confused) chance = chance / 2;\r
390 \r
391         /* Hight level objects are harder */\r
392         chance = chance - lev;\r
393 \r
394         /* Give everyone a (slight) chance */\r
395         if ((chance < USE_DEVICE) && one_in_(USE_DEVICE - chance + 1))\r
396         {\r
397                 chance = USE_DEVICE;\r
398         }\r
399 \r
400         if (world_player)\r
401         {\r
402                 if (flush_failure) flush();\r
403                 msg_print(_("止まった時の中ではうまく働かないようだ。", "Nothing happen. Maybe this staff is freezing too."));\r
404                 sound(SOUND_FAIL);\r
405                 return;\r
406         }\r
407 \r
408         /* Roll for usage */\r
409         if ((chance < USE_DEVICE) || (randint1(chance) < USE_DEVICE) || (p_ptr->pclass == CLASS_BERSERKER))\r
410         {\r
411                 if (flush_failure) flush();\r
412                 msg_print(_("杖をうまく使えなかった。", "You failed to use the staff properly."));\r
413                 sound(SOUND_FAIL);\r
414                 return;\r
415         }\r
416 \r
417         /* Notice empty staffs */\r
418         if (o_ptr->pval <= 0)\r
419         {\r
420                 if (flush_failure) flush();\r
421                 msg_print(_("この杖にはもう魔力が残っていない。", "The staff has no charges left."));\r
422                 o_ptr->ident |= (IDENT_EMPTY);\r
423 \r
424                 /* Combine / Reorder the pack (later) */\r
425                 p_ptr->notice |= (PN_COMBINE | PN_REORDER);\r
426                 p_ptr->window |= (PW_INVEN);\r
427 \r
428                 return;\r
429         }\r
430 \r
431 \r
432         /* Sound */\r
433         sound(SOUND_ZAP);\r
434 \r
435         ident = staff_effect(o_ptr->sval, &use_charge, FALSE, FALSE, object_is_aware(o_ptr));\r
436 \r
437         if (!(object_is_aware(o_ptr)))\r
438         {\r
439                 chg_virtue(V_PATIENCE, -1);\r
440                 chg_virtue(V_CHANCE, 1);\r
441                 chg_virtue(V_KNOWLEDGE, -1);\r
442         }\r
443 \r
444         /* Combine / Reorder the pack (later) */\r
445         p_ptr->notice |= (PN_COMBINE | PN_REORDER);\r
446 \r
447         /* Tried the item */\r
448         object_tried(o_ptr);\r
449 \r
450         /* An identification was made */\r
451         if (ident && !object_is_aware(o_ptr))\r
452         {\r
453                 object_aware(o_ptr);\r
454                 gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev);\r
455         }\r
456 \r
457         /* Window stuff */\r
458         p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);\r
459 \r
460 \r
461         /* Hack -- some uses are "free" */\r
462         if (!use_charge) return;\r
463 \r
464 \r
465         /* Use a single charge */\r
466         o_ptr->pval--;\r
467 \r
468         /* XXX Hack -- unstack if necessary */\r
469         if ((item >= 0) && (o_ptr->number > 1))\r
470         {\r
471                 object_type forge;\r
472                 object_type *q_ptr;\r
473 \r
474                 /* Get local object */\r
475                 q_ptr = &forge;\r
476 \r
477                 /* Obtain a local object */\r
478                 object_copy(q_ptr, o_ptr);\r
479 \r
480                 /* Modify quantity */\r
481                 q_ptr->number = 1;\r
482 \r
483                 /* Restore the charges */\r
484                 o_ptr->pval++;\r
485 \r
486                 /* Unstack the used item */\r
487                 o_ptr->number--;\r
488                 p_ptr->total_weight -= q_ptr->weight;\r
489                 item = inven_carry(q_ptr);\r
490 \r
491                 /* Message */\r
492                 msg_print(_("杖をまとめなおした。", "You unstack your staff."));\r
493         }\r
494 \r
495         /* Describe charges in the pack */\r
496         if (item >= 0)\r
497         {\r
498                 inven_item_charges(item);\r
499         }\r
500 \r
501         /* Describe charges on the floor */\r
502         else\r
503         {\r
504                 floor_item_charges(0 - item);\r
505         }\r
506 }\r
507 \r
508 /*!\r
509 * @brief 杖を使うコマンドのメインルーチン /\r
510 * @return なし\r
511 */\r
512 void do_cmd_use_staff(void)\r
513 {\r
514         OBJECT_IDX item;\r
515         cptr q, s;\r
516 \r
517         if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN))\r
518         {\r
519                 set_action(ACTION_NONE);\r
520         }\r
521 \r
522         /* Restrict choices to wands */\r
523         item_tester_tval = TV_STAFF;\r
524 \r
525         /* Get an item */\r
526         q = _("どの杖を使いますか? ", "Use which staff? ");\r
527         s = _("使える杖がない。", "You have no staff to use.");\r
528 \r
529         if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return;\r
530 \r
531         do_cmd_use_staff_aux(item);\r
532 }\r