OSDN Git Service

[Refactor] #3286 Removed player-redraw-types.h
[hengbandforosx/hengbandosx.git] / src / realm / realm-chaos.cpp
1 #include "realm/realm-chaos.h"
2 #include "cmd-action/cmd-spell.h"
3 #include "core/asking-player.h"
4 #include "effect/attribute-types.h"
5 #include "effect/effect-characteristics.h"
6 #include "effect/effect-processor.h"
7 #include "player-base/player-class.h"
8 #include "player/attack-defense-types.h"
9 #include "spell-kind/magic-item-recharger.h"
10 #include "spell-kind/spells-floor.h"
11 #include "spell-kind/spells-launcher.h"
12 #include "spell-kind/spells-lite.h"
13 #include "spell-kind/spells-neighbor.h"
14 #include "spell-kind/spells-random.h"
15 #include "spell-kind/spells-teleport.h"
16 #include "spell-kind/spells-world.h"
17 #include "spell-realm/spells-chaos.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/shape-changer.h"
23 #include "system/player-type-definition.h"
24 #include "system/redrawing-flags-updater.h"
25 #include "target/target-getter.h"
26 #include "view/display-messages.h"
27
28 /*!
29  * @brief カオス領域魔法の各処理を行う
30  * @param player_ptr プレイヤーへの参照ポインタ
31  * @param spell 魔法ID
32  * @param mode 処理内容 (SpellProcessType::NAME / SPELL_DESC / SpellProcessType::INFO / SpellProcessType::CAST)
33  * @return SpellProcessType::NAME / SPELL_DESC / SpellProcessType::INFO 時には文字列を返す。SpellProcessType::CAST時は std::nullopt を返す。
34  */
35 std::optional<std::string> do_chaos_spell(PlayerType *player_ptr, SPELL_IDX spell, SpellProcessType mode)
36 {
37     bool name = mode == SpellProcessType::NAME;
38     bool desc = mode == SpellProcessType::DESCRIPTION;
39     bool info = mode == SpellProcessType::INFO;
40     bool cast = mode == SpellProcessType::CAST;
41
42     DIRECTION dir;
43     PLAYER_LEVEL plev = player_ptr->lev;
44
45     switch (spell) {
46     case 0:
47         if (name) {
48             return _("マジック・ミサイル", "Magic Missile");
49         }
50         if (desc) {
51             return _("弱い魔法の矢を放つ。", "Fires a weak bolt of magic.");
52         }
53
54         {
55             DICE_NUMBER dice = 3 + ((plev - 1) / 5);
56             DICE_SID sides = 4;
57
58             if (info) {
59                 return info_damage(dice, sides, 0);
60             }
61
62             if (cast) {
63                 if (!get_aim_dir(player_ptr, &dir)) {
64                     return std::nullopt;
65                 }
66
67                 fire_bolt_or_beam(player_ptr, beam_chance(player_ptr) - 10, AttributeType::MISSILE, dir, damroll(dice, sides));
68             }
69         }
70         break;
71
72     case 1:
73         if (name) {
74             return _("トラップ/ドア破壊", "Trap / Door Destruction");
75         }
76         if (desc) {
77             return _("隣接する罠と扉を破壊する。", "Destroys all doors and traps in adjacent squares.");
78         }
79
80         {
81             POSITION rad = 1;
82
83             if (info) {
84                 return info_radius(rad);
85             }
86
87             if (cast) {
88                 destroy_doors_touch(player_ptr);
89             }
90         }
91         break;
92
93     case 2:
94         if (name) {
95             return _("閃光", "Flash of Light");
96         }
97         if (desc) {
98             return _("光源が照らしている範囲か部屋全体を永久に明るくする。", "Lights up nearby area and the inside of a room permanently.");
99         }
100
101         {
102             DICE_NUMBER dice = 2;
103             DICE_SID sides = plev / 2;
104             POSITION rad = (plev / 10) + 1;
105
106             if (info) {
107                 return info_damage(dice, sides, 0);
108             }
109
110             if (cast) {
111                 lite_area(player_ptr, damroll(dice, sides), rad);
112             }
113         }
114         break;
115
116     case 3:
117         if (name) {
118             return _("混乱の手", "Touch of Confusion");
119         }
120         if (desc) {
121             return _("相手を混乱させる攻撃をできるようにする。", "Attempts to confuse the next monster that you hit.");
122         }
123
124         {
125             if (cast) {
126                 if (!(player_ptr->special_attack & ATTACK_CONFUSE)) {
127                     msg_print(_("あなたの手は光り始めた。", "Your hands start glowing."));
128                     player_ptr->special_attack |= ATTACK_CONFUSE;
129                     RedrawingFlagsUpdater::get_instance().set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
130                 }
131             }
132         }
133         break;
134
135     case 4:
136         if (name) {
137             return _("魔力炸裂", "Mana Burst");
138         }
139         if (desc) {
140             return _("魔法の球を放つ。", "Fires a ball of magic.");
141         }
142
143         {
144             DICE_NUMBER dice = 3;
145             DICE_SID sides = 5;
146             POSITION rad = (plev < 30) ? 2 : 3;
147             int base;
148
149             if (PlayerClass(player_ptr).is_wizard()) {
150                 base = plev + plev / 2;
151             } else {
152                 base = plev + plev / 4;
153             }
154
155             if (info) {
156                 return info_damage(dice, sides, base);
157             }
158
159             if (cast) {
160                 if (!get_aim_dir(player_ptr, &dir)) {
161                     return std::nullopt;
162                 }
163
164                 fire_ball(player_ptr, AttributeType::MISSILE, dir, damroll(dice, sides) + base, rad);
165
166                 /*
167                  * Shouldn't actually use MANA, as
168                  * it will destroy all items on the
169                  * floor
170                  */
171             }
172         }
173         break;
174
175     case 5:
176         if (name) {
177             return _("ファイア・ボルト", "Fire Bolt");
178         }
179         if (desc) {
180             return _("炎のボルトもしくはビームを放つ。", "Fires a bolt or beam of fire.");
181         }
182
183         {
184             DICE_NUMBER dice = 8 + (plev - 5) / 4;
185             DICE_SID sides = 8;
186
187             if (info) {
188                 return info_damage(dice, sides, 0);
189             }
190
191             if (cast) {
192                 if (!get_aim_dir(player_ptr, &dir)) {
193                     return std::nullopt;
194                 }
195
196                 fire_bolt_or_beam(player_ptr, beam_chance(player_ptr), AttributeType::FIRE, dir, damroll(dice, sides));
197             }
198         }
199         break;
200
201     case 6:
202         if (name) {
203             return _("力の拳", "Fist of Force");
204         }
205         if (desc) {
206             return _("ごく小さな分解の球を放つ。", "Fires a tiny ball of disintegration.");
207         }
208
209         {
210             DICE_NUMBER dice = 8 + ((plev - 5) / 4);
211             DICE_SID sides = 8;
212
213             if (info) {
214                 return info_damage(dice, sides, 0);
215             }
216
217             if (cast) {
218                 if (!get_aim_dir(player_ptr, &dir)) {
219                     return std::nullopt;
220                 }
221
222                 fire_ball(player_ptr, AttributeType::DISINTEGRATE, dir, damroll(dice, sides), 0);
223             }
224         }
225         break;
226
227     case 7:
228         if (name) {
229             return _("テレポート", "Teleport Self");
230         }
231         if (desc) {
232             return _("遠距離のテレポートをする。", "Teleports you a long distance.");
233         }
234
235         {
236             POSITION range = plev * 5;
237
238             if (info) {
239                 return info_range(range);
240             }
241
242             if (cast) {
243                 teleport_player(player_ptr, range, TELEPORT_SPONTANEOUS);
244             }
245         }
246         break;
247
248     case 8:
249         if (name) {
250             return _("ワンダー", "Wonder");
251         }
252         if (desc) {
253             return _("モンスターにランダムな効果を与える。", "Fires something with random effects.");
254         }
255
256         {
257             if (info) {
258                 return KWD_RANDOM;
259             }
260
261             if (cast) {
262
263                 if (!get_aim_dir(player_ptr, &dir)) {
264                     return std::nullopt;
265                 }
266
267                 cast_wonder(player_ptr, dir);
268             }
269         }
270         break;
271
272     case 9:
273         if (name) {
274             return _("カオス・ボルト", "Chaos Bolt");
275         }
276         if (desc) {
277             return _("カオスのボルトもしくはビームを放つ。", "Fires a bolt or ball of chaos.");
278         }
279
280         {
281             DICE_NUMBER dice = 10 + (plev - 5) / 4;
282             DICE_SID sides = 8;
283
284             if (info) {
285                 return info_damage(dice, sides, 0);
286             }
287
288             if (cast) {
289                 if (!get_aim_dir(player_ptr, &dir)) {
290                     return std::nullopt;
291                 }
292
293                 fire_bolt_or_beam(player_ptr, beam_chance(player_ptr), AttributeType::CHAOS, dir, damroll(dice, sides));
294             }
295         }
296         break;
297
298     case 10:
299         if (name) {
300             return _("ソニック・ブーム", "Sonic Boom");
301         }
302         if (desc) {
303             return _("自分を中心とした轟音の球を発生させる。", "Generates a ball of sound centered on you.");
304         }
305
306         {
307             int dam = 60 + plev;
308             POSITION rad = plev / 10 + 2;
309
310             if (info) {
311                 return info_damage(0, 0, dam / 2);
312             }
313
314             if (cast) {
315                 msg_print(_("ドーン!部屋が揺れた!", "BOOM! Shake the room!"));
316                 project(player_ptr, 0, rad, player_ptr->y, player_ptr->x, dam, AttributeType::SOUND, PROJECT_KILL | PROJECT_ITEM);
317             }
318         }
319         break;
320
321     case 11:
322         if (name) {
323             return _("破滅の矢", "Doom Bolt");
324         }
325         if (desc) {
326             return _("純粋な魔力のビームを放つ。", "Fires a beam of pure mana.");
327         }
328
329         {
330             DICE_NUMBER dice = 11 + (plev - 5) / 4;
331             DICE_SID sides = 8;
332
333             if (info) {
334                 return info_damage(dice, sides, 0);
335             }
336
337             if (cast) {
338                 if (!get_aim_dir(player_ptr, &dir)) {
339                     return std::nullopt;
340                 }
341
342                 fire_beam(player_ptr, AttributeType::MANA, dir, damroll(dice, sides));
343             }
344         }
345         break;
346
347     case 12:
348         if (name) {
349             return _("ファイア・ボール", "Fire Ball");
350         }
351         if (desc) {
352             return _("炎の球を放つ。", "Fires a ball of fire.");
353         }
354
355         {
356             int dam = plev + 55;
357             POSITION rad = 2;
358
359             if (info) {
360                 return info_damage(0, 0, dam);
361             }
362
363             if (cast) {
364                 if (!get_aim_dir(player_ptr, &dir)) {
365                     return std::nullopt;
366                 }
367
368                 fire_ball(player_ptr, AttributeType::FIRE, dir, dam, rad);
369             }
370         }
371         break;
372
373     case 13:
374         if (name) {
375             return _("テレポート・アウェイ", "Teleport Other");
376         }
377         if (desc) {
378             return _("モンスターをテレポートさせるビームを放つ。抵抗されると無効。", "Teleports all monsters on the line away unless resisted.");
379         }
380
381         {
382             int power = plev;
383
384             if (info) {
385                 return info_power(power);
386             }
387
388             if (cast) {
389                 if (!get_aim_dir(player_ptr, &dir)) {
390                     return std::nullopt;
391                 }
392
393                 fire_beam(player_ptr, AttributeType::AWAY_ALL, dir, power);
394             }
395         }
396         break;
397
398     case 14:
399         if (name) {
400             return _("破壊の言葉", "Word of Destruction");
401         }
402         if (desc) {
403             return _("周辺のアイテム、モンスター、地形を破壊する。", "Destroys everything in nearby area.");
404         }
405
406         {
407             int base = 12;
408             DICE_SID sides = 4;
409
410             if (cast) {
411                 destroy_area(player_ptr, player_ptr->y, player_ptr->x, base + randint1(sides), false);
412             }
413         }
414         break;
415
416     case 15:
417         if (name) {
418             return _("ログルス発動", "Invoke Logrus");
419         }
420         if (desc) {
421             return _("巨大なカオスの球を放つ。", "Fires a huge ball of chaos.");
422         }
423
424         {
425             int dam = plev * 2 + 99;
426             POSITION rad = plev / 5;
427
428             if (info) {
429                 return info_damage(0, 0, dam);
430             }
431
432             if (cast) {
433                 if (!get_aim_dir(player_ptr, &dir)) {
434                     return std::nullopt;
435                 }
436
437                 fire_ball(player_ptr, AttributeType::CHAOS, dir, dam, rad);
438             }
439         }
440         break;
441
442     case 16:
443         if (name) {
444             return _("他者変容", "Polymorph Other");
445         }
446         if (desc) {
447             return _("モンスター1体を変身させる。抵抗されると無効。", "Attempts to polymorph a monster.");
448         }
449
450         {
451             int power = plev;
452
453             if (info) {
454                 return info_power(power);
455             }
456
457             if (cast) {
458                 if (!get_aim_dir(player_ptr, &dir)) {
459                     return std::nullopt;
460                 }
461
462                 poly_monster(player_ptr, dir, plev);
463             }
464         }
465         break;
466
467     case 17:
468         if (name) {
469             return _("連鎖稲妻", "Chain Lightning");
470         }
471         if (desc) {
472             return _("全方向に対して電撃のビームを放つ。", "Fires lightning beams in all directions.");
473         }
474
475         {
476             DICE_NUMBER dice = 5 + plev / 10;
477             DICE_SID sides = 8;
478
479             if (info) {
480                 return info_damage(dice, sides, 0);
481             }
482
483             if (cast) {
484                 for (dir = 0; dir <= 9; dir++) {
485                     fire_beam(player_ptr, AttributeType::ELEC, dir, damroll(dice, sides));
486                 }
487             }
488         }
489         break;
490
491     case 18:
492         if (name) {
493             return _("魔力封入", "Arcane Binding");
494         }
495         if (desc) {
496             return _("杖/魔法棒の充填回数を増やすか、充填中のロッドの充填時間を減らす。", "Recharges staffs, wands or rods.");
497         }
498
499         {
500             int power = 90;
501
502             if (info) {
503                 return info_power(power);
504             }
505             if (cast) {
506                 if (!recharge(player_ptr, power)) {
507                     return std::nullopt;
508                 }
509             }
510         }
511         break;
512
513     case 19:
514         if (name) {
515             return _("原子分解", "Disintegrate");
516         }
517         if (desc) {
518             return _("巨大な分解の球を放つ。", "Fires a huge ball of disintegration.");
519         }
520
521         {
522             int dam = plev + 70;
523             POSITION rad = 3 + plev / 40;
524
525             if (info) {
526                 return info_damage(0, 0, dam);
527             }
528
529             if (cast) {
530                 if (!get_aim_dir(player_ptr, &dir)) {
531                     return std::nullopt;
532                 }
533
534                 fire_ball(player_ptr, AttributeType::DISINTEGRATE, dir, dam, rad);
535             }
536         }
537         break;
538
539     case 20:
540         if (name) {
541             return _("現実変容", "Alter Reality");
542         }
543         if (desc) {
544             return _("現在の階を再構成する。", "Recreates current dungeon level.");
545         }
546
547         {
548             int base = 15;
549             DICE_SID sides = 20;
550
551             if (info) {
552                 return info_delay(base, sides);
553             }
554
555             if (cast) {
556                 reserve_alter_reality(player_ptr, randint0(sides) + base);
557             }
558         }
559         break;
560
561     case 21:
562         if (name) {
563             return _("マジック・ロケット", "Magic Rocket");
564         }
565         if (desc) {
566             return _("ロケットを発射する。", "Fires a magic rocket.");
567         }
568
569         {
570             int dam = 120 + plev * 2;
571             POSITION rad = 2;
572
573             if (info) {
574                 return info_damage(0, 0, dam);
575             }
576
577             if (cast) {
578                 if (!get_aim_dir(player_ptr, &dir)) {
579                     return std::nullopt;
580                 }
581
582                 msg_print(_("ロケット発射!", "You launch a rocket!"));
583                 fire_rocket(player_ptr, AttributeType::ROCKET, dir, dam, rad);
584             }
585         }
586         break;
587
588     case 22:
589         if (name) {
590             return _("混沌の刃", "Chaos Branding");
591         }
592         if (desc) {
593             return _("武器にカオスの属性をつける。", "Makes current weapon a Chaotic weapon.");
594         }
595
596         {
597             if (cast) {
598                 brand_weapon(player_ptr, 2);
599             }
600         }
601         break;
602
603     case 23:
604         if (name) {
605             return _("悪魔召喚", "Summon Demon");
606         }
607         if (desc) {
608             return _("悪魔を1体召喚する。", "Summons a demon.");
609         }
610
611         {
612             if (cast) {
613                 cast_summon_demon(player_ptr, (plev * 3) / 2);
614             }
615         }
616         break;
617
618     case 24:
619         if (name) {
620             return _("重力光線", "Beam of Gravity");
621         }
622         if (desc) {
623             return _("重力のビームを放つ。", "Fires a beam of gravity.");
624         }
625
626         {
627             DICE_NUMBER dice = 9 + (plev - 5) / 4;
628             DICE_SID sides = 8;
629
630             if (info) {
631                 return info_damage(dice, sides, 0);
632             }
633
634             if (cast) {
635                 if (!get_aim_dir(player_ptr, &dir)) {
636                     return std::nullopt;
637                 }
638                 fire_beam(player_ptr, AttributeType::GRAVITY, dir, damroll(dice, sides));
639             }
640         }
641         break;
642
643     case 25:
644         if (name) {
645             return _("流星群", "Meteor Swarm");
646         }
647         if (desc) {
648             return _("自分の周辺に隕石を落とす。", "Causes meteorites to fall down on nearby random locations.");
649         }
650
651         {
652             int dam = plev * 2;
653             POSITION rad = 2;
654
655             if (info) {
656                 return info_multi_damage(dam);
657             }
658
659             if (cast) {
660                 cast_meteor(player_ptr, dam, rad);
661             }
662         }
663         break;
664
665     case 26:
666         if (name) {
667             return _("焔の一撃", "Flame Strike");
668         }
669         if (desc) {
670             return _("自分を中心とした超巨大な炎の球を発生させる。", "Generates a huge ball of fire centered on you.");
671         }
672
673         {
674             int dam = 300 + 3 * plev;
675             POSITION rad = 8;
676
677             if (info) {
678                 return info_damage(0, 0, dam / 2);
679             }
680
681             if (cast) {
682                 fire_ball(player_ptr, AttributeType::FIRE, 0, dam, rad);
683             }
684         }
685         break;
686
687     case 27:
688         if (name) {
689             return _("混沌召来", "Call Chaos");
690         }
691         if (desc) {
692             return _("ランダムな属性の球やビームを発生させる。", "Generates random kinds of balls or beams.");
693         }
694
695         {
696             if (info) {
697                 return format("%s150 / 250", KWD_DAM);
698             }
699
700             if (cast) {
701                 call_chaos(player_ptr);
702             }
703         }
704         break;
705
706     case 28:
707         if (name) {
708             return _("自己変容", "Polymorph Self");
709         }
710         if (desc) {
711             return _("自分を変身させようとする。", "Polymorphs yourself.");
712         }
713
714         {
715             if (cast) {
716                 if (!get_check(_("変身します。よろしいですか?", "You will polymorph yourself. Are you sure? "))) {
717                     return std::nullopt;
718                 }
719                 do_poly_self(player_ptr);
720             }
721         }
722         break;
723
724     case 29:
725         if (name) {
726             return _("魔力の嵐", "Mana Storm");
727         }
728         if (desc) {
729             return _("非常に強力で巨大な純粋な魔力の球を放つ。", "Fires an extremely powerful huge ball of pure mana.");
730         }
731
732         {
733             int dam = 300 + plev * 4;
734             POSITION rad = 4;
735
736             if (info) {
737                 return info_damage(0, 0, dam);
738             }
739
740             if (cast) {
741                 if (!get_aim_dir(player_ptr, &dir)) {
742                     return std::nullopt;
743                 }
744                 fire_ball(player_ptr, AttributeType::MANA, dir, dam, rad);
745             }
746         }
747         break;
748
749     case 30:
750         if (name) {
751             return _("ログルスのブレス", "Breathe Logrus");
752         }
753         if (desc) {
754             return _("非常に強力なカオスの球を放つ。", "Fires an extremely powerful ball of chaos.");
755         }
756
757         {
758             int dam = player_ptr->chp;
759             POSITION rad = 2;
760
761             if (info) {
762                 return info_damage(0, 0, dam);
763             }
764
765             if (cast) {
766                 if (!get_aim_dir(player_ptr, &dir)) {
767                     return std::nullopt;
768                 }
769
770                 fire_ball(player_ptr, AttributeType::CHAOS, dir, dam, rad);
771             }
772         }
773         break;
774
775     case 31:
776         if (name) {
777             return _("虚無召来", "Call the Void");
778         }
779         if (desc) {
780             return _("自分の周囲に向かって、ロケット、純粋な魔力の球、放射性廃棄物の球を放つ。ただし、壁に隣接して使用すると広範囲を破壊する。",
781                 "Fires rockets, mana balls and nuclear waste balls in all directions if you are not adjacent to any walls. Otherwise *destroys* huge area.");
782         }
783         {
784             if (info) {
785                 return format("%s3 * 175", KWD_DAM);
786             }
787
788             if (cast) {
789                 call_the_void(player_ptr);
790             }
791         }
792         break;
793     }
794
795     return "";
796 }