OSDN Git Service

[Refactor] #1951 整形
[hengbandforosx/hengbandosx.git] / src / effect / effect-monster.cpp
1 /*!
2  * @brief 魔法によるモンスターへの効果まとめ
3  * @date 2020/04/29
4  * @author Hourier
5  */
6
7 #include "effect/effect-monster.h"
8 #include "avatar/avatar.h"
9 #include "core/disturbance.h"
10 #include "core/player-redraw-types.h"
11 #include "core/stuff-handler.h"
12 #include "core/window-redrawer.h"
13 #include "effect/attribute-types.h"
14 #include "effect/effect-characteristics.h"
15 #include "effect/effect-monster-switcher.h"
16 #include "effect/effect-monster-util.h"
17 #include "floor/cave.h"
18 #include "floor/floor-object.h"
19 #include "game-option/play-record-options.h"
20 #include "grid/grid.h"
21 #include "io/write-diary.h"
22 #include "main/sound-definitions-table.h"
23 #include "main/sound-of-music.h"
24 #include "monster-floor/monster-death.h"
25 #include "monster-floor/monster-move.h"
26 #include "monster-floor/monster-remover.h"
27 #include "monster-race/monster-race.h"
28 #include "monster-race/race-flags-resistance.h"
29 #include "monster-race/race-flags1.h"
30 #include "monster-race/race-flags3.h"
31 #include "monster-race/race-flags7.h"
32 #include "monster-race/race-indice-types.h"
33 #include "monster/monster-damage.h"
34 #include "monster/monster-describer.h"
35 #include "monster/monster-description-types.h"
36 #include "monster/monster-info.h"
37 #include "monster/monster-status-setter.h"
38 #include "monster/monster-status.h"
39 #include "monster/monster-update.h"
40 #include "object-enchant/special-object-flags.h"
41 #include "object/object-kind-hook.h"
42 #include "spell-kind/blood-curse.h"
43 #include "spell-kind/spells-polymorph.h"
44 #include "spell-kind/spells-teleport.h"
45 #include "spells-effect-util.h"
46 #include "sv-definition/sv-other-types.h"
47 #include "system/floor-type-definition.h"
48 #include "system/grid-type-definition.h"
49 #include "system/monster-race-definition.h"
50 #include "system/monster-type-definition.h"
51 #include "system/object-type-definition.h"
52 #include "system/player-type-definition.h"
53 #include "util/bit-flags-calculator.h"
54 #include "view/display-messages.h"
55 #include <algorithm>
56
57 /*!
58  * @brief ビーム/ボルト/ボール系魔法によるモンスターへの効果があるかないかを判定する
59  * @param player_ptr プレイヤーへの参照ポインタ
60  * @param em_ptr モンスター効果構造体への参照ポインタ
61  * @return 効果が何もないならFALSE、何かあるならTRUE
62  */
63 static process_result is_affective(PlayerType *player_ptr, effect_monster_type *em_ptr)
64 {
65     if (!em_ptr->g_ptr->m_idx)
66         return PROCESS_FALSE;
67     if (em_ptr->who && (em_ptr->g_ptr->m_idx == em_ptr->who))
68         return PROCESS_FALSE;
69     if (sukekaku && ((em_ptr->m_ptr->r_idx == MON_SUKE) || (em_ptr->m_ptr->r_idx == MON_KAKU)))
70         return PROCESS_FALSE;
71     if (em_ptr->m_ptr->hp < 0)
72         return PROCESS_FALSE;
73     if (em_ptr->who || em_ptr->g_ptr->m_idx != player_ptr->riding)
74         return PROCESS_TRUE;
75
76     switch (em_ptr->attribute) {
77     case AttributeType::OLD_HEAL:
78     case AttributeType::OLD_SPEED:
79     case AttributeType::STAR_HEAL:
80         return PROCESS_TRUE;
81     case AttributeType::OLD_SLOW:
82     case AttributeType::OLD_SLEEP:
83     case AttributeType::OLD_CLONE:
84     case AttributeType::OLD_CONF:
85     case AttributeType::OLD_POLY:
86     case AttributeType::GENOCIDE:
87     case AttributeType::E_GENOCIDE:
88         return PROCESS_CONTINUE;
89     default:
90         break;
91     }
92
93     return PROCESS_FALSE;
94 }
95
96 /*!
97  * @brief 魔法の効果やモンスター種別(MAKE/FEMALE/なし)に応じて表示するメッセージを変更する
98  * @param player_ptr プレイヤーへの参照ポインタ
99  * @param em_ptr モンスター効果構造体への参照ポインタ
100  */
101 static void make_description_of_affecred_monster(PlayerType *player_ptr, effect_monster_type *em_ptr)
102 {
103     em_ptr->dam = (em_ptr->dam + em_ptr->r) / (em_ptr->r + 1);
104     monster_desc(player_ptr, em_ptr->m_name, em_ptr->m_ptr, 0);
105     monster_desc(player_ptr, em_ptr->m_poss, em_ptr->m_ptr, MD_PRON_VISIBLE | MD_POSSESSIVE);
106 }
107
108 /*!
109  * @brief モンスターへの効果属性による耐性及び効果を処理する( / Proccess affecting to monster by effect.
110  * @param player_ptr プレイヤーへの参照ポインタ
111  * @param em_ptr モンスター効果構造体への参照ポインタ
112  * @return 完全な耐性が発動したらCONTINUE、そうでないなら効果処理の結果
113  * @details
114  * 完全な耐性を持っていたら、一部属性を除いて影響は及ぼさない
115  * デバッグ属性、モンスター打撃、モンスター射撃であれば貫通する
116  */
117 static process_result exe_affect_monster_by_effect(PlayerType *player_ptr, effect_monster_type *em_ptr)
118 {
119     const std::vector<AttributeType> effect_arrtibute = {
120         AttributeType::OLD_CLONE,
121         AttributeType::STAR_HEAL,
122         AttributeType::OLD_HEAL,
123         AttributeType::OLD_SPEED,
124         AttributeType::CAPTURE,
125         AttributeType::PHOTO,
126     };
127     const auto check = [em_ptr](const AttributeType attribute) {
128         return em_ptr->attribute == attribute;
129     };
130
131     process_result result = is_affective(player_ptr, em_ptr);
132     if (result != PROCESS_TRUE) {
133         if (result == PROCESS_CONTINUE) {
134             em_ptr->note = _("には効果がなかった。", " is unaffected.");
135             em_ptr->dam = 0;
136         }
137         return result;
138     }
139
140     bool do_effect = none_bits(em_ptr->r_ptr->flagsr, RFR_RES_ALL);
141     do_effect |= std::any_of(effect_arrtibute.cbegin(), effect_arrtibute.cend(), check);
142
143     if (do_effect)
144         return switch_effects_monster(player_ptr, em_ptr);
145
146     bool ignore_res_all = (em_ptr->attribute == AttributeType::DEBUG);
147     ignore_res_all |= (em_ptr->attribute == AttributeType::MONSTER_MELEE);
148     ignore_res_all |= (em_ptr->attribute == AttributeType::MONSTER_SHOOT);
149
150     if (any_bits(em_ptr->r_ptr->flagsr, RFR_RES_ALL) && ignore_res_all)
151         return switch_effects_monster(player_ptr, em_ptr);
152
153     em_ptr->note = _("には完全な耐性がある!", " is immune.");
154     em_ptr->dam = 0;
155     if (is_original_ap_and_seen(player_ptr, em_ptr->m_ptr))
156         em_ptr->r_ptr->r_flagsr |= (RFR_RES_ALL);
157
158     if (em_ptr->attribute == AttributeType::LITE_WEAK || em_ptr->attribute == AttributeType::KILL_WALL)
159         em_ptr->skipped = true;
160
161     return PROCESS_CONTINUE;
162 }
163
164 /*!
165  * @brief ペットの死亡を処理する
166  * @param player_ptr プレイヤーへの参照ポインタ
167  * @param em_ptr モンスター効果構造体への参照ポインタ
168  */
169 static void effect_damage_killed_pet(PlayerType *player_ptr, effect_monster_type *em_ptr)
170 {
171     bool sad = is_pet(em_ptr->m_ptr) && !(em_ptr->m_ptr->ml);
172     if (em_ptr->known && em_ptr->note) {
173         monster_desc(player_ptr, em_ptr->m_name, em_ptr->m_ptr, MD_TRUE_NAME);
174         if (em_ptr->see_s_msg)
175             msg_format("%^s%s", em_ptr->m_name, em_ptr->note);
176         else
177             player_ptr->current_floor_ptr->monster_noise = true;
178     }
179
180     if (em_ptr->who > 0)
181         monster_gain_exp(player_ptr, em_ptr->who, em_ptr->m_ptr->r_idx);
182
183     monster_death(player_ptr, em_ptr->g_ptr->m_idx, false, em_ptr->attribute);
184     delete_monster_idx(player_ptr, em_ptr->g_ptr->m_idx);
185     if (sad)
186         msg_print(_("少し悲しい気分がした。", "You feel sad for a moment."));
187 }
188
189 /*!
190  * @brief モンスターの睡眠を処理する
191  * @param player_ptr プレイヤーへの参照ポインタ
192  * @param em_ptr モンスター効果構造体への参照ポインタ
193  */
194 static void effect_damage_makes_sleep(PlayerType *player_ptr, effect_monster_type *em_ptr)
195 {
196     if (em_ptr->note && em_ptr->seen_msg)
197         msg_format("%^s%s", em_ptr->m_name, em_ptr->note);
198     else if (em_ptr->see_s_msg)
199         message_pain(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->dam);
200     else
201         player_ptr->current_floor_ptr->monster_noise = true;
202
203     if (em_ptr->do_sleep)
204         (void)set_monster_csleep(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->do_sleep);
205 }
206
207 /*!
208  * @brief モンスターからモンスターへのダメージを処理する / Hurt the monster by damages another monster did.
209  * @param player_ptr プレイヤーへの参照ポインタ
210  * @param em_ptr モンスター効果構造体への参照ポインタ
211  * @return ダメージを処理しなかった(モンスターIDがプレイヤー自身)場合はFALSE、処理した(モンスターだった)場合TRUE
212  * @details
213  * モンスターIDがプレイヤー(0)の場合は処理しない。
214  */
215 static bool deal_effect_damage_from_monster(PlayerType *player_ptr, effect_monster_type *em_ptr)
216 {
217     if (em_ptr->who <= 0)
218         return false;
219
220     if (player_ptr->health_who == em_ptr->g_ptr->m_idx)
221         player_ptr->redraw |= (PR_HEALTH);
222     if (player_ptr->riding == em_ptr->g_ptr->m_idx)
223         player_ptr->redraw |= (PR_UHEALTH);
224
225     (void)set_monster_csleep(player_ptr, em_ptr->g_ptr->m_idx, 0);
226     em_ptr->m_ptr->hp -= em_ptr->dam;
227     if (em_ptr->m_ptr->hp < 0)
228         effect_damage_killed_pet(player_ptr, em_ptr);
229     else
230         effect_damage_makes_sleep(player_ptr, em_ptr);
231
232     return true;
233 }
234
235 /*!
236  * @brief 不潔な病人の治療処理
237  * @param player_ptr プレイヤーへの参照ポインタ
238  * @param em_ptr モンスター効果構造体への参照ポインタ
239  * @return 大賞モンスターが不潔な病人だった場合はTRUE、それ以外はFALSE
240  */
241 static bool heal_leaper(PlayerType *player_ptr, effect_monster_type *em_ptr)
242 {
243     if (!em_ptr->heal_leper)
244         return false;
245
246     if (em_ptr->seen_msg)
247         msg_print(_("不潔な病人は病気が治った!", "The Mangy looking leper is healed!"));
248
249     if (record_named_pet && is_pet(em_ptr->m_ptr) && em_ptr->m_ptr->nickname) {
250         char m2_name[MAX_NLEN];
251         monster_desc(player_ptr, m2_name, em_ptr->m_ptr, MD_INDEF_VISIBLE);
252         exe_write_diary(player_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_HEAL_LEPER, m2_name);
253     }
254
255     delete_monster_idx(player_ptr, em_ptr->g_ptr->m_idx);
256     return true;
257 }
258
259 /*!
260  * @brief プレイヤー起因の効果によるダメージを処理 / Deal damages from player and fear by them.
261  * @param player_ptr プレイヤーへの参照ポインタ
262  * @param em_ptr モンスター効果構造体への参照ポインタ
263  * @return モンスターが死んだらTRUE、生きていたらFALSE
264  * @details
265  * em_ptr->do_fearによる恐怖メッセージもここで表示。
266  */
267 static bool deal_effect_damage_from_player(PlayerType *player_ptr, effect_monster_type *em_ptr)
268 {
269     bool fear = false;
270     MonsterDamageProcessor mdp(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->dam, &fear, em_ptr->attribute);
271     if (mdp.mon_take_hit(em_ptr->note_dies))
272         return true;
273
274     if (em_ptr->do_sleep)
275         anger_monster(player_ptr, em_ptr->m_ptr);
276
277     if (em_ptr->note && em_ptr->seen)
278         msg_format(_("%s%s", "%^s%s"), em_ptr->m_name, em_ptr->note);
279     else if (em_ptr->known && (em_ptr->dam || !em_ptr->do_fear))
280         message_pain(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->dam);
281
282     if (((em_ptr->dam > 0) || em_ptr->get_angry) && !em_ptr->do_sleep)
283         anger_monster(player_ptr, em_ptr->m_ptr);
284
285     if ((fear || em_ptr->do_fear) && em_ptr->seen) {
286         sound(SOUND_FLEE);
287         msg_format(_("%^sは恐怖して逃げ出した!", "%^s flees in terror!"), em_ptr->m_name);
288     }
289
290     return false;
291 }
292
293 /*!
294  * @brief モンスターに効果のダメージを与える / Deal effect damage to monster.
295  * @param player_ptr プレイヤーへの参照ポインタ
296  * @param em_ptr モンスター効果構造体への参照ポインタ
297  * @details
298  * 以下のいずれかの処理を行う。
299  * 1.モンスターによる効果ダメージの処理
300  * 2.不潔な病人を癒す処理
301  * 3.プレイヤーによる効果ダメージの処理
302  * 4.睡眠する処理
303  */
304 static void deal_effect_damage_to_monster(PlayerType *player_ptr, effect_monster_type *em_ptr)
305 {
306     if (em_ptr->attribute == AttributeType::DRAIN_MANA)
307         return;
308
309     // モンスターによる効果
310     if (deal_effect_damage_from_monster(player_ptr, em_ptr))
311         return;
312
313     //プレイヤーによる効果
314     if (heal_leaper(player_ptr, em_ptr))
315         return;
316     if (deal_effect_damage_from_player(player_ptr, em_ptr))
317         return;
318
319     if (em_ptr->do_sleep)
320         (void)set_monster_csleep(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->do_sleep);
321 }
322
323 /*!
324  * @brief プレイヤーが眠っている敵に効果を及ぼした場合の徳の変化
325  * @param player_ptr プレイヤーへの参照ポインタ
326  * @param em_ptr モンスター効果構造体への参照ポインタ
327  */
328 static void effect_makes_change_virtues(PlayerType *player_ptr, effect_monster_type *em_ptr)
329 {
330     if ((em_ptr->who > 0) || !em_ptr->slept)
331         return;
332
333     if (em_ptr->r_ptr->kind_flags.has_not(MonsterKindType::EVIL) || one_in_(5))
334         chg_virtue(player_ptr, V_COMPASSION, -1);
335     if (em_ptr->r_ptr->kind_flags.has_not(MonsterKindType::EVIL) || one_in_(5))
336         chg_virtue(player_ptr, V_HONOUR, -1);
337 }
338
339 /*!
340  * @brief 魔法効果に対する強制処理(変身の強制解除、死なない処理)
341  * @param player_ptr プレイヤーへの参照ポインタ
342  * @param em_ptr モンスター効果構造体への参照ポインタ
343  */
344 static void affected_monster_prevents_bad_status(PlayerType *player_ptr, effect_monster_type *em_ptr)
345 {
346     if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE) || any_bits(em_ptr->r_ptr->flags1, RF1_QUESTOR) || (player_ptr->riding && (em_ptr->g_ptr->m_idx == player_ptr->riding)))
347         em_ptr->do_polymorph = false;
348
349     if ((em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE) || any_bits(em_ptr->r_ptr->flags1, RF1_QUESTOR) || (em_ptr->r_ptr->flags7 & RF7_NAZGUL)) && !player_ptr->phase_out && (em_ptr->who > 0) && (em_ptr->dam > em_ptr->m_ptr->hp))
350         em_ptr->dam = em_ptr->m_ptr->hp;
351 }
352
353 /*!
354  * @brief モンスターの朦朧値を蓄積させる
355  * @param player_ptr プレイヤーへの参照ポインタ
356  * @param em_ptr モンスター効果構造体への参照ポインタ
357  * @param stun_damage 朦朧値
358  */
359 static void effect_damage_piles_stun(PlayerType *player_ptr, effect_monster_type *em_ptr)
360 {
361     if ((em_ptr->do_stun == 0) || (em_ptr->r_ptr->flagsr & (RFR_RES_SOUN | RFR_RES_WALL)) || (em_ptr->r_ptr->flags3 & RF3_NO_STUN))
362         return;
363
364     if (em_ptr->seen)
365         em_ptr->obvious = true;
366
367     int turns = 0;
368     if (monster_stunned_remaining(em_ptr->m_ptr)) {
369         em_ptr->note = _("はひどくもうろうとした。", " is more dazed.");
370         turns = monster_stunned_remaining(em_ptr->m_ptr) + (em_ptr->do_stun / 2);
371     } else {
372         em_ptr->note = _("はもうろうとした。", " is dazed.");
373         turns = em_ptr->do_stun;
374     }
375
376     (void)set_monster_stunned(player_ptr, em_ptr->g_ptr->m_idx, turns);
377     em_ptr->get_angry = true;
378 }
379
380 /*!
381  * @brief モンスターの混乱値を蓄積させる
382  * @param player_ptr プレイヤーへの参照ポインタ
383  * @param em_ptr モンスター効果構造体への参照ポインタ
384  * @param stun_damage 混乱値
385  */
386 static void effect_damage_piles_confusion(PlayerType *player_ptr, effect_monster_type *em_ptr)
387 {
388     if ((em_ptr->do_conf == 0) || (em_ptr->r_ptr->flags3 & RF3_NO_CONF) || (em_ptr->r_ptr->flagsr & RFR_EFF_RES_CHAO_MASK))
389         return;
390
391     if (em_ptr->seen)
392         em_ptr->obvious = true;
393
394     int turns = 0;
395     if (monster_confused_remaining(em_ptr->m_ptr)) {
396         em_ptr->note = _("はさらに混乱したようだ。", " looks more confused.");
397         turns = monster_confused_remaining(em_ptr->m_ptr) + (em_ptr->do_conf / 2);
398     } else {
399         em_ptr->note = _("は混乱したようだ。", " looks confused.");
400         turns = em_ptr->do_conf;
401     }
402
403     (void)set_monster_confused(player_ptr, em_ptr->g_ptr->m_idx, turns);
404     em_ptr->get_angry = true;
405 }
406
407 /*!
408  * @brief モンスターの恐怖値を蓄積させる
409  * @param player_ptr プレイヤーへの参照ポインタ
410  * @param em_ptr モンスター効果構造体への参照ポインタ
411  * @param stun_damage 恐怖値
412  * @details
413  * 打撃ダメージによる恐怖もあるため、メッセージは後で表示。
414  */
415 static void effect_damage_piles_fear(PlayerType *player_ptr, effect_monster_type *em_ptr)
416 {
417     if (em_ptr->do_fear == 0 || any_bits(em_ptr->r_ptr->flags3, RF3_NO_FEAR))
418         return;
419
420     (void)set_monster_monfear(player_ptr, em_ptr->g_ptr->m_idx, monster_fear_remaining(em_ptr->m_ptr) + em_ptr->do_fear);
421     em_ptr->get_angry = true;
422 }
423
424 /*!
425  * @brief モンスターを衰弱させる
426  * @param em_ptr モンスター効果構造体への参照ポインタ
427  */
428 static void effect_damage_makes_weak(effect_monster_type *em_ptr)
429 {
430     if (em_ptr->do_time == 0)
431         return;
432
433     if (em_ptr->seen)
434         em_ptr->obvious = true;
435
436     if (em_ptr->do_time >= em_ptr->m_ptr->maxhp)
437         em_ptr->do_time = em_ptr->m_ptr->maxhp - 1;
438
439     if (em_ptr->do_time) {
440         em_ptr->note = _("は弱くなったようだ。", " seems weakened.");
441         em_ptr->m_ptr->maxhp -= em_ptr->do_time;
442         if ((em_ptr->m_ptr->hp - em_ptr->dam) > em_ptr->m_ptr->maxhp)
443             em_ptr->dam = em_ptr->m_ptr->hp - em_ptr->m_ptr->maxhp;
444     }
445
446     em_ptr->get_angry = true;
447 }
448
449 /*!
450  * @brief モンスターを変身させる
451  * @param player_ptr プレイヤーへの参照ポインタ
452  * @param em_ptr モンスター効果構造体への参照ポインタ
453  */
454 static void effect_damage_makes_polymorph(PlayerType *player_ptr, effect_monster_type *em_ptr)
455 {
456     if (!em_ptr->do_polymorph || (randint1(90) <= em_ptr->r_ptr->level))
457         return;
458
459     if (polymorph_monster(player_ptr, em_ptr->y, em_ptr->x)) {
460         if (em_ptr->seen)
461             em_ptr->obvious = true;
462
463         em_ptr->note = _("が変身した!", " changes!");
464         em_ptr->dam = 0;
465     }
466
467     em_ptr->m_ptr = &player_ptr->current_floor_ptr->m_list[em_ptr->g_ptr->m_idx];
468     em_ptr->r_ptr = &r_info[em_ptr->m_ptr->r_idx];
469 }
470
471 /*!
472  * @brief モンスターをテレポートさせる
473  * @param player_ptr プレイヤーへの参照ポインタ
474  * @param em_ptr モンスター効果構造体への参照ポインタ
475  */
476 static void effect_damage_makes_teleport(PlayerType *player_ptr, effect_monster_type *em_ptr)
477 {
478     if (em_ptr->do_dist == 0)
479         return;
480
481     if (em_ptr->seen)
482         em_ptr->obvious = true;
483
484     em_ptr->note = _("が消え去った!", " disappears!");
485
486     if (!em_ptr->who)
487         chg_virtue(player_ptr, V_VALOUR, -1);
488
489     teleport_flags tflag = i2enum<teleport_flags>((!em_ptr->who ? TELEPORT_DEC_VALOUR : TELEPORT_SPONTANEOUS) | TELEPORT_PASSIVE);
490     teleport_away(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->do_dist, tflag);
491
492     em_ptr->y = em_ptr->m_ptr->fy;
493     em_ptr->x = em_ptr->m_ptr->fx;
494     em_ptr->g_ptr = &player_ptr->current_floor_ptr->grid_array[em_ptr->y][em_ptr->x];
495 }
496
497 /*!
498  * @brief モンスターへのダメージに応じたメッセージを表示させ、異常状態を与える
499  * @param player_ptr プレイヤーへの参照ポインタ
500  * @param em_ptr モンスター効果構造体への参照ポインタ
501  * @details
502  * 以下の判定と処理を行う。
503  * 1.全耐性または無敵でダメージが通らなかった場合
504  * 2.ダメージ量が現HPを上回る場合
505  * 3.通常時(デバフをかける)
506  */
507 static void effect_damage_gives_bad_status(PlayerType *player_ptr, effect_monster_type *em_ptr)
508 {
509     int tmp_damage = em_ptr->dam;
510     em_ptr->dam = mon_damage_mod(player_ptr, em_ptr->m_ptr, em_ptr->dam, (bool)(em_ptr->attribute == AttributeType::PSY_SPEAR));
511     if ((tmp_damage > 0) && (em_ptr->dam == 0) && em_ptr->seen)
512         em_ptr->note = _("はダメージを受けていない。", " is unharmed.");
513
514     if (em_ptr->dam > em_ptr->m_ptr->hp)
515         em_ptr->note = em_ptr->note_dies;
516     else {
517         effect_damage_piles_stun(player_ptr, em_ptr);
518         effect_damage_piles_confusion(player_ptr, em_ptr);
519         effect_damage_piles_fear(player_ptr, em_ptr);
520         effect_damage_makes_weak(em_ptr);
521         effect_damage_makes_polymorph(player_ptr, em_ptr);
522         effect_damage_makes_teleport(player_ptr, em_ptr);
523     }
524 }
525
526 /*!
527  * @brief 効果によるモンスターへのダメージと付随効果を処理する
528  * @param player_ptr プレイヤーへの参照ポインタ
529  * @param em_ptr モンスター効果構造体への参照ポインタ
530  * @details
531  * 以下の処理を行う。
532  * 1.奇襲による徳の変化
533  * 2.完全な耐性及び無敵によるダメージのカット
534  * 3.ダメージによる付随効果の処理(混乱/朦朧/恐怖/衰弱/変身/テレポート)
535  * 4.ダメージ処理及び恐怖メッセージ
536  * 5.悪魔領域血の呪いによる事後処理
537  */
538 static void exe_affect_monster_by_damage(PlayerType *player_ptr, effect_monster_type *em_ptr)
539 {
540     effect_makes_change_virtues(player_ptr, em_ptr);
541     affected_monster_prevents_bad_status(player_ptr, em_ptr);
542     effect_damage_gives_bad_status(player_ptr, em_ptr);
543     deal_effect_damage_to_monster(player_ptr, em_ptr);
544     if ((em_ptr->attribute == AttributeType::BLOOD_CURSE) && one_in_(4))
545         blood_curse_to_enemy(player_ptr, em_ptr->who);
546 }
547
548 /*!
549  * @brief モンスター闘技場にいる場合の画面更新処理
550  * @param player_ptr プレイヤーへの参照ポインタ
551  * @param em_ptr モンスター効果構造体への参照ポインタ
552  */
553 static void update_phase_out_stat(PlayerType *player_ptr, effect_monster_type *em_ptr)
554 {
555     if (!player_ptr->phase_out)
556         return;
557
558     player_ptr->health_who = em_ptr->g_ptr->m_idx;
559     player_ptr->redraw |= (PR_HEALTH);
560     handle_stuff(player_ptr);
561 }
562
563 /*!
564  * @brief 魔法効果がペットに及んだ時の処理
565  * @param player_ptr プレイヤーへの参照ポインタ
566  * @param em_ptr モンスター効果構造体への参照ポインタ
567  */
568 static void postprocess_by_effected_pet(PlayerType *player_ptr, effect_monster_type *em_ptr)
569 {
570     if ((em_ptr->dam <= 0) || is_pet(em_ptr->m_ptr) || is_friendly(em_ptr->m_ptr))
571         return;
572
573     if (em_ptr->who == 0) {
574         if (!(em_ptr->flag & PROJECT_NO_HANGEKI))
575             set_target(em_ptr->m_ptr, monster_target_y, monster_target_x);
576
577         return;
578     }
579
580     if ((em_ptr->who > 0) && is_pet(em_ptr->m_caster_ptr) && !player_bold(player_ptr, em_ptr->m_ptr->target_y, em_ptr->m_ptr->target_x))
581         set_target(em_ptr->m_ptr, em_ptr->m_caster_ptr->fy, em_ptr->m_caster_ptr->fx);
582 }
583
584 /*!
585  * @brief 魔法効果が騎乗モンスターに及んだ時の処理
586  * @param player_ptr プレイヤーへの参照ポインタ
587  * @param em_ptr モンスター効果構造体への参照ポインタ
588  */
589 static void postprocess_by_riding_pet_effected(PlayerType *player_ptr, effect_monster_type *em_ptr)
590 {
591     if (!player_ptr->riding || (player_ptr->riding != em_ptr->g_ptr->m_idx) || (em_ptr->dam <= 0))
592         return;
593
594     if (em_ptr->m_ptr->hp > (em_ptr->m_ptr->maxhp / 3))
595         em_ptr->dam = (em_ptr->dam + 1) / 2;
596
597     rakubadam_m = (em_ptr->dam > 200) ? 200 : em_ptr->dam;
598 }
599
600 /*!
601  * @brief 写真を撮った時の処理
602  * @param player_ptr プレイヤーへの参照ポインタ
603  * @param em_ptr モンスター効果構造体への参照ポインタ
604  * @details 写真のフラッシュは弱閃光属性
605  */
606 static void postprocess_by_taking_photo(PlayerType *player_ptr, effect_monster_type *em_ptr)
607 {
608     if (em_ptr->photo == 0)
609         return;
610
611     ObjectType *q_ptr;
612     ObjectType forge;
613     q_ptr = &forge;
614     q_ptr->prep(lookup_kind(ItemKindType::STATUE, SV_PHOTO));
615     q_ptr->pval = em_ptr->photo;
616     q_ptr->ident |= (IDENT_FULL_KNOWN);
617     (void)drop_near(player_ptr, q_ptr, -1, player_ptr->y, player_ptr->x);
618 }
619
620 /*!
621  * @brief モンスター効果の後処理 (ペット関係、記念撮影、グローバル変数更新)
622  * @param player_ptr プレイヤーへの参照ポインタ
623  * @param em_ptr モンスター効果構造体への参照ポインタ
624  */
625 static void exe_affect_monster_postprocess(PlayerType *player_ptr, effect_monster_type *em_ptr)
626 {
627     postprocess_by_effected_pet(player_ptr, em_ptr);
628     postprocess_by_riding_pet_effected(player_ptr, em_ptr);
629     postprocess_by_taking_photo(player_ptr, em_ptr);
630     project_m_n++;
631     project_m_x = em_ptr->x;
632     project_m_y = em_ptr->y;
633 }
634
635 /*!
636  * @brief 汎用的なビーム/ボルト/ボール系によるモンスターへの効果処理 / Handle a beam/bolt/ball causing damage to a monster.
637  * @param player_ptr プレイヤーへの参照ポインタ
638  * @param who 魔法を発動したモンスター(0ならばプレイヤー) / Index of "source" monster (zero for "player")
639  * @param r 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion (0 = beam/bolt, 1 to 9 = ball)
640  * @param y 目標y座標 / Target y location (or location to travel "towards")
641  * @param x 目標x座標 / Target x location (or location to travel "towards")
642  * @param dam 基本威力 / Base damage roll to apply to affected monsters (or player)
643  * @param attribute 効果属性 / Type of damage to apply to monsters (and objects)
644  * @param flag 効果フラグ
645  * @param see_s_msg TRUEならばメッセージを表示する
646  * @return 何か一つでも効力があればTRUEを返す / TRUE if any "effects" of the projection were observed, else FALSE
647  * @details
648  * 以下の処理を行う。
649  * 1.魔法効果による効果に対する耐性による軽減計算及び効果の発動
650  * 2.魔法効果によるダメージの処理とダメージによる効果の発動
651  * 3.ペット及び撮影による事後効果
652  */
653 bool affect_monster(
654     PlayerType *player_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, AttributeType attribute, BIT_FLAGS flag, bool see_s_msg)
655 {
656     effect_monster_type tmp_effect;
657     effect_monster_type *em_ptr = initialize_effect_monster(player_ptr, &tmp_effect, who, r, y, x, dam, attribute, flag, see_s_msg);
658
659     make_description_of_affecred_monster(player_ptr, em_ptr);
660
661     if (player_ptr->riding && (em_ptr->g_ptr->m_idx == player_ptr->riding))
662         disturb(player_ptr, true, true);
663
664     process_result result = exe_affect_monster_by_effect(player_ptr, em_ptr);
665     if (result != PROCESS_CONTINUE)
666         return (bool)result;
667
668     if (em_ptr->skipped)
669         return false;
670
671     exe_affect_monster_by_damage(player_ptr, em_ptr);
672
673     update_phase_out_stat(player_ptr, em_ptr);
674     if (em_ptr->m_ptr->r_idx)
675         update_monster(player_ptr, em_ptr->g_ptr->m_idx, false);
676
677     lite_spot(player_ptr, em_ptr->y, em_ptr->x);
678     if ((player_ptr->monster_race_idx == em_ptr->m_ptr->r_idx) && (em_ptr->seen || !em_ptr->m_ptr->r_idx))
679         player_ptr->window_flags |= (PW_MONSTER);
680
681     exe_affect_monster_postprocess(player_ptr, em_ptr);
682     return em_ptr->obvious;
683 }