OSDN Git Service

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