OSDN Git Service

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