diff --git a/TR5Main/Game/floordata.cpp b/TR5Main/Game/floordata.cpp index 8128399fb..85c69f86a 100644 --- a/TR5Main/Game/floordata.cpp +++ b/TR5Main/Game/floordata.cpp @@ -2,41 +2,163 @@ #include "trmath.h" #include "floordata.h" #include "room.h" +#include "level.h" -SECTOR_POSITION FLOOR_INFO::GetSectorPosition(ROOM_INFO* room, int x, int z) +VectorInt2 FLOOR_INFO::GetRoomPosition(int roomNumber, int x, int z) { - SECTOR_POSITION pos; - - pos.x = (z - room->z) / WALL_SIZE; - pos.y = (x - room->x) / WALL_SIZE; + auto& room = g_Level.Rooms[roomNumber]; + auto xRoom = (x - room.x) / WALL_SIZE; + auto zRoom = (z - room.z) / WALL_SIZE; + auto pos = VectorInt2{xRoom, zRoom}; if (pos.x < 0) { pos.x = 0; } - else if (pos.x > room->xSize - 1) + else if (pos.x > room.xSize - 1) { - pos.x = room->xSize - 1; + pos.x = room.xSize - 1; } if (pos.y < 0) { pos.y = 0; } - else if (pos.y > room->ySize - 1) + else if (pos.y > room.ySize - 1) { - pos.y = room->ySize - 1; + pos.y = room.ySize - 1; } return pos; } -FLOOR_INFO& FLOOR_INFO::GetFloor(ROOM_INFO* room, int x, int z) +FLOOR_INFO& FLOOR_INFO::GetFloor(int roomNumber, VectorInt2 pos) { - return GetFloor(room, GetSectorPosition(room, x, z)); + auto& room = g_Level.Rooms[roomNumber]; + return room.floor[pos.x + room.xSize * pos.y]; } -FLOOR_INFO& FLOOR_INFO::GetFloor(ROOM_INFO* room, SECTOR_POSITION pos) +FLOOR_INFO& FLOOR_INFO::GetFloor(int roomNumber, int x, int z) { - return room->floor[pos.x + pos.y * room->xSize]; + return GetFloor(roomNumber, GetRoomPosition(roomNumber, x, z)); +} + +int FLOOR_INFO::GetBottomRoom(int startRoomNumber, int x, int z) +{ + auto roomNumber = startRoomNumber; + auto roomBelow = GetFloor(roomNumber, x, z).RoomBelow(x, z); + + while (roomBelow) + { + roomNumber = *roomBelow; + roomBelow = GetFloor(roomNumber, x, z).RoomBelow(x, z); + } + + return roomNumber; +} + +int FLOOR_INFO::GetTopRoom(int startRoomNumber, int x, int z) +{ + auto roomNumber = startRoomNumber; + auto roomAbove = GetFloor(roomNumber, x, z).RoomAbove(x, z); + + while (roomAbove) + { + roomNumber = *roomAbove; + roomAbove = GetFloor(roomNumber, x, z).RoomAbove(x, z); + } + + return roomNumber; +} + +int FLOOR_INFO::GetRoom(int startRoomNumber, int x, int y, int z) +{ + auto roomNumber = startRoomNumber; + auto pos = GetRoomPosition(roomNumber, x, z); + auto& room = g_Level.Rooms[roomNumber]; + auto floor = GetFloor(roomNumber, pos); + + if (pos.x > 0 && pos.y > 0 && pos.x < room.xSize - 1 && pos.y < room.ySize - 1) + { + if (y > floor.FloorHeight(x, z)) + { + auto roomBelow = floor.RoomBelow(x, z); + if (roomBelow) + roomNumber = *roomBelow; + } + else if (y < floor.CeilingHeight(x, z)) + { + auto roomAbove = floor.RoomAbove(x, z); + if (roomAbove) + roomNumber = *roomAbove; + } + } + else + { + auto roomSide = floor.RoomSide(); + if (roomSide) + roomNumber = *roomSide; + } + + return roomNumber; +} + +VectorInt2 FLOOR_INFO::GetSectorPoint(int x, int z) +{ + auto xPoint = x % WALL_SIZE - WALL_SIZE / 2; + auto yPoint = z % WALL_SIZE - WALL_SIZE / 2; + + return VectorInt2{xPoint, yPoint}; +} + +int FLOOR_INFO::SectorPlane(int x, int z) +{ + auto vector = GetSectorPoint(x, z); + auto matrix = Matrix::CreateRotationZ(FloorCollision.SplitAngle); + auto result = Vector2::Transform(Vector2(vector.x, vector.y), matrix); + + return result.x < 0 ? 0 : 1; +} + +std::optional FLOOR_INFO::RoomBelow(int plane) +{ + auto room = FloorCollision.Portals[plane]; + return room != -1 ? std::optional{room} : std::nullopt; +} + +std::optional FLOOR_INFO::RoomBelow(int x, int z) +{ + return RoomBelow(SectorPlane(x, z)); +} + +std::optional FLOOR_INFO::RoomAbove(int plane) +{ + auto room = CeilingCollision.Portals[plane]; + return room != -1 ? std::optional{room} : std::nullopt; +} + +std::optional FLOOR_INFO::RoomAbove(int x, int z) +{ + return RoomAbove(SectorPlane(x, z)); +} + +std::optional FLOOR_INFO::RoomSide() +{ + return WallPortal != -1 ? std::optional{WallPortal} : std::nullopt; +} + +int FLOOR_INFO::FloorHeight(int x, int z) +{ + auto plane = SectorPlane(x, z); + auto vector = GetSectorPoint(x, z); + + return FloorCollision.Planes[plane].x * vector.x + FloorCollision.Planes[plane].y * vector.y + FloorCollision.Planes[plane].z; +} + +int FLOOR_INFO::CeilingHeight(int x, int z) +{ + auto plane = SectorPlane(x, z); + auto vector = GetSectorPoint(x, z); + + return CeilingCollision.Planes[plane].x * vector.x + CeilingCollision.Planes[plane].y * vector.y + CeilingCollision.Planes[plane].z; } diff --git a/TR5Main/Game/floordata.h b/TR5Main/Game/floordata.h index de935bc6c..bfa944e54 100644 --- a/TR5Main/Game/floordata.h +++ b/TR5Main/Game/floordata.h @@ -1,6 +1,5 @@ #pragma once - -struct ROOM_INFO; +#include "trmath.h" struct SECTOR_COLLISION_INFO { @@ -9,12 +8,6 @@ struct SECTOR_COLLISION_INFO Vector3 Planes[2]; }; -struct SECTOR_POSITION -{ - int x; - int y; -}; - class FLOOR_INFO { public: @@ -30,7 +23,20 @@ public: SECTOR_COLLISION_INFO CeilingCollision; int WallPortal; - static SECTOR_POSITION GetSectorPosition(ROOM_INFO* room, int x, int z); - static FLOOR_INFO& GetFloor(ROOM_INFO* room, int x, int z); - static FLOOR_INFO& GetFloor(ROOM_INFO* room, SECTOR_POSITION pos); + static VectorInt2 GetRoomPosition(int roomNumber, int x, int z); + static FLOOR_INFO& GetFloor(int roomNumber, VectorInt2 pos); + static FLOOR_INFO& GetFloor(int roomNumber, int x, int z); + static int GetBottomRoom(int startRoomNumber, int x, int z); + static int GetTopRoom(int startRoomNumber, int x, int z); + static int GetRoom(int startRoomNumber, int x, int y, int z); + static VectorInt2 GetSectorPoint(int x, int z); + + int SectorPlane(int x, int z); + std::optional RoomBelow(int plane); + std::optional RoomBelow(int x, int z); + std::optional RoomAbove(int plane); + std::optional RoomAbove(int x, int z); + std::optional RoomSide(); + int FloorHeight(int x, int z); + int CeilingHeight(int x, int z); }; diff --git a/TR5Main/Game/trmath.h b/TR5Main/Game/trmath.h index 0bd2da3bd..40af9f5ad 100644 --- a/TR5Main/Game/trmath.h +++ b/TR5Main/Game/trmath.h @@ -1,6 +1,19 @@ #pragma once #include "phd_global.h" +struct VectorInt2 +{ + int x; + int y; +}; + +struct VectorInt3 +{ + int x; + int y; + int z; +}; + constexpr auto PI = 3.14159265358979323846f; constexpr auto RADIAN = 0.01745329252f; constexpr auto ONE_DEGREE = 182;