mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-05-02 09:47:58 +03:00
1100 lines
28 KiB
C++
1100 lines
28 KiB
C++
#include "framework.h"
|
|
#include "snowmobile.h"
|
|
#include "lara.h"
|
|
#include "items.h"
|
|
#include "collide.h"
|
|
#include "lara_fire.h"
|
|
#include "lara_one_gun.h"
|
|
#include "effects/effects.h"
|
|
#include "lara_flare.h"
|
|
#include "effects/tomb4fx.h"
|
|
#include "sphere.h"
|
|
#include "setup.h"
|
|
#include "level.h"
|
|
#include "input.h"
|
|
#include "animation.h"
|
|
#include "Sound/sound.h"
|
|
#include "particle/SimpleParticle.h"
|
|
#include "Specific/prng.h"
|
|
#include "camera.h"
|
|
#include "skidoo_info.h"
|
|
|
|
using std::vector;
|
|
using namespace TEN::Math::Random;
|
|
|
|
#define DAMAGE_START 140
|
|
#define DAMAGE_LENGTH 14
|
|
|
|
#define SKIDOO_DISMOUNT_DIST 295
|
|
|
|
#define SKIDOO_UNDO_TURN ANGLE(2.0f)
|
|
#define SKIDOO_TURN ((ANGLE(1.0f) / 2) + SKIDOO_UNDO_TURN)
|
|
#define SKIDOO_MAX_TURN ANGLE(6.0f)
|
|
#define SKIDOO_MOMENTUM_TURN ANGLE(3.0f)
|
|
#define SKIDOO_MAX_MOM_TURN ANGLE(150.0f)
|
|
|
|
#define SKIDOO_FAST_SPEED 150
|
|
#define SKIDOO_MAX_SPEED 100
|
|
#define SKIDOO_SLOW_SPEED 50
|
|
#define SKIDOO_MIN_SPEED 15
|
|
|
|
#define SKIDOO_ACCELERATION 10
|
|
#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
|
|
#define SKIDOO_MIN_BOUNCE ((SKIDOO_MAX_SPEED / 2) / 256)
|
|
|
|
#define SKIDOO_IN_FIRE IN_ACTION
|
|
#define SKIDOO_IN_DISMOUNT (IN_JUMP | IN_ROLL)
|
|
#define SKIDOO_IN_SLOW IN_WALK
|
|
#define SKIDOO_IN_ACCELERATE IN_FORWARD
|
|
#define SKIDOO_IN_BRAKE IN_BACK
|
|
#define SKIDOO_IN_LEFT IN_LEFT
|
|
#define SKIDOO_IN_RIGHT IN_RIGHT
|
|
|
|
enum SkidooState
|
|
{
|
|
SKIDOO_STATE_SIT,
|
|
SKIDOO_STATE_MOUNT,
|
|
SKIDOO_STATE_LEFT,
|
|
SKIDOO_STATE_RIGHT,
|
|
SKIDOO_STATE_FALL,
|
|
SKIDOO_STATE_HIT,
|
|
SKIDOO_STATE_MOUNT_LEFT,
|
|
SKIDOO_STATE_DISMOUNT_RIGHT_LEFT,
|
|
SKIDOO_STATE_IDLE,
|
|
SKIDOO_STATE_DISMOUNT_RIGHT,
|
|
SKIDOO_STATE_JUMP_OFF,
|
|
SKIDOO_STATE_DEATH,
|
|
SKIDOO_STATE_FALLOFF
|
|
};
|
|
|
|
enum SkidooAnim
|
|
{
|
|
SKIDOO_ANIM_DRIVE = 0,
|
|
SKIDOO_ANIM_MOUNT_RIGHT = 1,
|
|
SKIDOO_ANIM_TURN_LEFT_START = 2,
|
|
SKIDOO_ANIM_TURN_LEFT_CONTINUE = 3,
|
|
SKIDOO_ANIM_TURN_LEFT_END = 4,
|
|
SKIDOO_ANIM_TURN_RIGHT_START = 5,
|
|
SKIDOO_ANIM_TURN_RIGHT_CONTINUE = 6,
|
|
SKIDOO_ANIM_TURN_RIGHT_END = 7,
|
|
SKIDOO_ANIM_LEAP_START = 8,
|
|
SKIDOO_ANIM_LEAP_END = 9,
|
|
SKIDOO_ANIM_LEAP_CONTINUE = 10,
|
|
SKIDOO_ANIM_HIT_LEFT = 11,
|
|
SKIDOO_ANIM_HIT_RIGHT = 12,
|
|
SKIDOO_ANIM_HIT_FRONT = 13,
|
|
SKIDOO_ANIM_HIT_BACK = 14,
|
|
SKIDOO_ANIM_IDLE = 15,
|
|
SKIDOO_ANIM_DISMOUNT_RIGHT = 16,
|
|
SKIDOO_ANIM_UNK = 17, // TODO
|
|
SKIDOO_ANIM_MOUNT_LEFT = 18,
|
|
SKIDOO_ANIM_DISMOUNT_LEFT = 19,
|
|
SKIDOO_ANIM_FALL_OFF = 20,
|
|
SKIDOO_ANIM_IDLE_DEATH = 21,
|
|
SKIDOO_ANIM_FALL_DEATH = 22
|
|
};
|
|
|
|
// TODO
|
|
enum SkidooMountType
|
|
{
|
|
SKIDOO_MOUNT_NONE = 0,
|
|
SKIDOO_MOUNT_RIGHT = 1,
|
|
SKIDOO_MOUNT_LEFT = 2
|
|
};
|
|
|
|
void InitialiseSkidoo(short itemNum)
|
|
{
|
|
ITEM_INFO* skidoo = &g_Level.Items[itemNum];
|
|
skidoo->data = SKIDOO_INFO();
|
|
auto skidooInfo = (SKIDOO_INFO*)skidoo->data;
|
|
|
|
skidooInfo->alreadyCdPlayed = false;
|
|
|
|
if (skidoo->objectNumber == ID_SNOWMOBILE_GUN)
|
|
skidooInfo->armed = true;
|
|
else
|
|
skidooInfo->armed = false;
|
|
|
|
skidooInfo->extraRotation = 0;
|
|
skidooInfo->flashTimer = 0;
|
|
skidooInfo->leftFallspeed = 0;
|
|
skidooInfo->momentumAngle = skidoo->pos.yRot;
|
|
skidooInfo->pitch = 0;
|
|
skidooInfo->rightFallspeed = 0;
|
|
skidooInfo->skidooTurn = 0;
|
|
|
|
if (skidoo->status != ITEM_ACTIVE)
|
|
{
|
|
AddActiveItem(itemNum);
|
|
skidoo->status = ITEM_ACTIVE;
|
|
}
|
|
}
|
|
|
|
void SkidooBaddieCollision(ITEM_INFO* skidoo)
|
|
{
|
|
int x, y, z, i;
|
|
|
|
vector<short> roomsList;
|
|
roomsList.push_back(skidoo->roomNumber);
|
|
|
|
ROOM_INFO* room = &g_Level.Rooms[skidoo->roomNumber];
|
|
for (i = 0; i < room->doors.size(); i++)
|
|
{
|
|
roomsList.push_back(room->doors[i].room);
|
|
}
|
|
|
|
for (int i = 0; i < roomsList.size(); i++)
|
|
{
|
|
short itemNum = g_Level.Rooms[roomsList[i]].itemNumber;
|
|
|
|
while (itemNum != NO_ITEM)
|
|
{
|
|
ITEM_INFO* item = &g_Level.Items[itemNum];
|
|
|
|
if (item->collidable && item->status != IFLAG_INVISIBLE && item != LaraItem && item != skidoo)
|
|
{
|
|
OBJECT_INFO* object = &Objects[item->objectNumber];
|
|
|
|
if (object->collision && (object->intelligent))
|
|
{
|
|
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)
|
|
{
|
|
if (item->objectNumber == ID_ROLLINGBALL)
|
|
{
|
|
if (TestBoundsCollide(item, LaraItem, 100))
|
|
{
|
|
if (LaraItem->hitPoints > 0)
|
|
{
|
|
DoLotsOfBlood(LaraItem->pos.xPos, LaraItem->pos.yPos - (STEP_SIZE * 2), LaraItem->pos.zPos, GetRandomControl() & 3, LaraItem->pos.yRot, LaraItem->roomNumber, 5);
|
|
item->hitPoints -= 8;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (TestBoundsCollide(item, skidoo, SKIDOO_FRONT))
|
|
{
|
|
DoLotsOfBlood(skidoo->pos.xPos, skidoo->pos.yPos, skidoo->pos.zPos, GetRandomControl() & 3, LaraItem->pos.yRot, LaraItem->roomNumber, 3);
|
|
item->hitPoints = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
itemNum = item->nextItem;
|
|
}
|
|
}
|
|
}
|
|
|
|
void SkidooGuns(ITEM_INFO* lara, ITEM_INFO* skidoo)
|
|
{
|
|
LaraInfo*& laraInfo = lara->data;
|
|
SKIDOO_INFO* skidooInfo = (SKIDOO_INFO*)skidoo->data;
|
|
WEAPON_INFO* wepInfo = &Weapons[WEAPON_SNOWMOBILE];
|
|
|
|
LaraGetNewTarget(wepInfo);
|
|
AimWeapon(wepInfo, &laraInfo->rightArm);
|
|
|
|
if (TrInput & SKIDOO_IN_FIRE && !skidoo->itemFlags[0])
|
|
{
|
|
short angles[] = {
|
|
laraInfo->rightArm.yRot + lara->pos.yRot,
|
|
laraInfo->rightArm.xRot
|
|
};
|
|
|
|
if (FireWeapon(WEAPON_PISTOLS, laraInfo->target, lara, angles) +
|
|
FireWeapon(WEAPON_PISTOLS, laraInfo->target, lara, angles))
|
|
{
|
|
skidooInfo->flashTimer = 2;
|
|
SoundEffect(wepInfo->sampleNum, &lara->pos, 0);
|
|
skidoo->itemFlags[0] = 4;
|
|
}
|
|
}
|
|
|
|
if (skidoo->itemFlags[0])
|
|
skidoo->itemFlags[0]--;
|
|
}
|
|
|
|
void SkidooExplode(ITEM_INFO* lara, ITEM_INFO* skidoo)
|
|
{
|
|
LaraInfo*& laraInfo = lara->data;
|
|
|
|
if (g_Level.Rooms[skidoo->roomNumber].flags & ENV_FLAG_WATER)
|
|
TriggerUnderwaterExplosion(skidoo, 1);
|
|
else
|
|
{
|
|
TriggerExplosionSparks(skidoo->pos.xPos, skidoo->pos.yPos, skidoo->pos.zPos, 3, -2, 0, skidoo->roomNumber);
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
TriggerExplosionSparks(skidoo->pos.xPos, skidoo->pos.yPos, skidoo->pos.zPos, 3, -1, 0, skidoo->roomNumber);
|
|
}
|
|
|
|
auto pos = PHD_3DPOS(skidoo->pos.xPos, skidoo->pos.yPos - 128, skidoo->pos.zPos, 0, skidoo->pos.yRot, 0);
|
|
TriggerShockwave(&pos, 50, 180, 40, GenerateFloat(160, 200), 60, 60, 64, GenerateFloat(0, 359), 0);
|
|
//ExplodingDeath(laraInfo->Vehicle, -1, 256);
|
|
KillItem(laraInfo->Vehicle);
|
|
skidoo->status = ITEM_DEACTIVATED;
|
|
|
|
SoundEffect(SFX_TR4_EXPLOSION1, 0, 0);
|
|
SoundEffect(SFX_TR4_EXPLOSION2, 0, 0);
|
|
|
|
laraInfo->Vehicle = NO_ITEM;
|
|
}
|
|
|
|
bool SkidooCheckGetOffOK(ITEM_INFO* skidoo, int dir)
|
|
{
|
|
short angle;
|
|
if (dir == SKIDOO_STATE_DISMOUNT_RIGHT_LEFT)
|
|
angle = skidoo->pos.yRot + ANGLE(90.0f);
|
|
else
|
|
angle = skidoo->pos.yRot - ANGLE(90.0f);
|
|
|
|
int x = skidoo->pos.xPos - SKIDOO_DISMOUNT_DIST * phd_sin(angle);
|
|
int y = skidoo->pos.yPos;
|
|
int z = skidoo->pos.zPos - SKIDOO_DISMOUNT_DIST * phd_cos(angle);
|
|
auto probe = GetCollisionResult(x, y, z, skidoo->roomNumber);
|
|
|
|
if ((probe.Position.Slope || probe.Position.Floor == NO_HEIGHT) ||
|
|
abs(probe.Position.Floor - skidoo->pos.yPos) > (WALL_SIZE / 2) ||
|
|
((probe.Position.Ceiling - skidoo->pos.yPos) > -LARA_HEIGHT || (probe.Position.Floor - probe.Position.Ceiling) < LARA_HEIGHT))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool SkidooCheckGetOff(ITEM_INFO* lara, ITEM_INFO* skidoo)
|
|
{
|
|
LaraInfo*& laraInfo = lara->data;
|
|
|
|
if (laraInfo->Vehicle != NO_ITEM)
|
|
{
|
|
if ((lara->currentAnimState == SKIDOO_STATE_DISMOUNT_RIGHT || lara->currentAnimState == SKIDOO_STATE_DISMOUNT_RIGHT_LEFT) &&
|
|
lara->frameNumber == g_Level.Anims[lara->animNumber].frameEnd)
|
|
{
|
|
if (lara->currentAnimState == SKIDOO_STATE_DISMOUNT_RIGHT_LEFT)
|
|
lara->pos.yRot += ANGLE(90.0f);
|
|
else
|
|
lara->pos.yRot -= ANGLE(90.0f);
|
|
|
|
SetAnimation(lara, LA_STAND_IDLE);
|
|
lara->pos.xPos -= SKIDOO_DISMOUNT_DIST * phd_sin(lara->pos.yRot);
|
|
lara->pos.zPos -= SKIDOO_DISMOUNT_DIST * phd_cos(lara->pos.yRot);
|
|
lara->pos.xRot = 0;
|
|
lara->pos.zRot = 0;
|
|
laraInfo->Vehicle = NO_ITEM;
|
|
laraInfo->gunStatus = LG_NO_ARMS;
|
|
}
|
|
else if (lara->currentAnimState == SKIDOO_STATE_JUMP_OFF &&
|
|
(skidoo->pos.yPos == skidoo->floor || TestLastFrame(lara, lara->animNumber)))
|
|
{
|
|
SetAnimation(lara, LA_FREEFALL);
|
|
|
|
if (skidoo->pos.yPos == skidoo->floor)
|
|
{
|
|
lara->goalAnimState = LS_DEATH;
|
|
lara->fallspeed = DAMAGE_START + DAMAGE_LENGTH;
|
|
lara->speed = 0;
|
|
SkidooExplode(lara, skidoo);
|
|
}
|
|
else
|
|
{
|
|
lara->goalAnimState = LS_FREEFALL;
|
|
lara->pos.yPos -= 200;
|
|
lara->fallspeed = skidoo->fallspeed;
|
|
lara->speed = skidoo->speed;
|
|
SoundEffect(SFX_TR4_LARA_FALL, &lara->pos, 0);
|
|
}
|
|
|
|
lara->pos.xRot = 0;
|
|
lara->pos.zRot = 0;
|
|
lara->gravityStatus = true;
|
|
laraInfo->gunStatus = LG_NO_ARMS;
|
|
laraInfo->moveAngle = skidoo->pos.yRot;
|
|
skidoo->flags |= ONESHOT;
|
|
skidoo->collidable = false;
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else
|
|
return true;
|
|
}
|
|
|
|
void DoSnowEffect(ITEM_INFO* skidoo)
|
|
{
|
|
auto material = GetCollisionResult(skidoo).BottomBlock->Material;
|
|
if (material != FLOOR_MATERIAL::Ice && material != FLOOR_MATERIAL::Snow)
|
|
return;
|
|
|
|
TEN::Effects::TriggerSnowmobileSnow(skidoo);
|
|
}
|
|
|
|
void SkidooAnimation(ITEM_INFO* lara, ITEM_INFO* skidoo, int collide, bool dead)
|
|
{
|
|
SKIDOO_INFO* skidooInfo = (SKIDOO_INFO*)skidoo->data;
|
|
|
|
if (skidoo->pos.yPos != skidoo->floor &&
|
|
skidoo->fallspeed > 0 &&
|
|
lara->currentAnimState != SKIDOO_STATE_FALL &&
|
|
!dead)
|
|
{
|
|
lara->animNumber = Objects[ID_SNOWMOBILE_LARA_ANIMS].animIndex + SKIDOO_ANIM_LEAP_START;
|
|
lara->frameNumber = g_Level.Anims[lara->animNumber].frameBase;
|
|
lara->currentAnimState = SKIDOO_STATE_FALL;
|
|
lara->goalAnimState = SKIDOO_STATE_FALL;
|
|
}
|
|
else if (collide &&
|
|
!dead &&
|
|
lara->currentAnimState != SKIDOO_STATE_FALL)
|
|
{
|
|
if (lara->currentAnimState != SKIDOO_STATE_HIT)
|
|
{
|
|
if (collide == SKIDOO_ANIM_HIT_FRONT)
|
|
SoundEffect(SFX_TR2_CLATTER_1, &skidoo->pos, 0);
|
|
else
|
|
SoundEffect(SFX_TR2_CLATTER_2, &skidoo->pos, 0);
|
|
|
|
lara->animNumber = (short)(Objects[ID_SNOWMOBILE_LARA_ANIMS].animIndex + collide);
|
|
lara->frameNumber = g_Level.Anims[lara->animNumber].frameBase;
|
|
lara->currentAnimState = lara->goalAnimState = SKIDOO_STATE_HIT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (lara->currentAnimState)
|
|
{
|
|
case SKIDOO_STATE_IDLE:
|
|
|
|
if (dead)
|
|
{
|
|
lara->goalAnimState = SKIDOO_STATE_DEATH;
|
|
|
|
break;
|
|
}
|
|
|
|
lara->goalAnimState = SKIDOO_STATE_IDLE;
|
|
|
|
if (TrInput & SKIDOO_IN_DISMOUNT)
|
|
{
|
|
if (TrInput & SKIDOO_IN_RIGHT &&
|
|
SkidooCheckGetOffOK(skidoo, SKIDOO_STATE_DISMOUNT_RIGHT))
|
|
{
|
|
lara->goalAnimState = SKIDOO_STATE_DISMOUNT_RIGHT;
|
|
skidoo->speed = 0;
|
|
}
|
|
else if (TrInput & SKIDOO_IN_LEFT &&
|
|
SkidooCheckGetOffOK(skidoo, SKIDOO_STATE_DISMOUNT_RIGHT_LEFT))
|
|
{
|
|
lara->goalAnimState = SKIDOO_STATE_DISMOUNT_RIGHT_LEFT;
|
|
skidoo->speed = 0;
|
|
}
|
|
}
|
|
else if (TrInput & SKIDOO_IN_LEFT)
|
|
lara->goalAnimState = SKIDOO_STATE_LEFT;
|
|
else if (TrInput & SKIDOO_IN_RIGHT)
|
|
lara->goalAnimState = SKIDOO_STATE_RIGHT;
|
|
else if (TrInput & (SKIDOO_IN_ACCELERATE | SKIDOO_IN_BRAKE))
|
|
lara->goalAnimState = SKIDOO_STATE_SIT;
|
|
|
|
break;
|
|
|
|
case SKIDOO_STATE_SIT:
|
|
if (skidoo->speed == 0)
|
|
lara->goalAnimState = SKIDOO_STATE_IDLE;
|
|
|
|
if (dead)
|
|
lara->goalAnimState = SKIDOO_STATE_FALLOFF;
|
|
else if (TrInput & SKIDOO_IN_LEFT)
|
|
lara->goalAnimState = SKIDOO_STATE_LEFT;
|
|
else if (TrInput & SKIDOO_IN_RIGHT)
|
|
lara->goalAnimState = SKIDOO_STATE_RIGHT;
|
|
|
|
break;
|
|
|
|
case SKIDOO_STATE_LEFT:
|
|
if (!(TrInput & SKIDOO_IN_LEFT))
|
|
lara->goalAnimState = SKIDOO_STATE_SIT;
|
|
|
|
break;
|
|
|
|
case SKIDOO_STATE_RIGHT:
|
|
if (!(TrInput & SKIDOO_IN_RIGHT))
|
|
lara->goalAnimState = SKIDOO_STATE_SIT;
|
|
|
|
break;
|
|
|
|
case SKIDOO_STATE_FALL:
|
|
if (skidoo->fallspeed <= 0 ||
|
|
skidooInfo->leftFallspeed <= 0 ||
|
|
skidooInfo->rightFallspeed <= 0)
|
|
{
|
|
lara->goalAnimState = SKIDOO_STATE_SIT;
|
|
SoundEffect(SFX_TR2_CLATTER_3, &skidoo->pos, 0);
|
|
}
|
|
else if (skidoo->fallspeed > (DAMAGE_START + DAMAGE_LENGTH))
|
|
lara->goalAnimState = SKIDOO_STATE_JUMP_OFF;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (g_Level.Rooms[skidoo->roomNumber].flags & (ENV_FLAG_WATER | ENV_FLAG_SWAMP))
|
|
{
|
|
lara->goalAnimState = SKIDOO_STATE_JUMP_OFF;
|
|
lara->hitPoints = 0;
|
|
lara->roomNumber = skidoo->roomNumber;
|
|
SkidooExplode(lara, skidoo);
|
|
}
|
|
}
|
|
|
|
int GetSkidooCollisionAnim(ITEM_INFO* skidoo, PHD_VECTOR* moved)
|
|
{
|
|
moved->x = skidoo->pos.xPos - moved->x;
|
|
moved->z = skidoo->pos.zPos - moved->z;
|
|
|
|
if (moved->x || moved->z)
|
|
{
|
|
float s = phd_sin(skidoo->pos.yRot);
|
|
float c = phd_cos(skidoo->pos.yRot);
|
|
|
|
int side = -moved->z * s + moved->x * c;
|
|
int front = moved->z * c + moved->x * s;
|
|
|
|
if (abs(front) > abs(side))
|
|
{
|
|
if (front > 0)
|
|
return SKIDOO_ANIM_HIT_BACK;
|
|
else
|
|
return SKIDOO_ANIM_HIT_FRONT;
|
|
}
|
|
else
|
|
{
|
|
if (side > 0)
|
|
return SKIDOO_ANIM_HIT_LEFT;
|
|
else
|
|
return SKIDOO_ANIM_HIT_RIGHT;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool SkidooUserControl(ITEM_INFO* skidoo, int height, int* pitch)
|
|
{
|
|
auto skidooInfo = (SKIDOO_INFO*)skidoo->data;
|
|
bool drive = false;
|
|
int maxSpeed = 0;
|
|
|
|
if (skidoo->pos.yPos >= height - STEP_SIZE)
|
|
{
|
|
*pitch = skidoo->speed + (height - skidoo->pos.yPos);
|
|
|
|
if (TrInput & IN_LOOK && skidoo->speed == 0)
|
|
LookUpDown();
|
|
|
|
if ((TrInput & SKIDOO_IN_LEFT && !(TrInput & SKIDOO_IN_BRAKE)) ||
|
|
(TrInput & SKIDOO_IN_RIGHT && TrInput & SKIDOO_IN_BRAKE))
|
|
{
|
|
skidooInfo->skidooTurn -= SKIDOO_TURN;
|
|
if (skidooInfo->skidooTurn < -SKIDOO_MAX_TURN)
|
|
skidooInfo->skidooTurn = -SKIDOO_MAX_TURN;
|
|
}
|
|
|
|
if ((TrInput & SKIDOO_IN_RIGHT && !(TrInput & SKIDOO_IN_BRAKE)) ||
|
|
(TrInput & SKIDOO_IN_LEFT && TrInput & SKIDOO_IN_BRAKE))
|
|
{
|
|
skidooInfo->skidooTurn += SKIDOO_TURN;
|
|
if (skidooInfo->skidooTurn > SKIDOO_MAX_TURN)
|
|
skidooInfo->skidooTurn = SKIDOO_MAX_TURN;
|
|
}
|
|
|
|
if (TrInput & SKIDOO_IN_BRAKE)
|
|
{
|
|
if (skidoo->speed > 0)
|
|
skidoo->speed -= SKIDOO_BRAKE;
|
|
else
|
|
{
|
|
if (skidoo->speed > SKIDOO_MAX_BACK)
|
|
skidoo->speed += SKIDOO_REVERSE;
|
|
|
|
drive = true;
|
|
}
|
|
}
|
|
else if (TrInput & SKIDOO_IN_ACCELERATE)
|
|
{
|
|
if (TrInput & SKIDOO_IN_FIRE && !skidooInfo->armed)
|
|
maxSpeed = SKIDOO_FAST_SPEED;
|
|
else if (TrInput & SKIDOO_IN_SLOW)
|
|
maxSpeed = SKIDOO_SLOW_SPEED;
|
|
else
|
|
maxSpeed = SKIDOO_MAX_SPEED;
|
|
|
|
if (skidoo->speed < maxSpeed)
|
|
skidoo->speed += SKIDOO_ACCELERATION / 2 + SKIDOO_ACCELERATION * skidoo->speed / (2 * maxSpeed);
|
|
else if (skidoo->speed > maxSpeed + SKIDOO_SLOWDOWN)
|
|
skidoo->speed -= SKIDOO_SLOWDOWN;
|
|
drive = true;
|
|
}
|
|
else if (skidoo->speed >= 0 &&
|
|
skidoo->speed < SKIDOO_MIN_SPEED &&
|
|
TrInput & (SKIDOO_IN_LEFT | SKIDOO_IN_RIGHT))
|
|
{
|
|
skidoo->speed = SKIDOO_MIN_SPEED;
|
|
drive = true;
|
|
}
|
|
else if (skidoo->speed > SKIDOO_SLOWDOWN)
|
|
{
|
|
skidoo->speed -= SKIDOO_SLOWDOWN;
|
|
if ((GetRandomControl() & 0x7f) < skidoo->speed)
|
|
drive = true;
|
|
}
|
|
else
|
|
skidoo->speed = 0;
|
|
}
|
|
else if (TrInput & (SKIDOO_IN_ACCELERATE | SKIDOO_IN_BRAKE))
|
|
{
|
|
drive = true;
|
|
*pitch = skidooInfo->pitch + 50;
|
|
}
|
|
|
|
return drive;
|
|
}
|
|
|
|
int DoSkidooDynamics(int height, int fallspeed, int* y)
|
|
{
|
|
int kick;
|
|
|
|
if (height > * y)
|
|
{
|
|
*y += fallspeed;
|
|
if (*y > height - SKIDOO_MIN_BOUNCE)
|
|
{
|
|
*y = height;
|
|
fallspeed = 0;
|
|
}
|
|
else
|
|
fallspeed += GRAVITY;
|
|
}
|
|
else
|
|
{
|
|
kick = (height - *y) * 4;
|
|
if (kick < SKIDOO_MAX_KICK)
|
|
kick = SKIDOO_MAX_KICK;
|
|
|
|
fallspeed += ((kick - fallspeed) / 8);
|
|
|
|
if (*y > height)
|
|
*y = height;
|
|
}
|
|
|
|
return fallspeed;
|
|
}
|
|
|
|
int SkidooCheckGetOn(ITEM_INFO* lara, ITEM_INFO* skidoo, COLL_INFO* coll)
|
|
{
|
|
LaraInfo*& laraInfo = lara->data;
|
|
int mountType = 0;
|
|
|
|
if (!(TrInput & IN_ACTION) ||
|
|
laraInfo->gunStatus != LG_NO_ARMS ||
|
|
lara->gravityStatus)
|
|
{
|
|
return mountType = 0;
|
|
}
|
|
|
|
auto probe = GetCollisionResult(skidoo);
|
|
short rot = skidoo->pos.yRot - lara->pos.yRot;
|
|
|
|
if (rot > ANGLE(45.0f) && rot < ANGLE(135.0f))
|
|
mountType = 1;
|
|
else if (rot > -ANGLE(135.0f) && rot < -ANGLE(45.0f))
|
|
mountType = 2;
|
|
else
|
|
mountType = 0;
|
|
|
|
if (probe.Position.Floor < -32000 ||
|
|
!TestBoundsCollide(skidoo, lara, coll->Setup.Radius) ||
|
|
!TestCollision(skidoo, lara))
|
|
{
|
|
mountType = 0;
|
|
}
|
|
|
|
return mountType;
|
|
}
|
|
|
|
void SkidooCollision(short itemNum, ITEM_INFO* lara, COLL_INFO* coll)
|
|
{
|
|
LaraInfo*& laraInfo = lara->data;
|
|
ITEM_INFO* skidoo = &g_Level.Items[itemNum];
|
|
|
|
if (lara->hitPoints < 0 || laraInfo->Vehicle != NO_ITEM)
|
|
return;
|
|
|
|
int mountType = SkidooCheckGetOn(lara, skidoo, coll);
|
|
if (mountType == 0)
|
|
{
|
|
ObjectCollision(itemNum, lara, coll);
|
|
|
|
return;
|
|
}
|
|
|
|
laraInfo->Vehicle = itemNum;
|
|
|
|
if (laraInfo->gunType == WEAPON_FLARE)
|
|
{
|
|
CreateFlare(lara, ID_FLARE_ITEM, false);
|
|
undraw_flare_meshes(lara);
|
|
laraInfo->flareControlLeft = 0;
|
|
laraInfo->requestGunType = WEAPON_NONE;
|
|
laraInfo->gunStatus = LG_NO_ARMS;
|
|
}
|
|
|
|
if (mountType == 1)
|
|
lara->animNumber = Objects[ID_SNOWMOBILE_LARA_ANIMS].animIndex + SKIDOO_ANIM_MOUNT_RIGHT;
|
|
else if (mountType == 2)
|
|
lara->animNumber = Objects[ID_SNOWMOBILE_LARA_ANIMS].animIndex + SKIDOO_ANIM_MOUNT_LEFT;
|
|
|
|
lara->frameNumber = g_Level.Anims[lara->animNumber].frameBase;
|
|
lara->currentAnimState = SKIDOO_STATE_MOUNT;
|
|
lara->pos.yRot = skidoo->pos.yRot;
|
|
lara->pos.xPos = skidoo->pos.xPos;
|
|
lara->pos.yPos = skidoo->pos.yPos;
|
|
lara->pos.zPos = skidoo->pos.zPos;
|
|
laraInfo->gunStatus = LG_HANDS_BUSY;
|
|
skidoo->collidable = true;
|
|
}
|
|
|
|
int TestSkidooHeight(ITEM_INFO* skidoo, int zOff, int xOff, PHD_VECTOR* pos)
|
|
{
|
|
pos->y = skidoo->pos.yPos - zOff * phd_sin(skidoo->pos.xRot) + xOff * phd_sin(skidoo->pos.zRot);
|
|
|
|
float s = phd_sin(skidoo->pos.yRot);
|
|
float c = phd_cos(skidoo->pos.yRot);
|
|
|
|
pos->x = skidoo->pos.xPos + zOff * s + xOff * c;
|
|
pos->z = skidoo->pos.zPos + zOff * c - xOff * s;
|
|
|
|
auto probe = GetCollisionResult(pos->x, pos->y, pos->z, skidoo->roomNumber);
|
|
if (probe.Position.Ceiling > pos->y ||
|
|
probe.Position.Ceiling == NO_HEIGHT)
|
|
{
|
|
return NO_HEIGHT;
|
|
}
|
|
|
|
return probe.Position.Floor;
|
|
}
|
|
|
|
short DoSkidooShift(ITEM_INFO* skidoo, PHD_VECTOR* pos, PHD_VECTOR* old)
|
|
{
|
|
COLL_RESULT probe;
|
|
int x = pos->x / SECTOR(1);
|
|
int z = pos->z / SECTOR(1);
|
|
int xOld = old->x / SECTOR(1);
|
|
int zOld = old->z / SECTOR(1);
|
|
int shiftX = pos->x & (WALL_SIZE - 1);
|
|
int shiftZ = pos->z & (WALL_SIZE - 1);
|
|
|
|
if (x == xOld)
|
|
{
|
|
if (z == zOld)
|
|
{
|
|
skidoo->pos.zPos += (old->z - pos->z);
|
|
skidoo->pos.xPos += (old->x - pos->x);
|
|
}
|
|
else if (z > zOld)
|
|
{
|
|
skidoo->pos.zPos -= shiftZ + 1;
|
|
|
|
return (pos->x - skidoo->pos.xPos);
|
|
}
|
|
else
|
|
{
|
|
skidoo->pos.zPos += WALL_SIZE - shiftZ;
|
|
|
|
return (skidoo->pos.xPos - pos->x);
|
|
}
|
|
}
|
|
else if (z == zOld)
|
|
{
|
|
if (x > xOld)
|
|
{
|
|
skidoo->pos.xPos -= shiftX + 1;
|
|
|
|
return (skidoo->pos.zPos - pos->z);
|
|
}
|
|
else
|
|
{
|
|
skidoo->pos.xPos += WALL_SIZE - shiftX;
|
|
|
|
return (pos->z - skidoo->pos.zPos);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
x = z = 0;
|
|
|
|
probe = GetCollisionResult(old->x, pos->y, pos->z, skidoo->roomNumber);
|
|
if (probe.Position.Floor < old->y - STEP_SIZE)
|
|
{
|
|
if (pos->z > old->z)
|
|
z = -shiftZ - 1;
|
|
else
|
|
z = WALL_SIZE - shiftZ;
|
|
}
|
|
|
|
probe = GetCollisionResult(pos->x, pos->y, old->z, skidoo->roomNumber);
|
|
if (probe.Position.Floor < old->y - STEP_SIZE)
|
|
{
|
|
if (pos->x > old->x)
|
|
x = -shiftX - 1;
|
|
else
|
|
x = WALL_SIZE - shiftX;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
int SkidooDynamics(ITEM_INFO* lara, ITEM_INFO* skidoo)
|
|
{
|
|
auto skidooInfo = (SKIDOO_INFO*)skidoo->data;
|
|
PHD_VECTOR moved, frontLeft, frontRight, backRight, backLeft;
|
|
PHD_VECTOR old, frontLeftOld, frontRightOld, backLeftOld, backRightOld;
|
|
|
|
auto heightFrontLeftOld = TestSkidooHeight(skidoo, SKIDOO_FRONT, -SKIDOO_SIDE, &frontLeftOld);
|
|
auto heightFrontRightOld = TestSkidooHeight(skidoo, SKIDOO_FRONT, SKIDOO_SIDE, &frontRightOld);
|
|
auto heightBackLeftOld = TestSkidooHeight(skidoo, -SKIDOO_FRONT, -SKIDOO_SIDE, &backLeftOld);
|
|
auto heightBackRightOld = TestSkidooHeight(skidoo, -SKIDOO_FRONT, SKIDOO_SIDE, &backRightOld);
|
|
old.x = skidoo->pos.xPos;
|
|
old.y = skidoo->pos.yPos;
|
|
old.z = skidoo->pos.zPos;
|
|
|
|
if (backLeftOld.y > heightBackLeftOld)
|
|
backLeftOld.y = heightBackLeftOld;
|
|
if (backRightOld.y > heightBackRightOld)
|
|
backRightOld.y = heightBackRightOld;
|
|
if (frontLeftOld.y > heightFrontLeftOld)
|
|
frontLeftOld.y = heightFrontLeftOld;
|
|
if (frontRightOld.y > heightFrontRightOld)
|
|
frontRightOld.y = heightFrontRightOld;
|
|
|
|
short rot;
|
|
|
|
if (skidoo->pos.yPos > skidoo->floor - STEP_SIZE)
|
|
{
|
|
if (skidooInfo->skidooTurn < -SKIDOO_UNDO_TURN)
|
|
skidooInfo->skidooTurn += SKIDOO_UNDO_TURN;
|
|
else if (skidooInfo->skidooTurn > SKIDOO_UNDO_TURN)
|
|
skidooInfo->skidooTurn -= SKIDOO_UNDO_TURN;
|
|
else
|
|
skidooInfo->skidooTurn = 0;
|
|
skidoo->pos.yRot += skidooInfo->skidooTurn + skidooInfo->extraRotation;
|
|
|
|
rot = skidoo->pos.yRot - skidooInfo->momentumAngle;
|
|
if (rot < -SKIDOO_MOMENTUM_TURN)
|
|
{
|
|
if (rot < -SKIDOO_MAX_MOM_TURN)
|
|
{
|
|
rot = -SKIDOO_MAX_MOM_TURN;
|
|
skidooInfo->momentumAngle = skidoo->pos.yRot - rot;
|
|
}
|
|
else
|
|
skidooInfo->momentumAngle -= SKIDOO_MOMENTUM_TURN;
|
|
}
|
|
else if (rot > SKIDOO_MOMENTUM_TURN)
|
|
{
|
|
if (rot > SKIDOO_MAX_MOM_TURN)
|
|
{
|
|
rot = SKIDOO_MAX_MOM_TURN;
|
|
skidooInfo->momentumAngle = skidoo->pos.yRot - rot;
|
|
}
|
|
else
|
|
skidooInfo->momentumAngle += SKIDOO_MOMENTUM_TURN;
|
|
}
|
|
else
|
|
skidooInfo->momentumAngle = skidoo->pos.yRot;
|
|
}
|
|
else
|
|
skidoo->pos.yRot += skidooInfo->skidooTurn + skidooInfo->extraRotation;
|
|
|
|
skidoo->pos.zPos += skidoo->speed * phd_cos(skidooInfo->momentumAngle);
|
|
skidoo->pos.xPos += skidoo->speed * phd_sin(skidooInfo->momentumAngle);
|
|
|
|
int slip = SKIDOO_SLIP * phd_sin(skidoo->pos.xRot);
|
|
if (abs(slip) > SKIDOO_SLIP / 2)
|
|
{
|
|
skidoo->pos.zPos -= slip * phd_cos(skidoo->pos.yRot);
|
|
skidoo->pos.xPos -= slip * phd_sin(skidoo->pos.yRot);
|
|
}
|
|
|
|
slip = SKIDOO_SLIP_SIDE * phd_sin(skidoo->pos.zRot);
|
|
if (abs(slip) > SKIDOO_SLIP_SIDE / 2)
|
|
{
|
|
skidoo->pos.zPos -= slip * phd_sin(skidoo->pos.yRot);
|
|
skidoo->pos.xPos += slip * phd_cos(skidoo->pos.yRot);
|
|
}
|
|
|
|
moved.x = skidoo->pos.xPos;
|
|
moved.z = skidoo->pos.zPos;
|
|
|
|
if (!(skidoo->flags & ONESHOT))
|
|
SkidooBaddieCollision(skidoo);
|
|
|
|
rot = 0;
|
|
auto heightBackLeft = TestSkidooHeight(skidoo, -SKIDOO_FRONT, -SKIDOO_SIDE, &backLeft);
|
|
if (heightBackLeft < (backLeftOld.y - STEP_SIZE))
|
|
rot = DoSkidooShift(skidoo, &backLeft, &backLeftOld);
|
|
|
|
auto heightBackRight = TestSkidooHeight(skidoo, -SKIDOO_FRONT, SKIDOO_SIDE, &backRight);
|
|
if (heightBackRight < (backRightOld.y - STEP_SIZE))
|
|
rot += DoSkidooShift(skidoo, &backRight, &backRightOld);
|
|
|
|
auto heightFrontLeft = TestSkidooHeight(skidoo, SKIDOO_FRONT, -SKIDOO_SIDE, &frontLeft);
|
|
if (heightFrontLeft < (frontLeftOld.y - STEP_SIZE))
|
|
rot += DoSkidooShift(skidoo, &frontLeft, &frontLeftOld);
|
|
|
|
auto heightFrontRight = TestSkidooHeight(skidoo, SKIDOO_FRONT, SKIDOO_SIDE, &frontRight);
|
|
if (heightFrontRight < (frontRightOld.y - STEP_SIZE))
|
|
rot += DoSkidooShift(skidoo, &frontRight, &frontRightOld);
|
|
|
|
auto probe = GetCollisionResult(skidoo);
|
|
if (probe.Position.Floor < (skidoo->pos.yPos - STEP_SIZE))
|
|
DoSkidooShift(skidoo, (PHD_VECTOR*)&skidoo->pos, &old);
|
|
|
|
skidooInfo->extraRotation = rot;
|
|
|
|
auto collide = GetSkidooCollisionAnim(skidoo, &moved);
|
|
if (collide)
|
|
{
|
|
int newspeed = (skidoo->pos.zPos - old.z) * phd_cos(skidooInfo->momentumAngle) + (skidoo->pos.xPos - old.x) * phd_sin(skidooInfo->momentumAngle);
|
|
if (skidoo->speed > SKIDOO_MAX_SPEED + SKIDOO_ACCELERATION && newspeed < skidoo->speed - 10)
|
|
{
|
|
lara->hitPoints -= (skidoo->speed - newspeed) / 2;
|
|
lara->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;
|
|
}
|
|
|
|
bool SkidooControl(ITEM_INFO* lara, COLL_INFO* coll)
|
|
{
|
|
LaraInfo*& laraInfo = lara->data;
|
|
ITEM_INFO* skidoo = &g_Level.Items[laraInfo->Vehicle];
|
|
SKIDOO_INFO* skidooInfo = (SKIDOO_INFO*)skidoo->data;
|
|
|
|
PHD_VECTOR fl, fr;
|
|
auto collide = SkidooDynamics(lara, skidoo);
|
|
auto heightFrontLeft = TestSkidooHeight(skidoo, SKIDOO_FRONT, -SKIDOO_SIDE, &fl);
|
|
auto heightFrontRight = TestSkidooHeight(skidoo, SKIDOO_FRONT, SKIDOO_SIDE, &fr);
|
|
|
|
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);
|
|
|
|
TestTriggers(skidoo, true);
|
|
TestTriggers(skidoo, false);
|
|
|
|
bool dead = false;
|
|
int drive = 0;
|
|
|
|
if (lara->hitPoints <= 0)
|
|
{
|
|
TrInput &= ~(IN_LEFT | IN_RIGHT | IN_BACK | IN_FORWARD);
|
|
dead = true;
|
|
}
|
|
else if (lara->currentAnimState == SKIDOO_STATE_JUMP_OFF)
|
|
{
|
|
dead = true;
|
|
collide = 0;
|
|
}
|
|
|
|
int pitch = 0;
|
|
|
|
if (skidoo->flags & ONESHOT)
|
|
{
|
|
drive = false;
|
|
collide = 0;
|
|
}
|
|
else
|
|
{
|
|
switch (lara->currentAnimState)
|
|
{
|
|
case SKIDOO_STATE_MOUNT:
|
|
case SKIDOO_STATE_DISMOUNT_RIGHT:
|
|
case SKIDOO_STATE_DISMOUNT_RIGHT_LEFT:
|
|
case SKIDOO_STATE_JUMP_OFF:
|
|
drive = -1;
|
|
collide = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
drive = SkidooUserControl(skidoo, height, &pitch);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool banditSkidoo = skidooInfo->armed;
|
|
if (drive > 0)
|
|
{
|
|
skidooInfo->trackMesh = ((skidooInfo->trackMesh & 3) == 1) ? 2 : 1;
|
|
|
|
skidooInfo->pitch += (pitch - skidooInfo->pitch) / 4;
|
|
SoundEffect(skidooInfo->pitch ? SFX_TR2_SKIDOO_MOVING : SFX_TR2_SKIDOO_ACCELERATE, &skidoo->pos, 0, 0.5f + skidooInfo->pitch / (float)SKIDOO_MAX_SPEED);
|
|
}
|
|
else
|
|
{
|
|
skidooInfo->trackMesh = 0;
|
|
if (!drive)
|
|
SoundEffect(SFX_TR2_SKIDOO_IDLE, &skidoo->pos, 0);
|
|
skidooInfo->pitch = 0;
|
|
}
|
|
skidoo->floor = height;
|
|
|
|
skidooInfo->leftFallspeed = DoSkidooDynamics(heightFrontLeft, skidooInfo->leftFallspeed, (int*)&fl.y);
|
|
skidooInfo->rightFallspeed = DoSkidooDynamics(heightFrontRight, skidooInfo->rightFallspeed, (int*)&fr.y);
|
|
skidoo->fallspeed = DoSkidooDynamics(height, skidoo->fallspeed, (int*)&skidoo->pos.yPos);
|
|
|
|
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);
|
|
|
|
skidoo->pos.xRot += ((xRot - skidoo->pos.xRot) / 2);
|
|
skidoo->pos.zRot += ((zRot - skidoo->pos.zRot) / 2);
|
|
|
|
if (skidoo->flags & ONESHOT)
|
|
{
|
|
if (roomNumber != skidoo->roomNumber)
|
|
{
|
|
ItemNewRoom(laraInfo->Vehicle, roomNumber);
|
|
ItemNewRoom(laraInfo->itemNumber, roomNumber);
|
|
}
|
|
|
|
AnimateItem(lara);
|
|
|
|
if (skidoo->pos.yPos == skidoo->floor)
|
|
SkidooExplode(lara, skidoo);
|
|
|
|
return 0;
|
|
}
|
|
|
|
SkidooAnimation(lara, skidoo, collide, dead);
|
|
|
|
if (roomNumber != skidoo->roomNumber)
|
|
{
|
|
ItemNewRoom(laraInfo->Vehicle, roomNumber);
|
|
ItemNewRoom(laraInfo->itemNumber, roomNumber);
|
|
}
|
|
|
|
if (lara->currentAnimState != SKIDOO_STATE_FALLOFF)
|
|
{
|
|
lara->pos.xPos = skidoo->pos.xPos;
|
|
lara->pos.yPos = skidoo->pos.yPos;
|
|
lara->pos.zPos = skidoo->pos.zPos;
|
|
lara->pos.yRot = skidoo->pos.yRot;
|
|
if (drive >= 0)
|
|
{
|
|
lara->pos.xRot = skidoo->pos.xRot;
|
|
lara->pos.zRot = skidoo->pos.zRot;
|
|
}
|
|
else
|
|
lara->pos.xRot = lara->pos.zRot = 0;
|
|
}
|
|
else
|
|
lara->pos.xRot = lara->pos.zRot = 0;
|
|
|
|
AnimateItem(lara);
|
|
|
|
if (!dead && drive >= 0 && banditSkidoo)
|
|
SkidooGuns(lara, skidoo);
|
|
|
|
if (!dead)
|
|
{
|
|
skidoo->animNumber = Objects[ID_SNOWMOBILE].animIndex + (lara->animNumber - Objects[ID_SNOWMOBILE_LARA_ANIMS].animIndex);
|
|
skidoo->frameNumber = g_Level.Anims[skidoo->animNumber].frameBase + (lara->frameNumber - g_Level.Anims[lara->animNumber].frameBase);
|
|
}
|
|
else
|
|
{
|
|
skidoo->animNumber = Objects[ID_SNOWMOBILE].animIndex + SKIDOO_ANIM_IDLE;
|
|
skidoo->frameNumber = g_Level.Anims[skidoo->animNumber].frameBase;
|
|
}
|
|
|
|
if (skidoo->speed && skidoo->floor == skidoo->pos.yPos)
|
|
{
|
|
DoSnowEffect(skidoo);
|
|
if (skidoo->speed < 50)
|
|
DoSnowEffect(skidoo);
|
|
}
|
|
|
|
return SkidooCheckGetOff(lara, skidoo);
|
|
}
|
|
|
|
void DrawSkidoo(ITEM_INFO* item)
|
|
{
|
|
|
|
}
|