TombEngine/TR5Main/Game/floordata.cpp

248 lines
6 KiB
C++
Raw Normal View History

2020-09-17 00:08:10 -03:00
#include "framework.h"
#include "trmath.h"
#include "floordata.h"
#include "room.h"
#include "level.h"
2020-09-15 11:01:24 -03:00
VectorInt2 FLOOR_INFO::GetRoomPosition(int roomNumber, int x, int z)
2020-09-14 00:19:05 -03:00
{
2020-09-19 20:09:57 -03:00
auto room = &g_Level.Rooms[roomNumber];
auto xRoom = (z - room->z) / WALL_SIZE;
auto yRoom = (x - room->x) / WALL_SIZE;
auto pos = VectorInt2{xRoom, yRoom};
2020-09-17 00:08:10 -03:00
if (pos.x < 0)
{
pos.x = 0;
}
2020-09-19 20:09:57 -03:00
else if (pos.x > room->xSize - 1)
2020-09-17 00:08:10 -03:00
{
2020-09-19 20:09:57 -03:00
pos.x = room->xSize - 1;
2020-09-17 00:08:10 -03:00
}
if (pos.y < 0)
{
pos.y = 0;
}
2020-09-19 20:09:57 -03:00
else if (pos.y > room->ySize - 1)
2020-09-17 00:08:10 -03:00
{
2020-09-19 20:09:57 -03:00
pos.y = room->ySize - 1;
2020-09-17 00:08:10 -03:00
}
return pos;
2020-09-14 00:19:05 -03:00
}
2020-09-19 20:09:57 -03:00
FLOOR_INFO* FLOOR_INFO::GetFloor(int roomNumber, VectorInt2 pos)
2020-09-15 11:01:24 -03:00
{
2020-09-19 20:09:57 -03:00
auto room = &g_Level.Rooms[roomNumber];
return &room->floor[room->xSize * pos.y + pos.x];
2020-09-15 11:01:24 -03:00
}
2020-09-19 20:09:57 -03:00
FLOOR_INFO* FLOOR_INFO::GetFloor(int roomNumber, int x, int z)
2020-09-15 11:01:24 -03:00
{
return GetFloor(roomNumber, GetRoomPosition(roomNumber, x, z));
}
2020-09-19 20:09:57 -03:00
FLOOR_INFO* FLOOR_INFO::GetBottomFloor(int startRoomNumber, int x, int z, bool first)
2020-09-15 11:01:24 -03:00
{
auto roomNumber = startRoomNumber;
2020-09-17 00:08:10 -03:00
auto floor = GetFloor(roomNumber, x, z);
2020-09-19 20:09:57 -03:00
auto plane = floor->SectorPlane(x, z);
auto roomBelow = floor->RoomBelow(plane);
2020-09-15 11:01:24 -03:00
2020-09-19 20:09:57 -03:00
while ((!first || floor->IsWall(plane)) && roomBelow)
2020-09-15 11:01:24 -03:00
{
2020-09-19 20:09:57 -03:00
roomNumber = GetFloor(*roomBelow, x, z)->RoomSide().value_or(*roomBelow);
2020-09-17 00:08:10 -03:00
floor = GetFloor(roomNumber, x, z);
2020-09-19 20:09:57 -03:00
plane = floor->SectorPlane(x, z);
roomBelow = floor->RoomBelow(plane);
2020-09-15 11:01:24 -03:00
}
2020-09-17 00:08:10 -03:00
return floor;
2020-09-15 11:01:24 -03:00
}
2020-09-19 20:09:57 -03:00
FLOOR_INFO* FLOOR_INFO::GetTopFloor(int startRoomNumber, int x, int z, bool first)
2020-09-14 00:19:05 -03:00
{
2020-09-15 11:01:24 -03:00
auto roomNumber = startRoomNumber;
2020-09-17 00:08:10 -03:00
auto floor = GetFloor(roomNumber, x, z);
2020-09-19 20:09:57 -03:00
auto plane = floor->SectorPlane(x, z);
auto roomAbove = floor->RoomAbove(plane);
2020-09-15 11:01:24 -03:00
2020-09-19 20:09:57 -03:00
while ((!first || floor->IsWall(plane)) && roomAbove)
2020-09-15 11:01:24 -03:00
{
2020-09-19 20:09:57 -03:00
roomNumber = GetFloor(*roomAbove, x, z)->RoomSide().value_or(*roomAbove);
2020-09-17 00:08:10 -03:00
floor = GetFloor(roomNumber, x, z);
2020-09-19 20:09:57 -03:00
plane = floor->SectorPlane(x, z);
roomAbove = floor->RoomAbove(plane);
2020-09-15 11:01:24 -03:00
}
2020-09-17 00:08:10 -03:00
return floor;
}
2020-09-18 23:11:04 -03:00
FLOOR_INFO* FLOOR_INFO::GetNearBottomFloor(int startRoomNumber, int x, int z)
2020-09-17 00:08:10 -03:00
{
2020-09-19 20:09:57 -03:00
auto roomNumber = GetFloor(startRoomNumber, x, z)->RoomSide().value_or(startRoomNumber);
2020-09-17 00:08:10 -03:00
auto floor = GetFloor(roomNumber, x, z);
2020-09-19 20:09:57 -03:00
if (floor->IsWall(x, z))
2020-09-17 00:08:10 -03:00
{
floor = GetTopFloor(roomNumber, x, z, true);
}
else
{
floor = GetBottomFloor(roomNumber, x, z);
}
2020-09-19 20:09:57 -03:00
return floor->IsWall(x, z) ? nullptr : floor;
2020-09-17 00:08:10 -03:00
}
2020-09-18 23:11:04 -03:00
FLOOR_INFO* FLOOR_INFO::GetNearTopFloor(int startRoomNumber, int x, int z)
2020-09-17 00:08:10 -03:00
{
2020-09-19 20:09:57 -03:00
auto roomNumber = GetFloor(startRoomNumber, x, z)->RoomSide().value_or(startRoomNumber);
2020-09-17 00:08:10 -03:00
auto floor = GetFloor(roomNumber, x, z);
2020-09-19 20:09:57 -03:00
if (floor->IsWall(x, z))
2020-09-17 00:08:10 -03:00
{
floor = GetBottomFloor(roomNumber, x, z, true);
}
else
{
floor = GetTopFloor(roomNumber, x, z);
}
2020-09-19 20:09:57 -03:00
return floor->IsWall(x, z) ? nullptr : floor;
2020-09-15 11:01:24 -03:00
}
int FLOOR_INFO::GetRoom(int startRoomNumber, int x, int y, int z)
{
auto roomNumber = startRoomNumber;
auto pos = GetRoomPosition(roomNumber, x, z);
2020-09-19 20:09:57 -03:00
auto room = &g_Level.Rooms[roomNumber];
2020-09-15 11:01:24 -03:00
auto floor = GetFloor(roomNumber, pos);
2020-09-19 20:09:57 -03:00
if (pos.x > 0 && pos.y > 0 && pos.x < room->xSize - 1 && pos.y < room->ySize - 1)
2020-09-15 11:01:24 -03:00
{
2020-09-19 20:09:57 -03:00
auto plane = floor->SectorPlane(x, z);
2020-09-17 00:08:10 -03:00
2020-09-19 20:09:57 -03:00
if (!floor->IsWall(plane))
2020-09-15 11:01:24 -03:00
{
2020-09-19 20:09:57 -03:00
if (y > floor->FloorHeight(x, z))
2020-09-17 00:08:10 -03:00
{
2020-09-19 20:09:57 -03:00
roomNumber = floor->RoomBelow(plane).value_or(roomNumber);
2020-09-17 00:08:10 -03:00
}
2020-09-19 20:09:57 -03:00
else if (y < floor->CeilingHeight(x, z))
2020-09-17 00:08:10 -03:00
{
2020-09-19 20:09:57 -03:00
roomNumber = floor->RoomAbove(plane).value_or(roomNumber);
2020-09-17 00:08:10 -03:00
}
2020-09-15 11:01:24 -03:00
}
}
else
{
2020-09-19 20:09:57 -03:00
roomNumber = floor->RoomSide().value_or(roomNumber);
2020-09-15 11:01:24 -03:00
}
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};
2020-09-14 00:19:05 -03:00
}
2020-09-19 01:29:52 -03:00
std::optional<int> FLOOR_INFO::GetFloorHeight(int startRoomNumber, int x, int z)
2020-09-17 00:08:10 -03:00
{
2020-09-18 23:11:04 -03:00
auto floor = GetNearBottomFloor(startRoomNumber, x, z);
2020-09-17 00:08:10 -03:00
return floor ? std::optional<int>{floor->FloorHeight(x, z)} : std::nullopt;
}
2020-09-19 01:29:52 -03:00
std::optional<int> FLOOR_INFO::GetCeilingHeight(int startRoomNumber, int x, int z)
2020-09-17 00:08:10 -03:00
{
2020-09-18 23:11:04 -03:00
auto floor = GetNearTopFloor(startRoomNumber, x, z);
2020-09-17 00:08:10 -03:00
return floor ? std::optional<int>{floor->CeilingHeight(x, z)} : std::nullopt;
}
2020-09-15 11:01:24 -03:00
int FLOOR_INFO::SectorPlane(int x, int z)
2020-09-14 00:19:05 -03:00
{
2020-09-15 11:01:24 -03:00
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<int> FLOOR_INFO::RoomBelow(int plane)
2020-09-17 00:08:10 -03:00
{
2020-09-15 11:01:24 -03:00
auto room = FloorCollision.Portals[plane];
return room != -1 ? std::optional<int>{room} : std::nullopt;
}
std::optional<int> FLOOR_INFO::RoomBelow(int x, int z)
{
return RoomBelow(SectorPlane(x, z));
}
std::optional<int> FLOOR_INFO::RoomAbove(int plane)
2020-09-17 00:08:10 -03:00
{
2020-09-15 11:01:24 -03:00
auto room = CeilingCollision.Portals[plane];
return room != -1 ? std::optional<int>{room} : std::nullopt;
}
std::optional<int> FLOOR_INFO::RoomAbove(int x, int z)
{
return RoomAbove(SectorPlane(x, z));
}
std::optional<int> FLOOR_INFO::RoomSide()
{
return WallPortal != -1 ? std::optional<int>{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;
2020-09-14 00:19:05 -03:00
}
2020-09-17 00:08:10 -03:00
Vector2 FLOOR_INFO::FloorSlope(int plane)
{
return Vector2{FloorCollision.Planes[plane].x, FloorCollision.Planes[plane].y};
}
Vector2 FLOOR_INFO::FloorSlope(int x, int z)
{
return FloorSlope(SectorPlane(x, z));
}
Vector2 FLOOR_INFO::CeilingSlope(int plane)
{
return Vector2{CeilingCollision.Planes[plane].x, CeilingCollision.Planes[plane].y};
}
Vector2 FLOOR_INFO::CeilingSlope(int x, int z)
{
return CeilingSlope(SectorPlane(x, z));
}
bool FLOOR_INFO::IsWall(int plane)
{
return FloorCollision.SplitAngle == CeilingCollision.SplitAngle && FloorCollision.Planes[plane] == CeilingCollision.Planes[plane];
}
bool FLOOR_INFO::IsWall(int x, int z)
{
return IsWall(SectorPlane(x, z));
}