2020-05-27 09:21:20 +02:00
|
|
|
#include "framework.h"
|
|
|
|
#include "snowmobile.h"
|
|
|
|
#include "lara.h"
|
|
|
|
#include "items.h"
|
|
|
|
#include "collide.h"
|
|
|
|
#include "effect.h"
|
2020-08-09 22:09:14 -03:00
|
|
|
#include "lara_fire.h"
|
|
|
|
#include "lara_one_gun.h"
|
2020-05-27 09:21:20 +02:00
|
|
|
#include "effect2.h"
|
2020-08-09 22:09:14 -03:00
|
|
|
#include "lara_flare.h"
|
2020-05-27 09:21:20 +02:00
|
|
|
#include "lot.h"
|
|
|
|
#include "tomb4fx.h"
|
|
|
|
#include "sphere.h"
|
|
|
|
#include "setup.h"
|
|
|
|
#include "level.h"
|
|
|
|
#include "input.h"
|
|
|
|
#include "sound.h"
|
2020-09-15 08:10:38 +02:00
|
|
|
#include <Game\particle\SimpleParticle.h>
|
2020-10-24 01:05:59 -03:00
|
|
|
#include "prng.h"
|
2020-09-13 15:53:37 +02:00
|
|
|
|
2020-06-20 23:39:08 +02:00
|
|
|
using std::vector;
|
2020-12-21 13:16:29 -03:00
|
|
|
using namespace T5M::Math::Random;
|
2019-11-26 15:55:37 +01:00
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
enum SKIDOO_STATE
|
|
|
|
{
|
|
|
|
STATE_SKIDOO_SIT,
|
|
|
|
STATE_SKIDOO_GETON,
|
|
|
|
STATE_SKIDOO_LEFT,
|
|
|
|
STATE_SKIDOO_RIGHT,
|
|
|
|
STATE_SKIDOO_FALL,
|
|
|
|
STATE_SKIDOO_HIT,
|
|
|
|
STATE_SKIDOO_GETONL,
|
|
|
|
STATE_SKIDOO_GETOFFL,
|
|
|
|
STATE_SKIDOO_STILL,
|
|
|
|
STATE_SKIDOO_GETOFF,
|
|
|
|
STATE_SKIDOO_LETGO,
|
|
|
|
STATE_SKIDOO_DEATH,
|
|
|
|
STATE_SKIDOO_FALLOFF
|
|
|
|
};
|
2019-11-20 11:24:36 +01:00
|
|
|
|
|
|
|
#define SWIM_DEPTH 730
|
|
|
|
#define WADE_DEPTH STEP_SIZE
|
2020-09-13 15:53:37 +02:00
|
|
|
#define DAMAGE_START 140
|
2019-11-20 11:24:36 +01:00
|
|
|
#define DAMAGE_LENGTH 14
|
|
|
|
#define SKIDOO_GETON_ANIM 1
|
|
|
|
#define SKIDOO_GETONL_ANIM 18
|
|
|
|
#define SKIDOO_FALL_ANIM 8
|
|
|
|
#define SKIDOO_DEAD_ANIM 15
|
|
|
|
#define SKIDOO_HIT_LEFT 11
|
|
|
|
#define SKIDOO_HIT_RIGHT 12
|
|
|
|
#define SKIDOO_HIT_FRONT 13
|
|
|
|
#define SKIDOO_HIT_BACK 14
|
|
|
|
#define SKIDOO_GETOFF_DIST 330
|
|
|
|
#define SKIDOO_UNDO_TURN ANGLE(2)
|
|
|
|
#define SKIDOO_TURN ((ANGLE(1)/2) + SKIDOO_UNDO_TURN)
|
|
|
|
#define SKIDOO_MAX_TURN ANGLE(6)
|
|
|
|
#define SKIDOO_MOMENTUM_TURN ANGLE(3)
|
|
|
|
#define SKIDOO_MAX_MOM_TURN ANGLE(150)
|
|
|
|
#define SKIDOO_FAST_SPEED 150
|
|
|
|
#define SKIDOO_MAX_SPEED 100
|
|
|
|
#define SKIDOO_SLOW_SPEED 50
|
|
|
|
#define SKIDOO_MIN_SPEED 15
|
2019-11-26 15:55:37 +01:00
|
|
|
#define SKIDOO_ACCELERATION 10
|
2019-11-20 11:24:36 +01:00
|
|
|
#define SKIDOO_BRAKE 5
|
|
|
|
#define SKIDOO_SLOWDOWN 2
|
|
|
|
#define SKIDOO_REVERSE -5
|
|
|
|
#define SKIDOO_MAX_BACK -30
|
|
|
|
#define SKIDOO_MAX_KICK -80
|
|
|
|
#define SKIDOO_SLIP 100
|
|
|
|
#define SKIDOO_SLIP_SIDE 50
|
|
|
|
#define SKIDOO_FRONT 550
|
|
|
|
#define SKIDOO_SIDE 260
|
|
|
|
#define SKIDOO_RADIUS 500
|
|
|
|
#define SKIDOO_SNOW 500
|
|
|
|
#define SKIDOO_MAX_HEIGHT STEP_SIZE
|
2020-10-06 10:36:30 -05:00
|
|
|
#define SKIDOO_MIN_BOUNCE ((SKIDOO_MAX_SPEED/2)/256)
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2019-12-02 14:49:19 +01:00
|
|
|
void InitialiseSkidoo(short itemNum)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
ITEM_INFO* skidoo = &g_Level.Items[itemNum];
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
SKIDOO_INFO* skinfo = game_malloc<SKIDOO_INFO>();
|
2019-11-20 11:24:36 +01:00
|
|
|
skidoo->data = (void*)skinfo;
|
2020-09-13 15:53:37 +02:00
|
|
|
|
|
|
|
skinfo->alreadyCdPlayed = false;
|
2019-11-26 15:55:37 +01:00
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
if (skidoo->objectNumber == ID_SNOWMOBILE_GUN)
|
|
|
|
skinfo->armed = true;
|
|
|
|
else
|
2019-11-26 15:55:37 +01:00
|
|
|
skinfo->armed = false;
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
skinfo->extraRotation = 0;
|
|
|
|
skinfo->flashTimer = 0;
|
|
|
|
skinfo->leftFallspeed = 0;
|
|
|
|
skinfo->momentumAngle = skidoo->pos.yRot;
|
2019-11-20 11:24:36 +01:00
|
|
|
skinfo->pitch = 0;
|
2020-09-13 15:53:37 +02:00
|
|
|
skinfo->rightFallspeed = 0;
|
|
|
|
skinfo->skidooTurn = 0;
|
2019-11-20 11:24:36 +01:00
|
|
|
|
|
|
|
if (skidoo->status != ITEM_ACTIVE)
|
|
|
|
{
|
|
|
|
AddActiveItem(itemNum);
|
|
|
|
skidoo->status = ITEM_ACTIVE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-09 23:11:43 -05:00
|
|
|
void SkidooBaddieCollision(ITEM_INFO* skidoo)
|
|
|
|
{
|
|
|
|
int x, y, z, i;
|
2020-09-13 15:53:37 +02:00
|
|
|
|
2020-09-09 23:11:43 -05:00
|
|
|
vector<short> roomsList;
|
|
|
|
roomsList.push_back(skidoo->roomNumber);
|
2020-09-13 15:53:37 +02:00
|
|
|
|
2020-09-09 23:11:43 -05:00
|
|
|
ROOM_INFO* room = &g_Level.Rooms[skidoo->roomNumber];
|
|
|
|
for (i = 0; i < room->doors.size(); i++)
|
|
|
|
{
|
|
|
|
roomsList.push_back(room->doors[i].room);
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
|
2020-09-09 23:11:43 -05:00
|
|
|
for (int i = 0; i < roomsList.size(); i++)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-09 23:11:43 -05:00
|
|
|
short itemNum = g_Level.Rooms[roomsList[i]].itemNumber;
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
while (itemNum != NO_ITEM)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNum];
|
|
|
|
|
|
|
|
if (item->collidable && item->status != IFLAG_INVISIBLE && item != LaraItem && item != skidoo)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
OBJECT_INFO* object = &Objects[item->objectNumber];
|
|
|
|
|
|
|
|
if (object->collision && (object->intelligent))
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
x = skidoo->pos.xPos - item->pos.xPos;
|
|
|
|
y = skidoo->pos.yPos - item->pos.yPos;
|
|
|
|
z = skidoo->pos.zPos - item->pos.zPos;
|
|
|
|
|
|
|
|
if (x > -2048 && x < 2048 && z > -2048 && z < 2048 && y > -2048 && y < 2048)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
if (item->objectNumber == ID_ROLLINGBALL)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
if (TestBoundsCollide(item, LaraItem, 100))
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
if (LaraItem->hitPoints > 0)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
DoLotsOfBlood(LaraItem->pos.xPos, LaraItem->pos.yPos - (STEP_SIZE * 2), LaraItem->pos.zPos, GetRandomControl() & 3, LaraItem->pos.yRot, LaraItem->roomNumber, 5);
|
|
|
|
item->hitPoints -= 8;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
}
|
2020-09-13 15:53:37 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (TestBoundsCollide(item, skidoo, SKIDOO_FRONT))
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
DoLotsOfBlood(skidoo->pos.xPos, skidoo->pos.yPos, skidoo->pos.zPos, GetRandomControl() & 3, LaraItem->pos.yRot, LaraItem->roomNumber, 3);
|
|
|
|
item->hitPoints = 0;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-09-13 15:53:37 +02:00
|
|
|
|
|
|
|
itemNum = item->nextItem;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
void SkidooGuns()
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
WEAPON_INFO* winfo = &Weapons[WEAPON_SNOWMOBILE];
|
|
|
|
ITEM_INFO* skidoo = &g_Level.Items[Lara.Vehicle];
|
|
|
|
SKIDOO_INFO* skinfo = (SKIDOO_INFO*)skidoo->data;
|
2019-11-20 11:24:36 +01:00
|
|
|
|
|
|
|
LaraGetNewTarget(winfo);
|
|
|
|
AimWeapon(winfo, &Lara.rightArm);
|
|
|
|
|
|
|
|
if (!skidoo->itemFlags[0] && (TrInput & IN_ACTION))
|
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
short angles[] = {
|
|
|
|
Lara.rightArm.yRot + LaraItem->pos.yRot,
|
|
|
|
Lara.rightArm.xRot
|
|
|
|
};
|
|
|
|
|
2019-11-20 11:24:36 +01:00
|
|
|
if (FireWeapon(WEAPON_PISTOLS, Lara.target, LaraItem, angles) +
|
|
|
|
FireWeapon(WEAPON_PISTOLS, Lara.target, LaraItem, angles))
|
|
|
|
{
|
2021-03-24 20:06:37 +01:00
|
|
|
skinfo->flashTimer = 2;
|
2019-11-20 11:24:36 +01:00
|
|
|
SoundEffect(winfo->sampleNum, &LaraItem->pos, 0);
|
|
|
|
skidoo->itemFlags[0] = 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (skidoo->itemFlags[0])
|
|
|
|
skidoo->itemFlags[0]--;
|
|
|
|
}
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
void SkidooExplode(ITEM_INFO* skidoo)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-07-21 09:56:47 +02:00
|
|
|
if (g_Level.Rooms[skidoo->roomNumber].flags & ENV_FLAG_WATER)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-08-10 18:17:59 +02:00
|
|
|
TriggerUnderwaterExplosion(skidoo, 1);
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TriggerExplosionSparks(skidoo->pos.xPos, skidoo->pos.yPos, skidoo->pos.zPos, 3, -2, 0, skidoo->roomNumber);
|
2019-11-27 15:12:35 +01:00
|
|
|
for (int i = 0; i < 3; i++)
|
2019-11-20 11:24:36 +01:00
|
|
|
TriggerExplosionSparks(skidoo->pos.xPos, skidoo->pos.yPos, skidoo->pos.zPos, 3, -1, 0, skidoo->roomNumber);
|
|
|
|
}
|
|
|
|
|
2020-10-24 01:05:59 -03:00
|
|
|
TriggerShockwave(&PHD_3DPOS(skidoo->pos.xPos, skidoo->pos.yPos - 128, skidoo->pos.zPos, 0, skidoo->pos.yRot, 0), 50, 180, 40, generateFloat(160, 200), 60, 60, 64, generateFloat(0, 359), 0);
|
2020-10-02 12:55:00 -05:00
|
|
|
// ExplodingDeath(Lara.Vehicle, -1, 256);
|
|
|
|
// KillItem(Lara.Vehicle);
|
2019-11-20 11:24:36 +01:00
|
|
|
skidoo->status = ITEM_DEACTIVATED;
|
2020-09-13 15:53:37 +02:00
|
|
|
|
2021-05-26 06:04:32 +02:00
|
|
|
SoundEffect(SFX_TR4_EXPLOSION1, 0, 0);
|
|
|
|
SoundEffect(SFX_TR4_EXPLOSION2, 0, 0);
|
2020-09-13 15:53:37 +02:00
|
|
|
|
2020-04-27 14:01:00 +02:00
|
|
|
Lara.Vehicle = NO_ITEM;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
bool SkidooCheckGetOffOK(int direction)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
ITEM_INFO* skidoo = &g_Level.Items[Lara.Vehicle];
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
short angle;
|
|
|
|
if (direction == STATE_SKIDOO_GETOFFL)
|
2019-11-20 11:24:36 +01:00
|
|
|
angle = skidoo->pos.yRot + 0x4000;
|
|
|
|
else
|
|
|
|
angle = skidoo->pos.yRot - 0x4000;
|
|
|
|
|
2020-10-05 22:24:57 -03:00
|
|
|
int x = skidoo->pos.xPos - SKIDOO_GETOFF_DIST * phd_sin(angle);
|
2020-09-13 15:53:37 +02:00
|
|
|
int y = skidoo->pos.yPos;
|
2020-10-05 22:24:57 -03:00
|
|
|
int z = skidoo->pos.zPos - SKIDOO_GETOFF_DIST * phd_cos(angle);
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
short roomNumber = skidoo->roomNumber;
|
|
|
|
FLOOR_INFO* floor = GetFloor(x, y, z, &roomNumber);
|
|
|
|
int height = GetFloorHeight(floor, x, y, z);
|
2019-11-20 11:24:36 +01:00
|
|
|
|
|
|
|
if (HeightType == BIG_SLOPE || height == NO_HEIGHT || HeightType == DIAGONAL)
|
2020-09-13 15:53:37 +02:00
|
|
|
return false;
|
2019-11-20 11:24:36 +01:00
|
|
|
|
|
|
|
if (abs(height - skidoo->pos.yPos) > WALL_SIZE / 2)
|
2020-09-13 15:53:37 +02:00
|
|
|
return false;
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
int ceiling = GetCeiling(floor, x, y, z);
|
2019-11-20 11:24:36 +01:00
|
|
|
if (ceiling - skidoo->pos.yPos > -LARA_HITE || height - ceiling < LARA_HITE)
|
2020-09-13 15:53:37 +02:00
|
|
|
return false;
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
return true;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
bool SkidooCheckGetOff()
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-10-02 12:55:00 -05:00
|
|
|
if (Lara.Vehicle != NO_ITEM)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-10-02 12:55:00 -05:00
|
|
|
ITEM_INFO* skidoo = &g_Level.Items[Lara.Vehicle];
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-10-02 12:55:00 -05:00
|
|
|
if ((LaraItem->currentAnimState == STATE_SKIDOO_GETOFF
|
|
|
|
|| LaraItem->currentAnimState == STATE_SKIDOO_GETOFFL)
|
|
|
|
&& LaraItem->frameNumber == g_Level.Anims[LaraItem->animNumber].frameEnd)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-10-02 12:55:00 -05:00
|
|
|
if (LaraItem->currentAnimState == STATE_SKIDOO_GETOFFL)
|
|
|
|
LaraItem->pos.yRot += ANGLE(90);
|
|
|
|
else
|
|
|
|
LaraItem->pos.yRot -= ANGLE(90);
|
|
|
|
|
|
|
|
LaraItem->animNumber = LA_STAND_SOLID;
|
|
|
|
LaraItem->frameNumber = g_Level.Anims[LaraItem->animNumber].frameBase;
|
|
|
|
LaraItem->currentAnimState = LaraItem->goalAnimState = LS_STOP;
|
2020-10-14 22:22:10 -03:00
|
|
|
LaraItem->pos.xPos -= SKIDOO_GETOFF_DIST * phd_sin(LaraItem->pos.yRot);
|
|
|
|
LaraItem->pos.zPos -= SKIDOO_GETOFF_DIST * phd_cos(LaraItem->pos.yRot);
|
2020-10-02 12:55:00 -05:00
|
|
|
LaraItem->pos.xRot = LaraItem->pos.zRot = 0;
|
|
|
|
Lara.Vehicle = NO_ITEM;
|
|
|
|
Lara.gunStatus = LG_NO_ARMS;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
2020-10-02 12:55:00 -05:00
|
|
|
else if (LaraItem->currentAnimState == STATE_SKIDOO_LETGO
|
|
|
|
&& (skidoo->pos.yPos == skidoo->floor
|
|
|
|
|| LaraItem->frameNumber == g_Level.Anims[LaraItem->animNumber].frameEnd))
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-10-02 12:55:00 -05:00
|
|
|
LaraItem->animNumber = LA_FREEFALL;
|
|
|
|
LaraItem->frameNumber = g_Level.Anims[LaraItem->animNumber].frameBase;
|
|
|
|
LaraItem->currentAnimState = LS_FREEFALL;
|
|
|
|
|
|
|
|
if (skidoo->pos.yPos == skidoo->floor)
|
|
|
|
{
|
|
|
|
LaraItem->goalAnimState = LS_DEATH;
|
|
|
|
LaraItem->fallspeed = DAMAGE_START + DAMAGE_LENGTH;
|
|
|
|
LaraItem->speed = 0;
|
|
|
|
SkidooExplode(skidoo);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LaraItem->goalAnimState = LS_FREEFALL;
|
|
|
|
LaraItem->pos.yPos -= 200;
|
|
|
|
LaraItem->fallspeed = skidoo->fallspeed;
|
|
|
|
LaraItem->speed = skidoo->speed;
|
2021-05-26 06:04:32 +02:00
|
|
|
SoundEffect(SFX_TR4_LARA_FALL, &LaraItem->pos, 0);
|
2020-10-02 12:55:00 -05:00
|
|
|
}
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-10-02 12:55:00 -05:00
|
|
|
LaraItem->pos.xRot = LaraItem->pos.zRot = 0;
|
|
|
|
LaraItem->gravityStatus = true;
|
|
|
|
Lara.gunStatus = LG_NO_ARMS;
|
2020-12-19 23:34:52 -03:00
|
|
|
Lara.moveAngle = skidoo->pos.yRot;
|
2021-03-24 20:06:37 +01:00
|
|
|
skidoo->flags |= ONESHOT;
|
2020-10-02 12:55:00 -05:00
|
|
|
skidoo->collidable = false;
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-10-02 12:55:00 -05:00
|
|
|
return false;
|
|
|
|
}
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-10-02 12:55:00 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return true;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
|
2019-12-02 14:49:19 +01:00
|
|
|
void DoSnowEffect(ITEM_INFO* skidoo)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-15 08:10:38 +02:00
|
|
|
T5M::Effects::TriggerSnowmobileSnow(skidoo);
|
2021-03-24 20:06:37 +01:00
|
|
|
// OLD SPARK EFFECT
|
2020-09-15 08:10:38 +02:00
|
|
|
/*SPARKS* spark = &Sparks[GetFreeSpark()];
|
2020-09-13 15:53:37 +02:00
|
|
|
spark->on = 1;
|
|
|
|
spark->sR = 64;
|
|
|
|
spark->sG = 64;
|
|
|
|
spark->sB = 64;
|
|
|
|
spark->dR = 64;
|
|
|
|
spark->dG = 64;
|
|
|
|
spark->dB = 64;
|
|
|
|
spark->colFadeSpeed = 1;
|
|
|
|
spark->transType = COLADD;
|
|
|
|
spark->life = spark->sLife = (GetRandomControl() & 3) + 6;
|
|
|
|
spark->fadeToBlack = spark->life - 4;
|
|
|
|
spark->x = (GetRandomControl() & 255) + skidoo->pos.xPos - 8;
|
|
|
|
spark->y = (GetRandomControl() & 15) + skidoo->pos.yPos - 8;
|
|
|
|
spark->z = (GetRandomControl() & 255) + skidoo->pos.zPos - 8;
|
|
|
|
spark->xVel = 0;
|
|
|
|
spark->zVel = 0;
|
|
|
|
spark->friction = 0;
|
|
|
|
spark->flags = 538;
|
|
|
|
spark->yVel = (GetRandomControl() & 0x7F) - 256;
|
|
|
|
spark->rotAng = GetRandomControl() & 0xFFF;
|
|
|
|
spark->scalar = 3;
|
|
|
|
spark->maxYvel = 0;
|
|
|
|
spark->rotAdd = (GetRandomControl() & 0x1F) - 16;
|
|
|
|
spark->gravity = -spark->yVel >> 2;
|
|
|
|
spark->sSize = spark->size = ((GetRandomControl() & 3) + 16) * 32;
|
2020-09-15 08:10:38 +02:00
|
|
|
spark->dSize = 2 * spark->size;*/
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
void SkidooAnimation(ITEM_INFO* skidoo, int collide, bool dead)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
SKIDOO_INFO* skinfo = (SKIDOO_INFO*)skidoo->data;
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
if (skidoo->pos.yPos != skidoo->floor
|
|
|
|
&& skidoo->fallspeed > 0
|
|
|
|
&& LaraItem->currentAnimState != STATE_SKIDOO_FALL
|
|
|
|
&& !dead)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
|
|
|
LaraItem->animNumber = Objects[ID_SNOWMOBILE_LARA_ANIMS].animIndex + SKIDOO_FALL_ANIM;
|
2020-07-21 09:56:47 +02:00
|
|
|
LaraItem->frameNumber = g_Level.Anims[LaraItem->animNumber].frameBase;
|
2020-09-13 15:53:37 +02:00
|
|
|
LaraItem->currentAnimState = LaraItem->goalAnimState = STATE_SKIDOO_FALL;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
2020-09-13 15:53:37 +02:00
|
|
|
else if (collide
|
|
|
|
&& !dead
|
|
|
|
&& LaraItem->currentAnimState != STATE_SKIDOO_FALL)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
if (LaraItem->currentAnimState != STATE_SKIDOO_HIT)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
|
|
|
if (collide == SKIDOO_HIT_FRONT)
|
2020-03-02 09:49:11 +01:00
|
|
|
SoundEffect(SFX_TR2_CLATTER_1, &skidoo->pos, 0);
|
2019-11-20 11:24:36 +01:00
|
|
|
else
|
2020-03-02 09:49:11 +01:00
|
|
|
SoundEffect(SFX_TR2_CLATTER_2, &skidoo->pos, 0);
|
2019-11-27 15:12:35 +01:00
|
|
|
LaraItem->animNumber = (short)(Objects[ID_SNOWMOBILE_LARA_ANIMS].animIndex + collide);
|
2020-07-21 09:56:47 +02:00
|
|
|
LaraItem->frameNumber = g_Level.Anims[LaraItem->animNumber].frameBase;
|
2020-09-13 15:53:37 +02:00
|
|
|
LaraItem->currentAnimState = LaraItem->goalAnimState = STATE_SKIDOO_HIT;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (LaraItem->currentAnimState)
|
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
case STATE_SKIDOO_STILL:
|
2019-11-20 11:24:36 +01:00
|
|
|
|
|
|
|
if (dead)
|
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
LaraItem->goalAnimState = STATE_SKIDOO_DEATH;
|
2019-11-20 11:24:36 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
LaraItem->goalAnimState = STATE_SKIDOO_STILL;
|
2019-11-20 11:24:36 +01:00
|
|
|
|
|
|
|
if (TrInput & IN_JUMP)
|
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
if ((TrInput & IN_RIGHT) && SkidooCheckGetOffOK(STATE_SKIDOO_GETOFF))
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
LaraItem->goalAnimState = STATE_SKIDOO_GETOFF;
|
2019-11-20 11:24:36 +01:00
|
|
|
skidoo->speed = 0;
|
|
|
|
}
|
2020-09-13 15:53:37 +02:00
|
|
|
else if ((TrInput & IN_LEFT) && SkidooCheckGetOffOK(STATE_SKIDOO_GETOFFL))
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
LaraItem->goalAnimState = STATE_SKIDOO_GETOFFL;
|
2019-11-20 11:24:36 +01:00
|
|
|
skidoo->speed = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (TrInput & IN_LEFT)
|
2020-09-13 15:53:37 +02:00
|
|
|
LaraItem->goalAnimState = STATE_SKIDOO_LEFT;
|
2019-11-20 11:24:36 +01:00
|
|
|
else if (TrInput & IN_RIGHT)
|
2020-09-13 15:53:37 +02:00
|
|
|
LaraItem->goalAnimState = STATE_SKIDOO_RIGHT;
|
2019-11-20 11:24:36 +01:00
|
|
|
else if (TrInput & (IN_FORWARD | IN_BACK))
|
2020-09-13 15:53:37 +02:00
|
|
|
LaraItem->goalAnimState = STATE_SKIDOO_SIT;
|
2019-11-20 11:24:36 +01:00
|
|
|
break;
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
case STATE_SKIDOO_SIT:
|
2019-11-20 11:24:36 +01:00
|
|
|
if (skidoo->speed == 0)
|
2020-09-13 15:53:37 +02:00
|
|
|
LaraItem->goalAnimState = STATE_SKIDOO_STILL;
|
2019-11-20 11:24:36 +01:00
|
|
|
|
|
|
|
if (dead)
|
2020-09-13 15:53:37 +02:00
|
|
|
LaraItem->goalAnimState = STATE_SKIDOO_FALLOFF;
|
2019-11-20 11:24:36 +01:00
|
|
|
else if (TrInput & IN_LEFT)
|
2020-09-13 15:53:37 +02:00
|
|
|
LaraItem->goalAnimState = STATE_SKIDOO_LEFT;
|
2019-11-20 11:24:36 +01:00
|
|
|
else if (TrInput & IN_RIGHT)
|
2020-09-13 15:53:37 +02:00
|
|
|
LaraItem->goalAnimState = STATE_SKIDOO_RIGHT;
|
2019-11-20 11:24:36 +01:00
|
|
|
break;
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
case STATE_SKIDOO_LEFT:
|
2019-11-20 11:24:36 +01:00
|
|
|
if (!(TrInput & IN_LEFT))
|
2020-09-13 15:53:37 +02:00
|
|
|
LaraItem->goalAnimState = STATE_SKIDOO_SIT;
|
2019-11-20 11:24:36 +01:00
|
|
|
break;
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
case STATE_SKIDOO_RIGHT:
|
2019-11-20 11:24:36 +01:00
|
|
|
if (!(TrInput & IN_RIGHT))
|
2020-09-13 15:53:37 +02:00
|
|
|
LaraItem->goalAnimState = STATE_SKIDOO_SIT;
|
2019-11-20 11:24:36 +01:00
|
|
|
break;
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
case STATE_SKIDOO_FALL:
|
|
|
|
if (skidoo->fallspeed <= 0 || skinfo->leftFallspeed <= 0 || skinfo->rightFallspeed <= 0)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-03-02 09:49:11 +01:00
|
|
|
SoundEffect(SFX_TR2_CLATTER_3, &skidoo->pos, 0);
|
2020-09-13 15:53:37 +02:00
|
|
|
LaraItem->goalAnimState = STATE_SKIDOO_SIT;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
2020-09-13 15:53:37 +02:00
|
|
|
else if (skidoo->fallspeed > DAMAGE_START + DAMAGE_LENGTH)
|
|
|
|
LaraItem->goalAnimState = STATE_SKIDOO_LETGO;
|
2019-11-20 11:24:36 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-10-02 12:55:00 -05:00
|
|
|
|
|
|
|
if (g_Level.Rooms[skidoo->roomNumber].flags & (ENV_FLAG_WATER | ENV_FLAG_SWAMP))
|
|
|
|
{
|
|
|
|
LaraItem->goalAnimState = STATE_SKIDOO_LETGO;
|
|
|
|
LaraItem->hitPoints = 0;
|
|
|
|
LaraItem->roomNumber = skidoo->roomNumber;
|
|
|
|
SkidooExplode(skidoo);
|
|
|
|
}
|
|
|
|
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
int GetSkidooCollisionAnim(ITEM_INFO* skidoo, PHD_VECTOR* moved)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
|
|
|
moved->x = skidoo->pos.xPos - moved->x;
|
|
|
|
moved->z = skidoo->pos.zPos - moved->z;
|
2020-09-13 15:53:37 +02:00
|
|
|
|
2019-11-20 11:24:36 +01:00
|
|
|
if (moved->x || moved->z)
|
|
|
|
{
|
2020-10-05 22:24:57 -03:00
|
|
|
float s = phd_sin(skidoo->pos.yRot);
|
|
|
|
float c = phd_cos(skidoo->pos.yRot);
|
2020-09-13 15:53:37 +02:00
|
|
|
|
2020-10-05 22:24:57 -03:00
|
|
|
int side = -moved->z * s + moved->x * c;
|
|
|
|
int front = moved->z * c + moved->x * s;
|
2020-09-13 15:53:37 +02:00
|
|
|
|
2019-11-20 11:24:36 +01:00
|
|
|
if (abs(front) > abs(side))
|
|
|
|
{
|
|
|
|
if (front > 0)
|
|
|
|
return SKIDOO_HIT_BACK;
|
|
|
|
else
|
|
|
|
return SKIDOO_HIT_FRONT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (side > 0)
|
|
|
|
return SKIDOO_HIT_LEFT;
|
|
|
|
else
|
|
|
|
return SKIDOO_HIT_RIGHT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
bool SkidooUserControl(ITEM_INFO* skidoo, int height, int* pitch)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
SKIDOO_INFO* skinfo = (SKIDOO_INFO*)skidoo->data;
|
|
|
|
|
|
|
|
bool drive = false;
|
|
|
|
int maxSpeed = 0;
|
2019-11-20 11:24:36 +01:00
|
|
|
|
|
|
|
if (skidoo->pos.yPos >= height - STEP_SIZE)
|
|
|
|
{
|
|
|
|
*pitch = skidoo->speed + (height - skidoo->pos.yPos);
|
|
|
|
|
|
|
|
if (skidoo->speed == 0 && (TrInput & IN_LOOK))
|
|
|
|
LookUpDown();
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
if (((TrInput & IN_LEFT)
|
|
|
|
&& !(TrInput & IN_BACK))
|
|
|
|
|| ((TrInput & IN_RIGHT)
|
|
|
|
&& (TrInput & IN_BACK)))
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
skinfo->skidooTurn -= SKIDOO_TURN;
|
|
|
|
if (skinfo->skidooTurn < -SKIDOO_MAX_TURN)
|
|
|
|
skinfo->skidooTurn = -SKIDOO_MAX_TURN;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
if (((TrInput & IN_RIGHT)
|
|
|
|
&& !(TrInput & IN_BACK))
|
|
|
|
|| ((TrInput & IN_LEFT)
|
|
|
|
&& (TrInput & IN_BACK)))
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
skinfo->skidooTurn += SKIDOO_TURN;
|
|
|
|
if (skinfo->skidooTurn > SKIDOO_MAX_TURN)
|
|
|
|
skinfo->skidooTurn = SKIDOO_MAX_TURN;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (TrInput & IN_BACK)
|
|
|
|
{
|
|
|
|
if (skidoo->speed > 0)
|
|
|
|
skidoo->speed -= SKIDOO_BRAKE;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (skidoo->speed > SKIDOO_MAX_BACK)
|
|
|
|
skidoo->speed += SKIDOO_REVERSE;
|
2020-09-13 15:53:37 +02:00
|
|
|
drive = true;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (TrInput & IN_FORWARD)
|
|
|
|
{
|
2021-03-24 20:06:37 +01:00
|
|
|
if ((TrInput & IN_ACTION) && !skinfo->armed)
|
2020-09-13 15:53:37 +02:00
|
|
|
maxSpeed = SKIDOO_FAST_SPEED;
|
2019-11-20 11:24:36 +01:00
|
|
|
else if (TrInput & IN_STEPSHIFT)
|
2020-09-13 15:53:37 +02:00
|
|
|
maxSpeed = SKIDOO_SLOW_SPEED;
|
2019-11-20 11:24:36 +01:00
|
|
|
else
|
2020-09-13 15:53:37 +02:00
|
|
|
maxSpeed = SKIDOO_MAX_SPEED;
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
if (skidoo->speed < maxSpeed)
|
|
|
|
skidoo->speed += SKIDOO_ACCELERATION / 2 + SKIDOO_ACCELERATION * skidoo->speed / (2 * maxSpeed);
|
|
|
|
else if (skidoo->speed > maxSpeed + SKIDOO_SLOWDOWN)
|
2019-11-20 11:24:36 +01:00
|
|
|
skidoo->speed -= SKIDOO_SLOWDOWN;
|
2020-09-13 15:53:37 +02:00
|
|
|
drive = true;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
2020-09-13 15:53:37 +02:00
|
|
|
else if (skidoo->speed >= 0
|
|
|
|
&& skidoo->speed < SKIDOO_MIN_SPEED
|
|
|
|
&& (TrInput & (IN_LEFT | IN_RIGHT)))
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2021-03-24 20:06:37 +01:00
|
|
|
skidoo->speed = SKIDOO_MIN_SPEED;
|
2020-09-13 15:53:37 +02:00
|
|
|
drive = true;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
else if (skidoo->speed > SKIDOO_SLOWDOWN)
|
|
|
|
{
|
|
|
|
skidoo->speed -= SKIDOO_SLOWDOWN;
|
|
|
|
if ((GetRandomControl() & 0x7f) < skidoo->speed)
|
2020-09-13 15:53:37 +02:00
|
|
|
drive = true;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
skidoo->speed = 0;
|
|
|
|
}
|
|
|
|
else if (TrInput & (IN_FORWARD | IN_BACK))
|
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
drive = true;
|
2019-11-20 11:24:36 +01:00
|
|
|
*pitch = skinfo->pitch + 50;
|
|
|
|
}
|
|
|
|
|
|
|
|
return drive;
|
|
|
|
}
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
int DoSkidooDynamics(int height, int fallspeed, int* y)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
|
|
|
int kick;
|
|
|
|
|
|
|
|
if (height > * y)
|
|
|
|
{
|
|
|
|
*y += fallspeed;
|
|
|
|
if (*y > height - SKIDOO_MIN_BOUNCE)
|
|
|
|
{
|
|
|
|
*y = height;
|
|
|
|
fallspeed = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
fallspeed += GRAVITY;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-10-02 12:55:00 -05:00
|
|
|
kick = (height - *y) * 4;
|
2019-11-20 11:24:36 +01:00
|
|
|
if (kick < SKIDOO_MAX_KICK)
|
|
|
|
kick = SKIDOO_MAX_KICK;
|
2020-10-02 12:55:00 -05:00
|
|
|
fallspeed += ((kick - fallspeed) / 8);
|
2019-11-20 11:24:36 +01:00
|
|
|
if (*y > height)
|
|
|
|
*y = height;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fallspeed;
|
|
|
|
}
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
int SkidooCheckGetOn(short itemNum, COLL_INFO* coll)
|
2021-03-24 20:06:37 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
if (!(TrInput & IN_ACTION)
|
|
|
|
|| Lara.gunStatus != LG_NO_ARMS
|
|
|
|
|| LaraItem->gravityStatus)
|
2019-11-20 11:24:36 +01:00
|
|
|
return 0;
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
ITEM_INFO* skidoo = &g_Level.Items[itemNum];
|
|
|
|
|
|
|
|
short rot = (skidoo->pos.yRot - LaraItem->pos.yRot);
|
|
|
|
int geton = 0;
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
if (rot > ANGLE(45) && rot < ANGLE(135))
|
2021-03-24 20:06:37 +01:00
|
|
|
geton = 1;
|
2020-09-13 15:53:37 +02:00
|
|
|
else if (rot > -ANGLE(135) && rot < -ANGLE(45))
|
2021-03-24 20:06:37 +01:00
|
|
|
geton = 2;
|
2019-11-20 11:24:36 +01:00
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!TestBoundsCollide(skidoo, LaraItem, coll->radius))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!TestCollision(skidoo, LaraItem))
|
|
|
|
return 0;
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
short roomNumber = skidoo->roomNumber;
|
|
|
|
FLOOR_INFO* floor = GetFloor(skidoo->pos.xPos, skidoo->pos.yPos, skidoo->pos.zPos, &roomNumber);
|
2019-11-20 11:24:36 +01:00
|
|
|
if (GetFloorHeight(floor, skidoo->pos.xPos, skidoo->pos.yPos, skidoo->pos.zPos) < -32000)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return geton;
|
|
|
|
}
|
|
|
|
|
2019-12-02 14:49:19 +01:00
|
|
|
void SkidooCollision(short itemNum, ITEM_INFO* litem, COLL_INFO* coll)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-04-27 14:01:00 +02:00
|
|
|
if (litem->hitPoints < 0 || Lara.Vehicle != NO_ITEM)
|
2019-11-20 11:24:36 +01:00
|
|
|
return;
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
int geton = SkidooCheckGetOn(itemNum, coll);
|
2019-11-20 11:24:36 +01:00
|
|
|
if (!geton)
|
|
|
|
{
|
|
|
|
ObjectCollision(itemNum, litem, coll);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-04-27 14:01:00 +02:00
|
|
|
Lara.Vehicle = itemNum;
|
2019-11-20 11:24:36 +01:00
|
|
|
|
|
|
|
if (Lara.gunType == WEAPON_FLARE)
|
|
|
|
{
|
|
|
|
CreateFlare(ID_FLARE_ITEM, FALSE);
|
2019-12-02 09:11:21 +01:00
|
|
|
undraw_flare_meshes();
|
2019-11-20 11:24:36 +01:00
|
|
|
Lara.flareControlLeft = 0;
|
|
|
|
Lara.requestGunType = WEAPON_NONE;
|
|
|
|
Lara.gunStatus = LG_NO_ARMS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (geton == 1)
|
|
|
|
litem->animNumber = Objects[ID_SNOWMOBILE_LARA_ANIMS].animIndex + SKIDOO_GETON_ANIM;
|
|
|
|
else
|
|
|
|
litem->animNumber = Objects[ID_SNOWMOBILE_LARA_ANIMS].animIndex + SKIDOO_GETONL_ANIM;
|
|
|
|
|
2020-07-21 09:56:47 +02:00
|
|
|
litem->frameNumber = g_Level.Anims[litem->animNumber].frameBase;
|
2020-09-13 15:53:37 +02:00
|
|
|
litem->currentAnimState = STATE_SKIDOO_GETON;
|
2019-11-20 11:24:36 +01:00
|
|
|
Lara.gunStatus = LG_HANDS_BUSY;
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
ITEM_INFO* skidoo = &g_Level.Items[itemNum];
|
2019-11-20 11:24:36 +01:00
|
|
|
litem->pos.yRot = skidoo->pos.yRot;
|
|
|
|
litem->pos.xPos = skidoo->pos.xPos;
|
|
|
|
litem->pos.yPos = skidoo->pos.yPos;
|
|
|
|
litem->pos.zPos = skidoo->pos.zPos;
|
|
|
|
|
|
|
|
skidoo->collidable = true;
|
|
|
|
}
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
int TestSkidooHeight(ITEM_INFO* item, int zOff, int xOff, PHD_VECTOR* pos)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-10-05 22:24:57 -03:00
|
|
|
pos->y = item->pos.yPos - zOff * phd_sin(item->pos.xRot) + xOff * phd_sin(item->pos.zRot);
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-10-05 22:24:57 -03:00
|
|
|
float s = phd_sin(item->pos.yRot);
|
|
|
|
float c = phd_cos(item->pos.yRot);
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-10-05 22:24:57 -03:00
|
|
|
pos->x = item->pos.xPos + zOff * s + xOff * c;
|
|
|
|
pos->z = item->pos.zPos + zOff * c - xOff * s;
|
2020-09-13 15:53:37 +02:00
|
|
|
|
2019-11-27 15:12:35 +01:00
|
|
|
short roomNumber = item->roomNumber;
|
2019-11-20 11:24:36 +01:00
|
|
|
FLOOR_INFO* floor = GetFloor(pos->x, pos->y, pos->z, &roomNumber);
|
2019-11-27 15:12:35 +01:00
|
|
|
int ceiling = GetCeiling(floor, pos->x, pos->y, pos->z);
|
2019-11-20 11:24:36 +01:00
|
|
|
if (pos->y < ceiling || ceiling == NO_HEIGHT)
|
|
|
|
return NO_HEIGHT;
|
|
|
|
|
|
|
|
return GetFloorHeight(floor, pos->x, pos->y, pos->z);
|
|
|
|
}
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
short DoSkidooShift(ITEM_INFO* skidoo, PHD_VECTOR* pos, PHD_VECTOR* old)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-10-06 10:36:30 -05:00
|
|
|
int x = pos->x / SECTOR(1);
|
|
|
|
int z = pos->z / SECTOR(1);
|
|
|
|
int xOld = old->x / SECTOR(1);
|
|
|
|
int zOld = old->z / SECTOR(1);
|
2020-09-13 15:53:37 +02:00
|
|
|
int shiftX = pos->x & (WALL_SIZE - 1);
|
|
|
|
int shiftZ = pos->z & (WALL_SIZE - 1);
|
|
|
|
|
|
|
|
if (x == xOld)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
if (z == zOld)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
|
|
|
skidoo->pos.zPos += (old->z - pos->z);
|
|
|
|
skidoo->pos.xPos += (old->x - pos->x);
|
|
|
|
}
|
2020-09-13 15:53:37 +02:00
|
|
|
else if (z > zOld)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
skidoo->pos.zPos -= shiftZ + 1;
|
2019-11-20 11:24:36 +01:00
|
|
|
return (pos->x - skidoo->pos.xPos);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
skidoo->pos.zPos += WALL_SIZE - shiftZ;
|
2019-11-20 11:24:36 +01:00
|
|
|
return (skidoo->pos.xPos - pos->x);
|
|
|
|
}
|
|
|
|
}
|
2020-09-13 15:53:37 +02:00
|
|
|
else if (z == zOld)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
if (x > xOld)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
skidoo->pos.xPos -= shiftX + 1;
|
2019-11-20 11:24:36 +01:00
|
|
|
return (skidoo->pos.zPos - pos->z);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
skidoo->pos.xPos += WALL_SIZE - shiftX;
|
2019-11-20 11:24:36 +01:00
|
|
|
return (pos->z - skidoo->pos.zPos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x = z = 0;
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
short roomNumber = skidoo->roomNumber;
|
|
|
|
FLOOR_INFO* floor = GetFloor(old->x, pos->y, pos->z, &roomNumber);
|
|
|
|
int height = GetFloorHeight(floor, old->x, pos->y, pos->z);
|
2019-11-20 11:24:36 +01:00
|
|
|
if (height < old->y - STEP_SIZE)
|
|
|
|
{
|
|
|
|
if (pos->z > old->z)
|
2020-09-13 15:53:37 +02:00
|
|
|
z = -shiftZ - 1;
|
2019-11-20 11:24:36 +01:00
|
|
|
else
|
2020-09-13 15:53:37 +02:00
|
|
|
z = WALL_SIZE - shiftZ;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
|
2020-04-09 14:19:18 +02:00
|
|
|
roomNumber = skidoo->roomNumber;
|
|
|
|
floor = GetFloor(pos->x, pos->y, old->z, &roomNumber);
|
2019-11-20 11:24:36 +01:00
|
|
|
height = GetFloorHeight(floor, pos->x, pos->y, old->z);
|
|
|
|
if (height < old->y - STEP_SIZE)
|
|
|
|
{
|
|
|
|
if (pos->x > old->x)
|
2020-09-13 15:53:37 +02:00
|
|
|
x = -shiftX - 1;
|
2019-11-20 11:24:36 +01:00
|
|
|
else
|
2020-09-13 15:53:37 +02:00
|
|
|
x = WALL_SIZE - shiftX;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (x && z)
|
|
|
|
{
|
|
|
|
skidoo->pos.zPos += z;
|
|
|
|
skidoo->pos.xPos += x;
|
|
|
|
skidoo->speed -= 50;
|
|
|
|
}
|
|
|
|
else if (z)
|
|
|
|
{
|
|
|
|
skidoo->pos.zPos += z;
|
|
|
|
skidoo->speed -= 50;
|
|
|
|
if (z > 0)
|
|
|
|
return (skidoo->pos.xPos - pos->x);
|
|
|
|
else
|
|
|
|
return (pos->x - skidoo->pos.xPos);
|
|
|
|
}
|
|
|
|
else if (x)
|
|
|
|
{
|
|
|
|
skidoo->pos.xPos += x;
|
|
|
|
skidoo->speed -= 50;
|
|
|
|
if (x > 0)
|
|
|
|
return (pos->z - skidoo->pos.zPos);
|
|
|
|
else
|
|
|
|
return (skidoo->pos.zPos - pos->z);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
skidoo->pos.zPos += (old->z - pos->z);
|
|
|
|
skidoo->pos.xPos += (old->x - pos->x);
|
|
|
|
skidoo->speed -= 50;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
int SkidooDynamics(ITEM_INFO* skidoo)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
|
|
|
PHD_VECTOR moved, fl, fr, br, bl;
|
2020-09-13 15:53:37 +02:00
|
|
|
PHD_VECTOR old, flOld, frOld, blOld, brOld;
|
|
|
|
|
|
|
|
SKIDOO_INFO* skinfo = (SKIDOO_INFO*)skidoo->data;
|
|
|
|
|
|
|
|
int hflOld = TestSkidooHeight(skidoo, SKIDOO_FRONT, -SKIDOO_SIDE, &flOld);
|
|
|
|
int hfrOld = TestSkidooHeight(skidoo, SKIDOO_FRONT, SKIDOO_SIDE, &frOld);
|
|
|
|
int hblOld = TestSkidooHeight(skidoo, -SKIDOO_FRONT, -SKIDOO_SIDE, &blOld);
|
|
|
|
int hbrOld = TestSkidooHeight(skidoo, -SKIDOO_FRONT, SKIDOO_SIDE, &brOld);
|
2019-11-20 11:24:36 +01:00
|
|
|
old.x = skidoo->pos.xPos;
|
|
|
|
old.y = skidoo->pos.yPos;
|
|
|
|
old.z = skidoo->pos.zPos;
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
if (blOld.y > hblOld)
|
|
|
|
blOld.y = hblOld;
|
|
|
|
if (brOld.y > hbrOld)
|
|
|
|
brOld.y = hbrOld;
|
|
|
|
if (flOld.y > hflOld)
|
|
|
|
flOld.y = hflOld;
|
|
|
|
if (frOld.y > hfrOld)
|
|
|
|
frOld.y = hfrOld;
|
|
|
|
|
|
|
|
short rot;
|
|
|
|
|
2019-11-20 11:24:36 +01:00
|
|
|
if (skidoo->pos.yPos > skidoo->floor - STEP_SIZE)
|
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
if (skinfo->skidooTurn < -SKIDOO_UNDO_TURN)
|
|
|
|
skinfo->skidooTurn += SKIDOO_UNDO_TURN;
|
|
|
|
else if (skinfo->skidooTurn > SKIDOO_UNDO_TURN)
|
|
|
|
skinfo->skidooTurn -= SKIDOO_UNDO_TURN;
|
2019-11-20 11:24:36 +01:00
|
|
|
else
|
2020-09-13 15:53:37 +02:00
|
|
|
skinfo->skidooTurn = 0;
|
|
|
|
skidoo->pos.yRot += skinfo->skidooTurn + skinfo->extraRotation;
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
rot = skidoo->pos.yRot - skinfo->momentumAngle;
|
2019-11-20 11:24:36 +01:00
|
|
|
if (rot < -SKIDOO_MOMENTUM_TURN)
|
|
|
|
{
|
|
|
|
if (rot < -SKIDOO_MAX_MOM_TURN)
|
|
|
|
{
|
|
|
|
rot = -SKIDOO_MAX_MOM_TURN;
|
2020-09-13 15:53:37 +02:00
|
|
|
skinfo->momentumAngle = skidoo->pos.yRot - rot;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
else
|
2020-09-13 15:53:37 +02:00
|
|
|
skinfo->momentumAngle -= SKIDOO_MOMENTUM_TURN;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
else if (rot > SKIDOO_MOMENTUM_TURN)
|
|
|
|
{
|
|
|
|
if (rot > SKIDOO_MAX_MOM_TURN)
|
|
|
|
{
|
|
|
|
rot = SKIDOO_MAX_MOM_TURN;
|
2020-09-13 15:53:37 +02:00
|
|
|
skinfo->momentumAngle = skidoo->pos.yRot - rot;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
else
|
2020-09-13 15:53:37 +02:00
|
|
|
skinfo->momentumAngle += SKIDOO_MOMENTUM_TURN;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
else
|
2020-09-13 15:53:37 +02:00
|
|
|
skinfo->momentumAngle = skidoo->pos.yRot;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
else
|
2020-09-13 15:53:37 +02:00
|
|
|
skidoo->pos.yRot += skinfo->skidooTurn + skinfo->extraRotation;
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-10-05 22:24:57 -03:00
|
|
|
skidoo->pos.zPos += skidoo->speed * phd_cos(skinfo->momentumAngle);
|
|
|
|
skidoo->pos.xPos += skidoo->speed * phd_sin(skinfo->momentumAngle);
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-10-05 22:24:57 -03:00
|
|
|
int slip = SKIDOO_SLIP * phd_sin(skidoo->pos.xRot);
|
2019-11-20 11:24:36 +01:00
|
|
|
if (abs(slip) > SKIDOO_SLIP / 2)
|
|
|
|
{
|
2020-10-05 22:24:57 -03:00
|
|
|
skidoo->pos.zPos -= slip * phd_cos(skidoo->pos.yRot);
|
|
|
|
skidoo->pos.xPos -= slip * phd_sin(skidoo->pos.yRot);
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
|
2020-10-05 22:24:57 -03:00
|
|
|
slip = SKIDOO_SLIP_SIDE * phd_sin(skidoo->pos.zRot);
|
2019-11-20 11:24:36 +01:00
|
|
|
if (abs(slip) > SKIDOO_SLIP_SIDE / 2)
|
|
|
|
{
|
2020-10-05 22:24:57 -03:00
|
|
|
skidoo->pos.zPos -= slip * phd_sin(skidoo->pos.yRot);
|
|
|
|
skidoo->pos.xPos += slip * phd_cos(skidoo->pos.yRot);
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
moved.x = skidoo->pos.xPos;
|
|
|
|
moved.z = skidoo->pos.zPos;
|
|
|
|
|
2021-03-24 20:06:37 +01:00
|
|
|
if (!(skidoo->flags & ONESHOT))
|
2020-09-09 15:10:16 -05:00
|
|
|
SkidooBaddieCollision(skidoo);
|
2019-11-20 11:24:36 +01:00
|
|
|
|
|
|
|
rot = 0;
|
2020-09-13 15:53:37 +02:00
|
|
|
int hbl = TestSkidooHeight(skidoo, -SKIDOO_FRONT, -SKIDOO_SIDE, &bl);
|
|
|
|
if (hbl < blOld.y - STEP_SIZE)
|
|
|
|
rot = DoSkidooShift(skidoo, &bl, &blOld);
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
int hbr = TestSkidooHeight(skidoo, -SKIDOO_FRONT, SKIDOO_SIDE, &br);
|
|
|
|
if (hbr < brOld.y - STEP_SIZE)
|
|
|
|
rot += DoSkidooShift(skidoo, &br, &brOld);
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
int hfl = TestSkidooHeight(skidoo, SKIDOO_FRONT, -SKIDOO_SIDE, &fl);
|
|
|
|
if (hfl < flOld.y - STEP_SIZE)
|
|
|
|
rot += DoSkidooShift(skidoo, &fl, &flOld);
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
int hfr = TestSkidooHeight(skidoo, SKIDOO_FRONT, SKIDOO_SIDE, &fr);
|
|
|
|
if (hfr < frOld.y - STEP_SIZE)
|
|
|
|
rot += DoSkidooShift(skidoo, &fr, &frOld);
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
short roomNumber = skidoo->roomNumber;
|
|
|
|
FLOOR_INFO* floor = GetFloor(skidoo->pos.xPos, skidoo->pos.yPos, skidoo->pos.zPos, &roomNumber);
|
|
|
|
int height = GetFloorHeight(floor, skidoo->pos.xPos, skidoo->pos.yPos, skidoo->pos.zPos);
|
2019-11-20 11:24:36 +01:00
|
|
|
if (height < skidoo->pos.yPos - STEP_SIZE)
|
|
|
|
DoSkidooShift(skidoo, (PHD_VECTOR*)&skidoo->pos, &old);
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
skinfo->extraRotation = rot;
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
int collide = GetSkidooCollisionAnim(skidoo, &moved);
|
2019-11-20 11:24:36 +01:00
|
|
|
|
|
|
|
if (collide)
|
|
|
|
{
|
2020-10-05 22:24:57 -03:00
|
|
|
int newspeed = (skidoo->pos.zPos - old.z) * phd_cos(skinfo->momentumAngle) + (skidoo->pos.xPos - old.x) * phd_sin(skinfo->momentumAngle);
|
2019-11-20 11:24:36 +01:00
|
|
|
if (skidoo->speed > SKIDOO_MAX_SPEED + SKIDOO_ACCELERATION && newspeed < skidoo->speed - 10)
|
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
LaraItem->hitPoints -= (skidoo->speed - newspeed) / 2;
|
2019-11-20 11:24:36 +01:00
|
|
|
LaraItem->hitStatus = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (skidoo->speed > 0 && newspeed < skidoo->speed)
|
|
|
|
skidoo->speed = (newspeed < 0) ? 0 : newspeed;
|
|
|
|
else if (skidoo->speed < 0 && newspeed > skidoo->speed)
|
|
|
|
skidoo->speed = (newspeed > 0) ? 0 : newspeed;
|
|
|
|
|
|
|
|
if (skidoo->speed < SKIDOO_MAX_BACK)
|
|
|
|
skidoo->speed = SKIDOO_MAX_BACK;
|
|
|
|
}
|
|
|
|
|
|
|
|
return collide;
|
|
|
|
}
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
bool SkidooControl()
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
|
|
|
PHD_VECTOR fl, fr;
|
2020-09-13 15:53:37 +02:00
|
|
|
|
|
|
|
ITEM_INFO* skidoo = &g_Level.Items[Lara.Vehicle];
|
|
|
|
SKIDOO_INFO* skinfo = (SKIDOO_INFO*)skidoo->data;
|
|
|
|
int collide = SkidooDynamics(skidoo);
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
int hfl = TestSkidooHeight(skidoo, SKIDOO_FRONT, -SKIDOO_SIDE, &fl);
|
|
|
|
int hfr = TestSkidooHeight(skidoo, SKIDOO_FRONT, SKIDOO_SIDE, &fr);
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
short roomNumber = skidoo->roomNumber;
|
|
|
|
FLOOR_INFO* floor = GetFloor(skidoo->pos.xPos, skidoo->pos.yPos, skidoo->pos.zPos, &roomNumber);
|
|
|
|
int height = GetFloorHeight(floor, skidoo->pos.xPos, skidoo->pos.yPos, skidoo->pos.zPos);
|
2019-11-20 11:24:36 +01:00
|
|
|
|
|
|
|
TestTriggers(TriggerIndex, 0, 0);
|
|
|
|
TestTriggers(TriggerIndex, 1, 0);
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
bool dead = false;
|
|
|
|
int drive = 0;
|
|
|
|
|
2019-11-20 11:24:36 +01:00
|
|
|
if (LaraItem->hitPoints <= 0)
|
|
|
|
{
|
|
|
|
TrInput &= ~(IN_LEFT | IN_RIGHT | IN_BACK | IN_FORWARD);
|
2020-09-13 15:53:37 +02:00
|
|
|
dead = true;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
2020-09-13 15:53:37 +02:00
|
|
|
else if (LaraItem->currentAnimState == STATE_SKIDOO_LETGO)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
dead = true;
|
2019-11-20 11:24:36 +01:00
|
|
|
collide = 0;
|
|
|
|
}
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
int pitch = 0;
|
|
|
|
|
2019-11-20 11:24:36 +01:00
|
|
|
if (skidoo->flags & ONESHOT)
|
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
drive = false;
|
2019-11-20 11:24:36 +01:00
|
|
|
collide = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (LaraItem->currentAnimState)
|
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
case STATE_SKIDOO_GETON:
|
|
|
|
case STATE_SKIDOO_GETOFF:
|
|
|
|
case STATE_SKIDOO_GETOFFL:
|
|
|
|
case STATE_SKIDOO_LETGO:
|
2019-11-20 11:24:36 +01:00
|
|
|
drive = -1;
|
|
|
|
collide = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
drive = SkidooUserControl(skidoo, height, &pitch);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
bool banditSkidoo = skinfo->armed;
|
2019-11-20 11:24:36 +01:00
|
|
|
if (drive > 0)
|
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
skinfo->trackMesh = ((skinfo->trackMesh & 3) == 1) ? 2 : 1;
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
skinfo->pitch += (pitch - skinfo->pitch) / 4;
|
2021-05-26 06:04:32 +02:00
|
|
|
SoundEffect(SFX_TR2_SKIDOO_ACCELERATE, &skidoo->pos, 4 + ((0x10000 - (SKIDOO_MAX_SPEED - skinfo->pitch) * 100) * 256));
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-09-13 15:53:37 +02:00
|
|
|
skinfo->trackMesh = 0;
|
2019-11-20 11:24:36 +01:00
|
|
|
if (!drive)
|
2021-05-26 06:04:32 +02:00
|
|
|
SoundEffect(SFX_TR2_SKIDOO_IDLE, &skidoo->pos, 0);
|
2019-11-20 11:24:36 +01:00
|
|
|
skinfo->pitch = 0;
|
|
|
|
}
|
|
|
|
skidoo->floor = height;
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
skinfo->leftFallspeed = DoSkidooDynamics(hfl, skinfo->leftFallspeed, (int*)&fl.y);
|
|
|
|
skinfo->rightFallspeed = DoSkidooDynamics(hfr, skinfo->rightFallspeed, (int*)&fr.y);
|
2019-11-20 11:24:36 +01:00
|
|
|
skidoo->fallspeed = DoSkidooDynamics(height, skidoo->fallspeed, (int*)&skidoo->pos.yPos);
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
height = (fl.y + fr.y) / 2;
|
|
|
|
short xRot = phd_atan(SKIDOO_FRONT, skidoo->pos.yPos - height);
|
|
|
|
short zRot = phd_atan(SKIDOO_SIDE, height - fl.y);
|
2019-11-20 11:24:36 +01:00
|
|
|
|
2020-10-06 10:36:30 -05:00
|
|
|
skidoo->pos.xRot += ((xRot - skidoo->pos.xRot) / 2);
|
|
|
|
skidoo->pos.zRot += ((zRot - skidoo->pos.zRot) / 2);
|
2019-11-20 11:24:36 +01:00
|
|
|
|
|
|
|
if (skidoo->flags & ONESHOT)
|
|
|
|
{
|
2020-04-09 14:19:18 +02:00
|
|
|
if (roomNumber != skidoo->roomNumber)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-04-27 14:01:00 +02:00
|
|
|
ItemNewRoom(Lara.Vehicle, roomNumber);
|
2020-04-09 14:19:18 +02:00
|
|
|
ItemNewRoom(Lara.itemNumber, roomNumber);
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
AnimateItem(LaraItem);
|
|
|
|
|
|
|
|
if (skidoo->pos.yPos == skidoo->floor)
|
|
|
|
SkidooExplode(skidoo);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
SkidooAnimation(skidoo, collide, dead);
|
|
|
|
|
2020-04-09 14:19:18 +02:00
|
|
|
if (roomNumber != skidoo->roomNumber)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2020-04-27 14:01:00 +02:00
|
|
|
ItemNewRoom(Lara.Vehicle, roomNumber);
|
2020-04-09 14:19:18 +02:00
|
|
|
ItemNewRoom(Lara.itemNumber, roomNumber);
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
if (LaraItem->currentAnimState != STATE_SKIDOO_FALLOFF)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
|
|
|
LaraItem->pos.xPos = skidoo->pos.xPos;
|
|
|
|
LaraItem->pos.yPos = skidoo->pos.yPos;
|
|
|
|
LaraItem->pos.zPos = skidoo->pos.zPos;
|
|
|
|
LaraItem->pos.yRot = skidoo->pos.yRot;
|
|
|
|
if (drive >= 0)
|
|
|
|
{
|
|
|
|
LaraItem->pos.xRot = skidoo->pos.xRot;
|
|
|
|
LaraItem->pos.zRot = skidoo->pos.zRot;
|
|
|
|
}
|
|
|
|
else
|
2021-03-24 20:06:37 +01:00
|
|
|
|
2019-11-20 11:24:36 +01:00
|
|
|
LaraItem->pos.xRot = LaraItem->pos.zRot = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
LaraItem->pos.xRot = LaraItem->pos.zRot = 0;
|
|
|
|
|
|
|
|
AnimateItem(LaraItem);
|
|
|
|
|
2020-09-13 15:53:37 +02:00
|
|
|
if (!dead && drive >= 0 && banditSkidoo)
|
2019-11-20 11:24:36 +01:00
|
|
|
SkidooGuns();
|
|
|
|
|
|
|
|
if (!dead)
|
|
|
|
{
|
|
|
|
skidoo->animNumber = Objects[ID_SNOWMOBILE].animIndex + (LaraItem->animNumber - Objects[ID_SNOWMOBILE_LARA_ANIMS].animIndex);
|
2020-07-21 09:56:47 +02:00
|
|
|
skidoo->frameNumber = g_Level.Anims[skidoo->animNumber].frameBase + (LaraItem->frameNumber - g_Level.Anims[LaraItem->animNumber].frameBase);
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
skidoo->animNumber = Objects[ID_SNOWMOBILE].animIndex + SKIDOO_DEAD_ANIM;
|
2020-07-21 09:56:47 +02:00
|
|
|
skidoo->frameNumber = g_Level.Anims[skidoo->animNumber].frameBase;
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|
|
|
|
|
2021-03-24 20:06:37 +01:00
|
|
|
if (skidoo->speed && skidoo->floor == skidoo->pos.yPos)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
|
|
|
DoSnowEffect(skidoo);
|
|
|
|
if (skidoo->speed < 50)
|
|
|
|
DoSnowEffect(skidoo);
|
|
|
|
}
|
|
|
|
|
|
|
|
return SkidooCheckGetOff();
|
|
|
|
}
|
|
|
|
|
2019-12-02 14:49:19 +01:00
|
|
|
void DrawSkidoo(ITEM_INFO* item)
|
2019-11-20 11:24:36 +01:00
|
|
|
{
|
2019-11-26 15:55:37 +01:00
|
|
|
|
2019-11-20 11:24:36 +01:00
|
|
|
}
|