1 #include "specific-object/torch.h"
2 #include "dungeon/dungeon-flag-types.h"
3 #include "floor/cave.h"
5 #include "inventory/inventory-slot-types.h"
6 #include "mind/mind-ninja.h"
7 #include "object-enchant/object-ego.h"
8 #include "object-enchant/tr-types.h"
9 #include "object/tval-types.h"
10 #include "player/special-defense-types.h"
11 #include "sv-definition/sv-lite-types.h"
12 #include "system/dungeon-info.h"
13 #include "system/floor-type-definition.h"
14 #include "system/grid-type-definition.h"
15 #include "system/item-entity.h"
16 #include "system/player-type-definition.h"
17 #include "system/redrawing-flags-updater.h"
18 #include "util/bit-flags-calculator.h"
19 #include "util/point-2d.h"
23 * @brief 該当オブジェクトが残量アリの松明か否かを判定。
24 * @param o_ptr オブジェクトの構造体参照ポインタ
25 * @return 残量アリの松明ならtrue
27 bool is_active_torch(ItemEntity *o_ptr)
29 return (o_ptr->bi_key == BaseitemKey(ItemKindType::LITE, SV_LITE_TORCH)) && (o_ptr->fuel > 0);
33 * @brief 投擲時たいまつに投げやすい/焼棄/アンデッドスレイの特別効果を返す。
34 * Torches have special abilities when they are flaming.
35 * @param o_ptr 投擲するオブジェクトの構造体参照ポインタ
36 * @param flags 特別に追加するフラグを返す参照ポインタ
38 void torch_flags(ItemEntity *o_ptr, TrFlags &flags)
40 if (!is_active_torch(o_ptr)) {
44 flags.set(TR_BRAND_FIRE);
45 flags.set(TR_KILL_UNDEAD);
50 * @brief 投擲時たいまつにダイスを与える。
51 * Torches have special abilities when they are flaming.
52 * @param o_ptr 投擲するオブジェクトの構造体参照ポインタ
53 * @param dd 特別なダイス数を返す参照ポインタ
54 * @param ds 特別なダイス面数を返す参照ポインタ
56 void torch_dice(ItemEntity *o_ptr, DICE_NUMBER *dd, DICE_SID *ds)
58 if (!is_active_torch(o_ptr)) {
67 * @brief 投擲時命中したたいまつの寿命を縮める。
68 * Torches have special abilities when they are flaming.
69 * @param o_ptr 投擲するオブジェクトの構造体参照ポインタ
71 void torch_lost_fuel(ItemEntity *o_ptr)
73 if (!is_active_torch(o_ptr)) {
77 o_ptr->fuel -= FUEL_TORCH / 25;
78 if (o_ptr->fuel < 0) {
84 * @brief プレイヤーの光源半径を計算する / Extract and set the current "lite radius"
86 * SWD: Experimental modification: multiple light sources have additive effect.
88 void update_lite_radius(PlayerType *player_ptr)
90 player_ptr->cur_lite = 0;
91 for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
93 o_ptr = &player_ptr->inventory_list[i];
94 auto flags = o_ptr->get_flags();
96 if (!o_ptr->is_valid()) {
100 if (o_ptr->ego_idx == EgoType::LITE_SHINE) {
101 player_ptr->cur_lite++;
104 if (flags.has_not(TR_DARK_SOURCE)) {
105 if (o_ptr->bi_key.tval() == ItemKindType::LITE) {
106 const auto sval = o_ptr->bi_key.sval();
107 if ((sval == SV_LITE_TORCH) && (o_ptr->fuel <= 0)) {
111 if ((sval == SV_LITE_LANTERN) && (o_ptr->fuel <= 0)) {
118 if (flags.has(TR_LITE_1) && flags.has_not(TR_DARK_SOURCE)) {
122 if (flags.has(TR_LITE_2) && flags.has_not(TR_DARK_SOURCE)) {
126 if (flags.has(TR_LITE_3) && flags.has_not(TR_DARK_SOURCE)) {
130 if (flags.has(TR_LITE_M1)) {
134 if (flags.has(TR_LITE_M2)) {
138 if (flags.has(TR_LITE_M3)) {
142 player_ptr->cur_lite += rad;
145 if (player_ptr->current_floor_ptr->get_dungeon_definition().flags.has(DungeonFeatureType::DARKNESS) && player_ptr->cur_lite > 1) {
146 player_ptr->cur_lite = 1;
149 if (player_ptr->cur_lite <= 0 && player_ptr->lite) {
150 player_ptr->cur_lite++;
153 if (player_ptr->cur_lite > 14) {
154 player_ptr->cur_lite = 14;
157 if (player_ptr->cur_lite < 0) {
158 player_ptr->cur_lite = 0;
161 if (player_ptr->old_lite == player_ptr->cur_lite) {
165 static constexpr auto flags = {
166 StatusRecalculatingFlag::LITE,
167 StatusRecalculatingFlag::MONSTER_LITE,
168 StatusRecalculatingFlag::MONSTER_STATUSES,
170 RedrawingFlagsUpdater::get_instance().set_flags(flags);
171 player_ptr->old_lite = player_ptr->cur_lite;
172 if (player_ptr->cur_lite > 0) {
173 set_superstealth(player_ptr, false);
178 * Update the set of grids "illuminated" by the player's lite.
180 * This routine needs to use the results of "update_view()"
182 * Note that "blindness" does NOT affect "torch lite". Be careful!
184 * We optimize most lites (all non-artifact lites) by using "obvious"
185 * facts about the results of "small" lite radius, and we attempt to
186 * list the "nearby" grids before the more "distant" ones in the
187 * array of torch-lit grids.
189 * We assume that "radius zero" lite is in fact no lite at all.
191 * Torch Lantern Artifacts
201 void update_lite(PlayerType *player_ptr)
203 // 前回照らされていた座標たちを格納する配列。
204 std::vector<Pos2D> points;
206 POSITION p = player_ptr->cur_lite;
207 FloorType *const floor_ptr = player_ptr->current_floor_ptr;
210 for (int i = 0; i < floor_ptr->lite_n; i++) {
211 const POSITION y = floor_ptr->lite_y[i];
212 const POSITION x = floor_ptr->lite_x[i];
214 floor_ptr->grid_array[y][x].info &= ~(CAVE_LITE);
215 floor_ptr->grid_array[y][x].info |= CAVE_TEMP;
217 points.emplace_back(y, x);
220 floor_ptr->lite_n = 0;
222 cave_lite_hack(floor_ptr, player_ptr->y, player_ptr->x);
223 cave_lite_hack(floor_ptr, player_ptr->y + 1, player_ptr->x);
224 cave_lite_hack(floor_ptr, player_ptr->y - 1, player_ptr->x);
225 cave_lite_hack(floor_ptr, player_ptr->y, player_ptr->x + 1);
226 cave_lite_hack(floor_ptr, player_ptr->y, player_ptr->x - 1);
227 cave_lite_hack(floor_ptr, player_ptr->y + 1, player_ptr->x + 1);
228 cave_lite_hack(floor_ptr, player_ptr->y + 1, player_ptr->x - 1);
229 cave_lite_hack(floor_ptr, player_ptr->y - 1, player_ptr->x + 1);
230 cave_lite_hack(floor_ptr, player_ptr->y - 1, player_ptr->x - 1);
234 if (cave_los_bold(floor_ptr, player_ptr->y + 1, player_ptr->x)) {
235 cave_lite_hack(floor_ptr, player_ptr->y + 2, player_ptr->x);
236 cave_lite_hack(floor_ptr, player_ptr->y + 2, player_ptr->x + 1);
237 cave_lite_hack(floor_ptr, player_ptr->y + 2, player_ptr->x - 1);
240 if (cave_los_bold(floor_ptr, player_ptr->y - 1, player_ptr->x)) {
241 cave_lite_hack(floor_ptr, player_ptr->y - 2, player_ptr->x);
242 cave_lite_hack(floor_ptr, player_ptr->y - 2, player_ptr->x + 1);
243 cave_lite_hack(floor_ptr, player_ptr->y - 2, player_ptr->x - 1);
246 if (cave_los_bold(floor_ptr, player_ptr->y, player_ptr->x + 1)) {
247 cave_lite_hack(floor_ptr, player_ptr->y, player_ptr->x + 2);
248 cave_lite_hack(floor_ptr, player_ptr->y + 1, player_ptr->x + 2);
249 cave_lite_hack(floor_ptr, player_ptr->y - 1, player_ptr->x + 2);
252 if (cave_los_bold(floor_ptr, player_ptr->y, player_ptr->x - 1)) {
253 cave_lite_hack(floor_ptr, player_ptr->y, player_ptr->x - 2);
254 cave_lite_hack(floor_ptr, player_ptr->y + 1, player_ptr->x - 2);
255 cave_lite_hack(floor_ptr, player_ptr->y - 1, player_ptr->x - 2);
265 if (cave_los_bold(floor_ptr, player_ptr->y + 1, player_ptr->x + 1)) {
266 cave_lite_hack(floor_ptr, player_ptr->y + 2, player_ptr->x + 2);
269 if (cave_los_bold(floor_ptr, player_ptr->y + 1, player_ptr->x - 1)) {
270 cave_lite_hack(floor_ptr, player_ptr->y + 2, player_ptr->x - 2);
273 if (cave_los_bold(floor_ptr, player_ptr->y - 1, player_ptr->x + 1)) {
274 cave_lite_hack(floor_ptr, player_ptr->y - 2, player_ptr->x + 2);
277 if (cave_los_bold(floor_ptr, player_ptr->y - 1, player_ptr->x - 1)) {
278 cave_lite_hack(floor_ptr, player_ptr->y - 2, player_ptr->x - 2);
281 POSITION min_y = player_ptr->y - p;
286 POSITION max_y = player_ptr->y + p;
287 if (max_y > floor_ptr->height - 1) {
288 max_y = floor_ptr->height - 1;
291 POSITION min_x = player_ptr->x - p;
296 POSITION max_x = player_ptr->x + p;
297 if (max_x > floor_ptr->width - 1) {
298 max_x = floor_ptr->width - 1;
301 for (POSITION y = min_y; y <= max_y; y++) {
302 for (POSITION x = min_x; x <= max_x; x++) {
303 int dy = (player_ptr->y > y) ? (player_ptr->y - y) : (y - player_ptr->y);
304 int dx = (player_ptr->x > x) ? (player_ptr->x - x) : (x - player_ptr->x);
305 if ((dy <= 2) && (dx <= 2)) {
309 d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
314 if (floor_ptr->grid_array[y][x].info & CAVE_VIEW) {
315 cave_lite_hack(floor_ptr, y, x);
321 for (int i = 0; i < floor_ptr->lite_n; i++) {
322 POSITION y = floor_ptr->lite_y[i];
323 POSITION x = floor_ptr->lite_x[i];
324 auto *g_ptr = &floor_ptr->grid_array[y][x];
325 if (g_ptr->info & CAVE_TEMP) {
329 cave_note_and_redraw_later(floor_ptr, y, x);
332 // 前回照らされていた座標たちのうち、状態が変わったものについて再描画フラグを立てる。
333 for (const auto &[y, x] : points) {
334 auto *g_ptr = &floor_ptr->grid_array[y][x];
335 g_ptr->info &= ~(CAVE_TEMP);
336 if (g_ptr->info & CAVE_LITE) {
340 cave_redraw_later(floor_ptr, y, x);
343 RedrawingFlagsUpdater::get_instance().set_flag(StatusRecalculatingFlag::DELAY_VISIBILITY);