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-21 23:59:57 -03:00
|
|
|
#include "setup.h"
|
2020-09-17 00:08:10 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
using namespace T5M::Floordata;
|
|
|
|
|
|
|
|
int FLOOR_INFO::SectorPlane(int x, int z) const
|
2020-09-14 00:19:05 -03:00
|
|
|
{
|
2020-11-10 22:31:29 -03:00
|
|
|
const auto point = GetSectorPoint(x, z);
|
|
|
|
auto vector = Vector2(point.x, point.y);
|
|
|
|
const auto matrix = Matrix::CreateRotationZ(FloorCollision.SplitAngle);
|
|
|
|
Vector2::Transform(vector, matrix, vector);
|
2020-09-17 00:08:10 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
return vector.x < 0 ? 0 : 1;
|
|
|
|
}
|
2020-09-17 00:08:10 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
std::optional<int> FLOOR_INFO::RoomBelow(int plane) const
|
|
|
|
{
|
|
|
|
const auto room = FloorCollision.Portals[plane];
|
|
|
|
return room != -1 ? std::optional{room} : std::nullopt;
|
|
|
|
}
|
2020-09-17 00:08:10 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
std::optional<int> FLOOR_INFO::RoomBelow(int x, int z) const
|
|
|
|
{
|
|
|
|
return RoomBelow(SectorPlane(x, z));
|
2020-09-14 00:19:05 -03:00
|
|
|
}
|
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
std::optional<int> FLOOR_INFO::RoomAbove(int plane) const
|
2020-09-15 11:01:24 -03:00
|
|
|
{
|
2020-11-10 22:31:29 -03:00
|
|
|
const auto room = CeilingCollision.Portals[plane];
|
|
|
|
return room != -1 ? std::optional{room} : std::nullopt;
|
2020-09-15 11:01:24 -03:00
|
|
|
}
|
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
std::optional<int> FLOOR_INFO::RoomAbove(int x, int z) const
|
2020-09-15 11:01:24 -03:00
|
|
|
{
|
2020-11-10 22:31:29 -03:00
|
|
|
return RoomAbove(SectorPlane(x, z));
|
2020-09-15 11:01:24 -03:00
|
|
|
}
|
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
std::optional<int> FLOOR_INFO::RoomSide() const
|
2020-09-15 11:01:24 -03:00
|
|
|
{
|
2020-11-10 22:31:29 -03:00
|
|
|
return WallPortal != -1 ? std::optional{WallPortal} : std::nullopt;
|
|
|
|
}
|
2020-09-15 11:01:24 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
int FLOOR_INFO::FloorHeight(int x, int z) const
|
|
|
|
{
|
|
|
|
const auto plane = SectorPlane(x, z);
|
|
|
|
const auto vector = GetSectorPoint(x, z);
|
2020-09-15 11:01:24 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
return FloorCollision.Planes[plane].x * vector.x + FloorCollision.Planes[plane].y * vector.y + FloorCollision.Planes[plane].z;
|
2020-09-15 11:01:24 -03:00
|
|
|
}
|
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
int FLOOR_INFO::CeilingHeight(int x, int z) const
|
2020-09-14 00:19:05 -03:00
|
|
|
{
|
2020-11-10 22:31:29 -03:00
|
|
|
const auto plane = SectorPlane(x, z);
|
|
|
|
const auto vector = GetSectorPoint(x, z);
|
2020-09-15 11:01:24 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
return CeilingCollision.Planes[plane].x * vector.x + CeilingCollision.Planes[plane].y * vector.y + CeilingCollision.Planes[plane].z;
|
|
|
|
}
|
2020-09-15 11:01:24 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
Vector2 FLOOR_INFO::FloorSlope(int plane) const
|
|
|
|
{
|
|
|
|
return Vector2{FloorCollision.Planes[plane].x, FloorCollision.Planes[plane].y};
|
2020-09-17 00:08:10 -03:00
|
|
|
}
|
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
Vector2 FLOOR_INFO::FloorSlope(int x, int z) const
|
2020-09-17 00:08:10 -03:00
|
|
|
{
|
2020-11-10 22:31:29 -03:00
|
|
|
return FloorSlope(SectorPlane(x, z));
|
|
|
|
}
|
2020-09-22 23:38:48 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
Vector2 FLOOR_INFO::CeilingSlope(int plane) const
|
|
|
|
{
|
|
|
|
return Vector2{CeilingCollision.Planes[plane].x, CeilingCollision.Planes[plane].y};
|
|
|
|
}
|
2020-09-22 23:38:48 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
Vector2 FLOOR_INFO::CeilingSlope(int x, int z) const
|
|
|
|
{
|
|
|
|
return CeilingSlope(SectorPlane(x, z));
|
|
|
|
}
|
2020-09-17 00:08:10 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
bool FLOOR_INFO::IsWall(int plane) const
|
|
|
|
{
|
|
|
|
return FloorCollision.SplitAngle == CeilingCollision.SplitAngle && FloorCollision.Planes[plane] == CeilingCollision.Planes[plane];
|
2020-09-17 00:08:10 -03:00
|
|
|
}
|
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
bool FLOOR_INFO::IsWall(int x, int z) const
|
2020-09-17 00:08:10 -03:00
|
|
|
{
|
2020-11-10 22:31:29 -03:00
|
|
|
return IsWall(SectorPlane(x, z));
|
|
|
|
}
|
2020-09-22 23:38:48 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
namespace T5M::Floordata
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2020-11-10 22:31:29 -03:00
|
|
|
VectorInt2 GetRoomPosition(int roomNumber, int x, int z)
|
2020-09-22 23:38:48 -03:00
|
|
|
{
|
2020-11-10 22:31:29 -03:00
|
|
|
const auto& room = g_Level.Rooms[roomNumber];
|
|
|
|
const auto xRoom = (z - room.z) / SECTOR(1);
|
|
|
|
const auto yRoom = (x - room.x) / SECTOR(1);
|
|
|
|
auto pos = VectorInt2{xRoom, yRoom};
|
|
|
|
|
|
|
|
if (pos.x < 0)
|
|
|
|
{
|
|
|
|
pos.x = 0;
|
|
|
|
}
|
|
|
|
else if (pos.x > room.xSize - 1)
|
|
|
|
{
|
|
|
|
pos.x = room.xSize - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pos.y < 0)
|
|
|
|
{
|
|
|
|
pos.y = 0;
|
|
|
|
}
|
|
|
|
else if (pos.y > room.ySize - 1)
|
|
|
|
{
|
|
|
|
pos.y = room.ySize - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pos;
|
2020-09-22 23:38:48 -03:00
|
|
|
}
|
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
FLOOR_INFO& GetFloor(int roomNumber, const VectorInt2 pos)
|
2020-09-17 00:08:10 -03:00
|
|
|
{
|
2020-11-10 22:31:29 -03:00
|
|
|
auto& room = g_Level.Rooms[roomNumber];
|
|
|
|
return room.floor[room.xSize * pos.y + pos.x];
|
2020-09-17 00:08:10 -03:00
|
|
|
}
|
2020-11-10 22:31:29 -03:00
|
|
|
|
|
|
|
FLOOR_INFO& GetFloor(int roomNumber, int x, int z)
|
2020-09-17 00:08:10 -03:00
|
|
|
{
|
2020-11-10 22:31:29 -03:00
|
|
|
return GetFloor(roomNumber, GetRoomPosition(roomNumber, x, z));
|
2020-09-17 00:08:10 -03:00
|
|
|
}
|
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
std::tuple<FLOOR_INFO&, int> GetBottomFloor(int startRoomNumber, int x, int z, bool first)
|
|
|
|
{
|
|
|
|
auto roomNumber = startRoomNumber;
|
|
|
|
auto floor = &GetFloor(roomNumber, x, z);
|
|
|
|
auto plane = floor->SectorPlane(x, z);
|
|
|
|
auto roomBelow = floor->RoomBelow(plane);
|
2020-09-15 11:01:24 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
while ((!first || floor->IsWall(plane)) && roomBelow)
|
|
|
|
{
|
|
|
|
roomNumber = *roomBelow;
|
|
|
|
floor = &GetFloor(roomNumber, x, z);
|
|
|
|
const auto roomSide = floor->RoomSide();
|
|
|
|
if (roomSide)
|
|
|
|
{
|
|
|
|
roomNumber = *roomSide;
|
|
|
|
floor = &GetFloor(roomNumber, x, z);
|
|
|
|
}
|
|
|
|
plane = floor->SectorPlane(x, z);
|
|
|
|
roomBelow = floor->RoomBelow(plane);
|
|
|
|
}
|
2020-09-22 23:38:48 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
return std::tie(*floor, roomNumber);
|
|
|
|
}
|
2020-09-22 23:38:48 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
std::tuple<FLOOR_INFO&, int> GetTopFloor(int startRoomNumber, int x, int z, bool first)
|
2020-09-15 11:01:24 -03:00
|
|
|
{
|
2020-11-10 22:31:29 -03:00
|
|
|
auto roomNumber = startRoomNumber;
|
|
|
|
auto floor = &GetFloor(roomNumber, x, z);
|
|
|
|
auto plane = floor->SectorPlane(x, z);
|
|
|
|
auto roomAbove = floor->RoomAbove(plane);
|
|
|
|
|
|
|
|
while ((!first || floor->IsWall(plane)) && roomAbove)
|
2020-09-15 11:01:24 -03:00
|
|
|
{
|
2020-11-10 22:31:29 -03:00
|
|
|
roomNumber = *roomAbove;
|
|
|
|
floor = &GetFloor(roomNumber, x, z);
|
|
|
|
const auto roomSide = floor->RoomSide();
|
|
|
|
if (roomSide)
|
|
|
|
{
|
|
|
|
roomNumber = *roomSide;
|
|
|
|
floor = &GetFloor(roomNumber, x, z);
|
|
|
|
}
|
|
|
|
plane = floor->SectorPlane(x, z);
|
|
|
|
roomAbove = floor->RoomAbove(plane);
|
2020-09-20 23:16:21 -03:00
|
|
|
}
|
2020-09-22 23:38:48 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
return std::tie(*floor, roomNumber);
|
2020-09-22 23:38:48 -03:00
|
|
|
}
|
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
std::tuple<FLOOR_INFO&, int> GetNearestBottomFloor(int startRoomNumber, int x, int z)
|
|
|
|
{
|
|
|
|
auto roomNumber = startRoomNumber;
|
|
|
|
auto floor = &GetFloor(roomNumber, x, z);
|
2020-09-22 23:38:48 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
const auto roomSide = floor->RoomSide();
|
|
|
|
if (roomSide)
|
|
|
|
{
|
|
|
|
roomNumber = *roomSide;
|
|
|
|
floor = &GetFloor(roomNumber, x, z);
|
|
|
|
}
|
2020-09-22 23:38:48 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
return floor->IsWall(x, z) ? GetTopFloor(roomNumber, x, z, true) : GetBottomFloor(roomNumber, x, z);
|
|
|
|
}
|
2020-09-22 23:38:48 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
std::tuple<FLOOR_INFO&, int> GetNearestTopFloor(int startRoomNumber, int x, int z)
|
2020-09-22 23:38:48 -03:00
|
|
|
{
|
2020-11-10 22:31:29 -03:00
|
|
|
auto roomNumber = startRoomNumber;
|
|
|
|
auto floor = &GetFloor(roomNumber, x, z);
|
|
|
|
|
|
|
|
const auto roomSide = floor->RoomSide();
|
2020-09-22 23:38:48 -03:00
|
|
|
if (roomSide)
|
2020-09-20 23:16:21 -03:00
|
|
|
{
|
2020-09-22 23:38:48 -03:00
|
|
|
roomNumber = *roomSide;
|
2020-11-10 22:31:29 -03:00
|
|
|
floor = &GetFloor(roomNumber, x, z);
|
2020-09-15 11:01:24 -03:00
|
|
|
}
|
2020-09-22 23:38:48 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
return floor->IsWall(x, z) ? GetBottomFloor(roomNumber, x, z, true) : GetTopFloor(roomNumber, x, z);
|
2020-09-22 23:38:48 -03:00
|
|
|
}
|
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
std::optional<int> GetBottomRoom(int startRoomNumber, int x, int y, int z)
|
2020-09-22 23:38:48 -03:00
|
|
|
{
|
2020-11-10 22:31:29 -03:00
|
|
|
auto roomNumber = startRoomNumber;
|
|
|
|
auto floor = &GetFloor(roomNumber, x, z);
|
|
|
|
auto plane = floor->SectorPlane(x, z);
|
2020-09-22 23:38:48 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
if (!floor->IsWall(plane) && y <= floor->FloorHeight(x, z) && y >= floor->CeilingHeight(x, z))
|
|
|
|
return std::nullopt;
|
2020-09-22 23:38:48 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
auto roomBelow = floor->RoomBelow(plane);
|
2020-09-15 11:01:24 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
while (roomBelow)
|
|
|
|
{
|
|
|
|
roomNumber = *roomBelow;
|
|
|
|
floor = &GetFloor(roomNumber, x, z);
|
|
|
|
const auto roomSide = floor->RoomSide();
|
|
|
|
if (roomSide)
|
|
|
|
{
|
|
|
|
roomNumber = *roomSide;
|
|
|
|
floor = &GetFloor(roomNumber, x, z);
|
|
|
|
}
|
|
|
|
plane = floor->SectorPlane(x, z);
|
2020-09-15 11:01:24 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
if (!floor->IsWall(plane) && y <= floor->FloorHeight(x, z) && y >= floor->CeilingHeight(x, z))
|
|
|
|
return std::optional{roomNumber};
|
2020-09-15 11:01:24 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
roomBelow = floor->RoomBelow(plane);
|
|
|
|
}
|
2020-09-14 00:19:05 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
return std::nullopt;
|
|
|
|
}
|
2020-09-21 23:59:57 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
std::optional<int> GetTopRoom(int startRoomNumber, int x, int y, int z)
|
2020-09-21 23:59:57 -03:00
|
|
|
{
|
2020-11-10 22:31:29 -03:00
|
|
|
auto roomNumber = startRoomNumber;
|
|
|
|
auto floor = &GetFloor(roomNumber, x, z);
|
|
|
|
auto plane = floor->SectorPlane(x, z);
|
|
|
|
|
|
|
|
if (!floor->IsWall(plane) && y <= floor->FloorHeight(x, z) && y >= floor->CeilingHeight(x, z))
|
|
|
|
return std::nullopt;
|
|
|
|
|
|
|
|
auto roomAbove = floor->RoomAbove(plane);
|
|
|
|
|
|
|
|
while (roomAbove)
|
2020-09-21 23:59:57 -03:00
|
|
|
{
|
2020-11-10 22:31:29 -03:00
|
|
|
roomNumber = *roomAbove;
|
|
|
|
floor = &GetFloor(roomNumber, x, z);
|
|
|
|
const auto roomSide = floor->RoomSide();
|
|
|
|
if (roomSide)
|
2020-09-21 23:59:57 -03:00
|
|
|
{
|
2020-11-10 22:31:29 -03:00
|
|
|
roomNumber = *roomSide;
|
|
|
|
floor = &GetFloor(roomNumber, x, z);
|
2020-09-21 23:59:57 -03:00
|
|
|
}
|
2020-11-10 22:31:29 -03:00
|
|
|
plane = floor->SectorPlane(x, z);
|
|
|
|
|
|
|
|
if (!floor->IsWall(plane) && y <= floor->FloorHeight(x, z) && y >= floor->CeilingHeight(x, z))
|
|
|
|
return std::optional{roomNumber};
|
|
|
|
|
|
|
|
roomAbove = floor->RoomAbove(plane);
|
2020-09-21 23:59:57 -03:00
|
|
|
}
|
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
return std::nullopt;
|
2020-09-21 23:59:57 -03:00
|
|
|
}
|
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
int GetRoom(int startRoomNumber, int x, int y, int z)
|
|
|
|
{
|
|
|
|
auto roomNumber = startRoomNumber;
|
|
|
|
auto floor = &GetFloor(roomNumber, x, z);
|
2020-09-17 00:08:10 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
const auto roomSide = floor->RoomSide();
|
|
|
|
if (roomSide)
|
|
|
|
{
|
|
|
|
roomNumber = *roomSide;
|
|
|
|
floor = &GetFloor(roomNumber, x, z);
|
|
|
|
}
|
2020-09-21 23:59:57 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
const auto roomBelow = GetBottomRoom(roomNumber, x, y, z);
|
|
|
|
const auto roomAbove = GetTopRoom(roomNumber, x, y, z);
|
|
|
|
|
|
|
|
if (roomBelow)
|
2020-09-21 23:59:57 -03:00
|
|
|
{
|
2020-11-10 22:31:29 -03:00
|
|
|
roomNumber = *roomBelow;
|
|
|
|
}
|
|
|
|
else if (roomAbove)
|
|
|
|
{
|
|
|
|
roomNumber = *roomAbove;
|
2020-09-21 23:59:57 -03:00
|
|
|
}
|
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
return roomNumber;
|
2020-09-21 23:59:57 -03:00
|
|
|
}
|
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
VectorInt2 GetSectorPoint(int x, int z)
|
|
|
|
{
|
|
|
|
const auto xPoint = x % SECTOR(1) - SECTOR(1) / 2;
|
|
|
|
const auto yPoint = z % SECTOR(1) - SECTOR(1) / 2;
|
2020-09-21 23:59:57 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
return VectorInt2{xPoint, yPoint};
|
|
|
|
}
|
2020-09-21 23:59:57 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
std::optional<int> GetFloorHeight(int startRoomNumber, int x, int y, int z, bool raw)
|
|
|
|
{
|
|
|
|
const auto [floor, roomNumber] = GetNearestBottomFloor(startRoomNumber, x, z);
|
2020-09-21 23:59:57 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
if (!floor.IsWall(x, z))
|
|
|
|
{
|
2020-12-20 14:04:27 -03:00
|
|
|
auto floorHeight = floor.FloorHeight(x, z);
|
|
|
|
auto height = floorHeight;
|
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
if (!raw)
|
|
|
|
{
|
2020-12-20 14:04:27 -03:00
|
|
|
if (y > height)
|
|
|
|
y = height;
|
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
auto list = std::vector<int>{};
|
|
|
|
GetRoomList(roomNumber, x, z, list);
|
|
|
|
|
2020-12-20 14:04:27 -03:00
|
|
|
auto it = list.begin();
|
|
|
|
while (it != list.end())
|
2020-11-10 22:31:29 -03:00
|
|
|
{
|
2020-12-20 14:04:27 -03:00
|
|
|
auto reset = false;
|
|
|
|
for (auto itemNumber = g_Level.Rooms[*it].itemNumber; itemNumber != NO_ITEM; itemNumber = g_Level.Items[itemNumber].nextItem)
|
2020-11-10 22:31:29 -03:00
|
|
|
{
|
|
|
|
const auto& item = g_Level.Items[itemNumber];
|
|
|
|
if (Objects[item.objectNumber].floor)
|
|
|
|
{
|
2020-11-11 15:01:45 -03:00
|
|
|
const auto [itemHeight, inside] = Objects[item.objectNumber].floor(itemNumber, x, y, z);
|
|
|
|
if (itemHeight)
|
|
|
|
{
|
|
|
|
if (inside)
|
|
|
|
{
|
2020-12-20 14:04:27 -03:00
|
|
|
y = *itemHeight;
|
|
|
|
reset = true;
|
2020-11-11 15:01:45 -03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (*itemHeight >= y && *itemHeight < height)
|
|
|
|
height = *itemHeight;
|
|
|
|
}
|
2020-11-10 22:31:29 -03:00
|
|
|
}
|
|
|
|
}
|
2020-11-11 15:01:45 -03:00
|
|
|
|
2020-12-20 14:04:27 -03:00
|
|
|
if (reset)
|
|
|
|
{
|
|
|
|
height = floorHeight;
|
|
|
|
it = list.begin();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
++it;
|
|
|
|
}
|
2020-11-10 22:31:29 -03:00
|
|
|
}
|
|
|
|
}
|
2020-09-21 23:59:57 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
return std::optional{height};
|
|
|
|
}
|
2020-09-17 00:08:10 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
return std::nullopt;
|
|
|
|
}
|
2020-09-15 11:01:24 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
std::optional<int> GetCeilingHeight(int startRoomNumber, int x, int y, int z, bool raw)
|
|
|
|
{
|
|
|
|
const auto [floor, roomNumber] = GetNearestTopFloor(startRoomNumber, x, z);
|
2020-09-15 11:01:24 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
if (!floor.IsWall(x, z))
|
|
|
|
{
|
2020-12-20 14:04:27 -03:00
|
|
|
auto ceilingHeight = floor.CeilingHeight(x, z);
|
|
|
|
auto height = ceilingHeight;
|
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
if (!raw)
|
|
|
|
{
|
2020-12-20 14:04:27 -03:00
|
|
|
if (y < height)
|
|
|
|
y = height;
|
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
auto list = std::vector<int>{};
|
|
|
|
GetRoomList(roomNumber, x, z, list);
|
|
|
|
|
2020-12-20 14:04:27 -03:00
|
|
|
auto it = list.begin();
|
|
|
|
while (it != list.end())
|
2020-11-10 22:31:29 -03:00
|
|
|
{
|
2020-12-20 14:04:27 -03:00
|
|
|
auto reset = false;
|
|
|
|
for (auto itemNumber = g_Level.Rooms[*it].itemNumber; itemNumber != NO_ITEM; itemNumber = g_Level.Items[itemNumber].nextItem)
|
2020-11-10 22:31:29 -03:00
|
|
|
{
|
|
|
|
const auto& item = g_Level.Items[itemNumber];
|
|
|
|
if (Objects[item.objectNumber].ceiling)
|
|
|
|
{
|
2020-11-11 15:01:45 -03:00
|
|
|
const auto [itemHeight, inside] = Objects[item.objectNumber].ceiling(itemNumber, x, y, z);
|
|
|
|
if (itemHeight)
|
|
|
|
{
|
|
|
|
if (inside)
|
|
|
|
{
|
2020-12-20 14:04:27 -03:00
|
|
|
y = *itemHeight;
|
|
|
|
reset = true;
|
2020-11-11 15:01:45 -03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (*itemHeight <= y && *itemHeight > height)
|
|
|
|
height = *itemHeight;
|
|
|
|
}
|
2020-11-10 22:31:29 -03:00
|
|
|
}
|
|
|
|
}
|
2020-11-11 15:01:45 -03:00
|
|
|
|
2020-12-20 14:04:27 -03:00
|
|
|
if (reset)
|
|
|
|
{
|
|
|
|
height = ceilingHeight;
|
|
|
|
it = list.begin();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
++it;
|
|
|
|
}
|
2020-11-10 22:31:29 -03:00
|
|
|
}
|
|
|
|
}
|
2020-09-15 11:01:24 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
return std::optional{height};
|
|
|
|
}
|
2020-09-15 11:01:24 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
return std::nullopt;
|
|
|
|
}
|
2020-09-15 11:01:24 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
void GetBottomRoomList(int startRoomNumber, int x, int z, std::vector<int>& list)
|
|
|
|
{
|
|
|
|
auto roomNumber = startRoomNumber;
|
|
|
|
auto floor = &GetFloor(roomNumber, x, z);
|
|
|
|
auto plane = floor->SectorPlane(x, z);
|
|
|
|
auto roomBelow = floor->RoomBelow(plane);
|
2020-09-15 11:01:24 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
while (!floor->IsWall(plane) && roomBelow)
|
|
|
|
{
|
|
|
|
roomNumber = *roomBelow;
|
|
|
|
floor = &GetFloor(roomNumber, x, z);
|
|
|
|
const auto roomSide = floor->RoomSide();
|
|
|
|
if (roomSide)
|
|
|
|
{
|
|
|
|
roomNumber = *roomSide;
|
|
|
|
floor = &GetFloor(roomNumber, x, z);
|
|
|
|
}
|
2020-09-15 11:01:24 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
plane = floor->SectorPlane(x, z);
|
|
|
|
roomBelow = floor->RoomBelow(plane);
|
2020-09-15 11:01:24 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
list.push_back(roomNumber);
|
|
|
|
}
|
|
|
|
}
|
2020-09-15 11:01:24 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
void GetTopRoomList(int startRoomNumber, int x, int z, std::vector<int>& list)
|
|
|
|
{
|
|
|
|
auto roomNumber = startRoomNumber;
|
|
|
|
auto floor = &GetFloor(roomNumber, x, z);
|
|
|
|
auto plane = floor->SectorPlane(x, z);
|
|
|
|
auto roomAbove = floor->RoomAbove(plane);
|
2020-09-15 11:01:24 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
while (!floor->IsWall(plane) && roomAbove)
|
|
|
|
{
|
|
|
|
roomNumber = *roomAbove;
|
|
|
|
floor = &GetFloor(roomNumber, x, z);
|
|
|
|
const auto roomSide = floor->RoomSide();
|
|
|
|
if (roomSide)
|
|
|
|
{
|
|
|
|
roomNumber = *roomSide;
|
|
|
|
floor = &GetFloor(roomNumber, x, z);
|
|
|
|
}
|
2020-09-17 00:08:10 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
plane = floor->SectorPlane(x, z);
|
|
|
|
roomAbove = floor->RoomAbove(plane);
|
2020-09-17 00:08:10 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
list.push_back(roomNumber);
|
|
|
|
}
|
|
|
|
}
|
2020-09-17 00:08:10 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
void GetRoomList(int startRoomNumber, int x, int z, std::vector<int>& list)
|
|
|
|
{
|
|
|
|
auto roomNumber = startRoomNumber;
|
|
|
|
auto floor = &GetFloor(roomNumber, x, z);
|
2020-09-17 00:08:10 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
const auto roomSide = floor->RoomSide();
|
|
|
|
if (roomSide)
|
|
|
|
{
|
|
|
|
roomNumber = *roomSide;
|
|
|
|
floor = &GetFloor(roomNumber, x, z);
|
|
|
|
}
|
2020-09-17 00:08:10 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
list.push_back(roomNumber);
|
2020-09-17 00:08:10 -03:00
|
|
|
|
2020-11-10 22:31:29 -03:00
|
|
|
GetBottomRoomList(roomNumber, x, z, list);
|
|
|
|
GetTopRoomList(roomNumber, x, z, list);
|
|
|
|
}
|
2020-09-17 00:08:10 -03:00
|
|
|
}
|