TombEngine/TR5Main/Objects/TR5/Object/tr5_twoblockplatform.cpp

207 lines
5.4 KiB
C++
Raw Normal View History

#include "framework.h"
#include "tr5_twoblockplatform.h"
#include "level.h"
#include "control.h"
#include "items.h"
#include "lara.h"
#include "sound.h"
void InitialiseTwoBlocksPlatform(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
item->itemFlags[0] = item->pos.yPos;
item->itemFlags[1] = 1;
2021-06-02 16:59:30 -03:00
AddTwoBlocksPlatform(itemNumber);
}
void AddTwoBlocksPlatform(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
ten::Floordata::AddBridge(itemNumber);
2021-06-02 16:59:30 -03:00
switch (GetQuadrant(item->pos.yRot))
{
case NORTH:
ten::Floordata::AddBridge(itemNumber, -SECTOR(1), 0);
ten::Floordata::AddBridge(itemNumber, 0, SECTOR(1));
ten::Floordata::AddBridge(itemNumber, -SECTOR(1), SECTOR(1));
2021-06-02 16:59:30 -03:00
break;
case EAST:
ten::Floordata::AddBridge(itemNumber, SECTOR(1), 0);
ten::Floordata::AddBridge(itemNumber, 0, SECTOR(1));
ten::Floordata::AddBridge(itemNumber, SECTOR(1), SECTOR(1));
2021-06-02 16:59:30 -03:00
break;
case SOUTH:
ten::Floordata::AddBridge(itemNumber, SECTOR(1), 0);
ten::Floordata::AddBridge(itemNumber, 0, -SECTOR(1));
ten::Floordata::AddBridge(itemNumber, SECTOR(1), -SECTOR(1));
2021-06-02 16:59:30 -03:00
break;
case WEST:
ten::Floordata::AddBridge(itemNumber, -SECTOR(1), 0);
ten::Floordata::AddBridge(itemNumber, 0, -SECTOR(1));
ten::Floordata::AddBridge(itemNumber, -SECTOR(1), -SECTOR(1));
2021-06-02 16:59:30 -03:00
break;
}
}
void RemoveTwoBlocksPlatform(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
ten::Floordata::RemoveBridge(itemNumber);
2021-06-02 16:59:30 -03:00
switch (GetQuadrant(item->pos.yRot))
{
case NORTH:
ten::Floordata::RemoveBridge(itemNumber, -SECTOR(1), 0);
ten::Floordata::RemoveBridge(itemNumber, 0, SECTOR(1));
ten::Floordata::RemoveBridge(itemNumber, -SECTOR(1), SECTOR(1));
2021-06-02 16:59:30 -03:00
break;
case EAST:
ten::Floordata::RemoveBridge(itemNumber, SECTOR(1), 0);
ten::Floordata::RemoveBridge(itemNumber, 0, SECTOR(1));
ten::Floordata::RemoveBridge(itemNumber, SECTOR(1), SECTOR(1));
2021-06-02 16:59:30 -03:00
break;
case SOUTH:
ten::Floordata::RemoveBridge(itemNumber, SECTOR(1), 0);
ten::Floordata::RemoveBridge(itemNumber, 0, -SECTOR(1));
ten::Floordata::RemoveBridge(itemNumber, SECTOR(1), -SECTOR(1));
2021-06-02 16:59:30 -03:00
break;
case WEST:
ten::Floordata::RemoveBridge(itemNumber, -SECTOR(1), 0);
ten::Floordata::RemoveBridge(itemNumber, 0, -SECTOR(1));
ten::Floordata::RemoveBridge(itemNumber, -SECTOR(1), -SECTOR(1));
2021-06-02 16:59:30 -03:00
break;
}
}
BOOL IsOnTwoBlocksPlatform(ITEM_INFO* item, int x, int z)
{
if (!item->meshBits)
2020-07-07 07:32:33 +02:00
return false;
short angle = item->pos.yRot;
int xb = x / SECTOR(1);
int zb = z / SECTOR(1);
int itemxb = item->pos.xPos / SECTOR(1);
int itemzb = item->pos.zPos / SECTOR(1);
if (!angle && (xb == itemxb || xb == itemxb - 1) && (zb == itemzb || zb == itemzb + 1))
2020-07-07 07:32:33 +02:00
return true;
if (angle == -ANGLE(180) && (xb == itemxb || xb == itemxb + 1) && (zb == itemzb || zb == itemzb - 1))
2020-07-07 07:32:33 +02:00
return true;
2021-06-02 16:59:30 -03:00
if (angle == ANGLE(90) && (zb == itemzb || zb == itemzb + 1) && (xb == itemxb || xb == itemxb + 1))
2020-07-07 07:32:33 +02:00
return true;
if (angle == -ANGLE(90) && (zb == itemzb || zb == itemzb - 1) && (xb == itemxb || xb == itemxb - 1))
2020-07-07 07:32:33 +02:00
return true;
2020-07-07 07:32:33 +02:00
return false;
}
std::optional<int> TwoBlocksPlatformFloor(short itemNumber, int x, int y, int z)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
2021-06-02 16:59:30 -03:00
if (!item->meshBits)
return std::nullopt;
2021-06-02 16:59:30 -03:00
int height = item->pos.yPos;
return std::optional{ height };
}
void TwoBlocksPlatformControl(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
if (TriggerActive(item))
{
if (item->triggerFlags)
{
2021-06-02 16:59:30 -03:00
if (item->pos.yPos > (item->itemFlags[0] - 16 * (int) (item->triggerFlags & 0xFFFFFFF0)))
{
item->pos.yPos -= item->triggerFlags & 0xF;
}
short roomNumber = item->roomNumber;
FLOOR_INFO* floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
item->floor = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
if (roomNumber != item->roomNumber)
2021-06-02 16:59:30 -03:00
{
RemoveTwoBlocksPlatform(itemNumber);
ItemNewRoom(itemNumber, roomNumber);
2021-06-02 16:59:30 -03:00
AddTwoBlocksPlatform(itemNumber);
}
}
else
{
2021-08-27 19:29:18 +03:00
bool onObject = false;
int height = LaraItem->pos.yPos + 1;
if (IsOnTwoBlocksPlatform(item, LaraItem->pos.xPos, LaraItem->pos.zPos))
{
if (LaraItem->pos.yPos <= item->pos.yPos + 32)
{
if (item->pos.yPos < height)
{
2021-08-27 19:29:18 +03:00
onObject = true;
}
}
}
2021-08-27 19:29:18 +03:00
if (onObject && LaraItem->animNumber != LA_HOP_BACK_CONTINUE)
item->itemFlags[1] = 1;
else
item->itemFlags[1] = -1;
if (item->itemFlags[1] < 0)
{
if (item->pos.yPos <= item->itemFlags[0])
{
item->itemFlags[1] = 1;
}
else
{
SoundEffect(SFX_TR4_RUMBLE_NEXTDOOR, &item->pos, 0);
item->pos.yPos -= 4;
}
}
else if (item->itemFlags[1] > 0)
{
if (item->pos.yPos >= item->itemFlags[0] + 128)
{
item->itemFlags[1] = -1;
}
else
{
SoundEffect(SFX_TR4_RUMBLE_NEXTDOOR, &item->pos, 0);
item->pos.yPos += 4;
}
}
}
}
}
std::optional<int> TwoBlocksPlatformCeiling(short itemNumber, int x, int y, int z)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
2021-06-02 16:59:30 -03:00
if (!item->meshBits)
return std::nullopt;
//+ 256 is more accurate, but prevents a tall block from entering underneath
int height = item->pos.yPos + 20;
return std::optional{ height };
}
int TwoBlocksPlatformFloorBorder(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
return item->pos.yPos;
}
int TwoBlocksPlatformCeilingBorder(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
return (item->pos.yPos + 256);
}