void paintLight(lightSource *theLight, short x, short y, boolean isMinersLight) { short i, j, k; short colorComponents[3], randComponent, lightMultiplier, thisComponent; short fadeToPercent; float radius; char grid[DCOLS][DROWS]; boolean dispelShadows; #ifdef BROGUE_ASSERTS assert(rogue.RNG == RNG_SUBSTANTIVE); #endif radius = randClump(theLight->lightRadius); radius /= 100; randComponent = rand_range(0, theLight->lightColor->rand); colorComponents[0] = randComponent + theLight->lightColor->red + rand_range(0, theLight->lightColor->redRand); colorComponents[1] = randComponent + theLight->lightColor->green + rand_range(0, theLight->lightColor->greenRand); colorComponents[2] = randComponent + theLight->lightColor->blue + rand_range(0, theLight->lightColor->blueRand); // the miner's light does not dispel IS_IN_SHADOW, // so the player can be in shadow despite casting his own light. dispelShadows = !isMinersLight && colorComponents[0] + colorComponents[1] + colorComponents[2] > 0; fadeToPercent = theLight->radialFadeToPercent; // zero out only the relevant rectangle of the grid for (i = max(0, x - radius); i < DCOLS && i < x + radius; i++) { for (j = max(0, y - radius); j < DROWS && j < y + radius; j++) { grid[i][j] = 0; } } getFOVMask(grid, x, y, radius, T_OBSTRUCTS_VISION, (theLight->passThroughCreatures ? 0 : (HAS_MONSTER | HAS_PLAYER)), (!isMinersLight)); for (i = max(0, x - radius); i < DCOLS && i < x + radius; i++) { for (j = max(0, y - radius); j < DROWS && j < y + radius; j++) { if (grid[i][j]) { lightMultiplier = 100 - (100 - fadeToPercent) * (sqrt((i-x) * (i-x) + (j-y) * (j-y)) / (radius)); for (k=0; k<3; k++) { thisComponent = colorComponents[k] * lightMultiplier / 100; tmap[i][j].light[k] += thisComponent; } if (dispelShadows) { pmap[i][j].flags &= ~IS_IN_SHADOW; } } } } tmap[x][y].light[0] += colorComponents[0]; tmap[x][y].light[1] += colorComponents[1]; tmap[x][y].light[2] += colorComponents[2]; if (dispelShadows) { pmap[x][y].flags &= ~IS_IN_SHADOW; } }
// Returns true if any part of the light hit cells that are in the player's field of view. boolean paintLight(lightSource *theLight, short x, short y, boolean isMinersLight, boolean maintainShadows) { short i, j, k; short colorComponents[3], randComponent, lightMultiplier; short fadeToPercent; double radius; char grid[DCOLS][DROWS]; boolean dispelShadows, overlappedFieldOfView; #ifdef BROGUE_ASSERTS assert(rogue.RNG == RNG_SUBSTANTIVE); #endif radius = randClump(theLight->lightRadius); radius /= 100; randComponent = rand_range(0, theLight->lightColor->rand); colorComponents[0] = randComponent + theLight->lightColor->red + rand_range(0, theLight->lightColor->redRand); colorComponents[1] = randComponent + theLight->lightColor->green + rand_range(0, theLight->lightColor->greenRand); colorComponents[2] = randComponent + theLight->lightColor->blue + rand_range(0, theLight->lightColor->blueRand); // the miner's light does not dispel IS_IN_SHADOW, // so the player can be in shadow despite casting his own light. dispelShadows = !maintainShadows && (colorComponents[0] + colorComponents[1] + colorComponents[2]) > 0; fadeToPercent = theLight->radialFadeToPercent; // zero out only the relevant rectangle of the grid for (i = max(0, x - (radius + FLOAT_FUDGE)); i < DCOLS && i < x + radius + FLOAT_FUDGE; i++) { for (j = max(0, y - (radius + FLOAT_FUDGE)); j < DROWS && j < y + radius + FLOAT_FUDGE; j++) { grid[i][j] = 0; } } getFOVMask(grid, x, y, radius, T_OBSTRUCTS_VISION, (theLight->passThroughCreatures ? 0 : (HAS_MONSTER | HAS_PLAYER)), (!isMinersLight)); overlappedFieldOfView = false; for (i = max(0, x - (radius + FLOAT_FUDGE)); i < DCOLS && i < x + radius; i++) { for (j = max(0, y - (radius + FLOAT_FUDGE)); j < DROWS && j < y + radius; j++) { if (grid[i][j]) { lightMultiplier = 100 - (100 - fadeToPercent) * (sqrt((i-x) * (i-x) + (j-y) * (j-y)) / radius + FLOAT_FUDGE); for (k=0; k<3; k++) { tmap[i][j].light[k] += colorComponents[k] * lightMultiplier / 100; } if (dispelShadows) { pmap[i][j].flags &= ~IS_IN_SHADOW; } if (pmap[i][j].flags & (IN_FIELD_OF_VIEW | ANY_KIND_OF_VISIBLE)) { overlappedFieldOfView = true; } } } } for (i = x - radius - 1; i < x + radius + 1; i++) { if (i < 0 || i >= DCOLS + 1) { continue; } for (j = y - radius - 1; j < y + radius + 1; j++) { boolean visible = false; if (j < 0 || j >= DROWS + 1) { continue; } if (i > 0 && j > 0 && grid[i - 1][j - 1]) { visible = true; } if (i < DCOLS && j > 0 && grid[i][j - 1]) { visible = true; } if (i > 0 && j < DROWS && grid[i - 1][j]) { visible = true; } if (i < DCOLS && j < DROWS && grid[i][j]) { visible = true; } if (visible) { lightMultiplier = 100 - (100 - fadeToPercent) * (sqrt((i - x + 0.5) * (i - x + 0.5) + (j - y + 0.5) * (j - y + 0.5)) / radius + FLOAT_FUDGE); if (lightMultiplier > 0) { for (k=0; k<3; k++) { lightmap[i][j].light[k] += colorComponents[k] * lightMultiplier / 100; } } } } } tmap[x][y].light[0] += colorComponents[0]; tmap[x][y].light[1] += colorComponents[1]; tmap[x][y].light[2] += colorComponents[2]; if (dispelShadows) { pmap[x][y].flags &= ~IS_IN_SHADOW; } return overlappedFieldOfView; }