OSDN Git Service

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