OSDN Git Service

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