TombEngine/TR5Main/Objects/TR3/Vehicles/upv.cpp

1081 lines
26 KiB
C++
Raw Normal View History

#include "framework.h"
2021-12-24 03:32:19 +03:00
#include "Objects/TR3/Vehicles/upv.h"
2021-12-24 11:08:16 +03:00
#include "Game/animation.h"
#include "Game/camera.h"
2021-12-22 16:23:57 +03:00
#include "Game/collision/sphere.h"
#include "Game/collision/collide_item.h"
#include "Game/control/box.h"
2021-12-24 11:08:16 +03:00
#include "Game/control/los.h"
#include "Game/effects/bubble.h"
#include "Game/effects/effects.h"
#include "Game/items.h"
#include "Game/Lara/lara.h"
2021-12-22 16:23:57 +03:00
#include "Game/Lara/lara_flare.h"
#include "Game/Lara/lara_one_gun.h"
#include "Game/savegame.h"
2021-12-24 03:32:19 +03:00
#include "Objects/TR3/Vehicles/upv_info.h"
2021-12-24 11:08:16 +03:00
#include "Sound/sound.h"
#include "Specific/level.h"
#include "Specific/input.h"
#include "Specific/setup.h"
2021-09-25 11:27:47 +02:00
2020-09-28 15:21:19 -05:00
#define UPV_CONTROL 1
#define UPV_SURFACE 2
#define UPV_DIVE 4
#define UPV_DEAD 8
#define ACCELERATION 0x40000
#define FRICTION 0x18000
#define MAX_SPEED 0x400000
#define ROT_ACCELERATION 0x400000
#define ROT_SLOWACCEL 0x200000
#define ROT_FRICTION 0x100000
#define MAX_ROTATION 0x1c00000
2021-12-08 15:27:46 +11:00
#define UPDOWN_ACCEL (ANGLE(2.0f) * 65536)
#define UPDOWN_SLOWACCEL (ANGLE(1.0f) * 65536)
#define UPDOWN_FRICTION (ANGLE(1.0f) * 65536)
#define MAX_UPDOWN (ANGLE(2.0f) * 65536)
#define UPDOWN_LIMIT ANGLE(80.0f)
#define UPDOWN_SPEED 10
#define SURFACE_DIST 210
2021-12-08 22:02:02 +11:00
#define SURFACE_ANGLE ANGLE(30.0f)
2021-12-08 15:27:46 +11:00
#define DIVE_ANGLE ANGLE(15.0f)
#define DIVE_SPEED ANGLE(5.0f)
#define SUB_DRAW_SHIFT 128
#define SUB_RADIUS 300
#define SUB_HEIGHT 400
#define SUB_LENGTH WALL_SIZE
2021-12-08 15:27:46 +11:00
#define FRONT_TOLERANCE (ANGLE(45.0f) * 65536)
#define TOP_TOLERANCE (ANGLE(45.0f) * 65536)
#define WALLDEFLECT (ANGLE(2.0f) * 65536)
#define GETOFF_DIST WALL_SIZE
#define HARPOON_SPEED 256
#define HARPOON_RELOAD 15
2021-12-08 15:27:46 +11:00
#define UPV_TURBINE_BONE 3
#define DEATH_FRAME_1 16
#define DEATH_FRAME_2 17
#define DISMOUNT_SURFACE_FRAME 51
#define MOUNT_SURFACE_SOUND_FRAME 30
#define MOUNT_SURFACE_CONTROL_FRAME 50
#define DISMOUNT_UNDERWATER_FRAME 42
#define MOUNT_UNDERWATER_SOUND_FRAME 30
#define MOUNT_UNDERWATER_CONTROL_FRAME 42
#define UPV_IN_PROPEL IN_JUMP
#define UPV_IN_UP IN_FORWARD
#define UPV_IN_DOWN IN_BACK
#define UPV_IN_LEFT IN_LEFT
#define UPV_IN_RIGHT IN_RIGHT
#define UPV_IN_FIRE IN_ACTION
#define UPV_IN_DISMOUNT IN_ROLL
BITE_INFO sub_bites[6] =
{
2021-03-24 12:49:36 -05:00
{ 0, 0, 0, 3 },
{ 0, 96, 256, 0 },
{ -128, 0, -64, 1 },
{ 0, 0, -64, 1 },
{ 128, 0, -64, 2 },
{ 0, 0, -64, 2 }
};
2021-12-08 15:27:46 +11:00
enum SUB_BITE_FLAG
{
SUB_FAN = 0,
SUB_FRONT_LIGHT,
SUB_LEFT_FIN_LEFT,
SUB_LEFT_FIN_RIGHT,
SUB_RIGHT_FIN_RIGHT,
SUB_RIGHT_FIN_LEFT
};
2021-12-08 15:27:46 +11:00
enum UPVState
{
UPV_STATE_DEATH,
UPV_STATE_HIT,
UPV_STATE_DISMOUNT_SURFACE,
UPV_STATE_UNK1,
UPV_STATE_MOVE,
UPV_STATE_IDLE,
UPV_STATE_UNK2,
UPV_STATE_UNK3,
UPV_STATE_MOUNT,
UPV_STATE_DISMOUNT_UNDERWATER
};
2021-12-08 15:27:46 +11:00
// TODO
enum UPVAnim
{
2021-12-08 15:27:46 +11:00
UPV_ANIM_DEATH = 0,
UPV_ANIM_IDLE = 5,
UPV_ANIM_DISMOUNT_SURFACE = 9,
UPV_ANIM_MOUNT_SURFACE_START = 10,
UPV_ANIM_MOUNT_SURFACE_END = 11,
UPV_ANIM_DISMOUNT_UNDERWATER = 12,
UPV_ANIM_MOUNT_UNDERWATER = 13,
};
void SubInitialise(short itemNum)
{
ITEM_INFO* UPVItem = &g_Level.Items[itemNum];
UPVItem->data = SUB_INFO();
SUB_INFO* UPVInfo = UPVItem->data;
UPVInfo->Vel = UPVInfo->Rot = 0;
UPVInfo->Flags = UPV_SURFACE;
UPVInfo->WeaponTimer = 0;
}
static void FireSubHarpoon(ITEM_INFO* laraItem, ITEM_INFO* UPVItem)
{
short itemNum = CreateItem();
if (itemNum != NO_ITEM)
{
static char lr = 0;
2021-12-08 15:27:46 +11:00
PHD_VECTOR pos { (lr ? 22 : -22), 24, 230 };
ITEM_INFO* harpoonItem = &g_Level.Items[itemNum];
2021-12-08 15:27:46 +11:00
harpoonItem->objectNumber = ID_HARPOON;
harpoonItem->shade = 0xC210;
harpoonItem->roomNumber = UPVItem->roomNumber;
2021-12-08 15:27:46 +11:00
GetJointAbsPosition(UPVItem, &pos, UPV_TURBINE_BONE);
2021-12-08 15:27:46 +11:00
harpoonItem->pos.xPos = pos.x;
harpoonItem->pos.yPos = pos.y;
harpoonItem->pos.zPos = pos.z;
InitialiseItem(itemNum);
2021-12-08 15:27:46 +11:00
harpoonItem->pos.xRot = UPVItem->pos.xRot;
harpoonItem->pos.yRot = UPVItem->pos.yRot;
harpoonItem->pos.zRot = 0;
2021-12-08 15:27:46 +11:00
harpoonItem->fallspeed = -HARPOON_SPEED * phd_sin(harpoonItem->pos.xRot);
harpoonItem->speed = HARPOON_SPEED * phd_cos(harpoonItem->pos.xRot);
harpoonItem->hitPoints = HARPOON_TIME;
harpoonItem->itemFlags[0] = 1;
AddActiveItem(itemNum);
SoundEffect(SFX_TR3_LARA_HARPOON_FIRE_WATER, &LaraItem->pos, 2);
2020-10-30 00:00:41 -05:00
if (Lara.Weapons[WEAPON_HARPOON_GUN].Ammo[WEAPON_AMMO1])
Lara.Weapons[WEAPON_HARPOON_GUN].Ammo[WEAPON_AMMO1]--;
Statistics.Game.AmmoUsed++;
lr ^= 1;
}
}
static void TriggerSubMist(long x, long y, long z, long speed, short angle)
{
long size, xv, zv;
SPARKS* sptr;
sptr = &Sparks[GetFreeSpark()];
sptr->on = 1;
sptr->sR = 0;
sptr->sG = 0;
sptr->sB = 0;
sptr->dR = 64;
sptr->dG = 64;
sptr->dB = 64;
sptr->colFadeSpeed = 4 + (GetRandomControl() & 3);
sptr->fadeToBlack = 12;
sptr->sLife = sptr->life = (GetRandomControl() & 3) + 20;
2021-09-25 16:03:28 -05:00
sptr->transType = TransTypeEnum::COLADD;
sptr->extras = 0;
sptr->dynamic = -1;
sptr->x = x + ((GetRandomControl() & 15) - 8);
sptr->y = y + ((GetRandomControl() & 15) - 8);
sptr->z = z + ((GetRandomControl() & 15) - 8);
2020-10-05 22:24:57 -03:00
zv = speed * phd_cos(angle) / 4;
xv = speed * phd_sin(angle) / 4;
sptr->xVel = xv + ((GetRandomControl() & 127) - 64);
sptr->yVel = 0;
sptr->zVel = zv + ((GetRandomControl() & 127) - 64);
sptr->friction = 3;
if (GetRandomControl() & 1)
{
sptr->flags = SP_SCALE | SP_DEF | SP_ROTATE | SP_EXPDEF;
sptr->rotAng = GetRandomControl() & 4095;
2021-12-08 15:27:46 +11:00
if (GetRandomControl() & 1)
sptr->rotAdd = -(GetRandomControl() & 15) - 16;
else
sptr->rotAdd = (GetRandomControl() & 15) + 16;
}
else
sptr->flags = SP_SCALE | SP_DEF | SP_EXPDEF;
sptr->scalar = 3;
sptr->gravity = sptr->maxYvel = 0;
2020-10-06 10:36:30 -05:00
size = (GetRandomControl() & 7) + (speed / 2) + 16;
sptr->size = sptr->sSize = size / 4;
sptr->dSize = size;
}
2021-12-08 15:27:46 +11:00
void SubEffects(short itemNum)
{
2021-12-08 15:27:46 +11:00
if (itemNum == NO_ITEM)
2020-09-30 14:45:46 -05:00
return;
2021-12-08 15:27:46 +11:00
ITEM_INFO* laraItem = LaraItem;
LaraInfo*& laraInfo = laraItem->data;
ITEM_INFO* UPVItem = &g_Level.Items[itemNum];
SUB_INFO* UPVInfo = UPVItem->data;
PHD_VECTOR pos;
long lp;
2021-12-08 15:27:46 +11:00
if (laraInfo->Vehicle == itemNum)
{
2021-12-08 15:27:46 +11:00
if (!UPVInfo->Vel)
UPVInfo->FanRot += ANGLE(2.0f);
else
2021-12-08 15:27:46 +11:00
UPVInfo->FanRot += (UPVInfo->Vel / 4069);
2021-12-08 15:27:46 +11:00
if (UPVInfo->Vel)
{
2021-12-08 15:27:46 +11:00
pos = { sub_bites[SUB_FAN].x, sub_bites[SUB_FAN].y, sub_bites[SUB_FAN].z };
GetJointAbsPosition(UPVItem, &pos, sub_bites[SUB_FAN].meshNum);
TriggerSubMist(pos.x, pos.y + SUB_DRAW_SHIFT, pos.z, abs(UPVInfo->Vel) / 65536, UPVItem->pos.yRot + ANGLE(180.0f));
if ((GetRandomControl() & 1) == 0)
{
PHD_3DPOS pos3d;
2021-12-08 15:27:46 +11:00
short roomNum;
pos3d.xPos = pos.x + (GetRandomControl() & 63) - 32;
pos3d.yPos = pos.y + SUB_DRAW_SHIFT;
pos3d.zPos = pos.z + (GetRandomControl() & 63) - 32;
2021-12-08 15:27:46 +11:00
roomNum = UPVItem->roomNumber;
GetFloor(pos3d.xPos, pos3d.yPos, pos3d.zPos, &roomNum);
CreateBubble((PHD_VECTOR*)&pos3d, roomNum, 4, 8, BUBBLE_FLAG_CLUMP, 0, 0, 0);
}
}
}
2020-09-30 14:45:46 -05:00
for (lp = 0; lp < 2; lp++)
{
GAME_VECTOR source, target;
2021-12-08 15:27:46 +11:00
long r;
r = 31 - (GetRandomControl() & 3);
2021-12-08 15:27:46 +11:00
pos = { sub_bites[SUB_FRONT_LIGHT].x, sub_bites[SUB_FRONT_LIGHT].y, sub_bites[SUB_FRONT_LIGHT].z << (lp * 6) };
GetJointAbsPosition(UPVItem, &pos, sub_bites[SUB_FRONT_LIGHT].meshNum);
2021-03-24 12:49:36 -05:00
if (lp == 1)
{
target.x = pos.x;
target.y = pos.y;
target.z = pos.z;
2021-12-08 15:27:46 +11:00
target.roomNumber = UPVItem->roomNumber;
LOS(&source, &target);
2021-12-08 15:27:46 +11:00
pos = { target.x, target.y, target.z };
}
else
{
source.x = pos.x;
source.y = pos.y;
source.z = pos.z;
2021-12-08 15:27:46 +11:00
source.roomNumber = UPVItem->roomNumber;
}
2021-12-08 15:27:46 +11:00
2020-09-30 14:45:46 -05:00
TriggerDynamicLight(pos.x, pos.y, pos.z, 16 + (lp << 3), r, r, r);
}
2021-03-24 12:49:36 -05:00
2021-12-08 15:27:46 +11:00
if (UPVInfo->WeaponTimer)
UPVInfo->WeaponTimer--;
}
2021-12-08 15:27:46 +11:00
static bool TestUPVDismount(ITEM_INFO* laraItem, ITEM_INFO* UPVItem)
{
2021-12-08 15:27:46 +11:00
LaraInfo*& laraInfo = laraItem->data;
if (laraInfo->currentXvel || laraInfo->currentZvel)
return false;
short moveAngle = UPVItem->pos.yRot + ANGLE(180.0f);
int speed = GETOFF_DIST * phd_cos(UPVItem->pos.xRot);
int x = UPVItem->pos.xPos + speed * phd_sin(moveAngle);
int z = UPVItem->pos.zPos + speed * phd_cos(moveAngle);
int y = UPVItem->pos.yPos - GETOFF_DIST * phd_sin(-UPVItem->pos.xRot);
auto probe = GetCollisionResult(x, y, z, UPVItem->roomNumber);
if (probe.Position.Floor < y ||
(probe.Position.Floor - probe.Position.Ceiling) < STEP_SIZE ||
probe.Position.Ceiling > y ||
probe.Position.Floor == NO_HEIGHT ||
probe.Position.Ceiling == NO_HEIGHT)
{
return false;
}
2021-12-08 15:27:46 +11:00
return true;
}
2021-12-08 15:27:46 +11:00
static bool TestUPVMount(ITEM_INFO* laraItem, ITEM_INFO* UPVItem)
{
2021-12-08 15:27:46 +11:00
LaraInfo*& laraInfo = laraItem->data;
2021-12-08 15:27:46 +11:00
if (!(TrInput & IN_ACTION) ||
laraInfo->gunStatus != LG_HANDS_FREE ||
2022-01-21 23:23:10 +11:00
laraItem->airborne)
2021-12-08 15:27:46 +11:00
{
return false;
}
2020-10-30 00:00:41 -05:00
2021-12-08 15:27:46 +11:00
int y = abs(laraItem->pos.yPos - (UPVItem->pos.yPos - STEP_SIZE / 2));
int dist = pow(laraItem->pos.xPos - UPVItem->pos.xPos, 2) + pow(laraItem->pos.zPos - UPVItem->pos.zPos, 2);
short rotDelta = abs(laraItem->pos.yRot - UPVItem->pos.yRot);
2021-12-08 15:27:46 +11:00
if (y > STEP_SIZE ||
dist > pow(STEP_SIZE * 2, 2) ||
rotDelta > ANGLE(35.0f) || rotDelta < -ANGLE(35.0f) ||
GetCollisionResult(UPVItem).Position.Floor < -32000)
{
return false;
}
2021-12-08 15:27:46 +11:00
return true;
}
static void DoCurrent(ITEM_INFO* item)
{
PHD_VECTOR target;
if (!Lara.currentActive)
{
long shifter, absvel;
absvel = abs(Lara.currentXvel);
if (absvel > 16)
shifter = 4;
else if (absvel > 8)
shifter = 3;
else
shifter = 2;
Lara.currentXvel -= Lara.currentXvel >> shifter;
if (abs(Lara.currentXvel) < 4)
Lara.currentXvel = 0;
absvel = abs(Lara.currentZvel);
if (absvel > 16)
shifter = 4;
else if (absvel > 8)
shifter = 3;
else
shifter = 2;
Lara.currentZvel -= Lara.currentZvel >> shifter;
if (abs(Lara.currentZvel) < 4)
Lara.currentZvel = 0;
if (Lara.currentXvel == 0 && Lara.currentZvel == 0)
return;
}
else
{
long angle, dx, dz, speed, sinkval;
sinkval = Lara.currentActive - 1;
target.x = g_Level.Sinks[sinkval].x;
target.y = g_Level.Sinks[sinkval].y;
target.z = g_Level.Sinks[sinkval].z;
2020-10-06 10:36:30 -05:00
angle = ((mGetAngle(target.x, target.z, LaraItem->pos.xPos, LaraItem->pos.zPos) - ANGLE(90)) / 16) & 4095;
dx = target.x - LaraItem->pos.xPos;
dz = target.z - LaraItem->pos.zPos;
speed = g_Level.Sinks[sinkval].strength;
2020-10-06 10:36:30 -05:00
dx = phd_sin(angle * 16) * speed * 1024;
dz = phd_cos(angle * 16) * speed * 1024;
2020-10-06 10:36:30 -05:00
Lara.currentXvel += ((dx - Lara.currentXvel) / 16);
Lara.currentZvel += ((dz - Lara.currentZvel) / 16);
}
2020-10-06 10:36:30 -05:00
item->pos.xPos += (Lara.currentXvel / 256);
item->pos.zPos += (Lara.currentZvel / 256);
Lara.currentActive = 0;
}
2021-12-08 15:27:46 +11:00
static void BackgroundCollision(ITEM_INFO* laraItem, ITEM_INFO* UPVItem)
{
2021-12-08 15:27:46 +11:00
LaraInfo*& laraInfo = laraItem->data;
SUB_INFO* UPVInfo = UPVItem->data;
COLL_INFO cinfo, * coll = &cinfo; // ??
coll->Setup.LowerFloorBound = NO_LOWER_BOUND;
coll->Setup.UpperFloorBound = -SUB_HEIGHT;
coll->Setup.LowerCeilingBound = SUB_HEIGHT;
2021-12-08 15:27:46 +11:00
coll->Setup.OldPosition.x = UPVItem->pos.xPos;
coll->Setup.OldPosition.y = UPVItem->pos.yPos;
coll->Setup.OldPosition.z = UPVItem->pos.zPos;
2021-09-10 00:20:59 +03:00
coll->Setup.Radius = SUB_RADIUS;
coll->Setup.FloorSlopeIsWall = false;
coll->Setup.FloorSlopeIsPit = false;
coll->Setup.DeathFlagIsPit = false;
coll->Setup.EnableSpasm = false;
2021-09-10 00:20:59 +03:00
coll->Setup.EnableObjectPush = true;
2021-10-27 09:48:31 +03:00
coll->Setup.Mode = COLL_PROBE_MODE::QUADRANTS;
2021-12-08 15:27:46 +11:00
if ((UPVItem->pos.xRot >= -16384) && (UPVItem->pos.xRot <= 16384))
coll->Setup.ForwardAngle = laraInfo->moveAngle = UPVItem->pos.yRot;
else
2021-12-08 15:27:46 +11:00
coll->Setup.ForwardAngle = laraInfo->moveAngle = UPVItem->pos.yRot - ANGLE(180.0f);
2021-12-08 15:27:46 +11:00
int height = phd_sin(UPVItem->pos.xRot) * SUB_LENGTH;
if (height < 0)
height = -height;
if (height < 200)
height = 200;
coll->Setup.UpperFloorBound = -height;
coll->Setup.Height = height;
2021-12-08 15:27:46 +11:00
GetCollisionInfo(coll, UPVItem, PHD_VECTOR(0, height / 2, 0));
ShiftItem(UPVItem, coll);
2021-09-10 00:18:47 +03:00
if (coll->CollisionType == CT_FRONT)
{
2021-12-08 15:27:46 +11:00
if (UPVInfo->RotX > FRONT_TOLERANCE)
UPVInfo->RotX += WALLDEFLECT;
else if (UPVInfo->RotX < -FRONT_TOLERANCE)
UPVInfo->RotX -= WALLDEFLECT;
else
{
2021-12-08 22:02:02 +11:00
if (abs(UPVInfo->Vel) >= MAX_SPEED)
{
2021-12-08 15:27:46 +11:00
laraItem->goalAnimState = UPV_STATE_HIT;
UPVInfo->Vel = -UPVInfo->Vel / 2;
}
else
2021-12-08 22:02:02 +11:00
UPVInfo->Vel = 0;
}
}
2021-09-10 00:18:47 +03:00
else if (coll->CollisionType == CT_TOP)
{
2021-12-08 15:27:46 +11:00
if (UPVInfo->RotX >= -TOP_TOLERANCE)
UPVInfo->RotX -= WALLDEFLECT;
}
2021-09-10 00:18:47 +03:00
else if (coll->CollisionType == CT_TOP_FRONT)
2021-12-08 15:27:46 +11:00
UPVInfo->Vel = 0;
2021-09-10 00:18:47 +03:00
else if (coll->CollisionType == CT_LEFT)
2021-12-08 15:27:46 +11:00
UPVItem->pos.yRot += ANGLE(5.0f);
2021-09-10 00:18:47 +03:00
else if (coll->CollisionType == CT_RIGHT)
2021-12-08 15:27:46 +11:00
UPVItem->pos.yRot -= ANGLE(5.0f);
2021-09-10 00:18:47 +03:00
else if (coll->CollisionType == CT_CLAMP)
{
2021-12-08 15:27:46 +11:00
UPVItem->pos.xPos = coll->Setup.OldPosition.x;
UPVItem->pos.yPos = coll->Setup.OldPosition.y;
UPVItem->pos.zPos = coll->Setup.OldPosition.z;
UPVInfo->Vel = 0;
return;
}
2021-09-10 00:18:47 +03:00
if (coll->Middle.Floor < 0)
{
2021-12-08 15:27:46 +11:00
UPVItem->pos.yPos += coll->Middle.Floor;
UPVInfo->RotX += WALLDEFLECT;
}
}
2021-12-08 15:27:46 +11:00
static void UserInput(ITEM_INFO* laraItem, ITEM_INFO* UPVItem)
{
2021-12-08 15:27:46 +11:00
LaraInfo*& laraInfo = laraItem->data;
SUB_INFO* UPVInfo = UPVItem->data;
2021-12-08 15:27:46 +11:00
TestUPVDismount(laraItem, UPVItem);
2021-12-08 15:27:46 +11:00
int anim = laraItem->animNumber - Objects[ID_UPV_LARA_ANIMS].animIndex;
int frame = laraItem->frameNumber - g_Level.Anims[laraItem->animNumber].frameBase;
2021-12-08 15:27:46 +11:00
switch (laraItem->currentAnimState)
{
2021-12-08 15:27:46 +11:00
case UPV_STATE_MOVE:
if (laraItem->hitPoints <= 0)
{
2021-12-08 15:27:46 +11:00
laraItem->goalAnimState = UPV_STATE_DEATH;
break;
}
2021-12-08 15:27:46 +11:00
if (TrInput & UPV_IN_LEFT)
UPVInfo->Rot -= ROT_ACCELERATION;
2021-12-08 15:27:46 +11:00
else if (TrInput & UPV_IN_RIGHT)
UPVInfo->Rot += ROT_ACCELERATION;
2021-12-08 15:27:46 +11:00
if (UPVInfo->Flags & UPV_SURFACE)
{
2021-12-08 15:27:46 +11:00
int xa = UPVItem->pos.xRot - SURFACE_ANGLE;
int ax = SURFACE_ANGLE - UPVItem->pos.xRot;
2020-09-30 22:00:54 -05:00
if (xa > 0)
{
2021-12-08 15:27:46 +11:00
if (xa > ANGLE(1.0f))
UPVItem->pos.xRot -= ANGLE(1.0f);
2020-09-30 22:00:54 -05:00
else
2021-12-08 15:27:46 +11:00
UPVItem->pos.xRot -= ANGLE(0.1f);
2020-09-30 22:00:54 -05:00
}
else if (ax)
{
2021-12-08 15:27:46 +11:00
if (ax > ANGLE(1.0f))
UPVItem->pos.xRot += ANGLE(1.0f);
2020-09-30 22:00:54 -05:00
else
2021-12-08 15:27:46 +11:00
UPVItem->pos.xRot += ANGLE(0.1f);
2020-09-30 22:00:54 -05:00
}
else
2021-12-08 15:27:46 +11:00
UPVItem->pos.xRot = SURFACE_ANGLE;
}
else
{
2021-12-08 15:27:46 +11:00
if (TrInput & UPV_IN_UP)
UPVInfo->RotX -= UPDOWN_ACCEL;
else if (TrInput & UPV_IN_DOWN)
UPVInfo->RotX += UPDOWN_ACCEL;
}
2021-12-08 15:27:46 +11:00
if (TrInput & UPV_IN_PROPEL)
{
2021-12-08 15:27:46 +11:00
if (TrInput & UPV_IN_UP &&
UPVInfo->Flags & UPV_SURFACE &&
UPVItem->pos.xRot > -DIVE_ANGLE)
{
UPVInfo->Flags |= UPV_DIVE;
}
2021-12-08 15:27:46 +11:00
UPVInfo->Vel += ACCELERATION;
}
else
2021-12-08 15:27:46 +11:00
laraItem->goalAnimState = UPV_STATE_IDLE;
break;
2021-12-08 15:27:46 +11:00
case UPV_STATE_IDLE:
if (laraItem->hitPoints <= 0)
{
2021-12-08 15:27:46 +11:00
laraItem->goalAnimState = UPV_STATE_DEATH;
break;
}
2021-12-08 15:27:46 +11:00
if (TrInput & UPV_IN_LEFT)
UPVInfo->Rot -= ROT_SLOWACCEL;
else if (TrInput & UPV_IN_RIGHT)
UPVInfo->Rot += ROT_SLOWACCEL;
2021-12-08 15:27:46 +11:00
if (UPVInfo->Flags & UPV_SURFACE)
{
2021-12-08 15:27:46 +11:00
int xa = UPVItem->pos.xRot - SURFACE_ANGLE;
int ax = SURFACE_ANGLE - UPVItem->pos.xRot;
2020-09-30 22:00:54 -05:00
if (xa > 0)
{
2021-12-08 15:27:46 +11:00
if (xa > ANGLE(1.0f))
UPVItem->pos.xRot -= ANGLE(1.0f);
2020-09-30 22:00:54 -05:00
else
2021-12-08 15:27:46 +11:00
UPVItem->pos.xRot -= ANGLE(0.1f);
2020-09-30 22:00:54 -05:00
}
else if (ax)
{
2021-12-08 15:27:46 +11:00
if (ax > ANGLE(1.0f))
UPVItem->pos.xRot += ANGLE(1.0f);
2020-09-30 22:00:54 -05:00
else
2021-12-08 15:27:46 +11:00
UPVItem->pos.xRot += ANGLE(0.1f);
2020-09-30 22:00:54 -05:00
}
else
2021-12-08 15:27:46 +11:00
UPVItem->pos.xRot = SURFACE_ANGLE;
}
else
{
2021-12-08 15:27:46 +11:00
if (TrInput & UPV_IN_UP)
UPVInfo->RotX -= UPDOWN_ACCEL;
else if (TrInput & UPV_IN_DOWN)
UPVInfo->RotX += UPDOWN_ACCEL;
}
2021-12-08 15:27:46 +11:00
if (TrInput & UPV_IN_DISMOUNT && TestUPVDismount(laraItem, UPVItem))
{
2021-12-08 15:27:46 +11:00
if (UPVInfo->Vel > 0)
UPVInfo->Vel -= ACCELERATION;
2020-10-19 15:06:51 -05:00
else
2020-09-28 15:21:19 -05:00
{
2021-12-08 15:27:46 +11:00
if (UPVInfo->Flags & UPV_SURFACE)
laraItem->goalAnimState = UPV_STATE_DISMOUNT_SURFACE;
2020-09-28 15:21:19 -05:00
else
2021-12-08 15:27:46 +11:00
laraItem->goalAnimState = UPV_STATE_DISMOUNT_UNDERWATER;
2021-10-06 19:54:04 +03:00
2020-10-19 15:06:51 -05:00
//sub->Flags &= ~UPV_CONTROL; having this here causes the UPV glitch, moving it directly to the states' code is better
2021-10-06 19:54:04 +03:00
StopSoundEffect(SFX_TR3_LITTLE_SUB_LOOP);
2021-12-08 15:27:46 +11:00
SoundEffect(SFX_TR3_LITTLE_SUB_STOP, (PHD_3DPOS*)&UPVItem->pos.xPos, 2);
2020-09-28 15:21:19 -05:00
}
}
2021-12-08 15:27:46 +11:00
else if (TrInput & UPV_IN_PROPEL)
{
2021-12-08 15:27:46 +11:00
if (TrInput & UPV_IN_UP &&
UPVInfo->Flags & UPV_SURFACE &&
UPVItem->pos.xRot > -DIVE_ANGLE)
{
UPVInfo->Flags |= UPV_DIVE;
}
2021-12-08 15:27:46 +11:00
laraItem->goalAnimState = UPV_STATE_MOVE;
}
break;
2021-12-08 15:27:46 +11:00
case UPV_STATE_MOUNT:
if (anim == UPV_ANIM_MOUNT_SURFACE_END)
{
2021-12-08 15:27:46 +11:00
UPVItem->pos.yPos += 4;
UPVItem->pos.xRot += ANGLE(1.0f);
2021-12-08 15:27:46 +11:00
if (frame == MOUNT_SURFACE_SOUND_FRAME)
SoundEffect(SFX_TR3_LITTLE_SUB_LOOP, (PHD_3DPOS*)&UPVItem->pos.xPos, 2);
2021-12-08 15:27:46 +11:00
if (frame == MOUNT_SURFACE_CONTROL_FRAME)
UPVInfo->Flags |= UPV_CONTROL;
}
2021-12-08 15:27:46 +11:00
else if (anim == UPV_ANIM_MOUNT_UNDERWATER)
{
2021-12-08 15:27:46 +11:00
if (frame == MOUNT_UNDERWATER_SOUND_FRAME)
SoundEffect(SFX_TR3_LITTLE_SUB_LOOP, (PHD_3DPOS*)&UPVItem->pos.xPos, 2);
2021-12-08 15:27:46 +11:00
if (frame == MOUNT_UNDERWATER_CONTROL_FRAME)
UPVInfo->Flags |= UPV_CONTROL;
}
break;
2021-12-08 15:27:46 +11:00
case UPV_STATE_DISMOUNT_UNDERWATER:
if (anim == UPV_ANIM_DISMOUNT_UNDERWATER && frame == DISMOUNT_UNDERWATER_FRAME)
{
2021-12-08 15:27:46 +11:00
UPVInfo->Flags &= ~UPV_CONTROL;
PHD_VECTOR vec = { 0, 0, 0 };
GAME_VECTOR VPos, LPos;
2019-12-15 16:19:01 +01:00
GetLaraJointPosition(&vec, LM_HIPS);
LPos.x = vec.x;
LPos.y = vec.y;
LPos.z = vec.z;
2021-12-08 15:27:46 +11:00
LPos.roomNumber = UPVItem->roomNumber;
VPos.x = UPVItem->pos.xPos;
VPos.y = UPVItem->pos.yPos;
VPos.z = UPVItem->pos.zPos;
VPos.roomNumber = UPVItem->roomNumber;
2021-12-01 18:12:04 +03:00
LOSAndReturnTarget(&VPos, &LPos, 0);
2021-12-08 15:27:46 +11:00
laraItem->pos.xPos = LPos.x;
laraItem->pos.yPos = LPos.y;
laraItem->pos.zPos = LPos.z;
2021-12-08 15:27:46 +11:00
SetAnimation(laraItem, LA_UNDERWATER_IDLE);
laraItem->fallspeed = 0;
2022-01-21 23:23:10 +11:00
laraItem->airborne = false;
2021-12-08 15:27:46 +11:00
laraItem->pos.xRot = laraItem->pos.zRot = 0;
2021-12-08 15:27:46 +11:00
UpdateItemRoom(laraItem, 0);
2021-12-08 15:27:46 +11:00
laraInfo->waterStatus = LW_UNDERWATER;
laraInfo->gunStatus = LG_HANDS_FREE;
2021-12-08 15:27:46 +11:00
laraInfo->Vehicle = NO_ITEM;
2021-12-08 15:27:46 +11:00
UPVItem->hitPoints = 0;
}
break;
2021-12-08 15:27:46 +11:00
case UPV_STATE_DISMOUNT_SURFACE:
if (anim == UPV_ANIM_DISMOUNT_SURFACE && frame == DISMOUNT_SURFACE_FRAME)
{
2021-12-08 15:27:46 +11:00
UPVInfo->Flags &= ~UPV_CONTROL;
int waterDepth, waterHeight, heightFromWater;
PHD_VECTOR vec = { 0, 0, 0 };
waterDepth = GetWaterSurface(laraItem);
waterHeight = GetWaterHeight(laraItem);
2021-12-08 15:27:46 +11:00
if (waterHeight != NO_HEIGHT)
heightFromWater = laraItem->pos.yPos - waterHeight;
else
2021-12-08 15:27:46 +11:00
heightFromWater = NO_HEIGHT;
2019-12-15 16:19:01 +01:00
GetLaraJointPosition(&vec, LM_HIPS);
2021-12-08 15:27:46 +11:00
laraItem->pos.xPos = vec.x;
2021-12-08 22:02:02 +11:00
//laraItem->pos.yPos += -heightFromWater + 1; // Doesn't work as intended.
2021-12-08 15:27:46 +11:00
laraItem->pos.yPos = vec.y;
laraItem->pos.zPos = vec.z;
2021-12-08 22:02:02 +11:00
SetAnimation(laraItem, LA_ONWATER_IDLE);
2021-12-08 15:27:46 +11:00
laraItem->fallspeed = 0;
2022-01-21 23:23:10 +11:00
laraItem->airborne = false;
2021-12-08 15:27:46 +11:00
laraItem->pos.xRot = laraItem->pos.zRot = 0;
UpdateItemRoom(laraItem, -LARA_HEIGHT / 2);
laraInfo->waterStatus = LW_SURFACE;
laraInfo->waterSurfaceDist = -heightFromWater;
laraInfo->diveCount = 11;
laraInfo->torsoXrot = 0;
laraInfo->torsoYrot = 0;
laraInfo->headXrot = 0;
laraInfo->headYrot = 0;
laraInfo->gunStatus = LG_HANDS_FREE;
2021-12-08 15:27:46 +11:00
laraInfo->Vehicle = NO_ITEM;
UPVItem->hitPoints = 0;
}
2021-12-08 22:02:02 +11:00
else
{
UPVInfo->RotX -= UPDOWN_ACCEL;
if (UPVItem->pos.xRot < 0)
UPVItem->pos.xRot = 0;
}
break;
2021-12-08 15:27:46 +11:00
case UPV_STATE_DEATH:
if (anim == UPV_ANIM_DEATH && (frame == DEATH_FRAME_1 || frame == DEATH_FRAME_2))
{
PHD_VECTOR vec = { 0, 0, 0 };
2019-12-15 16:19:01 +01:00
GetLaraJointPosition(&vec, LM_HIPS);
2021-12-08 15:27:46 +11:00
laraItem->pos.xPos = vec.x;
laraItem->pos.yPos = vec.y;
laraItem->pos.zPos = vec.z;
laraItem->pos.xRot = 0;
laraItem->pos.zRot = 0;
SetAnimation(UPVItem, LA_UNDERWATER_DEATH, 17);
laraItem->fallspeed = 0;
2022-01-21 23:23:10 +11:00
laraItem->airborne = 0;
2021-12-08 15:27:46 +11:00
UPVInfo->Flags |= UPV_DEAD;
}
2021-12-08 15:27:46 +11:00
UPVItem->speed = 0;
break;
}
2021-12-08 15:27:46 +11:00
if (UPVInfo->Flags & UPV_DIVE)
{
2021-12-08 15:27:46 +11:00
if (UPVItem->pos.xRot > -DIVE_ANGLE)
UPVItem->pos.xRot -= DIVE_SPEED;
else
2021-12-08 15:27:46 +11:00
UPVInfo->Flags &= ~UPV_DIVE;
}
2021-12-08 15:27:46 +11:00
if (UPVInfo->Vel > 0)
{
2021-12-08 15:27:46 +11:00
UPVInfo->Vel -= FRICTION;
if (UPVInfo->Vel < 0)
UPVInfo->Vel = 0;
}
2021-12-08 15:27:46 +11:00
else if (UPVInfo->Vel < 0)
{
2021-12-08 15:27:46 +11:00
UPVInfo->Vel += FRICTION;
if (UPVInfo->Vel > 0)
UPVInfo->Vel = 0;
}
2021-12-08 15:27:46 +11:00
if (UPVInfo->Vel > MAX_SPEED)
UPVInfo->Vel = MAX_SPEED;
else if (UPVInfo->Vel < -MAX_SPEED)
UPVInfo->Vel = -MAX_SPEED;
2021-12-08 15:27:46 +11:00
if (UPVInfo->Rot > 0)
{
2021-12-08 15:27:46 +11:00
UPVInfo->Rot -= ROT_FRICTION;
if (UPVInfo->Rot < 0)
UPVInfo->Rot = 0;
}
2021-12-08 15:27:46 +11:00
else if (UPVInfo->Rot < 0)
{
2021-12-08 15:27:46 +11:00
UPVInfo->Rot += ROT_FRICTION;
if (UPVInfo->Rot > 0)
UPVInfo->Rot = 0;
}
2021-12-08 15:27:46 +11:00
if (UPVInfo->RotX > 0)
{
2021-12-08 15:27:46 +11:00
UPVInfo->RotX -= UPDOWN_FRICTION;
if (UPVInfo->RotX < 0)
UPVInfo->RotX = 0;
}
2021-12-08 15:27:46 +11:00
else if (UPVInfo->RotX < 0)
{
2021-12-08 15:27:46 +11:00
UPVInfo->RotX += UPDOWN_FRICTION;
if (UPVInfo->RotX > 0)
UPVInfo->RotX = 0;
}
2021-12-08 15:27:46 +11:00
if (UPVInfo->Rot > MAX_ROTATION)
UPVInfo->Rot = MAX_ROTATION;
else if (UPVInfo->Rot < -MAX_ROTATION)
UPVInfo->Rot = -MAX_ROTATION;
2021-12-08 15:27:46 +11:00
if (UPVInfo->RotX > MAX_UPDOWN)
UPVInfo->RotX = MAX_UPDOWN;
else if (UPVInfo->RotX < -MAX_UPDOWN)
UPVInfo->RotX = -MAX_UPDOWN;
}
2021-12-08 15:27:46 +11:00
void NoGetOnCollision(short itemNum, ITEM_INFO* laraitem, COLL_INFO* coll)
{
2021-12-08 15:27:46 +11:00
ITEM_INFO* item = &g_Level.Items[itemNum];
2021-09-10 00:20:59 +03:00
if (!TestBoundsCollide(item, laraitem, coll->Setup.Radius))
2020-09-28 15:21:19 -05:00
return;
if (!TestCollision(item, laraitem))
return;
2021-12-08 15:27:46 +11:00
ItemPushItem(item, laraitem, coll, 0, 0);
2020-09-28 15:21:19 -05:00
}
2021-12-08 15:27:46 +11:00
void SubCollision(short itemNum, ITEM_INFO* laraItem, COLL_INFO* coll)
{
2021-12-08 15:27:46 +11:00
LaraInfo*& laraInfo = laraItem->data;
2021-12-08 15:27:46 +11:00
if (laraItem->hitPoints <= 0 || laraInfo->Vehicle != NO_ITEM)
return;
2021-12-08 15:27:46 +11:00
ITEM_INFO* UPVItem = &g_Level.Items[itemNum];
2021-12-08 15:27:46 +11:00
if (TestUPVMount(laraItem, UPVItem))
{
2021-12-08 15:27:46 +11:00
laraInfo->Vehicle = itemNum;
laraInfo->waterStatus = LW_ABOVE_WATER;
2021-12-08 15:27:46 +11:00
if (laraInfo->gunType == WEAPON_FLARE)
{
CreateFlare(LaraItem, ID_FLARE_ITEM, 0);
2021-12-09 00:48:55 +11:00
UndrawFlareMeshes(laraItem);
2021-12-08 15:27:46 +11:00
laraInfo->flareControlLeft = false;
laraInfo->requestGunType = laraInfo->gunType = WEAPON_NONE;
}
2021-12-08 15:27:46 +11:00
laraInfo->gunStatus = LG_HANDS_BUSY;
laraItem->pos.xPos = UPVItem->pos.xPos;
laraItem->pos.yPos = UPVItem->pos.yPos;
laraItem->pos.zPos = UPVItem->pos.zPos;
laraItem->pos.xRot = UPVItem->pos.xRot;
laraItem->pos.yRot = UPVItem->pos.yRot;
laraItem->pos.zRot = UPVItem->pos.zRot;
UPVItem->hitPoints = 1;
2021-12-08 15:27:46 +11:00
if (laraItem->currentAnimState == LS_ONWATER_STOP || laraItem->currentAnimState == LS_ONWATER_FORWARD)
{
2021-12-08 15:27:46 +11:00
laraItem->animNumber = Objects[ID_UPV_LARA_ANIMS].animIndex + UPV_ANIM_MOUNT_SURFACE_START;
laraItem->currentAnimState = laraItem->goalAnimState = UPV_STATE_MOUNT;
}
else
{
2021-12-08 15:27:46 +11:00
laraItem->animNumber = Objects[ID_UPV_LARA_ANIMS].animIndex + UPV_ANIM_MOUNT_UNDERWATER;
laraItem->currentAnimState = laraItem->goalAnimState = UPV_STATE_MOUNT;
}
2021-12-08 15:27:46 +11:00
laraItem->frameNumber = g_Level.Anims[laraItem->animNumber].frameBase;
2021-12-08 15:27:46 +11:00
AnimateItem(laraItem);
}
else
{
2021-12-08 15:27:46 +11:00
UPVItem->pos.yPos += SUB_DRAW_SHIFT;
NoGetOnCollision(itemNum, laraItem, coll);
UPVItem->pos.yPos -= SUB_DRAW_SHIFT;
}
}
2021-12-08 15:27:46 +11:00
bool SubControl(ITEM_INFO* laraItem, COLL_INFO* coll)
{
2021-12-08 15:27:46 +11:00
LaraInfo*& laraInfo = laraItem->data;
ITEM_INFO* UPVItem = &g_Level.Items[laraInfo->Vehicle];
SUB_INFO* UPVInfo = UPVItem->data;
2021-12-19 03:54:13 +03:00
auto oldPos = UPVItem->pos;
2021-12-08 15:27:46 +11:00
auto probe = GetCollisionResult(UPVItem);
2021-12-08 15:27:46 +11:00
if (!(UPVInfo->Flags & UPV_DEAD))
{
2021-12-08 15:27:46 +11:00
UserInput(laraItem, UPVItem);
2021-12-08 15:27:46 +11:00
UPVItem->speed = UPVInfo->Vel / 65536;
2021-12-08 15:27:46 +11:00
UPVItem->pos.xRot += UPVInfo->RotX / 65536;
UPVItem->pos.yRot += UPVInfo->Rot / 65536;
UPVItem->pos.zRot = UPVInfo->Rot / 65536;
2021-12-08 15:27:46 +11:00
if (UPVItem->pos.xRot > UPDOWN_LIMIT)
UPVItem->pos.xRot = UPDOWN_LIMIT;
else if (UPVItem->pos.xRot < -UPDOWN_LIMIT)
UPVItem->pos.xRot = -UPDOWN_LIMIT;
2021-12-08 15:27:46 +11:00
UPVItem->pos.xPos += phd_sin(UPVItem->pos.yRot) * UPVItem->speed * phd_cos(UPVItem->pos.xRot);
UPVItem->pos.yPos -= phd_sin(UPVItem->pos.xRot) * UPVItem->speed;
UPVItem->pos.zPos += phd_cos(UPVItem->pos.yRot) * UPVItem->speed * phd_cos(UPVItem->pos.xRot);
}
2021-12-19 03:54:13 +03:00
int newHeight = GetCollisionResult(UPVItem).Position.Floor;
int waterHeight = GetWaterHeight(UPVItem);
2021-12-19 03:54:13 +03:00
if ((newHeight - waterHeight) < SUB_HEIGHT || (newHeight < UPVItem->pos.yPos - SUB_HEIGHT / 2))
{
2021-12-19 03:54:13 +03:00
UPVItem->pos.xPos = oldPos.xPos;
UPVItem->pos.yPos = oldPos.yPos;
UPVItem->pos.zPos = oldPos.zPos;
UPVItem->speed = 0;
}
2021-12-19 03:54:13 +03:00
UPVItem->floor = probe.Position.Floor;
if (UPVInfo->Flags & UPV_CONTROL && !(UPVInfo->Flags & UPV_DEAD))
{
2021-12-08 15:27:46 +11:00
if (!(g_Level.Rooms[UPVItem->roomNumber].flags & ENV_FLAG_WATER) &&
waterHeight != NO_HEIGHT)
{
2021-12-08 15:27:46 +11:00
if ((waterHeight - UPVItem->pos.yPos) >= -SURFACE_DIST)
UPVItem->pos.yPos = waterHeight + SURFACE_DIST;
2021-12-08 15:27:46 +11:00
if (!(UPVInfo->Flags & UPV_SURFACE))
{
2021-10-06 19:54:04 +03:00
SoundEffect(SFX_TR4_LARA_BREATH, &LaraItem->pos, 2);
2021-12-08 15:27:46 +11:00
UPVInfo->Flags &= ~UPV_DIVE;
}
2021-12-08 15:27:46 +11:00
UPVInfo->Flags |= UPV_SURFACE;
}
2021-12-19 03:54:13 +03:00
else if ((waterHeight - UPVItem->pos.yPos) >= -SURFACE_DIST && waterHeight != NO_HEIGHT)
{
2021-12-08 15:27:46 +11:00
UPVItem->pos.yPos = waterHeight + SURFACE_DIST;
2021-12-08 15:27:46 +11:00
if (!(UPVInfo->Flags & UPV_SURFACE))
{
2021-10-06 19:54:04 +03:00
SoundEffect(SFX_TR4_LARA_BREATH, &LaraItem->pos, 2);
2021-12-08 15:27:46 +11:00
UPVInfo->Flags &= ~UPV_DIVE;
}
2021-12-08 15:27:46 +11:00
UPVInfo->Flags |= UPV_SURFACE;
}
else
2021-12-08 15:27:46 +11:00
UPVInfo->Flags &= ~UPV_SURFACE;
2021-12-08 15:27:46 +11:00
if (!(UPVInfo->Flags & UPV_SURFACE))
{
2021-12-08 15:27:46 +11:00
if (laraItem->hitPoints > 0)
{
2021-12-08 15:27:46 +11:00
laraInfo->air--;
2021-12-08 15:27:46 +11:00
if (laraInfo->air < 0)
{
2021-12-08 15:27:46 +11:00
laraInfo->air = -1;
laraItem->hitPoints -= 5;
}
}
}
else
{
2021-12-08 15:27:46 +11:00
if (laraItem->hitPoints >= 0)
{
2021-12-08 15:27:46 +11:00
laraInfo->air += 10;
2021-12-08 15:27:46 +11:00
if (laraInfo->air > 1800)
laraInfo->air = 1800;
}
}
}
2021-12-08 15:27:46 +11:00
TestTriggers(UPVItem, false);
SubEffects(laraInfo->Vehicle);
2021-12-08 15:27:46 +11:00
if (!(UPVInfo->Flags & UPV_DEAD) &&
laraInfo->Vehicle != NO_ITEM)
{
2021-12-08 15:27:46 +11:00
DoCurrent(UPVItem);
2021-12-08 15:27:46 +11:00
if (TrInput & UPV_IN_FIRE &&
UPVInfo->Flags & UPV_CONTROL &&
!UPVInfo->WeaponTimer)
{
2021-12-08 15:27:46 +11:00
if (laraItem->currentAnimState != UPV_STATE_DISMOUNT_UNDERWATER &&
laraItem->currentAnimState != UPV_STATE_DISMOUNT_SURFACE &&
laraItem->currentAnimState != UPV_STATE_MOUNT)
{
FireSubHarpoon(laraItem, UPVItem);
UPVInfo->WeaponTimer = HARPOON_RELOAD;
}
}
2021-12-08 15:27:46 +11:00
if (probe.RoomNumber != UPVItem->roomNumber)
{
2021-12-08 15:27:46 +11:00
ItemNewRoom(laraInfo->Vehicle, probe.RoomNumber);
ItemNewRoom(laraInfo->itemNumber, probe.RoomNumber);
}
2021-12-08 15:27:46 +11:00
laraItem->pos.xPos = UPVItem->pos.xPos;
laraItem->pos.yPos = UPVItem->pos.yPos;
laraItem->pos.zPos = UPVItem->pos.zPos;
laraItem->pos.xRot = UPVItem->pos.xRot;
laraItem->pos.yRot = UPVItem->pos.yRot;
laraItem->pos.zRot = UPVItem->pos.zRot;
2021-12-08 15:27:46 +11:00
AnimateItem(laraItem);
BackgroundCollision(laraItem, UPVItem);
2021-12-08 15:27:46 +11:00
if (UPVInfo->Flags & UPV_CONTROL)
SoundEffect(SFX_TR3_LITTLE_SUB_LOOP, (PHD_3DPOS*)&UPVItem->pos.xPos, 2 | 4 | 0x1000000 | (UPVItem->speed * 65536));
2021-12-08 15:27:46 +11:00
UPVItem->animNumber = Objects[ID_UPV].animIndex + (laraItem->animNumber - Objects[ID_UPV_LARA_ANIMS].animIndex);
UPVItem->frameNumber = g_Level.Anims[UPVItem->animNumber].frameBase + (laraItem->frameNumber - g_Level.Anims[laraItem->animNumber].frameBase);
2021-12-08 15:27:46 +11:00
if (UPVInfo->Flags & UPV_SURFACE)
Camera.targetElevation = -ANGLE(60.0f);
else
Camera.targetElevation = 0;
2021-12-08 15:27:46 +11:00
return true;
}
2021-12-08 15:27:46 +11:00
else if (UPVInfo->Flags & UPV_DEAD)
{
2021-12-08 15:27:46 +11:00
AnimateItem(laraItem);
2021-12-08 15:27:46 +11:00
if (probe.RoomNumber != UPVItem->roomNumber)
ItemNewRoom(laraInfo->Vehicle, probe.RoomNumber);
2021-12-08 15:27:46 +11:00
BackgroundCollision(laraItem, UPVItem);
2021-12-08 15:27:46 +11:00
UPVInfo->RotX = 0;
2021-12-08 15:27:46 +11:00
SetAnimation(UPVItem, UPV_ANIM_IDLE);
UPVItem->fallspeed = 0;
UPVItem->speed = 0;
2022-01-21 23:23:10 +11:00
UPVItem->airborne = true;
2021-12-08 15:27:46 +11:00
AnimateItem(UPVItem);
2021-12-08 15:27:46 +11:00
return true;
}
else
2021-12-08 15:27:46 +11:00
return false;
}