mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-20 20:50:58 +02:00
Quake 4 integrated with DoomRTX
This commit is contained in:
@@ -0,0 +1,603 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../Game_local.h"
|
||||
#include "../vehicle/Vehicle.h"
|
||||
|
||||
//
|
||||
class rvMonsterConvoyGround : public idAI {
|
||||
public:
|
||||
|
||||
CLASS_PROTOTYPE( rvMonsterConvoyGround );
|
||||
|
||||
rvMonsterConvoyGround ( void );
|
||||
|
||||
void Spawn ( void );
|
||||
void InitSpawnArgsVariables ( void );
|
||||
void Save ( idSaveGame *savefile ) const;
|
||||
void Restore ( idRestoreGame *savefile );
|
||||
|
||||
virtual void Postthink ( void );
|
||||
virtual bool Pain ( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
|
||||
virtual bool CheckPainActions ( void );
|
||||
|
||||
virtual bool CanTurn ( void ) const;
|
||||
virtual bool CanMove ( void ) const;
|
||||
virtual void Damage ( idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location );
|
||||
virtual void AdjustHealthByDamage ( int inDamage );
|
||||
|
||||
virtual void GetDebugInfo ( debugInfoProc_t proc, void* userData );
|
||||
|
||||
protected:
|
||||
|
||||
int shots;
|
||||
int minShots;
|
||||
int maxShots;
|
||||
bool isOpen;
|
||||
bool vehicleCollision;
|
||||
float moveCurrentAnimRate;
|
||||
float moveAnimRateMin;
|
||||
float moveAnimRateRange;
|
||||
float moveAccelRate;
|
||||
bool onGround;
|
||||
idVec3 oldOrigin;
|
||||
idVec3 lastPainDir;
|
||||
|
||||
rvAIAction actionBlasterAttack;
|
||||
|
||||
virtual bool CheckActions ( void );
|
||||
virtual int FilterTactical ( int availableTactical );
|
||||
|
||||
virtual const char* GetIdleAnimName ( void );
|
||||
|
||||
virtual void OnDeath ( void );
|
||||
|
||||
private:
|
||||
|
||||
// General states
|
||||
stateResult_t State_Fall ( const stateParms_t& parms );
|
||||
|
||||
// Legs States
|
||||
stateResult_t State_Legs_Move ( const stateParms_t& parms );
|
||||
|
||||
// Torso States
|
||||
stateResult_t State_Torso_BlasterAttack ( const stateParms_t& parms );
|
||||
stateResult_t State_Torso_Open ( const stateParms_t& parms );
|
||||
stateResult_t State_Torso_Close ( const stateParms_t& parms );
|
||||
stateResult_t State_Torso_Pain ( const stateParms_t& parms );
|
||||
|
||||
CLASS_STATES_PROTOTYPE ( rvMonsterConvoyGround );
|
||||
};
|
||||
|
||||
CLASS_DECLARATION( idAI, rvMonsterConvoyGround )
|
||||
END_CLASS
|
||||
|
||||
/*
|
||||
================
|
||||
rvMonsterConvoyGround::rvMonsterConvoyGround
|
||||
================
|
||||
*/
|
||||
rvMonsterConvoyGround::rvMonsterConvoyGround ( ) {
|
||||
shots = 0;
|
||||
isOpen = false;
|
||||
vehicleCollision = false;
|
||||
moveCurrentAnimRate = 1.0f;
|
||||
}
|
||||
|
||||
void rvMonsterConvoyGround::InitSpawnArgsVariables ( void )
|
||||
{
|
||||
minShots = spawnArgs.GetInt ( "minShots" );
|
||||
maxShots = spawnArgs.GetInt ( "maxShots" );
|
||||
moveAccelRate = spawnArgs.GetFloat ( "moveAccelRate", ".1" );
|
||||
moveAnimRateMin = spawnArgs.GetFloat ( "moveMinAnimRate", "1" );
|
||||
moveAnimRateRange = spawnArgs.GetFloat ( "moveMaxAnimRate", "10" ) - moveAnimRateMin;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvMonsterConvoyGround::Spawn
|
||||
================
|
||||
*/
|
||||
void rvMonsterConvoyGround::Spawn ( void ) {
|
||||
actionBlasterAttack.Init ( spawnArgs, "action_blasterAttack", "Torso_BlasterAttack", AIACTIONF_ATTACK );
|
||||
|
||||
InitSpawnArgsVariables();
|
||||
|
||||
aifl.disableLook = true;
|
||||
|
||||
onGround = true;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvMonsterConvoyGround::Prethink
|
||||
================
|
||||
*/
|
||||
void rvMonsterConvoyGround::Postthink ( void ) {
|
||||
/* FIXME
|
||||
if ( onGround && !physicsObj.HasGroundContacts ( ) ) {
|
||||
onGround = false;
|
||||
InterruptState ( "State_Fall" );
|
||||
}
|
||||
*/
|
||||
|
||||
idAI::Postthink ( );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvMonsterConvoyGround::Save
|
||||
================
|
||||
*/
|
||||
bool rvMonsterConvoyGround::Pain ( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
|
||||
lastPainDir = dir;
|
||||
return idAI::Pain ( inflictor, attacker, damage, dir, location );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvMonsterConvoyGround::Save
|
||||
================
|
||||
*/
|
||||
void rvMonsterConvoyGround::Save ( idSaveGame *savefile ) const {
|
||||
savefile->WriteInt ( shots );
|
||||
//minShots and maxShots are set in the Restore
|
||||
savefile->WriteBool ( isOpen );
|
||||
savefile->WriteBool ( vehicleCollision );
|
||||
savefile->WriteBool ( onGround );
|
||||
|
||||
savefile->WriteFloat ( moveCurrentAnimRate );
|
||||
savefile->WriteVec3 ( oldOrigin );
|
||||
savefile->WriteVec3 ( lastPainDir );
|
||||
|
||||
actionBlasterAttack.Save ( savefile );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvMonsterConvoyGround::Restore
|
||||
================
|
||||
*/
|
||||
void rvMonsterConvoyGround::Restore ( idRestoreGame *savefile ) {
|
||||
savefile->ReadInt ( shots );
|
||||
savefile->ReadBool ( isOpen );
|
||||
savefile->ReadBool ( vehicleCollision );
|
||||
savefile->ReadBool ( onGround );
|
||||
|
||||
savefile->ReadFloat ( moveCurrentAnimRate );
|
||||
savefile->ReadVec3 ( oldOrigin );
|
||||
savefile->ReadVec3 ( lastPainDir );
|
||||
|
||||
actionBlasterAttack.Restore ( savefile );
|
||||
|
||||
InitSpawnArgsVariables();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvMonsterConvoyGround::CanMove
|
||||
================
|
||||
*/
|
||||
bool rvMonsterConvoyGround::CanMove ( void ) const {
|
||||
if ( isOpen ) {
|
||||
return false;
|
||||
}
|
||||
return idAI::CanMove ( );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvMonsterConvoyGround::CanTurn
|
||||
================
|
||||
*/
|
||||
bool rvMonsterConvoyGround::CanTurn ( void ) const {
|
||||
if ( isOpen ) {
|
||||
return false;
|
||||
}
|
||||
return idAI::CanTurn ( );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvMonsterConvoyGround::OnDeath
|
||||
================
|
||||
*/
|
||||
void rvMonsterConvoyGround::OnDeath ( void ) {
|
||||
idVec3 fxOrg;
|
||||
idVec3 up;
|
||||
idMat3 fxAxis;
|
||||
|
||||
//center it
|
||||
fxOrg = GetPhysics()->GetCenterMass();
|
||||
|
||||
//point it up
|
||||
up.Set( 0, 0, 1 );
|
||||
fxAxis = up.ToMat3();
|
||||
|
||||
//if we can play it at the joint, do that
|
||||
jointHandle_t axisJoint = animator.GetJointHandle ( "axis" );
|
||||
if ( axisJoint != INVALID_JOINT ) {
|
||||
idMat3 junk;
|
||||
animator.GetJointLocalTransform( axisJoint, gameLocal.GetTime(), fxOrg, junk );
|
||||
fxOrg = renderEntity.origin + (fxOrg*renderEntity.axis);
|
||||
}
|
||||
|
||||
gameLocal.PlayEffect ( spawnArgs, "fx_death", fxOrg, fxAxis );
|
||||
idAI::OnDeath ( );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvMonsterConvoyGround::AdjustHealthByDamage
|
||||
================
|
||||
*/
|
||||
void rvMonsterConvoyGround::AdjustHealthByDamage ( int damage ) {
|
||||
if ( isOpen || vehicleCollision ) {
|
||||
idAI::AdjustHealthByDamage ( damage );
|
||||
} else {
|
||||
PlayEffect ( "fx_shieldHit", animator.GetJointHandle ( "axis" ) );
|
||||
}
|
||||
}
|
||||
|
||||
void rvMonsterConvoyGround::Damage ( idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location )
|
||||
{
|
||||
vehicleCollision = false;
|
||||
const idDict *damageDef = gameLocal.FindEntityDefDict( damageDefName, false );
|
||||
if ( damageDef && damageDef->GetBool( "vehicle_collision" ) ) {
|
||||
vehicleCollision = true;
|
||||
}
|
||||
|
||||
idAI::Damage( inflictor, attacker, dir, damageDefName, damageScale, location );
|
||||
}
|
||||
/*
|
||||
================
|
||||
rvMonsterConvoyGround::Spawn
|
||||
================
|
||||
*/
|
||||
bool rvMonsterConvoyGround::CheckActions ( void ) {
|
||||
if ( isOpen ) {
|
||||
if ( move.fl.moving ) {
|
||||
/*
|
||||
|| !CheckAction_RangedAttack( &actionBlasterAttack, -1 )
|
||||
|| enemy.range > actionBlasterAttack.maxRange
|
||||
|| enemy.range < actionBlasterAttack.minRange
|
||||
|| (!move.fl.moving && (gameLocal.GetTime()-move.startTime) > 3000 ) ) {
|
||||
*/
|
||||
StartSound( "snd_prepare", SND_CHANNEL_ANY, 0, 0, 0 );
|
||||
PerformAction ( "Torso_Close", 4, true );
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( PerformAction ( &actionBlasterAttack, (checkAction_t)&idAI::CheckAction_RangedAttack, &actionTimerRangedAttack ) ) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// Open up if we have stopped and have an enemy
|
||||
if ( !move.fl.moving && physicsObj.HasGroundContacts ( ) && enemy.ent && legsAnim.IsIdle ( ) && CheckTactical ( AITACTICAL_RANGED ) ) {
|
||||
StartSound( "snd_prepare", SND_CHANNEL_ANY, 0, 0, 0 );
|
||||
PerformAction ( "Torso_Open", 4, true );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return idAI::CheckActions ( );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvMonsterConvoyGround::CheckPainActions
|
||||
================
|
||||
*/
|
||||
bool rvMonsterConvoyGround::CheckPainActions ( void ) {
|
||||
if ( isOpen ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return idAI::CheckPainActions ( );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvMonsterConvoyGround::GetIdleAnimName
|
||||
================
|
||||
*/
|
||||
const char* rvMonsterConvoyGround::GetIdleAnimName ( void ) {
|
||||
// Start idle animation
|
||||
if ( isOpen ) {
|
||||
return "idle_open";
|
||||
}
|
||||
return "idle";
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvMonsterConvoyGround::FilterTactical
|
||||
================
|
||||
*/
|
||||
int rvMonsterConvoyGround::FilterTactical ( int availableTactical ) {
|
||||
return idAI::FilterTactical ( availableTactical );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvMonsterConvoyGround::GetDebugInfo
|
||||
=====================
|
||||
*/
|
||||
void rvMonsterConvoyGround::GetDebugInfo ( debugInfoProc_t proc, void* userData ) {
|
||||
// Base class first
|
||||
idAI::GetDebugInfo ( proc, userData );
|
||||
|
||||
proc ( "idAI", "action_blasterAttack", aiActionStatusString[actionBlasterAttack.status], userData );
|
||||
|
||||
proc ( "rvMonsterConvoyGround", "moveAnimRate", va("%g", moveCurrentAnimRate ), userData );
|
||||
proc ( "rvMonsterConvoyGround", "isOpen", isOpen ? "true" : "false", userData );
|
||||
}
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
States
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
CLASS_STATES_DECLARATION ( rvMonsterConvoyGround )
|
||||
STATE ( "State_Fall", rvMonsterConvoyGround::State_Fall )
|
||||
STATE ( "Torso_Open", rvMonsterConvoyGround::State_Torso_Open )
|
||||
STATE ( "Torso_Close", rvMonsterConvoyGround::State_Torso_Close )
|
||||
STATE ( "Torso_BlasterAttack", rvMonsterConvoyGround::State_Torso_BlasterAttack )
|
||||
STATE ( "Torso_Pain", rvMonsterConvoyGround::State_Torso_Pain )
|
||||
|
||||
STATE ( "Legs_Move", rvMonsterConvoyGround::State_Legs_Move )
|
||||
END_CLASS_STATES
|
||||
|
||||
/*
|
||||
================
|
||||
rvMonsterConvoyGround::State_Fall
|
||||
================
|
||||
*/
|
||||
stateResult_t rvMonsterConvoyGround::State_Fall ( const stateParms_t& parms ) {
|
||||
enum {
|
||||
STAGE_INIT, // Initialize fall stage
|
||||
STAGE_WAITIMPACT, // Wait for the drop turret to hit the ground
|
||||
STAGE_IMPACT, // Handle drop turret impact, switch to combat state
|
||||
STAGE_WAITDONE,
|
||||
STAGE_DONE
|
||||
};
|
||||
switch ( parms.stage ) {
|
||||
case STAGE_INIT:
|
||||
StopMove ( MOVE_STATUS_DONE );
|
||||
StopAnimState ( ANIMCHANNEL_LEGS );
|
||||
StopAnimState ( ANIMCHANNEL_TORSO );
|
||||
StartSound ( "snd_falling", SND_CHANNEL_VOICE, 0, false, NULL );
|
||||
PlayEffect ( "fx_droptrail", animator.GetJointHandle ( "origin" ), true );
|
||||
DisableAnimState ( ANIMCHANNEL_LEGS );
|
||||
PlayCycle ( ANIMCHANNEL_TORSO, "idle", 0 );
|
||||
oldOrigin = physicsObj.GetOrigin ( );
|
||||
return SRESULT_STAGE(STAGE_WAITIMPACT);
|
||||
|
||||
case STAGE_WAITIMPACT:
|
||||
if ( physicsObj.HasGroundContacts ( ) ) {
|
||||
return SRESULT_STAGE(STAGE_IMPACT);
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case STAGE_IMPACT:
|
||||
StopSound ( SND_CHANNEL_VOICE, false );
|
||||
StopEffect ( "fx_droptrail" );
|
||||
PlayEffect ( "fx_landing", GetPhysics()->GetOrigin(), (-GetPhysics()->GetGravityNormal()).ToMat3() );
|
||||
|
||||
if ( (physicsObj.GetOrigin ( ) - oldOrigin).LengthSqr() > Square(128.0f) ) {
|
||||
PlayAnim ( ANIMCHANNEL_TORSO, "land", 0 );
|
||||
return SRESULT_STAGE ( STAGE_WAITDONE );
|
||||
}
|
||||
return SRESULT_STAGE ( STAGE_DONE );
|
||||
|
||||
case STAGE_WAITDONE:
|
||||
if ( AnimDone ( ANIMCHANNEL_TORSO, 4 ) ) {
|
||||
return SRESULT_STAGE ( STAGE_DONE );
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case STAGE_DONE:
|
||||
onGround = true;
|
||||
SetAnimState ( ANIMCHANNEL_LEGS, "Legs_Idle" );
|
||||
SetAnimState ( ANIMCHANNEL_TORSO, "Torso_Idle" );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvMonsterConvoyGround::State_Torso_BlasterAttack
|
||||
================
|
||||
*/
|
||||
stateResult_t rvMonsterConvoyGround::State_Torso_BlasterAttack ( const stateParms_t& parms ) {
|
||||
enum {
|
||||
STAGE_INIT,
|
||||
STAGE_ATTACK,
|
||||
STAGE_WAIT
|
||||
};
|
||||
switch ( parms.stage ) {
|
||||
case STAGE_INIT:
|
||||
shots = (gameLocal.random.RandomInt ( maxShots - minShots ) + minShots) * combat.aggressiveScale;
|
||||
return SRESULT_STAGE ( STAGE_ATTACK );
|
||||
|
||||
case STAGE_ATTACK:
|
||||
PlayAnim ( ANIMCHANNEL_TORSO, "range_attack", parms.blendFrames );
|
||||
shots--;
|
||||
return SRESULT_STAGE ( STAGE_WAIT );
|
||||
|
||||
case STAGE_WAIT:
|
||||
if ( AnimDone ( ANIMCHANNEL_TORSO, 0 ) ) {
|
||||
if ( --shots <= 0 || (IsEnemyVisible() && !enemy.fl.inFov) ) {
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_STAGE ( STAGE_ATTACK );
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvMonsterConvoyGround::State_Torso_Open
|
||||
================
|
||||
*/
|
||||
stateResult_t rvMonsterConvoyGround::State_Torso_Open ( const stateParms_t& parms ) {
|
||||
enum {
|
||||
STAGE_INIT,
|
||||
STAGE_WAIT,
|
||||
};
|
||||
|
||||
switch ( parms.stage ) {
|
||||
case STAGE_INIT:
|
||||
DisableAnimState ( ANIMCHANNEL_LEGS );
|
||||
PlayAnim ( ANIMCHANNEL_TORSO, "extend_legs", parms.blendFrames );
|
||||
isOpen = true;
|
||||
aifl.disableLook = false;
|
||||
return SRESULT_STAGE ( STAGE_WAIT );
|
||||
|
||||
case STAGE_WAIT:
|
||||
if ( AnimDone ( ANIMCHANNEL_TORSO, parms.blendFrames ) ) {
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvMonsterConvoyGround::State_Torso_Close
|
||||
================
|
||||
*/
|
||||
stateResult_t rvMonsterConvoyGround::State_Torso_Close ( const stateParms_t& parms ) {
|
||||
enum {
|
||||
STAGE_INIT,
|
||||
STAGE_WAIT,
|
||||
};
|
||||
|
||||
switch ( parms.stage ) {
|
||||
case STAGE_INIT:
|
||||
DisableAnimState ( ANIMCHANNEL_LEGS );
|
||||
PlayAnim ( ANIMCHANNEL_TORSO, "retract_legs", parms.blendFrames );
|
||||
return SRESULT_STAGE ( STAGE_WAIT );
|
||||
|
||||
case STAGE_WAIT:
|
||||
if ( AnimDone ( ANIMCHANNEL_TORSO, 0 ) ) {
|
||||
isOpen = false;
|
||||
aifl.disableLook = true;
|
||||
ForceTacticalUpdate();
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
|
||||
}
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvMonsterConvoyGround::State_Torso_Pain
|
||||
================
|
||||
*/
|
||||
stateResult_t rvMonsterConvoyGround::State_Torso_Pain ( const stateParms_t& parms ) {
|
||||
enum {
|
||||
STAGE_START,
|
||||
STAGE_END
|
||||
};
|
||||
|
||||
switch ( parms.stage ) {
|
||||
case STAGE_START:
|
||||
// Force the orientation to the direction we got hit from so the animation looks correct
|
||||
OverrideFlag ( AIFLAGOVERRIDE_NOTURN, true );
|
||||
TurnToward ( physicsObj.GetOrigin() - lastPainDir * 128.0f );
|
||||
move.current_yaw = move.ideal_yaw;
|
||||
|
||||
// Just in case the pain anim wasnt set before we got here.
|
||||
if ( !painAnim.Length ( ) ) {
|
||||
painAnim = "pain";
|
||||
}
|
||||
|
||||
DisableAnimState ( ANIMCHANNEL_LEGS );
|
||||
PlayAnim ( ANIMCHANNEL_TORSO, painAnim, parms.blendFrames );
|
||||
return SRESULT_STAGE ( STAGE_END );
|
||||
|
||||
case STAGE_END:
|
||||
if ( AnimDone ( ANIMCHANNEL_TORSO, parms.blendFrames ) ) {
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvMonsterConvoyGround::State_Legs_Move
|
||||
================
|
||||
*/
|
||||
stateResult_t rvMonsterConvoyGround::State_Legs_Move ( const stateParms_t& parms ) {
|
||||
enum {
|
||||
STAGE_INIT,
|
||||
STAGE_MOVE
|
||||
};
|
||||
switch ( parms.stage ) {
|
||||
case STAGE_INIT:
|
||||
move.fl.allowAnimMove = true;
|
||||
move.fl.allowPrevAnimMove = false;
|
||||
move.fl.running = true;
|
||||
move.currentDirection = MOVEDIR_FORWARD;
|
||||
// TODO: Looks like current anim rate never gets reset, so they do not correctly accelerate from a stop
|
||||
// unfortunately, adding this change (with a decent acceleration factor) caused them to do lots of
|
||||
// not-so-good looking short moves.
|
||||
// moveCurrentAnimRate = 0;
|
||||
|
||||
oldOrigin = physicsObj.GetOrigin ( );
|
||||
PlayCycle ( ANIMCHANNEL_LEGS, "run", 0 );
|
||||
StartSound( "snd_move", SND_CHANNEL_BODY3, 0, false, NULL );
|
||||
|
||||
return SRESULT_STAGE ( STAGE_MOVE );
|
||||
|
||||
case STAGE_MOVE:
|
||||
|
||||
// If not moving forward just go back to idle
|
||||
if ( !move.fl.moving || !CanMove() ) {
|
||||
StopSound( SND_CHANNEL_BODY3, 0 );
|
||||
PostAnimState ( ANIMCHANNEL_LEGS, "Legs_Idle", 0 );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
// If on the ground update the animation rate based on the normal of the ground plane
|
||||
if ( !ai_debugHelpers.GetBool ( ) && physicsObj.HasGroundContacts ( ) ) {
|
||||
float rate;
|
||||
idVec3 dir;
|
||||
|
||||
dir = (physicsObj.GetOrigin ( ) - oldOrigin);
|
||||
|
||||
if ( DistanceTo ( move.moveDest ) < move.walkRange ) {
|
||||
rate = moveAnimRateMin;
|
||||
} else if ( dir.Normalize ( ) > 0.0f ) {
|
||||
rate = idMath::ClampFloat ( -0.7f, 0.7f, physicsObj.GetGravityNormal ( ) * dir ) / 0.7f;
|
||||
rate = moveAnimRateMin + moveAnimRateRange * (1.0f + rate) / 2.0f;
|
||||
} else {
|
||||
rate = moveAnimRateMin + moveAnimRateRange * 0.5f;
|
||||
}
|
||||
moveCurrentAnimRate += ((rate - moveCurrentAnimRate) * moveAccelRate);
|
||||
|
||||
animator.CurrentAnim ( ANIMCHANNEL_LEGS )->SetPlaybackRate ( gameLocal.time, moveCurrentAnimRate );
|
||||
}
|
||||
|
||||
oldOrigin = physicsObj.GetOrigin ( );
|
||||
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user