2020-09-20 10:11:10 -05:00
|
|
|
#include "framework.h"
|
2021-12-24 11:08:16 +03:00
|
|
|
#include "Objects/TR3/Trap/train.h"
|
|
|
|
|
|
|
|
#include "Game/animation.h"
|
2021-12-22 16:23:57 +03:00
|
|
|
#include "Game/camera.h"
|
2021-12-24 11:08:16 +03:00
|
|
|
#include "Game/control/control.h"
|
2021-12-22 16:23:57 +03:00
|
|
|
#include "Game/collision/collide_room.h"
|
|
|
|
#include "Game/collision/collide_item.h"
|
2021-12-24 11:08:16 +03:00
|
|
|
#include "Game/collision/floordata.h"
|
|
|
|
#include "Game/collision/sphere.h"
|
|
|
|
#include "Game/effects/effects.h"
|
|
|
|
#include "Game/items.h"
|
|
|
|
#include "Game/Lara/lara.h"
|
2022-02-24 21:55:14 +11:00
|
|
|
#include "Game/Lara/lara_helpers.h"
|
2021-12-24 11:08:16 +03:00
|
|
|
#include "Sound/sound.h"
|
|
|
|
#include "Specific/level.h"
|
|
|
|
#include "Specific/setup.h"
|
2021-09-25 11:27:47 +02:00
|
|
|
|
2020-09-20 10:07:15 -05:00
|
|
|
#define TRAIN_VEL 260
|
|
|
|
#define LARA_TRAIN_DEATH_ANIM 3;
|
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
long TrainTestHeight(ITEM_INFO* item, long x, long z, short* roomNumber)
|
2020-09-20 10:07:15 -05:00
|
|
|
{
|
2020-10-05 22:24:57 -03:00
|
|
|
float s, c;
|
2020-09-20 10:07:15 -05:00
|
|
|
PHD_VECTOR pos;
|
|
|
|
FLOOR_INFO *floor;
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
s = phd_sin(item->Position.yRot);
|
2022-02-24 21:55:14 +11:00
|
|
|
c = phd_cos(item->Position.yRot);
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
pos.x = item->Position.xPos + z * s + x * c;
|
|
|
|
pos.y = item->Position.yPos - z * phd_sin(item->Position.xRot) + x * phd_sin(item->Position.zRot);
|
|
|
|
pos.z = item->Position.zPos + z * c - x * s;
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
auto probe = GetCollisionResult(pos.x, pos.y, pos.z, item->RoomNumber);
|
|
|
|
|
|
|
|
*roomNumber = probe.RoomNumber;
|
|
|
|
return probe.Position.Floor;
|
2020-09-20 10:07:15 -05:00
|
|
|
}
|
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
void TrainControl(short itemNumber)
|
2020-09-20 10:07:15 -05:00
|
|
|
{
|
2022-02-24 21:55:14 +11:00
|
|
|
auto* item = &g_Level.Items[itemNumber];
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
long fh;
|
|
|
|
FLOOR_INFO *floor;
|
|
|
|
short roomNumber;
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
if (!TriggerActive(item))
|
2020-09-20 10:07:15 -05:00
|
|
|
return;
|
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
if (item->ItemFlags[0] == 0)
|
|
|
|
item->ItemFlags[0] = item->ItemFlags[1] = TRAIN_VEL;
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
float s = phd_sin(item->Position.yRot);
|
|
|
|
float c = phd_cos(item->Position.yRot);
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
item->Position.xPos += item->ItemFlags[1] * s;
|
|
|
|
item->Position.zPos += item->ItemFlags[1] * c;
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
long rh = TrainTestHeight(item, 0, SECTOR(5), &roomNumber);
|
|
|
|
item->Position.yPos = fh = TrainTestHeight(item, 0, 0, &roomNumber);
|
2020-09-20 10:07:15 -05:00
|
|
|
|
|
|
|
if (fh == NO_HEIGHT)
|
|
|
|
{
|
2022-02-24 21:55:14 +11:00
|
|
|
KillItem(itemNumber);
|
2020-09-20 10:07:15 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
item->Position.yPos -= 32;// ?
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
roomNumber = item->RoomNumber;
|
|
|
|
GetFloor(item->Position.xPos, item->Position.yPos, item->Position.zPos, &roomNumber);
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
if (roomNumber != item->RoomNumber)
|
|
|
|
ItemNewRoom(itemNumber, roomNumber);
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
item->Position.xRot = -(rh - fh) * 2;
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
TriggerDynamicLight(item->Position.xPos + SECTOR(3) * s, item->Position.yPos, item->Position.zPos + SECTOR(3) * c, 16, 31, 31, 31);
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
if (item->ItemFlags[1] != TRAIN_VEL)
|
2020-09-20 10:07:15 -05:00
|
|
|
{
|
2022-02-24 21:55:14 +11:00
|
|
|
item->ItemFlags[1] -= 48;
|
|
|
|
if (item->ItemFlags[1] < 0)
|
|
|
|
item->ItemFlags[1] = 0;
|
2020-09-20 10:07:15 -05:00
|
|
|
|
|
|
|
if (!UseForcedFixedCamera)
|
|
|
|
{
|
2022-02-24 21:55:14 +11:00
|
|
|
ForcedFixedCamera.x = item->Position.xPos + SECTOR(8) * s;
|
|
|
|
ForcedFixedCamera.z = item->Position.zPos + SECTOR(8) * c;
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
roomNumber = item->RoomNumber;
|
|
|
|
floor = GetFloor(ForcedFixedCamera.x, item->Position.yPos - CLICK(2), ForcedFixedCamera.z, &roomNumber);
|
|
|
|
ForcedFixedCamera.y = GetFloorHeight(floor, ForcedFixedCamera.x, item->Position.yPos - CLICK(2), ForcedFixedCamera.z);
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
ForcedFixedCamera.roomNumber = roomNumber;
|
2020-09-20 10:07:15 -05:00
|
|
|
UseForcedFixedCamera = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2022-02-24 21:55:14 +11:00
|
|
|
SoundEffect(SFX_TR3_TUBE_LOOP, &item->Position, SFX_ALWAYS);
|
2020-09-20 10:07:15 -05:00
|
|
|
}
|
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
void TrainCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
|
2020-09-20 10:07:15 -05:00
|
|
|
{
|
2022-02-24 21:55:14 +11:00
|
|
|
auto* laraInfo = GetLaraInfo(laraItem);
|
|
|
|
auto* trainItem = &g_Level.Items[itemNumber];
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
if (!TestBoundsCollide(trainItem, laraItem, coll->Setup.Radius))
|
2020-09-20 10:07:15 -05:00
|
|
|
return;
|
2022-02-24 21:55:14 +11:00
|
|
|
if (!TestCollision(trainItem, laraItem))
|
2020-09-20 10:07:15 -05:00
|
|
|
return;
|
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
SoundEffect(SFX_TR3_LARA_GENERAL_DEATH, &laraItem->Position, SFX_ALWAYS);
|
|
|
|
SoundEffect(SFX_TR3_LARA_FALLDETH, &laraItem->Position, SFX_ALWAYS);
|
2020-09-20 10:07:15 -05:00
|
|
|
StopSoundEffect(SFX_TR3_TUBE_LOOP);
|
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
laraItem->AnimNumber = Objects[ID_LARA_EXTRA_ANIMS].animIndex + LARA_TRAIN_DEATH_ANIM;
|
|
|
|
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
|
2022-02-09 16:55:46 +11:00
|
|
|
// larA->ActiveState = EXTRA_TRAINKILL;
|
|
|
|
// larA->TargetState = EXTRA_TRAINKILL;
|
2022-02-24 21:55:14 +11:00
|
|
|
laraItem->HitPoints = 0;
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
laraItem->Position.yRot = trainItem->Position.yRot;
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
laraItem->Velocity = 0;
|
|
|
|
laraItem->VerticalVelocity = 0;
|
|
|
|
laraItem->Airborne = false;
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
AnimateItem(laraItem);
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
laraInfo->ExtraAnim = 1;
|
|
|
|
laraInfo->Control.HandStatus = HandStatus::Busy;
|
|
|
|
laraInfo->Control.WeaponControl.GunType = WEAPON_NONE;
|
|
|
|
laraInfo->hitDirection = -1;
|
|
|
|
laraInfo->Air = -1;
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
trainItem->ItemFlags[1] = 160;
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
float s = phd_sin(trainItem->Position.yRot);
|
|
|
|
float c = phd_cos(trainItem->Position.yRot);
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
long x = laraItem->Position.xPos + CLICK(1) * s;
|
|
|
|
long z = laraItem->Position.zPos + CLICK(1) * c;
|
2020-09-20 10:07:15 -05:00
|
|
|
|
2022-02-24 21:55:14 +11:00
|
|
|
DoLotsOfBlood(x, laraItem->Position.yPos - CLICK(2), z, SECTOR(1), trainItem->Position.yRot, laraItem->RoomNumber, 15);
|
2020-09-20 10:07:15 -05:00
|
|
|
}
|