2019-12-05 17:35:57 +01:00
|
|
|
#include "../newobjects.h"
|
|
|
|
#include "../../Game/lara.h"
|
|
|
|
#include "../../Game/items.h"
|
|
|
|
#include "../../Game/sphere.h"
|
|
|
|
#include "../../Game/effect2.h"
|
|
|
|
#include "../../Game/effects.h"
|
|
|
|
#include "../../Game/collide.h"
|
|
|
|
#include "../../Game/box.h"
|
|
|
|
#include "../../Game/laraflar.h"
|
2019-12-13 19:00:59 +01:00
|
|
|
#include "../../Game/draw.h"
|
2019-12-22 00:20:10 +01:00
|
|
|
#include "../../Game/tomb4fx.h"
|
2019-12-15 19:07:38 +01:00
|
|
|
#include "../../Game/misc.h"
|
2019-12-28 15:19:33 -03:00
|
|
|
#include "../../Game/camera.h"
|
2019-11-27 15:12:35 +01:00
|
|
|
|
|
|
|
extern LaraExtraInfo g_LaraExtra;
|
|
|
|
|
|
|
|
enum UPV_FLAG
|
|
|
|
{
|
|
|
|
UPV_CONTROL = 1,
|
|
|
|
UPV_SURFACE = 2,
|
|
|
|
UPV_DIVE = 4,
|
|
|
|
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
|
2019-11-30 13:51:37 +01:00
|
|
|
#define UPDOWN_ACCEL (ANGLE(2) << 16)
|
2019-12-17 21:46:50 -03:00
|
|
|
#define UPDOWN_SLOWACCEL (ANGLE(1) << 16)
|
|
|
|
#define UPDOWN_FRICTION (ANGLE(1) << 16)
|
2019-11-30 13:51:37 +01:00
|
|
|
#define MAX_UPDOWN (ANGLE(2) << 16)
|
2019-11-27 15:12:35 +01:00
|
|
|
#define UPDOWN_LIMIT ANGLE(80)
|
|
|
|
#define UPDOWN_SPEED 10
|
|
|
|
#define SURFACE_DIST 210
|
|
|
|
#define SURFACE_ANGLE ANGLE(50)
|
|
|
|
#define DIVE_ANGLE ANGLE(15)
|
|
|
|
#define DIVE_SPEED ANGLE(5)
|
|
|
|
#define SUB_DRAW_SHIFT 128
|
|
|
|
#define SUB_RADIUS 300
|
|
|
|
#define SUB_HEIGHT 400
|
|
|
|
#define SUB_LENGTH WALL_SIZE
|
2019-11-30 13:51:37 +01:00
|
|
|
#define FRONT_TOLERANCE (ANGLE(45) << 16)
|
|
|
|
#define TOP_TOLERANCE (ANGLE(45) << 16)
|
|
|
|
#define WALLDEFLECT (ANGLE(2) << 16)
|
2019-11-27 15:12:35 +01:00
|
|
|
#define GETOFF_DIST WALL_SIZE
|
|
|
|
#define HARPOON_SPEED 256
|
|
|
|
#define HARPOON_TIME 256
|
|
|
|
#define HARPOON_RELOAD 15
|
|
|
|
|
|
|
|
BITE_INFO sub_bites[6] = {
|
|
|
|
{ 0, 0, 0, 3 }, // Fan.
|
|
|
|
{ 0, 96, 256, 0 }, // Front light.
|
|
|
|
{ -128, 0, -64, 1 }, // Left Fin Left.
|
|
|
|
{ 0, 0, -64, 1 }, // Left Fin right.
|
|
|
|
{ 128, 0, -64, 2 }, // Right Fin Right.
|
|
|
|
{ 0, 0, -64, 2 } // Right fin left.
|
|
|
|
};
|
|
|
|
|
|
|
|
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
|
|
|
|
};
|
|
|
|
|
|
|
|
enum UPV_STATE {
|
|
|
|
SUBS_DIE,
|
|
|
|
SUBS_HIT,
|
|
|
|
SUBS_GETOFFS,
|
|
|
|
SUBS_1,
|
|
|
|
SUBS_MOVE,
|
|
|
|
SUBS_POSE,
|
|
|
|
SUBS_2,
|
|
|
|
SUBS_3,
|
|
|
|
SUBS_GETON,
|
|
|
|
SUBS_GETOFF
|
|
|
|
};
|
|
|
|
|
2019-12-05 17:35:57 +01:00
|
|
|
static void FireSubHarpoon(ITEM_INFO* v)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
short itemNum;
|
|
|
|
|
|
|
|
itemNum = CreateItem();
|
|
|
|
if (itemNum != NO_ITEM)
|
|
|
|
{
|
|
|
|
PHD_VECTOR pos;
|
|
|
|
ITEM_INFO* item;
|
|
|
|
static char lr = 0;
|
|
|
|
|
|
|
|
item = &Items[itemNum];
|
|
|
|
|
|
|
|
item->objectNumber = ID_HARPOON;
|
|
|
|
item->shade = 0x4210 | 0x8000;
|
|
|
|
item->roomNumber = v->roomNumber;
|
|
|
|
|
|
|
|
pos.x = (lr) ? 22 : -22;
|
|
|
|
pos.y = 24;
|
|
|
|
pos.z = 230;
|
|
|
|
GetJointAbsPosition(v, &pos, 3);
|
|
|
|
|
|
|
|
item->pos.xPos = pos.x;
|
|
|
|
item->pos.yPos = pos.y;
|
|
|
|
item->pos.zPos = pos.z;
|
|
|
|
InitialiseItem(itemNum);
|
|
|
|
|
|
|
|
item->pos.xRot = v->pos.xRot;
|
|
|
|
item->pos.yRot = v->pos.yRot;
|
|
|
|
item->pos.zRot = 0;
|
|
|
|
|
|
|
|
item->fallspeed = (short)(-HARPOON_SPEED * SIN(item->pos.xRot) >> W2V_SHIFT);
|
|
|
|
item->speed = (short)(HARPOON_SPEED * COS(item->pos.xRot) >> W2V_SHIFT);
|
|
|
|
item->hitPoints = HARPOON_TIME;
|
|
|
|
item->itemFlags[0] = 1;
|
|
|
|
|
|
|
|
AddActiveItem(itemNum);
|
|
|
|
|
2020-03-02 09:49:11 +01:00
|
|
|
SoundEffect(SFX_TR3_LARA_HARPOON_FIRE_WATER, &LaraItem->pos, 2);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
|
|
|
// if lara have ammo, reduce it.
|
|
|
|
if (g_LaraExtra.Weapons[WEAPON_HARPOON_GUN].Ammo[0])
|
|
|
|
g_LaraExtra.Weapons[WEAPON_HARPOON_GUN].Ammo[0]--;
|
|
|
|
Savegame.Game.AmmoUsed++;
|
|
|
|
|
|
|
|
lr ^= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-12-02 14:49:19 +01:00
|
|
|
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;
|
|
|
|
sptr->transType = 2;
|
|
|
|
sptr->extras = 0;
|
|
|
|
sptr->dynamic = -1;
|
|
|
|
|
|
|
|
sptr->x = x + ((GetRandomControl() & 15) - 8);
|
|
|
|
sptr->y = y + ((GetRandomControl() & 15) - 8);
|
|
|
|
sptr->z = z + ((GetRandomControl() & 15) - 8);
|
|
|
|
zv = (speed * COS(angle)) >> (W2V_SHIFT + 2);
|
|
|
|
xv = (speed * SIN(angle)) >> (W2V_SHIFT + 2);
|
|
|
|
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;
|
|
|
|
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;
|
|
|
|
size = (GetRandomControl() & 7) + (speed >> 1) + 16;
|
|
|
|
sptr->size = sptr->sSize = size >> 2;
|
|
|
|
sptr->dSize = size;
|
|
|
|
}
|
|
|
|
|
2019-12-02 14:49:19 +01:00
|
|
|
void SubEffects(short item_number)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
ITEM_INFO* v;
|
|
|
|
SUB_INFO* sub;
|
|
|
|
PHD_VECTOR pos;
|
|
|
|
long lp;
|
|
|
|
|
|
|
|
v = &Items[item_number];
|
|
|
|
sub = (SUB_INFO*)v->data;
|
|
|
|
|
|
|
|
/* -------- Lara is using this vehicle */
|
|
|
|
|
|
|
|
if (g_LaraExtra.Vehicle == item_number)
|
|
|
|
{
|
|
|
|
if (!sub->Vel)
|
|
|
|
sub->FanRot += ANGLE(2);
|
|
|
|
else
|
|
|
|
sub->FanRot += sub->Vel >> 12;
|
|
|
|
|
|
|
|
if (sub->Vel)
|
|
|
|
{
|
|
|
|
pos.x = sub_bites[SUB_FAN].x;
|
|
|
|
pos.y = sub_bites[SUB_FAN].y;
|
|
|
|
pos.z = sub_bites[SUB_FAN].z;
|
|
|
|
GetJointAbsPosition(v, &pos, sub_bites[SUB_FAN].meshNum);
|
|
|
|
TriggerSubMist(pos.x, pos.y + SUB_DRAW_SHIFT, pos.z, abs(sub->Vel) >> 16, v->pos.yRot + 0x8000);
|
|
|
|
|
|
|
|
if ((GetRandomControl() & 1) == 0)
|
|
|
|
{
|
|
|
|
PHD_3DPOS pos3d;
|
|
|
|
short room_number;
|
|
|
|
|
|
|
|
pos3d.xPos = pos.x + (GetRandomControl() & 63) - 32;
|
|
|
|
pos3d.yPos = pos.y + SUB_DRAW_SHIFT;
|
|
|
|
pos3d.zPos = pos.z + (GetRandomControl() & 63) - 32;
|
|
|
|
room_number = v->roomNumber;
|
|
|
|
GetFloor(pos3d.xPos, pos3d.yPos, pos3d.zPos, &room_number);
|
2019-12-22 00:20:10 +01:00
|
|
|
CreateBubble((PHD_VECTOR*)&pos3d, room_number, 4, 8, 0, 0, 0, 0); // CHECK
|
2019-11-27 15:12:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: enable the light for UPV
|
|
|
|
|
|
|
|
/*
|
|
|
|
for (lp = 0; lp < 2; lp++)
|
|
|
|
{
|
|
|
|
GAME_VECTOR source, target;
|
|
|
|
long r;
|
|
|
|
|
|
|
|
r = 31 - (GetRandomControl() & 3);
|
|
|
|
pos.x = sub_bites[SUB_FRONT_LIGHT].x;
|
|
|
|
pos.y = sub_bites[SUB_FRONT_LIGHT].y;
|
|
|
|
pos.z = sub_bites[SUB_FRONT_LIGHT].z << (lp * 6);
|
|
|
|
GetJointAbsPosition(v, &pos, sub_bites[SUB_FRONT_LIGHT].meshNum);
|
|
|
|
|
|
|
|
if (lp == 1) // LOS light?
|
|
|
|
{
|
|
|
|
target.x = pos.x;
|
|
|
|
target.y = pos.y;
|
|
|
|
target.z = pos.z;
|
|
|
|
target.roomNumber = v->roomNumber;
|
|
|
|
LOS(&source, &target);
|
|
|
|
pos.x = target.x;
|
|
|
|
pos.y = target.y;
|
|
|
|
pos.z = target.z;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
source.x = pos.x;
|
|
|
|
source.y = pos.y;
|
|
|
|
source.z = pos.z;
|
|
|
|
source.roomNumber = v->roomNumber;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: enable the light for UPV
|
|
|
|
//TriggerDynamic(pos.x, pos.y, pos.z, 16 + (lp << 3), r, r, r);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
2019-12-05 17:35:57 +01:00
|
|
|
static int CanGetOff(ITEM_INFO* v)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
FLOOR_INFO* floor;
|
|
|
|
short room_number;
|
|
|
|
int x, y, z, height, ceiling, speed;
|
|
|
|
short yangle;
|
|
|
|
|
|
|
|
if (Lara.currentXvel || Lara.currentZvel)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
yangle = v->pos.yRot + 0x8000;
|
|
|
|
speed = (GETOFF_DIST * COS(v->pos.xRot)) >> W2V_SHIFT;
|
|
|
|
x = v->pos.xPos + (speed * SIN(yangle) >> W2V_SHIFT);
|
|
|
|
z = v->pos.zPos + (speed * COS(yangle) >> W2V_SHIFT);
|
|
|
|
y = v->pos.yPos - ((GETOFF_DIST * SIN(-v->pos.xRot)) >> W2V_SHIFT);
|
|
|
|
|
|
|
|
room_number = v->roomNumber;
|
|
|
|
floor = GetFloor(x, y, z, &room_number);
|
|
|
|
|
|
|
|
height = GetFloorHeight(floor, x, y, z);
|
|
|
|
if (height == NO_HEIGHT || y > height)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
ceiling = GetCeiling(floor, x, y, z);
|
|
|
|
if (height - ceiling < 256 || y < ceiling || ceiling == NO_HEIGHT)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-12-02 14:49:19 +01:00
|
|
|
int GetOnSub(short item_number, COLL_INFO* coll)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
/* Returns 0 if no get on, 1 if right get on and 2 if left get on */
|
|
|
|
int dist;
|
|
|
|
int x, y, z;
|
|
|
|
ITEM_INFO* v, * l;
|
|
|
|
FLOOR_INFO* floor;
|
|
|
|
short room_number, ang;
|
|
|
|
unsigned short tempang;
|
|
|
|
|
|
|
|
l = LaraItem;
|
|
|
|
v = &Items[item_number];
|
|
|
|
|
|
|
|
if ((!(TrInput & IN_ACTION)) || (Lara.gunStatus != LG_NO_ARMS) || (l->gravityStatus))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
y = abs(l->pos.yPos - (v->pos.yPos - 128));
|
|
|
|
if (y > 256)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
x = l->pos.xPos - v->pos.xPos;
|
|
|
|
z = l->pos.zPos - v->pos.zPos;
|
|
|
|
|
|
|
|
dist = (x * x) + (z * z);
|
|
|
|
if (dist > SQUARE(512))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
room_number = v->roomNumber;
|
|
|
|
floor = GetFloor(v->pos.xPos, v->pos.yPos, v->pos.zPos, &room_number);
|
|
|
|
|
|
|
|
if (GetFloorHeight(floor, v->pos.xPos, v->pos.yPos, v->pos.zPos) < -32000)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-12-02 14:49:19 +01:00
|
|
|
void DoCurrent(ITEM_INFO* item)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
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 = Camera.fixed[sinkval].x;
|
|
|
|
target.y = Camera.fixed[sinkval].y;
|
|
|
|
target.z = Camera.fixed[sinkval].z;
|
|
|
|
angle = ((mGetAngle(target.x, target.z, LaraItem->pos.xPos, LaraItem->pos.zPos) - 0x4000) >> 4) & 4095;
|
|
|
|
|
|
|
|
dx = target.x - LaraItem->pos.xPos;
|
|
|
|
dz = target.z - LaraItem->pos.zPos;
|
|
|
|
|
|
|
|
speed = Camera.fixed[sinkval].data;
|
|
|
|
dx = (((rcossin_tbl[(angle << 1)] * speed))) >> 2;
|
|
|
|
dz = (((rcossin_tbl[(angle << 1) + 1] * speed))) >> 2;
|
|
|
|
|
|
|
|
Lara.currentXvel += (dx - Lara.currentXvel) >> 4;
|
|
|
|
Lara.currentZvel += (dz - Lara.currentZvel) >> 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Move Lara in direction of sink. */
|
|
|
|
item->pos.xPos += Lara.currentXvel >> 8;
|
|
|
|
item->pos.zPos += Lara.currentZvel >> 8;
|
|
|
|
|
|
|
|
/* Reset current (will get set again so long as Lara is over triggers) */
|
|
|
|
Lara.currentActive = 0;
|
|
|
|
}
|
|
|
|
|
2019-12-02 14:49:19 +01:00
|
|
|
void BackgroundCollision(ITEM_INFO* v, ITEM_INFO* l, SUB_INFO* sub)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
int height;
|
|
|
|
COLL_INFO cinfo, *coll = &cinfo;
|
|
|
|
|
|
|
|
coll->badPos = NO_BAD_POS;
|
|
|
|
coll->badNeg = -SUB_HEIGHT;
|
|
|
|
coll->badCeiling = SUB_HEIGHT;
|
|
|
|
coll->old.x = v->pos.xPos;
|
|
|
|
coll->old.y = v->pos.yPos;
|
|
|
|
coll->old.z = v->pos.zPos;
|
|
|
|
coll->radius = SUB_RADIUS;
|
|
|
|
coll->trigger = NULL;
|
|
|
|
coll->slopesAreWalls = false;
|
|
|
|
coll->slopesArePits = false;
|
|
|
|
coll->lavaIsPit = false;
|
|
|
|
coll->enableSpaz = false;
|
|
|
|
coll->enableBaddiePush = true;
|
|
|
|
|
|
|
|
if ((v->pos.xRot >= -16384) && (v->pos.xRot <= 16384))
|
|
|
|
coll->facing = Lara.moveAngle = v->pos.yRot;
|
|
|
|
else
|
|
|
|
coll->facing = Lara.moveAngle = v->pos.yRot - 32768;
|
|
|
|
|
|
|
|
height = SIN(v->pos.xRot) * SUB_LENGTH >> W2V_SHIFT;
|
|
|
|
if (height < 0)
|
|
|
|
height = -height;
|
|
|
|
if (height < 200)
|
|
|
|
height = 200;
|
|
|
|
|
|
|
|
coll->badNeg = -height;
|
|
|
|
|
|
|
|
GetCollisionInfo(coll, v->pos.xPos, v->pos.yPos + height / 2, v->pos.zPos, v->roomNumber, height);
|
|
|
|
ShiftItem(v, coll);
|
|
|
|
|
2019-12-02 09:11:21 +01:00
|
|
|
if (coll->collType == CT_FRONT)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
if (sub->RotX > FRONT_TOLERANCE)
|
|
|
|
sub->RotX += WALLDEFLECT;
|
|
|
|
else if (sub->RotX < -FRONT_TOLERANCE)
|
|
|
|
sub->RotX -= WALLDEFLECT;
|
|
|
|
else
|
|
|
|
sub->Vel = 0;
|
|
|
|
}
|
2019-12-02 09:11:21 +01:00
|
|
|
else if (coll->collType == CT_TOP)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
if (sub->RotX >= -TOP_TOLERANCE)
|
|
|
|
sub->RotX -= WALLDEFLECT;
|
|
|
|
}
|
2019-12-02 09:11:21 +01:00
|
|
|
else if (coll->collType == CT_TOP_FRONT)
|
2019-11-27 15:12:35 +01:00
|
|
|
sub->Vel = 0;
|
2019-12-02 09:11:21 +01:00
|
|
|
else if (coll->collType == CT_LEFT)
|
2019-11-27 15:12:35 +01:00
|
|
|
v->pos.yRot += ANGLE(5);
|
2019-12-02 09:11:21 +01:00
|
|
|
else if (coll->collType == CT_RIGHT)
|
2019-11-27 15:12:35 +01:00
|
|
|
v->pos.yRot -= ANGLE(5);
|
2019-12-02 09:11:21 +01:00
|
|
|
else if (coll->collType == CT_CLAMP)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
v->pos.xPos = coll->old.x;
|
|
|
|
v->pos.yPos = coll->old.y;
|
|
|
|
v->pos.zPos = coll->old.z;
|
|
|
|
sub->Vel = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coll->midFloor < 0)
|
|
|
|
{
|
|
|
|
v->pos.yPos += coll->midFloor;
|
|
|
|
sub->RotX += WALLDEFLECT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-05 17:35:57 +01:00
|
|
|
static void UserInput(ITEM_INFO* v, ITEM_INFO* l, SUB_INFO* sub)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
short anim, frame;
|
|
|
|
|
|
|
|
CanGetOff(v);
|
|
|
|
|
2019-12-31 14:56:02 +01:00
|
|
|
anim = l->animNumber - Objects[ID_UPV_LARA_ANIMS].animIndex;
|
2019-11-27 15:12:35 +01:00
|
|
|
frame = l->frameNumber - Anims[l->animNumber].frameBase;
|
|
|
|
|
|
|
|
switch (l->currentAnimState)
|
|
|
|
{
|
|
|
|
case SUBS_MOVE:
|
|
|
|
if (l->hitPoints <= 0)
|
|
|
|
{
|
|
|
|
l->goalAnimState = SUBS_DIE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TrInput & IN_LEFT)
|
|
|
|
sub->Rot -= ROT_ACCELERATION;
|
|
|
|
|
|
|
|
else if (TrInput & IN_RIGHT)
|
|
|
|
sub->Rot += ROT_ACCELERATION;
|
|
|
|
|
|
|
|
if (sub->Flags & UPV_SURFACE)
|
|
|
|
{
|
|
|
|
if (v->pos.xRot > SURFACE_ANGLE)
|
|
|
|
v->pos.xRot -= ANGLE(1);
|
|
|
|
else if (v->pos.xRot < SURFACE_ANGLE)
|
|
|
|
v->pos.xRot += ANGLE(1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (TrInput & IN_FORWARD)
|
|
|
|
sub->RotX -= UPDOWN_ACCEL;
|
|
|
|
else if (TrInput & IN_BACK)
|
|
|
|
sub->RotX += UPDOWN_ACCEL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TrInput & IN_JUMP)
|
|
|
|
{
|
|
|
|
if ((sub->Flags & UPV_SURFACE) && (TrInput & IN_FORWARD) && (v->pos.xRot > -DIVE_ANGLE))
|
|
|
|
sub->Flags |= UPV_DIVE;
|
|
|
|
|
|
|
|
sub->Vel += ACCELERATION;
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
l->goalAnimState = SUBS_POSE;
|
|
|
|
|
|
|
|
break;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2019-11-27 15:12:35 +01:00
|
|
|
case SUBS_POSE:
|
|
|
|
if (l->hitPoints <= 0)
|
|
|
|
{
|
|
|
|
l->goalAnimState = SUBS_DIE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TrInput & IN_LEFT)
|
|
|
|
sub->Rot -= ROT_SLOWACCEL;
|
|
|
|
else if (TrInput & IN_RIGHT)
|
|
|
|
sub->Rot += ROT_SLOWACCEL;
|
|
|
|
|
|
|
|
if (sub->Flags & UPV_SURFACE)
|
|
|
|
{
|
|
|
|
if (v->pos.xRot > SURFACE_ANGLE)
|
|
|
|
v->pos.xRot -= ANGLE(1);
|
|
|
|
else if (v->pos.xRot < SURFACE_ANGLE)
|
|
|
|
v->pos.xRot += ANGLE(1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (TrInput & IN_FORWARD)
|
|
|
|
sub->RotX -= UPDOWN_ACCEL;
|
|
|
|
else if (TrInput & IN_BACK)
|
|
|
|
sub->RotX += UPDOWN_ACCEL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((TrInput & IN_ROLL) && (CanGetOff(v)))
|
|
|
|
{
|
|
|
|
if (sub->Flags & UPV_SURFACE)
|
|
|
|
l->goalAnimState = SUBS_GETOFFS;
|
|
|
|
else
|
|
|
|
l->goalAnimState = SUBS_GETOFF;
|
|
|
|
|
|
|
|
sub->Flags &= ~UPV_CONTROL;
|
|
|
|
|
|
|
|
StopSoundEffect(346);
|
|
|
|
SoundEffect(348, (PHD_3DPOS*)&v->pos.xPos, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (TrInput & IN_JUMP)
|
|
|
|
{
|
|
|
|
if ((sub->Flags & UPV_SURFACE) && (TrInput & IN_FORWARD) && (v->pos.xRot > -DIVE_ANGLE))
|
|
|
|
sub->Flags |= UPV_DIVE;
|
|
|
|
|
|
|
|
l->goalAnimState = SUBS_MOVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2019-11-27 15:12:35 +01:00
|
|
|
case SUBS_GETON:
|
2019-11-30 13:51:37 +01:00
|
|
|
if (anim == 11)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
v->pos.yPos += 4;
|
|
|
|
v->pos.xRot += ANGLE(1);
|
|
|
|
|
|
|
|
if (frame == 30)
|
|
|
|
SoundEffect(347, (PHD_3DPOS*)&v->pos.xPos, 2);
|
|
|
|
|
|
|
|
if (frame == 50)
|
|
|
|
sub->Flags |= UPV_CONTROL;
|
|
|
|
}
|
|
|
|
|
2019-11-30 13:51:37 +01:00
|
|
|
else if (anim == 13)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
if (frame == 30)
|
|
|
|
SoundEffect(347, (PHD_3DPOS*)&v->pos.xPos, 2);
|
|
|
|
|
|
|
|
if (frame == 42)
|
|
|
|
sub->Flags |= UPV_CONTROL;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2019-11-27 15:12:35 +01:00
|
|
|
case SUBS_GETOFF:
|
2019-11-30 13:51:37 +01:00
|
|
|
if ((anim == 12) && (frame == 42))
|
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;
|
|
|
|
LPos.roomNumber = v->roomNumber;
|
|
|
|
VPos.x = v->pos.xPos;
|
|
|
|
VPos.y = v->pos.yPos;
|
|
|
|
VPos.z = v->pos.zPos;
|
|
|
|
VPos.roomNumber = v->roomNumber;
|
|
|
|
mgLOS(&VPos, &LPos, 0);
|
|
|
|
|
|
|
|
l->pos.xPos = LPos.x;
|
|
|
|
l->pos.yPos = LPos.y;
|
|
|
|
l->pos.zPos = LPos.z;
|
|
|
|
l->animNumber = 108;
|
|
|
|
l->frameNumber = Anims[l->animNumber].frameBase;
|
|
|
|
l->currentAnimState = 13;
|
|
|
|
|
|
|
|
l->fallspeed = 0;
|
|
|
|
l->gravityStatus = false;
|
|
|
|
l->pos.xRot = l->pos.zRot = 0;
|
|
|
|
|
|
|
|
UpdateLaraRoom(l, 0);
|
|
|
|
|
|
|
|
Lara.waterStatus = LW_UNDERWATER;
|
|
|
|
Lara.gunStatus = LG_NO_ARMS;
|
|
|
|
g_LaraExtra.Vehicle = NO_ITEM;
|
|
|
|
|
|
|
|
v->hitPoints = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2019-11-30 13:51:37 +01:00
|
|
|
|
2019-11-27 15:12:35 +01:00
|
|
|
case SUBS_GETOFFS:
|
2019-11-30 13:51:37 +01:00
|
|
|
if ((anim == 9) && (frame == 51))
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
int wd, wh, hfw;
|
|
|
|
PHD_VECTOR vec = { 0, 0, 0 };
|
|
|
|
|
|
|
|
wd = GetWaterSurface(l->pos.xPos, l->pos.yPos, l->pos.zPos, l->roomNumber);
|
|
|
|
wh = GetWaterHeight(l->pos.xPos, l->pos.yPos, l->pos.zPos, l->roomNumber);
|
|
|
|
|
|
|
|
if (wh != NO_HEIGHT)
|
|
|
|
hfw = l->pos.yPos - wh;
|
|
|
|
else
|
|
|
|
hfw = NO_HEIGHT;
|
|
|
|
|
2019-12-15 16:19:01 +01:00
|
|
|
GetLaraJointPosition(&vec, LM_HIPS);
|
2019-11-27 15:12:35 +01:00
|
|
|
|
|
|
|
l->pos.xPos = vec.x;
|
|
|
|
l->pos.yPos = l->pos.yPos + 1 - hfw;
|
|
|
|
l->pos.yPos = vec.y;
|
|
|
|
l->pos.zPos = vec.z;
|
|
|
|
l->animNumber = 114;
|
|
|
|
l->frameNumber = Anims[l->animNumber].frameBase;
|
|
|
|
l->currentAnimState = l->goalAnimState = 34;
|
|
|
|
|
|
|
|
l->fallspeed = 0;
|
|
|
|
l->gravityStatus = false;
|
|
|
|
l->pos.xRot = l->pos.zRot = 0;
|
|
|
|
|
|
|
|
UpdateLaraRoom(l, -LARA_HITE / 2);
|
|
|
|
|
|
|
|
Lara.waterStatus = LW_SURFACE;
|
|
|
|
Lara.waterSurfaceDist = -hfw;
|
|
|
|
Lara.diveCount = 11;
|
|
|
|
Lara.torsoXrot = Lara.torsoYrot = 0;
|
|
|
|
Lara.headXrot = Lara.headYrot = 0;
|
|
|
|
Lara.gunStatus = LG_NO_ARMS;
|
|
|
|
g_LaraExtra.Vehicle = NO_ITEM;
|
|
|
|
|
|
|
|
v->hitPoints = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SUBS_DIE:
|
2019-11-30 13:51:37 +01:00
|
|
|
if (((anim == 0) && (frame == 16)) || ((anim == 0) && (frame == 17)))
|
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
|
|
|
|
|
|
|
l->pos.xPos = vec.x;
|
|
|
|
l->pos.yPos = vec.y;
|
|
|
|
l->pos.zPos = vec.z;
|
2019-11-30 13:51:37 +01:00
|
|
|
l->animNumber = 124;
|
|
|
|
l->frameNumber = GF(124, 17);
|
2019-11-27 15:12:35 +01:00
|
|
|
l->currentAnimState = l->goalAnimState = 44;
|
|
|
|
l->fallspeed = 0;
|
|
|
|
l->gravityStatus = 0;
|
|
|
|
l->pos.xRot = l->pos.zRot = 0;
|
|
|
|
|
|
|
|
sub->Flags |= UPV_DEAD;
|
|
|
|
}
|
|
|
|
v->speed = 0;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sub->Flags & UPV_DIVE)
|
|
|
|
{
|
|
|
|
if (v->pos.xRot > -DIVE_ANGLE)
|
|
|
|
v->pos.xRot -= DIVE_SPEED;
|
|
|
|
else
|
|
|
|
sub->Flags &= ~UPV_DIVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sub->Vel > 0)
|
|
|
|
{
|
|
|
|
if ((sub->Vel -= FRICTION) < 0)
|
|
|
|
sub->Vel = 0;
|
|
|
|
}
|
|
|
|
else if (sub->Vel < 0)
|
|
|
|
{
|
|
|
|
if ((sub->Vel += FRICTION) > 0)
|
|
|
|
sub->Vel = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sub->Vel > MAX_SPEED)
|
|
|
|
sub->Vel = MAX_SPEED;
|
|
|
|
else if (sub->Vel < -MAX_SPEED)
|
|
|
|
sub->Vel = -MAX_SPEED;
|
|
|
|
|
|
|
|
if (sub->Rot > 0)
|
|
|
|
{
|
|
|
|
if ((sub->Rot -= ROT_FRICTION) < 0)
|
|
|
|
sub->Rot = 0;
|
|
|
|
}
|
|
|
|
else if (sub->Rot < 0)
|
|
|
|
{
|
|
|
|
if ((sub->Rot += ROT_FRICTION) > 0)
|
|
|
|
sub->Rot = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sub->RotX > 0)
|
|
|
|
{
|
|
|
|
if ((sub->RotX -= UPDOWN_FRICTION) < 0)
|
|
|
|
sub->RotX = 0;
|
|
|
|
}
|
|
|
|
else if (sub->RotX < 0)
|
|
|
|
{
|
|
|
|
if ((sub->RotX += UPDOWN_FRICTION) > 0)
|
|
|
|
sub->RotX = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sub->Rot > MAX_ROTATION)
|
|
|
|
sub->Rot = MAX_ROTATION;
|
|
|
|
else if (sub->Rot < -MAX_ROTATION)
|
|
|
|
sub->Rot = -MAX_ROTATION;
|
|
|
|
|
|
|
|
if (sub->RotX > MAX_UPDOWN)
|
|
|
|
sub->RotX = MAX_UPDOWN;
|
|
|
|
else if (sub->RotX < -MAX_UPDOWN)
|
|
|
|
sub->RotX = -MAX_UPDOWN;
|
|
|
|
}
|
|
|
|
|
2019-12-02 14:49:19 +01:00
|
|
|
void SubInitialise(short itemNum)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
ITEM_INFO* v;
|
|
|
|
SUB_INFO* sub;
|
|
|
|
|
|
|
|
v = &Items[itemNum];
|
|
|
|
sub = (SUB_INFO*)GameMalloc(sizeof(SUB_INFO));
|
|
|
|
v->data = (void*)sub;
|
|
|
|
sub->Vel = sub->Rot = 0;
|
|
|
|
sub->Flags = UPV_SURFACE;
|
|
|
|
sub->WeaponTimer = 0;
|
|
|
|
}
|
|
|
|
|
2019-12-02 14:49:19 +01:00
|
|
|
void SubCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
int geton;
|
|
|
|
ITEM_INFO* v;
|
|
|
|
|
|
|
|
if ((l->hitPoints <= 0) || (g_LaraExtra.Vehicle != NO_ITEM))
|
|
|
|
return;
|
|
|
|
|
|
|
|
v = &Items[itemNum];
|
|
|
|
|
|
|
|
geton = GetOnSub(itemNum, coll);
|
|
|
|
if (geton)
|
|
|
|
{
|
|
|
|
g_LaraExtra.Vehicle = itemNum;
|
|
|
|
Lara.waterStatus = LW_ABOVE_WATER;
|
|
|
|
|
|
|
|
/* -------- throw flare away if using */
|
|
|
|
|
|
|
|
if (Lara.gunType == WEAPON_FLARE)
|
|
|
|
{
|
|
|
|
CreateFlare(ID_FLARE_ITEM, 0);
|
2019-12-02 09:11:21 +01:00
|
|
|
undraw_flare_meshes();
|
2019-11-27 15:12:35 +01:00
|
|
|
Lara.flareControlLeft = false;
|
|
|
|
Lara.requestGunType = Lara.gunType = WEAPON_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------- determine animation */
|
|
|
|
Lara.gunStatus = LG_HANDS_BUSY;
|
|
|
|
|
|
|
|
l->pos.xPos = v->pos.xPos;
|
|
|
|
l->pos.yPos = v->pos.yPos;
|
|
|
|
l->pos.zPos = v->pos.zPos;
|
|
|
|
l->pos.yRot = v->pos.yRot;
|
|
|
|
|
|
|
|
if ((l->currentAnimState == 33) || (l->currentAnimState == 34))
|
|
|
|
{
|
2019-12-31 14:56:02 +01:00
|
|
|
l->animNumber = Objects[ID_UPV_LARA_ANIMS].animIndex + 10;
|
|
|
|
l->frameNumber = GF2(ID_UPV_LARA_ANIMS, 10, 0);
|
2019-11-27 15:12:35 +01:00
|
|
|
l->currentAnimState = l->goalAnimState = SUBS_GETON;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-12-31 14:56:02 +01:00
|
|
|
l->animNumber = Objects[ID_UPV_LARA_ANIMS].animIndex + 13;
|
2019-11-30 13:51:37 +01:00
|
|
|
l->frameNumber = GF2(ID_UPV, 13, 0);
|
2019-11-27 15:12:35 +01:00
|
|
|
l->currentAnimState = l->goalAnimState = SUBS_GETON;
|
|
|
|
}
|
|
|
|
|
|
|
|
AnimateItem(l);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//v->pos.yPos += SUB_DRAW_SHIFT;
|
|
|
|
|
|
|
|
if (!TestBoundsCollide(v, LaraItem, coll->radius))
|
|
|
|
return;
|
|
|
|
if (!TestCollision(v, LaraItem))
|
|
|
|
return;
|
|
|
|
ItemPushLara(v, LaraItem, coll, false, 0);
|
|
|
|
|
|
|
|
//v->pos.yPos -= SUB_DRAW_SHIFT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-02 14:49:19 +01:00
|
|
|
int SubControl()
|
2019-11-27 15:12:35 +01:00
|
|
|
{
|
|
|
|
int h;
|
|
|
|
SUB_INFO* sub;
|
|
|
|
ITEM_INFO* v, * l;
|
|
|
|
FLOOR_INFO* floor;
|
|
|
|
short room_number;
|
|
|
|
|
|
|
|
l = LaraItem;
|
|
|
|
v = &Items[g_LaraExtra.Vehicle];
|
|
|
|
sub = (SUB_INFO*)v->data;
|
|
|
|
|
|
|
|
/* -------- update dynamics */
|
|
|
|
if (!(sub->Flags & UPV_DEAD))
|
|
|
|
{
|
|
|
|
UserInput(v, l, sub);
|
|
|
|
|
|
|
|
v->speed = sub->Vel >> 16;
|
|
|
|
|
|
|
|
v->pos.xRot += sub->RotX >> 16;
|
|
|
|
v->pos.yRot += (sub->Rot >> 16);
|
|
|
|
v->pos.zRot = (sub->Rot >> 12);
|
|
|
|
|
|
|
|
if (v->pos.xRot > UPDOWN_LIMIT)
|
|
|
|
v->pos.xRot = UPDOWN_LIMIT;
|
|
|
|
else if (v->pos.xRot < -UPDOWN_LIMIT)
|
|
|
|
v->pos.xRot = -UPDOWN_LIMIT;
|
|
|
|
|
|
|
|
v->pos.xPos += (((SIN(v->pos.yRot) * v->speed) >> W2V_SHIFT)* COS(v->pos.xRot)) >> W2V_SHIFT;
|
|
|
|
v->pos.yPos -= (SIN(v->pos.xRot) * v->speed) >> W2V_SHIFT;
|
|
|
|
v->pos.zPos += (((COS(v->pos.yRot) * v->speed) >> W2V_SHIFT)* COS(v->pos.xRot)) >> W2V_SHIFT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------- determine if vehicle is near the surface */
|
|
|
|
room_number = v->roomNumber;
|
|
|
|
floor = GetFloor(v->pos.xPos, v->pos.yPos, v->pos.zPos, &room_number);
|
|
|
|
v->floor = GetFloorHeight(floor, v->pos.xPos, v->pos.yPos, v->pos.zPos);
|
|
|
|
|
|
|
|
if ((sub->Flags & UPV_CONTROL) && (!(sub->Flags & UPV_DEAD)))
|
|
|
|
{
|
|
|
|
h = GetWaterHeight(v->pos.xPos, v->pos.yPos, v->pos.zPos, room_number);
|
|
|
|
|
|
|
|
if ((h != NO_HEIGHT) && (!(Rooms[v->roomNumber].flags & ENV_FLAG_WATER)))
|
|
|
|
{
|
|
|
|
if ((h - v->pos.yPos) >= -SURFACE_DIST)
|
|
|
|
v->pos.yPos = h + SURFACE_DIST;
|
|
|
|
|
|
|
|
if (!(sub->Flags & UPV_SURFACE))
|
|
|
|
{
|
|
|
|
SoundEffect(36, &LaraItem->pos, 2);
|
|
|
|
sub->Flags &= ~UPV_DIVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub->Flags |= UPV_SURFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if ((h != NO_HEIGHT) && ((h - v->pos.yPos) >= -SURFACE_DIST))
|
|
|
|
{
|
|
|
|
v->pos.yPos = h + SURFACE_DIST;
|
|
|
|
|
|
|
|
if (!(sub->Flags & UPV_SURFACE))
|
|
|
|
{
|
|
|
|
SoundEffect(36, &LaraItem->pos, 2);
|
|
|
|
sub->Flags &= ~UPV_DIVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub->Flags |= UPV_SURFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
sub->Flags &= ~UPV_SURFACE;
|
|
|
|
|
|
|
|
/* -------- update air bar */
|
|
|
|
if (!(sub->Flags & UPV_SURFACE))
|
|
|
|
{
|
|
|
|
if (l->hitPoints > 0)
|
|
|
|
{
|
|
|
|
Lara.air--;
|
|
|
|
|
|
|
|
if (Lara.air < 0)
|
|
|
|
{
|
|
|
|
Lara.air = -1;
|
|
|
|
l->hitPoints -= 5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (l->hitPoints >= 0)
|
|
|
|
{
|
|
|
|
Lara.air += 10;
|
|
|
|
|
|
|
|
if (Lara.air > 1800)
|
|
|
|
Lara.air = 1800;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TestTriggers(TriggerIndex, false, 0);
|
|
|
|
SubEffects(g_LaraExtra.Vehicle);
|
|
|
|
|
|
|
|
/* -------- update vehicle & Lara */
|
|
|
|
if ((g_LaraExtra.Vehicle != NO_ITEM) && (!(sub->Flags & UPV_DEAD)))
|
|
|
|
{
|
|
|
|
DoCurrent(v);
|
|
|
|
|
|
|
|
if ((TrInput & IN_ACTION) && (sub->Flags & UPV_CONTROL) && (!sub->WeaponTimer))
|
|
|
|
{
|
|
|
|
FireSubHarpoon(v);
|
|
|
|
sub->WeaponTimer = HARPOON_RELOAD;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (room_number != v->roomNumber)
|
|
|
|
{
|
|
|
|
ItemNewRoom(g_LaraExtra.Vehicle, room_number);
|
|
|
|
ItemNewRoom(Lara.itemNumber, room_number);
|
|
|
|
}
|
|
|
|
|
|
|
|
l->pos.xPos = v->pos.xPos;
|
|
|
|
l->pos.yPos = v->pos.yPos + SUB_DRAW_SHIFT;
|
|
|
|
l->pos.zPos = v->pos.zPos;
|
|
|
|
l->pos.xRot = v->pos.xRot;
|
|
|
|
l->pos.yRot = v->pos.yRot;
|
|
|
|
l->pos.zRot = v->pos.zRot;
|
|
|
|
|
|
|
|
AnimateItem(l);
|
|
|
|
BackgroundCollision(v, l, sub);
|
|
|
|
|
|
|
|
if (sub->Flags & UPV_CONTROL)
|
|
|
|
SoundEffect(346, (PHD_3DPOS*)&v->pos.xPos, 2 | 4 | 0x1000000 | (v->speed << 16));
|
|
|
|
|
2019-12-31 14:56:02 +01:00
|
|
|
v->animNumber = Objects[ID_UPV].animIndex + (l->animNumber - Objects[ID_UPV_LARA_ANIMS].animIndex);
|
2019-11-27 15:12:35 +01:00
|
|
|
v->frameNumber = Anims[v->animNumber].frameBase + (l->frameNumber - Anims[l->animNumber].frameBase);
|
|
|
|
|
|
|
|
if (sub->Flags & UPV_SURFACE)
|
|
|
|
Camera.targetElevation = -ANGLE(60);
|
|
|
|
else
|
|
|
|
Camera.targetElevation = 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else if (sub->Flags & UPV_DEAD)
|
|
|
|
{
|
|
|
|
AnimateItem(l);
|
|
|
|
|
|
|
|
if (room_number != v->roomNumber)
|
|
|
|
ItemNewRoom(g_LaraExtra.Vehicle, room_number);
|
|
|
|
|
|
|
|
BackgroundCollision(v, l, sub);
|
|
|
|
|
|
|
|
sub->RotX = 0;
|
|
|
|
|
2019-11-30 13:51:37 +01:00
|
|
|
v->animNumber = 5;
|
|
|
|
v->frameNumber = GF2(ID_UPV, 5, 0);
|
2019-11-27 15:12:35 +01:00
|
|
|
v->goalAnimState = v->currentAnimState = SUBS_POSE;
|
|
|
|
v->fallspeed = 0;
|
|
|
|
v->speed = 0;
|
|
|
|
v->gravityStatus = true;
|
|
|
|
AnimateItem(v);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|