OSDN Git Service

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