OSDN Git Service

[Refactor] #40466 Moved hp_player() from player-effects.c/h to hp-mp-processor.c/h
[hengband/hengband.git] / src / realm / realm-arcane.c
1 #include "realm/realm-arcane.h"
2 #include "cmd-action/cmd-spell.h"
3 #include "core/asking-player.h"
4 #include "io/targeting.h"
5 #include "monster-floor/monster-summon.h"
6 #include "monster-floor/place-monster-types.h"
7 #include "player/avatar.h"
8 #include "player/digestion-processor.h"
9 #include "spell-kind/spells-beam.h"
10 #include "spell-kind/spells-detection.h"
11 #include "spell-kind/spells-floor.h"
12 #include "spell-kind/spells-launcher.h"
13 #include "spell-kind/spells-lite.h"
14 #include "spell-kind/spells-perception.h"
15 #include "spell-kind/spells-recall.h"
16 #include "spell-kind/spells-teleport.h"
17 #include "spell/spell-types.h"
18 #include "spell/spells-diceroll.h"
19 #include "spell/spells-object.h"
20 #include "spell/spells-status.h"
21 #include "spell/spells-summon.h"
22 #include "status/bad-status-setter.h"
23 #include "status/element-resistance.h"
24 #include "status/sight-setter.h"
25 #include "view/display-messages.h"
26
27 /*!
28 * @brief 秘術領域魔法の各処理を行う
29 * @param caster_ptr プレーヤーへの参照ポインタ
30 * @param spell 魔法ID
31 * @param mode 処理内容 (SPELL_NAME / SPELL_DESC / SPELL_INFO / SPELL_CAST)
32 * @return SPELL_NAME / SPELL_DESC / SPELL_INFO 時には文字列ポインタを返す。SPELL_CAST時はNULL文字列を返す。
33 */
34 concptr do_arcane_spell(player_type *caster_ptr, SPELL_IDX spell, spell_type mode)
35 {
36         bool name = (mode == SPELL_NAME) ? TRUE : FALSE;
37         bool desc = (mode == SPELL_DESC) ? TRUE : FALSE;
38         bool info = (mode == SPELL_INFO) ? TRUE : FALSE;
39         bool cast = (mode == SPELL_CAST) ? TRUE : FALSE;
40
41         DIRECTION dir;
42         PLAYER_LEVEL plev = caster_ptr->lev;
43
44         switch (spell)
45         {
46         case 0:
47                 if (name) return _("電撃", "Zap");
48                 if (desc) return _("電撃のボルトもしくはビームを放つ。", "Fires a bolt or beam of lightning.");
49
50                 {
51                         DICE_NUMBER dice = 3 + (plev - 1) / 5;
52                         DICE_SID sides = 3;
53
54                         if (info) return info_damage(dice, sides, 0);
55
56                         if (cast)
57                         {
58                                 if (!get_aim_dir(caster_ptr, &dir)) return NULL;
59
60                                 fire_bolt_or_beam(caster_ptr, beam_chance(caster_ptr) - 10, GF_ELEC, dir, damroll(dice, sides));
61                         }
62                 }
63                 break;
64
65         case 1:
66                 if (name) return _("魔法の施錠", "Wizard Lock");
67                 if (desc) return _("扉に鍵をかける。", "Locks a door.");
68
69                 {
70                         if (cast)
71                         {
72                                 if (!get_aim_dir(caster_ptr, &dir)) return NULL;
73
74                                 wizard_lock(caster_ptr, dir);
75                         }
76                 }
77                 break;
78
79         case 2:
80                 if (name) return _("透明体感知", "Detect Invisibility");
81                 if (desc) return _("近くの透明なモンスターを感知する。", "Detects all invisible monsters in your vicinity.");
82
83                 {
84                         POSITION rad = DETECT_RAD_DEFAULT;
85
86                         if (info) return info_radius(rad);
87
88                         if (cast)
89                         {
90                                 detect_monsters_invis(caster_ptr, rad);
91                         }
92                 }
93                 break;
94
95         case 3:
96                 if (name) return _("モンスター感知", "Detect Monsters");
97                 if (desc) return _("近くの全ての見えるモンスターを感知する。", "Detects all monsters in your vicinity unless invisible.");
98
99                 {
100                         POSITION rad = DETECT_RAD_DEFAULT;
101
102                         if (info) return info_radius(rad);
103
104                         if (cast)
105                         {
106                                 detect_monsters_normal(caster_ptr, rad);
107                         }
108                 }
109                 break;
110
111         case 4:
112                 if (name) return _("ショート・テレポート", "Blink");
113                 if (desc) return _("近距離のテレポートをする。", "Teleports you a short distance.");
114
115                 {
116                         POSITION range = 10;
117
118                         if (info) return info_range(range);
119
120                         if (cast)
121                         {
122                                 teleport_player(caster_ptr, range, TELEPORT_SPONTANEOUS);
123                         }
124                 }
125                 break;
126
127         case 5:
128                 if (name) return _("ライト・エリア", "Light Area");
129                 if (desc) return _("光源が照らしている範囲か部屋全体を永久に明るくする。", "Lights up nearby area and the inside of a room permanently.");
130
131                 {
132                         DICE_NUMBER dice = 2;
133                         DICE_SID sides = plev / 2;
134                         POSITION rad = plev / 10 + 1;
135
136                         if (info) return info_damage(dice, sides, 0);
137
138                         if (cast)
139                         {
140                                 lite_area(caster_ptr, damroll(dice, sides), rad);
141                         }
142                 }
143                 break;
144
145         case 6:
146                 if (name) return _("罠と扉 破壊", "Trap & Door Destruction");
147                 if (desc) return _("一直線上の全ての罠と扉を破壊する。", "Fires a beam which destroy traps and doors.");
148
149                 {
150                         if (cast)
151                         {
152                                 if (!get_aim_dir(caster_ptr, &dir)) return NULL;
153
154                                 destroy_door(caster_ptr, dir);
155                         }
156                 }
157                 break;
158
159         case 7:
160                 if (name) return _("軽傷の治癒", "Cure Light Wounds");
161                 if (desc) return _("怪我と体力を少し回復させる。", "Heals cuts and HP a little.");
162
163                 {
164                         DICE_NUMBER dice = 2;
165                         DICE_SID sides = 8;
166
167                         if (info) return info_heal(dice, sides, 0);
168                         if (cast) (void)cure_light_wounds(caster_ptr, dice, sides);
169                 }
170                 break;
171
172         case 8:
173                 if (name) return _("罠と扉 感知", "Detect Doors & Traps");
174                 if (desc) return _("近くの全ての罠と扉と階段を感知する。", "Detects traps, doors, and stairs in your vicinity.");
175
176                 {
177                         POSITION rad = DETECT_RAD_DEFAULT;
178
179                         if (info) return info_radius(rad);
180
181                         if (cast)
182                         {
183                                 detect_traps(caster_ptr, rad, TRUE);
184                                 detect_doors(caster_ptr, rad);
185                                 detect_stairs(caster_ptr, rad);
186                         }
187                 }
188                 break;
189
190         case 9:
191                 if (name) return _("燃素", "Phlogiston");
192                 if (desc) return _("光源に燃料を補給する。", "Adds more turns of light to a lantern or torch.");
193
194                 {
195                         if (cast)
196                         {
197                                 phlogiston(caster_ptr);
198                         }
199                 }
200                 break;
201
202         case 10:
203                 if (name) return _("財宝感知", "Detect Treasure");
204                 if (desc) return _("近くの財宝を感知する。", "Detects all treasures in your vicinity.");
205
206                 {
207                         POSITION rad = DETECT_RAD_DEFAULT;
208
209                         if (info) return info_radius(rad);
210
211                         if (cast)
212                         {
213                                 detect_treasure(caster_ptr, rad);
214                                 detect_objects_gold(caster_ptr, rad);
215                         }
216                 }
217                 break;
218
219         case 11:
220                 if (name) return _("魔法 感知", "Detect Enchantment");
221                 if (desc) return _("近くの魔法がかかったアイテムを感知する。", "Detects all magical items in your vicinity.");
222
223                 {
224                         POSITION rad = DETECT_RAD_DEFAULT;
225
226                         if (info) return info_radius(rad);
227
228                         if (cast)
229                         {
230                                 detect_objects_magic(caster_ptr, rad);
231                         }
232                 }
233                 break;
234
235         case 12:
236                 if (name) return _("アイテム感知", "Detect Objects");
237                 if (desc) return _("近くの全てのアイテムを感知する。", "Detects all items in your vicinity.");
238
239                 {
240                         POSITION rad = DETECT_RAD_DEFAULT;
241
242                         if (info) return info_radius(rad);
243
244                         if (cast)
245                         {
246                                 detect_objects_normal(caster_ptr, rad);
247                         }
248                 }
249                 break;
250
251         case 13:
252                 if (name) return _("解毒", "Cure Poison");
253                 if (desc) return _("毒を体内から完全に取り除く。", "Cures poison status.");
254
255                 {
256                         if (cast)
257                         {
258                                 set_poisoned(caster_ptr, 0);
259                         }
260                 }
261                 break;
262
263         case 14:
264                 if (name) return _("耐冷", "Resist Cold");
265                 if (desc) return _("一定時間、冷気への耐性を得る。装備による耐性に累積する。", "Gives resistance to cold. This resistance can be added to that from equipment for more powerful resistance.");
266
267                 {
268                         int base = 20;
269
270                         if (info) return info_duration(base, base);
271
272                         if (cast)
273                         {
274                                 set_oppose_cold(caster_ptr, randint1(base) + base, FALSE);
275                         }
276                 }
277                 break;
278
279         case 15:
280                 if (name) return _("耐火", "Resist Fire");
281                 if (desc) return _("一定時間、炎への耐性を得る。装備による耐性に累積する。",
282                         "Gives resistance to fire. This resistance can be added to that from equipment for more powerful resistance.");
283
284                 {
285                         int base = 20;
286
287                         if (info) return info_duration(base, base);
288
289                         if (cast)
290                         {
291                                 set_oppose_fire(caster_ptr, randint1(base) + base, FALSE);
292                         }
293                 }
294                 break;
295
296         case 16:
297                 if (name) return _("耐電", "Resist Lightning");
298                 if (desc) return _("一定時間、電撃への耐性を得る。装備による耐性に累積する。",
299                         "Gives resistance to electricity. This resistance can be added to that from equipment for more powerful resistance.");
300
301                 {
302                         int base = 20;
303
304                         if (info) return info_duration(base, base);
305
306                         if (cast)
307                         {
308                                 set_oppose_elec(caster_ptr, randint1(base) + base, FALSE);
309                         }
310                 }
311                 break;
312
313         case 17:
314                 if (name) return _("耐酸", "Resist Acid");
315                 if (desc) return _("一定時間、酸への耐性を得る。装備による耐性に累積する。",
316                         "Gives resistance to acid. This resistance can be added to that from equipment for more powerful resistance.");
317
318                 {
319                         int base = 20;
320
321                         if (info) return info_duration(base, base);
322
323                         if (cast)
324                         {
325                                 set_oppose_acid(caster_ptr, randint1(base) + base, FALSE);
326                         }
327                 }
328                 break;
329
330         case 18:
331                 if (name) return _("重傷の治癒", "Cure Medium Wounds");
332                 if (desc) return _("怪我と体力を中程度回復させる。", "Heals cuts and HP.");
333
334                 {
335                         DICE_NUMBER dice = 4;
336                         DICE_SID sides = 8;
337
338                         if (info) return info_heal(dice, sides, 0);
339                         if (cast) (void)cure_serious_wounds(caster_ptr, 4, 8);
340                 }
341                 break;
342
343         case 19:
344                 if (name) return _("テレポート", "Teleport");
345                 if (desc) return _("遠距離のテレポートをする。", "Teleports you a long distance.");
346
347                 {
348                         POSITION range = plev * 5;
349
350                         if (info) return info_range(range);
351
352                         if (cast)
353                         {
354                                 teleport_player(caster_ptr, range, TELEPORT_SPONTANEOUS);
355                         }
356                 }
357                 break;
358
359         case 20:
360                 if (name) return _("鑑定", "Identify");
361                 if (desc) return _("アイテムを識別する。", "Identifies an item.");
362
363                 {
364                         if (cast)
365                         {
366                                 if (!ident_spell(caster_ptr, FALSE, 0)) return NULL;
367                         }
368                 }
369                 break;
370
371         case 21:
372                 if (name) return _("岩石溶解", "Stone to Mud");
373                 if (desc) return _("壁を溶かして床にする。", "Turns one rock square to mud.");
374
375                 {
376                         DICE_NUMBER dice = 1;
377                         DICE_SID sides = 30;
378                         int base = 20;
379
380                         if (info) return info_damage(dice, sides, base);
381
382                         if (cast)
383                         {
384                                 if (!get_aim_dir(caster_ptr, &dir)) return NULL;
385
386                                 wall_to_mud(caster_ptr, dir, 20 + randint1(30));
387                         }
388                 }
389                 break;
390
391         case 22:
392                 if (name) return _("閃光", "Ray of Light");
393                 if (desc) return _("光線を放つ。光りを嫌うモンスターに効果がある。", "Fires a beam of light which damages to light-sensitive monsters.");
394
395                 {
396                         DICE_NUMBER dice = 6;
397                         DICE_SID sides = 8;
398
399                         if (info) return info_damage(dice, sides, 0);
400
401                         if (cast)
402                         {
403                                 if (!get_aim_dir(caster_ptr, &dir)) return NULL;
404
405                                 msg_print(_("光線が放たれた。", "A line of light appears."));
406                                 lite_line(caster_ptr, dir, damroll(6, 8));
407                         }
408                 }
409                 break;
410
411         case 23:
412                 if (name) return _("空腹充足", "Satisfy Hunger");
413                 if (desc) return _("満腹にする。", "Satisfies hunger.");
414
415                 {
416                         if (cast)
417                         {
418                                 set_food(caster_ptr, PY_FOOD_MAX - 1);
419                         }
420                 }
421                 break;
422
423         case 24:
424                 if (name) return _("透明視認", "See Invisible");
425                 if (desc) return _("一定時間、透明なものが見えるようになる。", "Gives see invisible for a while.");
426
427                 {
428                         int base = 24;
429
430                         if (info) return info_duration(base, base);
431
432                         if (cast)
433                         {
434                                 set_tim_invis(caster_ptr, randint1(base) + base, FALSE);
435                         }
436                 }
437                 break;
438
439         case 25:
440                 if (name) return _("エレメンタル召喚", "Conjure Elemental");
441                 if (desc) return _("1体のエレメンタルを召喚する。", "Summons an elemental.");
442                 {
443                         if (cast)
444                         {
445                                 if (!summon_specific(caster_ptr, -1, caster_ptr->y, caster_ptr->x, plev, SUMMON_ELEMENTAL, (PM_ALLOW_GROUP | PM_FORCE_PET)))
446                                 {
447                                         msg_print(_("エレメンタルは現れなかった。", "No Elementals arrive."));
448                                 }
449                         }
450                 }
451                 break;
452
453         case 26:
454                 if (name) return _("テレポート・レベル", "Teleport Level");
455                 if (desc) return _("瞬時に上か下の階にテレポートする。", "Instantly teleports you up or down a level.");
456
457                 {
458                         if (cast)
459                         {
460                                 if (!get_check(_("本当に他の階にテレポートしますか?", "Are you sure? (Teleport Level)"))) return NULL;
461                                 teleport_level(caster_ptr, 0);
462                         }
463                 }
464                 break;
465
466         case 27:
467                 if (name) return _("テレポート・モンスター", "Teleport Away");
468                 if (desc) return _("モンスターをテレポートさせるビームを放つ。抵抗されると無効。", "Teleports all monsters on the line away unless resisted.");
469
470                 {
471                         int power = plev;
472
473                         if (info) return info_power(power);
474
475                         if (cast)
476                         {
477                                 if (!get_aim_dir(caster_ptr, &dir)) return NULL;
478
479                                 fire_beam(caster_ptr, GF_AWAY_ALL, dir, power);
480                         }
481                 }
482                 break;
483
484         case 28:
485                 if (name) return _("元素の球", "Elemental Ball");
486                 if (desc) return _("炎、電撃、冷気、酸のどれかの球を放つ。", "Fires a ball of some elements.");
487
488                 {
489                         HIT_POINT dam = 75 + plev;
490                         POSITION rad = 2;
491
492                         if (info) return info_damage(0, 0, dam);
493
494                         if (cast)
495                         {
496                                 int type;
497
498                                 if (!get_aim_dir(caster_ptr, &dir)) return NULL;
499
500                                 switch (randint1(4))
501                                 {
502                                 case 1:  type = GF_FIRE; break;
503                                 case 2:  type = GF_ELEC; break;
504                                 case 3:  type = GF_COLD; break;
505                                 default: type = GF_ACID; break;
506                                 }
507
508                                 fire_ball(caster_ptr, type, dir, dam, rad);
509                         }
510                 }
511                 break;
512
513         case 29:
514                 if (name) return _("全感知", "Detection");
515                 if (desc) return _("近くの全てのモンスター、罠、扉、階段、財宝、そしてアイテムを感知する。",
516                         "Detects all monsters, traps, doors, stairs, treasures and items in your vicinity.");
517
518                 {
519                         POSITION rad = DETECT_RAD_DEFAULT;
520
521                         if (info) return info_radius(rad);
522
523                         if (cast)
524                         {
525                                 detect_all(caster_ptr, rad);
526                         }
527                 }
528                 break;
529
530         case 30:
531                 if (name) return _("帰還の呪文", "Word of Recall");
532                 if (desc) return _("地上にいるときはダンジョンの最深階へ、ダンジョンにいるときは地上へと移動する。",
533                         "Recalls player from dungeon to town or from town to the deepest level of dungeon.");
534
535                 {
536                         int base = 15;
537                         DICE_SID sides = 20;
538
539                         if (info) return info_delay(base, sides);
540
541                         if (cast)
542                         {
543                                 if (!recall_player(caster_ptr, randint0(21) + 15)) return NULL;
544                         }
545                 }
546                 break;
547
548         case 31:
549                 if (name) return _("千里眼", "Clairvoyance");
550                 if (desc) return _("その階全体を永久に照らし、ダンジョン内すべてのアイテムを感知する。さらに、一定時間テレパシー能力を得る。",
551                         "Maps and lights whole dungeon level. Reveals locations of all objects. Gives telepathy for a while.");
552
553                 {
554                         int base = 25;
555                         DICE_SID sides = 30;
556
557                         if (info) return info_duration(base, sides);
558
559                         if (cast)
560                         {
561                                 chg_virtue(caster_ptr, V_KNOWLEDGE, 1);
562                                 chg_virtue(caster_ptr, V_ENLIGHTEN, 1);
563
564                                 wiz_lite(caster_ptr, FALSE);
565
566                                 if (!caster_ptr->telepathy)
567                                 {
568                                         set_tim_esp(caster_ptr, randint1(sides) + base, FALSE);
569                                 }
570                         }
571                 }
572                 break;
573         }
574
575         return "";
576 }