1 #include "monster/monster-status-setter.h"
2 #include "cmd-visual/cmd-draw.h"
3 #include "core/player-update-types.h"
4 #include "core/player-redraw-types.h"
5 #include "core/speed-table.h"
6 #include "core/stuff-handler.h"
7 #include "core/window-redrawer.h"
8 #include "dungeon/quest-completion-checker.h"
9 #include "floor/cave.h"
10 #include "monster-floor/monster-move.h"
11 #include "monster-race/monster-race.h"
12 #include "monster-race/race-flags3.h"
13 #include "monster-race/race-flags7.h"
14 #include "monster/monster-describer.h"
15 #include "monster/monster-info.h"
16 #include "monster/monster-processor.h"
17 #include "monster/monster-status.h" // todo 相互依存. 後で何とかする.
18 #include "monster/monster-util.h"
19 #include "monster/smart-learn-types.h"
20 #include "player-info/avatar.h"
21 #include "system/floor-type-definition.h"
22 #include "system/monster-type-definition.h"
23 #include "target/projection-path-calculator.h"
24 #include "view/display-messages.h"
25 #include "world/world.h"
29 * @param player_type プレーヤーへの参照ポインタ
30 * @param m_ptr モンスター情報構造体の参照ポインタ
33 void set_pet(player_type *player_ptr, monster_type *m_ptr)
35 check_quest_completion(player_ptr, m_ptr);
36 m_ptr->smart |= SM_PET;
37 if (!(r_info[m_ptr->r_idx].flags3 & (RF3_EVIL | RF3_GOOD)))
38 m_ptr->sub_align = SUB_ALIGN_NEUTRAL;
43 * Makes the monster hostile towards the player
44 * @param m_ptr モンスター情報構造体の参照ポインタ
47 void set_hostile(player_type *player_ptr, monster_type *m_ptr)
49 if (player_ptr->phase_out)
52 m_ptr->smart &= ~SM_PET;
53 m_ptr->smart &= ~SM_FRIENDLY;
59 * @param m_ptr モンスター情報構造体の参照ポインタ
62 void anger_monster(player_type *player_ptr, monster_type *m_ptr)
64 if (player_ptr->phase_out || !is_friendly(m_ptr))
67 GAME_TEXT m_name[MAX_NLEN];
68 monster_desc(player_ptr, m_name, m_ptr, 0);
69 msg_format(_("%^sは怒った!", "%^s gets angry!"), m_name);
70 set_hostile(player_ptr, m_ptr);
71 chg_virtue(player_ptr, V_INDIVIDUALISM, 1);
72 chg_virtue(player_ptr, V_HONOUR, -1);
73 chg_virtue(player_ptr, V_JUSTICE, -1);
74 chg_virtue(player_ptr, V_COMPASSION, -1);
78 * @brief モンスターの時限ステータスリストを削除
79 * @param floor_ptr 現在フロアへの参照ポインタ
80 * @return m_idx モンスターの参照ID
81 * @return mproc_type 削除したいモンスターの時限ステータスID
84 static void mproc_remove(floor_type *floor_ptr, MONSTER_IDX m_idx, int mproc_type)
86 int mproc_idx = get_mproc_idx(floor_ptr, m_idx, mproc_type);
88 floor_ptr->mproc_list[mproc_type][mproc_idx] = floor_ptr->mproc_list[mproc_type][--floor_ptr->mproc_max[mproc_type]];
92 * @brief モンスターの睡眠状態値をセットする。0で起きる。 /
93 * Set "m_ptr->mtimed[MTIMED_CSLEEP]", notice observable changes
94 * @param target_ptr プレーヤーへの参照ポインタ
95 * @param m_idx モンスター参照ID
97 * @return 別途更新処理が必要な場合TRUEを返す
99 bool set_monster_csleep(player_type *target_ptr, MONSTER_IDX m_idx, int v)
101 floor_type *floor_ptr = target_ptr->current_floor_ptr;
102 monster_type *m_ptr = &floor_ptr->m_list[m_idx];
104 v = (v > 10000) ? 10000 : (v < 0) ? 0 : v;
106 if (!monster_csleep_remaining(m_ptr)) {
107 mproc_add(floor_ptr, m_idx, MTIMED_CSLEEP);
111 if (monster_csleep_remaining(m_ptr)) {
112 mproc_remove(floor_ptr, m_idx, MTIMED_CSLEEP);
117 m_ptr->mtimed[MTIMED_CSLEEP] = (s16b)v;
122 if (target_ptr->health_who == m_idx)
123 target_ptr->redraw |= PR_HEALTH;
125 if (target_ptr->riding == m_idx)
126 target_ptr->redraw |= PR_UHEALTH;
129 if (r_info[m_ptr->r_idx].flags7 & RF7_HAS_LD_MASK)
130 target_ptr->update |= PU_MON_LITE;
136 * @brief モンスターの加速状態値をセット /
137 * Set "m_ptr->mtimed[MTIMED_FAST]", notice observable changes
138 * @param target_ptr プレーヤーへの参照ポインタ
139 * @param m_idx モンスター参照ID
141 * @return 別途更新処理が必要な場合TRUEを返す
143 bool set_monster_fast(player_type *target_ptr, MONSTER_IDX m_idx, int v)
145 floor_type *floor_ptr = target_ptr->current_floor_ptr;
146 monster_type *m_ptr = &floor_ptr->m_list[m_idx];
148 v = (v > 200) ? 200 : (v < 0) ? 0 : v;
150 if (!monster_fast_remaining(m_ptr)) {
151 mproc_add(floor_ptr, m_idx, MTIMED_FAST);
155 if (monster_fast_remaining(m_ptr)) {
156 mproc_remove(floor_ptr, m_idx, MTIMED_FAST);
161 m_ptr->mtimed[MTIMED_FAST] = (s16b)v;
165 if ((target_ptr->riding == m_idx) && !target_ptr->leaving)
166 target_ptr->update |= PU_BONUS;
172 * Set "m_ptr->mtimed[MTIMED_SLOW]", notice observable changes
174 bool set_monster_slow(player_type *target_ptr, MONSTER_IDX m_idx, int v)
176 floor_type *floor_ptr = target_ptr->current_floor_ptr;
177 monster_type *m_ptr = &floor_ptr->m_list[m_idx];
179 v = (v > 200) ? 200 : (v < 0) ? 0 : v;
181 if (!monster_slow_remaining(m_ptr)) {
182 mproc_add(floor_ptr, m_idx, MTIMED_SLOW);
186 if (monster_slow_remaining(m_ptr)) {
187 mproc_remove(floor_ptr, m_idx, MTIMED_SLOW);
192 m_ptr->mtimed[MTIMED_SLOW] = (s16b)v;
196 if ((target_ptr->riding == m_idx) && !target_ptr->leaving)
197 target_ptr->update |= PU_BONUS;
203 * @brief モンスターの朦朧状態値をセット /
204 * Set "m_ptr->mtimed[MTIMED_STUNNED]", notice observable changes
205 * @param target_ptr プレーヤーへの参照ポインタ
206 * @param m_idx モンスター参照ID
208 * @return 別途更新処理が必要な場合TRUEを返す
210 bool set_monster_stunned(player_type *target_ptr, MONSTER_IDX m_idx, int v)
212 floor_type *floor_ptr = target_ptr->current_floor_ptr;
213 monster_type *m_ptr = &floor_ptr->m_list[m_idx];
215 v = (v > 200) ? 200 : (v < 0) ? 0 : v;
217 if (!monster_stunned_remaining(m_ptr)) {
218 mproc_add(floor_ptr, m_idx, MTIMED_STUNNED);
222 if (monster_stunned_remaining(m_ptr)) {
223 mproc_remove(floor_ptr, m_idx, MTIMED_STUNNED);
228 m_ptr->mtimed[MTIMED_STUNNED] = (s16b)v;
233 * @brief モンスターの混乱状態値をセット /
234 * Set "m_ptr->mtimed[MTIMED_CONFUSED]", notice observable changes
235 * @param target_ptr プレーヤーへの参照ポインタ
236 * @param m_idx モンスター参照ID
238 * @return 別途更新処理が必要な場合TRUEを返す
240 bool set_monster_confused(player_type *target_ptr, MONSTER_IDX m_idx, int v)
242 floor_type *floor_ptr = target_ptr->current_floor_ptr;
243 monster_type *m_ptr = &floor_ptr->m_list[m_idx];
245 v = (v > 200) ? 200 : (v < 0) ? 0 : v;
247 if (!monster_confused_remaining(m_ptr)) {
248 mproc_add(floor_ptr, m_idx, MTIMED_CONFUSED);
252 if (monster_confused_remaining(m_ptr)) {
253 mproc_remove(floor_ptr, m_idx, MTIMED_CONFUSED);
258 m_ptr->mtimed[MTIMED_CONFUSED] = (s16b)v;
263 * @brief モンスターの恐慌状態値をセット /
264 * Set "m_ptr->mtimed[MTIMED_MONFEAR]", notice observable changes
265 * @param target_ptr プレーヤーへの参照ポインタ
266 * @param m_idx モンスター参照ID
268 * @return 別途更新処理が必要な場合TRUEを返す
270 bool set_monster_monfear(player_type *target_ptr, MONSTER_IDX m_idx, int v)
272 floor_type *floor_ptr = target_ptr->current_floor_ptr;
273 monster_type *m_ptr = &floor_ptr->m_list[m_idx];
275 v = (v > 200) ? 200 : (v < 0) ? 0 : v;
277 if (!monster_fear_remaining(m_ptr)) {
278 mproc_add(floor_ptr, m_idx, MTIMED_MONFEAR);
282 if (monster_fear_remaining(m_ptr)) {
283 mproc_remove(floor_ptr, m_idx, MTIMED_MONFEAR);
288 m_ptr->mtimed[MTIMED_MONFEAR] = (s16b)v;
294 if (target_ptr->health_who == m_idx)
295 target_ptr->redraw |= PR_HEALTH;
297 if (target_ptr->riding == m_idx)
298 target_ptr->redraw |= PR_UHEALTH;
305 * @brief モンスターの無敵状態値をセット /
306 * Set "m_ptr->mtimed[MTIMED_INVULNER]", notice observable changes
307 * @param target_ptr プレーヤーへの参照ポインタ
308 * @param m_idx モンスター参照ID
310 * @param energy_need TRUEならば無敵解除時に行動ターン消費を行う
311 * @return 別途更新処理が必要な場合TRUEを返す
313 bool set_monster_invulner(player_type *target_ptr, MONSTER_IDX m_idx, int v, bool energy_need)
315 floor_type *floor_ptr = target_ptr->current_floor_ptr;
316 monster_type *m_ptr = &floor_ptr->m_list[m_idx];
318 v = (v > 200) ? 200 : (v < 0) ? 0 : v;
320 if (!monster_invulner_remaining(m_ptr)) {
321 mproc_add(floor_ptr, m_idx, MTIMED_INVULNER);
325 if (monster_invulner_remaining(m_ptr)) {
326 mproc_remove(floor_ptr, m_idx, MTIMED_INVULNER);
327 if (energy_need && !target_ptr->wild_mode)
328 m_ptr->energy_need += ENERGY_NEED();
333 m_ptr->mtimed[MTIMED_INVULNER] = (s16b)v;
338 if (target_ptr->health_who == m_idx)
339 target_ptr->redraw |= PR_HEALTH;
341 if (target_ptr->riding == m_idx)
342 target_ptr->redraw |= PR_UHEALTH;
349 * @brief モンスターの時間停止処理
350 * @param target_ptr プレーヤーへの参照ポインタ
351 * @param num 時間停止を行った敵が行動できる回数
352 * @param who 時間停止処理の主体ID
353 * @param vs_player TRUEならば時間停止開始処理を行う
354 * @return 時間停止が行われている状態ならばTRUEを返す
356 bool set_monster_timewalk(player_type *target_ptr, int num, MONSTER_IDX who, bool vs_player)
358 monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[hack_m_idx];
359 if (current_world_ptr->timewalk_m_idx)
363 GAME_TEXT m_name[MAX_NLEN];
364 monster_desc(target_ptr, m_name, m_ptr, 0);
367 msg_format(_("「『ザ・ワールド』!時は止まった!」", "%s yells 'The World! Time has stopped!'"), m_name);
369 msg_format(_("「時よ!」", "%s yells 'Time!'"), m_name);
376 current_world_ptr->timewalk_m_idx = hack_m_idx;
378 do_cmd_redraw(target_ptr);
381 if (!monster_is_valid(m_ptr))
384 process_monster(target_ptr, current_world_ptr->timewalk_m_idx);
386 handle_stuff(target_ptr);
388 term_xtra(TERM_XTRA_DELAY, 500);
391 target_ptr->redraw |= PR_MAP;
392 target_ptr->update |= PU_MONSTERS;
393 target_ptr->window |= PW_OVERHEAD | PW_DUNGEON;
394 current_world_ptr->timewalk_m_idx = 0;
395 if (vs_player || (player_has_los_bold(target_ptr, m_ptr->fy, m_ptr->fx) && projectable(target_ptr, target_ptr->y, target_ptr->x, m_ptr->fy, m_ptr->fx))) {
396 msg_print(_("「時は動きだす…」", "You feel time flowing around you once more."));
400 handle_stuff(target_ptr);