TombEngine/TR5Main/Game/Lara/lara_slide.cpp

441 lines
8.7 KiB
C++
Raw Normal View History

#include "framework.h"
#include "lara.h"
#include "lara_collide.h"
#include "lara_tests.h"
#include "input.h"
#include "sound.h"
//#include "lara_slide.h"
int OldAngle = 1; // Don't care. To be deleted.
// For later.
bool EnableAugmentedSlide; // Adds steep sliding, slope hugging, 180 turn.
bool EnableNonCardinalSlide; // Slides Lara in true slope direction.
bool EnableSlideInterpolation; // Adapts Lara angles to slope.
bool EnableSlideSteering; // Allows player influence on slide trajectory.
// SLOPE SLIDING
// ------------------------------
// Auxiliary functions
// ------------------------------
bool TestLaraSlide(COLL_INFO* coll)
{
if (abs(coll->tiltX) <= 2 && abs(coll->tiltZ) <= 2)
{
return false;
}
return true;
}
short GetLaraSlideDirection(COLL_INFO* coll)
{
short laraAngle = ANGLE(0.0f);
//if (EnableNonCardinalSlide)
//{
// // TODO: Get true slope direction.
//}
//else
//{
if (coll->tiltX > 2)
{
laraAngle = -ANGLE(90.0f);
}
else if (coll->tiltX < -2)
{
laraAngle = ANGLE(90.0f);
}
if (coll->tiltZ > 2 && coll->tiltZ > abs(coll->tiltX))
{
laraAngle = ANGLE(180.0f);
}
else if (coll->tiltZ < -2 && -coll->tiltZ > abs(coll->tiltX))
{
laraAngle = ANGLE(0.0f);
}
//}
return laraAngle;
}
int GetSlopeAngle(COLL_INFO* coll)
{
return 1;
}
void SetLaraSlide(ITEM_INFO* item, COLL_INFO* coll)
{
short dir = GetLaraSlideDirection(coll);
short polarity = dir - item->pos.yRot;
ShiftItem(item, coll);
// Slide back.
if (polarity < ANGLE(-90.0f) || polarity > ANGLE(90.0f))
{
if (GetSlopeAngle(coll) < ANGLE(60.0f))//SLOPE_ANGLE_STEEP)
{
Lara.moveAngle = ANGLE(180);
item->goalAnimState = LS_SLIDE_BACK;
item->pos.yRot = dir + ANGLE(180.0f);
}
else
{
item->goalAnimState = LS_SLIDE_STEEP_BACK;
item->pos.yRot = dir + ANGLE(180.0f);
}
}
// Slide forward.
else
{
if (GetSlopeAngle(coll) < ANGLE(60.0f))//SLOPE_ANGLE_STEEP)
{
Lara.moveAngle = 0;
item->goalAnimState = LS_SLIDE_FORWARD;
item->pos.yRot = dir;
}
else
{
item->goalAnimState = LS_SLIDE_STEEP_FORWARD;
item->pos.yRot = dir;
}
}
}
// LEGACY. Staying until everything is done.
int Old_TestLaraSlide(ITEM_INFO* item, COLL_INFO* coll) // (F) (D)
{
if (abs(coll->tiltX) <= 2 && abs(coll->tiltZ) <= 2)
return 0;
short angle = ANGLE(0.0f);
if (coll->tiltX > 2)
angle = -ANGLE(90.0f);
else if (coll->tiltX < -2)
angle = ANGLE(90.0f);
if (coll->tiltZ > 2 && coll->tiltZ > abs(coll->tiltX))
angle = ANGLE(180.0f);
else if (coll->tiltZ < -2 && -coll->tiltZ > abs(coll->tiltX))
angle = ANGLE(0.0f);
short delta = angle - item->pos.yRot;
ShiftItem(item, coll);
if (delta < -ANGLE(90.0f) || delta > ANGLE(90.0f))
{
if (item->currentAnimState == LS_SLIDE_BACK && OldAngle == angle)
return 1;
item->animNumber = LA_SLIDE_BACK_START;
item->goalAnimState = LS_SLIDE_BACK;
item->currentAnimState = LS_SLIDE_BACK;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->pos.yRot = angle + ANGLE(180.0f);
Lara.moveAngle = ANGLE(180);
}
else
{
if (item->currentAnimState == LS_SLIDE_FORWARD && OldAngle == angle)
return 1;
item->animNumber = LA_SLIDE_FORWARD;
item->goalAnimState = LS_SLIDE_FORWARD;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = LS_SLIDE_FORWARD;
item->pos.yRot = angle;
Lara.moveAngle = 0;
}
OldAngle = angle;
return 1;
}
void PerformLaraSlide(ITEM_INFO* item, COLL_INFO* coll)//127BC, 1286C (F)
{
}
void PerformLaraSlideEdgeJump(ITEM_INFO* item, COLL_INFO* coll)//12B18, 12BC8 (F)
{
ShiftItem(item, coll);
switch (coll->collType)
{
case CT_LEFT:
item->pos.yRot += ANGLE(5.0f);
break;
case CT_RIGHT:
item->pos.yRot -= ANGLE(5.0f);
break;
case CT_TOP:
case CT_TOP_FRONT:
if (item->fallspeed <= 0)
item->fallspeed = 1;
break;
case CT_CLAMP:
item->pos.zPos -= (400 * phd_cos(coll->facing)) >> W2V_SHIFT;
item->pos.xPos -= (400 * phd_sin(coll->facing)) >> W2V_SHIFT;
item->speed = 0;
coll->midFloor = 0;
if (item->fallspeed <= 0)
item->fallspeed = 16;
break;
}
}
// ------------------------------
// SLOPE SLIDING
// Control & Collision Functions
// ------------------------------
// State: 24
// Collision: lara_col_Slide()
void lara_as_slide(ITEM_INFO* player, COLL_INFO* coll)//1A824(<), 1A958(<) (F)
{
Camera.targetElevation = player->pos.xRot - ANGLE(45.0f);
/*if (TrInput & IN_LEFT)
{
player->pos.yRot -= ANGLE(2.0f);
Lara.turnRate -= LARA_TURN_RATE;
if (Lara.turnRate < -LARA_FAST_TURN)
{
Lara.turnRate = -LARA_FAST_TURN;
}
if (TestLaraLean(coll) & EnableSlideSteering)
{
player->pos.zRot -= LARA_LEAN_RATE;
if (player->pos.zRot < -LARA_LEAN_MAX)
{
player->pos.zRot = -LARA_LEAN_MAX;
}
}
}
else if (TrInput & IN_RIGHT)
{
player->pos.yRot += ANGLE(2.0f);
Lara.turnRate += LARA_TURN_RATE;
if (Lara.turnRate > LARA_FAST_TURN)
{
Lara.turnRate = LARA_FAST_TURN;
}
if (TestLaraLean(coll) && EnableSlideSteering)
{
player->pos.zRot += LARA_LEAN_RATE;
if (player->pos.zRot > LARA_LEAN_MAX)
{
player->pos.zRot = LARA_LEAN_MAX;
}
}
}*/
if ((TrInput & IN_BACK) || (TrInput & IN_DUCK))
{
player->goalAnimState = LS_SLIDE_STEEP_FORWARD;
}
if (TrInput & IN_JUMP)
{
player->goalAnimState = LS_JUMP_FORWARD;
}
if (TrInput & IN_ROLL)
{
player->goalAnimState = LS_SLIDE_TURN_180;
//SetLaraSlide(item, coll); // Temp: Lara slides up the slope otherwise.
}
}
void lara_col_slide(ITEM_INFO* item, COLL_INFO* coll)//1C108(<), 1C23C(<) (F)
{
Lara.moveAngle = ANGLE(0.0f);
coll->badPos = NO_BAD_POS;
coll->badNeg = -512;
coll->badCeiling = 0;
coll->facing = Lara.moveAngle;
if (TestLaraHitCeiling(coll))
{
SetLaraHitCeiling(item, coll);
return;
}
GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE);
LaraDeflectEdge(item, coll);
if (coll->midFloor <= 200)
{
item->pos.yPos += coll->midFloor;
if (!TestLaraSlide(coll))
{
item->goalAnimState = (TrInput & IN_FORWARD) ? LS_RUN_FORWARD : LS_STOP;
StopSoundEffect(SFX_LARA_SLIPPING);
}
}
else
{
if (TrInput & IN_ACTION && coll->midFloor >= 1024 && EnableSafetyDrop)
{
item->goalAnimState = LS_SAFE_DROP;
}
else
{
item->goalAnimState = LS_FALL;
}
item->gravityStatus = true;
item->fallspeed = 0;
StopSoundEffect(SFX_LARA_SLIPPING);
}
}
// State: 32
// Collision: lara_col_SlideBack()
void lara_as_slide_back(ITEM_INFO* item, COLL_INFO* coll)//1A9E0(<), 1AB14(<) (F)
{
Camera.targetElevation = item->pos.xRot;
//if (TrInput & IN_FORWARD)
// item->goalAnimState = LS_SLIDE_STEEP_BACK;
if (TrInput & IN_JUMP)
{
item->goalAnimState = LS_JUMP_BACK;
}
/*if (TrInput & IN_ROLL)
{
item->pos.yRot += ANGLE(180.0f);
item->goalAnimState = LS_SLIDE_FORWARD;
SetLaraSlide(item, coll);
}*/
}
void lara_col_slide_back(ITEM_INFO* item, COLL_INFO* coll)//1C284(<), 1C3B8(<) (F)
{
Lara.moveAngle = ANGLE(180.0f);
coll->badPos = NO_BAD_POS;
coll->badNeg = -512;
coll->badCeiling = 0;
coll->facing = Lara.moveAngle;
if (TestLaraHitCeiling(coll))
{
SetLaraHitCeiling(item, coll);
return;
}
GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE);
LaraDeflectEdge(item, coll);
if (coll->midFloor <= 200)
{
item->pos.yPos += coll->midFloor;
if (!TestLaraSlide(coll))
{
item->goalAnimState = LS_STOP;
StopSoundEffect(SFX_LARA_SLIPPING);
}
}
else
{
if (TrInput & IN_ACTION && coll->midFloor >= 1024 && EnableSafetyDrop)
{
item->goalAnimState = LS_SAFE_DROP;
}
else
{
item->goalAnimState = LS_FALL_BACK;
}
item->gravityStatus = true;
item->fallspeed = 0;
StopSoundEffect(SFX_LARA_SLIPPING);
}
}
// TODO: Unique handling for steep slopes. Anims on the way.
void lara_as_steep_slide(ITEM_INFO* item, COLL_INFO* coll)
{
if (item->pos.xRot >= ANGLE(60))
{
Camera.targetElevation = ANGLE(-60.0f);
}
else
{
Camera.targetElevation = ANGLE(-45.0f);
}
if (TrInput & IN_FORWARD)
{
item->goalAnimState = LS_SLIDE_FORWARD;
}
if (TrInput & IN_JUMP)
{
item->goalAnimState = LS_JUMP_FORWARD;
}
}
void lara_col_steep_slide(ITEM_INFO* item, COLL_INFO* coll)
{
Lara.moveAngle = ANGLE(0.0f);
PerformLaraSlide(item, coll);
}
void lara_as_steep_slide_back(ITEM_INFO* item, COLL_INFO* coll)
{
Camera.targetElevation = ANGLE(-60.0f);
if (TrInput & IN_BACK)
{
item->goalAnimState = LS_SLIDE_BACK;
}
if (TrInput & IN_JUMP)
{
item->goalAnimState = LS_JUMP_BACK;
}
}
void lara_col_steep_slide_back(ITEM_INFO* item, COLL_INFO* coll)
{
Lara.moveAngle = ANGLE(180.0f);
PerformLaraSlide(item, coll);
}
void lara_as_slide_turn_180(ITEM_INFO* item, COLL_INFO* coll)
{
Lara.moveAngle = ANGLE(0.0f);
}
// TODO: Straddling illegal slopes.
// TODO: Grabbing edge of plateau leading to steep slope.