OSDN Git Service

[Refactor] enum spells-typeをenum class AttributeTypeに置換
[hengbandforosx/hengbandosx.git] / src / realm / realm-crusade.cpp
1 #include "realm/realm-crusade.h"
2 #include "cmd-action/cmd-spell.h"
3 #include "effect/effect-characteristics.h"
4 #include "effect/effect-processor.h"
5 #include "floor/cave.h"
6 #include "floor/floor-util.h"
7 #include "hpmp/hp-mp-processor.h"
8 #include "monster-floor/monster-summon.h"
9 #include "monster-floor/place-monster-types.h"
10 #include "player-info/class-info.h"
11 #include "spell-kind/spells-beam.h"
12 #include "spell-kind/spells-curse-removal.h"
13 #include "spell-kind/spells-detection.h"
14 #include "spell-kind/spells-floor.h"
15 #include "spell-kind/spells-launcher.h"
16 #include "spell-kind/spells-neighbor.h"
17 #include "spell-kind/spells-sight.h"
18 #include "spell-kind/spells-teleport.h"
19 #include "spell-realm/spells-crusade.h"
20 #include "effect/attribute-types.h"
21 #include "spell/spells-diceroll.h"
22 #include "spell/spells-object.h"
23 #include "spell/spells-status.h"
24 #include "spell/summon-types.h"
25 #include "status/bad-status-setter.h"
26 #include "status/body-improvement.h"
27 #include "status/buff-setter.h"
28 #include "status/sight-setter.h"
29 #include "system/player-type-definition.h"
30 #include "target/target-getter.h"
31 #include "view/display-messages.h"
32 #include "world/world.h"
33
34 /*!
35  * @brief 破邪領域魔法の各処理を行う
36  * @param player_ptr プレイヤーへの参照ポインタ
37  * @param spell 魔法ID
38  * @param mode 処理内容 (SpellProcessType::NAME / SPELL_DESC / SpellProcessType::INFO / SpellProcessType::CAST)
39  * @return SpellProcessType::NAME / SPELL_DESC / SpellProcessType::INFO 時には文字列ポインタを返す。SpellProcessType::CAST時はnullptr文字列を返す。
40  */
41 concptr do_crusade_spell(player_type *player_ptr, SPELL_IDX spell, SpellProcessType mode)
42 {
43     bool name = mode == SpellProcessType::NAME;
44     bool desc = mode == SpellProcessType::DESCRIPTION;
45     bool info = mode == SpellProcessType::INFO;
46     bool cast = mode == SpellProcessType::CAST;
47
48     DIRECTION dir;
49     PLAYER_LEVEL plev = player_ptr->lev;
50
51     switch (spell) {
52     case 0:
53         if (name)
54             return _("懲罰", "Punishment");
55         if (desc)
56             return _("電撃のボルトもしくはビームを放つ。", "Fires a bolt or beam of lightning.");
57         {
58             DICE_NUMBER dice = 3 + (plev - 1) / 5;
59             DICE_SID sides = 4;
60             if (info)
61                 return info_damage(dice, sides, 0);
62             if (cast) {
63                 if (!get_aim_dir(player_ptr, &dir))
64                     return nullptr;
65                 fire_bolt_or_beam(player_ptr, beam_chance(player_ptr) - 10, AttributeType::ELEC, dir, damroll(dice, sides));
66             }
67         }
68         break;
69
70     case 1:
71         if (name)
72             return _("邪悪存在感知", "Detect Evil");
73         if (desc)
74             return _("近くの邪悪なモンスターを感知する。", "Detects all evil monsters in your vicinity.");
75         {
76             POSITION rad = DETECT_RAD_DEFAULT;
77             if (info)
78                 return info_radius(rad);
79             if (cast) {
80                 detect_monsters_evil(player_ptr, rad);
81             }
82         }
83         break;
84
85     case 2:
86         if (name) {
87             return _("恐怖除去", "Remove Fear");
88         }
89
90         if (desc) {
91             return _("恐怖を取り除く。", "Removes fear.");
92         }
93
94         if (cast) {
95             (void)BadStatusSetter(player_ptr).afraidness(0);
96         }
97
98         break;
99     case 3:
100         if (name)
101             return _("威圧", "Scare Monster");
102         if (desc)
103             return _("モンスター1体を恐怖させる。抵抗されると無効。", "Attempts to scare a monster.");
104
105         {
106             PLAYER_LEVEL power = plev;
107             if (info)
108                 return info_power(power);
109             if (cast) {
110                 if (!get_aim_dir(player_ptr, &dir))
111                     return nullptr;
112                 fear_monster(player_ptr, dir, power);
113             }
114         }
115         break;
116
117     case 4:
118         if (name)
119             return _("聖域", "Sanctuary");
120         if (desc)
121             return _("隣接した全てのモンスターを眠らせる。抵抗されると無効。", "Attempts to put to sleep monsters in the adjacent squares.");
122         {
123             PLAYER_LEVEL power = plev;
124             if (info)
125                 return info_power(power);
126             if (cast)
127                 sleep_monsters_touch(player_ptr);
128         }
129         break;
130
131     case 5:
132         if (name)
133             return _("入口", "Portal");
134         if (desc)
135             return _("中距離のテレポートをする。", "Teleports you a medium distance.");
136
137         {
138             POSITION range = 25 + plev / 2;
139             if (info)
140                 return info_range(range);
141             if (cast)
142                 teleport_player(player_ptr, range, TELEPORT_SPONTANEOUS);
143         }
144         break;
145
146     case 6:
147         if (name)
148             return _("スターダスト", "Star Dust");
149         if (desc)
150             return _("ターゲット付近に閃光のボルトを連射する。", "Fires many bolts of light near the target.");
151
152         {
153             DICE_NUMBER dice = 3 + (plev - 1) / 9;
154             DICE_SID sides = 2;
155             if (info)
156                 return info_multi_damage_dice(dice, sides);
157             if (cast) {
158                 if (!get_aim_dir(player_ptr, &dir))
159                     return nullptr;
160                 fire_blast(player_ptr, AttributeType::LITE, dir, dice, sides, 10, 3);
161             }
162         }
163         break;
164
165     case 7:
166         if (name) {
167             return _("身体浄化", "Purify");
168         }
169
170         if (desc) {
171             return _("傷、毒、朦朧から全快する。", "Heals all cuts, poisons and being stunned.");
172         }
173
174         if (cast) {
175             BadStatusSetter bss(player_ptr);
176             (void)bss.cut(0);
177             (void)bss.poison(0);
178             (void)bss.stun(0);
179         }
180
181         break;
182
183     case 8:
184         if (name)
185             return _("邪悪飛ばし", "Scatter Evil");
186         if (desc)
187             return _("邪悪なモンスター1体をテレポートさせる。抵抗されると無効。", "Attempts to teleport an evil monster away.");
188
189         {
190             int power = MAX_SIGHT * 5;
191             if (info)
192                 return info_power(power);
193             if (cast) {
194                 if (!get_aim_dir(player_ptr, &dir))
195                     return nullptr;
196                 fire_ball(player_ptr, AttributeType::AWAY_EVIL, dir, power, 0);
197             }
198         }
199         break;
200
201     case 9:
202         if (name)
203             return _("聖なる光球", "Holy Orb");
204         if (desc)
205             return _("聖なる力をもつ宝珠を放つ。邪悪なモンスターに対して大きなダメージを与えるが、善良なモンスターには効果がない。",
206                 "Fires a ball with holy power. Hurts evil monsters greatly but doesn't affect good monsters.");
207
208         {
209             DICE_NUMBER dice = 3;
210             DICE_SID sides = 6;
211             POSITION rad = (plev < 30) ? 2 : 3;
212             int base;
213             if (player_ptr->pclass == PlayerClassType::PRIEST || player_ptr->pclass == PlayerClassType::HIGH_MAGE || player_ptr->pclass == PlayerClassType::SORCERER)
214                 base = plev + plev / 2;
215             else
216                 base = plev + plev / 4;
217
218             if (info)
219                 return info_damage(dice, sides, base);
220
221             if (cast) {
222                 if (!get_aim_dir(player_ptr, &dir))
223                     return nullptr;
224
225                 fire_ball(player_ptr, AttributeType::HOLY_FIRE, dir, damroll(dice, sides) + base, rad);
226             }
227         }
228         break;
229
230     case 10:
231         if (name)
232             return _("悪魔払い", "Exorcism");
233         if (desc)
234             return _("視界内の全てのアンデッド及び悪魔にダメージを与え、邪悪なモンスターを恐怖させる。",
235                 "Damages all undead and demons in sight, and scares all evil monsters in sight.");
236         {
237             DICE_SID sides = plev;
238             int power = plev;
239             if (info)
240                 return info_damage(1, sides, 0);
241             if (cast) {
242                 dispel_undead(player_ptr, randint1(sides));
243                 dispel_demons(player_ptr, randint1(sides));
244                 turn_evil(player_ptr, power);
245             }
246         }
247         break;
248
249     case 11:
250         if (name)
251             return _("解呪", "Remove Curse");
252         if (desc)
253             return _("アイテムにかかった弱い呪いを解除する。", "Removes normal curses from equipped items.");
254         {
255             if (cast)
256                 (void)remove_curse(player_ptr);
257         }
258         break;
259
260     case 12:
261         if (name)
262             return _("透明視認", "Sense Unseen");
263         if (desc)
264             return _("一定時間、透明なものが見えるようになる。", "Gives see invisible for a while.");
265
266         {
267             int base = 24;
268
269             if (info)
270                 return info_duration(base, base);
271
272             if (cast) {
273                 set_tim_invis(player_ptr, randint1(base) + base, false);
274             }
275         }
276         break;
277
278     case 13:
279         if (name)
280             return _("対邪悪結界", "Protection from Evil");
281         if (desc)
282             return _("邪悪なモンスターの攻撃を防ぐバリアを張る。", "Gives aura which protects you from evil monster's physical attack.");
283
284         {
285             int base = 25;
286             DICE_SID sides = 3 * plev;
287
288             if (info)
289                 return info_duration(base, sides);
290
291             if (cast) {
292                 set_protevil(player_ptr, randint1(sides) + base, false);
293             }
294         }
295         break;
296
297     case 14:
298         if (name)
299             return _("裁きの雷", "Judgment Thunder");
300         if (desc)
301             return _("強力な電撃のボルトを放つ。", "Fires a powerful bolt of lightning.");
302
303         {
304             HIT_POINT dam = plev * 5;
305
306             if (info)
307                 return info_damage(0, 0, dam);
308
309             if (cast) {
310                 if (!get_aim_dir(player_ptr, &dir))
311                     return nullptr;
312                 fire_bolt(player_ptr, AttributeType::ELEC, dir, dam);
313             }
314         }
315         break;
316
317     case 15: {
318         if (name) {
319             return _("聖なる御言葉", "Holy Word");
320         }
321
322         if (desc) {
323             return _("視界内の邪悪な存在に大きなダメージを与え、体力を回復し、毒、恐怖、朦朧状態、負傷から全快する。",
324                 "Damages all evil monsters in sight, heals HP somewhat and completely cures fear, poisons, cuts and being stunned.");
325         }
326
327         auto dam_sides = plev * 6;
328         auto heal = 100;
329         if (info) {
330             return format(_("損:1d%d/回%d", "dam:d%d/h%d"), dam_sides, heal);
331         }
332
333         if (cast) {
334             BadStatusSetter bss(player_ptr);
335             dispel_evil(player_ptr, randint1(dam_sides));
336             hp_player(player_ptr, heal);
337             (void)bss.afraidness(0);
338             (void)bss.poison(0);
339             (void)bss.stun(0);
340             (void)bss.cut(0);
341         }
342
343         break;
344     }    
345     case 16:
346         if (name)
347             return _("開かれた道", "Unbarring Ways");
348         if (desc)
349             return _("一直線上の全ての罠と扉を破壊する。", "Fires a beam which destroy traps and doors.");
350
351         {
352             if (cast) {
353                 if (!get_aim_dir(player_ptr, &dir))
354                     return nullptr;
355
356                 destroy_door(player_ptr, dir);
357             }
358         }
359         break;
360
361     case 17:
362         if (name)
363             return _("封魔", "Arrest");
364         if (desc)
365             return _("邪悪なモンスターの動きを止める。", "Attempts to paralyze an evil monster.");
366
367         {
368             int power = plev * 2;
369
370             if (info)
371                 return info_power(power);
372
373             if (cast) {
374                 if (!get_aim_dir(player_ptr, &dir))
375                     return nullptr;
376                 stasis_evil(player_ptr, dir);
377             }
378         }
379         break;
380
381     case 18:
382         if (name)
383             return _("聖なるオーラ", "Holy Aura");
384         if (desc)
385             return _("一定時間、邪悪なモンスターを傷つける聖なるオーラを得る。",
386                 "Gives a temporary aura of holy power that injures evil monsters which attack you.");
387
388         {
389             int base = 20;
390
391             if (info)
392                 return info_duration(base, base);
393
394             if (cast) {
395                 set_tim_sh_holy(player_ptr, randint1(base) + base, false);
396             }
397         }
398         break;
399
400     case 19:
401         if (name)
402             return _("アンデッド&悪魔退散", "Dispel Undead & Demons");
403         if (desc)
404             return _("視界内の全てのアンデッド及び悪魔にダメージを与える。", "Damages all undead and demons in sight.");
405
406         {
407             DICE_SID sides = plev * 4;
408
409             if (info)
410                 return info_damage(1, sides, 0);
411
412             if (cast) {
413                 dispel_undead(player_ptr, randint1(sides));
414                 dispel_demons(player_ptr, randint1(sides));
415             }
416         }
417         break;
418
419     case 20:
420         if (name)
421             return _("邪悪退散", "Dispel Evil");
422         if (desc)
423             return _("視界内の全ての邪悪なモンスターにダメージを与える。", "Damages all evil monsters in sight.");
424
425         {
426             DICE_SID sides = plev * 4;
427
428             if (info)
429                 return info_damage(1, sides, 0);
430
431             if (cast) {
432                 dispel_evil(player_ptr, randint1(sides));
433             }
434         }
435         break;
436
437     case 21:
438         if (name)
439             return _("聖なる刃", "Holy Blade");
440         if (desc)
441             return _("通常の武器に滅邪の属性をつける。", "Makes current weapon especially deadly against evil monsters.");
442
443         {
444             if (cast) {
445                 brand_weapon(player_ptr, 13);
446             }
447         }
448         break;
449
450     case 22:
451         if (name)
452             return _("スターバースト", "Star Burst");
453         if (desc)
454             return _("巨大な閃光の球を放つ。", "Fires a huge ball of powerful light.");
455
456         {
457             HIT_POINT dam = 100 + plev * 2;
458             POSITION rad = 4;
459
460             if (info)
461                 return info_damage(0, 0, dam);
462
463             if (cast) {
464                 if (!get_aim_dir(player_ptr, &dir))
465                     return nullptr;
466
467                 fire_ball(player_ptr, AttributeType::LITE, dir, dam, rad);
468             }
469         }
470         break;
471
472     case 23:
473         if (name)
474             return _("天使召喚", "Summon Angel");
475         if (desc)
476             return _("天使を1体召喚する。", "Summons an angel.");
477
478         {
479             if (cast) {
480                 bool pet = !one_in_(3);
481                 uint32_t flg = 0L;
482
483                 if (pet)
484                     flg |= PM_FORCE_PET;
485                 else
486                     flg |= PM_NO_PET;
487                 if (!(pet && (plev < 50)))
488                     flg |= PM_ALLOW_GROUP;
489
490                 if (summon_specific(player_ptr, (pet ? -1 : 0), player_ptr->y, player_ptr->x, (plev * 3) / 2, SUMMON_ANGEL, flg)) {
491                     if (pet) {
492                         msg_print(_("「ご用でございますか、ご主人様」", "'What is thy bidding... Master?'"));
493                     } else {
494                         msg_print(_("「我は汝の下僕にあらず! 悪行者よ、悔い改めよ!」", "Mortal! Repent of thy impiousness."));
495                     }
496                 }
497             }
498         }
499         break;
500
501     case 24:
502         if (name)
503             return _("士気高揚", "Heroism");
504         if (desc)
505             return _("一定時間、ヒーロー気分になる。", "Removes fear. Gives a bonus to hit for a while. Heals you for 10 HP.");
506
507         {
508             int base = 25;
509
510             if (info)
511                 return info_duration(base, base);
512
513             if (cast) {
514                 (void)heroism(player_ptr, base);
515             }
516         }
517         break;
518
519     case 25:
520         if (name)
521             return _("呪い退散", "Dispel Curse");
522         if (desc)
523             return _("アイテムにかかった強力な呪いを解除する。", "Removes normal and heavy curses from equipped items.");
524
525         {
526             if (cast)
527                 (void)remove_all_curse(player_ptr);
528         }
529         break;
530
531     case 26:
532         if (name)
533             return _("邪悪追放", "Banish Evil");
534         if (desc)
535             return _("視界内の全ての邪悪なモンスターをテレポートさせる。抵抗されると無効。", "Teleports all evil monsters in sight away unless resisted.");
536
537         {
538             int power = 100;
539
540             if (info)
541                 return info_power(power);
542
543             if (cast) {
544                 if (banish_evil(player_ptr, power)) {
545                     msg_print(_("神聖な力が邪悪を打ち払った!", "The holy power banishes evil!"));
546                 }
547             }
548         }
549         break;
550
551     case 27:
552         if (name)
553             return _("ハルマゲドン", "Armageddon");
554         if (desc)
555             return _("周辺のアイテム、モンスター、地形を破壊する。", "Destroys everything in nearby area.");
556
557         {
558             int base = 12;
559             DICE_SID sides = 4;
560
561             if (cast) {
562                 destroy_area(player_ptr, player_ptr->y, player_ptr->x, base + randint1(sides), false);
563             }
564         }
565         break;
566
567     case 28:
568         if (name)
569             return _("目には目を", "An Eye for an Eye");
570         if (desc)
571             return _("一定時間、自分がダメージを受けたときに攻撃を行ったモンスターに対して同等のダメージを与える。",
572                 "Gives special aura for a while. When you are attacked by a monster, the monster is injured with same amount of damage as you took.");
573
574         {
575             int base = 10;
576
577             if (info)
578                 return info_duration(base, base);
579
580             if (cast) {
581                 set_tim_eyeeye(player_ptr, randint1(base) + base, false);
582             }
583         }
584         break;
585
586     case 29:
587         if (name)
588             return _("神の怒り", "Wrath of the God");
589         if (desc)
590             return _("ターゲットの周囲に分解の球を多数落とす。", "Drops many balls of disintegration near the target.");
591
592         {
593             HIT_POINT dam = plev * 3 + 25;
594             POSITION rad = 2;
595
596             if (info)
597                 return info_multi_damage(dam);
598
599             if (cast) {
600                 if (!cast_wrath_of_the_god(player_ptr, dam, rad))
601                     return nullptr;
602             }
603         }
604         break;
605
606     case 30:
607         if (name)
608             return _("神威", "Divine Intervention");
609         if (desc)
610             return _("隣接するモンスターに聖なるダメージを与え、視界内のモンスターにダメージ、減速、朦朧、混乱、恐怖、眠りを与える。さらに体力を回復する。",
611                 "Damages all adjacent monsters with holy power. Damages and attempt to slow, stun, confuse, scare and freeze all monsters in sight. And heals "
612                 "HP.");
613
614         {
615             int b_dam = plev * 11;
616             int d_dam = plev * 4;
617             int heal = 100;
618             int power = plev * 4;
619
620             if (info)
621                 return format(_("回%d/損%d+%d", "h%d/dm%d+%d"), heal, d_dam, b_dam / 2);
622             if (cast) {
623                 project(player_ptr, 0, 1, player_ptr->y, player_ptr->x, b_dam, AttributeType::HOLY_FIRE, PROJECT_KILL);
624                 dispel_monsters(player_ptr, d_dam);
625                 slow_monsters(player_ptr, plev);
626                 stun_monsters(player_ptr, power);
627                 confuse_monsters(player_ptr, power);
628                 turn_monsters(player_ptr, power);
629                 stasis_monsters(player_ptr, power);
630                 hp_player(player_ptr, heal);
631             }
632         }
633         break;
634
635     case 31:
636         if (name) {
637             return _("聖戦", "Crusade");
638         }
639
640         if (desc) {
641             return _("視界内の善良なモンスターをペットにしようとし、ならなかった場合及び善良でないモンスターを恐怖させる。さらに多数の加速された騎士を召喚し、"
642                      "ヒーロー、祝福、加速、対邪悪結界を得る。",
643                 "Attempts to charm all good monsters in sight and scares all non-charmed monsters. Summons a great number of knights. Gives heroism, bless, "
644                 "speed and protection from evil to the caster.");
645         }
646         
647         if (cast) {
648             auto base = 25;
649             auto sp_sides = 20 + plev;
650             auto sp_base = plev;
651             crusade(player_ptr);
652             for (auto i = 0; i < 12; i++) {
653                 auto attempt = 10;
654                 POSITION my = 0, mx = 0;
655                 while (attempt--) {
656                     scatter(player_ptr, &my, &mx, player_ptr->y, player_ptr->x, 4, PROJECT_NONE);
657                     if (is_cave_empty_bold2(player_ptr, my, mx)) {
658                         break;
659                     }
660                 }
661
662                 if (attempt < 0) {
663                     continue;
664                 }
665
666                 summon_specific(player_ptr, -1, my, mx, plev, SUMMON_KNIGHTS, PM_ALLOW_GROUP | PM_FORCE_PET | PM_HASTE);
667             }
668
669             set_hero(player_ptr, randint1(base) + base, false);
670             set_blessed(player_ptr, randint1(base) + base, false);
671             set_fast(player_ptr, randint1(sp_sides) + sp_base, false);
672             set_protevil(player_ptr, randint1(base) + base, false);
673             (void)BadStatusSetter(player_ptr).afraidness(0);
674         }
675
676         break;
677     }
678
679     return "";
680 }