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

301 lines
8 KiB
C++
Raw Normal View History

#include "framework.h"
2021-09-25 16:00:30 +03:00
#include "tr5_expandingplatform.h"
#include "items.h"
#include "level.h"
2021-09-25 16:04:16 +03:00
#include "setup.h"
2021-09-19 23:41:26 +03:00
#include "control/control.h"
#include "control/box.h"
2021-09-19 18:29:25 +03:00
#include "animation.h"
#include "Sound/sound.h"
#include "camera.h"
2021-06-15 10:43:13 -04:00
#include "lara.h"
2021-08-28 13:27:58 +02:00
#include "collide.h"
2021-09-29 03:41:36 +03:00
#include "floordata.h"
using namespace TEN::Floordata;
2021-09-25 11:27:47 +02:00
void InitialiseExpandingPlatform(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
short roomNumber = item->roomNumber;
FLOOR_INFO* floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
2021-09-13 02:46:48 +03:00
g_Level.Boxes[floor->Box].flags &= ~BLOCKED;
// Set mutators to default
ExpandingPlatformUpdateMutators(itemNumber);
if (item->triggerFlags < 0)
{
item->aiBits |= ALL_AIOBJ;
AddActiveItem(itemNumber);
item->status = ITEM_ACTIVE;
}
2021-09-29 03:41:36 +03:00
TEN::Floordata::UpdateBridgeItem(itemNumber);
}
2021-09-29 03:41:36 +03:00
bool IsOnExpandingPlatform(int itemNumber, int x, int z)
2021-06-15 10:43:13 -04:00
{
2021-09-29 03:41:36 +03:00
auto item = &g_Level.Items[itemNumber];
if (item->itemFlags[1] <= 0)
2021-06-15 10:43:13 -04:00
return false;
2021-09-29 03:41:36 +03:00
2021-06-15 10:43:13 -04:00
int xb = x / SECTOR(1);
int zb = z / SECTOR(1);
2021-09-29 03:41:36 +03:00
int itemxb = item->pos.xPos / SECTOR(1);
int itemzb = item->pos.zPos / SECTOR(1);
auto bounds = GetBoundsAccurate(item);
auto halfWidth = abs(bounds->Z2 - bounds->Z1) / 2;
if (item->pos.yRot == ANGLE(90))
2021-06-15 10:43:13 -04:00
{
2021-09-29 03:41:36 +03:00
auto xBorder = item->pos.xPos + halfWidth - SECTOR(1) * item->itemFlags[1] / 4096;
2021-06-15 10:43:13 -04:00
if (x < xBorder || zb != itemzb || xb != itemxb)
return false;
}
2021-09-29 03:41:36 +03:00
else if (item->pos.yRot == ANGLE(270))
2021-06-15 10:43:13 -04:00
{
2021-09-29 03:41:36 +03:00
auto xBorder = item->pos.xPos - halfWidth + SECTOR(1) * item->itemFlags[1] / 4096;
2021-06-15 10:43:13 -04:00
if (x > xBorder || zb != itemzb || xb != itemxb)
return false;
}
2021-09-29 03:41:36 +03:00
else if (item->pos.yRot == 0)
2021-06-15 10:43:13 -04:00
{
2021-09-29 03:41:36 +03:00
auto zBorder = item->pos.zPos + halfWidth - SECTOR(1) * item->itemFlags[1] / 4096;
2021-06-15 10:43:13 -04:00
if (z < zBorder || zb != itemzb || xb != itemxb)
return false;
}
2021-09-29 03:41:36 +03:00
else if (item->pos.yRot == ANGLE(180))
2021-06-15 10:43:13 -04:00
{
2021-09-29 03:41:36 +03:00
auto zBorder = item->pos.zPos - halfWidth + SECTOR(1) * item->itemFlags[1] / 4096;
2021-06-15 10:43:13 -04:00
if (z > zBorder || zb != itemzb || xb != itemxb)
return false;
}
2021-09-29 03:41:36 +03:00
return GetBridgeItemIntersect(itemNumber, x, item->pos.yPos, z, false).has_value();
2021-06-15 10:43:13 -04:00
}
2021-09-29 03:41:36 +03:00
bool IsInFrontOfExpandingPlatform(int itemNumber, int x, int y, int z, int margin)
2021-06-15 10:43:13 -04:00
{
2021-09-29 03:41:36 +03:00
auto item = &g_Level.Items[itemNumber];
if (item->itemFlags[1] <= 0)
2021-06-15 10:43:13 -04:00
return false;
2021-09-29 03:41:36 +03:00
const auto topHeight = GetBridgeBorder(itemNumber, false);
const auto bottomHeight = GetBridgeBorder(itemNumber, true);
2021-06-15 10:43:13 -04:00
if (LaraItem->pos.yPos < topHeight - 32 || LaraItem->pos.yPos > bottomHeight + 32)
return false;
2021-09-29 03:41:36 +03:00
auto bounds = GetBoundsAccurate(item);
auto halfWidth = abs(bounds->Z2 - bounds->Z1) / 2;
2021-06-15 10:43:13 -04:00
int xb = x / SECTOR(1);
int zb = z / SECTOR(1);
2021-09-29 03:41:36 +03:00
int itemxb = item->pos.xPos / SECTOR(1);
int itemzb = item->pos.zPos / SECTOR(1);
if (item->pos.yRot == ANGLE(90))
2021-06-15 10:43:13 -04:00
{
2021-09-29 03:41:36 +03:00
auto xBorder = item->pos.xPos + halfWidth - margin - SECTOR(1) * item->itemFlags[1] / 4096;
auto xBorder2 = item->pos.xPos + halfWidth;
2021-06-15 10:43:13 -04:00
if (x < xBorder || zb != itemzb || x > xBorder2)
return false;
}
2021-09-29 03:41:36 +03:00
else if (item->pos.yRot == ANGLE(270))
2021-06-15 10:43:13 -04:00
{
2021-09-29 03:41:36 +03:00
auto xBorder = item->pos.xPos - halfWidth + margin + SECTOR(1) * item->itemFlags[1] / 4096;
auto xBorder2 = item->pos.xPos - halfWidth;
2021-06-15 10:43:13 -04:00
if (x > xBorder || zb != itemzb || x < xBorder2)
return false;
}
2021-09-29 03:41:36 +03:00
else if (item->pos.yRot == 0)
2021-06-15 10:43:13 -04:00
{
2021-09-29 03:41:36 +03:00
auto zBorder = item->pos.zPos + halfWidth - margin - SECTOR(1) * item->itemFlags[1] / 4096;
auto zBorder2 = item->pos.zPos + halfWidth;
2021-06-15 10:43:13 -04:00
if (z < zBorder || xb != itemxb || z > zBorder2)
return false;
}
2021-09-29 03:41:36 +03:00
else if (item->pos.yRot == ANGLE(180))
2021-06-15 10:43:13 -04:00
{
2021-09-29 03:41:36 +03:00
auto zBorder = item->pos.zPos - halfWidth + margin + SECTOR(1) * item->itemFlags[1] / 4096;
auto zBorder2 = item->pos.zPos - halfWidth;
2021-06-15 10:43:13 -04:00
if (z > zBorder || xb != itemxb || z < zBorder2)
return false;
}
2021-09-29 03:41:36 +03:00
return GetBridgeItemIntersect(itemNumber, x, item->pos.yPos, z, false).has_value();
2021-06-15 10:43:13 -04:00
}
void ShiftLaraOnPlatform(short itemNumber, bool isExpanding)
{
2021-09-29 03:41:36 +03:00
auto item = &g_Level.Items[itemNumber];
short angle = item->pos.yRot;
2021-06-15 10:43:13 -04:00
int xShift = 0;
int zShift = 0;
2021-09-29 03:41:36 +03:00
if (item->itemFlags[1] <= 0)
2021-06-15 10:43:13 -04:00
return;
2021-09-29 03:41:36 +03:00
const auto height = GetBridgeBorder(itemNumber, false);
if (IsOnExpandingPlatform(itemNumber, LaraItem->pos.xPos, LaraItem->pos.zPos))
2021-06-15 10:43:13 -04:00
{
//Slide Lara if on top of platform
if (LaraItem->pos.yPos < height - 32 || LaraItem->pos.yPos > height + 32)
return;
if (angle == ANGLE(0))
zShift = isExpanding ? -16 : 16;
else if (angle == ANGLE(180))
zShift = isExpanding ? 16 : -16;
else if (angle == ANGLE(90))
xShift = isExpanding ? -16 : 16;
else if (angle == -ANGLE(90))
xShift = isExpanding ? 16 : -16;
2021-09-29 03:41:36 +03:00
}
else if (isExpanding &&
IsInFrontOfExpandingPlatform(itemNumber, LaraItem->pos.xPos, LaraItem->pos.yPos, LaraItem->pos.zPos, LaraCollision.Setup.Radius))
2021-06-15 10:43:13 -04:00
{
//Push Lara if in front of expanding platform
if (angle == ANGLE(0))
2021-09-16 01:12:19 +03:00
zShift = -LaraCollision.Setup.Radius / 6;
2021-06-15 10:43:13 -04:00
else if (angle == ANGLE(180))
2021-09-16 01:12:19 +03:00
zShift = LaraCollision.Setup.Radius / 6;
2021-06-15 10:43:13 -04:00
else if (angle == ANGLE(90))
2021-09-16 01:12:19 +03:00
xShift = -LaraCollision.Setup.Radius / 6;
2021-06-15 10:43:13 -04:00
else if (angle == -ANGLE(90))
2021-09-16 01:12:19 +03:00
xShift = LaraCollision.Setup.Radius / 6;
2021-06-15 10:43:13 -04:00
}
2021-09-29 03:41:36 +03:00
auto coll = &LaraCollision;
GetCollisionInfo(coll, LaraItem, PHD_VECTOR(xShift, 0, zShift));
if (coll->Middle.Ceiling >= 0 || coll->HitStatic)
2021-06-15 10:43:13 -04:00
return;
if (zShift != 0)
LaraItem->pos.zPos += zShift;
if (xShift != 0)
LaraItem->pos.xPos += xShift;
}
void ControlExpandingPlatform(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
if (TriggerActive(item))
{
if (!item->itemFlags[2])
{
item->itemFlags[2] = 1;
}
if (item->triggerFlags < 0)
{
item->itemFlags[1] = 1;
}
else if (item->itemFlags[1] < 4096)
{
SoundEffect(SFX_TR4_BLK_PLAT_RAISE_AND_LOW, &item->pos, 0);
item->itemFlags[1] += 64;
2021-06-15 10:43:13 -04:00
ShiftLaraOnPlatform(itemNumber, true);
if (item->triggerFlags > 0)
{
if (abs(item->pos.xPos - Camera.pos.x) < 10240 &&
abs(item->pos.xPos - Camera.pos.x) < 10240 &&
abs(item->pos.xPos - Camera.pos.x) < 10240)
{
if (item->itemFlags[1] == 64 || item->itemFlags[1] == 4096)
Camera.bounce = -32;
else
Camera.bounce = -16;
}
}
}
}
else if (item->itemFlags[1] <= 0 || item->triggerFlags < 0)
{
if (item->itemFlags[2])
{
item->itemFlags[1] = 0;
item->itemFlags[2] = 0;
}
}
else
{
SoundEffect(SFX_TR4_BLK_PLAT_RAISE_AND_LOW, &item->pos, 0);
if (item->triggerFlags >= 0)
{
if (abs(item->pos.xPos - Camera.pos.x) < 10240 &&
abs(item->pos.xPos - Camera.pos.x) < 10240 &&
abs(item->pos.xPos - Camera.pos.x) < 10240)
{
if (item->itemFlags[1] == 64 || item->itemFlags[1] == 4096)
Camera.bounce = -32;
else
Camera.bounce = -16;
}
}
item->itemFlags[1] -= 64;
2021-06-15 10:43:13 -04:00
ShiftLaraOnPlatform(itemNumber, false);
}
ExpandingPlatformUpdateMutators(itemNumber);
}
std::optional<int> ExpandingPlatformFloor(short itemNumber, int x, int y, int z)
{
2021-09-29 03:41:36 +03:00
if (!IsOnExpandingPlatform(itemNumber, x, z))
return std::nullopt;
2021-09-29 03:41:36 +03:00
return GetBridgeItemIntersect(itemNumber, x, y, z, false);
}
std::optional<int> ExpandingPlatformCeiling(short itemNumber, int x, int y, int z)
{
2021-09-29 03:41:36 +03:00
if (!IsOnExpandingPlatform(itemNumber, x, z))
2021-06-15 10:43:13 -04:00
return std::nullopt;
2021-09-29 03:41:36 +03:00
return GetBridgeItemIntersect(itemNumber, x, y, z, true);
}
int ExpandingPlatformFloorBorder(short itemNumber)
{
2021-09-29 03:41:36 +03:00
return GetBridgeBorder(itemNumber, false);
}
int ExpandingPlatformCeilingBorder(short itemNumber)
{
2021-09-29 03:41:36 +03:00
return GetBridgeBorder(itemNumber, true);
}
void ExpandingPlatformUpdateMutators(short itemNumber)
{
auto item = &g_Level.Items[itemNumber];
2021-09-29 03:41:36 +03:00
auto bounds = GetBoundsAccurate(item);
auto normalizedThickness = item->itemFlags[1] / 4096.0f;
auto width = abs(bounds->Z2 - bounds->Z1) / 2;
auto offset = width * normalizedThickness;
// Update bone mutators
2021-09-29 03:41:36 +03:00
float zTranslate = 0.0f;
if (item->pos.yRot == ANGLE(0)) zTranslate = width - offset;
if (item->pos.yRot == ANGLE(90)) zTranslate = -offset + width;
if (item->pos.yRot == ANGLE(180)) zTranslate = -offset + width;
if (item->pos.yRot == ANGLE(270)) zTranslate = width - offset;
for (int i = 0; i < item->mutator.size(); i++)
{
2021-09-29 03:41:36 +03:00
item->mutator[i].Offset = Vector3(0, 0, zTranslate);
item->mutator[i].Scale = Vector3(1.0f, 1.0f, item->itemFlags[1] / 4096.0f);
}
}