2020-05-27 09:21:20 +02:00
|
|
|
#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"
|
2022-02-08 20:45:21 +11:00
|
|
|
#include "Game/Lara/lara_helpers.h"
|
2021-12-22 16:23:57 +03:00
|
|
|
#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
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
BITE_INFO UPVBites[6] =
|
|
|
|
{
|
|
|
|
{ 0, 0, 0, 3 },
|
|
|
|
{ 0, 96, 256, 0 },
|
|
|
|
{ -128, 0, -64, 1 },
|
|
|
|
{ 0, 0, -64, 1 },
|
|
|
|
{ 128, 0, -64, 2 },
|
|
|
|
{ 0, 0, -64, 2 }
|
|
|
|
};
|
|
|
|
|
2020-09-28 15:21:19 -05:00
|
|
|
#define UPV_CONTROL 1
|
|
|
|
#define UPV_SURFACE 2
|
|
|
|
#define UPV_DIVE 4
|
|
|
|
#define UPV_DEAD 8
|
2019-11-27 15:12:35 +01:00
|
|
|
|
|
|
|
#define ACCELERATION 0x40000
|
|
|
|
#define FRICTION 0x18000
|
2022-02-20 17:12:42 +11:00
|
|
|
#define MAX_VELOCITY 0x400000
|
2019-11-27 15:12:35 +01:00
|
|
|
#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)
|
2019-11-27 15:12:35 +01:00
|
|
|
#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)
|
2019-11-27 15:12:35 +01:00
|
|
|
#define SUB_DRAW_SHIFT 128
|
|
|
|
#define SUB_RADIUS 300
|
|
|
|
#define SUB_HEIGHT 400
|
2022-02-28 21:02:19 +11:00
|
|
|
#define SUB_LENGTH SECTOR(1)
|
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)
|
2022-02-28 21:02:19 +11:00
|
|
|
#define GETOFF_DIST SECTOR(1)
|
|
|
|
#define HARPOON_VELOCITY CLICK(1)
|
2019-11-27 15:12:35 +01:00
|
|
|
#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
|
|
|
|
|
|
|
|
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
|
2019-11-27 15:12:35 +01:00
|
|
|
};
|
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
// TODO
|
|
|
|
enum UPVAnim
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
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,
|
|
|
|
};
|
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
enum SUB_BITE_FLAG
|
2021-12-08 15:27:46 +11:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
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
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
void UPVInitialise(short itemNumber)
|
|
|
|
{
|
|
|
|
ITEM_INFO* UPVItem = &g_Level.Items[itemNumber];
|
|
|
|
UPVItem->Data = UPVInfo();
|
|
|
|
UPVInfo* UPV = UPVItem->Data;
|
|
|
|
|
|
|
|
UPV->Vel = UPV->Rot = 0;
|
|
|
|
UPV->Flags = UPV_SURFACE;
|
|
|
|
UPV->WeaponTimer = 0;
|
2021-12-08 15:27:46 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
static void FireSubHarpoon(ITEM_INFO* laraItem, ITEM_INFO* UPVItem)
|
|
|
|
{
|
|
|
|
short itemNum = CreateItem();
|
2019-11-27 15:12:35 +01:00
|
|
|
|
|
|
|
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];
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
harpoonItem->ObjectNumber = ID_HARPOON;
|
|
|
|
harpoonItem->Shade = 0xC210;
|
|
|
|
harpoonItem->RoomNumber = UPVItem->RoomNumber;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
GetJointAbsPosition(UPVItem, &pos, UPV_TURBINE_BONE);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
harpoonItem->Position.xPos = pos.x;
|
|
|
|
harpoonItem->Position.yPos = pos.y;
|
|
|
|
harpoonItem->Position.zPos = pos.z;
|
2019-11-27 15:12:35 +01:00
|
|
|
InitialiseItem(itemNum);
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
harpoonItem->Position.xRot = UPVItem->Position.xRot;
|
|
|
|
harpoonItem->Position.yRot = UPVItem->Position.yRot;
|
|
|
|
harpoonItem->Position.zRot = 0;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
harpoonItem->VerticalVelocity = -HARPOON_VELOCITY * phd_sin(harpoonItem->Position.xRot);
|
|
|
|
harpoonItem->VerticalVelocity = HARPOON_VELOCITY * phd_cos(harpoonItem->Position.xRot);
|
2022-02-09 16:55:46 +11:00
|
|
|
harpoonItem->HitPoints = HARPOON_TIME;
|
|
|
|
harpoonItem->ItemFlags[0] = 1;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
|
|
|
AddActiveItem(itemNum);
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
SoundEffect(SFX_TR3_LARA_HARPOON_FIRE_WATER, &LaraItem->Position, 2);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
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]--;
|
2021-10-31 21:36:13 +03:00
|
|
|
Statistics.Game.AmmoUsed++;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
|
|
|
lr ^= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-27 09:21:20 +02:00
|
|
|
static void TriggerSubMist(long x, long y, long z, long speed, short angle)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
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;
|
2019-11-27 15:12:35 +01:00
|
|
|
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;
|
2019-11-27 15:12:35 +01:00
|
|
|
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
|
|
|
|
2019-11-27 15:12:35 +01: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;
|
2019-11-27 15:12:35 +01:00
|
|
|
sptr->dSize = size;
|
|
|
|
}
|
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
void SubEffects(short itemNum)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
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;
|
2022-02-28 21:02:19 +11:00
|
|
|
auto* lara = GetLaraInfo(laraItem);
|
2021-12-08 15:27:46 +11:00
|
|
|
ITEM_INFO* UPVItem = &g_Level.Items[itemNum];
|
2022-02-28 21:02:19 +11:00
|
|
|
UPVInfo* UPV = UPVItem->Data;
|
|
|
|
|
2019-11-27 15:12:35 +01:00
|
|
|
PHD_VECTOR pos;
|
|
|
|
long lp;
|
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (lara->Vehicle == itemNum)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
if (!UPV->Vel)
|
|
|
|
UPV->FanRot += ANGLE(2.0f);
|
2019-11-27 15:12:35 +01:00
|
|
|
else
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->FanRot += (UPV->Vel / 4069);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (UPV->Vel)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
pos = { UPVBites[SUB_FAN].x, UPVBites[SUB_FAN].y, UPVBites[SUB_FAN].z };
|
|
|
|
GetJointAbsPosition(UPVItem, &pos, UPVBites[SUB_FAN].meshNum);
|
|
|
|
TriggerSubMist(pos.x, pos.y + SUB_DRAW_SHIFT, pos.z, abs(UPV->Vel) / 65536, UPVItem->Position.yRot + ANGLE(180.0f));
|
2019-11-27 15:12:35 +01:00
|
|
|
|
|
|
|
if ((GetRandomControl() & 1) == 0)
|
|
|
|
{
|
|
|
|
PHD_3DPOS pos3d;
|
2021-12-08 15:27:46 +11:00
|
|
|
short roomNum;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
|
|
|
pos3d.xPos = pos.x + (GetRandomControl() & 63) - 32;
|
|
|
|
pos3d.yPos = pos.y + SUB_DRAW_SHIFT;
|
|
|
|
pos3d.zPos = pos.z + (GetRandomControl() & 63) - 32;
|
2022-02-09 16:55:46 +11:00
|
|
|
roomNum = UPVItem->RoomNumber;
|
2021-12-08 15:27:46 +11:00
|
|
|
GetFloor(pos3d.xPos, pos3d.yPos, pos3d.zPos, &roomNum);
|
|
|
|
CreateBubble((PHD_VECTOR*)&pos3d, roomNum, 4, 8, BUBBLE_FLAG_CLUMP, 0, 0, 0);
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-09-30 14:45:46 -05:00
|
|
|
|
2019-11-27 15:12:35 +01:00
|
|
|
for (lp = 0; lp < 2; lp++)
|
|
|
|
{
|
|
|
|
GAME_VECTOR source, target;
|
2021-12-08 15:27:46 +11:00
|
|
|
long r;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
|
|
|
r = 31 - (GetRandomControl() & 3);
|
2022-02-28 21:02:19 +11:00
|
|
|
pos = { UPVBites[SUB_FRONT_LIGHT].x, UPVBites[SUB_FRONT_LIGHT].y, UPVBites[SUB_FRONT_LIGHT].z << (lp * 6) };
|
|
|
|
GetJointAbsPosition(UPVItem, &pos, UPVBites[SUB_FRONT_LIGHT].meshNum);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-03-24 12:49:36 -05:00
|
|
|
if (lp == 1)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
target.x = pos.x;
|
|
|
|
target.y = pos.y;
|
|
|
|
target.z = pos.z;
|
2022-02-09 16:55:46 +11:00
|
|
|
target.roomNumber = UPVItem->RoomNumber;
|
2019-11-27 15:12:35 +01:00
|
|
|
LOS(&source, &target);
|
2021-12-08 15:27:46 +11:00
|
|
|
pos = { target.x, target.y, target.z };
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
source.x = pos.x;
|
|
|
|
source.y = pos.y;
|
|
|
|
source.z = pos.z;
|
2022-02-09 16:55:46 +11:00
|
|
|
source.roomNumber = UPVItem->RoomNumber;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
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);
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
2021-03-24 12:49:36 -05:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (UPV->WeaponTimer)
|
|
|
|
UPV->WeaponTimer--;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
static bool TestUPVDismount(ITEM_INFO* laraItem, ITEM_INFO* UPVItem)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
auto* lara = GetLaraInfo(laraItem);
|
2021-12-08 15:27:46 +11:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (lara->ExtraVelocity.x || lara->ExtraVelocity.z)
|
2021-12-08 15:27:46 +11:00
|
|
|
return false;
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
short moveAngle = UPVItem->Position.yRot + ANGLE(180.0f);
|
|
|
|
int speed = GETOFF_DIST * phd_cos(UPVItem->Position.xRot);
|
|
|
|
int x = UPVItem->Position.xPos + speed * phd_sin(moveAngle);
|
|
|
|
int z = UPVItem->Position.zPos + speed * phd_cos(moveAngle);
|
|
|
|
int y = UPVItem->Position.yPos - GETOFF_DIST * phd_sin(-UPVItem->Position.xRot);
|
|
|
|
auto probe = GetCollisionResult(x, y, z, UPVItem->RoomNumber);
|
2021-12-08 15:27:46 +11:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
return true;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
static bool TestUPVMount(ITEM_INFO* laraItem, ITEM_INFO* UPVItem)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
auto* lara = GetLaraInfo(laraItem);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
if (!(TrInput & IN_ACTION) ||
|
2022-02-28 21:02:19 +11:00
|
|
|
lara->Control.HandStatus != HandStatus::Free ||
|
2022-02-09 13:20:57 +11:00
|
|
|
laraItem->Airborne)
|
2021-12-08 15:27:46 +11:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2020-10-30 00:00:41 -05:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
int y = abs(laraItem->Position.yPos - (UPVItem->Position.yPos - STEP_SIZE / 2));
|
|
|
|
int dist = pow(laraItem->Position.xPos - UPVItem->Position.xPos, 2) + pow(laraItem->Position.zPos - UPVItem->Position.zPos, 2);
|
|
|
|
short rotDelta = abs(laraItem->Position.yRot - UPVItem->Position.yRot);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
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;
|
|
|
|
}
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
return true;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2020-05-27 09:21:20 +02:00
|
|
|
static void DoCurrent(ITEM_INFO* item)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
PHD_VECTOR target;
|
|
|
|
|
2022-02-11 19:26:08 +11:00
|
|
|
if (!Lara.Control.WaterCurrentActive)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
long shifter, absvel;
|
|
|
|
|
2022-02-15 21:25:24 +11:00
|
|
|
absvel = abs(Lara.ExtraVelocity.x);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
|
|
|
if (absvel > 16)
|
|
|
|
shifter = 4;
|
|
|
|
else if (absvel > 8)
|
|
|
|
shifter = 3;
|
|
|
|
else
|
|
|
|
shifter = 2;
|
|
|
|
|
2022-02-15 21:25:24 +11:00
|
|
|
Lara.ExtraVelocity.x -= Lara.ExtraVelocity.x >> shifter;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-15 21:25:24 +11:00
|
|
|
if (abs(Lara.ExtraVelocity.x) < 4)
|
|
|
|
Lara.ExtraVelocity.x = 0;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-15 21:25:24 +11:00
|
|
|
absvel = abs(Lara.ExtraVelocity.z);
|
2019-11-27 15:12:35 +01:00
|
|
|
if (absvel > 16)
|
|
|
|
shifter = 4;
|
|
|
|
else if (absvel > 8)
|
|
|
|
shifter = 3;
|
|
|
|
else
|
|
|
|
shifter = 2;
|
|
|
|
|
2022-02-15 21:25:24 +11:00
|
|
|
Lara.ExtraVelocity.z -= Lara.ExtraVelocity.z >> shifter;
|
|
|
|
if (abs(Lara.ExtraVelocity.z) < 4)
|
|
|
|
Lara.ExtraVelocity.z = 0;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-15 21:25:24 +11:00
|
|
|
if (Lara.ExtraVelocity.x == 0 && Lara.ExtraVelocity.z == 0)
|
2019-11-27 15:12:35 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
long angle, dx, dz, speed, sinkval;
|
|
|
|
|
2022-02-11 19:26:08 +11:00
|
|
|
sinkval = Lara.Control.WaterCurrentActive - 1;
|
2021-07-10 06:55:37 +02:00
|
|
|
target.x = g_Level.Sinks[sinkval].x;
|
|
|
|
target.y = g_Level.Sinks[sinkval].y;
|
|
|
|
target.z = g_Level.Sinks[sinkval].z;
|
2022-02-09 16:55:46 +11:00
|
|
|
angle = ((mGetAngle(target.x, target.z, LaraItem->Position.xPos, LaraItem->Position.zPos) - ANGLE(90)) / 16) & 4095;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
dx = target.x - LaraItem->Position.xPos;
|
|
|
|
dz = target.z - LaraItem->Position.zPos;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-07-10 06:55:37 +02:00
|
|
|
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;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-15 21:25:24 +11:00
|
|
|
Lara.ExtraVelocity.x += ((dx - Lara.ExtraVelocity.x) / 16);
|
|
|
|
Lara.ExtraVelocity.z += ((dz - Lara.ExtraVelocity.z) / 16);
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2022-02-15 21:25:24 +11:00
|
|
|
item->Position.xPos += (Lara.ExtraVelocity.x / 256);
|
|
|
|
item->Position.zPos += (Lara.ExtraVelocity.z / 256);
|
2022-02-11 19:26:08 +11:00
|
|
|
Lara.Control.WaterCurrentActive = 0;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
static void BackgroundCollision(ITEM_INFO* laraItem, ITEM_INFO* UPVItem)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
auto* lara = GetLaraInfo(laraItem);
|
|
|
|
UPVInfo* UPV = UPVItem->Data;
|
2021-12-08 15:27:46 +11:00
|
|
|
COLL_INFO cinfo, * coll = &cinfo; // ??
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-01-30 14:43:33 +11:00
|
|
|
coll->Setup.LowerFloorBound = NO_LOWER_BOUND;
|
|
|
|
coll->Setup.UpperFloorBound = -SUB_HEIGHT;
|
|
|
|
coll->Setup.LowerCeilingBound = SUB_HEIGHT;
|
2022-02-09 16:55:46 +11:00
|
|
|
coll->Setup.OldPosition.x = UPVItem->Position.xPos;
|
|
|
|
coll->Setup.OldPosition.y = UPVItem->Position.yPos;
|
|
|
|
coll->Setup.OldPosition.z = UPVItem->Position.zPos;
|
2021-09-10 00:20:59 +03:00
|
|
|
coll->Setup.Radius = SUB_RADIUS;
|
2022-01-30 14:43:33 +11:00
|
|
|
coll->Setup.FloorSlopeIsWall = false;
|
|
|
|
coll->Setup.FloorSlopeIsPit = false;
|
2021-09-13 09:55:54 +03:00
|
|
|
coll->Setup.DeathFlagIsPit = false;
|
2022-01-30 14:43:33 +11:00
|
|
|
coll->Setup.EnableSpasm = false;
|
2021-09-10 00:20:59 +03:00
|
|
|
coll->Setup.EnableObjectPush = true;
|
2022-02-13 15:58:12 +11:00
|
|
|
coll->Setup.Mode = CollProbeMode::Quadrants;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
if ((UPVItem->Position.xRot >= -16384) && (UPVItem->Position.xRot <= 16384))
|
2022-02-28 21:02:19 +11:00
|
|
|
coll->Setup.ForwardAngle = lara->Control.MoveAngle = UPVItem->Position.yRot;
|
2019-11-27 15:12:35 +01:00
|
|
|
else
|
2022-02-28 21:02:19 +11:00
|
|
|
coll->Setup.ForwardAngle = lara->Control.MoveAngle = UPVItem->Position.yRot - ANGLE(180.0f);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
int height = phd_sin(UPVItem->Position.xRot) * SUB_LENGTH;
|
2019-11-27 15:12:35 +01:00
|
|
|
if (height < 0)
|
|
|
|
height = -height;
|
|
|
|
if (height < 200)
|
|
|
|
height = 200;
|
|
|
|
|
2022-01-30 14:43:33 +11:00
|
|
|
coll->Setup.UpperFloorBound = -height;
|
2021-09-19 06:42:24 +03:00
|
|
|
coll->Setup.Height = height;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
GetCollisionInfo(coll, UPVItem, PHD_VECTOR(0, height / 2, 0));
|
|
|
|
ShiftItem(UPVItem, coll);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-09-10 00:18:47 +03:00
|
|
|
if (coll->CollisionType == CT_FRONT)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
if (UPV->RotX > FRONT_TOLERANCE)
|
|
|
|
UPV->RotX += WALLDEFLECT;
|
|
|
|
else if (UPV->RotX < -FRONT_TOLERANCE)
|
|
|
|
UPV->RotX -= WALLDEFLECT;
|
2019-11-27 15:12:35 +01:00
|
|
|
else
|
2020-10-26 13:04:58 -05:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
if (abs(UPV->Vel) >= MAX_VELOCITY)
|
2020-10-26 13:04:58 -05:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
laraItem->TargetState = UPV_STATE_HIT;
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Vel = -UPV->Vel / 2;
|
2020-10-26 13:04:58 -05:00
|
|
|
}
|
|
|
|
else
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Vel = 0;
|
2020-10-26 13:04:58 -05:00
|
|
|
}
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
2021-09-10 00:18:47 +03:00
|
|
|
else if (coll->CollisionType == CT_TOP)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
if (UPV->RotX >= -TOP_TOLERANCE)
|
|
|
|
UPV->RotX -= WALLDEFLECT;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
2021-09-10 00:18:47 +03:00
|
|
|
else if (coll->CollisionType == CT_TOP_FRONT)
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Vel = 0;
|
2021-09-10 00:18:47 +03:00
|
|
|
else if (coll->CollisionType == CT_LEFT)
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.yRot += ANGLE(5.0f);
|
2021-09-10 00:18:47 +03:00
|
|
|
else if (coll->CollisionType == CT_RIGHT)
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.yRot -= ANGLE(5.0f);
|
2021-09-10 00:18:47 +03:00
|
|
|
else if (coll->CollisionType == CT_CLAMP)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.xPos = coll->Setup.OldPosition.x;
|
|
|
|
UPVItem->Position.yPos = coll->Setup.OldPosition.y;
|
|
|
|
UPVItem->Position.zPos = coll->Setup.OldPosition.z;
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Vel = 0;
|
2019-11-27 15:12:35 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-09-10 00:18:47 +03:00
|
|
|
if (coll->Middle.Floor < 0)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.yPos += coll->Middle.Floor;
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->RotX += WALLDEFLECT;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
static void UserInput(ITEM_INFO* laraItem, ITEM_INFO* UPVItem)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
auto* lara = GetLaraInfo(laraItem);
|
|
|
|
UPVInfo* UPV = UPVItem->Data;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
TestUPVDismount(laraItem, UPVItem);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
int anim = laraItem->AnimNumber - Objects[ID_UPV_LARA_ANIMS].animIndex;
|
|
|
|
int frame = laraItem->FrameNumber - g_Level.Anims[laraItem->AnimNumber].frameBase;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
switch (laraItem->ActiveState)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2021-12-08 15:27:46 +11:00
|
|
|
case UPV_STATE_MOVE:
|
2022-02-09 16:55:46 +11:00
|
|
|
if (laraItem->HitPoints <= 0)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
laraItem->TargetState = UPV_STATE_DEATH;
|
2019-11-27 15:12:35 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
if (TrInput & UPV_IN_LEFT)
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Rot -= ROT_ACCELERATION;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
else if (TrInput & UPV_IN_RIGHT)
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Rot += ROT_ACCELERATION;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (UPV->Flags & UPV_SURFACE)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
int xa = UPVItem->Position.xRot - SURFACE_ANGLE;
|
|
|
|
int ax = SURFACE_ANGLE - UPVItem->Position.xRot;
|
2021-12-08 15:27:46 +11:00
|
|
|
|
2020-09-30 22:00:54 -05:00
|
|
|
if (xa > 0)
|
|
|
|
{
|
2021-12-08 15:27:46 +11:00
|
|
|
if (xa > ANGLE(1.0f))
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.xRot -= ANGLE(1.0f);
|
2020-09-30 22:00:54 -05:00
|
|
|
else
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.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))
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.xRot += ANGLE(1.0f);
|
2020-09-30 22:00:54 -05:00
|
|
|
else
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.xRot += ANGLE(0.1f);
|
2020-09-30 22:00:54 -05:00
|
|
|
}
|
|
|
|
else
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.xRot = SURFACE_ANGLE;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-08 15:27:46 +11:00
|
|
|
if (TrInput & UPV_IN_UP)
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->RotX -= UPDOWN_ACCEL;
|
2021-12-08 15:27:46 +11:00
|
|
|
else if (TrInput & UPV_IN_DOWN)
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->RotX += UPDOWN_ACCEL;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
if (TrInput & UPV_IN_PROPEL)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2021-12-08 15:27:46 +11:00
|
|
|
if (TrInput & UPV_IN_UP &&
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Flags & UPV_SURFACE &&
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.xRot > -DIVE_ANGLE)
|
2021-12-08 15:27:46 +11:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Flags |= UPV_DIVE;
|
2021-12-08 15:27:46 +11:00
|
|
|
}
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Vel += ACCELERATION;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
else
|
2022-02-09 16:55:46 +11:00
|
|
|
laraItem->TargetState = UPV_STATE_IDLE;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
|
|
|
break;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
case UPV_STATE_IDLE:
|
2022-02-09 16:55:46 +11:00
|
|
|
if (laraItem->HitPoints <= 0)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
laraItem->TargetState = UPV_STATE_DEATH;
|
2019-11-27 15:12:35 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
if (TrInput & UPV_IN_LEFT)
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Rot -= ROT_SLOWACCEL;
|
2021-12-08 15:27:46 +11:00
|
|
|
else if (TrInput & UPV_IN_RIGHT)
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Rot += ROT_SLOWACCEL;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (UPV->Flags & UPV_SURFACE)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
int xa = UPVItem->Position.xRot - SURFACE_ANGLE;
|
|
|
|
int ax = SURFACE_ANGLE - UPVItem->Position.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))
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.xRot -= ANGLE(1.0f);
|
2020-09-30 22:00:54 -05:00
|
|
|
else
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.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))
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.xRot += ANGLE(1.0f);
|
2020-09-30 22:00:54 -05:00
|
|
|
else
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.xRot += ANGLE(0.1f);
|
2020-09-30 22:00:54 -05:00
|
|
|
}
|
|
|
|
else
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.xRot = SURFACE_ANGLE;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-08 15:27:46 +11:00
|
|
|
if (TrInput & UPV_IN_UP)
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->RotX -= UPDOWN_ACCEL;
|
2021-12-08 15:27:46 +11:00
|
|
|
else if (TrInput & UPV_IN_DOWN)
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->RotX += UPDOWN_ACCEL;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
if (TrInput & UPV_IN_DISMOUNT && TestUPVDismount(laraItem, UPVItem))
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
if (UPV->Vel > 0)
|
|
|
|
UPV->Vel -= ACCELERATION;
|
2020-10-19 15:06:51 -05:00
|
|
|
else
|
2020-09-28 15:21:19 -05:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
if (UPV->Flags & UPV_SURFACE)
|
2022-02-09 16:55:46 +11:00
|
|
|
laraItem->TargetState = UPV_STATE_DISMOUNT_SURFACE;
|
2020-09-28 15:21:19 -05:00
|
|
|
else
|
2022-02-09 16:55:46 +11:00
|
|
|
laraItem->TargetState = 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);
|
2022-02-09 16:55:46 +11:00
|
|
|
SoundEffect(SFX_TR3_LITTLE_SUB_STOP, (PHD_3DPOS*)&UPVItem->Position.xPos, 2);
|
2020-09-28 15:21:19 -05:00
|
|
|
}
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
else if (TrInput & UPV_IN_PROPEL)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2021-12-08 15:27:46 +11:00
|
|
|
if (TrInput & UPV_IN_UP &&
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Flags & UPV_SURFACE &&
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.xRot > -DIVE_ANGLE)
|
2021-12-08 15:27:46 +11:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Flags |= UPV_DIVE;
|
2021-12-08 15:27:46 +11:00
|
|
|
}
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
laraItem->TargetState = UPV_STATE_MOVE;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
case UPV_STATE_MOUNT:
|
|
|
|
if (anim == UPV_ANIM_MOUNT_SURFACE_END)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.yPos += 4;
|
|
|
|
UPVItem->Position.xRot += ANGLE(1.0f);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
if (frame == MOUNT_SURFACE_SOUND_FRAME)
|
2022-02-09 16:55:46 +11:00
|
|
|
SoundEffect(SFX_TR3_LITTLE_SUB_LOOP, (PHD_3DPOS*)&UPVItem->Position.xPos, 2);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
if (frame == MOUNT_SURFACE_CONTROL_FRAME)
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Flags |= UPV_CONTROL;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
else if (anim == UPV_ANIM_MOUNT_UNDERWATER)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2021-12-08 15:27:46 +11:00
|
|
|
if (frame == MOUNT_UNDERWATER_SOUND_FRAME)
|
2022-02-09 16:55:46 +11:00
|
|
|
SoundEffect(SFX_TR3_LITTLE_SUB_LOOP, (PHD_3DPOS*)&UPVItem->Position.xPos, 2);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
if (frame == MOUNT_UNDERWATER_CONTROL_FRAME)
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Flags |= UPV_CONTROL;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
case UPV_STATE_DISMOUNT_UNDERWATER:
|
|
|
|
if (anim == UPV_ANIM_DISMOUNT_UNDERWATER && frame == DISMOUNT_UNDERWATER_FRAME)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Flags &= ~UPV_CONTROL;
|
2019-11-27 15:12:35 +01:00
|
|
|
PHD_VECTOR vec = { 0, 0, 0 };
|
|
|
|
GAME_VECTOR VPos, LPos;
|
|
|
|
|
2019-12-15 16:19:01 +01:00
|
|
|
GetLaraJointPosition(&vec, LM_HIPS);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
|
|
|
LPos.x = vec.x;
|
|
|
|
LPos.y = vec.y;
|
|
|
|
LPos.z = vec.z;
|
2022-02-09 16:55:46 +11:00
|
|
|
LPos.roomNumber = UPVItem->RoomNumber;
|
|
|
|
VPos.x = UPVItem->Position.xPos;
|
|
|
|
VPos.y = UPVItem->Position.yPos;
|
|
|
|
VPos.z = UPVItem->Position.zPos;
|
|
|
|
VPos.roomNumber = UPVItem->RoomNumber;
|
2021-12-01 18:12:04 +03:00
|
|
|
LOSAndReturnTarget(&VPos, &LPos, 0);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
laraItem->Position.xPos = LPos.x;
|
|
|
|
laraItem->Position.yPos = LPos.y;
|
|
|
|
laraItem->Position.zPos = LPos.z;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
SetAnimation(laraItem, LA_UNDERWATER_IDLE);
|
2022-02-09 13:20:57 +11:00
|
|
|
laraItem->VerticalVelocity = 0;
|
|
|
|
laraItem->Airborne = false;
|
2022-02-09 16:55:46 +11:00
|
|
|
laraItem->Position.xRot = laraItem->Position.zRot = 0;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
UpdateItemRoom(laraItem, 0);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
lara->Control.WaterStatus = WaterStatus::Underwater;
|
|
|
|
lara->Control.HandStatus = HandStatus::Free;
|
|
|
|
lara->Vehicle = NO_ITEM;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->HitPoints = 0;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
case UPV_STATE_DISMOUNT_SURFACE:
|
|
|
|
if (anim == UPV_ANIM_DISMOUNT_SURFACE && frame == DISMOUNT_SURFACE_FRAME)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Flags &= ~UPV_CONTROL;
|
2021-12-08 15:27:46 +11:00
|
|
|
int waterDepth, waterHeight, heightFromWater;
|
2019-11-27 15:12:35 +01:00
|
|
|
PHD_VECTOR vec = { 0, 0, 0 };
|
|
|
|
|
2022-02-01 21:46:58 +11:00
|
|
|
waterDepth = GetWaterSurface(laraItem);
|
|
|
|
waterHeight = GetWaterHeight(laraItem);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
if (waterHeight != NO_HEIGHT)
|
2022-02-09 16:55:46 +11:00
|
|
|
heightFromWater = laraItem->Position.yPos - waterHeight;
|
2019-11-27 15:12:35 +01:00
|
|
|
else
|
2021-12-08 15:27:46 +11:00
|
|
|
heightFromWater = NO_HEIGHT;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2019-12-15 16:19:01 +01:00
|
|
|
GetLaraJointPosition(&vec, LM_HIPS);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
laraItem->Position.xPos = vec.x;
|
2021-12-08 22:02:02 +11:00
|
|
|
//laraItem->pos.yPos += -heightFromWater + 1; // Doesn't work as intended.
|
2022-02-09 16:55:46 +11:00
|
|
|
laraItem->Position.yPos = vec.y;
|
|
|
|
laraItem->Position.zPos = vec.z;
|
2021-12-08 15:27:46 +11:00
|
|
|
|
2021-12-08 22:02:02 +11:00
|
|
|
SetAnimation(laraItem, LA_ONWATER_IDLE);
|
2022-02-09 13:20:57 +11:00
|
|
|
laraItem->VerticalVelocity = 0;
|
|
|
|
laraItem->Airborne = false;
|
2022-02-09 16:55:46 +11:00
|
|
|
laraItem->Position.xRot = laraItem->Position.zRot = 0;
|
2021-12-08 15:27:46 +11:00
|
|
|
|
|
|
|
UpdateItemRoom(laraItem, -LARA_HEIGHT / 2);
|
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
lara->Control.WaterStatus = WaterStatus::TreadWater;
|
|
|
|
lara->WaterSurfaceDist = -heightFromWater;
|
|
|
|
lara->Control.Count.Dive = 11;
|
2022-02-08 20:45:21 +11:00
|
|
|
ResetLaraFlex(laraItem);
|
2022-02-28 21:02:19 +11:00
|
|
|
lara->Control.HandStatus = HandStatus::Free;
|
|
|
|
lara->Vehicle = NO_ITEM;
|
2021-12-08 15:27:46 +11:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->HitPoints = 0;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
2021-12-08 22:02:02 +11:00
|
|
|
else
|
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->RotX -= UPDOWN_ACCEL;
|
2022-02-09 16:55:46 +11:00
|
|
|
if (UPVItem->Position.xRot < 0)
|
|
|
|
UPVItem->Position.xRot = 0;
|
2021-12-08 22:02:02 +11:00
|
|
|
}
|
2019-11-27 15:12:35 +01:00
|
|
|
|
|
|
|
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))
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
PHD_VECTOR vec = { 0, 0, 0 };
|
|
|
|
|
2019-12-15 16:19:01 +01:00
|
|
|
GetLaraJointPosition(&vec, LM_HIPS);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
laraItem->Position.xPos = vec.x;
|
|
|
|
laraItem->Position.yPos = vec.y;
|
|
|
|
laraItem->Position.zPos = vec.z;
|
|
|
|
laraItem->Position.xRot = 0;
|
|
|
|
laraItem->Position.zRot = 0;
|
2021-12-08 15:27:46 +11:00
|
|
|
|
|
|
|
SetAnimation(UPVItem, LA_UNDERWATER_DEATH, 17);
|
2022-02-09 13:20:57 +11:00
|
|
|
laraItem->VerticalVelocity = 0;
|
|
|
|
laraItem->Airborne = 0;
|
2021-12-08 15:27:46 +11:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Flags |= UPV_DEAD;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2022-02-09 13:20:57 +11:00
|
|
|
UPVItem->VerticalVelocity = 0;
|
2019-11-27 15:12:35 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (UPV->Flags & UPV_DIVE)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
if (UPVItem->Position.xRot > -DIVE_ANGLE)
|
|
|
|
UPVItem->Position.xRot -= DIVE_SPEED;
|
2019-11-27 15:12:35 +01:00
|
|
|
else
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Flags &= ~UPV_DIVE;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (UPV->Vel > 0)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Vel -= FRICTION;
|
|
|
|
if (UPV->Vel < 0)
|
|
|
|
UPV->Vel = 0;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
2022-02-28 21:02:19 +11:00
|
|
|
else if (UPV->Vel < 0)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Vel += FRICTION;
|
|
|
|
if (UPV->Vel > 0)
|
|
|
|
UPV->Vel = 0;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (UPV->Vel > MAX_VELOCITY)
|
|
|
|
UPV->Vel = MAX_VELOCITY;
|
|
|
|
else if (UPV->Vel < -MAX_VELOCITY)
|
|
|
|
UPV->Vel = -MAX_VELOCITY;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (UPV->Rot > 0)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Rot -= ROT_FRICTION;
|
|
|
|
if (UPV->Rot < 0)
|
|
|
|
UPV->Rot = 0;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
2022-02-28 21:02:19 +11:00
|
|
|
else if (UPV->Rot < 0)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Rot += ROT_FRICTION;
|
|
|
|
if (UPV->Rot > 0)
|
|
|
|
UPV->Rot = 0;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (UPV->RotX > 0)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->RotX -= UPDOWN_FRICTION;
|
|
|
|
if (UPV->RotX < 0)
|
|
|
|
UPV->RotX = 0;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
2022-02-28 21:02:19 +11:00
|
|
|
else if (UPV->RotX < 0)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->RotX += UPDOWN_FRICTION;
|
|
|
|
if (UPV->RotX > 0)
|
|
|
|
UPV->RotX = 0;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (UPV->Rot > MAX_ROTATION)
|
|
|
|
UPV->Rot = MAX_ROTATION;
|
|
|
|
else if (UPV->Rot < -MAX_ROTATION)
|
|
|
|
UPV->Rot = -MAX_ROTATION;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (UPV->RotX > MAX_UPDOWN)
|
|
|
|
UPV->RotX = MAX_UPDOWN;
|
|
|
|
else if (UPV->RotX < -MAX_UPDOWN)
|
|
|
|
UPV->RotX = -MAX_UPDOWN;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
void NoGetOnCollision(short itemNum, ITEM_INFO* laraitem, COLL_INFO* coll)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2021-12-08 15:27:46 +11:00
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNum];
|
2019-11-27 15:12:35 +01:00
|
|
|
|
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
|
|
|
|
2021-09-02 11:32:08 +03: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)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
auto* lara = GetLaraInfo(laraItem);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (laraItem->HitPoints <= 0 || lara->Vehicle != NO_ITEM)
|
2019-11-27 15:12:35 +01:00
|
|
|
return;
|
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
ITEM_INFO* UPVItem = &g_Level.Items[itemNum];
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
if (TestUPVMount(laraItem, UPVItem))
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
lara->Vehicle = itemNum;
|
|
|
|
lara->Control.WaterStatus = WaterStatus::Dry;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (lara->Control.WeaponControl.GunType == WEAPON_FLARE)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2021-11-12 19:52:48 +11:00
|
|
|
CreateFlare(LaraItem, ID_FLARE_ITEM, 0);
|
2021-12-09 00:48:55 +11:00
|
|
|
UndrawFlareMeshes(laraItem);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
lara->Flare.ControlLeft = false;
|
|
|
|
lara->Control.WeaponControl.RequestGunType = lara->Control.WeaponControl.GunType = WEAPON_NONE;
|
2021-12-08 15:27:46 +11:00
|
|
|
}
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
lara->Control.HandStatus = HandStatus::Busy;
|
2022-02-09 16:55:46 +11:00
|
|
|
laraItem->Position.xPos = UPVItem->Position.xPos;
|
|
|
|
laraItem->Position.yPos = UPVItem->Position.yPos;
|
|
|
|
laraItem->Position.zPos = UPVItem->Position.zPos;
|
|
|
|
laraItem->Position.xRot = UPVItem->Position.xRot;
|
|
|
|
laraItem->Position.yRot = UPVItem->Position.yRot;
|
|
|
|
laraItem->Position.zRot = UPVItem->Position.zRot;
|
|
|
|
UPVItem->HitPoints = 1;
|
|
|
|
|
|
|
|
if (laraItem->ActiveState == LS_ONWATER_STOP || laraItem->ActiveState == LS_ONWATER_FORWARD)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
laraItem->AnimNumber = Objects[ID_UPV_LARA_ANIMS].animIndex + UPV_ANIM_MOUNT_SURFACE_START;
|
|
|
|
laraItem->ActiveState = laraItem->TargetState = UPV_STATE_MOUNT;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
laraItem->AnimNumber = Objects[ID_UPV_LARA_ANIMS].animIndex + UPV_ANIM_MOUNT_UNDERWATER;
|
|
|
|
laraItem->ActiveState = laraItem->TargetState = UPV_STATE_MOUNT;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
2022-02-09 16:55:46 +11:00
|
|
|
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
AnimateItem(laraItem);
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.yPos += SUB_DRAW_SHIFT;
|
2021-12-08 15:27:46 +11:00
|
|
|
NoGetOnCollision(itemNum, laraItem, coll);
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.yPos -= SUB_DRAW_SHIFT;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
bool SubControl(ITEM_INFO* laraItem, COLL_INFO* coll)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
auto* lara = GetLaraInfo(laraItem);
|
|
|
|
ITEM_INFO* UPVItem = &g_Level.Items[lara->Vehicle];
|
|
|
|
UPVInfo* UPV = UPVItem->Data;
|
2021-12-19 03:54:13 +03:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
auto oldPos = UPVItem->Position;
|
2021-12-08 15:27:46 +11:00
|
|
|
auto probe = GetCollisionResult(UPVItem);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (!(UPV->Flags & UPV_DEAD))
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2021-12-08 15:27:46 +11:00
|
|
|
UserInput(laraItem, UPVItem);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
UPVItem->VerticalVelocity = UPV->Vel / 65536;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
UPVItem->Position.xRot += UPV->RotX / 65536;
|
|
|
|
UPVItem->Position.yRot += UPV->Rot / 65536;
|
|
|
|
UPVItem->Position.zRot = UPV->Rot / 65536;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
if (UPVItem->Position.xRot > UPDOWN_LIMIT)
|
|
|
|
UPVItem->Position.xRot = UPDOWN_LIMIT;
|
|
|
|
else if (UPVItem->Position.xRot < -UPDOWN_LIMIT)
|
|
|
|
UPVItem->Position.xRot = -UPDOWN_LIMIT;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.xPos += phd_sin(UPVItem->Position.yRot) * UPVItem->VerticalVelocity * phd_cos(UPVItem->Position.xRot);
|
|
|
|
UPVItem->Position.yPos -= phd_sin(UPVItem->Position.xRot) * UPVItem->VerticalVelocity;
|
|
|
|
UPVItem->Position.zPos += phd_cos(UPVItem->Position.yRot) * UPVItem->VerticalVelocity * phd_cos(UPVItem->Position.xRot);
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2021-12-19 03:54:13 +03:00
|
|
|
int newHeight = GetCollisionResult(UPVItem).Position.Floor;
|
2022-02-01 21:46:58 +11:00
|
|
|
int waterHeight = GetWaterHeight(UPVItem);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
if ((newHeight - waterHeight) < SUB_HEIGHT || (newHeight < UPVItem->Position.yPos - SUB_HEIGHT / 2))
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.xPos = oldPos.xPos;
|
|
|
|
UPVItem->Position.yPos = oldPos.yPos;
|
|
|
|
UPVItem->Position.zPos = oldPos.zPos;
|
2022-02-09 13:20:57 +11:00
|
|
|
UPVItem->VerticalVelocity = 0;
|
2021-12-19 03:54:13 +03:00
|
|
|
}
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Floor = probe.Position.Floor;
|
2021-12-19 03:54:13 +03:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (UPV->Flags & UPV_CONTROL && !(UPV->Flags & UPV_DEAD))
|
2021-12-19 03:54:13 +03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
if (!(g_Level.Rooms[UPVItem->RoomNumber].flags & ENV_FLAG_WATER) &&
|
2021-12-08 15:27:46 +11:00
|
|
|
waterHeight != NO_HEIGHT)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
if ((waterHeight - UPVItem->Position.yPos) >= -SURFACE_DIST)
|
|
|
|
UPVItem->Position.yPos = waterHeight + SURFACE_DIST;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (!(UPV->Flags & UPV_SURFACE))
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
SoundEffect(SFX_TR4_LARA_BREATH, &LaraItem->Position, 2);
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Flags &= ~UPV_DIVE;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Flags |= UPV_SURFACE;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
else if ((waterHeight - UPVItem->Position.yPos) >= -SURFACE_DIST && waterHeight != NO_HEIGHT)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
UPVItem->Position.yPos = waterHeight + SURFACE_DIST;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (!(UPV->Flags & UPV_SURFACE))
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
SoundEffect(SFX_TR4_LARA_BREATH, &LaraItem->Position, 2);
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Flags &= ~UPV_DIVE;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Flags |= UPV_SURFACE;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
else
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Flags &= ~UPV_SURFACE;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (!(UPV->Flags & UPV_SURFACE))
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
if (laraItem->HitPoints > 0)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
lara->Air--;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (lara->Air < 0)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
lara->Air = -1;
|
2022-02-09 16:55:46 +11:00
|
|
|
laraItem->HitPoints -= 5;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
if (laraItem->HitPoints >= 0)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
lara->Air += 10;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (lara->Air > 1800)
|
|
|
|
lara->Air = 1800;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
TestTriggers(UPVItem, false);
|
2022-02-28 21:02:19 +11:00
|
|
|
SubEffects(lara->Vehicle);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (!(UPV->Flags & UPV_DEAD) &&
|
|
|
|
lara->Vehicle != NO_ITEM)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2021-12-08 15:27:46 +11:00
|
|
|
DoCurrent(UPVItem);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
if (TrInput & UPV_IN_FIRE &&
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->Flags & UPV_CONTROL &&
|
|
|
|
!UPV->WeaponTimer)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
if (laraItem->ActiveState != UPV_STATE_DISMOUNT_UNDERWATER &&
|
|
|
|
laraItem->ActiveState != UPV_STATE_DISMOUNT_SURFACE &&
|
|
|
|
laraItem->ActiveState != UPV_STATE_MOUNT)
|
2021-12-08 15:27:46 +11:00
|
|
|
{
|
|
|
|
FireSubHarpoon(laraItem, UPVItem);
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->WeaponTimer = HARPOON_RELOAD;
|
2021-12-08 15:27:46 +11:00
|
|
|
}
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
if (probe.RoomNumber != UPVItem->RoomNumber)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2022-02-28 21:02:19 +11:00
|
|
|
ItemNewRoom(lara->Vehicle, probe.RoomNumber);
|
|
|
|
ItemNewRoom(lara->ItemNumber, probe.RoomNumber);
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
laraItem->Position.xPos = UPVItem->Position.xPos;
|
|
|
|
laraItem->Position.yPos = UPVItem->Position.yPos;
|
|
|
|
laraItem->Position.zPos = UPVItem->Position.zPos;
|
|
|
|
laraItem->Position.xRot = UPVItem->Position.xRot;
|
|
|
|
laraItem->Position.yRot = UPVItem->Position.yRot;
|
|
|
|
laraItem->Position.zRot = UPVItem->Position.zRot;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
AnimateItem(laraItem);
|
|
|
|
BackgroundCollision(laraItem, UPVItem);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (UPV->Flags & UPV_CONTROL)
|
2022-02-09 16:55:46 +11:00
|
|
|
SoundEffect(SFX_TR3_LITTLE_SUB_LOOP, (PHD_3DPOS*)&UPVItem->Position.xPos, 2 | 4 | 0x1000000 | (UPVItem->VerticalVelocity * 65536));
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-09 16:55: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);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
if (UPV->Flags & UPV_SURFACE)
|
2021-12-08 15:27:46 +11:00
|
|
|
Camera.targetElevation = -ANGLE(60.0f);
|
2019-11-27 15:12:35 +01:00
|
|
|
else
|
|
|
|
Camera.targetElevation = 0;
|
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
return true;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
2022-02-28 21:02:19 +11:00
|
|
|
else if (UPV->Flags & UPV_DEAD)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
2021-12-08 15:27:46 +11:00
|
|
|
AnimateItem(laraItem);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
if (probe.RoomNumber != UPVItem->RoomNumber)
|
2022-02-28 21:02:19 +11:00
|
|
|
ItemNewRoom(lara->Vehicle, probe.RoomNumber);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
BackgroundCollision(laraItem, UPVItem);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2022-02-28 21:02:19 +11:00
|
|
|
UPV->RotX = 0;
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
SetAnimation(UPVItem, UPV_ANIM_IDLE);
|
2022-02-09 13:20:57 +11:00
|
|
|
UPVItem->VerticalVelocity = 0;
|
|
|
|
UPVItem->VerticalVelocity = 0;
|
|
|
|
UPVItem->Airborne = true;
|
2021-12-08 15:27:46 +11:00
|
|
|
AnimateItem(UPVItem);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
2021-12-08 15:27:46 +11:00
|
|
|
return true;
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
else
|
2021-12-08 15:27:46 +11:00
|
|
|
return false;
|
|
|
|
}
|