2 * @brief 魔法によるモンスターへの効果まとめ
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 "effect/spells-effect-util.h"
18 #include "floor/cave.h"
19 #include "floor/floor-object.h"
20 #include "game-option/play-record-options.h"
21 #include "grid/grid.h"
22 #include "io/write-diary.h"
23 #include "main/sound-definitions-table.h"
24 #include "main/sound-of-music.h"
25 #include "monster-floor/monster-death.h"
26 #include "monster-floor/monster-move.h"
27 #include "monster-floor/monster-remover.h"
28 #include "monster-race/monster-race.h"
29 #include "monster-race/race-flags-resistance.h"
30 #include "monster-race/race-flags1.h"
31 #include "monster-race/race-flags3.h"
32 #include "monster-race/race-flags7.h"
33 #include "monster-race/race-indice-types.h"
34 #include "monster-race/race-resistance-mask.h"
35 #include "monster/monster-damage.h"
36 #include "monster/monster-describer.h"
37 #include "monster/monster-description-types.h"
38 #include "monster/monster-info.h"
39 #include "monster/monster-pain-describer.h"
40 #include "monster/monster-status-setter.h"
41 #include "monster/monster-status.h"
42 #include "monster/monster-update.h"
43 #include "object-enchant/special-object-flags.h"
44 #include "object/object-kind-hook.h"
45 #include "spell-kind/blood-curse.h"
46 #include "spell-kind/spells-polymorph.h"
47 #include "spell-kind/spells-teleport.h"
48 #include "sv-definition/sv-other-types.h"
49 #include "system/baseitem-info.h"
50 #include "system/floor-type-definition.h"
51 #include "system/grid-type-definition.h"
52 #include "system/item-entity.h"
53 #include "system/monster-entity.h"
54 #include "system/monster-race-info.h"
55 #include "system/player-type-definition.h"
56 #include "util/bit-flags-calculator.h"
57 #include "util/string-processor.h"
58 #include "view/display-messages.h"
62 * @brief ビーム/ボルト/ボール系魔法によるモンスターへの効果があるかないかを判定する
63 * @param player_ptr プレイヤーへの参照ポインタ
64 * @param em_ptr モンスター効果構造体への参照ポインタ
65 * @return 効果が何もないならFALSE、何かあるならTRUE
67 static ProcessResult is_affective(PlayerType *player_ptr, effect_monster_type *em_ptr)
69 if (!em_ptr->g_ptr->m_idx) {
70 return ProcessResult::PROCESS_FALSE;
72 if (em_ptr->who && (em_ptr->g_ptr->m_idx == em_ptr->who)) {
73 return ProcessResult::PROCESS_FALSE;
75 if (sukekaku && ((em_ptr->m_ptr->r_idx == MonsterRaceId::SUKE) || (em_ptr->m_ptr->r_idx == MonsterRaceId::KAKU))) {
76 return ProcessResult::PROCESS_FALSE;
78 if (em_ptr->m_ptr->hp < 0) {
79 return ProcessResult::PROCESS_FALSE;
81 if (em_ptr->who || em_ptr->g_ptr->m_idx != player_ptr->riding) {
82 return ProcessResult::PROCESS_TRUE;
85 switch (em_ptr->attribute) {
86 case AttributeType::OLD_HEAL:
87 case AttributeType::OLD_SPEED:
88 case AttributeType::STAR_HEAL:
89 return ProcessResult::PROCESS_TRUE;
90 case AttributeType::OLD_SLOW:
91 case AttributeType::OLD_SLEEP:
92 case AttributeType::OLD_CLONE:
93 case AttributeType::OLD_CONF:
94 case AttributeType::OLD_POLY:
95 case AttributeType::GENOCIDE:
96 case AttributeType::E_GENOCIDE:
97 return ProcessResult::PROCESS_CONTINUE;
102 return ProcessResult::PROCESS_FALSE;
106 * @brief 魔法の効果やモンスター種別(MAKE/FEMALE/なし)に応じて表示するメッセージを変更する
107 * @param player_ptr プレイヤーへの参照ポインタ
108 * @param em_ptr モンスター効果構造体への参照ポインタ
110 static void make_description_of_affecred_monster(PlayerType *player_ptr, effect_monster_type *em_ptr)
112 em_ptr->dam = (em_ptr->dam + em_ptr->r) / (em_ptr->r + 1);
113 angband_strcpy(em_ptr->m_name, monster_desc(player_ptr, em_ptr->m_ptr, 0).data(), sizeof(em_ptr->m_name));
114 angband_strcpy(em_ptr->m_poss, monster_desc(player_ptr, em_ptr->m_ptr, MD_PRON_VISIBLE | MD_POSSESSIVE).data(), sizeof(em_ptr->m_poss));
118 * @brief モンスターへの効果属性による耐性及び効果を処理する( / Proccess affecting to monster by effect.
119 * @param player_ptr プレイヤーへの参照ポインタ
120 * @param em_ptr モンスター効果構造体への参照ポインタ
121 * @return 完全な耐性が発動したらCONTINUE、そうでないなら効果処理の結果
123 * 完全な耐性を持っていたら、一部属性を除いて影響は及ぼさない
124 * デバッグ属性、モンスター打撃、モンスター射撃であれば貫通する
126 static ProcessResult exe_affect_monster_by_effect(PlayerType *player_ptr, effect_monster_type *em_ptr, std::optional<CapturedMonsterType *> cap_mon_ptr)
128 const std::vector<AttributeType> effect_arrtibute = {
129 AttributeType::OLD_CLONE,
130 AttributeType::STAR_HEAL,
131 AttributeType::OLD_HEAL,
132 AttributeType::OLD_SPEED,
133 AttributeType::CAPTURE,
134 AttributeType::PHOTO,
136 const auto check = [em_ptr](const AttributeType attribute) {
137 return em_ptr->attribute == attribute;
140 ProcessResult result = is_affective(player_ptr, em_ptr);
141 if (result != ProcessResult::PROCESS_TRUE) {
142 if (result == ProcessResult::PROCESS_CONTINUE) {
143 em_ptr->note = _("には効果がなかった。", " is unaffected.");
149 bool do_effect = em_ptr->r_ptr->resistance_flags.has_not(MonsterResistanceType::RESIST_ALL);
150 do_effect |= std::any_of(effect_arrtibute.cbegin(), effect_arrtibute.cend(), check);
153 return switch_effects_monster(player_ptr, em_ptr, cap_mon_ptr);
156 bool ignore_res_all = (em_ptr->attribute == AttributeType::DEBUG);
157 ignore_res_all |= (em_ptr->attribute == AttributeType::MONSTER_MELEE);
158 ignore_res_all |= (em_ptr->attribute == AttributeType::MONSTER_SHOOT);
160 if (em_ptr->r_ptr->resistance_flags.has(MonsterResistanceType::RESIST_ALL) && ignore_res_all) {
161 return switch_effects_monster(player_ptr, em_ptr);
164 em_ptr->note = _("には完全な耐性がある!", " is immune.");
166 if (is_original_ap_and_seen(player_ptr, em_ptr->m_ptr)) {
167 em_ptr->r_ptr->r_resistance_flags.set(MonsterResistanceType::RESIST_ALL);
170 if (em_ptr->attribute == AttributeType::LITE_WEAK || em_ptr->attribute == AttributeType::KILL_WALL) {
171 em_ptr->skipped = true;
174 return ProcessResult::PROCESS_CONTINUE;
179 * @param player_ptr プレイヤーへの参照ポインタ
180 * @param em_ptr モンスター効果構造体への参照ポインタ
182 static void effect_damage_killed_pet(PlayerType *player_ptr, effect_monster_type *em_ptr)
184 bool sad = em_ptr->m_ptr->is_pet() && !(em_ptr->m_ptr->ml);
185 if (em_ptr->known && em_ptr->note) {
186 angband_strcpy(em_ptr->m_name, monster_desc(player_ptr, em_ptr->m_ptr, MD_TRUE_NAME).data(), sizeof(em_ptr->m_name));
187 if (em_ptr->see_s_msg) {
188 msg_format("%^s%s", em_ptr->m_name, em_ptr->note);
190 player_ptr->current_floor_ptr->monster_noise = true;
194 if (em_ptr->who > 0) {
195 monster_gain_exp(player_ptr, em_ptr->who, em_ptr->m_ptr->r_idx);
198 monster_death(player_ptr, em_ptr->g_ptr->m_idx, false, em_ptr->attribute);
199 delete_monster_idx(player_ptr, em_ptr->g_ptr->m_idx);
201 msg_print(_("少し悲しい気分がした。", "You feel sad for a moment."));
206 * @brief モンスターの睡眠を処理する
207 * @param player_ptr プレイヤーへの参照ポインタ
208 * @param em_ptr モンスター効果構造体への参照ポインタ
210 static void effect_damage_makes_sleep(PlayerType *player_ptr, effect_monster_type *em_ptr)
212 if (em_ptr->note && em_ptr->seen_msg) {
213 msg_format("%^s%s", em_ptr->m_name, em_ptr->note);
214 } else if (em_ptr->see_s_msg) {
215 const auto pain_message = MonsterPainDescriber(player_ptr, em_ptr->g_ptr->m_idx).describe(em_ptr->dam);
216 if (!pain_message.empty()) {
217 msg_print(pain_message);
220 player_ptr->current_floor_ptr->monster_noise = true;
223 if (em_ptr->do_sleep) {
224 (void)set_monster_csleep(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->do_sleep);
229 * @brief モンスターからモンスターへのダメージを処理する / Hurt the monster by damages another monster did.
230 * @param player_ptr プレイヤーへの参照ポインタ
231 * @param em_ptr モンスター効果構造体への参照ポインタ
232 * @return ダメージを処理しなかった(モンスターIDがプレイヤー自身)場合はFALSE、処理した(モンスターだった)場合TRUE
234 * モンスターIDがプレイヤー(0)の場合は処理しない。
236 static bool deal_effect_damage_from_monster(PlayerType *player_ptr, effect_monster_type *em_ptr)
238 if (em_ptr->who <= 0) {
242 if (player_ptr->health_who == em_ptr->g_ptr->m_idx) {
243 player_ptr->redraw |= (PR_HEALTH);
245 if (player_ptr->riding == em_ptr->g_ptr->m_idx) {
246 player_ptr->redraw |= (PR_UHEALTH);
249 (void)set_monster_csleep(player_ptr, em_ptr->g_ptr->m_idx, 0);
250 em_ptr->m_ptr->hp -= em_ptr->dam;
251 if (em_ptr->m_ptr->hp < 0) {
252 effect_damage_killed_pet(player_ptr, em_ptr);
254 effect_damage_makes_sleep(player_ptr, em_ptr);
262 * @param player_ptr プレイヤーへの参照ポインタ
263 * @param em_ptr モンスター効果構造体への参照ポインタ
264 * @return 大賞モンスターが不潔な病人だった場合はTRUE、それ以外はFALSE
266 static bool heal_leaper(PlayerType *player_ptr, effect_monster_type *em_ptr)
268 if (!em_ptr->heal_leper) {
272 if (em_ptr->seen_msg) {
273 msg_print(_("不潔な病人は病気が治った!", "The Mangy looking leper is healed!"));
276 if (record_named_pet && em_ptr->m_ptr->is_named_pet()) {
277 const auto m2_name = monster_desc(player_ptr, em_ptr->m_ptr, MD_INDEF_VISIBLE);
278 exe_write_diary(player_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_HEAL_LEPER, m2_name.data());
281 delete_monster_idx(player_ptr, em_ptr->g_ptr->m_idx);
286 * @brief プレイヤー起因の効果によるダメージを処理 / Deal damages from player and fear by them.
287 * @param player_ptr プレイヤーへの参照ポインタ
288 * @param em_ptr モンスター効果構造体への参照ポインタ
289 * @return モンスターが死んだらTRUE、生きていたらFALSE
291 * em_ptr->do_fearによる恐怖メッセージもここで表示。
293 static bool deal_effect_damage_from_player(PlayerType *player_ptr, effect_monster_type *em_ptr)
296 MonsterDamageProcessor mdp(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->dam, &fear, em_ptr->attribute);
297 if (mdp.mon_take_hit(em_ptr->note_dies)) {
301 if (em_ptr->do_sleep) {
302 anger_monster(player_ptr, em_ptr->m_ptr);
305 if (em_ptr->note && em_ptr->seen) {
306 msg_format(_("%s%s", "%^s%s"), em_ptr->m_name, em_ptr->note);
307 } else if (em_ptr->known && (em_ptr->dam || !em_ptr->do_fear)) {
308 const auto pain_message = MonsterPainDescriber(player_ptr, em_ptr->g_ptr->m_idx).describe(em_ptr->dam);
309 if (!pain_message.empty()) {
310 msg_print(pain_message);
314 if (((em_ptr->dam > 0) || em_ptr->get_angry) && !em_ptr->do_sleep) {
315 anger_monster(player_ptr, em_ptr->m_ptr);
318 if ((fear || em_ptr->do_fear) && em_ptr->seen) {
320 msg_format(_("%^sは恐怖して逃げ出した!", "%^s flees in terror!"), em_ptr->m_name);
327 * @brief モンスターに効果のダメージを与える / Deal effect damage to monster.
328 * @param player_ptr プレイヤーへの参照ポインタ
329 * @param em_ptr モンスター効果構造体への参照ポインタ
332 * 1.モンスターによる効果ダメージの処理
334 * 3.プレイヤーによる効果ダメージの処理
337 static void deal_effect_damage_to_monster(PlayerType *player_ptr, effect_monster_type *em_ptr)
339 if (em_ptr->attribute == AttributeType::DRAIN_MANA) {
344 if (deal_effect_damage_from_monster(player_ptr, em_ptr)) {
349 if (heal_leaper(player_ptr, em_ptr)) {
352 if (deal_effect_damage_from_player(player_ptr, em_ptr)) {
356 if (em_ptr->do_sleep) {
357 (void)set_monster_csleep(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->do_sleep);
362 * @brief プレイヤーが眠っている敵に効果を及ぼした場合の徳の変化
363 * @param player_ptr プレイヤーへの参照ポインタ
364 * @param em_ptr モンスター効果構造体への参照ポインタ
366 static void effect_makes_change_virtues(PlayerType *player_ptr, effect_monster_type *em_ptr)
368 if ((em_ptr->who > 0) || !em_ptr->slept) {
372 if (em_ptr->r_ptr->kind_flags.has_not(MonsterKindType::EVIL) || one_in_(5)) {
373 chg_virtue(player_ptr, V_COMPASSION, -1);
375 if (em_ptr->r_ptr->kind_flags.has_not(MonsterKindType::EVIL) || one_in_(5)) {
376 chg_virtue(player_ptr, V_HONOUR, -1);
381 * @brief 魔法効果に対する強制処理(変身の強制解除、死なない処理)
382 * @param player_ptr プレイヤーへの参照ポインタ
383 * @param em_ptr モンスター効果構造体への参照ポインタ
385 static void affected_monster_prevents_bad_status(PlayerType *player_ptr, effect_monster_type *em_ptr)
387 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))) {
388 em_ptr->do_polymorph = false;
391 if ((em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE) || any_bits(em_ptr->r_ptr->flags1, RF1_QUESTOR) || (em_ptr->r_ptr->population_flags.has(MonsterPopulationType::NAZGUL))) && !player_ptr->phase_out && (em_ptr->who > 0) && (em_ptr->dam > em_ptr->m_ptr->hp)) {
392 em_ptr->dam = em_ptr->m_ptr->hp;
397 * @brief モンスターの朦朧値を蓄積させる
398 * @param player_ptr プレイヤーへの参照ポインタ
399 * @param em_ptr モンスター効果構造体への参照ポインタ
400 * @param stun_damage 朦朧値
402 static void effect_damage_piles_stun(PlayerType *player_ptr, effect_monster_type *em_ptr)
404 if ((em_ptr->do_stun == 0) || em_ptr->r_ptr->resistance_flags.has_any_of({ MonsterResistanceType::RESIST_SOUND, MonsterResistanceType::RESIST_FORCE }) || (em_ptr->r_ptr->flags3 & RF3_NO_STUN)) {
409 em_ptr->obvious = true;
413 if (em_ptr->m_ptr->get_remaining_stun()) {
414 em_ptr->note = _("はひどくもうろうとした。", " is more dazed.");
415 turns = em_ptr->m_ptr->get_remaining_stun() + (em_ptr->do_stun / 2);
417 em_ptr->note = _("はもうろうとした。", " is dazed.");
418 turns = em_ptr->do_stun;
421 (void)set_monster_stunned(player_ptr, em_ptr->g_ptr->m_idx, turns);
422 em_ptr->get_angry = true;
426 * @brief モンスターの混乱値を蓄積させる
427 * @param player_ptr プレイヤーへの参照ポインタ
428 * @param em_ptr モンスター効果構造体への参照ポインタ
429 * @param stun_damage 混乱値
431 static void effect_damage_piles_confusion(PlayerType *player_ptr, effect_monster_type *em_ptr)
433 if ((em_ptr->do_conf == 0) || (em_ptr->r_ptr->flags3 & RF3_NO_CONF) || em_ptr->r_ptr->resistance_flags.has_any_of(RFR_EFF_RESIST_CHAOS_MASK)) {
438 em_ptr->obvious = true;
442 if (em_ptr->m_ptr->is_confused()) {
443 em_ptr->note = _("はさらに混乱したようだ。", " looks more confused.");
444 turns = em_ptr->m_ptr->get_remaining_confusion() + (em_ptr->do_conf / 2);
446 em_ptr->note = _("は混乱したようだ。", " looks confused.");
447 turns = em_ptr->do_conf;
450 (void)set_monster_confused(player_ptr, em_ptr->g_ptr->m_idx, turns);
451 em_ptr->get_angry = true;
455 * @brief モンスターの恐怖値を蓄積させる
456 * @param player_ptr プレイヤーへの参照ポインタ
457 * @param em_ptr モンスター効果構造体への参照ポインタ
458 * @param stun_damage 恐怖値
460 * 打撃ダメージによる恐怖もあるため、メッセージは後で表示。
462 static void effect_damage_piles_fear(PlayerType *player_ptr, effect_monster_type *em_ptr)
464 if (em_ptr->do_fear == 0 || any_bits(em_ptr->r_ptr->flags3, RF3_NO_FEAR)) {
468 (void)set_monster_monfear(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->m_ptr->get_remaining_fear() + em_ptr->do_fear);
469 em_ptr->get_angry = true;
474 * @param em_ptr モンスター効果構造体への参照ポインタ
476 static void effect_damage_makes_weak(effect_monster_type *em_ptr)
478 if (em_ptr->do_time == 0) {
483 em_ptr->obvious = true;
486 if (em_ptr->do_time >= em_ptr->m_ptr->maxhp) {
487 em_ptr->do_time = em_ptr->m_ptr->maxhp - 1;
490 if (em_ptr->do_time) {
491 em_ptr->note = _("は弱くなったようだ。", " seems weakened.");
492 em_ptr->m_ptr->maxhp -= em_ptr->do_time;
493 if ((em_ptr->m_ptr->hp - em_ptr->dam) > em_ptr->m_ptr->maxhp) {
494 em_ptr->dam = em_ptr->m_ptr->hp - em_ptr->m_ptr->maxhp;
498 em_ptr->get_angry = true;
503 * @param player_ptr プレイヤーへの参照ポインタ
504 * @param em_ptr モンスター効果構造体への参照ポインタ
506 static void effect_damage_makes_polymorph(PlayerType *player_ptr, effect_monster_type *em_ptr)
508 if (!em_ptr->do_polymorph || (randint1(90) <= em_ptr->r_ptr->level)) {
512 if (polymorph_monster(player_ptr, em_ptr->y, em_ptr->x)) {
514 em_ptr->obvious = true;
517 em_ptr->note = _("が変身した!", " changes!");
521 em_ptr->m_ptr = &player_ptr->current_floor_ptr->m_list[em_ptr->g_ptr->m_idx];
522 em_ptr->r_ptr = &monraces_info[em_ptr->m_ptr->r_idx];
526 * @brief モンスターをテレポートさせる
527 * @param player_ptr プレイヤーへの参照ポインタ
528 * @param em_ptr モンスター効果構造体への参照ポインタ
530 static void effect_damage_makes_teleport(PlayerType *player_ptr, effect_monster_type *em_ptr)
532 if (em_ptr->do_dist == 0) {
537 em_ptr->obvious = true;
540 em_ptr->note = _("が消え去った!", " disappears!");
543 chg_virtue(player_ptr, V_VALOUR, -1);
546 teleport_flags tflag = i2enum<teleport_flags>((!em_ptr->who ? TELEPORT_DEC_VALOUR : TELEPORT_SPONTANEOUS) | TELEPORT_PASSIVE);
547 teleport_away(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->do_dist, tflag);
549 em_ptr->y = em_ptr->m_ptr->fy;
550 em_ptr->x = em_ptr->m_ptr->fx;
551 em_ptr->g_ptr = &player_ptr->current_floor_ptr->grid_array[em_ptr->y][em_ptr->x];
555 * @brief モンスターへのダメージに応じたメッセージを表示させ、異常状態を与える
556 * @param player_ptr プレイヤーへの参照ポインタ
557 * @param em_ptr モンスター効果構造体への参照ポインタ
560 * 1.全耐性または無敵でダメージが通らなかった場合
564 static void effect_damage_gives_bad_status(PlayerType *player_ptr, effect_monster_type *em_ptr)
566 int tmp_damage = em_ptr->dam;
567 em_ptr->dam = mon_damage_mod(player_ptr, em_ptr->m_ptr, em_ptr->dam, (bool)(em_ptr->attribute == AttributeType::PSY_SPEAR));
568 if ((tmp_damage > 0) && (em_ptr->dam == 0) && em_ptr->seen) {
569 em_ptr->note = _("はダメージを受けていない。", " is unharmed.");
572 if (em_ptr->dam > em_ptr->m_ptr->hp) {
573 em_ptr->note = em_ptr->note_dies;
575 effect_damage_piles_stun(player_ptr, em_ptr);
576 effect_damage_piles_confusion(player_ptr, em_ptr);
577 effect_damage_piles_fear(player_ptr, em_ptr);
578 effect_damage_makes_weak(em_ptr);
579 effect_damage_makes_polymorph(player_ptr, em_ptr);
580 effect_damage_makes_teleport(player_ptr, em_ptr);
585 * @brief 効果によるモンスターへのダメージと付随効果を処理する
586 * @param player_ptr プレイヤーへの参照ポインタ
587 * @param em_ptr モンスター効果構造体への参照ポインタ
591 * 2.完全な耐性及び無敵によるダメージのカット
592 * 3.ダメージによる付随効果の処理(混乱/朦朧/恐怖/衰弱/変身/テレポート)
596 static void exe_affect_monster_by_damage(PlayerType *player_ptr, effect_monster_type *em_ptr)
598 effect_makes_change_virtues(player_ptr, em_ptr);
599 affected_monster_prevents_bad_status(player_ptr, em_ptr);
600 effect_damage_gives_bad_status(player_ptr, em_ptr);
601 deal_effect_damage_to_monster(player_ptr, em_ptr);
602 if ((em_ptr->attribute == AttributeType::BLOOD_CURSE) && one_in_(4)) {
603 blood_curse_to_enemy(player_ptr, em_ptr->who);
608 * @brief モンスター闘技場にいる場合の画面更新処理
609 * @param player_ptr プレイヤーへの参照ポインタ
610 * @param em_ptr モンスター効果構造体への参照ポインタ
612 static void update_phase_out_stat(PlayerType *player_ptr, effect_monster_type *em_ptr)
614 if (!player_ptr->phase_out) {
618 player_ptr->health_who = em_ptr->g_ptr->m_idx;
619 player_ptr->redraw |= (PR_HEALTH);
620 handle_stuff(player_ptr);
624 * @brief 魔法効果がペットに及んだ時の処理
625 * @param player_ptr プレイヤーへの参照ポインタ
626 * @param em_ptr モンスター効果構造体への参照ポインタ
628 static void postprocess_by_effected_pet(PlayerType *player_ptr, effect_monster_type *em_ptr)
630 auto *m_ptr = em_ptr->m_ptr;
631 if ((em_ptr->dam <= 0) || m_ptr->is_pet() || m_ptr->is_friendly()) {
635 if (em_ptr->who == 0) {
636 if (!(em_ptr->flag & PROJECT_NO_HANGEKI)) {
637 set_target(m_ptr, monster_target_y, monster_target_x);
643 const auto &m_caster_ref = *em_ptr->m_caster_ptr;
644 if ((em_ptr->who > 0) && m_caster_ref.is_pet() && !player_bold(player_ptr, m_ptr->target_y, m_ptr->target_x)) {
645 set_target(m_ptr, m_caster_ref.fy, m_caster_ref.fx);
650 * @brief 魔法効果が騎乗モンスターに及んだ時の処理
651 * @param player_ptr プレイヤーへの参照ポインタ
652 * @param em_ptr モンスター効果構造体への参照ポインタ
654 static void postprocess_by_riding_pet_effected(PlayerType *player_ptr, effect_monster_type *em_ptr)
656 if (!player_ptr->riding || (player_ptr->riding != em_ptr->g_ptr->m_idx) || (em_ptr->dam <= 0)) {
660 if (em_ptr->m_ptr->hp > (em_ptr->m_ptr->maxhp / 3)) {
661 em_ptr->dam = (em_ptr->dam + 1) / 2;
664 rakubadam_m = (em_ptr->dam > 200) ? 200 : em_ptr->dam;
669 * @param player_ptr プレイヤーへの参照ポインタ
670 * @param em_ptr モンスター効果構造体への参照ポインタ
671 * @details 写真のフラッシュは弱閃光属性
673 static void postprocess_by_taking_photo(PlayerType *player_ptr, effect_monster_type *em_ptr)
675 if (em_ptr->photo == 0) {
682 q_ptr->prep(lookup_baseitem_id({ ItemKindType::STATUE, SV_PHOTO }));
683 q_ptr->pval = em_ptr->photo;
684 q_ptr->ident |= (IDENT_FULL_KNOWN);
685 (void)drop_near(player_ptr, q_ptr, -1, player_ptr->y, player_ptr->x);
689 * @brief モンスター効果の後処理 (ペット関係、記念撮影、グローバル変数更新)
690 * @param player_ptr プレイヤーへの参照ポインタ
691 * @param em_ptr モンスター効果構造体への参照ポインタ
693 static void exe_affect_monster_postprocess(PlayerType *player_ptr, effect_monster_type *em_ptr)
695 postprocess_by_effected_pet(player_ptr, em_ptr);
696 postprocess_by_riding_pet_effected(player_ptr, em_ptr);
697 postprocess_by_taking_photo(player_ptr, em_ptr);
699 project_m_x = em_ptr->x;
700 project_m_y = em_ptr->y;
704 * @brief 汎用的なビーム/ボルト/ボール系によるモンスターへの効果処理 / Handle a beam/bolt/ball causing damage to a monster.
705 * @param player_ptr プレイヤーへの参照ポインタ
706 * @param who 魔法を発動したモンスター(0ならばプレイヤー) / Index of "source" monster (zero for "player")
707 * @param r 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion (0 = beam/bolt, 1 to 9 = ball)
708 * @param y 目標y座標 / Target y location (or location to travel "towards")
709 * @param x 目標x座標 / Target x location (or location to travel "towards")
710 * @param dam 基本威力 / Base damage roll to apply to affected monsters (or player)
711 * @param attribute 効果属性 / Type of damage to apply to monsters (and objects)
713 * @param see_s_msg TRUEならばメッセージを表示する
714 * @return 何か一つでも効力があればTRUEを返す / TRUE if any "effects" of the projection were observed, else FALSE
717 * 1.魔法効果による効果に対する耐性による軽減計算及び効果の発動
718 * 2.魔法効果によるダメージの処理とダメージによる効果の発動
722 PlayerType *player_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, int dam, AttributeType attribute, BIT_FLAGS flag, bool see_s_msg, std::optional<CapturedMonsterType *> cap_mon_ptr)
724 effect_monster_type tmp_effect;
725 effect_monster_type *em_ptr = initialize_effect_monster(player_ptr, &tmp_effect, who, r, y, x, dam, attribute, flag, see_s_msg);
727 make_description_of_affecred_monster(player_ptr, em_ptr);
729 if (player_ptr->riding && (em_ptr->g_ptr->m_idx == player_ptr->riding)) {
730 disturb(player_ptr, true, true);
733 ProcessResult result = exe_affect_monster_by_effect(player_ptr, em_ptr, cap_mon_ptr);
734 if (result != ProcessResult::PROCESS_CONTINUE) {
735 return result == ProcessResult::PROCESS_TRUE;
738 if (em_ptr->skipped) {
742 exe_affect_monster_by_damage(player_ptr, em_ptr);
744 update_phase_out_stat(player_ptr, em_ptr);
745 const auto monster_is_valid = MonsterRace(em_ptr->m_ptr->r_idx).is_valid();
746 if (monster_is_valid) {
747 update_monster(player_ptr, em_ptr->g_ptr->m_idx, false);
750 lite_spot(player_ptr, em_ptr->y, em_ptr->x);
751 if ((player_ptr->monster_race_idx == em_ptr->m_ptr->r_idx) && (em_ptr->seen || !monster_is_valid)) {
752 player_ptr->window_flags |= (PW_MONSTER);
755 exe_affect_monster_postprocess(player_ptr, em_ptr);
756 return em_ptr->obvious;