… | |
… | |
267 | |
267 | |
268 | return 0; |
268 | return 0; |
269 | } |
269 | } |
270 | |
270 | |
271 | /* radius, distance => lightness adjust */ |
271 | /* radius, distance => lightness adjust */ |
272 | static sint8 darkness[MAX_LIGHT_RADIUS * 2 + 1][MAX_LIGHT_RADIUS * 3 / 2 + 1]; |
272 | static sint8 light_atten[MAX_LIGHT_RADIUS * 2 + 1][MAX_LIGHT_RADIUS * 3 / 2 + 1]; |
273 | |
273 | |
274 | static struct darkness_init |
274 | static struct los_init |
275 | { |
275 | { |
276 | darkness_init () |
276 | los_init () |
277 | { |
277 | { |
278 | for (int radius = -MAX_LIGHT_RADIUS; radius <= MAX_LIGHT_RADIUS; ++radius) |
278 | for (int radius = -MAX_LIGHT_RADIUS; radius <= MAX_LIGHT_RADIUS; ++radius) |
279 | for (int distance = 0; distance <= MAX_LIGHT_RADIUS * 3 / 2; ++distance) |
279 | for (int distance = 0; distance <= MAX_LIGHT_RADIUS * 3 / 2; ++distance) |
280 | { |
280 | { |
281 | // max intensity |
281 | // max intensity |
282 | int intensity = min (LOS_MAX, abs (radius) + 1); |
282 | int intensity = min (LOS_MAX, abs (radius) + 1); |
283 | |
283 | |
284 | // actual intensity |
284 | // actual intensity |
285 | intensity = max (0, lerp_rd (distance, 0, abs (radius) + 1, intensity, 0)); |
285 | intensity = max (0, lerp_rd (distance, 0, abs (radius) + 1, intensity, 0)); |
286 | |
286 | |
287 | darkness [radius + MAX_LIGHT_RADIUS][distance] = radius < 0 |
287 | light_atten [radius + MAX_LIGHT_RADIUS][distance] = radius < 0 |
288 | ? min (3, intensity) |
288 | ? min (3, intensity) |
289 | : LOS_MAX - intensity; |
289 | : LOS_MAX - intensity; |
290 | } |
290 | } |
291 | } |
291 | } |
292 | } darkness_init; |
292 | } los_init; |
293 | |
293 | |
294 | sint8 |
294 | sint8 |
295 | los_brighten (sint8 b, sint8 l) |
295 | los_brighten (sint8 b, sint8 l) |
296 | { |
296 | { |
297 | return b == LOS_BLOCKED ? b : min (b, l); |
297 | return b == LOS_BLOCKED ? b : min (b, l); |
… | |
… | |
303 | return max (b, l); |
303 | return max (b, l); |
304 | } |
304 | } |
305 | |
305 | |
306 | template<sint8 change_it (sint8, sint8)> |
306 | template<sint8 change_it (sint8, sint8)> |
307 | static void |
307 | static void |
308 | apply_light (object *op, int dx, int dy, int light, const sint8 *darkness_table) |
308 | apply_light (object *op, int dx, int dy, int light, const sint8 *atten_table) |
309 | { |
309 | { |
310 | // min or max the circular area around basex, basey |
310 | // min or max the circular area around basex, basey |
311 | player *pl = op->contr; |
311 | player *pl = op->contr; |
312 | |
312 | |
313 | dx += LOS_X0; |
313 | dx += LOS_X0; |
… | |
… | |
322 | int ay1 = min (dy + light, LOS_Y0 + hy); |
322 | int ay1 = min (dy + light, LOS_Y0 + hy); |
323 | |
323 | |
324 | for (int ax = ax0; ax <= ax1; ax++) |
324 | for (int ax = ax0; ax <= ax1; ax++) |
325 | for (int ay = ay0; ay <= ay1; ay++) |
325 | for (int ay = ay0; ay <= ay1; ay++) |
326 | pl->los[ax][ay] = |
326 | pl->los[ax][ay] = |
327 | change_it (pl->los[ax][ay], darkness_table [idistance (ax - dx, ay - dy)]); |
327 | change_it (pl->los[ax][ay], atten_table [idistance (ax - dx, ay - dy)]); |
328 | } |
328 | } |
329 | |
329 | |
330 | /* add light, by finding all (non-null) nearby light sources, then |
330 | /* add light, by finding all (non-null) nearby light sources, then |
331 | * mark those squares specially. |
331 | * mark those squares specially. |
332 | */ |
332 | */ |
… | |
… | |
394 | |
394 | |
395 | if (expect_false (light)) |
395 | if (expect_false (light)) |
396 | if (light < 0) |
396 | if (light < 0) |
397 | pass2 = 1; |
397 | pass2 = 1; |
398 | else |
398 | else |
399 | apply_light<los_brighten> (op, x - op->x, y - op->y, light, darkness [light + MAX_LIGHT_RADIUS]); |
399 | apply_light<los_brighten> (op, x - op->x, y - op->y, light, light_atten [light + MAX_LIGHT_RADIUS]); |
400 | } |
400 | } |
401 | |
401 | |
402 | /* grant some vision to the player, based on the darklevel */ |
402 | /* grant some vision to the player, based on the darklevel */ |
403 | /* for outdoor maps, ensure some mininum visibility radius */ |
|
|
404 | { |
403 | { |
405 | int light = clamp (MAX_DARKNESS - darklevel, op->map->outdoor ? 2 : 0, MAX_LIGHT_RADIUS); |
404 | int light = clamp (MAX_DARKNESS - darklevel, 0, MAX_LIGHT_RADIUS); |
406 | |
405 | |
407 | apply_light<los_brighten> (op, 0, 0, light, darkness [light + MAX_LIGHT_RADIUS]); |
406 | apply_light<los_brighten> (op, 0, 0, light, light_atten [light + MAX_LIGHT_RADIUS]); |
408 | } |
407 | } |
409 | } |
408 | } |
410 | |
409 | |
411 | // possibly do 2nd pass for rare negative glow radii |
410 | // possibly do 2nd pass for rare negative glow radii |
412 | // for effect, those are always considered to be stronger than anything else |
411 | // for effect, those are always considered to be stronger than anything else |
… | |
… | |
425 | mapspace &ms = m->at (nx, ny); |
424 | mapspace &ms = m->at (nx, ny); |
426 | ms.update (); |
425 | ms.update (); |
427 | sint8 light = ms.light; |
426 | sint8 light = ms.light; |
428 | |
427 | |
429 | if (expect_false (light < 0)) |
428 | if (expect_false (light < 0)) |
430 | apply_light<los_darken> (op, x - op->x, y - op->y, -light, darkness [light + MAX_LIGHT_RADIUS]); |
429 | apply_light<los_darken> (op, x - op->x, y - op->y, -light, light_atten [light + MAX_LIGHT_RADIUS]); |
431 | } |
430 | } |
432 | } |
431 | } |
433 | |
432 | |
434 | /* blinded_sight() - sets all viewable squares to blocked except |
433 | /* blinded_sight() - sets all viewable squares to blocked except |
435 | * for the one the central one that the player occupies. A little |
434 | * for the one the central one that the player occupies. A little |