OSDN Git Service

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