Merge pull request #163 from mapbase-source/feature/singleplayer-anim-state

Singleplayer animation state (full player model animations)
This commit is contained in:
Blixibon 2021-11-18 11:13:39 -06:00 committed by GitHub
commit 751fa218e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 1467 additions and 218 deletions

View File

@ -509,7 +509,7 @@ int C_BaseCombatWeapon::DrawModel( int flags )
{
// If this isn't the main view, draw the weapon.
view_id_t viewID = CurrentViewID();
if (viewID != VIEW_MAIN && viewID != VIEW_INTRO_CAMERA && (viewID != VIEW_SHADOW_DEPTH_TEXTURE || !localplayer->IsEffectActive(EF_DIMLIGHT)))
if ( (!localplayer->InFirstPersonView() || (viewID != VIEW_MAIN && viewID != VIEW_INTRO_CAMERA)) && (viewID != VIEW_SHADOW_DEPTH_TEXTURE || !localplayer->IsEffectActive(EF_DIMLIGHT)) )
{
// TODO: Is this inefficient?
int nModelIndex = GetModelIndex();

View File

@ -1367,6 +1367,10 @@ void C_BasePlayer::AddEntity( void )
// Add in lighting effects
CreateLightEffects();
#ifdef MAPBASE
SetLocalAnglesDim( X_INDEX, 0 );
#endif
}
extern float UTIL_WaterLevel( const Vector &position, float minz, float maxz );
@ -1514,6 +1518,38 @@ int C_BasePlayer::DrawModel( int flags )
return BaseClass::DrawModel( flags );
}
#ifdef MAPBASE
ConVar cl_player_allow_thirdperson_projtex( "cl_player_allow_thirdperson_projtex", "1", FCVAR_NONE, "Allows players to receive projected textures if they're non-local or in third person." );
ConVar cl_player_allow_thirdperson_rttshadows( "cl_player_allow_thirdperson_rttshadows", "0", FCVAR_NONE, "Allows players to cast RTT shadows if they're non-local or in third person." );
ConVar cl_player_allow_firstperson_projtex( "cl_player_allow_firstperson_projtex", "1", FCVAR_NONE, "Allows players to receive projected textures even if they're in first person." );
ConVar cl_player_allow_firstperson_rttshadows( "cl_player_allow_firstperson_rttshadows", "0", FCVAR_NONE, "Allows players to cast RTT shadows even if they're in first person." );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
ShadowType_t C_BasePlayer::ShadowCastType()
{
if ( (!IsLocalPlayer() || ShouldDraw()) ? !cl_player_allow_thirdperson_rttshadows.GetBool() : !cl_player_allow_firstperson_rttshadows.GetBool() )
return SHADOWS_NONE;
if ( !IsVisible() )
return SHADOWS_NONE;
return SHADOWS_RENDER_TO_TEXTURE_DYNAMIC;
}
//-----------------------------------------------------------------------------
// Should this object receive shadows?
//-----------------------------------------------------------------------------
bool C_BasePlayer::ShouldReceiveProjectedTextures( int flags )
{
if ( (!IsLocalPlayer() || ShouldDraw()) ? !cl_player_allow_thirdperson_projtex.GetBool() : !cl_player_allow_firstperson_projtex.GetBool() )
return false;
return BaseClass::ShouldReceiveProjectedTextures( flags );
}
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------

View File

@ -207,6 +207,11 @@ public:
void SetMaxSpeed( float flMaxSpeed ) { m_flMaxspeed = flMaxSpeed; }
float MaxSpeed() const { return m_flMaxspeed; }
#ifdef MAPBASE
// See c_baseplayer.cpp
virtual ShadowType_t ShadowCastType();
virtual bool ShouldReceiveProjectedTextures( int flags );
#else
// Should this object cast shadows?
virtual ShadowType_t ShadowCastType() { return SHADOWS_NONE; }
@ -214,6 +219,7 @@ public:
{
return false;
}
#endif
bool IsLocalPlayer( void ) const;

View File

@ -47,6 +47,8 @@ $Project
$File "$SRCDIR\game\shared\mapbase\MapEdit.h"
$File "$SRCDIR\game\shared\mapbase\matchers.cpp"
$File "$SRCDIR\game\shared\mapbase\matchers.h"
$File "$SRCDIR\game\shared\mapbase\singleplayer_animstate.cpp"
$File "$SRCDIR\game\shared\mapbase\singleplayer_animstate.h"
$File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.cpp" [$MAPBASE_VSCRIPT]
$File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.h" [$MAPBASE_VSCRIPT]
$File "$SRCDIR\game\shared\mapbase\vscript_singletons.cpp" [$MAPBASE_VSCRIPT]

View File

@ -31,6 +31,9 @@ ConVar cl_npc_speedmod_outtime( "cl_npc_speedmod_outtime", "1.5", FCVAR_CLIENTDL
IMPLEMENT_CLIENTCLASS_DT(C_BaseHLPlayer, DT_HL2_Player, CHL2_Player)
RecvPropDataTable( RECVINFO_DT(m_HL2Local),0, &REFERENCE_RECV_TABLE(DT_HL2Local) ),
RecvPropBool( RECVINFO( m_fIsSprinting ) ),
#ifdef SP_ANIM_STATE
RecvPropFloat( RECVINFO( m_flAnimRenderYaw ) ),
#endif
END_RECV_TABLE()
BEGIN_PREDICTION_DATA( C_BaseHLPlayer )
@ -90,6 +93,13 @@ void C_BaseHLPlayer::OnDataChanged( DataUpdateType_t updateType )
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
#ifdef SP_ANIM_STATE
if (m_flAnimRenderYaw != FLT_MAX)
{
m_angAnimRender = QAngle( 0, m_flAnimRenderYaw, 0 );
}
#endif
BaseClass::OnDataChanged( updateType );
}
@ -657,3 +667,21 @@ void C_BaseHLPlayer::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quatern
BuildFirstPersonMeathookTransformations( hdr, pos, q, cameraTransform, boneMask, boneComputed, "ValveBiped.Bip01_Head1" );
}
#ifdef SP_ANIM_STATE
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const QAngle& C_BaseHLPlayer::GetRenderAngles( void )
{
if ( m_flAnimRenderYaw != FLT_MAX )
{
return m_angAnimRender;
}
else
{
return BaseClass::GetRenderAngles();
}
}
#endif

View File

@ -15,6 +15,10 @@
#include "c_baseplayer.h"
#include "c_hl2_playerlocaldata.h"
#if !defined( HL2MP ) && defined ( MAPBASE )
#include "mapbase/singleplayer_animstate.h"
#endif
class C_BaseHLPlayer : public C_BasePlayer
{
public:
@ -58,6 +62,10 @@ public:
bool IsWeaponLowered( void ) { return m_HL2Local.m_bWeaponLowered; }
#ifdef SP_ANIM_STATE
virtual const QAngle& GetRenderAngles( void );
#endif
public:
C_HL2PlayerLocalData m_HL2Local;
@ -79,6 +87,12 @@ private:
float m_flSpeedMod;
float m_flExitSpeedMod;
#ifdef SP_ANIM_STATE
// At the moment, we network the render angles since almost none of the player anim stuff is done on the client in SP.
// If any of this is ever adapted for MP, this method should be replaced with replicating/moving the anim state to the client.
float m_flAnimRenderYaw;
QAngle m_angAnimRender;
#endif
friend class CHL2GameMovement;
};

View File

@ -2344,6 +2344,42 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_LOW_R_PISTOL );
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_LOW_L_PISTOL );
#endif
#ifdef EXPANDED_HL2DM_ACTIVITIES
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_PISTOL );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_SHOTGUN );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_SMG1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_AR2 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_PHYSGUN );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_GRENADE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_RPG );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_CROSSBOW );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_MELEE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_SLAM );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_PISTOL );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SHOTGUN );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR2 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_PHYSGUN );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_GRENADE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_RPG );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_CROSSBOW );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_MELEE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SLAM );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_RUN_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_CROUCH_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_CROUCH_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_REVOLVER );
#endif
}
#ifdef MAPBASE

View File

@ -406,4 +406,8 @@ void CBaseHLBludgeonWeapon::Swing( int bIsSecondary )
//Play swing sound
WeaponSound( SINGLE );
#endif
#ifdef MAPBASE
pOwner->SetAnimation( PLAYER_ATTACK1 );
#endif
}

View File

@ -2727,8 +2727,7 @@ bool CBaseCombatCharacter::Weapon_CanUse( CBaseCombatWeapon *pWeapon )
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Purpose: Uses an activity from a different weapon when the activity we were originally looking for does not exist on this character.
// Created to give NPCs the ability to use weapons they are not otherwise allowed to use.
// Right now, everyone falls back to the SMG act table.
// This gives NPCs and players the ability to use weapons they are otherwise unable to use.
//-----------------------------------------------------------------------------
Activity CBaseCombatCharacter::Weapon_BackupActivity( Activity activity, bool weaponTranslationWasRequired, CBaseCombatWeapon *pSpecificWeapon )
{
@ -2740,8 +2739,9 @@ Activity CBaseCombatCharacter::Weapon_BackupActivity( Activity activity, bool we
if (!pWeapon->SupportsBackupActivity(activity))
return activity;
// Sometimes, the NPC is supposed to use the default activity. Return that if the weapon translation was "not required" and we have an original activity.
if (!weaponTranslationWasRequired && GetModelPtr()->HaveSequenceForActivity(activity))
// Sometimes, a NPC is supposed to use the default activity. Return that if the weapon translation was "not required" and we have an original activity.
// Don't do this with players.
if (!weaponTranslationWasRequired && GetModelPtr()->HaveSequenceForActivity(activity) && !IsPlayer())
{
return activity;
}
@ -2754,7 +2754,7 @@ Activity CBaseCombatCharacter::Weapon_BackupActivity( Activity activity, bool we
{
if ( activity == pTable->baseAct )
{
// Don't pick SMG animations we don't actually have an animation for.
// Don't pick backup activities we don't actually have an animation for.
if (GetModelPtr() ? !GetModelPtr()->HaveSequenceForActivity(pTable->weaponAct) : false)
{
return activity;

View File

@ -394,6 +394,10 @@ void CHLSelectFireMachineGun::SecondaryAttack( void )
{
m_iSecondaryAttacks++;
gamestats->Event_WeaponFired( pOwner, false, GetClassname() );
#ifdef MAPBASE
pOwner->SetAnimation( PLAYER_ATTACK2 );
#endif
}
}

View File

@ -118,6 +118,11 @@ ConVar sv_stickysprint("sv_stickysprint", "0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBO
#ifdef MAPBASE
ConVar player_autoswitch_enabled( "player_autoswitch_enabled", "1", FCVAR_NONE, "This convar was added by Mapbase to toggle whether players automatically switch to their ''best'' weapon upon picking up ammo for it after it was dry." );
#ifdef SP_ANIM_STATE
ConVar hl2_use_sp_animstate( "hl2_use_sp_animstate", "1", FCVAR_NONE, "Allows SP HL2 players to use HL2:DM animations for custom player models. (changes may not apply until model is reloaded)" );
#endif
#endif
#define FLASH_DRAIN_TIME 1.1111 // 100 units / 90 secs
@ -616,6 +621,10 @@ BEGIN_ENT_SCRIPTDESC( CHL2_Player, CBasePlayer, "The HL2 player entity." )
DEFINE_SCRIPTFUNC( RemoveCustomSuitDevice, "Removes a custom suit device ID. (1-3)" )
DEFINE_SCRIPTFUNC( IsCustomSuitDeviceActive, "Checks if a custom suit device is active." )
#ifdef SP_ANIM_STATE
DEFINE_SCRIPTFUNC( AddAnimStateLayer, "Adds a custom sequence index as a misc. layer for the singleplayer anim state, wtih parameters for blending in/out, setting the playback rate, holding the animation at the end, and only playing when the player is still." )
#endif
END_SCRIPTDESC();
#endif
@ -661,6 +670,9 @@ CSuitPowerDevice SuitDeviceCustom[] =
IMPLEMENT_SERVERCLASS_ST(CHL2_Player, DT_HL2_Player)
SendPropDataTable(SENDINFO_DT(m_HL2Local), &REFERENCE_SEND_TABLE(DT_HL2Local), SendProxy_SendLocalDataTable),
SendPropBool( SENDINFO(m_fIsSprinting) ),
#ifdef SP_ANIM_STATE
SendPropFloat( SENDINFO(m_flAnimRenderYaw), 0, SPROP_NOSCALE ),
#endif
END_SEND_TABLE()
@ -1144,6 +1156,16 @@ void CHL2_Player::PostThink( void )
{
HandleAdmireGlovesAnimation();
}
#ifdef SP_ANIM_STATE
if (m_pPlayerAnimState)
{
QAngle angEyeAngles = EyeAngles();
m_pPlayerAnimState->Update( angEyeAngles.y, angEyeAngles.x );
m_flAnimRenderYaw.Set( m_pPlayerAnimState->GetRenderAngles().y );
}
#endif
}
void CHL2_Player::StartAdmireGlovesAnimation( void )
@ -1353,192 +1375,55 @@ void CHL2_Player::SpawnedAtPoint( CBaseEntity *pSpawnPoint )
//-----------------------------------------------------------------------------
ConVar hl2_use_hl2dm_anims( "hl2_use_hl2dm_anims", "0", FCVAR_NONE, "Allows SP HL2 players to use HL2:DM animations (for custom player models)" );
void CHL2_Player::ResetAnimation( void )
{
if (!hl2_use_hl2dm_anims.GetBool())
return;
if (IsAlive())
{
SetSequence( -1 );
SetActivity( ACT_INVALID );
if (!GetAbsVelocity().x && !GetAbsVelocity().y)
SetAnimation( PLAYER_IDLE );
else if ((GetAbsVelocity().x || GetAbsVelocity().y) && (GetFlags() & FL_ONGROUND))
SetAnimation( PLAYER_WALK );
else if (GetWaterLevel() > 1)
SetAnimation( PLAYER_WALK );
}
}
#ifdef SP_ANIM_STATE
// Set the activity based on an event or current state
void CHL2_Player::SetAnimation( PLAYER_ANIM playerAnim )
{
if (!hl2_use_hl2dm_anims.GetBool())
if (!m_pPlayerAnimState)
{
BaseClass::SetAnimation( playerAnim );
return;
}
int animDesired;
m_pPlayerAnimState->SetPlayerAnimation( playerAnim );
}
float speed;
speed = GetAbsVelocity().Length2D();
// bool bRunning = true;
//Revisit!
/* if ( ( m_nButtons & ( IN_FORWARD | IN_BACK | IN_MOVELEFT | IN_MOVERIGHT ) ) )
{
if ( speed > 1.0f && speed < hl2_normspeed.GetFloat() - 20.0f )
{
bRunning = false;
}
}*/
if ( GetFlags() & ( FL_FROZEN | FL_ATCONTROLS ) )
{
speed = 0;
playerAnim = PLAYER_IDLE;
}
Activity idealActivity = ACT_HL2MP_RUN;
// This could stand to be redone. Why is playerAnim abstracted from activity? (sjb)
if ( playerAnim == PLAYER_JUMP )
{
idealActivity = ACT_HL2MP_JUMP;
}
else if ( playerAnim == PLAYER_DIE )
{
if ( m_lifeState == LIFE_ALIVE )
{
return;
}
}
else if ( playerAnim == PLAYER_ATTACK1 )
{
if ( GetActivity( ) == ACT_HOVER ||
GetActivity( ) == ACT_SWIM ||
GetActivity( ) == ACT_HOP ||
GetActivity( ) == ACT_LEAP ||
GetActivity( ) == ACT_DIESIMPLE )
{
idealActivity = GetActivity( );
}
else
{
idealActivity = ACT_HL2MP_GESTURE_RANGE_ATTACK;
}
}
else if ( playerAnim == PLAYER_RELOAD )
{
idealActivity = ACT_HL2MP_GESTURE_RELOAD;
}
else if ( playerAnim == PLAYER_IDLE || playerAnim == PLAYER_WALK )
{
if ( !( GetFlags() & FL_ONGROUND ) && GetActivity( ) == ACT_HL2MP_JUMP ) // Still jumping
{
idealActivity = GetActivity( );
}
/*
else if ( GetWaterLevel() > 1 )
{
if ( speed == 0 )
idealActivity = ACT_HOVER;
else
idealActivity = ACT_SWIM;
}
*/
else
{
if ( GetFlags() & FL_DUCKING )
{
if ( speed > 0 )
{
idealActivity = ACT_HL2MP_WALK_CROUCH;
}
else
{
idealActivity = ACT_HL2MP_IDLE_CROUCH;
}
}
else
{
if ( speed > 0 )
{
/*
if ( bRunning == false )
{
idealActivity = ACT_WALK;
}
else
*/
{
idealActivity = ACT_HL2MP_RUN;
}
}
else
{
idealActivity = ACT_HL2MP_IDLE;
}
}
}
}
if ( idealActivity == ACT_HL2MP_GESTURE_RANGE_ATTACK )
{
RestartGesture( Weapon_TranslateActivity( idealActivity ) );
// FIXME: this seems a bit wacked
Weapon_SetActivity( Weapon_TranslateActivity( ACT_RANGE_ATTACK1 ), 0 );
return;
}
else if ( idealActivity == ACT_HL2MP_GESTURE_RELOAD )
{
RestartGesture( Weapon_TranslateActivity( idealActivity ) );
return;
}
else
{
SetActivity( idealActivity );
animDesired = SelectWeightedSequence( Weapon_TranslateActivity ( idealActivity ) );
if (animDesired == -1)
{
animDesired = SelectWeightedSequence( idealActivity );
if ( animDesired == -1 )
{
animDesired = 0;
}
}
// Already using the desired animation?
if ( GetSequence() == animDesired )
void CHL2_Player::AddAnimStateLayer( int iSequence, float flBlendIn, float flBlendOut, float flPlaybackRate, bool bHoldAtEnd, bool bOnlyWhenStill )
{
if (!m_pPlayerAnimState)
return;
m_flPlaybackRate = 1.0;
ResetSequence( animDesired );
SetCycle( 0 );
return;
m_pPlayerAnimState->AddMiscSequence( iSequence, flBlendIn, flBlendOut, flPlaybackRate, bHoldAtEnd, bOnlyWhenStill );
}
#endif
//-----------------------------------------------------------------------------
// Purpose: model-change notification. Fires on dynamic load completion as well
//-----------------------------------------------------------------------------
CStudioHdr *CHL2_Player::OnNewModel()
{
CStudioHdr *hdr = BaseClass::OnNewModel();
#ifdef SP_ANIM_STATE
// Clears the animation state if we already have one.
if ( m_pPlayerAnimState != NULL )
{
m_pPlayerAnimState->Release();
m_pPlayerAnimState = NULL;
}
// Already using the desired animation?
if ( GetSequence() == animDesired )
return;
if ( hdr && hdr->HaveSequenceForActivity(ACT_HL2MP_IDLE) && hl2_use_sp_animstate.GetBool() )
{
// Here we create and init the player animation state.
m_pPlayerAnimState = CreatePlayerAnimationState(this);
}
else
{
m_flAnimRenderYaw = FLT_MAX;
}
#endif
//Msg( "Set animation to %d\n", animDesired );
// Reset to first frame of desired animation
ResetSequence( animDesired );
SetCycle( 0 );
return hdr;
}
#endif
@ -1835,6 +1720,14 @@ void CHL2_Player::InitVCollision( const Vector &vecAbsOrigin, const Vector &vecA
CHL2_Player::~CHL2_Player( void )
{
#ifdef SP_ANIM_STATE
// Clears the animation state.
if ( m_pPlayerAnimState != NULL )
{
m_pPlayerAnimState->Release();
m_pPlayerAnimState = NULL;
}
#endif
}
//-----------------------------------------------------------------------------

View File

@ -18,6 +18,8 @@
// In HL2MP we need to inherit from BaseMultiplayerPlayer!
#if defined ( HL2MP )
#include "basemultiplayerplayer.h"
#elif defined ( MAPBASE )
#include "mapbase/singleplayer_animstate.h"
#endif
class CAI_Squad;
@ -130,9 +132,14 @@ public:
// For the logic_playerproxy output
void SpawnedAtPoint( CBaseEntity *pSpawnPoint );
void ResetAnimation( void );
#ifdef SP_ANIM_STATE
void SetAnimation( PLAYER_ANIM playerAnim );
void AddAnimStateLayer( int iSequence, float flBlendIn = 0.0f, float flBlendOut = 0.0f, float flPlaybackRate = 1.0f, bool bHoldAtEnd = false, bool bOnlyWhenStill = false );
#endif
virtual CStudioHdr* OnNewModel();
virtual const char *GetOverrideStepSound( const char *pszBaseStepSoundName );
#endif
@ -432,6 +439,14 @@ private:
float m_flTimeNextLadderHint; // Next time we're eligible to display a HUD hint about a ladder.
friend class CHL2GameMovement;
#ifdef SP_ANIM_STATE
CSinglePlayerAnimState* m_pPlayerAnimState;
// At the moment, we network the render angles since almost none of the player anim stuff is done on the client in SP.
// If any of this is ever adapted for MP, this method should be replaced with replicating/moving the anim state to the client.
CNetworkVar( float, m_flAnimRenderYaw );
#endif
};

View File

@ -198,6 +198,29 @@ acttable_t CWeapon357::m_acttable[] =
{ ACT_RANGE_AIM_MED, ACT_RANGE_AIM_REVOLVER_MED, false },
{ ACT_RANGE_ATTACK1_MED, ACT_RANGE_ATTACK_REVOLVER_MED, false },
#endif
#ifdef MAPBASE
// HL2:DM activities (for third-person animations in SP)
#ifdef EXPANDED_HL2DM_ACTIVITIES
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_REVOLVER, false },
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_REVOLVER, false },
{ ACT_HL2MP_WALK, ACT_HL2MP_WALK_REVOLVER, false },
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_REVOLVER, false },
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_REVOLVER, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_REVOLVER, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK2, ACT_HL2MP_GESTURE_RANGE_ATTACK2_REVOLVER, false },
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_REVOLVER, false },
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_REVOLVER, false },
#else
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_PISTOL, false },
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_PISTOL, false },
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_PISTOL, false },
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_PISTOL, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_PISTOL, false },
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_PISTOL, false },
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_PISTOL, false },
#endif
#endif
};

View File

@ -105,6 +105,21 @@ acttable_t CWeaponAlyxGun::m_acttable[] =
// { ACT_ARM, ACT_ARM_PISTOL, true },
// { ACT_DISARM, ACT_DISARM_PISTOL, true },
#ifdef MAPBASE
// HL2:DM activities (for third-person animations in SP)
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_PISTOL, false },
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_PISTOL, false },
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_PISTOL, false },
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_PISTOL, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_PISTOL, false },
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_PISTOL, false },
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_PISTOL, false },
#ifdef EXPANDED_HL2DM_ACTIVITIES
{ ACT_HL2MP_WALK, ACT_HL2MP_WALK_PISTOL, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK2, ACT_HL2MP_GESTURE_RANGE_ATTACK2_PISTOL, false },
#endif
#endif
};
IMPLEMENT_ACTTABLE(CWeaponAlyxGun);

View File

@ -99,6 +99,21 @@ acttable_t CWeaponAnnabelle::m_acttable[] =
{ ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_SHOTGUN, true },
{ ACT_RELOAD_LOW, ACT_RELOAD_SMG1_LOW, false },
{ ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SMG1, false },
#ifdef MAPBASE
// HL2:DM activities (for third-person animations in SP)
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_AR2, false },
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_AR2, false },
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_AR2, false },
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_AR2, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_SHOTGUN, false },
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_AR2, false },
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_AR2, false },
#ifdef EXPANDED_HL2DM_ACTIVITIES
{ ACT_HL2MP_WALK, ACT_HL2MP_WALK_AR2, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK2, ACT_HL2MP_GESTURE_RANGE_ATTACK2_SHOTGUN, false },
#endif
#endif
};
IMPLEMENT_ACTTABLE(CWeaponAnnabelle);

View File

@ -171,6 +171,21 @@ acttable_t CWeaponAR2::m_acttable[] =
{ ACT_COVER_WALL_LOW_R, ACT_COVER_WALL_LOW_R_RIFLE, false },
{ ACT_COVER_WALL_LOW_L, ACT_COVER_WALL_LOW_L_RIFLE, false },
#endif
#ifdef MAPBASE
// HL2:DM activities (for third-person animations in SP)
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_AR2, false },
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_AR2, false },
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_AR2, false },
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_AR2, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_AR2, false },
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_AR2, false },
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_AR2, false },
#ifdef EXPANDED_HL2DM_ACTIVITIES
{ ACT_HL2MP_WALK, ACT_HL2MP_WALK_AR2, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK2, ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR2, false },
#endif
#endif
};
IMPLEMENT_ACTTABLE(CWeaponAR2);
@ -354,6 +369,9 @@ void CWeaponAR2::SecondaryAttack( void )
if( pPlayer )
{
pPlayer->RumbleEffect(RUMBLE_AR2_ALT_FIRE, 0, RUMBLE_FLAG_RESTART );
#ifdef MAPBASE
pPlayer->SetAnimation( PLAYER_ATTACK2 );
#endif
}
SendWeaponAnim( ACT_VM_FIDGET );

View File

@ -58,6 +58,9 @@ public:
bool ShouldDisplayHUDHint() { return true; }
DECLARE_DATADESC();
#ifdef MAPBASE
DECLARE_ACTTABLE();
#endif
protected:
@ -86,6 +89,26 @@ BEGIN_DATADESC( CWeaponBugBait )
END_DATADESC()
#ifdef MAPBASE
acttable_t CWeaponBugBait::m_acttable[] =
{
// HL2:DM activities (for third-person animations in SP)
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_GRENADE, false },
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_GRENADE, false },
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_GRENADE, false },
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_GRENADE, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_GRENADE, false },
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_GRENADE, false },
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_GRENADE, false },
#ifdef EXPANDED_HL2DM_ACTIVITIES
{ ACT_HL2MP_WALK, ACT_HL2MP_WALK_GRENADE, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK2, ACT_HL2MP_GESTURE_RANGE_ATTACK2_GRENADE, false },
#endif
};
IMPLEMENT_ACTTABLE( CWeaponBugBait );
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
@ -226,6 +249,10 @@ void CWeaponBugBait::PrimaryAttack( void )
SendWeaponAnim( ACT_VM_HAULBACK );
#ifdef MAPBASE
pPlayer->SetAnimation( PLAYER_ATTACK1 );
#endif
m_flTimeWeaponIdle = FLT_MAX;
m_flNextPrimaryAttack = FLT_MAX;

View File

@ -591,6 +591,7 @@ private:
void CheckZoomToggle( void );
void FireBolt( void );
#ifdef MAPBASE
void SetBolt( int iSetting );
void FireNPCBolt( CAI_BaseNPC *pOwner, Vector &vecShootOrigin, Vector &vecShootDir );
#endif
void ToggleZoom( void );
@ -743,6 +744,21 @@ acttable_t CWeaponCrossbow::m_acttable[] =
{ ACT_RANGE_AIM_MED, ACT_RANGE_AIM_CROSSBOW_MED, false },
{ ACT_RANGE_ATTACK1_MED, ACT_RANGE_ATTACK_CROSSBOW_MED, false },
#endif
#ifdef MAPBASE
// HL2:DM activities (for third-person animations in SP)
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_CROSSBOW, false },
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_CROSSBOW, false },
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_CROSSBOW, false },
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_CROSSBOW, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_CROSSBOW, false },
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_CROSSBOW, false },
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_CROSSBOW, false },
#ifdef EXPANDED_HL2DM_ACTIVITIES
{ ACT_HL2MP_WALK, ACT_HL2MP_WALK_CROSSBOW, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK2, ACT_HL2MP_GESTURE_RANGE_ATTACK2_CROSSBOW, false },
#endif
#endif
};
IMPLEMENT_ACTTABLE(CWeaponCrossbow);
@ -812,6 +828,10 @@ void CWeaponCrossbow::PrimaryAttack( void )
{
m_iPrimaryAttacks++;
gamestats->Event_WeaponFired( pPlayer, true, GetClassname() );
#ifdef MAPBASE
pPlayer->SetAnimation( PLAYER_ATTACK1 );
#endif
}
}
@ -846,11 +866,7 @@ void CWeaponCrossbow::Reload_NPC( bool bPlaySound )
{
BaseClass::Reload_NPC( bPlaySound );
int iBody = FindBodygroupByName( "bolt" );
if (iBody != -1)
SetBodygroup( iBody, 0 );
else
m_nSkin = 0;
SetBolt( 0 );
}
#endif
@ -955,6 +971,10 @@ void CWeaponCrossbow::FireBolt( void )
m_iClip1--;
#ifdef MAPBASE
SetBolt( 1 );
#endif
pOwner->ViewPunch( QAngle( -2, 0, 0 ) );
WeaponSound( SINGLE );
@ -977,6 +997,18 @@ void CWeaponCrossbow::FireBolt( void )
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Purpose: Sets whether or not the bolt is visible
//-----------------------------------------------------------------------------
inline void CWeaponCrossbow::SetBolt( int iSetting )
{
int iBody = FindBodygroupByName( "bolt" );
if (iBody != -1 || (GetOwner() && GetOwner()->IsPlayer())) // HACKHACK: Player models check the viewmodel instead of the worldmodel, so we have to do this manually
SetBodygroup( iBody, iSetting );
else
m_nSkin = iSetting;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
@ -1000,11 +1032,7 @@ void CWeaponCrossbow::FireNPCBolt( CAI_BaseNPC *pOwner, Vector &vecShootOrigin,
m_iClip1--;
int iBody = FindBodygroupByName( "bolt" );
if (iBody != -1)
SetBodygroup( iBody, 1 );
else
m_nSkin = 1;
SetBolt( 1 );
WeaponSound( SINGLE_NPC );
WeaponSound( SPECIAL2 );
@ -1026,11 +1054,18 @@ bool CWeaponCrossbow::Deploy( void )
{
if ( m_iClip1 <= 0 )
{
#ifdef MAPBASE
SetBolt( 1 );
#endif
return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), ACT_CROSSBOW_DRAW_UNLOADED, (char*)GetAnimPrefix() );
}
SetSkin( BOLT_SKIN_GLOW );
#ifdef MAPBASE
SetBolt( 0 );
#endif
return BaseClass::Deploy();
}
@ -1178,6 +1213,10 @@ void CWeaponCrossbow::SetChargerState( ChargerState_t state )
// Shoot some sparks and draw a beam between the two outer points
DoLoadEffect();
#ifdef MAPBASE
SetBolt( 0 );
#endif
break;
case CHARGER_STATE_START_CHARGE:

View File

@ -49,6 +49,22 @@ acttable_t CWeaponCrowbar::m_acttable[] =
{ ACT_ARM, ACT_ARM_MELEE, false },
{ ACT_DISARM, ACT_DISARM_MELEE, false },
#endif
#ifdef MAPBASE
// HL2:DM activities (for third-person animations in SP)
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, true },
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_MELEE, false },
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_MELEE, false },
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_MELEE, false },
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_MELEE, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE, false },
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_MELEE, false },
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_MELEE, false },
#ifdef EXPANDED_HL2DM_ACTIVITIES
{ ACT_HL2MP_GESTURE_RANGE_ATTACK2, ACT_HL2MP_GESTURE_RANGE_ATTACK2_MELEE, false },
{ ACT_HL2MP_WALK, ACT_HL2MP_WALK_MELEE, false },
#endif
#endif
};
IMPLEMENT_ACTTABLE(CWeaponCrowbar);

View File

@ -82,6 +82,21 @@ END_DATADESC()
acttable_t CWeaponFrag::m_acttable[] =
{
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, true },
#ifdef MAPBASE
// HL2:DM activities (for third-person animations in SP)
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_GRENADE, false },
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_GRENADE, false },
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_GRENADE, false },
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_GRENADE, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_GRENADE, false },
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_GRENADE, false },
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_GRENADE, false },
#ifdef EXPANDED_HL2DM_ACTIVITIES
{ ACT_HL2MP_WALK, ACT_HL2MP_WALK_GRENADE, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK2, ACT_HL2MP_GESTURE_RANGE_ATTACK2_GRENADE, false },
#endif
#endif
};
IMPLEMENT_ACTTABLE(CWeaponFrag);
@ -404,6 +419,10 @@ void CWeaponFrag::ThrowGrenade( CBasePlayer *pPlayer )
WeaponSound( SINGLE );
#ifdef MAPBASE
pPlayer->SetAnimation( PLAYER_ATTACK1 );
#endif
m_iPrimaryAttacks++;
gamestats->Event_WeaponFired( pPlayer, true, GetClassname() );
}
@ -428,6 +447,10 @@ void CWeaponFrag::LobGrenade( CBasePlayer *pPlayer )
WeaponSound( WPN_DOUBLE );
#ifdef MAPBASE
pPlayer->SetAnimation( PLAYER_ATTACK2 );
#endif
m_bRedraw = true;
m_iPrimaryAttacks++;
@ -472,6 +495,10 @@ void CWeaponFrag::RollGrenade( CBasePlayer *pPlayer )
WeaponSound( SPECIAL1 );
#ifdef MAPBASE
pPlayer->SetAnimation( PLAYER_ATTACK2 );
#endif
m_bRedraw = true;
m_iPrimaryAttacks++;

View File

@ -1238,6 +1238,9 @@ public:
DECLARE_SERVERCLASS();
DECLARE_DATADESC();
#ifdef MAPBASE
DECLARE_ACTTABLE();
#endif
CWeaponPhysCannon( void );
@ -1455,6 +1458,30 @@ BEGIN_DATADESC( CWeaponPhysCannon )
END_DATADESC()
#ifdef MAPBASE
acttable_t CWeaponPhysCannon::m_acttable[] =
{
// HL2:DM activities (for third-person animations in SP)
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_PHYSGUN, false },
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_PHYSGUN, false },
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_PHYSGUN, false },
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_PHYSGUN, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_PHYSGUN, false },
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_PHYSGUN, false },
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_PHYSGUN, false },
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, false },
#ifdef EXPANDED_HL2DM_ACTIVITIES
{ ACT_HL2MP_WALK, ACT_HL2MP_WALK_PHYSGUN, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK2, ACT_HL2MP_GESTURE_RANGE_ATTACK2_PHYSGUN, false },
#endif
{ ACT_ARM, ACT_ARM_RIFLE, false },
{ ACT_DISARM, ACT_DISARM_RIFLE, false },
};
IMPLEMENT_ACTTABLE( CWeaponPhysCannon );
#endif
enum
{
@ -1738,6 +1765,9 @@ void CWeaponPhysCannon::DryFire( void )
if ( pOwner )
{
pOwner->RumbleEffect( RUMBLE_PISTOL, 0, RUMBLE_FLAG_RESTART );
#ifdef MAPBASE // TODO: Is this animation too dramatic?
pOwner->SetAnimation( PLAYER_ATTACK1 );
#endif
}
}
@ -1794,6 +1824,11 @@ void CWeaponPhysCannon::PuntNonVPhysics( CBaseEntity *pEntity, const Vector &for
PrimaryFireEffect();
SendWeaponAnim( ACT_VM_SECONDARYATTACK );
#ifdef MAPBASE
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if (pPlayer)
pPlayer->SetAnimation( PLAYER_ATTACK1 );
#endif
m_nChangeState = ELEMENT_STATE_CLOSED;
m_flElementDebounce = gpGlobals->curtime + 0.5f;
@ -1944,6 +1979,10 @@ void CWeaponPhysCannon::PuntVPhysics( CBaseEntity *pEntity, const Vector &vecFor
PrimaryFireEffect();
SendWeaponAnim( ACT_VM_SECONDARYATTACK );
#ifdef MAPBASE
pOwner->SetAnimation( PLAYER_ATTACK1 );
#endif
m_nChangeState = ELEMENT_STATE_CLOSED;
m_flElementDebounce = gpGlobals->curtime + 0.5f;
m_flCheckSuppressTime = gpGlobals->curtime + 0.25f;
@ -2062,6 +2101,10 @@ void CWeaponPhysCannon::PuntRagdoll( CBaseEntity *pEntity, const Vector &vecForw
PrimaryFireEffect();
SendWeaponAnim( ACT_VM_SECONDARYATTACK );
#ifdef MAPBASE
pOwner->SetAnimation( PLAYER_ATTACK1 );
#endif
m_nChangeState = ELEMENT_STATE_CLOSED;
m_flElementDebounce = gpGlobals->curtime + 0.5f;
m_flCheckSuppressTime = gpGlobals->curtime + 0.25f;
@ -2167,6 +2210,9 @@ void CWeaponPhysCannon::PrimaryAttack( void )
PrimaryFireEffect();
SendWeaponAnim( ACT_VM_SECONDARYATTACK );
#ifdef MAPBASE
pOwner->SetAnimation( PLAYER_ATTACK1 );
#endif
return;
}

View File

@ -257,6 +257,21 @@ acttable_t CWeaponPistol::m_acttable[] =
{ ACT_COVER_WALL_LOW_R, ACT_COVER_WALL_LOW_R_PISTOL, false },
{ ACT_COVER_WALL_LOW_L, ACT_COVER_WALL_LOW_L_PISTOL, false },
#endif
#ifdef MAPBASE
// HL2:DM activities (for third-person animations in SP)
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_PISTOL, false },
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_PISTOL, false },
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_PISTOL, false },
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_PISTOL, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_PISTOL, false },
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_PISTOL, false },
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_PISTOL, false },
#ifdef EXPANDED_HL2DM_ACTIVITIES
{ ACT_HL2MP_WALK, ACT_HL2MP_WALK_PISTOL, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK2, ACT_HL2MP_GESTURE_RANGE_ATTACK2_PISTOL, false },
#endif
#endif
};

View File

@ -1426,6 +1426,21 @@ acttable_t CWeaponRPG::m_acttable[] =
{ ACT_RANGE_AIM_MED, ACT_RANGE_AIM_RPG_MED, false },
{ ACT_RANGE_ATTACK1_MED, ACT_RANGE_ATTACK_RPG_MED, false },
#endif
#ifdef MAPBASE
// HL2:DM activities (for third-person animations in SP)
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_RPG, false },
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_RPG, false },
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_RPG, false },
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_RPG, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_RPG, false },
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_RPG, false },
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_RPG, false },
#ifdef EXPANDED_HL2DM_ACTIVITIES
{ ACT_HL2MP_WALK, ACT_HL2MP_WALK_RPG, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK2, ACT_HL2MP_GESTURE_RANGE_ATTACK2_RPG, false },
#endif
#endif
};
IMPLEMENT_ACTTABLE(CWeaponRPG);
@ -1650,6 +1665,10 @@ void CWeaponRPG::PrimaryAttack( void )
SendWeaponAnim( ACT_VM_PRIMARYATTACK );
WeaponSound( SINGLE );
#ifdef MAPBASE
pOwner->SetAnimation( PLAYER_ATTACK1 );
#endif
pOwner->RumbleEffect( RUMBLE_SHOTGUN_SINGLE, 0, RUMBLE_FLAG_RESTART );
m_iPrimaryAttacks++;

View File

@ -215,6 +215,21 @@ acttable_t CWeaponShotgun::m_acttable[] =
{ ACT_RANGE_AIM_MED, ACT_RANGE_AIM_SHOTGUN_MED, false },
{ ACT_RANGE_ATTACK1_MED, ACT_RANGE_ATTACK_SHOTGUN_MED, false },
#endif
#ifdef MAPBASE
// HL2:DM activities (for third-person animations in SP)
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_SHOTGUN, false },
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_SHOTGUN, false },
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_SHOTGUN, false },
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_SHOTGUN, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_SHOTGUN, false },
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_SHOTGUN, false },
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_SHOTGUN, false },
#ifdef EXPANDED_HL2DM_ACTIVITIES
{ ACT_HL2MP_WALK, ACT_HL2MP_WALK_SHOTGUN, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK2, ACT_HL2MP_GESTURE_RANGE_ATTACK2_SHOTGUN, false },
#endif
#endif
};
IMPLEMENT_ACTTABLE(CWeaponShotgun);
@ -378,6 +393,13 @@ bool CWeaponShotgun::StartReload( void )
pOwner->m_flNextAttack = gpGlobals->curtime;
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
#ifdef MAPBASE
if ( pOwner->IsPlayer() )
{
static_cast<CBasePlayer*>(pOwner)->SetAnimation( PLAYER_RELOAD );
}
#endif
m_bInReload = true;
return true;
}
@ -531,7 +553,11 @@ void CWeaponShotgun::PrimaryAttack( void )
pPlayer->SetAnimation( PLAYER_ATTACK1 );
// Don't fire again until fire animation has completed
#ifdef MAPBASE
m_flNextPrimaryAttack = gpGlobals->curtime + GetViewModelSequenceDuration();
#else
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
#endif
m_iClip1 -= 1;
Vector vecSrc = pPlayer->Weapon_ShootPosition( );
@ -586,10 +612,18 @@ void CWeaponShotgun::SecondaryAttack( void )
SendWeaponAnim( ACT_VM_SECONDARYATTACK );
// player "shoot" animation
#ifdef MAPBASE
pPlayer->SetAnimation( PLAYER_ATTACK2 );
#else
pPlayer->SetAnimation( PLAYER_ATTACK1 );
#endif
// Don't fire again until fire animation has completed
#ifdef MAPBASE
m_flNextPrimaryAttack = gpGlobals->curtime + GetViewModelSequenceDuration();
#else
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
#endif
m_iClip1 -= 2; // Shotgun uses same clip for primary and secondary attacks
Vector vecSrc = pPlayer->Weapon_ShootPosition();

View File

@ -149,6 +149,21 @@ acttable_t CWeaponSMG1::m_acttable[] =
{ ACT_COVER_WALL_LOW_R, ACT_COVER_WALL_LOW_R_RIFLE, false },
{ ACT_COVER_WALL_LOW_L, ACT_COVER_WALL_LOW_L_RIFLE, false },
#endif
#ifdef MAPBASE
// HL2:DM activities (for third-person animations in SP)
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_SMG1, false },
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_SMG1, false },
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_SMG1, false },
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_SMG1, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG1, false },
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_SMG1, false },
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_SMG1, false },
#ifdef EXPANDED_HL2DM_ACTIVITIES
{ ACT_HL2MP_WALK, ACT_HL2MP_WALK_SMG1, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK2, ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG1, false },
#endif
#endif
};
IMPLEMENT_ACTTABLE(CWeaponSMG1);
@ -454,7 +469,11 @@ void CWeaponSMG1::SecondaryAttack( void )
CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 1000, 0.2, GetOwner(), SOUNDENT_CHANNEL_WEAPON );
// player "shoot" animation
#ifdef MAPBASE
pPlayer->SetAnimation( PLAYER_ATTACK2 );
#else
pPlayer->SetAnimation( PLAYER_ATTACK1 );
#endif
// Decrease ammo
pPlayer->RemoveAmmo( 1, m_iSecondaryAmmoType );

View File

@ -7817,39 +7817,24 @@ void CBasePlayer::Weapon_Equip( CBaseCombatWeapon *pWeapon )
//-----------------------------------------------------------------------------
Activity CBasePlayer::Weapon_TranslateActivity( Activity baseAct, bool *pRequired )
{
#ifdef HL2_DLL
// HAAAAAAAAAAAAAACKS!
if (GetActiveWeapon())
Activity weaponTranslation = BaseClass::Weapon_TranslateActivity( baseAct, pRequired );
if ( GetActiveWeapon() && GetActiveWeapon()->IsEffectActive(EF_NODRAW) && baseAct != ACT_ARM )
{
int translated = baseAct;
int iActOffset = (baseAct - ACT_HL2MP_IDLE);
string_t iszClassname = GetActiveWeapon()->m_iClassname;
if (iszClassname == gm_isz_class_Pistol || iszClassname == gm_isz_class_357)
translated = (ACT_HL2MP_IDLE_PISTOL + iActOffset);
else if (iszClassname == gm_isz_class_SMG1)
translated = (ACT_HL2MP_IDLE_SMG1 + iActOffset);
else if (iszClassname == gm_isz_class_AR2)
translated = (ACT_HL2MP_IDLE_AR2 + iActOffset);
else if (iszClassname == gm_isz_class_Shotgun)
translated = (ACT_HL2MP_IDLE_SHOTGUN + iActOffset);
else if (iszClassname == gm_isz_class_RPG)
translated = (ACT_HL2MP_IDLE_RPG + iActOffset);
else if (iszClassname == gm_isz_class_Grenade)
translated = (ACT_HL2MP_IDLE_GRENADE + iActOffset);
else if (iszClassname == gm_isz_class_Physcannon)
translated = (ACT_HL2MP_IDLE_PHYSGUN + iActOffset);
else if (iszClassname == gm_isz_class_Crossbow)
translated = (ACT_HL2MP_IDLE_CROSSBOW + iActOffset);
else if (iszClassname == gm_isz_class_Crowbar || iszClassname == gm_isz_class_Stunstick)
translated = (ACT_HL2MP_IDLE_MELEE + iActOffset);
if (translated != baseAct)
return (Activity)translated;
// Our weapon is holstered. Use the base activity.
return baseAct;
}
#endif
if ( GetModelPtr() && !GetModelPtr()->HaveSequenceForActivity(weaponTranslation) )
{
// This is used so players can fall back to backup activities in the same way NPCs in Mapbase can
Activity backupActivity = Weapon_BackupActivity(baseAct, pRequired);
if ( baseAct != backupActivity && GetModelPtr()->HaveSequenceForActivity(backupActivity) )
return backupActivity;
return BaseClass::Weapon_TranslateActivity( baseAct, pRequired );
return baseAct;
}
return weaponTranslation;
}
#endif

View File

@ -46,6 +46,8 @@ $Project
$File "$SRCDIR\game\shared\mapbase\MapEdit.h"
$File "$SRCDIR\game\shared\mapbase\matchers.cpp"
$File "$SRCDIR\game\shared\mapbase\matchers.h"
$File "$SRCDIR\game\shared\mapbase\singleplayer_animstate.cpp"
$File "$SRCDIR\game\shared\mapbase\singleplayer_animstate.h"
$File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.cpp" [$MAPBASE_VSCRIPT]
$File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.h" [$MAPBASE_VSCRIPT]
$File "$SRCDIR\game\shared\mapbase\vscript_singletons.cpp" [$MAPBASE_VSCRIPT]

View File

@ -2461,6 +2461,42 @@ void ActivityList_RegisterSharedActivities( void )
REGISTER_SHARED_ACTIVITY( ACT_COVER_WALL_LOW_L_PISTOL );
#endif
#ifdef EXPANDED_HL2DM_ACTIVITIES
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_WALK );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_WALK_PISTOL );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_WALK_SHOTGUN );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_WALK_SMG1 );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_WALK_AR2 );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_WALK_PHYSGUN );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_WALK_GRENADE );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_WALK_RPG );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_WALK_CROSSBOW );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_WALK_MELEE );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_WALK_SLAM );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2 );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_PISTOL );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SHOTGUN );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG1 );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR2 );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_PHYSGUN );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_GRENADE );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_RPG );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_CROSSBOW );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_MELEE );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SLAM );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_REVOLVER );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_RUN_REVOLVER );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_WALK_REVOLVER );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_CROUCH_REVOLVER );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_WALK_CROUCH_REVOLVER );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_REVOLVER );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_REVOLVER );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_REVOLVER );
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_REVOLVER );
#endif
AssertMsg( g_HighestActivity == LAST_SHARED_ACTIVITY - 1, "Not all activities from ai_activity.h registered in activitylist.cpp" );
}

View File

@ -49,6 +49,10 @@
// This enables some new cover-related activities.
#define EXPANDED_HL2_COVER_ACTIVITIES 1
// EXPANDED HL2DM ACTIVITIES
// This enables some new activities for the HL2:DM set.
#define EXPANDED_HL2DM_ACTIVITIES 1
#endif
#define ACTIVITY_NOT_AVAILABLE -1
@ -2345,6 +2349,42 @@ typedef enum
ACT_COVER_WALL_LOW_L_PISTOL,
#endif
#ifdef EXPANDED_HL2DM_ACTIVITIES
ACT_HL2MP_WALK,
ACT_HL2MP_WALK_PISTOL,
ACT_HL2MP_WALK_SHOTGUN,
ACT_HL2MP_WALK_SMG1,
ACT_HL2MP_WALK_AR2,
ACT_HL2MP_WALK_PHYSGUN,
ACT_HL2MP_WALK_GRENADE,
ACT_HL2MP_WALK_RPG,
ACT_HL2MP_WALK_CROSSBOW,
ACT_HL2MP_WALK_MELEE,
ACT_HL2MP_WALK_SLAM,
ACT_HL2MP_GESTURE_RANGE_ATTACK2,
ACT_HL2MP_GESTURE_RANGE_ATTACK2_PISTOL,
ACT_HL2MP_GESTURE_RANGE_ATTACK2_SHOTGUN,
ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG1,
ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR2,
ACT_HL2MP_GESTURE_RANGE_ATTACK2_PHYSGUN,
ACT_HL2MP_GESTURE_RANGE_ATTACK2_GRENADE,
ACT_HL2MP_GESTURE_RANGE_ATTACK2_RPG,
ACT_HL2MP_GESTURE_RANGE_ATTACK2_CROSSBOW,
ACT_HL2MP_GESTURE_RANGE_ATTACK2_MELEE,
ACT_HL2MP_GESTURE_RANGE_ATTACK2_SLAM,
ACT_HL2MP_IDLE_REVOLVER,
ACT_HL2MP_RUN_REVOLVER,
ACT_HL2MP_WALK_REVOLVER,
ACT_HL2MP_IDLE_CROUCH_REVOLVER,
ACT_HL2MP_WALK_CROUCH_REVOLVER,
ACT_HL2MP_GESTURE_RANGE_ATTACK_REVOLVER,
ACT_HL2MP_GESTURE_RANGE_ATTACK2_REVOLVER,
ACT_HL2MP_GESTURE_RELOAD_REVOLVER,
ACT_HL2MP_JUMP_REVOLVER,
#endif
// this is the end of the global activities, private per-monster activities start here.
LAST_SHARED_ACTIVITY,
} Activity;

View File

@ -539,7 +539,26 @@ bool CBasePlayerAnimState::CanThePlayerMove()
void CBasePlayerAnimState::ComputePlaybackRate()
{
VPROF( "CBasePlayerAnimState::ComputePlaybackRate" );
#ifdef MAPBASE
if ( m_AnimConfig.m_LegAnimType == LEGANIM_9WAY )
{
// If the movement would be greater than the pose range, set playback rate anyway
if ( abs(m_vLastMovePose.x) > 1.0f || abs(m_vLastMovePose.y) > 1.0f )
{
bool bIsMoving;
float flRate = CalcMovementPlaybackRate( &bIsMoving );
if ( bIsMoving )
GetOuter()->SetPlaybackRate( flRate );
else
GetOuter()->SetPlaybackRate( 1 );
}
else
GetOuter()->SetPlaybackRate( 1 );
}
else // Allow LEGANIM_8WAY to change playback rate
#else
if ( m_AnimConfig.m_LegAnimType != LEGANIM_9WAY && m_AnimConfig.m_LegAnimType != LEGANIM_8WAY )
#endif
{
// When using a 9-way blend, playback rate is always 1 and we just scale the pose params
// to speed up or slow down the animation.

View File

@ -1582,6 +1582,10 @@ bool CBaseCombatWeapon::DefaultDeploy( char *szViewModel, char *szWeaponModel, i
SetViewModel();
SendWeaponAnim( iActivity );
#ifdef MAPBASE
pOwner->SetAnimation( PLAYER_UNHOLSTER );
#endif
pOwner->SetNextAttack( gpGlobals->curtime + SequenceDuration() );
}
@ -1652,6 +1656,11 @@ bool CBaseCombatWeapon::Holster( CBaseCombatWeapon *pSwitchingTo )
if (pOwner)
{
pOwner->SetNextAttack( gpGlobals->curtime + flSequenceDuration );
#ifdef MAPBASE
if (pOwner->IsPlayer())
static_cast<CBasePlayer*>(pOwner)->SetAnimation( PLAYER_HOLSTER );
#endif
}
// If we don't have a holster anim, hide immediately to avoid timing issues

View File

@ -115,6 +115,10 @@ acttable_t CWeapon_SLAM::m_acttable[] =
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_SLAM, false },
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_SLAM, false },
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_SLAM, false },
#ifdef EXPANDED_HL2DM_ACTIVITIES
{ ACT_HL2MP_WALK, ACT_HL2MP_WALK_SLAM, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK2, ACT_HL2MP_GESTURE_RANGE_ATTACK2_SLAM, false },
#endif
};
IMPLEMENT_ACTTABLE(CWeapon_SLAM);

View File

@ -86,6 +86,22 @@ acttable_t CWeaponStunStick::m_acttable[] =
{ ACT_RUN, ACT_RUN_MELEE, false },
{ ACT_WALK, ACT_WALK_MELEE, false },
#endif
#ifdef MAPBASE
// HL2:DM activities (for third-person animations in SP)
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, true },
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_MELEE, false },
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_MELEE, false },
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_MELEE, false },
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_MELEE, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE, false },
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_MELEE, false },
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_MELEE, false },
#ifdef EXPANDED_HL2DM_ACTIVITIES
{ ACT_HL2MP_GESTURE_RANGE_ATTACK2, ACT_HL2MP_GESTURE_RANGE_ATTACK2_MELEE, false },
{ ACT_HL2MP_WALK, ACT_HL2MP_WALK_MELEE, false },
#endif
#endif
};
IMPLEMENT_ACTTABLE(CWeaponStunStick);

View File

@ -0,0 +1,669 @@
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
//
// Purpose: Single Player animation state 'handler'. This utility is used
// to evaluate the pose parameter value based on the direction
// and speed of the player.
//
// ------------------------------------------------------------------------------
//
// This was originally based on the following VDC article:
// https://developer.valvesoftware.com/wiki/Fixing_the_player_animation_state_(Single_Player)
//
// It has been modified by Blixibon to derive from CBasePlayerAnimState instead and support 9-way blends.
// Much of the work done to make this derive from CBasePlayerAnimState utilized code from the Alien Swarm SDK.
//
//=============================================================================//
#include "cbase.h"
#include "singleplayer_animstate.h"
#include "tier0/vprof.h"
#include "animation.h"
#include "studio.h"
#include "apparent_velocity_helper.h"
#include "utldict.h"
#include "filesystem.h"
#include "in_buttons.h"
#include "..\public\datacache\imdlcache.h"
extern ConVar mp_facefronttime, mp_feetyawrate, mp_ik;
ConVar sv_playeranimstate_animtype( "sv_playeranimstate_animtype", "0", FCVAR_NONE, "The leg animation type used by the singleplayer animation state. 9way = 0, 8way = 1, GoldSrc = 2" );
ConVar sv_playeranimstate_bodyyaw( "sv_playeranimstate_bodyyaw", "45.0", FCVAR_NONE, "The maximum body yaw used by the singleplayer animation state." );
ConVar sv_playeranimstate_use_aim_sequences( "sv_playeranimstate_use_aim_sequences", "1", FCVAR_NONE, "Allows the singleplayer animation state to use aim sequences." );
#define MIN_TURN_ANGLE_REQUIRING_TURN_ANIMATION 15.0f
#define FIRESEQUENCE_LAYER (AIMSEQUENCE_LAYER+NUM_AIMSEQUENCE_LAYERS)
#define RELOADSEQUENCE_LAYER (FIRESEQUENCE_LAYER + 1)
#define NUM_LAYERS_WANTED (RELOADSEQUENCE_LAYER + 1)
CSinglePlayerAnimState *CreatePlayerAnimationState( CBasePlayer *pPlayer )
{
MDLCACHE_CRITICAL_SECTION();
CSinglePlayerAnimState *pState = new CSinglePlayerAnimState( pPlayer );
// Setup the movement data.
CModAnimConfig movementData;
movementData.m_LegAnimType = (LegAnimType_t)sv_playeranimstate_animtype.GetInt();
movementData.m_flMaxBodyYawDegrees = sv_playeranimstate_bodyyaw.GetFloat();
movementData.m_bUseAimSequences = sv_playeranimstate_use_aim_sequences.GetBool();
pState->Init( pPlayer, movementData );
return pState;
}
// Below this many degrees, slow down turning rate linearly
#define FADE_TURN_DEGREES 45.0f
// After this, need to start turning feet
#define MAX_TORSO_ANGLE 90.0f
// Below this amount, don't play a turning animation/perform IK
#define MIN_TURN_ANGLE_REQUIRING_TURN_ANIMATION 15.0f
//static ConVar tf2_feetyawrunscale( "tf2_feetyawrunscale", "2", FCVAR_REPLICATED, "Multiplier on tf2_feetyawrate to allow turning faster when running." );
extern ConVar sv_backspeed;
extern ConVar mp_feetyawrate;
extern ConVar mp_facefronttime;
extern ConVar mp_ik;
CSinglePlayerAnimState::CSinglePlayerAnimState( CBasePlayer *pPlayer ): m_pPlayer( pPlayer )
{
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
Activity CSinglePlayerAnimState::CalcMainActivity()
{
#ifdef CLIENT_DLL
return ACT_IDLE;
#else
float speed = GetOuter()->GetAbsVelocity().Length2D();
if ( HandleJumping() )
{
return ACT_HL2MP_JUMP;
}
else
{
Activity idealActivity = ACT_HL2MP_IDLE;
if ( GetOuter()->GetFlags() & ( FL_FROZEN | FL_ATCONTROLS ) )
{
speed = 0;
}
else
{
if ( GetOuter()->GetFlags() & FL_DUCKING )
{
if ( speed > 0 )
{
idealActivity = ACT_HL2MP_WALK_CROUCH;
}
else
{
idealActivity = ACT_HL2MP_IDLE_CROUCH;
}
}
else
{
if ( speed > 0 )
{
#ifdef EXPANDED_HL2DM_ACTIVITIES
if ( m_pPlayer->GetButtons() & IN_WALK )
{
idealActivity = ACT_HL2MP_WALK;
}
else
#endif
{
idealActivity = ACT_HL2MP_RUN;
}
}
else
{
idealActivity = ACT_HL2MP_IDLE;
}
}
}
return idealActivity;
}
//return m_pPlayer->GetActivity();
#endif
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSinglePlayerAnimState::SetPlayerAnimation( PLAYER_ANIM playerAnim )
{
if ( playerAnim == PLAYER_ATTACK1 )
{
m_iFireSequence = SelectWeightedSequence( TranslateActivity( ACT_HL2MP_GESTURE_RANGE_ATTACK ) );
m_bFiring = m_iFireSequence != -1;
m_flFireCycle = 0;
}
else if ( playerAnim == PLAYER_ATTACK2 )
{
#ifdef EXPANDED_HL2DM_ACTIVITIES
m_iFireSequence = SelectWeightedSequence( TranslateActivity( ACT_HL2MP_GESTURE_RANGE_ATTACK2 ) );
#else
m_iFireSequence = SelectWeightedSequence( TranslateActivity( ACT_HL2MP_GESTURE_RANGE_ATTACK ) );
#endif
m_bFiring = m_iFireSequence != -1;
m_flFireCycle = 0;
}
else if ( playerAnim == PLAYER_JUMP )
{
// Play the jump animation.
if (!m_bJumping)
{
m_bJumping = true;
m_bFirstJumpFrame = true;
m_flJumpStartTime = gpGlobals->curtime;
}
}
else if ( playerAnim == PLAYER_RELOAD )
{
m_iReloadSequence = SelectWeightedSequence( TranslateActivity( ACT_HL2MP_GESTURE_RELOAD ) );
if (m_iReloadSequence != -1)
{
// clear other events that might be playing in our layer
m_bWeaponSwitching = false;
m_fReloadPlaybackRate = 1.0f;
m_bReloading = true;
m_flReloadCycle = 0;
}
}
else if ( playerAnim == PLAYER_UNHOLSTER || playerAnim == PLAYER_HOLSTER )
{
m_iWeaponSwitchSequence = SelectWeightedSequence( TranslateActivity( playerAnim == PLAYER_UNHOLSTER ? ACT_ARM : ACT_DISARM ) );
if (m_iWeaponSwitchSequence != -1)
{
// clear other events that might be playing in our layer
m_bPlayingMisc = false;
m_bReloading = false;
m_bWeaponSwitching = true;
m_flWeaponSwitchCycle = 0;
m_flMiscBlendOut = 0.1f;
m_flMiscBlendIn = 0.1f;
m_bMiscNoOverride = false;
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
Activity CSinglePlayerAnimState::TranslateActivity( Activity actDesired )
{
#ifdef CLIENT_DLL
return actDesired;
#else
return m_pPlayer->Weapon_TranslateActivity( actDesired );
#endif
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CSinglePlayerAnimState::HandleJumping()
{
if ( m_bJumping )
{
if ( m_bFirstJumpFrame )
{
m_bFirstJumpFrame = false;
RestartMainSequence(); // Reset the animation.
}
// Don't check if he's on the ground for a sec.. sometimes the client still has the
// on-ground flag set right when the message comes in.
if (m_flJumpStartTime > gpGlobals->curtime)
m_flJumpStartTime = gpGlobals->curtime;
if ( gpGlobals->curtime - m_flJumpStartTime > 0.2f)
{
if ( m_pOuter->GetFlags() & FL_ONGROUND || GetOuter()->GetGroundEntity() != NULL)
{
m_bJumping = false;
RestartMainSequence(); // Reset the animation.
}
}
}
// Are we still jumping? If so, keep playing the jump animation.
return m_bJumping;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSinglePlayerAnimState::ComputeSequences( CStudioHdr *pStudioHdr )
{
CBasePlayerAnimState::ComputeSequences(pStudioHdr);
ComputeFireSequence();
ComputeMiscSequence();
ComputeReloadSequence();
ComputeWeaponSwitchSequence();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSinglePlayerAnimState::AddMiscSequence( int iSequence, float flBlendIn, float flBlendOut, float flPlaybackRate, bool bHoldAtEnd, bool bOnlyWhenStill )
{
Assert( iSequence != -1 );
m_iMiscSequence = iSequence;
m_flMiscBlendIn = flBlendIn;
m_flMiscBlendOut = flBlendOut;
m_bPlayingMisc = true;
m_bMiscHoldAtEnd = bHoldAtEnd;
m_bReloading = false;
m_flMiscCycle = 0;
m_bMiscOnlyWhenStill = bOnlyWhenStill;
m_bMiscNoOverride = true;
m_fMiscPlaybackRate = flPlaybackRate;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSinglePlayerAnimState::ClearAnimationState()
{
m_bJumping = false;
m_bFiring = false;
m_bReloading = false;
m_bWeaponSwitching = false;
m_bPlayingMisc = false;
m_flReloadBlendIn = 0.0f;
m_flReloadBlendOut = 0.0f;
m_flMiscBlendIn = 0.0f;
m_flMiscBlendOut = 0.0f;
CBasePlayerAnimState::ClearAnimationState();
}
void CSinglePlayerAnimState::ClearAnimationLayers()
{
VPROF( "CBasePlayerAnimState::ClearAnimationLayers" );
if ( !m_pOuter )
return;
m_pOuter->SetNumAnimOverlays( NUM_LAYERS_WANTED );
for ( int i=0; i < m_pOuter->GetNumAnimOverlays(); i++ )
{
m_pOuter->GetAnimOverlay( i )->SetOrder( CBaseAnimatingOverlay::MAX_OVERLAYS );
#ifndef CLIENT_DLL
m_pOuter->GetAnimOverlay( i )->m_fFlags = 0;
#endif
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CSinglePlayerAnimState::CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle )
{
// TODO?
return m_pOuter->LookupSequence( "soldier_Aim_9_directions" );
}
void CSinglePlayerAnimState::UpdateLayerSequenceGeneric( int iLayer, bool &bEnabled,
float &flCurCycle, int &iSequence, bool bWaitAtEnd,
float fBlendIn, float fBlendOut, bool bMoveBlend, float fPlaybackRate, bool bUpdateCycle /* = true */ )
{
if ( !bEnabled )
return;
CStudioHdr *hdr = GetOuter()->GetModelPtr();
if ( !hdr )
return;
if ( iSequence < 0 || iSequence >= hdr->GetNumSeq() )
return;
// Increment the fire sequence's cycle.
if ( bUpdateCycle )
{
flCurCycle += m_pOuter->GetSequenceCycleRate( hdr, iSequence ) * gpGlobals->frametime * fPlaybackRate;
}
// temp: if the sequence is looping, don't override it - we need better handling of looping anims,
// especially in misc layer from melee (right now the same melee attack is looped manually in asw_melee_system.cpp)
bool bLooping = m_pOuter->IsSequenceLooping( hdr, iSequence );
if ( flCurCycle > 1 && !bLooping )
{
if ( iLayer == RELOADSEQUENCE_LAYER )
{
m_bReloading = false;
}
if ( bWaitAtEnd )
{
flCurCycle = 1;
}
else
{
// Not firing anymore.
bEnabled = false;
iSequence = 0;
return;
}
}
// if this animation should blend out as we move, then check for dropping it completely since we're moving too fast
float speed = 0;
if (bMoveBlend)
{
Vector vel;
GetOuterAbsVelocity( vel );
float speed = vel.Length2D();
if (speed > 50)
{
bEnabled = false;
iSequence = 0;
return;
}
}
// Now dump the state into its animation layer.
CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iLayer );
pLayer->m_flCycle = flCurCycle;
pLayer->m_nSequence = iSequence;
pLayer->m_flPlaybackRate = fPlaybackRate;
pLayer->m_flWeight = 1.0f;
if (iLayer == RELOADSEQUENCE_LAYER)
{
// blend this layer in and out for smooth reloading
if (flCurCycle < fBlendIn && fBlendIn>0)
{
pLayer->m_flWeight = ( clamp<float>(flCurCycle / fBlendIn,
0.001f, 1.0f) );
}
else if (flCurCycle >= (1.0f - fBlendOut) && fBlendOut>0)
{
pLayer->m_flWeight = ( clamp<float>((1.0f - flCurCycle) / fBlendOut,
0.001f, 1.0f) );
}
else
{
pLayer->m_flWeight = 1.0f;
}
}
else
{
pLayer->m_flWeight = 1.0f;
}
if (bMoveBlend)
{
// blend the animation out as we move faster
if (speed <= 50)
pLayer->m_flWeight = ( pLayer->m_flWeight * (50.0f - speed) / 50.0f );
}
#ifndef CLIENT_DLL
pLayer->m_fFlags |= ANIM_LAYER_ACTIVE;
#endif
pLayer->SetOrder( iLayer );
}
void CSinglePlayerAnimState::ComputeFireSequence()
{
UpdateLayerSequenceGeneric( FIRESEQUENCE_LAYER, m_bFiring, m_flFireCycle, m_iFireSequence, false );
}
void CSinglePlayerAnimState::ComputeReloadSequence()
{
UpdateLayerSequenceGeneric( RELOADSEQUENCE_LAYER, m_bReloading, m_flReloadCycle, m_iReloadSequence, false, m_flReloadBlendIn, m_flReloadBlendOut, false, m_fReloadPlaybackRate );
}
void CSinglePlayerAnimState::ComputeWeaponSwitchSequence()
{
UpdateLayerSequenceGeneric( RELOADSEQUENCE_LAYER, m_bWeaponSwitching, m_flWeaponSwitchCycle, m_iWeaponSwitchSequence, false, 0, 0.5f );
}
// does misc gestures if we're not firing
void CSinglePlayerAnimState::ComputeMiscSequence()
{
UpdateLayerSequenceGeneric( RELOADSEQUENCE_LAYER, m_bPlayingMisc, m_flMiscCycle, m_iMiscSequence, m_bMiscHoldAtEnd, m_flMiscBlendIn, m_flMiscBlendOut, m_bMiscOnlyWhenStill, m_fMiscPlaybackRate );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : -
// Output : float
//-----------------------------------------------------------------------------
float CSinglePlayerAnimState::GetCurrentMaxGroundSpeed()
{
CStudioHdr *pStudioHdr = GetOuter()->GetModelPtr();
if ( pStudioHdr == NULL )
return 1.0f;
int iMoveX = GetOuter()->LookupPoseParameter( "move_x" );
int iMoveY = GetOuter()->LookupPoseParameter( "move_y" );
float prevX = GetOuter()->GetPoseParameter( iMoveX );
float prevY = GetOuter()->GetPoseParameter( iMoveY );
float d = MAX( fabs( prevX ), fabs( prevY ) );
float newX, newY;
if ( d == 0.0 )
{
newX = 1.0;
newY = 0.0;
}
else
{
newX = prevX / d;
newY = prevY / d;
}
GetOuter()->SetPoseParameter( pStudioHdr, iMoveX, newX );
GetOuter()->SetPoseParameter( pStudioHdr, iMoveY, newY );
float speed = GetOuter()->GetSequenceGroundSpeed(GetOuter()->GetSequence() );
GetOuter()->SetPoseParameter( pStudioHdr, iMoveX, prevX );
GetOuter()->SetPoseParameter( pStudioHdr, iMoveY, prevY );
return speed;
}
//-----------------------------------------------------------------------------
// Purpose: Override for backpeddling
// Input : dt -
//-----------------------------------------------------------------------------
void CSinglePlayerAnimState::ComputePoseParam_BodyYaw( void )
{
CBasePlayerAnimState::ComputePoseParam_BodyYaw();
//ComputePoseParam_BodyLookYaw();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSinglePlayerAnimState::ComputePoseParam_BodyLookYaw( void )
{
// See if we even have a blender for pitch
int upper_body_yaw = GetOuter()->LookupPoseParameter( "aim_yaw" );
if ( upper_body_yaw < 0 )
{
return;
}
// Assume upper and lower bodies are aligned and that we're not turning
float flGoalTorsoYaw = 0.0f;
int turning = TURN_NONE;
float turnrate = 360.0f;
Vector vel;
GetOuterAbsVelocity( vel );
bool isMoving = ( vel.Length() > 1.0f ) ? true : false;
if ( !isMoving )
{
// Just stopped moving, try and clamp feet
if ( m_flLastTurnTime <= 0.0f )
{
m_flLastTurnTime = gpGlobals->curtime;
m_flLastYaw = GetOuter()->EyeAngles().y;
// Snap feet to be perfectly aligned with torso/eyes
m_flGoalFeetYaw = GetOuter()->EyeAngles().y;
m_flCurrentFeetYaw = m_flGoalFeetYaw;
m_nTurningInPlace = TURN_NONE;
}
// If rotating in place, update stasis timer
if ( m_flLastYaw != GetOuter()->EyeAngles().y )
{
m_flLastTurnTime = gpGlobals->curtime;
m_flLastYaw = GetOuter()->EyeAngles().y;
}
if ( m_flGoalFeetYaw != m_flCurrentFeetYaw )
{
m_flLastTurnTime = gpGlobals->curtime;
}
turning = ConvergeAngles( m_flGoalFeetYaw, turnrate, m_AnimConfig.m_flMaxBodyYawDegrees, gpGlobals->frametime, m_flCurrentFeetYaw );
QAngle eyeAngles = GetOuter()->EyeAngles();
QAngle vAngle = GetOuter()->GetLocalAngles();
// See how far off current feetyaw is from true yaw
float yawdelta = GetOuter()->EyeAngles().y - m_flCurrentFeetYaw;
yawdelta = AngleNormalize( yawdelta );
bool rotated_too_far = false;
float yawmagnitude = fabs( yawdelta );
// If too far, then need to turn in place
if ( yawmagnitude > 45 )
{
rotated_too_far = true;
}
// Standing still for a while, rotate feet around to face forward
// Or rotated too far
// FIXME: Play an in place turning animation
if ( rotated_too_far ||
( gpGlobals->curtime > m_flLastTurnTime + mp_facefronttime.GetFloat() ) )
{
m_flGoalFeetYaw = GetOuter()->EyeAngles().y;
m_flLastTurnTime = gpGlobals->curtime;
/* float yd = m_flCurrentFeetYaw - m_flGoalFeetYaw;
if ( yd > 0 )
{
m_nTurningInPlace = TURN_RIGHT;
}
else if ( yd < 0 )
{
m_nTurningInPlace = TURN_LEFT;
}
else
{
m_nTurningInPlace = TURN_NONE;
}
turning = ConvergeAngles( m_flGoalFeetYaw, turnrate, gpGlobals->frametime, m_flCurrentFeetYaw );
yawdelta = GetOuter()->EyeAngles().y - m_flCurrentFeetYaw;*/
}
// Snap upper body into position since the delta is already smoothed for the feet
flGoalTorsoYaw = yawdelta;
m_flCurrentTorsoYaw = flGoalTorsoYaw;
}
else
{
m_flLastTurnTime = 0.0f;
m_nTurningInPlace = TURN_NONE;
m_flCurrentFeetYaw = m_flGoalFeetYaw = GetOuter()->EyeAngles().y;
flGoalTorsoYaw = 0.0f;
m_flCurrentTorsoYaw = GetOuter()->EyeAngles().y - m_flCurrentFeetYaw;
}
if ( turning == TURN_NONE )
{
m_nTurningInPlace = turning;
}
if ( m_nTurningInPlace != TURN_NONE )
{
// If we're close to finishing the turn, then turn off the turning animation
if ( fabs( m_flCurrentFeetYaw - m_flGoalFeetYaw ) < MIN_TURN_ANGLE_REQUIRING_TURN_ANIMATION )
{
m_nTurningInPlace = TURN_NONE;
}
}
GetOuter()->SetPoseParameter( upper_body_yaw, clamp( m_flCurrentTorsoYaw, -60.0f, 60.0f ) );
/*
// FIXME: Adrian, what is this?
int body_yaw = GetOuter()->LookupPoseParameter( "body_yaw" );
if ( body_yaw >= 0 )
{
GetOuter()->SetPoseParameter( body_yaw, 30 );
}
*/
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSinglePlayerAnimState::ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr )
{
// Get pitch from v_angle
float flPitch = m_flEyePitch;
if ( flPitch > 180.0f )
{
flPitch -= 360.0f;
}
flPitch = clamp( flPitch, -90, 90 );
// See if we have a blender for pitch
GetOuter()->SetPoseParameter( pStudioHdr, "aim_pitch", flPitch );
ComputePoseParam_HeadPitch( pStudioHdr );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSinglePlayerAnimState::ComputePoseParam_HeadPitch( CStudioHdr *pStudioHdr )
{
// Get pitch from v_angle
int iHeadPitch = GetOuter()->LookupPoseParameter("head_pitch");
float flPitch = m_flEyePitch;
if ( flPitch > 180.0f )
{
flPitch -= 360.0f;
}
flPitch = clamp( flPitch, -90, 90 );
GetOuter()->SetPoseParameter( pStudioHdr, iHeadPitch, flPitch );
}

View File

@ -0,0 +1,110 @@
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
//
// Purpose: Single Player animation state 'handler'. This utility is used
// to evaluate the pose parameter value based on the direction
// and speed of the player.
//
// ------------------------------------------------------------------------------
//
// This was originally based on the following VDC article:
// https://developer.valvesoftware.com/wiki/Fixing_the_player_animation_state_(Single_Player)
//
// It has been modified by Blixibon to derive from CBasePlayerAnimState instead and support 9-way blends.
// Much of the work done to make this derive from CBasePlayerAnimState utilized code from the Alien Swarm SDK.
//
//=============================================================================//
#ifndef SINGLEPLAYER_ANIMSTATE_H
#define SINGLEPLAYER_ANIMSTATE_H
#ifdef _WIN32
#pragma once
#endif
#include "cbase.h"
#include "base_playeranimstate.h"
#ifdef CLIENT_DLL
#include "c_baseplayer.h"
#else
#include "player.h"
#endif
#ifdef MAPBASE
// Special definition for differentiating between SP and HL2:DM anim states
#define SP_ANIM_STATE 1
#endif
class CSinglePlayerAnimState : public CBasePlayerAnimState
{
public:
CSinglePlayerAnimState( CBasePlayer *pPlayer );
Activity CalcMainActivity();
int CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle );
float GetCurrentMaxGroundSpeed();
void SetPlayerAnimation( PLAYER_ANIM playerAnim );
Activity TranslateActivity( Activity actDesired );
void ComputeSequences( CStudioHdr *pStudioHdr );
void AddMiscSequence( int iSequence, float flBlendIn = 0.0f, float flBlendOut = 0.0f, float flPlaybackRate = 1.0f, bool bHoldAtEnd = false, bool bOnlyWhenStill = false );
void ClearAnimationState();
void ClearAnimationLayers();
private:
bool HandleJumping();
void ComputeFireSequence();
void ComputeReloadSequence();
void ComputeWeaponSwitchSequence();
void ComputeMiscSequence();
void UpdateLayerSequenceGeneric( int iLayer, bool &bEnabled, float &flCurCycle,
int &iSequence, bool bWaitAtEnd,
float fBlendIn=0.15f, float fBlendOut=0.15f, bool bMoveBlend = false,
float fPlaybackRate=1.0f, bool bUpdateCycle = true );
void ComputePoseParam_BodyYaw( void );
void ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr );
void ComputePoseParam_BodyLookYaw( void );
void ComputePoseParam_HeadPitch( CStudioHdr *pStudioHdr );
CBasePlayer* m_pPlayer;
// Current state variables.
bool m_bJumping; // Set on a jump event.
float m_flJumpStartTime;
bool m_bFirstJumpFrame;
// Aim sequence plays reload while this is on.
bool m_bReloading;
float m_flReloadCycle;
int m_iReloadSequence;
float m_flReloadBlendOut, m_flReloadBlendIn;
float m_fReloadPlaybackRate;
bool m_bWeaponSwitching;
float m_flWeaponSwitchCycle;
int m_iWeaponSwitchSequence;
bool m_bPlayingMisc;
float m_flMiscCycle, m_flMiscBlendOut, m_flMiscBlendIn;
int m_iMiscSequence;
bool m_bMiscOnlyWhenStill, m_bMiscHoldAtEnd;
bool m_bMiscNoOverride;
float m_fMiscPlaybackRate;
bool m_bMiscCycleRewound;
float m_flMiscRewindCycle;
// This is set to true if ANY animation is being played in the fire layer.
bool m_bFiring; // If this is on, then it'll continue the fire animation in the fire layer
// until it completes.
int m_iFireSequence; // (For any sequences in the fire layer, including grenade throw).
float m_flFireCycle;
};
CSinglePlayerAnimState *CreatePlayerAnimationState( CBasePlayer *pPlayer );
#endif // SINGLEPLAYER_ANIMSTATE_H

View File

@ -366,6 +366,14 @@ enum PLAYER_ANIM
PLAYER_RELOAD,
PLAYER_START_AIMING,
PLAYER_LEAVE_AIMING,
#ifdef MAPBASE
// New player animations from Mapbase
PLAYER_ATTACK2,
PLAYER_ATTACK3,
PLAYER_UNHOLSTER,
PLAYER_HOLSTER,
#endif
};
#ifdef HL2_DLL