diff --git a/Source/engine/displacement.hpp b/Source/engine/displacement.hpp index 7229084ae..341433498 100644 --- a/Source/engine/displacement.hpp +++ b/Source/engine/displacement.hpp @@ -95,6 +95,14 @@ struct DisplacementOf { return *this; } + template + constexpr DisplacementOf &operator*=(const DisplacementOf factor) + { + deltaX = static_cast(deltaX * factor.deltaX); + deltaY = static_cast(deltaY * factor.deltaY); + return *this; + } + constexpr DisplacementOf &operator/=(const int factor) { deltaX /= factor; @@ -284,6 +292,13 @@ constexpr DisplacementOf operator*(DisplacementOf +constexpr DisplacementOf operator*(DisplacementOf a, const DisplacementOf factor) +{ + a *= factor; + return a; +} + template constexpr DisplacementOf operator/(DisplacementOf a, const int factor) { diff --git a/Source/lighting.cpp b/Source/lighting.cpp index bfcbd5ff1..9ebe627d4 100644 --- a/Source/lighting.cpp +++ b/Source/lighting.cpp @@ -30,31 +30,31 @@ namespace { * X- Y-coordinate offsets of lighting visions. * The last entry-pair is only for alignment. */ -const uint8_t VisionCrawlTable[23][30] = { +const DisplacementOf VisionCrawlTable[23][15] = { // clang-format off - { 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0 }, - { 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 1, 9, 1, 10, 1, 11, 1, 12, 1, 13, 1, 14, 1, 15, 1 }, - { 1, 0, 2, 0, 3, 0, 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9, 1, 10, 1, 11, 1, 12, 2, 13, 2, 14, 2, 15, 2 }, - { 1, 0, 2, 0, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 2, 9, 2, 10, 2, 11, 2, 12, 2, 13, 3, 14, 3, 15, 3 }, - { 1, 0, 2, 1, 3, 1, 4, 1, 5, 1, 6, 2, 7, 2, 8, 2, 9, 3, 10, 3, 11, 3, 12, 3, 13, 4, 14, 4, 0, 0 }, - { 1, 0, 2, 1, 3, 1, 4, 1, 5, 2, 6, 2, 7, 3, 8, 3, 9, 3, 10, 4, 11, 4, 12, 4, 13, 5, 14, 5, 0, 0 }, - { 1, 0, 2, 1, 3, 1, 4, 2, 5, 2, 6, 3, 7, 3, 8, 3, 9, 4, 10, 4, 11, 5, 12, 5, 13, 6, 14, 6, 0, 0 }, - { 1, 1, 2, 1, 3, 2, 4, 2, 5, 3, 6, 3, 7, 4, 8, 4, 9, 5, 10, 5, 11, 6, 12, 6, 13, 7, 0, 0, 0, 0 }, - { 1, 1, 2, 1, 3, 2, 4, 2, 5, 3, 6, 4, 7, 4, 8, 5, 9, 6, 10, 6, 11, 7, 12, 7, 12, 8, 13, 8, 0, 0 }, - { 1, 1, 2, 2, 3, 2, 4, 3, 5, 4, 6, 5, 7, 5, 8, 6, 9, 7, 10, 7, 10, 8, 11, 8, 12, 9, 0, 0, 0, 0 }, - { 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 5, 7, 6, 8, 7, 9, 8, 10, 9, 11, 9, 11, 10, 0, 0, 0, 0, 0, 0 }, - { 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 9, 11, 10, 11, 0, 0, 0, 0, 0, 0 }, - { 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 5, 7, 6, 8, 7, 9, 7, 10, 8, 10, 8, 11, 9, 12, 0, 0, 0, 0 }, - { 1, 1, 1, 2, 2, 3, 2, 4, 3, 5, 4, 6, 4, 7, 5, 8, 6, 9, 6, 10, 7, 11, 7, 12, 8, 12, 8, 13, 0, 0 }, - { 1, 1, 1, 2, 2, 3, 2, 4, 3, 5, 3, 6, 4, 7, 4, 8, 5, 9, 5, 10, 6, 11, 6, 12, 7, 13, 0, 0, 0, 0 }, - { 0, 1, 1, 2, 1, 3, 2, 4, 2, 5, 3, 6, 3, 7, 3, 8, 4, 9, 4, 10, 5, 11, 5, 12, 6, 13, 6, 14, 0, 0 }, - { 0, 1, 1, 2, 1, 3, 1, 4, 2, 5, 2, 6, 3, 7, 3, 8, 3, 9, 4, 10, 4, 11, 4, 12, 5, 13, 5, 14, 0, 0 }, - { 0, 1, 1, 2, 1, 3, 1, 4, 1, 5, 2, 6, 2, 7, 2, 8, 3, 9, 3, 10, 3, 11, 3, 12, 4, 13, 4, 14, 0, 0 }, - { 0, 1, 0, 2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 2, 8, 2, 9, 2, 10, 2, 11, 2, 12, 3, 13, 3, 14, 3, 15 }, - { 0, 1, 0, 2, 0, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9, 1, 10, 1, 11, 2, 12, 2, 13, 2, 14, 2, 15 }, - { 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 1, 8, 1, 9, 1, 10, 1, 11, 1, 12, 1, 13, 1, 14, 1, 15 }, - { 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15 }, + { { 1, 0 }, { 2, 0 }, { 3, 0 }, { 4, 0 }, { 5, 0 }, { 6, 0 }, { 7, 0 }, { 8, 0 }, { 9, 0 }, { 10, 0 }, { 11, 0 }, { 12, 0 }, { 13, 0 }, { 14, 0 }, { 15, 0 } }, + { { 1, 0 }, { 2, 0 }, { 3, 0 }, { 4, 0 }, { 5, 0 }, { 6, 0 }, { 7, 0 }, { 8, 1 }, { 9, 1 }, { 10, 1 }, { 11, 1 }, { 12, 1 }, { 13, 1 }, { 14, 1 }, { 15, 1 } }, + { { 1, 0 }, { 2, 0 }, { 3, 0 }, { 4, 1 }, { 5, 1 }, { 6, 1 }, { 7, 1 }, { 8, 1 }, { 9, 1 }, { 10, 1 }, { 11, 1 }, { 12, 2 }, { 13, 2 }, { 14, 2 }, { 15, 2 } }, + { { 1, 0 }, { 2, 0 }, { 3, 1 }, { 4, 1 }, { 5, 1 }, { 6, 1 }, { 7, 1 }, { 8, 2 }, { 9, 2 }, { 10, 2 }, { 11, 2 }, { 12, 2 }, { 13, 3 }, { 14, 3 }, { 15, 3 } }, + { { 1, 0 }, { 2, 1 }, { 3, 1 }, { 4, 1 }, { 5, 1 }, { 6, 2 }, { 7, 2 }, { 8, 2 }, { 9, 3 }, { 10, 3 }, { 11, 3 }, { 12, 3 }, { 13, 4 }, { 14, 4 }, { 0, 0 } }, + { { 1, 0 }, { 2, 1 }, { 3, 1 }, { 4, 1 }, { 5, 2 }, { 6, 2 }, { 7, 3 }, { 8, 3 }, { 9, 3 }, { 10, 4 }, { 11, 4 }, { 12, 4 }, { 13, 5 }, { 14, 5 }, { 0, 0 } }, + { { 1, 0 }, { 2, 1 }, { 3, 1 }, { 4, 2 }, { 5, 2 }, { 6, 3 }, { 7, 3 }, { 8, 3 }, { 9, 4 }, { 10, 4 }, { 11, 5 }, { 12, 5 }, { 13, 6 }, { 14, 6 }, { 0, 0 } }, + { { 1, 1 }, { 2, 1 }, { 3, 2 }, { 4, 2 }, { 5, 3 }, { 6, 3 }, { 7, 4 }, { 8, 4 }, { 9, 5 }, { 10, 5 }, { 11, 6 }, { 12, 6 }, { 13, 7 }, { 0, 0 }, { 0, 0 } }, + { { 1, 1 }, { 2, 1 }, { 3, 2 }, { 4, 2 }, { 5, 3 }, { 6, 4 }, { 7, 4 }, { 8, 5 }, { 9, 6 }, { 10, 6 }, { 11, 7 }, { 12, 7 }, { 12, 8 }, { 13, 8 }, { 0, 0 } }, + { { 1, 1 }, { 2, 2 }, { 3, 2 }, { 4, 3 }, { 5, 4 }, { 6, 5 }, { 7, 5 }, { 8, 6 }, { 9, 7 }, { 10, 7 }, { 10, 8 }, { 11, 8 }, { 12, 9 }, { 0, 0 }, { 0, 0 } }, + { { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 5 }, { 7, 6 }, { 8, 7 }, { 9, 8 }, { 10, 9 }, { 11, 9 }, { 11, 10 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + { { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 }, { 7, 7 }, { 8, 8 }, { 9, 9 }, { 10, 10 }, { 11, 11 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + { { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 5, 6 }, { 6, 7 }, { 7, 8 }, { 8, 9 }, { 9, 10 }, { 9, 11 }, { 10, 11 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + { { 1, 1 }, { 2, 2 }, { 2, 3 }, { 3, 4 }, { 4, 5 }, { 5, 6 }, { 5, 7 }, { 6, 8 }, { 7, 9 }, { 7, 10 }, { 8, 10 }, { 8, 11 }, { 9, 12 }, { 0, 0 }, { 0, 0 } }, + { { 1, 1 }, { 1, 2 }, { 2, 3 }, { 2, 4 }, { 3, 5 }, { 4, 6 }, { 4, 7 }, { 5, 8 }, { 6, 9 }, { 6, 10 }, { 7, 11 }, { 7, 12 }, { 8, 12 }, { 8, 13 }, { 0, 0 } }, + { { 1, 1 }, { 1, 2 }, { 2, 3 }, { 2, 4 }, { 3, 5 }, { 3, 6 }, { 4, 7 }, { 4, 8 }, { 5, 9 }, { 5, 10 }, { 6, 11 }, { 6, 12 }, { 7, 13 }, { 0, 0 }, { 0, 0 } }, + { { 0, 1 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 2, 5 }, { 3, 6 }, { 3, 7 }, { 3, 8 }, { 4, 9 }, { 4, 10 }, { 5, 11 }, { 5, 12 }, { 6, 13 }, { 6, 14 }, { 0, 0 } }, + { { 0, 1 }, { 1, 2 }, { 1, 3 }, { 1, 4 }, { 2, 5 }, { 2, 6 }, { 3, 7 }, { 3, 8 }, { 3, 9 }, { 4, 10 }, { 4, 11 }, { 4, 12 }, { 5, 13 }, { 5, 14 }, { 0, 0 } }, + { { 0, 1 }, { 1, 2 }, { 1, 3 }, { 1, 4 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, { 2, 8 }, { 3, 9 }, { 3, 10 }, { 3, 11 }, { 3, 12 }, { 4, 13 }, { 4, 14 }, { 0, 0 } }, + { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 1, 4 }, { 1, 5 }, { 1, 6 }, { 1, 7 }, { 2, 8 }, { 2, 9 }, { 2, 10 }, { 2, 11 }, { 2, 12 }, { 3, 13 }, { 3, 14 }, { 3, 15 } }, + { { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 4 }, { 1, 5 }, { 1, 6 }, { 1, 7 }, { 1, 8 }, { 1, 9 }, { 1, 10 }, { 1, 11 }, { 2, 12 }, { 2, 13 }, { 2, 14 }, { 2, 15 } }, + { { 0, 1 }, { 0, 2 }, { 0, 3 }, { 0, 4 }, { 0, 5 }, { 0, 6 }, { 0, 7 }, { 1, 8 }, { 1, 9 }, { 1, 10 }, { 1, 11 }, { 1, 12 }, { 1, 13 }, { 1, 14 }, { 1, 15 } }, + { { 0, 1 }, { 0, 2 }, { 0, 3 }, { 0, 4 }, { 0, 5 }, { 0, 6 }, { 0, 7 }, { 0, 8 }, { 0, 9 }, { 0, 10 }, { 0, 11 }, { 0, 12 }, { 0, 13 }, { 0, 14 }, { 0, 15 } }, // clang-format on }; @@ -155,6 +155,25 @@ bool CrawlFlipsXY(Displacement mirrored, tl::function_ref fu return true; } +bool TileAllowsLight(Point position) +{ + if (!InDungeonBounds(position)) + return false; + return !TileHasAny(dPiece[position.x][position.y], TileProperties::BlockLight); +} + +void DoVisionFlags(Point position, MapExplorationType doAutomap, bool visible) +{ + if (doAutomap != MAP_EXP_NONE) { + if (dFlags[position.x][position.y] != DungeonFlag::None) + SetAutomapView(position, doAutomap); + dFlags[position.x][position.y] |= DungeonFlag::Explored; + } + if (visible) + dFlags[position.x][position.y] |= DungeonFlag::Lit; + dFlags[position.x][position.y] |= DungeonFlag::Visible; +} + } // namespace bool DoCrawl(unsigned radius, tl::function_ref function) @@ -278,90 +297,37 @@ void DoUnVision(Point position, int nRadius) } } -void DoVision(Point position, int nRadius, MapExplorationType doautomap, bool visible) +void DoVision(Point position, int radius, MapExplorationType doAutomap, bool visible) { - if (InDungeonBounds(position)) { - if (doautomap != MAP_EXP_NONE) { - if (dFlags[position.x][position.y] != DungeonFlag::None) { - SetAutomapView(position, doautomap); - } - dFlags[position.x][position.y] |= DungeonFlag::Explored; - } - if (visible) { - dFlags[position.x][position.y] |= DungeonFlag::Lit; - } - dFlags[position.x][position.y] |= DungeonFlag::Visible; - } + DoVisionFlags(position, doAutomap, visible); - for (int v = 0; v < 4; v++) { + static const Displacement factors[] = { { 1, 1 }, { -1, 1 }, { 1, -1 }, { -1, -1 } }; + for (auto factor : factors) { for (int j = 0; j < 23; j++) { - bool nBlockerFlag = false; - int nLineLen = 2 * (nRadius - RadiusAdj[j]); - for (int k = 0; k < nLineLen && !nBlockerFlag; k += 2) { - int x1adj = 0; - int x2adj = 0; - int y1adj = 0; - int y2adj = 0; - int nCrawlX = 0; - int nCrawlY = 0; - switch (v) { - case 0: - nCrawlX = position.x + VisionCrawlTable[j][k]; - nCrawlY = position.y + VisionCrawlTable[j][k + 1]; - if (VisionCrawlTable[j][k] > 0 && VisionCrawlTable[j][k + 1] > 0) { - x1adj = -1; - y2adj = -1; - } - break; - case 1: - nCrawlX = position.x - VisionCrawlTable[j][k]; - nCrawlY = position.y - VisionCrawlTable[j][k + 1]; - if (VisionCrawlTable[j][k] > 0 && VisionCrawlTable[j][k + 1] > 0) { - y1adj = 1; - x2adj = 1; - } + int lineLen = radius - RadiusAdj[j]; + for (int k = 0; k < lineLen; k++) { + Point crawl = position + VisionCrawlTable[j][k] * factor; + if (!InDungeonBounds(crawl)) break; - case 2: - nCrawlX = position.x + VisionCrawlTable[j][k]; - nCrawlY = position.y - VisionCrawlTable[j][k + 1]; - if (VisionCrawlTable[j][k] > 0 && VisionCrawlTable[j][k + 1] > 0) { - x1adj = -1; - y2adj = 1; - } + bool blockerFlag = TileHasAny(dPiece[crawl.x][crawl.y], TileProperties::BlockLight); + bool tileOK = !blockerFlag; + + if (VisionCrawlTable[j][k].deltaX > 0 && VisionCrawlTable[j][k].deltaY > 0) { + tileOK = tileOK || TileAllowsLight(crawl + Displacement { -factor.deltaX, 0 }); + tileOK = tileOK || TileAllowsLight(crawl + Displacement { 0, -factor.deltaY }); + } + + if (!tileOK) break; - case 3: - nCrawlX = position.x - VisionCrawlTable[j][k]; - nCrawlY = position.y + VisionCrawlTable[j][k + 1]; - if (VisionCrawlTable[j][k] > 0 && VisionCrawlTable[j][k + 1] > 0) { - y1adj = -1; - x2adj = 1; - } + + DoVisionFlags(crawl, doAutomap, visible); + + if (blockerFlag) break; - } - if (InDungeonBounds({ nCrawlX, nCrawlY })) { - nBlockerFlag = TileHasAny(dPiece[nCrawlX][nCrawlY], TileProperties::BlockLight); - if ((InDungeonBounds({ x1adj + nCrawlX, y1adj + nCrawlY }) - && !TileHasAny(dPiece[x1adj + nCrawlX][y1adj + nCrawlY], TileProperties::BlockLight)) - || (InDungeonBounds({ x2adj + nCrawlX, y2adj + nCrawlY }) - && !TileHasAny(dPiece[x2adj + nCrawlX][y2adj + nCrawlY], TileProperties::BlockLight))) { - if (doautomap != MAP_EXP_NONE) { - if (dFlags[nCrawlX][nCrawlY] != DungeonFlag::None) { - SetAutomapView({ nCrawlX, nCrawlY }, doautomap); - } - dFlags[nCrawlX][nCrawlY] |= DungeonFlag::Explored; - } - if (visible) { - dFlags[nCrawlX][nCrawlY] |= DungeonFlag::Lit; - } - dFlags[nCrawlX][nCrawlY] |= DungeonFlag::Visible; - if (!nBlockerFlag) { - int8_t nTrans = dTransVal[nCrawlX][nCrawlY]; - if (nTrans != 0) { - TransList[nTrans] = true; - } - } - } - } + + int8_t trans = dTransVal[crawl.x][crawl.y]; + if (trans != 0) + TransList[trans] = true; } } } diff --git a/Source/lighting.h b/Source/lighting.h index 7f38286a1..27ae9b39e 100644 --- a/Source/lighting.h +++ b/Source/lighting.h @@ -56,7 +56,7 @@ extern bool UpdateLighting; void DoLighting(Point position, int nRadius, int Lnum); void DoUnVision(Point position, int nRadius); -void DoVision(Point position, int nRadius, MapExplorationType doautomap, bool visible); +void DoVision(Point position, int radius, MapExplorationType doAutomap, bool visible); void MakeLightTable(); #ifdef _DEBUG void ToggleLighting(); @@ -128,6 +128,4 @@ auto Crawl(unsigned minRadius, unsigned maxRadius, F function) -> invoke_result_ return result; } -/* rdata */ - } // namespace devilution