OSDN Git Service

64d7b247e37bce25ec029283c1432c57651ed208
[hengbandforosx/hengbandosx.git] / src / player / player-damage.cpp
1 #include "player/player-damage.h"
2 #include "autopick/autopick-pref-processor.h"
3 #include "avatar/avatar.h"
4 #include "blue-magic/blue-magic-checker.h"
5 #include "cmd-io/cmd-process-screen.h"
6 #include "core/asking-player.h"
7 #include "core/disturbance.h"
8 #include "core/player-redraw-types.h"
9 #include "core/player-update-types.h"
10 #include "core/stuff-handler.h"
11 #include "core/window-redrawer.h"
12 #include "dungeon/dungeon.h"
13 #include "dungeon/quest.h"
14 #include "flavor/flavor-describer.h"
15 #include "flavor/object-flavor-types.h"
16 #include "floor/wild.h"
17 #include "game-option/birth-options.h"
18 #include "game-option/cheat-options.h"
19 #include "game-option/game-play-options.h"
20 #include "game-option/input-options.h"
21 #include "game-option/play-record-options.h"
22 #include "game-option/special-options.h"
23 #include "inventory/inventory-damage.h"
24 #include "inventory/inventory-slot-types.h"
25 #include "io/files-util.h"
26 #include "io/input-key-acceptor.h"
27 #include "io/report.h"
28 #include "io/write-diary.h"
29 #include "main/music-definitions-table.h"
30 #include "main/sound-definitions-table.h"
31 #include "main/sound-of-music.h"
32 #include "market/arena-info-table.h"
33 #include "mind/mind-mirror-master.h"
34 #include "monster-race/monster-race.h"
35 #include "monster-race/race-flags2.h"
36 #include "monster-race/race-flags3.h"
37 #include "monster/monster-describer.h"
38 #include "monster/monster-description-types.h"
39 #include "monster/monster-info.h"
40 #include "mutation/mutation-flag-types.h"
41 #include "object-enchant/tr-types.h"
42 #include "object-hook/hook-armor.h"
43 #include "object/item-tester-hooker.h"
44 #include "object/object-broken.h"
45 #include "object/object-flags.h"
46 #include "player-base/player-class.h"
47 #include "player-info/class-info.h"
48 #include "player-info/race-types.h"
49 #include "player-info/samurai-data-type.h"
50 #include "player/player-personality-types.h"
51 #include "player/player-status-flags.h"
52 #include "player/player-status-resist.h"
53 #include "player/player-status.h"
54 #include "player/race-info-table.h"
55 #include "player/special-defense-types.h"
56 #include "racial/racial-android.h"
57 #include "save/save.h"
58 #include "status/base-status.h"
59 #include "status/element-resistance.h"
60 #include "system/building-type-definition.h"
61 #include "system/floor-type-definition.h"
62 #include "system/monster-race-definition.h"
63 #include "system/monster-type-definition.h"
64 #include "system/object-type-definition.h"
65 #include "system/player-type-definition.h"
66 #include "term/screen-processor.h"
67 #include "term/term-color-types.h"
68 #include "util/bit-flags-calculator.h"
69 #include "util/string-processor.h"
70 #include "view/display-messages.h"
71 #include "world/world.h"
72
73 using dam_func = HIT_POINT (*)(PlayerType *player_ptr, HIT_POINT dam, concptr kb_str, bool aura);
74
75 /*!
76  * @brief 酸攻撃による装備のAC劣化処理 /
77  * Acid has hit the player, attempt to affect some armor.
78  * @param 酸を浴びたキャラクタへの参照ポインタ
79  * @return 装備による軽減があったならTRUEを返す
80  * @details
81  * 免疫があったらそもそもこの関数は実行されない (確実に錆びない).
82  * Note that the "base armor" of an object never changes.
83  * If any armor is damaged (or resists), the player takes less damage.
84  */
85 static bool acid_minus_ac(PlayerType *player_ptr)
86 {
87     ObjectType *o_ptr = nullptr;
88     switch (randint1(7)) {
89     case 1:
90         o_ptr = &player_ptr->inventory_list[INVEN_MAIN_HAND];
91         break;
92     case 2:
93         o_ptr = &player_ptr->inventory_list[INVEN_SUB_HAND];
94         break;
95     case 3:
96         o_ptr = &player_ptr->inventory_list[INVEN_BODY];
97         break;
98     case 4:
99         o_ptr = &player_ptr->inventory_list[INVEN_OUTER];
100         break;
101     case 5:
102         o_ptr = &player_ptr->inventory_list[INVEN_ARMS];
103         break;
104     case 6:
105         o_ptr = &player_ptr->inventory_list[INVEN_HEAD];
106         break;
107     case 7:
108         o_ptr = &player_ptr->inventory_list[INVEN_FEET];
109         break;
110     }
111
112     if ((o_ptr == nullptr) || (o_ptr->k_idx == 0) || !o_ptr->is_armour())
113         return false;
114
115     GAME_TEXT o_name[MAX_NLEN];
116     describe_flavor(player_ptr, o_name, o_ptr, OD_OMIT_PREFIX | OD_NAME_ONLY);
117     auto flgs = object_flags(o_ptr);
118     if (o_ptr->ac + o_ptr->to_a <= 0) {
119         msg_format(_("%sは既にボロボロだ!", "Your %s is already fully corroded!"), o_name);
120         return false;
121     }
122
123     if (flgs.has(TR_IGNORE_ACID)) {
124         msg_format(_("しかし%sには効果がなかった!", "Your %s is unaffected!"), o_name);
125         return true;
126     }
127
128     msg_format(_("%sが酸で腐食した!", "Your %s is corroded!"), o_name);
129     o_ptr->to_a--;
130     player_ptr->update |= PU_BONUS;
131     player_ptr->window_flags |= PW_EQUIP | PW_PLAYER;
132     calc_android_exp(player_ptr);
133     return true;
134 }
135
136 /*!
137  * @brief 酸属性によるプレイヤー損害処理 /
138  * Hurt the player with Acid
139  * @param player_ptr 酸を浴びたキャラクタへの参照ポインタ
140  * @param dam 基本ダメージ量
141  * @param kb_str ダメージ原因記述
142  * @param monspell 原因となったモンスター特殊攻撃ID
143  * @param aura オーラよるダメージが原因ならばTRUE
144  * @return 修正HPダメージ量
145  * @details 酸オーラは存在しないが関数ポインタのために引数だけは用意している
146  */
147 HIT_POINT acid_dam(PlayerType *player_ptr, HIT_POINT dam, concptr kb_str, bool aura)
148 {
149     int inv = (dam < 30) ? 1 : (dam < 60) ? 2
150                                           : 3;
151     bool double_resist = is_oppose_acid(player_ptr);
152     dam = dam * calc_acid_damage_rate(player_ptr) / 100;
153     if (dam <= 0)
154         return 0;
155
156     if (aura || !check_multishadow(player_ptr)) {
157         if ((!(double_resist || has_resist_acid(player_ptr))) && one_in_(HURT_CHANCE))
158             (void)do_dec_stat(player_ptr, A_CHR);
159
160         if (acid_minus_ac(player_ptr))
161             dam = (dam + 1) / 2;
162     }
163
164     HIT_POINT get_damage = take_hit(player_ptr, aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str);
165     if (!aura && !(double_resist && has_resist_acid(player_ptr)))
166         inventory_damage(player_ptr, BreakerAcid(), inv);
167
168     return get_damage;
169 }
170
171 /*!
172  * @brief 電撃属性によるプレイヤー損害処理 /
173  * Hurt the player with electricity
174  * @param player_ptr 電撃を浴びたキャラクタへの参照ポインタ
175  * @param dam 基本ダメージ量
176  * @param kb_str ダメージ原因記述
177  * @param monspell 原因となったモンスター特殊攻撃ID
178  * @param aura オーラよるダメージが原因ならばTRUE
179  * @return 修正HPダメージ量
180  */
181 HIT_POINT elec_dam(PlayerType *player_ptr, HIT_POINT dam, concptr kb_str, bool aura)
182 {
183     int inv = (dam < 30) ? 1 : (dam < 60) ? 2
184                                           : 3;
185     bool double_resist = is_oppose_elec(player_ptr);
186
187     dam = dam * calc_elec_damage_rate(player_ptr) / 100;
188
189     if (dam <= 0)
190         return 0;
191
192     if (aura || !check_multishadow(player_ptr)) {
193         if ((!(double_resist || has_resist_elec(player_ptr))) && one_in_(HURT_CHANCE))
194             (void)do_dec_stat(player_ptr, A_DEX);
195     }
196
197     HIT_POINT get_damage = take_hit(player_ptr, aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str);
198     if (!aura && !(double_resist && has_resist_elec(player_ptr)))
199         inventory_damage(player_ptr, BreakerElec(), inv);
200
201     return get_damage;
202 }
203
204 /*!
205  * @brief 火炎属性によるプレイヤー損害処理 /
206  * Hurt the player with Fire
207  * @param player_ptr 火炎を浴びたキャラクタへの参照ポインタ
208  * @param dam 基本ダメージ量
209  * @param kb_str ダメージ原因記述
210  * @param monspell 原因となったモンスター特殊攻撃ID
211  * @param aura オーラよるダメージが原因ならばTRUE
212  * @return 修正HPダメージ量
213  */
214 HIT_POINT fire_dam(PlayerType *player_ptr, HIT_POINT dam, concptr kb_str, bool aura)
215 {
216     int inv = (dam < 30) ? 1 : (dam < 60) ? 2
217                                           : 3;
218     bool double_resist = is_oppose_fire(player_ptr);
219
220     /* Totally immune */
221     if (has_immune_fire(player_ptr) || (dam <= 0))
222         return 0;
223
224     dam = dam * calc_fire_damage_rate(player_ptr) / 100;
225     if (aura || !check_multishadow(player_ptr)) {
226         if ((!(double_resist || has_resist_fire(player_ptr))) && one_in_(HURT_CHANCE))
227             (void)do_dec_stat(player_ptr, A_STR);
228     }
229
230     HIT_POINT get_damage = take_hit(player_ptr, aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str);
231     if (!aura && !(double_resist && has_resist_fire(player_ptr)))
232         inventory_damage(player_ptr, BreakerFire(), inv);
233
234     return get_damage;
235 }
236
237 /*!
238  * @brief 冷気属性によるプレイヤー損害処理 /
239  * Hurt the player with Cold
240  * @param player_ptr 冷気を浴びたキャラクタへの参照ポインタ
241  * @param dam 基本ダメージ量
242  * @param kb_str ダメージ原因記述
243  * @param monspell 原因となったモンスター特殊攻撃ID
244  * @param aura オーラよるダメージが原因ならばTRUE
245  * @return 修正HPダメージ量
246  */
247 HIT_POINT cold_dam(PlayerType *player_ptr, HIT_POINT dam, concptr kb_str, bool aura)
248 {
249     int inv = (dam < 30) ? 1 : (dam < 60) ? 2
250                                           : 3;
251     bool double_resist = is_oppose_cold(player_ptr);
252     if (has_immune_cold(player_ptr) || (dam <= 0))
253         return 0;
254
255     dam = dam * calc_cold_damage_rate(player_ptr) / 100;
256     if (aura || !check_multishadow(player_ptr)) {
257         if ((!(double_resist || has_resist_cold(player_ptr))) && one_in_(HURT_CHANCE))
258             (void)do_dec_stat(player_ptr, A_STR);
259     }
260
261     HIT_POINT get_damage = take_hit(player_ptr, aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str);
262     if (!aura && !(double_resist && has_resist_cold(player_ptr)))
263         inventory_damage(player_ptr, BreakerCold(), inv);
264
265     return get_damage;
266 }
267
268 /*
269  * Decreases players hit points and sets death flag if necessary
270  *
271  * Invulnerability needs to be changed into a "shield"
272  *
273  * Hack -- this function allows the user to save (or quit)
274  * the game when he dies, since the "You die." message is shown before
275  * setting the player to "dead".
276  */
277 int take_hit(PlayerType *player_ptr, int damage_type, HIT_POINT damage, concptr hit_from)
278 {
279     int old_chp = player_ptr->chp;
280
281     char death_message[1024];
282     char tmp[1024];
283
284     int warning = (player_ptr->mhp * hitpoint_warn / 10);
285     if (player_ptr->is_dead)
286         return 0;
287
288     if (player_ptr->sutemi)
289         damage *= 2;
290     if (PlayerClass(player_ptr).samurai_stance_is(SamuraiStanceType::IAI))
291         damage += (damage + 4) / 5;
292
293     if (damage_type != DAMAGE_USELIFE) {
294         disturb(player_ptr, true, true);
295         if (auto_more) {
296             player_ptr->now_damaged = true;
297         }
298     }
299
300     if ((damage_type != DAMAGE_USELIFE) && (damage_type != DAMAGE_LOSELIFE)) {
301         if (is_invuln(player_ptr) && (damage < 9000)) {
302             if (damage_type == DAMAGE_FORCE) {
303                 msg_print(_("バリアが切り裂かれた!", "The attack cuts your shield of invulnerability open!"));
304             } else if (one_in_(PENETRATE_INVULNERABILITY)) {
305                 msg_print(_("無敵のバリアを破って攻撃された!", "The attack penetrates your shield of invulnerability!"));
306             } else {
307                 return 0;
308             }
309         }
310
311         if (check_multishadow(player_ptr)) {
312             if (damage_type == DAMAGE_FORCE) {
313                 msg_print(_("幻影もろとも体が切り裂かれた!", "The attack hits Shadow together with you!"));
314             } else if (damage_type == DAMAGE_ATTACK) {
315                 msg_print(_("攻撃は幻影に命中し、あなたには届かなかった。", "The attack hits Shadow, but you are unharmed!"));
316                 return 0;
317             }
318         }
319
320         if (player_ptr->wraith_form) {
321             if (damage_type == DAMAGE_FORCE) {
322                 msg_print(_("半物質の体が切り裂かれた!", "The attack cuts through your ethereal body!"));
323             } else {
324                 damage /= 2;
325                 if ((damage == 0) && one_in_(2))
326                     damage = 1;
327             }
328         }
329
330         if (PlayerClass(player_ptr).samurai_stance_is(SamuraiStanceType::MUSOU)) {
331             damage /= 2;
332             if ((damage == 0) && one_in_(2))
333                 damage = 1;
334         }
335     }
336
337     player_ptr->chp -= damage;
338     if (player_ptr->chp < -9999)
339         player_ptr->chp = -9999;
340     if (damage_type == DAMAGE_GENO && player_ptr->chp < 0) {
341         damage += player_ptr->chp;
342         player_ptr->chp = 0;
343     }
344
345     player_ptr->redraw |= PR_HP;
346     player_ptr->window_flags |= PW_PLAYER;
347
348     if (damage_type != DAMAGE_GENO && player_ptr->chp == 0) {
349         chg_virtue(player_ptr, V_SACRIFICE, 1);
350         chg_virtue(player_ptr, V_CHANCE, 2);
351     }
352
353     if (player_ptr->chp < 0 && !cheat_immortal) {
354         bool android = player_ptr->prace == PlayerRaceType::ANDROID;
355
356         /* 死んだ時に強制終了して死を回避できなくしてみた by Habu */
357         if (!cheat_save && !save_player(player_ptr, SAVE_TYPE_CLOSE_GAME))
358             msg_print(_("セーブ失敗!", "death save failed!"));
359
360         sound(SOUND_DEATH);
361         chg_virtue(player_ptr, V_SACRIFICE, 10);
362         handle_stuff(player_ptr);
363         player_ptr->leaving = true;
364         if (!cheat_immortal)
365             player_ptr->is_dead = true;
366         if (player_ptr->current_floor_ptr->inside_arena) {
367             concptr m_name = r_info[arena_info[player_ptr->arena_number].r_idx].name.c_str();
368             msg_format(_("あなたは%sの前に敗れ去った。", "You are beaten by %s."), m_name);
369             msg_print(nullptr);
370             if (record_arena)
371                 exe_write_diary(player_ptr, DIARY_ARENA, -1 - player_ptr->arena_number, m_name);
372         } else {
373             auto q_idx = quest_number(player_ptr, player_ptr->current_floor_ptr->dun_level);
374             bool seppuku = streq(hit_from, "Seppuku");
375             bool winning_seppuku = w_ptr->total_winner && seppuku;
376
377             play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_GAMEOVER);
378
379 #ifdef WORLD_SCORE
380             screen_dump = make_screen_dump(player_ptr);
381 #endif
382             if (seppuku) {
383                 strcpy(player_ptr->died_from, hit_from);
384 #ifdef JP
385                 if (!winning_seppuku)
386                     strcpy(player_ptr->died_from, "切腹");
387 #endif
388             } else {
389                 char dummy[1024];
390 #ifdef JP
391                 sprintf(dummy, "%s%s%s",
392                     !player_ptr->paralyzed ? ""
393                     : player_ptr->free_act ? "彫像状態で"
394                                            : "麻痺状態で",
395                     player_ptr->hallucinated ? "幻覚に歪んだ" : "", hit_from);
396 #else
397                 sprintf(dummy, "%s%s", hit_from, !player_ptr->paralyzed ? "" : " while helpless");
398 #endif
399                 angband_strcpy(player_ptr->died_from, dummy, sizeof player_ptr->died_from);
400             }
401
402             w_ptr->total_winner = false;
403             if (winning_seppuku) {
404                 add_retired_class(player_ptr->pclass);
405                 exe_write_diary(player_ptr, DIARY_DESCRIPTION, 0, _("勝利の後切腹した。", "committed seppuku after the winning."));
406             } else {
407                 char buf[20];
408
409                 if (player_ptr->current_floor_ptr->inside_arena)
410                     strcpy(buf, _("アリーナ", "in the Arena"));
411                 else if (!is_in_dungeon(player_ptr))
412                     strcpy(buf, _("地上", "on the surface"));
413                 else if (inside_quest(q_idx) && (quest_type::is_fixed(q_idx) && !((q_idx == QuestId::OBERON) || (q_idx == QuestId::SERPENT))))
414                     strcpy(buf, _("クエスト", "in a quest"));
415                 else
416                     sprintf(buf, _("%d階", "level %d"), (int)player_ptr->current_floor_ptr->dun_level);
417
418                 sprintf(tmp, _("%sで%sに殺された。", "killed by %s %s."), buf, player_ptr->died_from);
419                 exe_write_diary(player_ptr, DIARY_DESCRIPTION, 0, tmp);
420             }
421
422             exe_write_diary(player_ptr, DIARY_GAMESTART, 1, _("-------- ゲームオーバー --------", "--------   Game  Over   --------"));
423             exe_write_diary(player_ptr, DIARY_DESCRIPTION, 1, "\n\n\n\n");
424             flush();
425             if (get_check_strict(player_ptr, _("画面を保存しますか?", "Dump the screen? "), CHECK_NO_HISTORY))
426                 do_cmd_save_screen(player_ptr);
427
428             flush();
429             if (player_ptr->last_message)
430                 string_free(player_ptr->last_message);
431
432             player_ptr->last_message = nullptr;
433             if (!last_words) {
434 #ifdef JP
435                 msg_format("あなたは%sました。", android ? "壊れ" : "死に");
436 #else
437                 msg_print(android ? "You are broken." : "You die.");
438 #endif
439
440                 msg_print(nullptr);
441             } else {
442                 if (winning_seppuku) {
443                     get_rnd_line(_("seppuku_j.txt", "seppuku.txt"), 0, death_message);
444                 } else {
445                     get_rnd_line(_("death_j.txt", "death.txt"), 0, death_message);
446                 }
447
448                 do {
449 #ifdef JP
450                     while (!get_string(winning_seppuku ? "辞世の句: " : "断末魔の叫び: ", death_message, sizeof(death_message)))
451                         ;
452 #else
453                     while (!get_string("Last words: ", death_message, 1024))
454                         ;
455 #endif
456                 } while (winning_seppuku && !get_check_strict(player_ptr, _("よろしいですか?", "Are you sure? "), CHECK_NO_HISTORY));
457
458                 if (death_message[0] == '\0') {
459 #ifdef JP
460                     strcpy(death_message, format("あなたは%sました。", android ? "壊れ" : "死に"));
461 #else
462                     strcpy(death_message, android ? "You are broken." : "You die.");
463 #endif
464                 } else
465                     player_ptr->last_message = string_make(death_message);
466
467 #ifdef JP
468                 if (winning_seppuku) {
469                     int i, len;
470                     int w = Term->wid;
471                     int h = Term->hgt;
472                     int msg_pos_x[9] = { 5, 7, 9, 12, 14, 17, 19, 21, 23 };
473                     int msg_pos_y[9] = { 3, 4, 5, 4, 5, 4, 5, 6, 4 };
474                     concptr str;
475                     char *str2;
476
477                     term_clear();
478
479                     /* 桜散る */
480                     for (i = 0; i < 40; i++)
481                         term_putstr(randint0(w / 2) * 2, randint0(h), 2, TERM_VIOLET, "υ");
482
483                     str = death_message;
484                     if (strncmp(str, "「", 2) == 0)
485                         str += 2;
486
487                     str2 = angband_strstr(str, "」");
488                     if (str2 != nullptr)
489                         *str2 = '\0';
490
491                     i = 0;
492                     while (i < 9) {
493                         str2 = angband_strstr(str, " ");
494                         if (str2 == nullptr)
495                             len = strlen(str);
496                         else
497                             len = str2 - str;
498
499                         if (len != 0) {
500                             term_putstr_v(w * 3 / 4 - 2 - msg_pos_x[i] * 2, msg_pos_y[i], len, TERM_WHITE, str);
501                             if (str2 == nullptr)
502                                 break;
503                             i++;
504                         }
505                         str = str2 + 1;
506                         if (*str == 0)
507                             break;
508                     }
509
510                     term_putstr(w - 1, h - 1, 1, TERM_WHITE, " ");
511                     flush();
512 #ifdef WORLD_SCORE
513                     screen_dump = make_screen_dump(player_ptr);
514 #endif
515                     (void)inkey();
516                 } else
517 #endif
518                     msg_print(death_message);
519             }
520         }
521
522         return damage;
523     }
524
525     handle_stuff(player_ptr);
526     if (player_ptr->chp < warning) {
527         if (old_chp > warning)
528             bell();
529
530         sound(SOUND_WARN);
531         if (record_danger && (old_chp > warning)) {
532             if (player_ptr->hallucinated && damage_type == DAMAGE_ATTACK)
533                 hit_from = _("何か", "something");
534
535             sprintf(tmp, _("%sによってピンチに陥った。", "was in a critical situation because of %s."), hit_from);
536             exe_write_diary(player_ptr, DIARY_DESCRIPTION, 0, tmp);
537         }
538
539         if (auto_more)
540             player_ptr->now_damaged = true;
541
542         msg_print(_("*** 警告:低ヒット・ポイント! ***", "*** LOW HITPOINT WARNING! ***"));
543         msg_print(nullptr);
544         flush();
545     }
546
547     if (player_ptr->wild_mode && !player_ptr->leaving && (player_ptr->chp < std::max(warning, player_ptr->mhp / 5)))
548         change_wild_mode(player_ptr, false);
549
550     return damage;
551 }
552
553 /*!
554  * @brief 属性に応じた敵オーラによるプレイヤーのダメージ処理
555  * @param m_ptr オーラを持つモンスターの構造体参照ポインタ
556  * @param immune ダメージを回避できる免疫フラグ
557  * @param flags_offset オーラフラグ配列の参照オフセット
558  * @param r_flags_offset モンスターの耐性配列の参照オフセット
559  * @param aura_flag オーラフラグ配列
560  * @param dam_func ダメージ処理を行う関数の参照ポインタ
561  * @param message オーラダメージを受けた際のメッセージ
562  */
563 static void process_aura_damage(monster_type *m_ptr, PlayerType *player_ptr, bool immune, MonsterAuraType aura_flag, dam_func dam_func, concptr message)
564 {
565     auto *r_ptr = &r_info[m_ptr->r_idx];
566     if (r_ptr->aura_flags.has_not(aura_flag) || immune) {
567         return;
568     }
569
570     GAME_TEXT mon_name[MAX_NLEN];
571     int aura_damage = damroll(1 + (r_ptr->level / 26), 1 + (r_ptr->level / 17));
572     monster_desc(player_ptr, mon_name, m_ptr, MD_WRONGDOER_NAME);
573     msg_print(message);
574     (*dam_func)(player_ptr, aura_damage, mon_name, true);
575     if (is_original_ap_and_seen(player_ptr, m_ptr)) {
576         r_ptr->r_aura_flags.set(aura_flag);
577     }
578
579     handle_stuff(player_ptr);
580 }
581
582 /*!
583  * @brief 敵オーラによるプレイヤーのダメージ処理
584  * @param m_ptr オーラを持つモンスターの構造体参照ポインタ
585  * @param player_ptr プレイヤーへの参照ポインタ
586  */
587 void touch_zap_player(monster_type *m_ptr, PlayerType *player_ptr)
588 {
589     process_aura_damage(m_ptr, player_ptr, has_immune_fire(player_ptr) != 0, MonsterAuraType::FIRE, fire_dam, _("突然とても熱くなった!", "You are suddenly very hot!"));
590     process_aura_damage(m_ptr, player_ptr, has_immune_cold(player_ptr) != 0, MonsterAuraType::COLD, cold_dam, _("突然とても寒くなった!", "You are suddenly very cold!"));
591     process_aura_damage(m_ptr, player_ptr, has_immune_elec(player_ptr) != 0, MonsterAuraType::ELEC, elec_dam, _("電撃をくらった!", "You get zapped!"));
592 }