OSDN Git Service

561c3fee26eca048809c4c472ca1f165b782d024
[hengband/hengband.git] / src / effect / effect-monster.c
1 /*!
2  * @brief 魔法によるモンスターへの効果まとめ
3  * @date 2020/04/29
4  * @author Hourier
5  */
6
7 #include "effect/effect-monster.h"
8 #include "core/stuff-handler.h"
9 #include "effect/effect-characteristics.h"
10 #include "effect/effect-monster-switcher.h"
11 #include "floor/floor-object.h"
12 #include "io/write-diary.h"
13 #include "main/sound-definitions-table.h"
14 #include "monster/monster-status.h"
15 #include "object-enchant/special-object-flags.h"
16 #include "object/object-generator.h"
17 #include "object/object-kind-hook.h"
18 #include "player/avatar.h"
19 #include "player/player-move.h"
20 #include "spell/spells-teleport.h"
21 #include "spell/spells-type.h"
22 #include "spell/spells3.h"
23 #include "spells-effect-util.h"
24 #include "sv-definition/sv-other-types.h"
25
26 /*!
27  * @brief ビーム/ボルト/ボール系魔法によるモンスターへの効果があるかないかを判定する
28  * @param caster_ptr プレーヤーへの参照ポインタ
29  * @param em_ptr モンスター効果構造体への参照ポインタ
30  * @return 効果が何もないならFALSE、何かあるならTRUE
31  */
32 static bool is_never_effect(player_type *caster_ptr, effect_monster_type *em_ptr)
33 {
34         if (!em_ptr->g_ptr->m_idx) return FALSE;
35         if (em_ptr->who && (em_ptr->g_ptr->m_idx == em_ptr->who)) return FALSE;
36         if ((em_ptr->g_ptr->m_idx == caster_ptr->riding) &&
37                 !em_ptr->who &&
38                 !(em_ptr->effect_type == GF_OLD_HEAL) &&
39                 !(em_ptr->effect_type == GF_OLD_SPEED) &&
40                 !(em_ptr->effect_type == GF_STAR_HEAL))
41                 return FALSE;
42         if (sukekaku && ((em_ptr->m_ptr->r_idx == MON_SUKE) || (em_ptr->m_ptr->r_idx == MON_KAKU))) return FALSE;
43         if (em_ptr->m_ptr->hp < 0) return FALSE;
44
45         return TRUE;
46 }
47
48
49 /*!
50  * @brief 魔法の効果やモンスター種別(MAKE/FEMALE/なし)に応じて表示するメッセージを変更する
51  * @param caster_ptr プレーヤーへの参照ポインタ
52  * @param em_ptr モンスター効果構造体への参照ポインタ
53  * @return なし
54  */
55 static void decide_spell_result_description(player_type *caster_ptr, effect_monster_type *em_ptr)
56 {
57         em_ptr->dam = (em_ptr->dam + em_ptr->r) / (em_ptr->r + 1);
58         monster_desc(caster_ptr, em_ptr->m_name, em_ptr->m_ptr, 0);
59         monster_desc(caster_ptr, em_ptr->m_poss, em_ptr->m_ptr, MD_PRON_VISIBLE | MD_POSSESSIVE);
60         if (caster_ptr->riding && (em_ptr->g_ptr->m_idx == caster_ptr->riding))
61                 disturb(caster_ptr, TRUE, TRUE);
62 }
63
64
65 /*!
66  * @brief 完全な耐性を持っていたら、モンスターへの効果処理をスキップする
67  * @param caster_ptr プレーヤーへの参照ポインタ
68  * @param em_ptr モンスター効果構造体への参照ポインタ
69  * @return 完全耐性ならCONTINUE、そうでないなら効果処理の結果
70  */
71 static gf_switch_result process_monster_perfect_resistance(player_type *caster_ptr, effect_monster_type *em_ptr)
72 {
73         if (((em_ptr->r_ptr->flagsr & RFR_RES_ALL) == 0) ||
74                 em_ptr->effect_type == GF_OLD_CLONE ||
75                 em_ptr->effect_type == GF_STAR_HEAL ||
76                 em_ptr->effect_type == GF_OLD_HEAL ||
77                 em_ptr->effect_type == GF_OLD_SPEED ||
78                 em_ptr->effect_type == GF_CAPTURE ||
79                 em_ptr->effect_type == GF_PHOTO)
80                 return switch_effects_monster(caster_ptr, em_ptr);
81
82         em_ptr->note = _("には完全な耐性がある!", " is immune.");
83         em_ptr->dam = 0;
84         if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr))
85                 em_ptr->r_ptr->r_flagsr |= (RFR_RES_ALL);
86
87         if (em_ptr->effect_type == GF_LITE_WEAK || em_ptr->effect_type == GF_KILL_WALL)
88                 em_ptr->skipped = TRUE;
89
90         return GF_SWITCH_CONTINUE;
91 }
92
93
94 /*!
95  * @brief ペットの死亡を処理する
96  * @param caster_ptr プレーヤーへの参照ポインタ
97  * @param em_ptr モンスター効果構造体への参照ポインタ
98  * @return なし
99  */
100 static void process_pet_death(player_type *caster_ptr, effect_monster_type *em_ptr)
101 {
102         bool sad = is_pet(em_ptr->m_ptr) && !(em_ptr->m_ptr->ml);
103         if (em_ptr->known && em_ptr->note)
104         {
105                 monster_desc(caster_ptr, em_ptr->m_name, em_ptr->m_ptr, MD_TRUE_NAME);
106                 if (em_ptr->see_s_msg) msg_format("%^s%s", em_ptr->m_name, em_ptr->note);
107                 else caster_ptr->current_floor_ptr->monster_noise = TRUE;
108         }
109
110         if (em_ptr->who > 0) monster_gain_exp(caster_ptr, em_ptr->who, em_ptr->m_ptr->r_idx);
111
112         monster_death(caster_ptr, em_ptr->g_ptr->m_idx, FALSE);
113         delete_monster_idx(caster_ptr, em_ptr->g_ptr->m_idx);
114         if (sad) msg_print(_("少し悲しい気分がした。", "You feel sad for a moment."));
115 }
116
117
118 /*!
119  * @brief モンスターの睡眠を処理する
120  * @param caster_ptr プレーヤーへの参照ポインタ
121  * @param em_ptr モンスター効果構造体への参照ポインタ
122  * @return なし
123  */
124 static void process_monster_sleep(player_type *caster_ptr, effect_monster_type *em_ptr)
125 {
126         if (em_ptr->note && em_ptr->seen_msg)
127                 msg_format("%^s%s", em_ptr->m_name, em_ptr->note);
128         else if (em_ptr->see_s_msg)
129                 message_pain(caster_ptr, em_ptr->g_ptr->m_idx, em_ptr->dam);
130         else
131                 caster_ptr->current_floor_ptr->monster_noise = TRUE;
132
133         if (em_ptr->do_sleep) (void)set_monster_csleep(caster_ptr, em_ptr->g_ptr->m_idx, em_ptr->do_sleep);
134 }
135
136
137 /*!
138  * @brief モンスターの被ダメージを処理する / If another monster did the damage, hurt the monster by hand
139  * @param caster_ptr プレーヤーへの参照ポインタ
140  * @param em_ptr モンスター効果構造体への参照ポインタ
141  * @return モンスターIDがプレーヤー自身だった場合FALSE、モンスターだった場合TRUE
142  */
143 static bool process_monster_damage(player_type *caster_ptr, effect_monster_type *em_ptr)
144 {
145         if (em_ptr->who <= 0) return FALSE;
146
147         if (caster_ptr->health_who == em_ptr->g_ptr->m_idx) caster_ptr->redraw |= (PR_HEALTH);
148         if (caster_ptr->riding == em_ptr->g_ptr->m_idx) caster_ptr->redraw |= (PR_UHEALTH);
149
150         (void)set_monster_csleep(caster_ptr, em_ptr->g_ptr->m_idx, 0);
151         em_ptr->m_ptr->hp -= em_ptr->dam;
152         if (em_ptr->m_ptr->hp < 0) process_pet_death(caster_ptr, em_ptr);
153         else process_monster_sleep(caster_ptr, em_ptr);
154
155         return TRUE;
156 }
157
158
159 /*!
160  * @brief 不潔な病人の治療処理
161  * @param caster_ptr プレーヤーへの参照ポインタ
162  * @param em_ptr モンスター効果構造体への参照ポインタ
163  * @return 大賞モンスターが不潔な病人だった場合はTRUE、それ以外はFALSE
164  */
165 static bool heal_leaper(player_type *caster_ptr, effect_monster_type *em_ptr)
166 {
167         if (!em_ptr->heal_leper) return FALSE;
168
169         if (em_ptr->seen_msg)
170                 msg_print(_("不潔な病人は病気が治った!", "The Mangy looking leper is healed!"));
171
172         if (record_named_pet && is_pet(em_ptr->m_ptr) && em_ptr->m_ptr->nickname)
173         {
174                 char m2_name[MAX_NLEN];
175                 monster_desc(caster_ptr, m2_name, em_ptr->m_ptr, MD_INDEF_VISIBLE);
176                 exe_write_diary(caster_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_HEAL_LEPER, m2_name);
177         }
178
179         delete_monster_idx(caster_ptr, em_ptr->g_ptr->m_idx);
180         return TRUE;
181 }
182
183
184 /*!
185  * @brief モンスターの恐慌処理 / If the player did it, give him experience, check fear
186  * @param caster_ptr プレーヤーへの参照ポインタ
187  * @param em_ptr モンスター効果構造体への参照ポインタ
188  * @return モンスターが死んだらTRUE、生きていたらFALSE
189  */
190 static bool process_monster_fear(player_type *caster_ptr, effect_monster_type *em_ptr)
191 {
192         bool fear = FALSE;
193         if (mon_take_hit(caster_ptr, em_ptr->g_ptr->m_idx, em_ptr->dam, &fear, em_ptr->note_dies))
194                 return TRUE;
195
196         if (em_ptr->do_sleep)
197                 anger_monster(caster_ptr, em_ptr->m_ptr);
198
199         if (em_ptr->note && em_ptr->seen_msg)
200                 msg_format(_("%s%s", "%^s%s"), em_ptr->m_name, em_ptr->note);
201         else if (em_ptr->known && (em_ptr->dam || !em_ptr->do_fear))
202                 message_pain(caster_ptr, em_ptr->g_ptr->m_idx, em_ptr->dam);
203
204         if (((em_ptr->dam > 0) || em_ptr->get_angry) && !em_ptr->do_sleep)
205                 anger_monster(caster_ptr, em_ptr->m_ptr);
206
207         if ((fear || em_ptr->do_fear) && em_ptr->seen)
208         {
209                 sound(SOUND_FLEE);
210                 msg_format(_("%^sは恐怖して逃げ出した!", "%^s flees in terror!"), em_ptr->m_name);
211         }
212
213         return FALSE;
214 }
215
216
217 /*!
218  * todo 睡眠処理があるので、死に際とは言えない。適切な関数名に要修正
219  * @brief モンスターの死に際処理 (魔力吸収を除く)
220  * @param caster_ptr プレーヤーへの参照ポインタ
221  * @param em_ptr モンスター効果構造体への参照ポインタ
222  * @return なし
223  */
224 static void process_monster_last_moment(player_type *caster_ptr, effect_monster_type *em_ptr)
225 {
226         if (em_ptr->effect_type == GF_DRAIN_MANA) return;
227
228         if (process_monster_damage(caster_ptr, em_ptr)) return;
229         if (heal_leaper(caster_ptr, em_ptr)) return;
230         if (process_monster_fear(caster_ptr, em_ptr)) return;
231
232         if (em_ptr->do_sleep) (void)set_monster_csleep(caster_ptr, em_ptr->g_ptr->m_idx, em_ptr->do_sleep);
233 }
234
235
236 /*!
237  * @brief 魔法の効果による汎用処理 (変身の有無、現在HPの減算、徳の変化)
238  * @param caster_ptr プレーヤーへの参照ポインタ
239  * @param em_ptr モンスター効果構造体への参照ポインタ
240  * @return なし
241  */
242 static void process_spell_result(player_type *caster_ptr, effect_monster_type *em_ptr)
243 {
244         if ((em_ptr->r_ptr->flags1 & RF1_UNIQUE) ||
245                 (em_ptr->r_ptr->flags1 & RF1_QUESTOR) ||
246                 (caster_ptr->riding && (em_ptr->g_ptr->m_idx == caster_ptr->riding)))
247                 em_ptr->do_polymorph = FALSE;
248
249         if (((em_ptr->r_ptr->flags1 & (RF1_UNIQUE | RF1_QUESTOR)) || (em_ptr->r_ptr->flags7 & RF7_NAZGUL)) &&
250                 !caster_ptr->phase_out &&
251                 (em_ptr->who > 0) &&
252                 (em_ptr->dam > em_ptr->m_ptr->hp))
253                 em_ptr->dam = em_ptr->m_ptr->hp;
254
255         if ((em_ptr->who > 0) || !em_ptr->slept) return;
256
257         if (!(em_ptr->r_ptr->flags3 & RF3_EVIL) || one_in_(5)) chg_virtue(caster_ptr, V_COMPASSION, -1);
258         if (!(em_ptr->r_ptr->flags3 & RF3_EVIL) || one_in_(5)) chg_virtue(caster_ptr, V_HONOUR, -1);
259 }
260
261
262 /*!
263  * @brief モンスターの朦朧値を蓄積させる
264  * @param caster_ptr プレーヤーへの参照ポインタ
265  * @param em_ptr モンスター効果構造体への参照ポインタ
266  * @param stun_damage 朦朧値
267  * @return なし
268  */
269 static void pile_monster_stun(player_type *caster_ptr, effect_monster_type *em_ptr, int *stun_damage)
270 {
271         if ((em_ptr->do_stun == 0) ||
272                 (em_ptr->r_ptr->flagsr & (RFR_RES_SOUN | RFR_RES_WALL)) ||
273                 (em_ptr->r_ptr->flags3 & RF3_NO_STUN))
274                 return;
275
276         if (em_ptr->seen) em_ptr->obvious = TRUE;
277
278         if (MON_STUNNED(em_ptr->m_ptr))
279         {
280                 em_ptr->note = _("はひどくもうろうとした。", " is more dazed.");
281                 *stun_damage = MON_STUNNED(em_ptr->m_ptr) + (em_ptr->do_stun / 2);
282         }
283         else
284         {
285                 em_ptr->note = _("はもうろうとした。", " is dazed.");
286                 *stun_damage = em_ptr->do_stun;
287         }
288
289         (void)set_monster_stunned(caster_ptr, em_ptr->g_ptr->m_idx, *stun_damage);
290         em_ptr->get_angry = TRUE;
291 }
292
293
294 /*!
295  * @brief モンスターの混乱値を蓄積させる
296  * @param caster_ptr プレーヤーへの参照ポインタ
297  * @param em_ptr モンスター効果構造体への参照ポインタ
298  * @param stun_damage 混乱値
299  * @return なし
300  */
301 static void pile_monster_conf(player_type *caster_ptr, effect_monster_type *em_ptr, int *conf_damage)
302 {
303         if ((em_ptr->do_conf == 0) ||
304                 (em_ptr->r_ptr->flags3 & RF3_NO_CONF) ||
305                 (em_ptr->r_ptr->flagsr & RFR_EFF_RES_CHAO_MASK))
306                 return;
307
308         if (em_ptr->seen) em_ptr->obvious = TRUE;
309
310         if (MON_CONFUSED(em_ptr->m_ptr))
311         {
312                 em_ptr->note = _("はさらに混乱したようだ。", " looks more confused.");
313                 *conf_damage = MON_CONFUSED(em_ptr->m_ptr) + (em_ptr->do_conf / 2);
314         }
315         else
316         {
317                 em_ptr->note = _("は混乱したようだ。", " looks confused.");
318                 *conf_damage = em_ptr->do_conf;
319         }
320
321         (void)set_monster_confused(caster_ptr, em_ptr->g_ptr->m_idx, *conf_damage);
322         em_ptr->get_angry = TRUE;
323 }
324
325
326 /*!
327  * @brief モンスターを衰弱させる
328  * @param em_ptr モンスター効果構造体への参照ポインタ
329  * @return なし
330  */
331 static void process_monster_weakening(effect_monster_type *em_ptr)
332 {
333         if (em_ptr->do_time == 0) return;
334
335         if (em_ptr->seen) em_ptr->obvious = TRUE;
336
337         if (em_ptr->do_time >= em_ptr->m_ptr->maxhp) em_ptr->do_time = em_ptr->m_ptr->maxhp - 1;
338
339         if (em_ptr->do_time)
340         {
341                 em_ptr->note = _("は弱くなったようだ。", " seems weakened.");
342                 em_ptr->m_ptr->maxhp -= em_ptr->do_time;
343                 if ((em_ptr->m_ptr->hp - em_ptr->dam) > em_ptr->m_ptr->maxhp) em_ptr->dam = em_ptr->m_ptr->hp - em_ptr->m_ptr->maxhp;
344         }
345
346         em_ptr->get_angry = TRUE;
347 }
348
349
350 /*!
351  * @brief モンスターを変身させる
352  * @param caster_ptr プレーヤーへの参照ポインタ
353  * @param em_ptr モンスター効果構造体への参照ポインタ
354  * @return なし
355  */
356 static void process_monster_polymorph(player_type *caster_ptr, effect_monster_type *em_ptr)
357 {
358         if (!em_ptr->do_polymorph || (randint1(90) <= em_ptr->r_ptr->level))
359                 return;
360
361         if (polymorph_monster(caster_ptr, em_ptr->y, em_ptr->x))
362         {
363                 if (em_ptr->seen) em_ptr->obvious = TRUE;
364
365                 em_ptr->note = _("が変身した!", " changes!");
366                 em_ptr->dam = 0;
367         }
368
369         em_ptr->m_ptr = &caster_ptr->current_floor_ptr->m_list[em_ptr->g_ptr->m_idx];
370         em_ptr->r_ptr = &r_info[em_ptr->m_ptr->r_idx];
371 }
372
373
374 /*!
375  * @brief モンスターをテレポートさせる
376  * @param caster_ptr プレーヤーへの参照ポインタ
377  * @param em_ptr モンスター効果構造体への参照ポインタ
378  * @return なし
379  */
380 static void process_monster_teleport(player_type *caster_ptr, effect_monster_type *em_ptr)
381 {
382         if (em_ptr->do_dist == 0) return;
383
384         if (em_ptr->seen) em_ptr->obvious = TRUE;
385
386         em_ptr->note = _("が消え去った!", " disappears!");
387
388         if (!em_ptr->who) chg_virtue(caster_ptr, V_VALOUR, -1);
389
390         teleport_away(caster_ptr, em_ptr->g_ptr->m_idx, em_ptr->do_dist,
391                 (!em_ptr->who ? TELEPORT_DEC_VALOUR : 0L) | TELEPORT_PASSIVE);
392
393         em_ptr->y = em_ptr->m_ptr->fy;
394         em_ptr->x = em_ptr->m_ptr->fx;
395         em_ptr->g_ptr = &caster_ptr->current_floor_ptr->grid_array[em_ptr->y][em_ptr->x];
396 }
397
398
399 /*!
400  * @brief モンスターの異常状態を処理する
401  * @param caster_ptr プレーヤーへの参照ポインタ
402  * @param em_ptr モンスター効果構造体への参照ポインタ
403  * @parama tmp_damage 朦朧/混乱値
404  * @return なし
405  */
406 static void process_monster_bad_status(player_type *caster_ptr, effect_monster_type *em_ptr, int *tmp_damage)
407 {
408         pile_monster_stun(caster_ptr, em_ptr, tmp_damage);
409         pile_monster_conf(caster_ptr, em_ptr, tmp_damage);
410         process_monster_weakening(em_ptr);
411         process_monster_polymorph(caster_ptr, em_ptr);
412         process_monster_teleport(caster_ptr, em_ptr);
413         if (em_ptr->do_fear == 0) return;
414
415         (void)set_monster_monfear(caster_ptr, em_ptr->g_ptr->m_idx, MON_MONFEAR(em_ptr->m_ptr) + em_ptr->do_fear);
416         em_ptr->get_angry = TRUE;
417 }
418
419
420 /*!
421  * @brief モンスターへのダメージに応じたメッセージを表示させ、異常状態を与える
422  * @param caster_ptr プレーヤーへの参照ポインタ
423  * @param em_ptr モンスター効果構造体への参照ポインタ
424  * @return なし
425  */
426 static void process_monster_bad_stat_damage(player_type *caster_ptr, effect_monster_type *em_ptr)
427 {
428         int tmp_damage = em_ptr->dam;
429         em_ptr->dam = mon_damage_mod(caster_ptr, em_ptr->m_ptr, em_ptr->dam, (bool)(em_ptr->effect_type == GF_PSY_SPEAR));
430         if ((tmp_damage > 0) && (em_ptr->dam == 0)) em_ptr->note = _("はダメージを受けていない。", " is unharmed.");
431
432         if (em_ptr->dam > em_ptr->m_ptr->hp)
433                 em_ptr->note = em_ptr->note_dies;
434         else
435                 process_monster_bad_status(caster_ptr, em_ptr, &tmp_damage);
436 }
437
438 /*!
439  * todo 関数名が微妙、もっと適切な関数名が欲しい
440  * @brief モンスターへの影響全般を処理する
441  * @param caster_ptr プレーヤーへの参照ポインタ
442  * @param em_ptr モンスター効果構造体への参照ポインタ
443  * @return なし
444  */
445 static void process_spell(player_type *caster_ptr, effect_monster_type *em_ptr)
446 {
447         process_spell_result(caster_ptr, em_ptr);
448         process_monster_bad_stat_damage(caster_ptr, em_ptr);
449         process_monster_last_moment(caster_ptr, em_ptr);
450         if ((em_ptr->effect_type == GF_BLOOD_CURSE) && one_in_(4))
451                 blood_curse_to_enemy(caster_ptr, em_ptr->who);
452 }
453
454
455 /*!
456  * @brief モンスター闘技場にいる場合の画面更新処理
457  * @param caster_ptr プレーヤーへの参照ポインタ
458  * @param em_ptr モンスター効果構造体への参照ポインタ
459  * @return なし
460  */
461 static void update_phase_out_stat(player_type *caster_ptr, effect_monster_type *em_ptr)
462 {
463         if (!caster_ptr->phase_out) return;
464
465         caster_ptr->health_who = em_ptr->g_ptr->m_idx;
466         caster_ptr->redraw |= (PR_HEALTH);
467         handle_stuff(caster_ptr);
468 }
469
470
471 /*!
472  * @brief 魔法効果がペットに及んだ時の処理
473  * @param caster_ptr プレーヤーへの参照ポインタ
474  * @param em_ptr モンスター効果構造体への参照ポインタ
475  * @return なし
476  */
477 static void postprocess_spell_pet(player_type *caster_ptr, effect_monster_type *em_ptr)
478 {
479         if ((em_ptr->dam <= 0) || is_pet(em_ptr->m_ptr) || is_friendly(em_ptr->m_ptr))
480                 return;
481
482         if (em_ptr->who == 0)
483         {
484                 if (!(em_ptr->flag & PROJECT_NO_HANGEKI))
485                         set_target(em_ptr->m_ptr, monster_target_y, monster_target_x);
486
487                 return;
488         }
489
490         if ((em_ptr->who > 0) && 
491                 is_pet(em_ptr->m_caster_ptr) && 
492                 !player_bold(caster_ptr, em_ptr->m_ptr->target_y, em_ptr->m_ptr->target_x))
493                 set_target(em_ptr->m_ptr, em_ptr->m_caster_ptr->fy, em_ptr->m_caster_ptr->fx);
494 }
495
496
497 /*!
498  * @brief 魔法効果が騎乗モンスターに及んだ時の処理
499  * @param caster_ptr プレーヤーへの参照ポインタ
500  * @param em_ptr モンスター効果構造体への参照ポインタ
501  * @return なし
502  */
503 static void postprocess_spell_riding(player_type *caster_ptr, effect_monster_type *em_ptr)
504 {
505         if (!caster_ptr->riding || (caster_ptr->riding != em_ptr->g_ptr->m_idx) || (em_ptr->dam <= 0))
506                 return;
507
508         if (em_ptr->m_ptr->hp > (em_ptr->m_ptr->maxhp / 3))
509                 em_ptr->dam = (em_ptr->dam + 1) / 2;
510
511         rakubadam_m = (em_ptr->dam > 200) ? 200 : em_ptr->dam;
512 }
513
514
515 /*!
516  * @brief 写真を撮った時の処理
517  * @param caster_ptr プレーヤーへの参照ポインタ
518  * @param em_ptr モンスター効果構造体への参照ポインタ
519  * @return なし
520  * @details 写真のフラッシュは弱閃光属性
521  */
522 static void postprocess_spell_photo(player_type *caster_ptr, effect_monster_type *em_ptr)
523 {
524         if (em_ptr->photo == 0) return;
525
526         object_type *q_ptr;
527         object_type forge;
528         q_ptr = &forge;
529         object_prep(q_ptr, lookup_kind(TV_STATUE, SV_PHOTO));
530         q_ptr->pval = em_ptr->photo;
531         q_ptr->ident |= (IDENT_FULL_KNOWN);
532         (void)drop_near(caster_ptr, q_ptr, -1, caster_ptr->y, caster_ptr->x);
533 }
534
535
536 /*!
537  * @brief モンスター効果の後処理 (ペット関係、記念撮影、グローバル変数更新)
538  * @param caster_ptr プレーヤーへの参照ポインタ
539  * @param em_ptr モンスター効果構造体への参照ポインタ
540  * @return なし
541  */
542 static void postprocess_spell(player_type *caster_ptr, effect_monster_type *em_ptr)
543 {
544         postprocess_spell_pet(caster_ptr, em_ptr);
545         postprocess_spell_riding(caster_ptr, em_ptr);
546         postprocess_spell_photo(caster_ptr, em_ptr);
547         project_m_n++;
548         project_m_x = em_ptr->x;
549         project_m_y = em_ptr->y;
550 }
551
552
553 /*!
554  * @brief 汎用的なビーム/ボルト/ボール系によるモンスターへの効果処理 / Handle a beam/bolt/ball causing damage to a monster.
555  * @param caster_ptr プレーヤーへの参照ポインタ
556  * @param who 魔法を発動したモンスター(0ならばプレイヤー) / Index of "source" monster (zero for "player")
557  * @param r 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion (0 = beam/bolt, 1 to 9 = ball)
558  * @param y 目標y座標 / Target y location (or location to travel "towards")
559  * @param x 目標x座標 / Target x location (or location to travel "towards")
560  * @param dam 基本威力 / Base damage roll to apply to affected monsters (or player)
561  * @param effect_type 効果属性 / Type of damage to apply to monsters (and objects)
562  * @param flag 効果フラグ
563  * @param see_s_msg TRUEならばメッセージを表示する
564  * @return 何か一つでも効力があればTRUEを返す / TRUE if any "effects" of the projection were observed, else FALSE
565  */
566 bool affect_monster(player_type *caster_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID effect_type, BIT_FLAGS flag, bool see_s_msg)
567 {
568         effect_monster_type tmp_effect;
569         effect_monster_type *em_ptr = initialize_effect_monster(caster_ptr, &tmp_effect, who, r, y, x, dam, effect_type, flag, see_s_msg);
570         if (!is_never_effect(caster_ptr, em_ptr)) return FALSE;
571
572         decide_spell_result_description(caster_ptr, em_ptr);
573         gf_switch_result result = process_monster_perfect_resistance(caster_ptr, em_ptr);
574         if (result != GF_SWITCH_CONTINUE) return (bool)result;
575
576         if (em_ptr->skipped) return FALSE;
577
578         process_spell(caster_ptr, em_ptr);
579         update_phase_out_stat(caster_ptr, em_ptr);
580         if (em_ptr->m_ptr->r_idx)
581                 update_monster(caster_ptr, em_ptr->g_ptr->m_idx, FALSE);
582
583         lite_spot(caster_ptr, em_ptr->y, em_ptr->x);
584         if ((caster_ptr->monster_race_idx == em_ptr->m_ptr->r_idx) && (em_ptr->seen || !em_ptr->m_ptr->r_idx))
585                 caster_ptr->window |= (PW_MONSTER);
586
587         postprocess_spell(caster_ptr, em_ptr);
588         return em_ptr->obvious;
589 }