From 231005e72cdb49dc87edaf41959e0dd4b053bcb0 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Fri, 27 Sep 2024 07:31:01 +0100 Subject: [PATCH] Fix stairs rendering in Caves and Hell Stairs can have the same `TileProperties` as floors but do not always follor the same graphics layout as floors, so we shouldn't apply optimizations to them. The only floors affected seem to be: 1. Caves: tile 48 sub-tile 171 frame 461 (TileProperties: None) 2. Hell: tile 46 sub-tile 141 frame 386 (TileProperties: BlocksMissile) Note that the few broken in pixels in caves are actually incorrectly attributed to the non-Solid tile, really they should be part of the solid tile 49. As there doesn't seem to be a quick and easy way to check if a frame is part of Stairs, we add a check for BlocksMissile tile property instead. This fixes Hell but isn't enough to fix Caves. To fix Caves, we then add a `BlocksMissile` flag to the broken sub-tile. --- Source/engine/render/scrollrt.cpp | 2 +- Source/levels/gendung.cpp | 4 ++++ Source/levels/reencode_dun_cels.hpp | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Source/engine/render/scrollrt.cpp b/Source/engine/render/scrollrt.cpp index 32dc679376f..2f674df99c9 100644 --- a/Source/engine/render/scrollrt.cpp +++ b/Source/engine/render/scrollrt.cpp @@ -84,7 +84,7 @@ constexpr auto RightFrameDisplacement = Displacement { DunFrameWidth, 0 }; [[nodiscard]] DVL_ALWAYS_INLINE bool IsFloor(Point tilePosition) { - return !TileHasAny(tilePosition, TileProperties::Solid); + return !TileHasAny(tilePosition, TileProperties::Solid | TileProperties::BlockMissile); } [[nodiscard]] DVL_ALWAYS_INLINE bool IsWall(Point tilePosition) diff --git a/Source/levels/gendung.cpp b/Source/levels/gendung.cpp index 4a59eb13435..8f5d9e6dadc 100644 --- a/Source/levels/gendung.cpp +++ b/Source/levels/gendung.cpp @@ -468,6 +468,10 @@ void LoadLevelSOLData() break; case DTYPE_CAVES: LoadFileInMem("levels\\l3data\\l3.sol", SOLData); + // The graphics for tile 48 sub-tile 171 frame 461 are partly incorrect, as they + // have a few pixels that should belong to the solid tile 49 instead. + // Marks the sub-tile as "BlockMissile" to avoid treating it as a floor during rendering. + SOLData[170] |= TileProperties::BlockMissile; break; case DTYPE_HELL: LoadFileInMem("levels\\l4data\\l4.sol", SOLData); diff --git a/Source/levels/reencode_dun_cels.hpp b/Source/levels/reencode_dun_cels.hpp index 977f1dd83eb..c91482d862f 100644 --- a/Source/levels/reencode_dun_cels.hpp +++ b/Source/levels/reencode_dun_cels.hpp @@ -19,7 +19,8 @@ struct DunFrameInfo { [[nodiscard]] bool isFloor() const { - return !HasAnyOf(properties, TileProperties::Solid) + // The BlockMissile check is for stairs in L3 and L4, e.g. tile 46 sub-tile 141 frame 386 in L4. + return !HasAnyOf(properties, TileProperties::Solid | TileProperties::BlockMissile) && (microTileIndex == 0 || microTileIndex == 1); } [[nodiscard]] bool isFloorLeft() const { return microTileIndex == 0; }