OSDN Git Service

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