OSDN Git Service

[Refactor] #40653 Separated spells-nature.c/h from spells-object.c/h
[hengband/hengband.git] / src / realm / realm-nature.c
1 #include "realm/realm-nature.h"
2 #include "cmd-action/cmd-spell.h"
3 #include "core/hp-mp-processor.h"
4 #include "effect/effect-characteristics.h"
5 #include "effect/effect-processor.h"
6 #include "effect/spells-effect-util.h"
7 #include "floor/floor-object.h"
8 #include "monster-floor/monster-summon.h"
9 #include "monster-floor/place-monster-types.h"
10 #include "object/object-generator.h"
11 #include "object/object-kind-hook.h"
12 #include "player-attack/player-attack.h"
13 #include "player-info/avatar.h"
14 #include "player/player-damage.h"
15 #include "player/player-race-types.h"
16 #include "player/player-race.h"
17 #include "spell-kind/earthquake.h"
18 #include "spell-kind/spells-beam.h"
19 #include "spell-kind/spells-charm.h"
20 #include "spell-kind/spells-detection.h"
21 #include "spell-kind/spells-floor.h"
22 #include "spell-kind/spells-grid.h"
23 #include "spell-kind/spells-launcher.h"
24 #include "spell-kind/spells-lite.h"
25 #include "spell-kind/spells-neighbor.h"
26 #include "spell-kind/spells-perception.h"
27 #include "spell-kind/spells-sight.h"
28 #include "spell-realm/spells-nature.h"
29 #include "spell/spell-types.h"
30 #include "spell/spells-diceroll.h"
31 #include "spell/spells-object.h"
32 #include "spell/spells-status.h"
33 #include "spell/spells-summon.h"
34 #include "status/bad-status-setter.h"
35 #include "status/buff-setter.h"
36 #include "status/element-resistance.h"
37 #include "sv-definition/sv-food-types.h"
38 #include "system/object-type-definition.h"
39 #include "target/target-getter.h"
40 #include "view/display-messages.h"
41
42 /*!
43  * @brief 自然領域魔法の各処理を行う
44  * @param caster_ptr プレーヤーへの参照ポインタ
45  * @param spell 魔法ID
46  * @param mode 処理内容 (SPELL_NAME / SPELL_DESC / SPELL_INFO / SPELL_CAST)
47  * @return SPELL_NAME / SPELL_DESC / SPELL_INFO 時には文字列ポインタを返す。SPELL_CAST時はNULL文字列を返す。
48  */
49 concptr do_nature_spell(player_type *caster_ptr, SPELL_IDX spell, spell_type mode)
50 {
51     bool name = (mode == SPELL_NAME) ? TRUE : FALSE;
52     bool desc = (mode == SPELL_DESC) ? TRUE : FALSE;
53     bool info = (mode == SPELL_INFO) ? TRUE : FALSE;
54     bool cast = (mode == SPELL_CAST) ? TRUE : FALSE;
55
56     DIRECTION dir;
57     PLAYER_LEVEL plev = caster_ptr->lev;
58
59     switch (spell) {
60     case 0:
61         if (name)
62             return _("モンスター感知", "Detect Creatures");
63         if (desc)
64             return _("近くの全ての見えるモンスターを感知する。", "Detects all monsters in your vicinity unless invisible.");
65
66         {
67             POSITION rad = DETECT_RAD_DEFAULT;
68
69             if (info)
70                 return info_radius(rad);
71
72             if (cast) {
73                 detect_monsters_normal(caster_ptr, rad);
74             }
75         }
76         break;
77
78     case 1:
79         if (name)
80             return _("稲妻", "Lightning");
81         if (desc)
82             return _("電撃の短いビームを放つ。", "Fires a short beam of lightning.");
83
84         {
85             DICE_NUMBER dice = 3 + (plev - 1) / 5;
86             DICE_SID sides = 4;
87             POSITION range = plev / 6 + 2;
88
89             if (info)
90                 return format("%s%dd%d %s%d", KWD_DAM, dice, sides, KWD_RANGE, range);
91
92             if (cast) {
93                 project_length = range;
94
95                 if (!get_aim_dir(caster_ptr, &dir))
96                     return NULL;
97
98                 fire_beam(caster_ptr, GF_ELEC, dir, damroll(dice, sides));
99             }
100         }
101         break;
102
103     case 2:
104         if (name)
105             return _("罠と扉感知", "Detect Doors and Traps");
106         if (desc)
107             return _("近くの全ての罠と扉を感知する。", "Detects traps, doors, and stairs in your vicinity.");
108
109         {
110             POSITION rad = DETECT_RAD_DEFAULT;
111
112             if (info)
113                 return info_radius(rad);
114
115             if (cast) {
116                 detect_traps(caster_ptr, rad, TRUE);
117                 detect_doors(caster_ptr, rad);
118                 detect_stairs(caster_ptr, rad);
119             }
120         }
121         break;
122
123     case 3:
124         if (name)
125             return _("食糧生成", "Produce Food");
126         if (desc)
127             return _("食料を一つ作り出す。", "Produces a Ration of Food.");
128
129         {
130             if (cast) {
131                 object_type forge, *q_ptr = &forge;
132                 msg_print(_("食料を生成した。", "A food ration is produced."));
133
134                 /* Create the food ration */
135                 object_prep(caster_ptr, q_ptr, lookup_kind(TV_FOOD, SV_FOOD_RATION));
136
137                 /* Drop the object from heaven */
138                 (void)drop_near(caster_ptr, q_ptr, -1, caster_ptr->y, caster_ptr->x);
139             }
140         }
141         break;
142
143     case 4:
144         if (name)
145             return _("日の光", "Daylight");
146         if (desc)
147             return _("光源が照らしている範囲か部屋全体を永久に明るくする。", "Lights up nearby area and the inside of a room permanently.");
148
149         {
150             DICE_NUMBER dice = 2;
151             DICE_SID sides = plev / 2;
152             POSITION rad = (plev / 10) + 1;
153
154             if (info)
155                 return info_damage(dice, sides, 0);
156
157             if (cast) {
158                 lite_area(caster_ptr, damroll(dice, sides), rad);
159
160                 if ((is_specific_player_race(caster_ptr, RACE_VAMPIRE) || (caster_ptr->mimic_form == MIMIC_VAMPIRE)) && !caster_ptr->resist_lite) {
161                     msg_print(_("日の光があなたの肉体を焦がした!", "The daylight scorches your flesh!"));
162                     take_hit(caster_ptr, DAMAGE_NOESCAPE, damroll(2, 2), _("日の光", "daylight"), -1);
163                 }
164             }
165         }
166         break;
167
168     case 5:
169         if (name)
170             return _("動物習し", "Animal Taming");
171         if (desc)
172             return _("動物1体を魅了する。抵抗されると無効。", "Attempts to charm an animal.");
173
174         {
175             int power = plev;
176
177             if (info)
178                 return info_power(power);
179
180             if (cast) {
181                 if (!get_aim_dir(caster_ptr, &dir))
182                     return NULL;
183
184                 charm_animal(caster_ptr, dir, plev);
185             }
186         }
187         break;
188
189     case 6:
190         if (name)
191             return _("環境への耐性", "Resist Environment");
192         if (desc)
193             return _("一定時間、冷気、炎、電撃に対する耐性を得る。装備による耐性に累積する。",
194                 "Gives resistance to fire, cold and electricity for a while. These resistances can be added to those from equipment for more powerful "
195                 "resistances.");
196
197         {
198             int base = 20;
199
200             if (info)
201                 return info_duration(base, base);
202
203             if (cast) {
204                 set_oppose_cold(caster_ptr, randint1(base) + base, FALSE);
205                 set_oppose_fire(caster_ptr, randint1(base) + base, FALSE);
206                 set_oppose_elec(caster_ptr, randint1(base) + base, FALSE);
207             }
208         }
209         break;
210
211     case 7:
212         if (name)
213             return _("傷と毒治療", "Cure Wounds & Poison");
214         if (desc)
215             return _("怪我を全快させ、毒を体から完全に取り除き、体力を少し回復させる。", "Heals all cuts and poisons. Heals HP a little.");
216
217         {
218             DICE_NUMBER dice = 2;
219             DICE_SID sides = 8;
220
221             if (info)
222                 return info_heal(dice, sides, 0);
223
224             if (cast) {
225                 hp_player(caster_ptr, damroll(dice, sides));
226                 set_cut(caster_ptr, 0);
227                 set_poisoned(caster_ptr, 0);
228             }
229         }
230         break;
231
232     case 8:
233         if (name)
234             return _("岩石溶解", "Stone to Mud");
235         if (desc)
236             return _("壁を溶かして床にする。", "Turns one rock square to mud.");
237
238         {
239             DICE_NUMBER dice = 1;
240             DICE_SID sides = 30;
241             int base = 20;
242
243             if (info)
244                 return info_damage(dice, sides, base);
245
246             if (cast) {
247                 if (!get_aim_dir(caster_ptr, &dir))
248                     return NULL;
249
250                 wall_to_mud(caster_ptr, dir, 20 + randint1(30));
251             }
252         }
253         break;
254
255     case 9:
256         if (name)
257             return _("アイス・ボルト", "Frost Bolt");
258         if (desc)
259             return _("冷気のボルトもしくはビームを放つ。", "Fires a bolt or beam of cold.");
260
261         {
262             DICE_NUMBER dice = 3 + (plev - 5) / 4;
263             DICE_SID sides = 8;
264
265             if (info)
266                 return info_damage(dice, sides, 0);
267
268             if (cast) {
269                 if (!get_aim_dir(caster_ptr, &dir))
270                     return NULL;
271                 fire_bolt_or_beam(caster_ptr, beam_chance(caster_ptr) - 10, GF_COLD, dir, damroll(dice, sides));
272             }
273         }
274         break;
275
276     case 10:
277         if (name)
278             return _("自然の覚醒", "Nature Awareness");
279         if (desc)
280             return _(
281                 "周辺の地形を感知し、近くの罠、扉、階段、全てのモンスターを感知する。", "Maps nearby area. Detects all monsters, traps, doors and stairs.");
282
283         {
284             int rad1 = DETECT_RAD_MAP;
285             int rad2 = DETECT_RAD_DEFAULT;
286
287             if (info)
288                 return info_radius(MAX(rad1, rad2));
289
290             if (cast) {
291                 map_area(caster_ptr, rad1);
292                 detect_traps(caster_ptr, rad2, TRUE);
293                 detect_doors(caster_ptr, rad2);
294                 detect_stairs(caster_ptr, rad2);
295                 detect_monsters_normal(caster_ptr, rad2);
296             }
297         }
298         break;
299
300     case 11:
301         if (name)
302             return _("ファイア・ボルト", "Fire Bolt");
303         if (desc)
304             return _("火炎のボルトもしくはビームを放つ。", "Fires a bolt or beam of fire.");
305
306         {
307             DICE_NUMBER dice = 5 + (plev - 5) / 4;
308             DICE_SID sides = 8;
309
310             if (info)
311                 return info_damage(dice, sides, 0);
312
313             if (cast) {
314                 if (!get_aim_dir(caster_ptr, &dir))
315                     return NULL;
316                 fire_bolt_or_beam(caster_ptr, beam_chance(caster_ptr) - 10, GF_FIRE, dir, damroll(dice, sides));
317             }
318         }
319         break;
320
321     case 12:
322         if (name)
323             return _("太陽光線", "Ray of Sunlight");
324         if (desc)
325             return _("光線を放つ。光りを嫌うモンスターに効果がある。", "Fires a beam of light which damages light-sensitive monsters.");
326
327         {
328             DICE_NUMBER dice = 6;
329             DICE_SID sides = 8;
330
331             if (info)
332                 return info_damage(dice, sides, 0);
333
334             if (cast) {
335                 if (!get_aim_dir(caster_ptr, &dir))
336                     return NULL;
337                 msg_print(_("太陽光線が現れた。", "A line of sunlight appears."));
338                 lite_line(caster_ptr, dir, damroll(6, 8));
339             }
340         }
341         break;
342
343     case 13:
344         if (name)
345             return _("足かせ", "Entangle");
346         if (desc)
347             return _("視界内の全てのモンスターを減速させる。抵抗されると無効。", "Attempts to slow all monsters in sight.");
348         {
349             int power = plev;
350             if (info)
351                 return info_power(power);
352             if (cast)
353                 slow_monsters(caster_ptr, plev);
354         }
355         break;
356
357     case 14:
358         if (name)
359             return _("動物召喚", "Summon Animal");
360         if (desc)
361             return _("動物を1体召喚する。", "Summons an animal.");
362
363         {
364             if (cast) {
365                 if (!(summon_specific(caster_ptr, -1, caster_ptr->y, caster_ptr->x, plev, SUMMON_ANIMAL_RANGER, (PM_ALLOW_GROUP | PM_FORCE_PET)))) {
366                     msg_print(_("動物は現れなかった。", "No animals arrive."));
367                 }
368                 break;
369             }
370         }
371         break;
372
373     case 15:
374         if (name)
375             return _("薬草治療", "Herbal Healing");
376         if (desc)
377             return _("体力を大幅に回復させ、負傷、朦朧状態、毒から全快する。", "Heals HP greatly. Completely cures cuts, poisons and being stunned.");
378         {
379             int heal = 500;
380             if (info)
381                 return info_heal(0, 0, heal);
382             if (cast)
383                 (void)cure_critical_wounds(caster_ptr, heal);
384         }
385         break;
386
387     case 16:
388         if (name)
389             return _("階段生成", "Stair Building");
390         if (desc)
391             return _("自分のいる位置に階段を作る。", "Creates a staircase which goes down or up.");
392
393         {
394             if (cast) {
395                 stair_creation(caster_ptr);
396             }
397         }
398         break;
399
400     case 17:
401         if (name)
402             return _("肌石化", "Stone Skin");
403         if (desc)
404             return _("一定時間、ACを上昇させる。", "Gives a bonus to AC for a while.");
405
406         {
407             int base = 20;
408             DICE_SID sides = 30;
409
410             if (info)
411                 return info_duration(base, sides);
412
413             if (cast) {
414                 set_shield(caster_ptr, randint1(sides) + base, FALSE);
415             }
416         }
417         break;
418
419     case 18:
420         if (name)
421             return _("真・耐性", "Resistance True");
422         if (desc)
423             return _("一定時間、酸、電撃、炎、冷気、毒に対する耐性を得る。装備による耐性に累積する。",
424                 "Gives resistance to fire, cold, electricity, acid and poison for a while. These resistances can be added to those from equipment for more "
425                 "powerful resistances.");
426
427         {
428             int base = 20;
429
430             if (info)
431                 return info_duration(base, base);
432
433             if (cast) {
434                 set_oppose_acid(caster_ptr, randint1(base) + base, FALSE);
435                 set_oppose_elec(caster_ptr, randint1(base) + base, FALSE);
436                 set_oppose_fire(caster_ptr, randint1(base) + base, FALSE);
437                 set_oppose_cold(caster_ptr, randint1(base) + base, FALSE);
438                 set_oppose_pois(caster_ptr, randint1(base) + base, FALSE);
439             }
440         }
441         break;
442
443     case 19:
444         if (name)
445             return _("森林創造", "Forest Creation");
446         if (desc)
447             return _("周囲に木を作り出す。", "Creates trees in all adjacent squares.");
448
449         {
450             if (cast) {
451                 tree_creation(caster_ptr, caster_ptr->y, caster_ptr->x);
452             }
453         }
454         break;
455
456     case 20:
457         if (name)
458             return _("動物友和", "Animal Friendship");
459         if (desc)
460             return _("視界内の全ての動物を魅了する。抵抗されると無効。", "Attempts to charm all animals in sight.");
461
462         {
463             int power = plev * 2;
464             if (info)
465                 return info_power(power);
466             if (cast)
467                 charm_animals(caster_ptr, power);
468         }
469         break;
470
471     case 21:
472         if (name)
473             return _("試金石", "Stone Tell");
474         if (desc)
475             return _("アイテムの持つ能力を完全に知る。", "*Identifies* an item.");
476
477         {
478             if (cast) {
479                 if (!identify_fully(caster_ptr, FALSE, 0))
480                     return NULL;
481             }
482         }
483         break;
484
485     case 22:
486         if (name)
487             return _("石の壁", "Wall of Stone");
488         if (desc)
489             return _("自分の周囲に花崗岩の壁を作る。", "Creates granite walls in all adjacent squares.");
490
491         {
492             if (cast) {
493                 wall_stone(caster_ptr);
494             }
495         }
496         break;
497
498     case 23:
499         if (name)
500             return _("腐食防止", "Protect from Corrosion");
501         if (desc)
502             return _("アイテムを酸で傷つかないよう加工する。", "Makes a piece of equipment acid-proof.");
503
504         {
505             if (cast) {
506                 if (!rustproof(caster_ptr))
507                     return NULL;
508             }
509         }
510         break;
511
512     case 24:
513         if (name)
514             return _("地震", "Earthquake");
515         if (desc)
516             return _(
517                 "周囲のダンジョンを揺らし、壁と床をランダムに入れ変える。", "Shakes dungeon structure, and results in random swapping of floors and walls.");
518
519         {
520             POSITION rad = 10;
521
522             if (info)
523                 return info_radius(rad);
524
525             if (cast) {
526                 earthquake(caster_ptr, caster_ptr->y, caster_ptr->x, rad, 0);
527             }
528         }
529         break;
530
531     case 25:
532         if (name)
533             return _("カマイタチ", "Whirlwind");
534         if (desc)
535             return _("全方向に向かって攻撃する。", "Attacks all adjacent monsters.");
536         if (cast)
537             massacre(caster_ptr);
538         break;
539
540     case 26:
541         if (name)
542             return _("ブリザード", "Blizzard");
543         if (desc)
544             return _("巨大な冷気の球を放つ。", "Fires a huge ball of cold.");
545
546         {
547             HIT_POINT dam = 70 + plev * 3 / 2;
548             POSITION rad = plev / 12 + 1;
549
550             if (info)
551                 return info_damage(0, 0, dam);
552
553             if (cast) {
554                 if (!get_aim_dir(caster_ptr, &dir))
555                     return NULL;
556
557                 fire_ball(caster_ptr, GF_COLD, dir, dam, rad);
558             }
559         }
560         break;
561
562     case 27:
563         if (name)
564             return _("稲妻嵐", "Lightning Storm");
565         if (desc)
566             return _("巨大な電撃の球を放つ。", "Fires a huge electric ball.");
567
568         {
569             HIT_POINT dam = 90 + plev * 3 / 2;
570             POSITION rad = plev / 12 + 1;
571
572             if (info)
573                 return info_damage(0, 0, dam);
574
575             if (cast) {
576                 if (!get_aim_dir(caster_ptr, &dir))
577                     return NULL;
578                 fire_ball(caster_ptr, GF_ELEC, dir, dam, rad);
579                 break;
580             }
581         }
582         break;
583
584     case 28:
585         if (name)
586             return _("渦潮", "Whirlpool");
587         if (desc)
588             return _("巨大な水の球を放つ。", "Fires a huge ball of water.");
589
590         {
591             HIT_POINT dam = 100 + plev * 3 / 2;
592             POSITION rad = plev / 12 + 1;
593
594             if (info)
595                 return info_damage(0, 0, dam);
596
597             if (cast) {
598                 if (!get_aim_dir(caster_ptr, &dir))
599                     return NULL;
600                 fire_ball(caster_ptr, GF_WATER, dir, dam, rad);
601             }
602         }
603         break;
604
605     case 29:
606         if (name)
607             return _("陽光召喚", "Call Sunlight");
608         if (desc)
609             return _("自分を中心とした光の球を発生させる。さらに、その階全体を永久に照らし、ダンジョン内すべてのアイテムを感知する。",
610                 "Generates ball of light centered on you. Maps and lights whole dungeon level. Knows all objects location.");
611
612         {
613             HIT_POINT dam = 150;
614             POSITION rad = 8;
615
616             if (info)
617                 return info_damage(0, 0, dam / 2);
618
619             if (cast) {
620                 fire_ball(caster_ptr, GF_LITE, 0, dam, rad);
621                 chg_virtue(caster_ptr, V_KNOWLEDGE, 1);
622                 chg_virtue(caster_ptr, V_ENLIGHTEN, 1);
623                 wiz_lite(caster_ptr, FALSE);
624
625                 if ((is_specific_player_race(caster_ptr, RACE_VAMPIRE) || (caster_ptr->mimic_form == MIMIC_VAMPIRE)) && !caster_ptr->resist_lite) {
626                     msg_print(_("日光があなたの肉体を焦がした!", "The sunlight scorches your flesh!"));
627                     take_hit(caster_ptr, DAMAGE_NOESCAPE, 50, _("日光", "sunlight"), -1);
628                 }
629             }
630         }
631         break;
632
633     case 30:
634         if (name)
635             return _("精霊の刃", "Elemental Branding");
636         if (desc)
637             return _("武器に炎か冷気の属性をつける。", "Brands current weapon with fire or frost.");
638
639         {
640             if (cast) {
641                 brand_weapon(caster_ptr, randint0(2));
642             }
643         }
644         break;
645
646     case 31:
647         if (name)
648             return _("自然の脅威", "Nature's Wrath");
649         if (desc)
650             return _("近くの全てのモンスターにダメージを与え、地震を起こし、自分を中心とした分解の球を発生させる。",
651                 "Damages all monsters in sight. Makes quake. Generates disintegration ball centered on you.");
652
653         {
654             int d_dam = 4 * plev;
655             int b_dam = (100 + plev) * 2;
656             POSITION b_rad = 1 + plev / 12;
657             POSITION q_rad = 20 + plev / 2;
658
659             if (info)
660                 return format("%s%d+%d", KWD_DAM, d_dam, b_dam / 2);
661
662             if (cast) {
663                 dispel_monsters(caster_ptr, d_dam);
664                 earthquake(caster_ptr, caster_ptr->y, caster_ptr->x, q_rad, 0);
665                 project(caster_ptr, 0, b_rad, caster_ptr->y, caster_ptr->x, b_dam, GF_DISINTEGRATE, PROJECT_KILL | PROJECT_ITEM, -1);
666             }
667         }
668         break;
669     }
670
671     return "";
672 }