2021-09-17 16:07:53 +03:00
|
|
|
#include "framework.h"
|
2021-12-22 16:23:57 +03:00
|
|
|
#include "Game/room.h"
|
|
|
|
#include "Game/control/control.h"
|
|
|
|
#include "Game/control/lot.h"
|
|
|
|
#include "Game/control/volume.h"
|
|
|
|
#include "Renderer/Renderer11.h"
|
|
|
|
#include "Game/items.h"
|
2021-09-25 11:27:47 +02:00
|
|
|
|
2021-09-19 23:41:26 +03:00
|
|
|
using namespace TEN::Renderer;
|
2021-11-23 01:31:09 +03:00
|
|
|
using namespace TEN::Floordata;
|
2021-09-19 23:41:26 +03:00
|
|
|
|
|
|
|
byte FlipStatus = 0;
|
|
|
|
int FlipStats[MAX_FLIPMAP];
|
|
|
|
int FlipMap[MAX_FLIPMAP];
|
|
|
|
|
|
|
|
std::vector<short> OutsideRoomTable[OUTSIDE_SIZE][OUTSIDE_SIZE];
|
|
|
|
|
|
|
|
void DoFlipMap(short group)
|
|
|
|
{
|
|
|
|
ROOM_INFO temp;
|
|
|
|
|
|
|
|
for (size_t i = 0; i < g_Level.Rooms.size(); i++)
|
|
|
|
{
|
|
|
|
ROOM_INFO* r = &g_Level.Rooms[i];
|
|
|
|
|
|
|
|
if (r->flippedRoom >= 0 && r->flipNumber == group)
|
|
|
|
{
|
|
|
|
RemoveRoomFlipItems(r);
|
|
|
|
|
|
|
|
ROOM_INFO* flipped = &g_Level.Rooms[r->flippedRoom];
|
|
|
|
|
|
|
|
temp = *r;
|
|
|
|
*r = *flipped;
|
|
|
|
*flipped = temp;
|
|
|
|
|
|
|
|
r->flippedRoom = flipped->flippedRoom;
|
|
|
|
flipped->flippedRoom = -1;
|
|
|
|
|
|
|
|
r->itemNumber = flipped->itemNumber;
|
|
|
|
r->fxNumber = flipped->fxNumber;
|
|
|
|
|
|
|
|
AddRoomFlipItems(r);
|
|
|
|
|
|
|
|
g_Renderer.flipRooms(static_cast<short>(i), r->flippedRoom);
|
|
|
|
|
|
|
|
for (auto& fd : r->floor)
|
|
|
|
fd.Room = i;
|
|
|
|
for (auto& fd : flipped->floor)
|
|
|
|
fd.Room = r->flippedRoom;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-27 08:35:11 +02:00
|
|
|
FlipStatus = FlipStats[group] = !FlipStats[group];
|
2021-09-19 23:41:26 +03:00
|
|
|
|
|
|
|
for (int i = 0; i < ActiveCreatures.size(); i++)
|
|
|
|
{
|
|
|
|
ActiveCreatures[i]->LOT.targetBox = NO_BOX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AddRoomFlipItems(ROOM_INFO* r)
|
|
|
|
{
|
|
|
|
for (short linkNum = r->itemNumber; linkNum != NO_ITEM; linkNum = g_Level.Items[linkNum].nextItem)
|
|
|
|
{
|
|
|
|
ITEM_INFO* item = &g_Level.Items[linkNum];
|
|
|
|
|
2021-11-23 01:31:09 +03:00
|
|
|
if (Objects[item->objectNumber].floor != nullptr)
|
|
|
|
UpdateBridgeItem(linkNum);
|
2021-09-19 23:41:26 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RemoveRoomFlipItems(ROOM_INFO* r)
|
|
|
|
{
|
|
|
|
for (short linkNum = r->itemNumber; linkNum != NO_ITEM; linkNum = g_Level.Items[linkNum].nextItem)
|
|
|
|
{
|
|
|
|
ITEM_INFO* item = &g_Level.Items[linkNum];
|
|
|
|
|
2021-10-27 08:35:11 +02:00
|
|
|
if (item->flags & ONESHOT
|
|
|
|
&& Objects[item->objectNumber].intelligent
|
|
|
|
&& item->hitPoints <= 0
|
|
|
|
&& item->hitPoints != NOT_TARGETABLE)
|
2021-09-19 23:41:26 +03:00
|
|
|
{
|
|
|
|
KillItem(linkNum);
|
|
|
|
}
|
2021-11-23 01:31:09 +03:00
|
|
|
|
|
|
|
if (Objects[item->objectNumber].floor != nullptr)
|
|
|
|
UpdateBridgeItem(linkNum, true);
|
2021-09-19 23:41:26 +03:00
|
|
|
}
|
|
|
|
}
|
2021-10-27 08:35:11 +02:00
|
|
|
|
2021-09-19 23:41:26 +03:00
|
|
|
int IsObjectInRoom(short roomNumber, short objectNumber)
|
|
|
|
{
|
|
|
|
short itemNumber = g_Level.Rooms[roomNumber].itemNumber;
|
|
|
|
|
|
|
|
if (itemNumber == NO_ITEM)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
|
|
|
|
|
|
|
if (item->objectNumber == objectNumber)
|
|
|
|
break;
|
|
|
|
|
|
|
|
itemNumber = item->nextItem;
|
|
|
|
|
|
|
|
if (itemNumber == NO_ITEM)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int IsRoomOutside(int x, int y, int z)
|
|
|
|
{
|
|
|
|
if (x < 0 || z < 0)
|
2021-11-12 00:48:51 +03:00
|
|
|
return NO_ROOM;
|
2021-09-19 23:41:26 +03:00
|
|
|
|
|
|
|
int xTable = x / 1024;
|
|
|
|
int zTable = z / 1024;
|
|
|
|
|
|
|
|
if (OutsideRoomTable[xTable][zTable].size() == 0)
|
2021-11-12 00:48:51 +03:00
|
|
|
return NO_ROOM;
|
2021-09-19 23:41:26 +03:00
|
|
|
|
|
|
|
for (size_t i = 0; i < OutsideRoomTable[xTable][zTable].size(); i++)
|
|
|
|
{
|
|
|
|
short roomNumber = OutsideRoomTable[xTable][zTable][i];
|
2021-11-12 00:48:51 +03:00
|
|
|
auto r = &g_Level.Rooms[roomNumber];
|
2021-09-19 23:41:26 +03:00
|
|
|
|
|
|
|
if ((y > r->maxceiling) && (y < r->minfloor)
|
2021-11-08 17:28:04 +03:00
|
|
|
&& ((z > (r->z + 1024)) && (z < (r->z + ((r->zSize - 1) * 1024))))
|
|
|
|
&& ((x > (r->x + 1024)) && (x < (r->x + ((r->xSize - 1) * 1024)))))
|
2021-09-19 23:41:26 +03:00
|
|
|
{
|
2021-11-12 00:48:51 +03:00
|
|
|
auto floor = GetFloor(x, y, z, &roomNumber);
|
2021-09-19 23:41:26 +03:00
|
|
|
int height = GetFloorHeight(floor, x, y, z);
|
|
|
|
if (height == NO_HEIGHT || y > height)
|
2021-11-12 00:48:51 +03:00
|
|
|
return NO_ROOM;
|
2021-09-19 23:41:26 +03:00
|
|
|
height = GetCeiling(floor, x, y, z);
|
|
|
|
if (y < height)
|
2021-11-12 00:48:51 +03:00
|
|
|
return NO_ROOM;
|
2021-09-19 23:41:26 +03:00
|
|
|
|
2021-11-12 00:48:51 +03:00
|
|
|
return ((r->flags & (ENV_FLAG_WIND | ENV_FLAG_WATER)) != 0 ? roomNumber : NO_ROOM);
|
2021-09-19 23:41:26 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-12 00:48:51 +03:00
|
|
|
return NO_ROOM;
|
2021-09-19 23:41:26 +03:00
|
|
|
}
|
2021-09-17 16:07:53 +03:00
|
|
|
|
|
|
|
FLOOR_INFO* GetSector(ROOM_INFO* r, int x, int z)
|
|
|
|
{
|
2021-11-08 19:55:44 +03:00
|
|
|
int sectorX = std::clamp(x / SECTOR(1), 0, r->xSize - 1);
|
|
|
|
int sectorZ = std::clamp(z / SECTOR(1), 0, r->zSize - 1);
|
|
|
|
|
2021-11-08 17:28:04 +03:00
|
|
|
int index = sectorZ + sectorX * r->zSize;
|
2021-09-17 16:07:53 +03:00
|
|
|
if (index > r->floor.size())
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return &r->floor[index];
|
|
|
|
}
|
2021-11-08 21:43:57 +00:00
|
|
|
|
|
|
|
bool IsPointInRoom(PHD_3DPOS const & pos, int roomNumber)
|
|
|
|
{
|
|
|
|
int x = pos.xPos;
|
|
|
|
int y = pos.yPos;
|
|
|
|
int z = pos.zPos;
|
|
|
|
ROOM_INFO* r = &g_Level.Rooms[roomNumber];
|
|
|
|
int xSector = (x - r->x) / SECTOR(1);
|
|
|
|
int zSector = (z - r->z) / SECTOR(1);
|
|
|
|
|
|
|
|
return (xSector >= 0 && xSector <= r->xSize - 1) &&
|
|
|
|
(zSector >= 0 && zSector <= r->zSize - 1) &&
|
|
|
|
(y <= r->minfloor && y >= r->maxceiling); // up is negative y axis, hence y should be "less" than floor
|
|
|
|
}
|
|
|
|
|
|
|
|
PHD_3DPOS GetRoomCenter(int roomNumber)
|
|
|
|
{
|
|
|
|
ROOM_INFO* r = &g_Level.Rooms[roomNumber];
|
|
|
|
auto halfLength = SECTOR(r->xSize)/2;
|
|
|
|
auto halfDepth = SECTOR(r->zSize)/2;
|
|
|
|
auto halfHeight = (r->maxceiling - r->minfloor) / 2;
|
|
|
|
PHD_3DPOS center;
|
|
|
|
center.xPos = r->x + halfLength;
|
|
|
|
center.yPos = r->minfloor + halfHeight;
|
|
|
|
center.zPos = r->z + halfDepth;
|
|
|
|
return center;
|
|
|
|
}
|
|
|
|
|
2021-12-19 05:24:12 +03:00
|
|
|
std::set<int> GetRoomList(int roomNumber)
|
2021-12-14 17:54:54 +03:00
|
|
|
{
|
|
|
|
std::set<int> result;
|
|
|
|
|
|
|
|
if (g_Level.Rooms.size() <= roomNumber)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
result.insert(roomNumber);
|
|
|
|
|
|
|
|
auto room = &g_Level.Rooms[roomNumber];
|
|
|
|
for (int i = 0; i < room->doors.size(); i++)
|
|
|
|
result.insert(room->doors[i].room);
|
|
|
|
|
|
|
|
for (auto i : result)
|
|
|
|
{
|
|
|
|
room = &g_Level.Rooms[i];
|
|
|
|
for (int j = 0; j < room->doors.size(); j++)
|
|
|
|
result.insert(room->doors[j].room);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|