OSDN Git Service

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