--- deliantra/server/common/los.C 2008/12/18 05:13:38 1.38 +++ deliantra/server/common/los.C 2008/12/18 07:01:31 1.39 @@ -276,8 +276,7 @@ } } - if (op->map->darkness > 0) /* player is on a dark map */ - expand_lighted_sight (op); + expand_lighted_sight (op); /* clear mark squares */ for (int x = 0; x < op->contr->ns->mapx; x++) @@ -324,10 +323,49 @@ } } darkness_init; +sint8 +los_brighten (sint8 b, sint8 l) +{ + return b == LOS_BLOCKED ? b : min (b, l); +} + +sint8 +los_brighten_blocked (sint8 b, sint8 l) +{ + return min (b, l); +} + +sint8 +los_darken (sint8 b, sint8 l) +{ + return max (b, l); +} + +template +static void +apply_light (object *op, int basex, int basey, int light, const sint8 *darkness_table) +{ + // min or max the ciruclar area around basex, basey + player *pl = op->contr; + + int ax0 = max (0, basex - light); + int ay0 = max (0, basey - light); + int ax1 = min (basex + light, pl->ns->mapx - 1); + int ay1 = min (basey + light, pl->ns->mapy - 1); + + for (int ax = ax0; ax <= ax1; ax++) + for (int ay = ay0; ay <= ay1; ay++) + pl->blocked_los[ax][ay] = + change_it (pl->blocked_los[ax][ay], darkness_table [idistance (ax - basex, ay - basey)]); +} + +/* add light, by finding all (non-null) nearby light sources, then + * mark those squares specially. + */ static void expand_lighted_sight (object *op) { - int x, y, darklevel, basex, basey, mflags, light, x1, y1; + int darklevel, mflags, light, x1, y1; maptile *m = op->map; sint16 nx, ny; @@ -337,14 +375,6 @@ if (QUERY_FLAG (op, FLAG_SEE_IN_DARK)) darklevel -= LOS_MAX / 2; - /* add light, by finding all (non-null) nearby light sources, then - * mark those squares specially. If the darklevel<1, there is no - * reason to do this, so we skip this function - */ - - if (darklevel < 1) - return; - /* Do a sanity check. If not valid, some code below may do odd * things. */ @@ -354,12 +384,6 @@ darklevel = MAX_DARKNESS; } - /* first, make everything totally dark */ - for (x = 0; x < op->contr->ns->mapx; x++) - for (y = 0; y < op->contr->ns->mapy; y++) - if (op->contr->blocked_los[x][y] != LOS_BLOCKED) - op->contr->blocked_los[x][y] = LOS_MAX; - int half_x = op->contr->ns->mapx / 2; int half_y = op->contr->ns->mapy / 2; @@ -370,47 +394,58 @@ int pass2 = 0; // negative lights have an extra pass - /* - * Only process the area of interest. - * the basex, basey values represent the position in the op->contr->blocked_los - * array. Its easier to just increment them here (and start with the right - * value) than to recalculate them down below. - */ - for (int x = min_x, basex = -MAX_LIGHT_RADIUS; x <= max_x; x++, basex++) - for (int y = min_y, basey = -MAX_LIGHT_RADIUS; y <= max_y; y++, basey++) + if (darklevel < 1) + pass2 = 1; + else + { + /* first, make everything totally dark */ + for (int x = 0; x < op->contr->ns->mapx; x++) + for (int y = 0; y < op->contr->ns->mapy; y++) + if (op->contr->blocked_los[x][y] != LOS_BLOCKED) + op->contr->blocked_los[x][y] = LOS_MAX; + + /* + * Only process the area of interest. + * the basex, basey values represent the position in the op->contr->blocked_los + * array. Its easier to just increment them here (and start with the right + * value) than to recalculate them down below. + */ + for (int x = min_x, basex = -MAX_LIGHT_RADIUS; x <= max_x; x++, basex++) + for (int y = min_y, basey = -MAX_LIGHT_RADIUS; y <= max_y; y++, basey++) + { + maptile *m = op->map; + sint16 nx = x; + sint16 ny = y; + + if (!xy_normalise (m, nx, ny)) + continue; + + mapspace &ms = m->at (nx, ny); + ms.update (); + sint8 light = ms.light; + + if (expect_false (light)) + if (light < 0) + pass2 = 1; + else + apply_light (op, basex, basey, light, darkness [light + MAX_LIGHT_RADIUS]); + } + + /* grant some vision to the player, based on the darklevel */ + /* for outdoor maps, ensure some mininum visibility radius */ { - maptile *m = op->map; - sint16 nx = x; - sint16 ny = y; - - if (!xy_normalise (m, nx, ny)) - continue; - - mapspace &ms = m->at (nx, ny); - ms.update (); - sint8 light = ms.light; - - if (expect_false (light)) - if (light < 0) - pass2 = 1; - else - { - /* This space is providing light, so we need to brighten up the - * spaces around here. - */ - const sint8 *darkness_table = darkness [light + MAX_LIGHT_RADIUS]; - - for (int ax = max (0, basex - light); ax <= min (basex + light, op->contr->ns->mapx - 1); ax++) - for (int ay = max (0, basey - light); ay <= min (basey + light, op->contr->ns->mapy - 1); ay++) - if (op->contr->blocked_los[ax][ay] != LOS_BLOCKED) - min_it (op->contr->blocked_los[ax][ay], darkness_table [idistance (ax - basex, ay - basey)]); - } + int light = clamp (MAX_DARKNESS - darklevel, op->map->outdoor ? 2 : 0, MAX_LIGHT_RADIUS); + + apply_light (op, half_x, half_y, light, darkness [light + MAX_LIGHT_RADIUS]); } + } // possibly do 2nd pass for rare negative glow radii - if (expect_false (pass2)) - for (x = min_x, basex = -MAX_LIGHT_RADIUS; x <= max_x; x++, basex++) - for (y = min_y, basey = -MAX_LIGHT_RADIUS; y <= max_y; y++, basey++) + // for effect, those are always considered to be stronger than anything else + // but they can't darken a place completely + if (pass2) + for (int x = min_x, basex = -MAX_LIGHT_RADIUS; x <= max_x; x++, basex++) + for (int y = min_y, basey = -MAX_LIGHT_RADIUS; y <= max_y; y++, basey++) { maptile *m = op->map; sint16 nx = x; @@ -424,36 +459,8 @@ sint8 light = ms.light; if (expect_false (light < 0)) - { - const sint8 *darkness_table = darkness [light + MAX_LIGHT_RADIUS]; - - for (int ax = max (0, basex + light); ax <= min (basex - light, op->contr->ns->mapx - 1); ax++) - for (int ay = max (0, basey + light); ay <= min (basey - light, op->contr->ns->mapy - 1); ay++) - if (op->contr->blocked_los[ax][ay] != LOS_BLOCKED) - max_it (op->contr->blocked_los[ax][ay], darkness_table [idistance (ax - basex, ay - basey)]); - } + apply_light (op, basex, basey, -light, darkness [light + MAX_LIGHT_RADIUS]); } - - /* Outdoor should never really be completely pitch black dark like - * a dungeon, so let the player at least see a little around themselves - */ - if (op->map->outdoor && darklevel > MAX_DARKNESS - 3) - { - if (op->contr->blocked_los[op->contr->ns->mapx / 2][op->contr->ns->mapy / 2] > (LOS_MAX - 3)) - op->contr->blocked_los[op->contr->ns->mapx / 2][op->contr->ns->mapy / 2] = LOS_MAX - 3; - - for (x = -1; x <= 1; x++) - for (y = -1; y <= 1; y++) - if (op->contr->blocked_los[x + op->contr->ns->mapx / 2][y + op->contr->ns->mapy / 2] > (LOS_MAX - 2)) - op->contr->blocked_los[x + op->contr->ns->mapx / 2][y + op->contr->ns->mapy / 2] = LOS_MAX - 2; - } - - /* grant some vision to the player, based on the darklevel */ - for (x = darklevel - MAX_DARKNESS; x < MAX_DARKNESS + 1 - darklevel; x++) - for (y = darklevel - MAX_DARKNESS; y < MAX_DARKNESS + 1 - darklevel; y++) - if (!(op->contr->blocked_los[x + op->contr->ns->mapx / 2][y + op->contr->ns->mapy / 2] == LOS_BLOCKED)) - op->contr->blocked_los[x + op->contr->ns->mapx / 2][y + op->contr->ns->mapy / 2] -= - max (0, 6 - darklevel - max (abs (x), abs (y))); } /* blinded_sight() - sets all viewable squares to blocked except