OSDN Git Service

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