diff options
Diffstat (limited to 'game/server/tf2/tf_walker_base.cpp')
| -rw-r--r-- | game/server/tf2/tf_walker_base.cpp | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/game/server/tf2/tf_walker_base.cpp b/game/server/tf2/tf_walker_base.cpp new file mode 100644 index 0000000..7fa3711 --- /dev/null +++ b/game/server/tf2/tf_walker_base.cpp @@ -0,0 +1,302 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "cbase.h" +#include "tf_walker_base.h" + + +#include "in_buttons.h" +#include "shake.h" + + +static float MAX_WALKER_VEL = 100; + + +IMPLEMENT_SERVERCLASS_ST( CWalkerBase, DT_WalkerBase ) +END_SEND_TABLE() + + +CWalkerBase::CWalkerBase() +{ + m_vSteerVelocity.Init(); + m_iMovePoseParamX = -1; + m_iMovePoseParamY = -1; + m_bWalkMode = false; + m_flDontMakeSoundsUntil = 0; + m_flPlaybackSpeedBoost = 1; + m_flVelocityDecayRate = 80; + m_LastButtons = 0; + m_vLastCmdViewAngles.Init(); +} + + +void CWalkerBase::SpawnWalker( + const char *pModelName, + int objectType, + const Vector &vPlacementMins, + const Vector &vPlacementMaxs, + int iHealth, + int nMaxPassengers, + float flPlaybackSpeedBoost + ) +{ + SetModel( pModelName ); + SetType( objectType ); + + UTIL_SetSize( this, vPlacementMins, vPlacementMaxs ); + m_iHealth = iHealth; + m_flPlaybackSpeedBoost = flPlaybackSpeedBoost; + + m_takedamage = DAMAGE_YES; + SetMaxPassengerCount( nMaxPassengers ); + + + + // The model should be set before the derived class calls our Spawn(). + Assert( GetModel() ); + + // By default, all walkers use the walk_box animation as they move. + m_iMovePoseParamX = LookupPoseParameter( "move_x" ); + m_iMovePoseParamY = LookupPoseParameter( "move_y" ); + EnableWalkMode( true ); + + // The base class spawn sets a default collision group, so this needs to + // be called post. + SetCollisionGroup( COLLISION_GROUP_VEHICLE ); + + BaseClass::Spawn(); + + + // HACKHACK: this is just so CBaseObject doesn't call StudioFrameAdvance for us. We should probably have + // a specific flag for this behavior. + m_fObjectFlags |= OF_DOESNT_HAVE_A_MODEL; + m_fObjectFlags &= ~OF_MUST_BE_BUILT_ON_ATTACHMENT; + + + // We animate, so let's not use manual mode for now. + SetMoveType( MOVETYPE_STEP ); + AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST ); + + EnableServerIK(); + + SetContextThink( WalkerThink, gpGlobals->curtime, "WalkerThink" ); +} + +void CWalkerBase::EnableWalkMode( bool bEnable ) +{ + m_bWalkMode = bEnable; + + // Stop any movement.. + m_vSteerVelocity.Init(); + + if ( bEnable ) + { + ResetSequence( LookupSequence( "walk_box" ) ); + + // HACK: there should be a better way to this.. like CBaseAnimating::ResetAnimation, + // or ResetSequence should do it. + SetCycle( 0 ); + } +} + + +void CWalkerBase::AdjustInitialBuildAngles() +{ + QAngle vNewAngles = GetAbsAngles(); + vNewAngles[YAW] += 90; + SetAbsAngles( vNewAngles ); +} + + +void CWalkerBase::WalkerThink() +{ + float dt = GetTimeDelta(); + + // Decay our velocity. + if ( m_bWalkMode ) + { + m_flPlaybackRate = m_flPlaybackSpeedBoost; + + + float flDecayRate = m_flVelocityDecayRate; + + float flLen = m_vSteerVelocity.Length(); + Vector2DNormalize( m_vSteerVelocity ); + + float flDecayAmt = flDecayRate * dt; + flLen = MAX( 0, flLen - flDecayAmt ); + m_vSteerVelocity *= flLen; + + + // Setup our pose parameters. + SetPoseParameter( m_iMovePoseParamX, RemapVal( m_vSteerVelocity.x, -MAX_WALKER_VEL, MAX_WALKER_VEL, -1, 1 ) ); + SetPoseParameter( m_iMovePoseParamY, RemapVal( m_vSteerVelocity.y, -MAX_WALKER_VEL, MAX_WALKER_VEL, -1, 1 ) ); + + // Use an idle animation if they're not moving. + int iWantedSequence = LookupSequence( "walk_box" ); + if ( m_vSteerVelocity.x == 0 && m_vSteerVelocity.y == 0 ) + { + iWantedSequence = LookupSequence( "idle" ); + + // HACK: HL2 Strider has no idle + if ( iWantedSequence == -1 ) + iWantedSequence = LookupSequence( "ragdoll" ); + } + + if ( iWantedSequence != -1 && GetSequence() != iWantedSequence ) + ResetSequence( iWantedSequence ); + } + + + // Now ask the model how far it thought it moved based on the animation. + // Turns out the animation thinks it's moving just a tiny bit, even when we're centered on the idle animation, + // so we just force it not to move here if we know we're not supposed to move. + if ( m_vSteerVelocity.Length() > 0 ) + { + Vector vNewPos = GetWalkerLocalMovement(); + + SetLocalOrigin( vNewPos ); + } + + + // Hard-coded for now. These should come from the vehicle's script eventually. + // Now slowly rotate towards the player's eye angles. + CBasePlayer *pPlayer = GetPassenger( VEHICLE_ROLE_DRIVER ); + if ( pPlayer ) + { + static float flAccelRate = 180; + static float flRotateRate = 60; + + + // Figure out a force to apply to our current velocity. + Vector2D vAccel( 0, 0 ); + + if ( m_LastButtons & IN_FORWARD ) + vAccel.x += flAccelRate; + + if ( m_LastButtons & IN_BACK ) + vAccel.x -= flAccelRate; + + if ( m_LastButtons & IN_MOVELEFT ) + vAccel.y -= flAccelRate; + + if ( m_LastButtons & IN_MOVERIGHT ) + vAccel.y += flAccelRate; + + m_vSteerVelocity += vAccel * dt; + + + m_vSteerVelocity.x = clamp( m_vSteerVelocity.x, -MAX_WALKER_VEL, MAX_WALKER_VEL ); + m_vSteerVelocity.y = clamp( m_vSteerVelocity.y, -MAX_WALKER_VEL, MAX_WALKER_VEL ); + + + float wantedYaw = m_vLastCmdViewAngles[YAW]; + QAngle curAngles = GetAbsAngles(); + curAngles[YAW] = ApproachAngle( wantedYaw, curAngles[YAW], flRotateRate * dt ); + SetAbsAngles( curAngles ); + } + + + DispatchAnimEvents( this ); + + + // Get another think. + SetContextThink( WalkerThink, gpGlobals->curtime + dt, "WalkerThink" ); +} + + +Vector CWalkerBase::GetWalkerLocalMovement() +{ + bool bIgnored; + Vector vNewPos; + QAngle vNewAngles; + GetIntervalMovement( GetAnimTimeInterval(), bIgnored, vNewPos, vNewAngles ); + return vNewPos; +} + + +const Vector2D& CWalkerBase::GetSteerVelocity() const +{ + return m_vSteerVelocity; +} + + + +void CWalkerBase::Spawn() +{ + // Derived classes should call SpawnWalker instead of chaining down to CWalkerBase::Spawn(). + Assert( false ); +} + + +void CWalkerBase::Activate() +{ + WalkerActivate(); + BaseClass::Activate(); +} + +void CWalkerBase::WalkerActivate( void ) +{ + // Until we're finished building, turn off vphysics-based motion + SetSolid( SOLID_VPHYSICS ); + VPhysicsInitStatic(); + + SetPoseParameter( m_iMovePoseParamX, 0 ); + SetPoseParameter( m_iMovePoseParamY, 0 ); +} + + +void CWalkerBase::SetVelocityDecayRate( float flDecayRate ) +{ + m_flVelocityDecayRate = flDecayRate; +} + + +float CWalkerBase::GetTimeDelta() const +{ + return 0.1; +} + + +void CWalkerBase::SetupMove( CBasePlayer *pPlayer, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) +{ + // This calls StudioFrameAdvance for us. + //BaseClass::SetupMove( pPlayer, ucmd, pHelper, move ); + + // Lose control when the player dies + if ( pPlayer->IsAlive() == false ) + { + m_LastButtons = 0; + return; + } + + // Only the driver gets to drive. + int nRole = GetPassengerRole( pPlayer ); + if ( nRole != VEHICLE_ROLE_DRIVER ) + return; + + m_LastButtons = ucmd->buttons; + m_vLastCmdViewAngles = ucmd->viewangles; +} + + +bool CWalkerBase::IsPassengerVisible( int nRole ) +{ + return true; +} + + +bool CWalkerBase::StartBuilding( CBaseEntity *pBuilder ) +{ + if ( !BaseClass::StartBuilding( pBuilder ) ) + return false; + + WalkerActivate(); + return true; +} + + + |