OSDN Git Service

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