OSDN Git Service

908b7adbcfd09cbbe101b3bf0ec4143ee022d855
[hengbandforosx/hengbandosx.git] / src / realm / realm-sorcery.cpp
1 #include "realm/realm-sorcery.h"
2 #include "avatar/avatar.h"
3 #include "cmd-action/cmd-spell.h"
4 #include "core/asking-player.h"
5 #include "effect/attribute-types.h"
6 #include "player-info/self-info.h"
7 #include "spell-kind/magic-item-recharger.h"
8 #include "spell-kind/spells-charm.h"
9 #include "spell-kind/spells-detection.h"
10 #include "spell-kind/spells-fetcher.h"
11 #include "spell-kind/spells-floor.h"
12 #include "spell-kind/spells-grid.h"
13 #include "spell-kind/spells-launcher.h"
14 #include "spell-kind/spells-lite.h"
15 #include "spell-kind/spells-perception.h"
16 #include "spell-kind/spells-sight.h"
17 #include "spell-kind/spells-teleport.h"
18 #include "spell-kind/spells-world.h"
19 #include "spell-realm/spells-sorcery.h"
20 #include "spell/spells-status.h"
21 #include "status/body-improvement.h"
22 #include "status/buff-setter.h"
23 #include "status/sight-setter.h"
24 #include "system/player-type-definition.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_sorcery_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 _("モンスター感知", "Detect Monsters");
49         }
50         if (desc) {
51             return _("近くの全ての見えるモンスターを感知する。", "Detects all monsters in your vicinity unless invisible.");
52         }
53
54         {
55             POSITION rad = DETECT_RAD_DEFAULT;
56
57             if (info) {
58                 return info_radius(rad);
59             }
60
61             if (cast) {
62                 detect_monsters_normal(player_ptr, rad);
63             }
64         }
65         break;
66
67     case 1:
68         if (name) {
69             return _("ショート・テレポート", "Phase Door");
70         }
71         if (desc) {
72             return _("近距離のテレポートをする。", "Teleports you a short distance.");
73         }
74
75         {
76             POSITION range = 10;
77
78             if (info) {
79                 return info_range(range);
80             }
81
82             if (cast) {
83                 teleport_player(player_ptr, range, TELEPORT_SPONTANEOUS);
84             }
85         }
86         break;
87
88     case 2:
89         if (name) {
90             return _("罠と扉感知", "Detect Doors and Traps");
91         }
92         if (desc) {
93             return _("近くの全ての扉と罠を感知する。", "Detects traps, doors, and stairs in your vicinity.");
94         }
95
96         {
97             POSITION rad = DETECT_RAD_DEFAULT;
98
99             if (info) {
100                 return info_radius(rad);
101             }
102
103             if (cast) {
104                 detect_traps(player_ptr, rad, true);
105                 detect_doors(player_ptr, rad);
106                 detect_stairs(player_ptr, rad);
107             }
108         }
109         break;
110
111     case 3:
112         if (name) {
113             return _("ライト・エリア", "Light Area");
114         }
115         if (desc) {
116             return _("光源が照らしている範囲か部屋全体を永久に明るくする。", "Lights up nearby area and the inside of a room permanently.");
117         }
118
119         {
120             DICE_NUMBER dice = 2;
121             DICE_SID sides = plev / 2;
122             POSITION rad = plev / 10 + 1;
123
124             if (info) {
125                 return info_damage(dice, sides, 0);
126             }
127
128             if (cast) {
129                 lite_area(player_ptr, damroll(dice, sides), rad);
130             }
131         }
132         break;
133
134     case 4:
135         if (name) {
136             return _("パニック・モンスター", "Confuse Monster");
137         }
138         if (desc) {
139             return _("モンスター1体を混乱させる。抵抗されると無効。", "Attempts to confuse a monster.");
140         }
141
142         {
143             PLAYER_LEVEL power = (plev * 3) / 2;
144
145             if (info) {
146                 return info_power(power);
147             }
148
149             if (cast) {
150                 if (!get_aim_dir(player_ptr, &dir)) {
151                     return std::nullopt;
152                 }
153
154                 confuse_monster(player_ptr, dir, power);
155             }
156         }
157         break;
158
159     case 5:
160         if (name) {
161             return _("テレポート", "Teleport");
162         }
163         if (desc) {
164             return _("遠距離のテレポートをする。", "Teleports you a long distance.");
165         }
166
167         {
168             POSITION range = plev * 5;
169
170             if (info) {
171                 return info_range(range);
172             }
173
174             if (cast) {
175                 teleport_player(player_ptr, range, TELEPORT_SPONTANEOUS);
176             }
177         }
178         break;
179
180     case 6:
181         if (name) {
182             return _("スリープ・モンスター", "Sleep Monster");
183         }
184         if (desc) {
185             return _("モンスター1体を眠らせる。抵抗されると無効。", "Attempts to put a monster to sleep.");
186         }
187
188         {
189             int power = plev;
190
191             if (info) {
192                 return info_power(power);
193             }
194
195             if (cast) {
196                 if (!get_aim_dir(player_ptr, &dir)) {
197                     return std::nullopt;
198                 }
199
200                 sleep_monster(player_ptr, dir, plev);
201             }
202         }
203         break;
204
205     case 7:
206         if (name) {
207             return _("魔力充填", "Recharging");
208         }
209         if (desc) {
210             return _("杖/魔法棒の充填回数を増やすか、充填中のロッドの充填時間を減らす。", "Recharges staffs, wands or rods.");
211         }
212
213         {
214             int power = plev * 4;
215
216             if (info) {
217                 return info_power(power);
218             }
219
220             if (cast) {
221                 if (!recharge(player_ptr, power)) {
222                     return std::nullopt;
223                 }
224             }
225         }
226         break;
227
228     case 8:
229         if (name) {
230             return _("魔法の地図", "Magic Mapping");
231         }
232         if (desc) {
233             return _("周辺の地形を感知する。", "Maps nearby area.");
234         }
235
236         {
237             POSITION rad = DETECT_RAD_MAP;
238
239             if (info) {
240                 return info_radius(rad);
241             }
242
243             if (cast) {
244                 map_area(player_ptr, rad);
245             }
246         }
247         break;
248
249     case 9:
250         if (name) {
251             return _("鑑定", "Identify");
252         }
253         if (desc) {
254             return _("アイテムを識別する。", "Identifies an item.");
255         }
256
257         {
258             if (cast) {
259                 if (!ident_spell(player_ptr, false)) {
260                     return std::nullopt;
261                 }
262             }
263         }
264         break;
265
266     case 10:
267         if (name) {
268             return _("スロウ・モンスター", "Slow Monster");
269         }
270         if (desc) {
271             return _("モンスター1体を減速させる。抵抗されると無効。", "Attempts to slow a monster.");
272         }
273
274         {
275             int power = plev;
276
277             if (info) {
278                 return info_power(power);
279             }
280
281             if (cast) {
282                 if (!get_aim_dir(player_ptr, &dir)) {
283                     return std::nullopt;
284                 }
285
286                 slow_monster(player_ptr, dir, plev);
287             }
288         }
289         break;
290
291     case 11:
292         if (name) {
293             return _("周辺スリープ", "Mass Sleep");
294         }
295         if (desc) {
296             return _("視界内の全てのモンスターを眠らせる。抵抗されると無効。", "Attempts to put all monsters in sight to sleep.");
297         }
298
299         {
300             int power = plev;
301
302             if (info) {
303                 return info_power(power);
304             }
305
306             if (cast) {
307                 sleep_monsters(player_ptr, plev);
308             }
309         }
310         break;
311
312     case 12:
313         if (name) {
314             return _("テレポート・モンスター", "Teleport Away");
315         }
316         if (desc) {
317             return _("モンスターをテレポートさせるビームを放つ。抵抗されると無効。", "Teleports all monsters on the line away unless resisted.");
318         }
319
320         {
321             int power = plev;
322
323             if (info) {
324                 return info_power(power);
325             }
326
327             if (cast) {
328                 if (!get_aim_dir(player_ptr, &dir)) {
329                     return std::nullopt;
330                 }
331
332                 fire_beam(player_ptr, AttributeType::AWAY_ALL, dir, power);
333             }
334         }
335         break;
336
337     case 13:
338         if (name) {
339             return _("スピード", "Haste Self");
340         }
341         if (desc) {
342             return _("一定時間、加速する。", "Hastes you for a while.");
343         }
344
345         {
346             int base = plev;
347             DICE_SID sides = 20 + plev;
348
349             if (info) {
350                 return info_duration(base, sides);
351             }
352
353             if (cast) {
354                 set_acceleration(player_ptr, randint1(sides) + base, false);
355             }
356         }
357         break;
358
359     case 14:
360         if (name) {
361             return _("真・感知", "Detection True");
362         }
363         if (desc) {
364             return _("近くの全てのモンスター、罠、扉、階段、財宝、そしてアイテムを感知する。",
365                 "Detects all monsters, traps, doors, stairs, treasures and items in your vicinity.");
366         }
367
368         {
369             POSITION rad = DETECT_RAD_DEFAULT;
370
371             if (info) {
372                 return info_radius(rad);
373             }
374
375             if (cast) {
376                 detect_all(player_ptr, rad);
377             }
378         }
379         break;
380
381     case 15:
382         if (name) {
383             return _("真・鑑定", "Identify True");
384         }
385         if (desc) {
386             return _("アイテムの持つ能力を完全に知る。", "*Identifies* an item.");
387         }
388
389         {
390             if (cast) {
391                 if (!identify_fully(player_ptr, false)) {
392                     return std::nullopt;
393                 }
394             }
395         }
396         break;
397
398     case 16:
399         if (name) {
400             return _("物体と財宝感知", "Detect items and Treasure");
401         }
402         if (desc) {
403             return _("近くの全てのアイテムと財宝を感知する。", "Detects all treasures and items in your vicinity.");
404         }
405
406         {
407             POSITION rad = DETECT_RAD_DEFAULT;
408
409             if (info) {
410                 return info_radius(rad);
411             }
412
413             if (cast) {
414                 detect_objects_normal(player_ptr, rad);
415                 detect_treasure(player_ptr, rad);
416                 detect_objects_gold(player_ptr, rad);
417             }
418         }
419         break;
420
421     case 17:
422         if (name) {
423             return _("チャーム・モンスター", "Charm Monster");
424         }
425         if (desc) {
426             return _("モンスター1体を魅了する。抵抗されると無効。", "Attempts to charm a monster.");
427         }
428
429         {
430             int power = plev;
431
432             if (info) {
433                 return info_power(power);
434             }
435
436             if (cast) {
437                 if (!get_aim_dir(player_ptr, &dir)) {
438                     return std::nullopt;
439                 }
440
441                 charm_monster(player_ptr, dir, plev);
442             }
443         }
444         break;
445
446     case 18:
447         if (name) {
448             return _("精神感知", "Sense Minds");
449         }
450         if (desc) {
451             return _("一定時間、テレパシー能力を得る。", "Gives telepathy for a while.");
452         }
453
454         {
455             int base = 25;
456             DICE_SID sides = 30;
457
458             if (info) {
459                 return info_duration(base, sides);
460             }
461
462             if (cast) {
463                 set_tim_esp(player_ptr, randint1(sides) + base, false);
464             }
465         }
466         break;
467
468     case 19:
469         if (name) {
470             return _("街移動", "Teleport to town");
471         }
472         if (desc) {
473             return _("街へ移動する。地上にいるときしか使えない。", "Instantly teleports you to a town which you choose. Can only be used outdoors.");
474         }
475
476         {
477             if (cast) {
478                 if (!tele_town(player_ptr)) {
479                     return std::nullopt;
480                 }
481             }
482         }
483         break;
484
485     case 20:
486         if (name) {
487             return _("自己分析", "Self Knowledge");
488         }
489         if (desc) {
490             return _("現在の自分の状態を完全に知る。",
491                 "Gives you useful info regarding your current resistances, the powers of your weapon and maximum limits of your stats.");
492         }
493
494         {
495             if (cast) {
496                 self_knowledge(player_ptr);
497             }
498         }
499         break;
500
501     case 21:
502         if (name) {
503             return _("テレポート・レベル", "Teleport Level");
504         }
505         if (desc) {
506             return _("瞬時に上か下の階にテレポートする。", "Instantly teleports you up or down a level.");
507         }
508
509         {
510             if (cast) {
511                 if (!input_check(_("本当に他の階にテレポートしますか?", "Are you sure? (Teleport Level)"))) {
512                     return std::nullopt;
513                 }
514                 teleport_level(player_ptr, 0);
515             }
516         }
517         break;
518
519     case 22:
520         if (name) {
521             return _("帰還の呪文", "Word of Recall");
522         }
523         if (desc) {
524             return _("地上にいるときはダンジョンの最深階へ、ダンジョンにいるときは地上へと移動する。",
525                 "Recalls player from dungeon to town or from town to the deepest level of dungeon.");
526         }
527
528         {
529             int base = 15;
530             DICE_SID sides = 20;
531
532             if (info) {
533                 return info_delay(base, sides);
534             }
535
536             if (cast) {
537                 if (!recall_player(player_ptr, randint0(21) + 15)) {
538                     return std::nullopt;
539                 }
540             }
541         }
542         break;
543
544     case 23:
545         if (name) {
546             return _("次元の扉", "Dimension Door");
547         }
548         if (desc) {
549             return _("短距離内の指定した場所にテレポートする。", "Teleports you to a given location.");
550         }
551
552         {
553             POSITION range = plev / 2 + 10;
554
555             if (info) {
556                 return info_range(range);
557             }
558
559             if (cast) {
560                 msg_print(_("次元の扉が開いた。目的地を選んで下さい。", "You open a dimensional gate. Choose a destination."));
561                 if (!dimension_door(player_ptr)) {
562                     return std::nullopt;
563                 }
564             }
565         }
566         break;
567
568     case 24:
569         if (name) {
570             return _("調査", "Probing");
571         }
572         if (desc) {
573             return _("モンスターの属性、残り体力、最大体力、スピード、正体を知る。", "Probes all monsters' alignment, HP, speed and their true character.");
574         }
575
576         {
577             if (cast) {
578                 probing(player_ptr);
579             }
580         }
581         break;
582
583     case 25:
584         if (name) {
585             return _("爆発のルーン", "Explosive Rune");
586         }
587         if (desc) {
588             return _("自分のいる床の上に、モンスターが通ると爆発してダメージを与えるルーンを描く。",
589                 "Sets a rune under you. The rune will explode when a monster moves on it.");
590         }
591
592         {
593             DICE_NUMBER dice = 7;
594             DICE_SID sides = 7;
595             int base = plev;
596
597             if (info) {
598                 return info_damage(dice, sides, base);
599             }
600
601             if (cast) {
602                 create_rune_explosion(player_ptr, player_ptr->y, player_ptr->x);
603             }
604         }
605         break;
606
607     case 26:
608         if (name) {
609             return _("念動力", "Telekinesis");
610         }
611         if (desc) {
612             return _("アイテムを自分の足元へ移動させる。", "Pulls a distant item close to you.");
613         }
614
615         {
616             WEIGHT weight = plev * 15;
617
618             if (info) {
619                 return info_weight(weight);
620             }
621
622             if (cast) {
623                 if (!get_aim_dir(player_ptr, &dir)) {
624                     return std::nullopt;
625                 }
626
627                 fetch_item(player_ptr, dir, weight, false);
628             }
629         }
630         break;
631
632     case 27:
633         if (name) {
634             return _("千里眼", "Clairvoyance");
635         }
636         if (desc) {
637             return _("その階全体を永久に照らし、ダンジョン内すべてのアイテムを感知する。さらに、一定時間テレパシー能力を得る。",
638                 "Maps and lights whole dungeon level. Knows all objects location. And gives telepathy for a while.");
639         }
640
641         {
642             int base = 25;
643             DICE_SID sides = 30;
644
645             if (info) {
646                 return info_duration(base, sides);
647             }
648
649             if (cast) {
650                 chg_virtue(player_ptr, Virtue::KNOWLEDGE, 1);
651                 chg_virtue(player_ptr, Virtue::ENLIGHTEN, 1);
652
653                 wiz_lite(player_ptr, false);
654
655                 if (!player_ptr->telepathy) {
656                     set_tim_esp(player_ptr, randint1(sides) + base, false);
657                 }
658             }
659         }
660         break;
661
662     case 28:
663         if (name) {
664             return _("魅了の視線", "Charm monsters");
665         }
666         if (desc) {
667             return _("視界内の全てのモンスターを魅了する。抵抗されると無効。", "Attempts to charm all monsters in sight.");
668         }
669
670         {
671             int power = plev * 2;
672
673             if (info) {
674                 return info_power(power);
675             }
676
677             if (cast) {
678                 charm_monsters(player_ptr, power);
679             }
680         }
681         break;
682
683     case 29:
684         if (name) {
685             return _("錬金術", "Alchemy");
686         }
687         if (desc) {
688             return _("アイテム1つをお金に変える。", "Turns an item into 1/3 of its value in gold.");
689         }
690
691         {
692             if (cast) {
693                 if (!alchemy(player_ptr)) {
694                     return std::nullopt;
695                 }
696             }
697         }
698         break;
699
700     case 30:
701         if (name) {
702             return _("怪物追放", "Banishment");
703         }
704         if (desc) {
705             return _("視界内の全てのモンスターをテレポートさせる。抵抗されると無効。", "Teleports all monsters in sight away unless resisted.");
706         }
707
708         {
709             int power = plev * 4;
710
711             if (info) {
712                 return info_power(power);
713             }
714
715             if (cast) {
716                 banish_monsters(player_ptr, power);
717             }
718         }
719         break;
720
721     case 31:
722         if (name) {
723             return _("無傷の球", "Globe of Invulnerability");
724         }
725         if (desc) {
726             return _("一定時間、ダメージを受けなくなるバリアを張る。切れた瞬間に少しターンを消費するので注意。",
727                 "Generates a barrier which completely protects you from almost all damage. Takes a few of your turns when the barrier breaks or duration time "
728                 "is exceeded.");
729         }
730
731         {
732             int base = 4;
733
734             if (info) {
735                 return info_duration(base, base);
736             }
737
738             if (cast) {
739                 set_invuln(player_ptr, randint1(base) + base, false);
740             }
741         }
742         break;
743     }
744
745     return "";
746 }