1 #include "monster-floor/monster-lite.h"
2 #include "dungeon/dungeon-flag-types.h"
3 #include "floor/cave.h"
4 #include "grid/feature-flag-types.h"
6 #include "monster-floor/monster-lite-util.h"
7 #include "monster-race/monster-race.h"
8 #include "monster-race/race-brightness-flags.h"
9 #include "monster-race/race-flags7.h"
10 #include "monster/monster-status.h"
11 #include "player-base/player-class.h"
12 #include "player-info/ninja-data-type.h"
13 #include "player/special-defense-types.h"
14 #include "system/dungeon-info.h"
15 #include "system/floor-type-definition.h"
16 #include "system/grid-type-definition.h"
17 #include "system/monster-entity.h"
18 #include "system/monster-race-info.h"
19 #include "system/player-type-definition.h"
20 #include "system/redrawing-flags-updater.h"
21 #include "util/point-2d.h"
22 #include "view/display-messages.h"
23 #include "world/world.h"
27 * @brief モンスターによる光量状態更新 / Add a square to the changes array
28 * @param player_ptr プレイヤーへの参照ポインタ
29 * @param points 座標たちを記録する配列
33 static void update_monster_lite(
34 PlayerType *const player_ptr, std::vector<Pos2D> &points, const POSITION y, const POSITION x, const monster_lite_type *const ml_ptr)
39 g_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
40 if ((g_ptr->info & (CAVE_MNLT | CAVE_VIEW)) != CAVE_VIEW) {
44 if (!feat_supports_los(g_ptr->feat)) {
45 if (((y < player_ptr->y) && (y > ml_ptr->mon_fy)) || ((y > player_ptr->y) && (y < ml_ptr->mon_fy))) {
46 dpf = player_ptr->y - ml_ptr->mon_fy;
47 d = y - ml_ptr->mon_fy;
48 midpoint = ml_ptr->mon_fx + ((player_ptr->x - ml_ptr->mon_fx) * std::abs(d)) / std::abs(dpf);
50 if (!cave_los_bold(player_ptr->current_floor_ptr, y, x + 1)) {
53 } else if (x > midpoint) {
54 if (!cave_los_bold(player_ptr->current_floor_ptr, y, x - 1)) {
57 } else if (ml_ptr->mon_invis) {
62 if (((x < player_ptr->x) && (x > ml_ptr->mon_fx)) || ((x > player_ptr->x) && (x < ml_ptr->mon_fx))) {
63 dpf = player_ptr->x - ml_ptr->mon_fx;
64 d = x - ml_ptr->mon_fx;
65 midpoint = ml_ptr->mon_fy + ((player_ptr->y - ml_ptr->mon_fy) * std::abs(d)) / std::abs(dpf);
67 if (!cave_los_bold(player_ptr->current_floor_ptr, y + 1, x)) {
70 } else if (y > midpoint) {
71 if (!cave_los_bold(player_ptr->current_floor_ptr, y - 1, x)) {
74 } else if (ml_ptr->mon_invis) {
80 if (!(g_ptr->info & CAVE_MNDK)) {
81 points.emplace_back(y, x);
83 g_ptr->info &= ~(CAVE_MNDK);
86 g_ptr->info |= CAVE_MNLT;
90 * Add a square to the changes array
92 static void update_monster_dark(
93 PlayerType *const player_ptr, std::vector<Pos2D> &points, const POSITION y, const POSITION x, const monster_lite_type *const ml_ptr)
97 g_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
98 if ((g_ptr->info & (CAVE_LITE | CAVE_MNLT | CAVE_MNDK | CAVE_VIEW)) != CAVE_VIEW) {
102 if (!feat_supports_los(g_ptr->feat) && !g_ptr->cave_has_flag(TerrainCharacteristics::PROJECT)) {
103 if (((y < player_ptr->y) && (y > ml_ptr->mon_fy)) || ((y > player_ptr->y) && (y < ml_ptr->mon_fy))) {
104 dpf = player_ptr->y - ml_ptr->mon_fy;
105 d = y - ml_ptr->mon_fy;
106 midpoint = ml_ptr->mon_fx + ((player_ptr->x - ml_ptr->mon_fx) * std::abs(d)) / std::abs(dpf);
108 if (!cave_los_bold(player_ptr->current_floor_ptr, y, x + 1) && !cave_has_flag_bold(player_ptr->current_floor_ptr, y, x + 1, TerrainCharacteristics::PROJECT)) {
111 } else if (x > midpoint) {
112 if (!cave_los_bold(player_ptr->current_floor_ptr, y, x - 1) && !cave_has_flag_bold(player_ptr->current_floor_ptr, y, x - 1, TerrainCharacteristics::PROJECT)) {
115 } else if (ml_ptr->mon_invis) {
120 if (((x < player_ptr->x) && (x > ml_ptr->mon_fx)) || ((x > player_ptr->x) && (x < ml_ptr->mon_fx))) {
121 dpf = player_ptr->x - ml_ptr->mon_fx;
122 d = x - ml_ptr->mon_fx;
123 midpoint = ml_ptr->mon_fy + ((player_ptr->y - ml_ptr->mon_fy) * std::abs(d)) / std::abs(dpf);
125 if (!cave_los_bold(player_ptr->current_floor_ptr, y + 1, x) && !cave_has_flag_bold(player_ptr->current_floor_ptr, y + 1, x, TerrainCharacteristics::PROJECT)) {
128 } else if (y > midpoint) {
129 if (!cave_los_bold(player_ptr->current_floor_ptr, y - 1, x) && !cave_has_flag_bold(player_ptr->current_floor_ptr, y - 1, x, TerrainCharacteristics::PROJECT)) {
132 } else if (ml_ptr->mon_invis) {
138 points.emplace_back(y, x);
139 g_ptr->info |= CAVE_MNDK;
143 * @brief Update squares illuminated or darkened by monsters.
144 * The CAVE_TEMP and CAVE_XTRA flag are used to store the state during the
145 * updating. Only squares in view of the player, whos state
146 * changes are drawn via lite_spot().
147 * @todo player-status からのみ呼ばれている。しかしあちらは行数が酷いので要調整
149 void update_mon_lite(PlayerType *player_ptr)
152 std::vector<Pos2D> points;
154 void (*add_mon_lite)(PlayerType *, std::vector<Pos2D> &, const POSITION, const POSITION, const monster_lite_type *);
155 auto *floor_ptr = player_ptr->current_floor_ptr;
156 const auto &dungeon = floor_ptr->get_dungeon_definition();
157 auto dis_lim = (dungeon.flags.has(DungeonFeatureType::DARKNESS) && !player_ptr->see_nocto) ? (MAX_PLAYER_SIGHT / 2 + 1) : (MAX_PLAYER_SIGHT + 3);
158 for (int i = 0; i < floor_ptr->mon_lite_n; i++) {
160 g_ptr = &floor_ptr->grid_array[floor_ptr->mon_lite_y[i]][floor_ptr->mon_lite_x[i]];
161 g_ptr->info |= (g_ptr->info & CAVE_MNLT) ? CAVE_TEMP : CAVE_XTRA;
162 g_ptr->info &= ~(CAVE_MNLT | CAVE_MNDK);
165 if (!w_ptr->timewalk_m_idx) {
166 MonsterEntity *m_ptr;
167 MonsterRaceInfo *r_ptr;
168 for (int i = 1; i < floor_ptr->m_max; i++) {
169 m_ptr = &floor_ptr->m_list[i];
170 r_ptr = &monraces_info[m_ptr->r_idx];
171 if (!m_ptr->is_valid() || (m_ptr->cdis > dis_lim)) {
176 if (r_ptr->brightness_flags.has_any_of({ MonsterBrightnessType::HAS_LITE_1, MonsterBrightnessType::SELF_LITE_1 })) {
180 if (r_ptr->brightness_flags.has_any_of({ MonsterBrightnessType::HAS_LITE_2, MonsterBrightnessType::SELF_LITE_2 })) {
184 if (r_ptr->brightness_flags.has_any_of({ MonsterBrightnessType::HAS_DARK_1, MonsterBrightnessType::SELF_DARK_1 })) {
188 if (r_ptr->brightness_flags.has_any_of({ MonsterBrightnessType::HAS_DARK_2, MonsterBrightnessType::SELF_DARK_2 })) {
196 TerrainCharacteristics f_flag;
198 if (r_ptr->brightness_flags.has_none_of({ MonsterBrightnessType::SELF_LITE_1, MonsterBrightnessType::SELF_LITE_2 }) && (m_ptr->is_asleep() || (!floor_ptr->dun_level && is_daytime()) || player_ptr->phase_out)) {
202 if (dungeon.flags.has(DungeonFeatureType::DARKNESS)) {
206 add_mon_lite = update_monster_lite;
207 f_flag = TerrainCharacteristics::LOS;
209 if (r_ptr->brightness_flags.has_none_of({ MonsterBrightnessType::SELF_DARK_1, MonsterBrightnessType::SELF_DARK_2 }) && (m_ptr->is_asleep() || (!floor_ptr->dun_level && !is_daytime()))) {
213 add_mon_lite = update_monster_dark;
214 f_flag = TerrainCharacteristics::PROJECT;
218 monster_lite_type tmp_ml;
219 monster_lite_type *ml_ptr = initialize_monster_lite_type(floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].info, &tmp_ml, m_ptr);
220 add_mon_lite(player_ptr, points, ml_ptr->mon_fy, ml_ptr->mon_fx, ml_ptr);
221 add_mon_lite(player_ptr, points, ml_ptr->mon_fy + 1, ml_ptr->mon_fx, ml_ptr);
222 add_mon_lite(player_ptr, points, ml_ptr->mon_fy - 1, ml_ptr->mon_fx, ml_ptr);
223 add_mon_lite(player_ptr, points, ml_ptr->mon_fy, ml_ptr->mon_fx + 1, ml_ptr);
224 add_mon_lite(player_ptr, points, ml_ptr->mon_fy, ml_ptr->mon_fx - 1, ml_ptr);
225 add_mon_lite(player_ptr, points, ml_ptr->mon_fy + 1, ml_ptr->mon_fx + 1, ml_ptr);
226 add_mon_lite(player_ptr, points, ml_ptr->mon_fy + 1, ml_ptr->mon_fx - 1, ml_ptr);
227 add_mon_lite(player_ptr, points, ml_ptr->mon_fy - 1, ml_ptr->mon_fx + 1, ml_ptr);
228 add_mon_lite(player_ptr, points, ml_ptr->mon_fy - 1, ml_ptr->mon_fx - 1, ml_ptr);
234 if (cave_has_flag_bold(player_ptr->current_floor_ptr, ml_ptr->mon_fy + 1, ml_ptr->mon_fx, f_flag)) {
235 add_mon_lite(player_ptr, points, ml_ptr->mon_fy + 2, ml_ptr->mon_fx + 1, ml_ptr);
236 add_mon_lite(player_ptr, points, ml_ptr->mon_fy + 2, ml_ptr->mon_fx, ml_ptr);
237 add_mon_lite(player_ptr, points, ml_ptr->mon_fy + 2, ml_ptr->mon_fx - 1, ml_ptr);
238 g_ptr = &floor_ptr->grid_array[ml_ptr->mon_fy + 2][ml_ptr->mon_fx];
239 if ((rad == 3) && g_ptr->cave_has_flag(f_flag)) {
240 add_mon_lite(player_ptr, points, ml_ptr->mon_fy + 3, ml_ptr->mon_fx + 1, ml_ptr);
241 add_mon_lite(player_ptr, points, ml_ptr->mon_fy + 3, ml_ptr->mon_fx, ml_ptr);
242 add_mon_lite(player_ptr, points, ml_ptr->mon_fy + 3, ml_ptr->mon_fx - 1, ml_ptr);
246 if (cave_has_flag_bold(player_ptr->current_floor_ptr, ml_ptr->mon_fy - 1, ml_ptr->mon_fx, f_flag)) {
247 add_mon_lite(player_ptr, points, ml_ptr->mon_fy - 2, ml_ptr->mon_fx + 1, ml_ptr);
248 add_mon_lite(player_ptr, points, ml_ptr->mon_fy - 2, ml_ptr->mon_fx, ml_ptr);
249 add_mon_lite(player_ptr, points, ml_ptr->mon_fy - 2, ml_ptr->mon_fx - 1, ml_ptr);
250 g_ptr = &floor_ptr->grid_array[ml_ptr->mon_fy - 2][ml_ptr->mon_fx];
251 if ((rad == 3) && g_ptr->cave_has_flag(f_flag)) {
252 add_mon_lite(player_ptr, points, ml_ptr->mon_fy - 3, ml_ptr->mon_fx + 1, ml_ptr);
253 add_mon_lite(player_ptr, points, ml_ptr->mon_fy - 3, ml_ptr->mon_fx, ml_ptr);
254 add_mon_lite(player_ptr, points, ml_ptr->mon_fy - 3, ml_ptr->mon_fx - 1, ml_ptr);
258 if (cave_has_flag_bold(player_ptr->current_floor_ptr, ml_ptr->mon_fy, ml_ptr->mon_fx + 1, f_flag)) {
259 add_mon_lite(player_ptr, points, ml_ptr->mon_fy + 1, ml_ptr->mon_fx + 2, ml_ptr);
260 add_mon_lite(player_ptr, points, ml_ptr->mon_fy, ml_ptr->mon_fx + 2, ml_ptr);
261 add_mon_lite(player_ptr, points, ml_ptr->mon_fy - 1, ml_ptr->mon_fx + 2, ml_ptr);
262 g_ptr = &floor_ptr->grid_array[ml_ptr->mon_fy][ml_ptr->mon_fx + 2];
263 if ((rad == 3) && g_ptr->cave_has_flag(f_flag)) {
264 add_mon_lite(player_ptr, points, ml_ptr->mon_fy + 1, ml_ptr->mon_fx + 3, ml_ptr);
265 add_mon_lite(player_ptr, points, ml_ptr->mon_fy, ml_ptr->mon_fx + 3, ml_ptr);
266 add_mon_lite(player_ptr, points, ml_ptr->mon_fy - 1, ml_ptr->mon_fx + 3, ml_ptr);
270 if (cave_has_flag_bold(player_ptr->current_floor_ptr, ml_ptr->mon_fy, ml_ptr->mon_fx - 1, f_flag)) {
271 add_mon_lite(player_ptr, points, ml_ptr->mon_fy + 1, ml_ptr->mon_fx - 2, ml_ptr);
272 add_mon_lite(player_ptr, points, ml_ptr->mon_fy, ml_ptr->mon_fx - 2, ml_ptr);
273 add_mon_lite(player_ptr, points, ml_ptr->mon_fy - 1, ml_ptr->mon_fx - 2, ml_ptr);
274 g_ptr = &floor_ptr->grid_array[ml_ptr->mon_fy][ml_ptr->mon_fx - 2];
275 if ((rad == 3) && g_ptr->cave_has_flag(f_flag)) {
276 add_mon_lite(player_ptr, points, ml_ptr->mon_fy + 1, ml_ptr->mon_fx - 3, ml_ptr);
277 add_mon_lite(player_ptr, points, ml_ptr->mon_fy, ml_ptr->mon_fx - 3, ml_ptr);
278 add_mon_lite(player_ptr, points, ml_ptr->mon_fy - 1, ml_ptr->mon_fx - 3, ml_ptr);
286 if (cave_has_flag_bold(player_ptr->current_floor_ptr, ml_ptr->mon_fy + 1, ml_ptr->mon_fx + 1, f_flag)) {
287 add_mon_lite(player_ptr, points, ml_ptr->mon_fy + 2, ml_ptr->mon_fx + 2, ml_ptr);
290 if (cave_has_flag_bold(player_ptr->current_floor_ptr, ml_ptr->mon_fy + 1, ml_ptr->mon_fx - 1, f_flag)) {
291 add_mon_lite(player_ptr, points, ml_ptr->mon_fy + 2, ml_ptr->mon_fx - 2, ml_ptr);
294 if (cave_has_flag_bold(player_ptr->current_floor_ptr, ml_ptr->mon_fy - 1, ml_ptr->mon_fx + 1, f_flag)) {
295 add_mon_lite(player_ptr, points, ml_ptr->mon_fy - 2, ml_ptr->mon_fx + 2, ml_ptr);
298 if (cave_has_flag_bold(player_ptr->current_floor_ptr, ml_ptr->mon_fy - 1, ml_ptr->mon_fx - 1, f_flag)) {
299 add_mon_lite(player_ptr, points, ml_ptr->mon_fy - 2, ml_ptr->mon_fx - 2, ml_ptr);
304 const auto end_temp = size(points);
305 for (int i = 0; i < floor_ptr->mon_lite_n; i++) {
306 POSITION fx = floor_ptr->mon_lite_x[i];
307 POSITION fy = floor_ptr->mon_lite_y[i];
309 g_ptr = &floor_ptr->grid_array[fy][fx];
310 if (g_ptr->info & CAVE_TEMP) {
311 if ((g_ptr->info & (CAVE_VIEW | CAVE_MNLT)) == CAVE_VIEW) {
312 cave_note_and_redraw_later(floor_ptr, fy, fx);
314 } else if ((g_ptr->info & (CAVE_VIEW | CAVE_MNDK)) == CAVE_VIEW) {
315 cave_note_and_redraw_later(floor_ptr, fy, fx);
318 points.emplace_back(fy, fx);
321 floor_ptr->mon_lite_n = 0;
322 for (size_t i = 0; i < end_temp; i++) {
323 const auto &[fy, fx] = points[i];
325 grid_type *const g_ptr = &floor_ptr->grid_array[fy][fx];
326 if (g_ptr->info & CAVE_MNLT) {
327 if ((g_ptr->info & (CAVE_VIEW | CAVE_TEMP)) == CAVE_VIEW) {
328 cave_note_and_redraw_later(floor_ptr, fy, fx);
330 } else if ((g_ptr->info & (CAVE_VIEW | CAVE_XTRA)) == CAVE_VIEW) {
331 cave_note_and_redraw_later(floor_ptr, fy, fx);
334 floor_ptr->mon_lite_x[floor_ptr->mon_lite_n] = fx;
335 floor_ptr->mon_lite_y[floor_ptr->mon_lite_n] = fy;
336 floor_ptr->mon_lite_n++;
339 for (size_t i = end_temp; i < size(points); i++) {
340 const auto &[y, x] = points[i];
341 floor_ptr->grid_array[y][x].info &= ~(CAVE_TEMP | CAVE_XTRA);
344 RedrawingFlagsUpdater::get_instance().set_flag(StatusRecalculatingFlag::DELAY_VISIBILITY);
345 player_ptr->monlite = (floor_ptr->grid_array[player_ptr->y][player_ptr->x].info & CAVE_MNLT) != 0;
346 auto ninja_data = PlayerClass(player_ptr).get_specific_data<ninja_data_type>();
347 if (!ninja_data || !ninja_data->s_stealth) {
348 player_ptr->old_monlite = player_ptr->monlite;
352 if (player_ptr->old_monlite == player_ptr->monlite) {
353 player_ptr->old_monlite = player_ptr->monlite;
357 if (player_ptr->monlite) {
358 msg_print(_("影の覆いが薄れた気がする。", "Your mantle of shadow becomes thin."));
360 msg_print(_("影の覆いが濃くなった!", "Your mantle of shadow is restored to its original darkness."));
363 player_ptr->old_monlite = player_ptr->monlite;
367 * @brief 画面切り替え等でモンスターの灯りを消去する
368 * @param floor_ptr 現在フロアへの参照ポインタ
370 void clear_mon_lite(FloorType *floor_ptr)
372 for (int i = 0; i < floor_ptr->mon_lite_n; i++) {
374 g_ptr = &floor_ptr->grid_array[floor_ptr->mon_lite_y[i]][floor_ptr->mon_lite_x[i]];
375 g_ptr->info &= ~(CAVE_MNLT | CAVE_MNDK);
378 floor_ptr->mon_lite_n = 0;