2 * @brief モンスターが移動した結果、床のアイテムに重なった時の処理と、モンスターがアイテムを落とす処理
7 #include "monster-floor/monster-object.h"
8 #include "flavor/flavor-describer.h"
9 #include "floor/floor-object.h"
10 #include "floor/cave.h"
11 #include "floor/geometry.h"
12 #include "grid/grid.h"
13 #include "monster-race/monster-race.h"
14 #include "monster-race/race-flags-resistance.h"
15 #include "monster-race/race-flags2.h"
16 #include "monster-race/race-flags3.h"
17 #include "monster/monster-describer.h"
18 #include "monster/monster-description-types.h"
19 #include "monster/monster-info.h"
20 #include "monster/monster-processor-util.h"
21 #include "monster/smart-learn-types.h"
22 #include "object-enchant/tr-types.h"
23 #include "object-hook/hook-enchant.h"
24 #include "object/object-flags.h"
25 #include "object/object-mark-types.h"
26 #include "system/floor-type-definition.h"
27 #include "system/monster-race-definition.h"
28 #include "system/monster-type-definition.h"
29 #include "system/object-type-definition.h"
30 #include "system/player-type-definition.h"
31 #include "util/bit-flags-calculator.h"
32 #include "view/display-messages.h"
35 * @brief オブジェクトのフラグを更新する
37 static void update_object_flags(BIT_FLAGS *flgs, BIT_FLAGS *flg2, BIT_FLAGS *flg3, BIT_FLAGS *flgr)
39 if (has_flag(flgs, TR_SLAY_DRAGON))
40 *flg3 |= (RF3_DRAGON);
41 if (has_flag(flgs, TR_KILL_DRAGON))
42 *flg3 |= (RF3_DRAGON);
43 if (has_flag(flgs, TR_SLAY_TROLL))
45 if (has_flag(flgs, TR_KILL_TROLL))
47 if (has_flag(flgs, TR_SLAY_GIANT))
49 if (has_flag(flgs, TR_KILL_GIANT))
51 if (has_flag(flgs, TR_SLAY_ORC))
53 if (has_flag(flgs, TR_KILL_ORC))
55 if (has_flag(flgs, TR_SLAY_DEMON))
57 if (has_flag(flgs, TR_KILL_DEMON))
59 if (has_flag(flgs, TR_SLAY_UNDEAD))
60 *flg3 |= (RF3_UNDEAD);
61 if (has_flag(flgs, TR_KILL_UNDEAD))
62 *flg3 |= (RF3_UNDEAD);
63 if (has_flag(flgs, TR_SLAY_ANIMAL))
64 *flg3 |= (RF3_ANIMAL);
65 if (has_flag(flgs, TR_KILL_ANIMAL))
66 *flg3 |= (RF3_ANIMAL);
67 if (has_flag(flgs, TR_SLAY_EVIL))
69 if (has_flag(flgs, TR_KILL_EVIL))
71 if (has_flag(flgs, TR_SLAY_GOOD))
73 if (has_flag(flgs, TR_KILL_GOOD))
75 if (has_flag(flgs, TR_SLAY_HUMAN))
77 if (has_flag(flgs, TR_KILL_HUMAN))
79 if (has_flag(flgs, TR_BRAND_ACID))
80 *flgr |= (RFR_IM_ACID);
81 if (has_flag(flgs, TR_BRAND_ELEC))
82 *flgr |= (RFR_IM_ELEC);
83 if (has_flag(flgs, TR_BRAND_FIRE))
84 *flgr |= (RFR_IM_FIRE);
85 if (has_flag(flgs, TR_BRAND_COLD))
86 *flgr |= (RFR_IM_COLD);
87 if (has_flag(flgs, TR_BRAND_POIS))
88 *flgr |= (RFR_IM_POIS);
92 * @brief モンスターがアイテムを拾うか壊す処理
93 * @param target_ptr プレーヤーへの参照ポインタ
94 * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
95 * @param m_idx モンスターID
96 * @param o_ptr オブジェクトへの参照ポインタ
97 * @param is_special_object モンスターが拾えないアイテム (アーティファクト等)であればTRUE
98 * @param ny 移動後の、モンスターのY座標
99 * @param nx 移動後の、モンスターのX座標
100 * @param m_name モンスター名
101 * @param o_name アイテム名
102 * @param this_o_idx モンスターが乗ったオブジェクトID
104 static void monster_pickup_object(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, object_type *o_ptr, bool is_special_object,
105 POSITION ny, POSITION nx, GAME_TEXT *m_name, GAME_TEXT *o_name, OBJECT_IDX this_o_idx)
107 monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
108 monster_race *r_ptr = &r_info[m_ptr->r_idx];
109 if (is_special_object) {
110 if (turn_flags_ptr->do_take && (r_ptr->flags2 & RF2_STUPID)) {
111 turn_flags_ptr->did_take_item = TRUE;
112 if (m_ptr->ml && player_can_see_bold(target_ptr, ny, nx)) {
113 msg_format(_("%^sは%sを拾おうとしたが、だめだった。", "%^s tries to pick up %s, but fails."), m_name, o_name);
120 if (turn_flags_ptr->do_take) {
121 turn_flags_ptr->did_take_item = TRUE;
122 if (player_can_see_bold(target_ptr, ny, nx)) {
123 msg_format(_("%^sが%sを拾った。", "%^s picks up %s."), m_name, o_name);
126 excise_object_idx(target_ptr->current_floor_ptr, this_o_idx);
127 o_ptr->marked &= OM_TOUCHED;
128 o_ptr->iy = o_ptr->ix = 0;
129 o_ptr->held_m_idx = m_idx;
130 m_ptr->hold_o_idx_list.push_front(this_o_idx);
137 turn_flags_ptr->did_kill_item = TRUE;
138 if (player_has_los_bold(target_ptr, ny, nx)) {
139 msg_format(_("%^sが%sを破壊した。", "%^s destroys %s."), m_name, o_name);
142 delete_object_idx(target_ptr, this_o_idx);
146 * @brief モンスターの移動に伴うオブジェクト処理 (アイテム破壊等)
147 * @param target_ptr プレーヤーへの参照ポインタ
148 * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
149 * @param m_idx モンスターID
150 * @param ny 移動後の、モンスターのY座標
151 * @param nx 移動後の、モンスターのX座標
153 void update_object_by_monster_movement(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION ny, POSITION nx)
155 monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
156 monster_race *r_ptr = &r_info[m_ptr->r_idx];
158 g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
160 turn_flags_ptr->do_take = (r_ptr->flags2 & RF2_TAKE_ITEM) != 0;
161 for (auto it = g_ptr->o_idx_list.begin(); it != g_ptr->o_idx_list.end();) {
162 BIT_FLAGS flgs[TR_FLAG_SIZE], flg2 = 0L, flg3 = 0L, flgr = 0L;
163 GAME_TEXT m_name[MAX_NLEN], o_name[MAX_NLEN];
164 OBJECT_IDX this_o_idx = *it++;
165 object_type *o_ptr = &target_ptr->current_floor_ptr->o_list[this_o_idx];
167 if (turn_flags_ptr->do_take) {
168 /* Skip gold, corpse and statue */
169 if (o_ptr->tval == TV_GOLD || (o_ptr->tval == TV_CORPSE) || (o_ptr->tval == TV_STATUE))
173 object_flags(target_ptr, o_ptr, flgs);
174 describe_flavor(target_ptr, o_name, o_ptr, 0);
175 monster_desc(target_ptr, m_name, m_ptr, MD_INDEF_HIDDEN);
176 update_object_flags(flgs, &flg2, &flg3, &flgr);
178 bool is_special_object = object_is_artifact(o_ptr) || ((r_ptr->flags3 & flg3) != 0) || ((r_ptr->flags2 & flg2) != 0)
179 || (((~(r_ptr->flagsr) & flgr) != 0) && !(r_ptr->flagsr & RFR_RES_ALL));
180 monster_pickup_object(target_ptr, turn_flags_ptr, m_idx, o_ptr, is_special_object, ny, nx, m_name, o_name, this_o_idx);
185 * @brief モンスターが盗みや拾いで確保していたアイテムを全てドロップさせる / Drop all items carried by a monster
186 * @param player_ptr プレーヤーへの参照ポインタ
187 * @param m_ptr モンスター参照ポインタ
189 void monster_drop_carried_objects(player_type *player_ptr, monster_type *m_ptr)
191 for (auto it = m_ptr->hold_o_idx_list.begin(); it != m_ptr->hold_o_idx_list.end();) {
195 const OBJECT_IDX this_o_idx = *it++;
196 o_ptr = &player_ptr->current_floor_ptr->o_list[this_o_idx];
198 q_ptr->copy_from(o_ptr);
199 q_ptr->held_m_idx = 0;
200 delete_object_idx(player_ptr, this_o_idx);
201 (void)drop_near(player_ptr, q_ptr, -1, m_ptr->fy, m_ptr->fx);
204 m_ptr->hold_o_idx_list.clear();