OSDN Git Service

[Refactor] #40014 Separated monster-describer.c/h from monster2.c/h
[hengband/hengband.git] / src / melee / melee-postprocess.c
1 /*!
2  * @brief モンスター同士の打撃後処理 / Melee post-process.
3  * @date 2014/01/17
4  * @author
5  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n
6  * This software may be copied and distributed for educational, research,\n
7  * and not for profit purposes provided that this copyright and statement\n
8  * are included in all such copies.  Other copyrights may also apply.\n
9  * 2014 Deskull rearranged comment for Doxygen.\n
10  * @details
11  */
12
13 #include "melee/melee-postprocess.h"
14 #include "monster-attack/monster-attack-types.h"
15 #include "grid/grid.h"
16 #include "main/sound-definitions-table.h"
17 #include "monster-race/race-flags-resistance.h"
18 #include "monster-race/race-flags1.h"
19 #include "monster-race/race-flags3.h"
20 #include "monster-race/race-flags7.h"
21 #include "monster-race/monster-race-hook.h"
22 #include "monster/monster-describer.h"
23 #include "monster/monster-description-types.h"
24 #include "monster/monster-death.h"
25 #include "monster/monster-status.h"
26 #include "monster/monster2.h"
27 #include "mspell/monster-spell.h"
28 #include "pet/pet-fall-off.h"
29 #include "player/player-class.h"
30 #include "player/player-move.h"
31 #include "player/player-personalities-table.h"
32 #include "player/player-races-table.h"
33 #include "util/util.h"
34
35 // Melee-post-process-type
36 typedef struct mam_pp_type {
37     MONSTER_IDX m_idx;
38     monster_type *m_ptr;
39     bool seen;
40     GAME_TEXT m_name[160];
41     HIT_POINT dam;
42     bool known; /* Can the player be aware of this attack? */
43     concptr note;
44     bool *dead;
45     bool *fear;
46     MONSTER_IDX who;
47 } mam_pp_type;
48
49 mam_pp_type *initialize_mam_pp_type(
50     player_type *player_ptr, mam_pp_type *mam_pp_ptr, MONSTER_IDX m_idx, HIT_POINT dam, bool *dead, bool *fear, concptr note, MONSTER_IDX who)
51 {
52     mam_pp_ptr->m_idx = m_idx;
53     mam_pp_ptr->m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
54     mam_pp_ptr->seen = is_seen(mam_pp_ptr->m_ptr);
55     mam_pp_ptr->dam = dam;
56     mam_pp_ptr->known = mam_pp_ptr->m_ptr->cdis <= MAX_SIGHT;
57     mam_pp_ptr->dead = dead;
58     mam_pp_ptr->fear = fear;
59     mam_pp_ptr->note = note;
60     mam_pp_ptr->who = who;
61     return mam_pp_ptr;
62 }
63
64 static void prepare_redraw(player_type *player_ptr, mam_pp_type *mam_pp_ptr)
65 {
66     if (!mam_pp_ptr->m_ptr->ml)
67         return;
68
69     if (player_ptr->health_who == mam_pp_ptr->m_idx)
70         player_ptr->redraw |= (PR_HEALTH);
71
72     if (player_ptr->riding == mam_pp_ptr->m_idx)
73         player_ptr->redraw |= (PR_UHEALTH);
74 }
75
76 /*!
77  * @brief モンスターが無敵だった場合の処理
78  * @param mam_pp_ptr 標的モンスター構造体への参照ポインタ
79  * @return 無敵ノーダメならTRUE、無敵でないか無敵を貫通したらFALSE
80  */
81 static bool process_invulnerability(mam_pp_type *mam_pp_ptr)
82 {
83     if (monster_invulner_remaining(mam_pp_ptr->m_ptr) && randint0(PENETRATE_INVULNERABILITY))
84         return FALSE;
85
86     if (mam_pp_ptr->seen)
87         msg_format(_("%^sはダメージを受けない。", "%^s is unharmed."), mam_pp_ptr->m_name);
88
89     return TRUE;
90 }
91
92 /*!
93  * @brief 魔法完全防御持ちの処理
94  * @param mam_pp_ptr 標的モンスター構造体への参照ポインタ
95  * @return ノーダメならTRUE、 そうでないならFALSE
96  */
97 static bool process_all_resistances(mam_pp_type *mam_pp_ptr)
98 {
99     monster_race *r_ptr = &r_info[mam_pp_ptr->m_ptr->r_idx];
100     if ((r_ptr->flagsr & RFR_RES_ALL) == 0)
101         return FALSE;
102
103     if (mam_pp_ptr->dam > 0) {
104         mam_pp_ptr->dam /= 100;
105         if ((mam_pp_ptr->dam == 0) && one_in_(3))
106             mam_pp_ptr->dam = 1;
107     }
108
109     if (mam_pp_ptr->dam != 0)
110         return FALSE;
111
112     if (mam_pp_ptr->seen)
113         msg_format(_("%^sはダメージを受けない。", "%^s is unharmed."), mam_pp_ptr->m_name);
114
115     return TRUE;
116 }
117
118 /*!
119  * @brief モンスター死亡時のメッセージ表示
120  * @param player_ptr プレーヤーへの参照ポインタ
121  * @param mam_pp_ptr 標的モンスター構造体への参照ポインタ
122  * @return なし
123  * @details
124  * 見えない位置で死んだら何も表示しない
125  * 爆発して粉々になった等ならその旨を、残りは生命か無生命かで分岐
126  */
127 static void print_monster_dead_by_monster(player_type *player_ptr, mam_pp_type *mam_pp_ptr)
128 {
129     if (!mam_pp_ptr->known)
130         return;
131
132     monster_desc(player_ptr, mam_pp_ptr->m_name, mam_pp_ptr->m_ptr, MD_TRUE_NAME);
133     if (!mam_pp_ptr->seen) {
134         player_ptr->current_floor_ptr->monster_noise = TRUE;
135         return;
136     }
137
138     if (mam_pp_ptr->note) {
139         msg_format(_("%^s%s", "%^s%s"), mam_pp_ptr->m_name, mam_pp_ptr->note);
140         return;
141     }
142
143     if (!monster_living(mam_pp_ptr->m_ptr->r_idx)) {
144         msg_format(_("%^sは破壊された。", "%^s is destroyed."), mam_pp_ptr->m_name);
145         return;
146     }
147
148     msg_format(_("%^sは殺された。", "%^s is killed."), mam_pp_ptr->m_name);
149 }
150
151 /*!
152  * @brief ダメージを受けたモンスターのHPが0未満になった際の処理
153  * @param player_ptr プレーヤーへの参照ポインタ
154  * @param mam_pp_ptr 標的モンスター構造体への参照ポインタ
155  * @return 生きていたらTRUE、それ以外 (ユニークは@以外の攻撃では死なない)はFALSE
156  */
157 static bool check_monster_hp(player_type *player_ptr, mam_pp_type *mam_pp_ptr)
158 {
159     monster_race *r_ptr = &r_info[mam_pp_ptr->m_ptr->r_idx];
160     if (mam_pp_ptr->m_ptr->hp < 0)
161         return FALSE;
162
163     if (((r_ptr->flags1 & (RF1_UNIQUE | RF1_QUESTOR)) || (r_ptr->flags7 & RF7_NAZGUL)) && !player_ptr->phase_out) {
164         mam_pp_ptr->m_ptr->hp = 1;
165         return FALSE;
166     }
167
168     sound_type kill_sound = monster_living(mam_pp_ptr->m_ptr->r_idx) ? SOUND_KILL : SOUND_N_KILL;
169     sound(kill_sound);
170     *(mam_pp_ptr->dead) = TRUE;
171     print_monster_dead_by_monster(player_ptr, mam_pp_ptr);
172     monster_gain_exp(player_ptr, mam_pp_ptr->who, mam_pp_ptr->m_ptr->r_idx);
173     monster_death(player_ptr, mam_pp_ptr->m_idx, FALSE);
174     delete_monster_idx(player_ptr, mam_pp_ptr->m_idx);
175     *(mam_pp_ptr->fear) = FALSE;
176     return TRUE;
177 }
178
179 /*!
180  * @brief 死亡等で恐慌状態をキャンセルする
181  * @param player_ptr プレーヤーへの参照ポインタ
182  * @param mam_pp_ptr 標的モンスター構造体への参照ポインタ
183  * @return なし
184  */
185 static void cancel_fear_by_pain(player_type *player_ptr, mam_pp_type *mam_pp_ptr)
186 {
187     if (!monster_fear_remaining(mam_pp_ptr->m_ptr) || (mam_pp_ptr->dam <= 0)
188         || !set_monster_monfear(player_ptr, mam_pp_ptr->m_idx, monster_fear_remaining(mam_pp_ptr->m_ptr) - randint1(mam_pp_ptr->dam / 4)))
189         return;
190
191     *(mam_pp_ptr->fear) = FALSE;
192 }
193
194 /*!
195  * @biref HP残量などに応じてモンスターを恐慌状態にする
196  * @param player_ptr プレーヤーへの参照ポインタ
197  * @param mam_pp_ptr 標的モンスター構造体への参照ポインタ
198  * @return なし
199  */
200 static void make_monster_fear(player_type *player_ptr, mam_pp_type *mam_pp_ptr)
201 {
202     monster_race *r_ptr = &r_info[mam_pp_ptr->m_ptr->r_idx];
203     if (monster_fear_remaining(mam_pp_ptr->m_ptr) || ((r_ptr->flags3 & RF3_NO_FEAR) == 0))
204         return;
205
206     int percentage = (100L * mam_pp_ptr->m_ptr->hp) / mam_pp_ptr->m_ptr->maxhp;
207     bool can_make_fear = ((percentage <= 10) && (randint0(10) < percentage)) || ((mam_pp_ptr->dam >= mam_pp_ptr->m_ptr->hp) && (randint0(100) < 80));
208     if (!can_make_fear)
209         return;
210
211     *(mam_pp_ptr->fear) = TRUE;
212     (void)set_monster_monfear(
213         player_ptr, mam_pp_ptr->m_idx, (randint1(10) + (((mam_pp_ptr->dam >= mam_pp_ptr->m_ptr->hp) && (percentage > 7)) ? 20 : ((11 - percentage) * 5))));
214 }
215
216 /*!
217  * @brief モンスター同士の乱闘による落馬処理
218  * @param player_ptr プレーヤーへの参照ポインタ
219  * @param mam_pp_ptr 標的モンスター構造体への参照ポインタ
220  * @return なし
221  */
222 static void fall_off_horse_by_melee(player_type *player_ptr, mam_pp_type *mam_pp_ptr)
223 {
224     if (!player_ptr->riding || (player_ptr->riding != mam_pp_ptr->m_idx) || (mam_pp_ptr->dam <= 0))
225         return;
226
227     monster_desc(player_ptr, mam_pp_ptr->m_name, mam_pp_ptr->m_ptr, 0);
228     if (mam_pp_ptr->m_ptr->hp > mam_pp_ptr->m_ptr->maxhp / 3)
229         mam_pp_ptr->dam = (mam_pp_ptr->dam + 1) / 2;
230
231     if (process_fall_off_horse(player_ptr, (mam_pp_ptr->dam > 200) ? 200 : mam_pp_ptr->dam, FALSE))
232         msg_format(_("%^sに振り落とされた!", "You have been thrown off from %s!"), mam_pp_ptr->m_name);
233 }
234
235 /*!
236  * todo 打撃が当たった時の後処理 (爆発持ちのモンスターを爆発させる等)なので、関数名を変更する必要あり
237  * @brief モンスターが敵モンスターに行う打撃処理 /
238  * Hack, based on mon_take_hit... perhaps all monster attacks on other monsters should use this?
239  * @param m_idx 目標となるモンスターの参照ID
240  * @param dam ダメージ量
241  * @param dead 目標となったモンスターの死亡状態を返す参照ポインタ
242  * @param fear 目標となったモンスターの恐慌状態を返す参照ポインタ
243  * @param note 目標モンスターが死亡した場合の特別メッセージ(NULLならば標準表示を行う)
244  * @param who 打撃を行ったモンスターの参照ID
245  * @return なし
246  */
247 void mon_take_hit_mon(player_type *player_ptr, MONSTER_IDX m_idx, HIT_POINT dam, bool *dead, bool *fear, concptr note, MONSTER_IDX who)
248 {
249     floor_type *floor_ptr = player_ptr->current_floor_ptr;
250     monster_type *m_ptr = &floor_ptr->m_list[m_idx];
251     mam_pp_type tmp_mam_pp;
252     mam_pp_type *mam_pp_ptr = initialize_mam_pp_type(player_ptr, &tmp_mam_pp, m_idx, dam, dead, fear, note, who);
253     monster_desc(player_ptr, mam_pp_ptr->m_name, m_ptr, 0);
254     prepare_redraw(player_ptr, mam_pp_ptr);
255     (void)set_monster_csleep(player_ptr, m_idx, 0);
256
257     if (player_ptr->riding && (m_idx == player_ptr->riding))
258         disturb(player_ptr, TRUE, TRUE);
259
260     if (process_invulnerability(mam_pp_ptr) || process_all_resistances(mam_pp_ptr))
261         return;
262
263     m_ptr->hp -= dam;
264     if (check_monster_hp(player_ptr, mam_pp_ptr))
265         return;
266
267     *dead = FALSE;
268     cancel_fear_by_pain(player_ptr, mam_pp_ptr);
269     make_monster_fear(player_ptr, mam_pp_ptr);
270     if ((dam > 0) && !is_pet(m_ptr) && !is_friendly(m_ptr) && (mam_pp_ptr->who != m_idx)) {
271         if (is_pet(&floor_ptr->m_list[mam_pp_ptr->who]) && !player_bold(player_ptr, m_ptr->target_y, m_ptr->target_x)) {
272             set_target(m_ptr, floor_ptr->m_list[mam_pp_ptr->who].fy, floor_ptr->m_list[mam_pp_ptr->who].fx);
273         }
274     }
275
276     fall_off_horse_by_melee(player_ptr, mam_pp_ptr);
277 }