… | |
… | |
274 | if (op->contr->blocked_los[dx][dy] > 0) /* for any square blocked */ |
274 | if (op->contr->blocked_los[dx][dy] > 0) /* for any square blocked */ |
275 | op->contr->blocked_los[dx][dy] = -1; |
275 | op->contr->blocked_los[dx][dy] = -1; |
276 | } |
276 | } |
277 | } |
277 | } |
278 | |
278 | |
279 | if (op->map->darkness > 0) /* player is on a dark map */ |
|
|
280 | expand_lighted_sight (op); |
279 | expand_lighted_sight (op); |
281 | |
280 | |
282 | /* clear mark squares */ |
281 | /* clear mark squares */ |
283 | for (int x = 0; x < op->contr->ns->mapx; x++) |
282 | for (int x = 0; x < op->contr->ns->mapx; x++) |
284 | for (int y = 0; y < op->contr->ns->mapy; y++) |
283 | for (int y = 0; y < op->contr->ns->mapy; y++) |
285 | if (op->contr->blocked_los[x][y] < 0) |
284 | if (op->contr->blocked_los[x][y] < 0) |
… | |
… | |
322 | : LOS_MAX - intensity; |
321 | : LOS_MAX - intensity; |
323 | } |
322 | } |
324 | } |
323 | } |
325 | } darkness_init; |
324 | } darkness_init; |
326 | |
325 | |
|
|
326 | sint8 |
|
|
327 | los_brighten (sint8 b, sint8 l) |
|
|
328 | { |
|
|
329 | return b == LOS_BLOCKED ? b : min (b, l); |
|
|
330 | } |
|
|
331 | |
|
|
332 | sint8 |
|
|
333 | los_brighten_blocked (sint8 b, sint8 l) |
|
|
334 | { |
|
|
335 | return min (b, l); |
|
|
336 | } |
|
|
337 | |
|
|
338 | sint8 |
|
|
339 | los_darken (sint8 b, sint8 l) |
|
|
340 | { |
|
|
341 | return max (b, l); |
|
|
342 | } |
|
|
343 | |
|
|
344 | template<sint8 change_it (sint8, sint8)> |
|
|
345 | static void |
|
|
346 | apply_light (object *op, int basex, int basey, int light, const sint8 *darkness_table) |
|
|
347 | { |
|
|
348 | // min or max the ciruclar area around basex, basey |
|
|
349 | player *pl = op->contr; |
|
|
350 | |
|
|
351 | int ax0 = max (0, basex - light); |
|
|
352 | int ay0 = max (0, basey - light); |
|
|
353 | int ax1 = min (basex + light, pl->ns->mapx - 1); |
|
|
354 | int ay1 = min (basey + light, pl->ns->mapy - 1); |
|
|
355 | |
|
|
356 | for (int ax = ax0; ax <= ax1; ax++) |
|
|
357 | for (int ay = ay0; ay <= ay1; ay++) |
|
|
358 | pl->blocked_los[ax][ay] = |
|
|
359 | change_it (pl->blocked_los[ax][ay], darkness_table [idistance (ax - basex, ay - basey)]); |
|
|
360 | } |
|
|
361 | |
|
|
362 | /* add light, by finding all (non-null) nearby light sources, then |
|
|
363 | * mark those squares specially. |
|
|
364 | */ |
327 | static void |
365 | static void |
328 | expand_lighted_sight (object *op) |
366 | expand_lighted_sight (object *op) |
329 | { |
367 | { |
330 | int x, y, darklevel, basex, basey, mflags, light, x1, y1; |
368 | int darklevel, mflags, light, x1, y1; |
331 | maptile *m = op->map; |
369 | maptile *m = op->map; |
332 | sint16 nx, ny; |
370 | sint16 nx, ny; |
333 | |
371 | |
334 | darklevel = m->darkness; |
372 | darklevel = m->darkness; |
335 | |
373 | |
336 | /* If the player can see in the dark, lower the darklevel for him */ |
374 | /* If the player can see in the dark, lower the darklevel for him */ |
337 | if (QUERY_FLAG (op, FLAG_SEE_IN_DARK)) |
375 | if (QUERY_FLAG (op, FLAG_SEE_IN_DARK)) |
338 | darklevel -= LOS_MAX / 2; |
376 | darklevel -= LOS_MAX / 2; |
339 | |
|
|
340 | /* add light, by finding all (non-null) nearby light sources, then |
|
|
341 | * mark those squares specially. If the darklevel<1, there is no |
|
|
342 | * reason to do this, so we skip this function |
|
|
343 | */ |
|
|
344 | |
|
|
345 | if (darklevel < 1) |
|
|
346 | return; |
|
|
347 | |
377 | |
348 | /* Do a sanity check. If not valid, some code below may do odd |
378 | /* Do a sanity check. If not valid, some code below may do odd |
349 | * things. |
379 | * things. |
350 | */ |
380 | */ |
351 | if (darklevel > MAX_DARKNESS) |
381 | if (darklevel > MAX_DARKNESS) |
352 | { |
382 | { |
353 | LOG (llevError, "Map darkness for %s on %s is too high (%d)\n", &op->name, &op->map->path, darklevel); |
383 | LOG (llevError, "Map darkness for %s on %s is too high (%d)\n", &op->name, &op->map->path, darklevel); |
354 | darklevel = MAX_DARKNESS; |
384 | darklevel = MAX_DARKNESS; |
355 | } |
385 | } |
356 | |
386 | |
357 | /* first, make everything totally dark */ |
|
|
358 | for (x = 0; x < op->contr->ns->mapx; x++) |
|
|
359 | for (y = 0; y < op->contr->ns->mapy; y++) |
|
|
360 | if (op->contr->blocked_los[x][y] != LOS_BLOCKED) |
|
|
361 | op->contr->blocked_los[x][y] = LOS_MAX; |
|
|
362 | |
|
|
363 | int half_x = op->contr->ns->mapx / 2; |
387 | int half_x = op->contr->ns->mapx / 2; |
364 | int half_y = op->contr->ns->mapy / 2; |
388 | int half_y = op->contr->ns->mapy / 2; |
365 | |
389 | |
366 | int min_x = op->x - half_x - MAX_LIGHT_RADIUS; |
390 | int min_x = op->x - half_x - MAX_LIGHT_RADIUS; |
367 | int min_y = op->y - half_y - MAX_LIGHT_RADIUS; |
391 | int min_y = op->y - half_y - MAX_LIGHT_RADIUS; |
368 | int max_x = op->x + half_x + MAX_LIGHT_RADIUS; |
392 | int max_x = op->x + half_x + MAX_LIGHT_RADIUS; |
369 | int max_y = op->y + half_y + MAX_LIGHT_RADIUS; |
393 | int max_y = op->y + half_y + MAX_LIGHT_RADIUS; |
370 | |
394 | |
371 | int pass2 = 0; // negative lights have an extra pass |
395 | int pass2 = 0; // negative lights have an extra pass |
372 | |
396 | |
373 | /* |
397 | if (darklevel < 1) |
|
|
398 | pass2 = 1; |
|
|
399 | else |
|
|
400 | { |
|
|
401 | /* first, make everything totally dark */ |
|
|
402 | for (int x = 0; x < op->contr->ns->mapx; x++) |
|
|
403 | for (int y = 0; y < op->contr->ns->mapy; y++) |
|
|
404 | if (op->contr->blocked_los[x][y] != LOS_BLOCKED) |
|
|
405 | op->contr->blocked_los[x][y] = LOS_MAX; |
|
|
406 | |
|
|
407 | /* |
374 | * Only process the area of interest. |
408 | * Only process the area of interest. |
375 | * the basex, basey values represent the position in the op->contr->blocked_los |
409 | * the basex, basey values represent the position in the op->contr->blocked_los |
376 | * array. Its easier to just increment them here (and start with the right |
410 | * array. Its easier to just increment them here (and start with the right |
377 | * value) than to recalculate them down below. |
411 | * value) than to recalculate them down below. |
378 | */ |
412 | */ |
379 | for (int x = min_x, basex = -MAX_LIGHT_RADIUS; x <= max_x; x++, basex++) |
413 | for (int x = min_x, basex = -MAX_LIGHT_RADIUS; x <= max_x; x++, basex++) |
380 | for (int y = min_y, basey = -MAX_LIGHT_RADIUS; y <= max_y; y++, basey++) |
414 | for (int y = min_y, basey = -MAX_LIGHT_RADIUS; y <= max_y; y++, basey++) |
|
|
415 | { |
|
|
416 | maptile *m = op->map; |
|
|
417 | sint16 nx = x; |
|
|
418 | sint16 ny = y; |
|
|
419 | |
|
|
420 | if (!xy_normalise (m, nx, ny)) |
|
|
421 | continue; |
|
|
422 | |
|
|
423 | mapspace &ms = m->at (nx, ny); |
|
|
424 | ms.update (); |
|
|
425 | sint8 light = ms.light; |
|
|
426 | |
|
|
427 | if (expect_false (light)) |
|
|
428 | if (light < 0) |
|
|
429 | pass2 = 1; |
|
|
430 | else |
|
|
431 | apply_light<los_brighten> (op, basex, basey, light, darkness [light + MAX_LIGHT_RADIUS]); |
|
|
432 | } |
|
|
433 | |
|
|
434 | /* grant some vision to the player, based on the darklevel */ |
|
|
435 | /* for outdoor maps, ensure some mininum visibility radius */ |
381 | { |
436 | { |
382 | maptile *m = op->map; |
437 | int light = clamp (MAX_DARKNESS - darklevel, op->map->outdoor ? 2 : 0, MAX_LIGHT_RADIUS); |
383 | sint16 nx = x; |
|
|
384 | sint16 ny = y; |
|
|
385 | |
438 | |
386 | if (!xy_normalise (m, nx, ny)) |
439 | apply_light<los_brighten_blocked> (op, half_x, half_y, light, darkness [light + MAX_LIGHT_RADIUS]); |
387 | continue; |
|
|
388 | |
|
|
389 | mapspace &ms = m->at (nx, ny); |
|
|
390 | ms.update (); |
|
|
391 | sint8 light = ms.light; |
|
|
392 | |
|
|
393 | if (expect_false (light)) |
|
|
394 | if (light < 0) |
|
|
395 | pass2 = 1; |
|
|
396 | else |
|
|
397 | { |
|
|
398 | /* This space is providing light, so we need to brighten up the |
|
|
399 | * spaces around here. |
|
|
400 | */ |
|
|
401 | const sint8 *darkness_table = darkness [light + MAX_LIGHT_RADIUS]; |
|
|
402 | |
|
|
403 | for (int ax = max (0, basex - light); ax <= min (basex + light, op->contr->ns->mapx - 1); ax++) |
|
|
404 | for (int ay = max (0, basey - light); ay <= min (basey + light, op->contr->ns->mapy - 1); ay++) |
|
|
405 | if (op->contr->blocked_los[ax][ay] != LOS_BLOCKED) |
|
|
406 | min_it (op->contr->blocked_los[ax][ay], darkness_table [idistance (ax - basex, ay - basey)]); |
|
|
407 | } |
|
|
408 | } |
440 | } |
|
|
441 | } |
409 | |
442 | |
410 | // possibly do 2nd pass for rare negative glow radii |
443 | // possibly do 2nd pass for rare negative glow radii |
411 | if (expect_false (pass2)) |
444 | // for effect, those are always considered to be stronger than anything else |
|
|
445 | // but they can't darken a place completely |
|
|
446 | if (pass2) |
412 | for (x = min_x, basex = -MAX_LIGHT_RADIUS; x <= max_x; x++, basex++) |
447 | for (int x = min_x, basex = -MAX_LIGHT_RADIUS; x <= max_x; x++, basex++) |
413 | for (y = min_y, basey = -MAX_LIGHT_RADIUS; y <= max_y; y++, basey++) |
448 | for (int y = min_y, basey = -MAX_LIGHT_RADIUS; y <= max_y; y++, basey++) |
414 | { |
449 | { |
415 | maptile *m = op->map; |
450 | maptile *m = op->map; |
416 | sint16 nx = x; |
451 | sint16 nx = x; |
417 | sint16 ny = y; |
452 | sint16 ny = y; |
418 | |
453 | |
… | |
… | |
422 | mapspace &ms = m->at (nx, ny); |
457 | mapspace &ms = m->at (nx, ny); |
423 | ms.update (); |
458 | ms.update (); |
424 | sint8 light = ms.light; |
459 | sint8 light = ms.light; |
425 | |
460 | |
426 | if (expect_false (light < 0)) |
461 | if (expect_false (light < 0)) |
427 | { |
462 | apply_light<los_darken> (op, basex, basey, -light, darkness [light + MAX_LIGHT_RADIUS]); |
428 | const sint8 *darkness_table = darkness [light + MAX_LIGHT_RADIUS]; |
|
|
429 | |
|
|
430 | for (int ax = max (0, basex + light); ax <= min (basex - light, op->contr->ns->mapx - 1); ax++) |
|
|
431 | for (int ay = max (0, basey + light); ay <= min (basey - light, op->contr->ns->mapy - 1); ay++) |
|
|
432 | if (op->contr->blocked_los[ax][ay] != LOS_BLOCKED) |
|
|
433 | max_it (op->contr->blocked_los[ax][ay], darkness_table [idistance (ax - basex, ay - basey)]); |
|
|
434 | } |
463 | } |
435 | } |
|
|
436 | |
|
|
437 | /* Outdoor should never really be completely pitch black dark like |
|
|
438 | * a dungeon, so let the player at least see a little around themselves |
|
|
439 | */ |
|
|
440 | if (op->map->outdoor && darklevel > MAX_DARKNESS - 3) |
|
|
441 | { |
|
|
442 | if (op->contr->blocked_los[op->contr->ns->mapx / 2][op->contr->ns->mapy / 2] > (LOS_MAX - 3)) |
|
|
443 | op->contr->blocked_los[op->contr->ns->mapx / 2][op->contr->ns->mapy / 2] = LOS_MAX - 3; |
|
|
444 | |
|
|
445 | for (x = -1; x <= 1; x++) |
|
|
446 | for (y = -1; y <= 1; y++) |
|
|
447 | if (op->contr->blocked_los[x + op->contr->ns->mapx / 2][y + op->contr->ns->mapy / 2] > (LOS_MAX - 2)) |
|
|
448 | op->contr->blocked_los[x + op->contr->ns->mapx / 2][y + op->contr->ns->mapy / 2] = LOS_MAX - 2; |
|
|
449 | } |
|
|
450 | |
|
|
451 | /* grant some vision to the player, based on the darklevel */ |
|
|
452 | for (x = darklevel - MAX_DARKNESS; x < MAX_DARKNESS + 1 - darklevel; x++) |
|
|
453 | for (y = darklevel - MAX_DARKNESS; y < MAX_DARKNESS + 1 - darklevel; y++) |
|
|
454 | if (!(op->contr->blocked_los[x + op->contr->ns->mapx / 2][y + op->contr->ns->mapy / 2] == LOS_BLOCKED)) |
|
|
455 | op->contr->blocked_los[x + op->contr->ns->mapx / 2][y + op->contr->ns->mapy / 2] -= |
|
|
456 | max (0, 6 - darklevel - max (abs (x), abs (y))); |
|
|
457 | } |
464 | } |
458 | |
465 | |
459 | /* blinded_sight() - sets all viewable squares to blocked except |
466 | /* blinded_sight() - sets all viewable squares to blocked except |
460 | * for the one the central one that the player occupies. A little |
467 | * for the one the central one that the player occupies. A little |
461 | * odd that you can see yourself (and what your standing on), but |
468 | * odd that you can see yourself (and what your standing on), but |