OSDN Git Service

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