OSDN Git Service

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