1 #include "specific-object/torch.h"
2 #include "core/player-update-types.h"
3 #include "dungeon/dungeon-flag-types.h"
4 #include "dungeon/dungeon.h"
5 #include "floor/cave.h"
7 #include "inventory/inventory-slot-types.h"
8 #include "mind/mind-ninja.h"
9 #include "object-enchant/object-ego.h"
10 #include "object-enchant/tr-types.h"
11 #include "object/object-flags.h"
12 #include "player/special-defense-types.h"
13 #include "sv-definition/sv-lite-types.h"
14 #include "system/floor-type-definition.h"
15 #include "system/grid-type-definition.h"
16 #include "system/object-type-definition.h"
17 #include "system/player-type-definition.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(object_type *o_ptr)
29 return (o_ptr->tval == ItemKindType::LITE) && (o_ptr->sval == SV_LITE_TORCH) && (o_ptr->xtra4 > 0);
33 * @brief 投擲時たいまつに投げやすい/焼棄/アンデッドスレイの特別効果を返す。
34 * Torches have special abilities when they are flaming.
35 * @param o_ptr 投擲するオブジェクトの構造体参照ポインタ
36 * @param flgs 特別に追加するフラグを返す参照ポインタ
38 void torch_flags(object_type *o_ptr, TrFlags &flgs)
40 if (!is_active_torch(o_ptr))
43 flgs.set(TR_BRAND_FIRE);
44 flgs.set(TR_KILL_UNDEAD);
49 * @brief 投擲時たいまつにダイスを与える。
50 * Torches have special abilities when they are flaming.
51 * @param o_ptr 投擲するオブジェクトの構造体参照ポインタ
52 * @param dd 特別なダイス数を返す参照ポインタ
53 * @param ds 特別なダイス面数を返す参照ポインタ
55 void torch_dice(object_type *o_ptr, DICE_NUMBER *dd, DICE_SID *ds)
57 if (!is_active_torch(o_ptr))
65 * @brief 投擲時命中したたいまつの寿命を縮める。
66 * Torches have special abilities when they are flaming.
67 * @param o_ptr 投擲するオブジェクトの構造体参照ポインタ
69 void torch_lost_fuel(object_type *o_ptr)
71 if (!is_active_torch(o_ptr))
74 o_ptr->xtra4 -= (FUEL_TORCH / 25);
80 * @brief プレイヤーの光源半径を計算する / Extract and set the current "lite radius"
82 * SWD: Experimental modification: multiple light sources have additive effect.
84 void update_lite_radius(PlayerType *player_ptr)
86 player_ptr->cur_lite = 0;
87 for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
89 o_ptr = &player_ptr->inventory_list[i];
90 auto flgs = object_flags(o_ptr);
95 if (o_ptr->name2 == EGO_LITE_SHINE)
96 player_ptr->cur_lite++;
98 if (flgs.has_not(TR_DARK_SOURCE)) {
99 if (o_ptr->tval == ItemKindType::LITE) {
100 if ((o_ptr->sval == SV_LITE_TORCH) && !(o_ptr->xtra4 > 0))
103 if ((o_ptr->sval == SV_LITE_LANTERN) && !(o_ptr->xtra4 > 0))
109 if (flgs.has(TR_LITE_1) && flgs.has_not(TR_DARK_SOURCE))
112 if (flgs.has(TR_LITE_2) && flgs.has_not(TR_DARK_SOURCE))
115 if (flgs.has(TR_LITE_3) && flgs.has_not(TR_DARK_SOURCE))
118 if (flgs.has(TR_LITE_M1))
121 if (flgs.has(TR_LITE_M2))
124 if (flgs.has(TR_LITE_M3))
127 player_ptr->cur_lite += rad;
130 if (d_info[player_ptr->dungeon_idx].flags.has(DungeonFeatureType::DARKNESS) && player_ptr->cur_lite > 1)
131 player_ptr->cur_lite = 1;
133 if (player_ptr->cur_lite <= 0 && player_ptr->lite)
134 player_ptr->cur_lite++;
136 if (player_ptr->cur_lite > 14)
137 player_ptr->cur_lite = 14;
139 if (player_ptr->cur_lite < 0)
140 player_ptr->cur_lite = 0;
142 if (player_ptr->old_lite == player_ptr->cur_lite)
145 player_ptr->update |= PU_LITE | PU_MON_LITE | PU_MONSTERS;
146 player_ptr->old_lite = player_ptr->cur_lite;
148 if (player_ptr->cur_lite > 0) {
149 set_superstealth(player_ptr, false);
154 * Update the set of grids "illuminated" by the player's lite.
156 * This routine needs to use the results of "update_view()"
158 * Note that "blindness" does NOT affect "torch lite". Be careful!
160 * We optimize most lites (all non-artifact lites) by using "obvious"
161 * facts about the results of "small" lite radius, and we attempt to
162 * list the "nearby" grids before the more "distant" ones in the
163 * array of torch-lit grids.
165 * We assume that "radius zero" lite is in fact no lite at all.
167 * Torch Lantern Artifacts
177 void update_lite(PlayerType *player_ptr)
179 // 前回照らされていた座標たちを格納する配列。
180 std::vector<Pos2D> points;
182 POSITION p = player_ptr->cur_lite;
183 floor_type *const floor_ptr = player_ptr->current_floor_ptr;
186 for (int i = 0; i < floor_ptr->lite_n; i++) {
187 const POSITION y = floor_ptr->lite_y[i];
188 const POSITION x = floor_ptr->lite_x[i];
190 floor_ptr->grid_array[y][x].info &= ~(CAVE_LITE);
191 floor_ptr->grid_array[y][x].info |= CAVE_TEMP;
193 points.emplace_back(y, x);
196 floor_ptr->lite_n = 0;
198 cave_lite_hack(floor_ptr, player_ptr->y, player_ptr->x);
199 cave_lite_hack(floor_ptr, player_ptr->y + 1, player_ptr->x);
200 cave_lite_hack(floor_ptr, player_ptr->y - 1, player_ptr->x);
201 cave_lite_hack(floor_ptr, player_ptr->y, player_ptr->x + 1);
202 cave_lite_hack(floor_ptr, player_ptr->y, player_ptr->x - 1);
203 cave_lite_hack(floor_ptr, player_ptr->y + 1, player_ptr->x + 1);
204 cave_lite_hack(floor_ptr, player_ptr->y + 1, player_ptr->x - 1);
205 cave_lite_hack(floor_ptr, player_ptr->y - 1, player_ptr->x + 1);
206 cave_lite_hack(floor_ptr, player_ptr->y - 1, player_ptr->x - 1);
210 if (cave_los_bold(floor_ptr, player_ptr->y + 1, player_ptr->x)) {
211 cave_lite_hack(floor_ptr, player_ptr->y + 2, player_ptr->x);
212 cave_lite_hack(floor_ptr, player_ptr->y + 2, player_ptr->x + 1);
213 cave_lite_hack(floor_ptr, player_ptr->y + 2, player_ptr->x - 1);
216 if (cave_los_bold(floor_ptr, player_ptr->y - 1, player_ptr->x)) {
217 cave_lite_hack(floor_ptr, player_ptr->y - 2, player_ptr->x);
218 cave_lite_hack(floor_ptr, player_ptr->y - 2, player_ptr->x + 1);
219 cave_lite_hack(floor_ptr, player_ptr->y - 2, player_ptr->x - 1);
222 if (cave_los_bold(floor_ptr, player_ptr->y, player_ptr->x + 1)) {
223 cave_lite_hack(floor_ptr, player_ptr->y, player_ptr->x + 2);
224 cave_lite_hack(floor_ptr, player_ptr->y + 1, player_ptr->x + 2);
225 cave_lite_hack(floor_ptr, player_ptr->y - 1, player_ptr->x + 2);
228 if (cave_los_bold(floor_ptr, player_ptr->y, player_ptr->x - 1)) {
229 cave_lite_hack(floor_ptr, player_ptr->y, player_ptr->x - 2);
230 cave_lite_hack(floor_ptr, player_ptr->y + 1, player_ptr->x - 2);
231 cave_lite_hack(floor_ptr, player_ptr->y - 1, player_ptr->x - 2);
240 if (cave_los_bold(floor_ptr, player_ptr->y + 1, player_ptr->x + 1))
241 cave_lite_hack(floor_ptr, player_ptr->y + 2, player_ptr->x + 2);
243 if (cave_los_bold(floor_ptr, player_ptr->y + 1, player_ptr->x - 1))
244 cave_lite_hack(floor_ptr, player_ptr->y + 2, player_ptr->x - 2);
246 if (cave_los_bold(floor_ptr, player_ptr->y - 1, player_ptr->x + 1))
247 cave_lite_hack(floor_ptr, player_ptr->y - 2, player_ptr->x + 2);
249 if (cave_los_bold(floor_ptr, player_ptr->y - 1, player_ptr->x - 1))
250 cave_lite_hack(floor_ptr, player_ptr->y - 2, player_ptr->x - 2);
252 POSITION min_y = player_ptr->y - p;
256 POSITION max_y = player_ptr->y + p;
257 if (max_y > floor_ptr->height - 1)
258 max_y = floor_ptr->height - 1;
260 POSITION min_x = player_ptr->x - p;
264 POSITION max_x = player_ptr->x + p;
265 if (max_x > floor_ptr->width - 1)
266 max_x = floor_ptr->width - 1;
268 for (POSITION y = min_y; y <= max_y; y++) {
269 for (POSITION x = min_x; x <= max_x; x++) {
270 int dy = (player_ptr->y > y) ? (player_ptr->y - y) : (y - player_ptr->y);
271 int dx = (player_ptr->x > x) ? (player_ptr->x - x) : (x - player_ptr->x);
272 if ((dy <= 2) && (dx <= 2))
275 d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
279 if (floor_ptr->grid_array[y][x].info & CAVE_VIEW)
280 cave_lite_hack(floor_ptr, y, x);
285 for (int i = 0; i < floor_ptr->lite_n; i++) {
286 POSITION y = floor_ptr->lite_y[i];
287 POSITION x = floor_ptr->lite_x[i];
288 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
289 if (g_ptr->info & CAVE_TEMP)
292 cave_note_and_redraw_later(floor_ptr, y, x);
295 // 前回照らされていた座標たちのうち、状態が変わったものについて再描画フラグを立てる。
296 for (const auto &[y, x] : points) {
297 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
298 g_ptr->info &= ~(CAVE_TEMP);
299 if (g_ptr->info & CAVE_LITE)
302 cave_redraw_later(floor_ptr, y, x);
305 player_ptr->update |= PU_DELAY_VIS;