OSDN Git Service

Merge pull request #3814 from Slimebreath6078/feature/Add_Laffey_II
[hengbandforosx/hengbandosx.git] / src / monster-floor / monster-remover.cpp
1 #include "monster-floor/monster-remover.h"
2 #include "core/stuff-handler.h"
3 #include "floor/cave.h"
4 #include "floor/floor-object.h"
5 #include "grid/grid.h"
6 #include "monster-race/monster-race.h"
7 #include "monster-race/race-brightness-mask.h"
8 #include "monster-race/race-indice-types.h"
9 #include "monster/monster-info.h"
10 #include "monster/monster-status-setter.h"
11 #include "monster/monster-status.h"
12 #include "system/floor-type-definition.h"
13 #include "system/grid-type-definition.h"
14 #include "system/item-entity.h"
15 #include "system/monster-entity.h"
16 #include "system/monster-race-info.h"
17 #include "system/player-type-definition.h"
18 #include "system/redrawing-flags-updater.h"
19 #include "target/target-checker.h"
20
21 /*!
22  * @brief モンスター配列からモンスターを消去する / Delete a monster by index.
23  * @param i 消去するモンスターのID
24  * @details
25  * モンスターを削除するとそのモンスターが拾っていたアイテムも同時に削除される。 /
26  * When a monster is deleted, all of its objects are deleted.
27  */
28 void delete_monster_idx(PlayerType *player_ptr, MONSTER_IDX i)
29 {
30     auto *floor_ptr = player_ptr->current_floor_ptr;
31     auto *m_ptr = &floor_ptr->m_list[i];
32     auto *r_ptr = &m_ptr->get_monrace();
33
34     POSITION y = m_ptr->fy;
35     POSITION x = m_ptr->fx;
36
37     m_ptr->get_real_monrace().cur_num--;
38     if (r_ptr->misc_flags.has(MonsterMiscType::MULTIPLY)) {
39         floor_ptr->num_repro--;
40     }
41
42     if (m_ptr->is_asleep()) {
43         (void)set_monster_csleep(player_ptr, i, 0);
44     }
45     if (m_ptr->is_accelerated()) {
46         (void)set_monster_fast(player_ptr, i, 0);
47     }
48     if (m_ptr->is_decelerated()) {
49         (void)set_monster_slow(player_ptr, i, 0);
50     }
51     if (m_ptr->is_stunned()) {
52         (void)set_monster_stunned(player_ptr, i, 0);
53     }
54     if (m_ptr->is_confused()) {
55         (void)set_monster_confused(player_ptr, i, 0);
56     }
57     if (m_ptr->is_fearful()) {
58         (void)set_monster_monfear(player_ptr, i, 0);
59     }
60     if (m_ptr->is_invulnerable()) {
61         (void)set_monster_invulner(player_ptr, i, 0, false);
62     }
63
64     if (i == target_who) {
65         target_who = 0;
66     }
67
68     if (i == player_ptr->health_who) {
69         health_track(player_ptr, 0);
70     }
71
72     if (player_ptr->pet_t_m_idx == i) {
73         player_ptr->pet_t_m_idx = 0;
74     }
75     if (player_ptr->riding_t_m_idx == i) {
76         player_ptr->riding_t_m_idx = 0;
77     }
78     if (player_ptr->riding == i) {
79         player_ptr->riding = 0;
80     }
81
82     floor_ptr->grid_array[y][x].m_idx = 0;
83     for (auto it = m_ptr->hold_o_idx_list.begin(); it != m_ptr->hold_o_idx_list.end();) {
84         const OBJECT_IDX this_o_idx = *it++;
85         delete_object_idx(player_ptr, this_o_idx);
86     }
87
88     // 召喚元のモンスターが消滅した時は、召喚されたモンスターのparent_m_idxが
89     // 召喚されたモンスター自身のm_idxを指すようにする
90     for (MONSTER_IDX child_m_idx = 1; child_m_idx < floor_ptr->m_max; child_m_idx++) {
91         MonsterEntity *child_m_ptr = &floor_ptr->m_list[child_m_idx];
92         if (MonsterRace(child_m_ptr->r_idx).is_valid() && child_m_ptr->parent_m_idx == i) {
93             child_m_ptr->parent_m_idx = child_m_idx;
94         }
95     }
96
97     *m_ptr = {};
98     floor_ptr->m_cnt--;
99     lite_spot(player_ptr, y, x);
100     if (r_ptr->brightness_flags.has_any_of(ld_mask)) {
101         RedrawingFlagsUpdater::get_instance().set_flag(StatusRecalculatingFlag::MONSTER_LITE);
102     }
103 }
104
105 /*!
106  * @brief プレイヤーのフロア離脱に伴う全モンスター配列の消去
107  * @param player_ptr プレイヤーへの参照ポインタ
108  * @details 視覚効果なしでdelete_monster() をフロア全体に対して呼び出す.
109  */
110 void wipe_monsters_list(PlayerType *player_ptr)
111 {
112     MonraceList::get_instance().defeat_separated_uniques();
113     auto *floor_ptr = player_ptr->current_floor_ptr;
114     for (int i = floor_ptr->m_max - 1; i >= 1; i--) {
115         auto *m_ptr = &floor_ptr->m_list[i];
116         if (!m_ptr->is_valid()) {
117             continue;
118         }
119
120         floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].m_idx = 0;
121         *m_ptr = {};
122     }
123
124     /*
125      * Wiping racial counters of all monsters and incrementing of racial
126      * counters of monsters in party_mon[] are required to prevent multiple
127      * generation of unique monster who is the minion of player.
128      */
129     for (auto &[r_idx, r_ref] : monraces_info) {
130         r_ref.cur_num = 0;
131     }
132
133     floor_ptr->m_max = 1;
134     floor_ptr->m_cnt = 0;
135     for (int i = 0; i < MAX_MTIMED; i++) {
136         floor_ptr->mproc_max[i] = 0;
137     }
138
139     floor_ptr->num_repro = 0;
140     target_who = 0;
141     player_ptr->pet_t_m_idx = 0;
142     player_ptr->riding_t_m_idx = 0;
143     health_track(player_ptr, 0);
144 }
145
146 /*!
147  * @brief 指定位置に存在するモンスターを削除する / Delete the monster, if any, at a given location
148  * @param player_ptr プレイヤーへの参照ポインタ
149  * @param x 削除位置x座標
150  * @param y 削除位置y座標
151  */
152 void delete_monster(PlayerType *player_ptr, POSITION y, POSITION x)
153 {
154     Grid *g_ptr;
155     auto *floor_ptr = player_ptr->current_floor_ptr;
156     if (!in_bounds(floor_ptr, y, x)) {
157         return;
158     }
159
160     g_ptr = &floor_ptr->grid_array[y][x];
161     if (g_ptr->has_monster()) {
162         delete_monster_idx(player_ptr, g_ptr->m_idx);
163     }
164 }