From 10f48a552de0def246f58b45d7af15f5f5b47521 Mon Sep 17 00:00:00 2001 From: "ALLEN-PC\\acj30" Date: Sat, 10 Aug 2024 15:42:23 -0500 Subject: [PATCH] Playermodel legs and other player anim improvements --- sp/src/game/client/c_basecombatweapon.cpp | 46 ++- sp/src/game/client/c_baseplayer.cpp | 265 +++++++++++++++++- sp/src/game/client/c_baseplayer.h | 51 ++++ sp/src/game/client/hl2/c_basehlplayer.cpp | 134 +++++++++ sp/src/game/client/hl2/c_basehlplayer.h | 12 +- sp/src/game/server/ai_activity.cpp | 20 ++ sp/src/game/server/hl2/hl2_player.cpp | 57 ++++ sp/src/game/server/hl2/hl2_player.h | 1 + sp/src/game/server/player.cpp | 1 + sp/src/game/server/player.h | 4 + sp/src/game/shared/activitylist.cpp | 20 ++ sp/src/game/shared/ai_activity.h | 20 ++ sp/src/game/shared/base_playeranimstate.cpp | 25 +- sp/src/game/shared/basecombatweapon_shared.h | 4 + .../mapbase/mapbase_playeranimstate.cpp | 190 +++++++++++-- .../shared/mapbase/mapbase_playeranimstate.h | 18 +- sp/src/game/shared/mapbase/mapbase_shared.cpp | 2 + 17 files changed, 831 insertions(+), 39 deletions(-) diff --git a/sp/src/game/client/c_basecombatweapon.cpp b/sp/src/game/client/c_basecombatweapon.cpp index 3ae13cdee8..ff8e6d64f9 100644 --- a/sp/src/game/client/c_basecombatweapon.cpp +++ b/sp/src/game/client/c_basecombatweapon.cpp @@ -90,11 +90,10 @@ static inline bool ShouldDrawLocalPlayerViewModel( void ) C_BasePlayer *localplayer = C_BasePlayer::GetLocalPlayer(); if (localplayer) { - if (localplayer->m_bDrawPlayerModelExternally) + if (localplayer->DrawingPlayerModelExternally() && localplayer->InFirstPersonView()) { // If this isn't the main view, draw the weapon. - view_id_t viewID = CurrentViewID(); - if (viewID != VIEW_MAIN && viewID != VIEW_INTRO_CAMERA) + if (!localplayer->InPerspectiveView()) return false; } @@ -224,8 +223,16 @@ ShadowType_t C_BaseCombatWeapon::ShadowCastType() if (!IsBeingCarried()) return SHADOWS_RENDER_TO_TEXTURE; - if (IsCarriedByLocalPlayer() && !C_BasePlayer::ShouldDrawLocalPlayer()) - return SHADOWS_NONE; + if (IsCarriedByLocalPlayer()) + { + if (!C_BasePlayer::ShouldDrawLocalPlayer()) + return SHADOWS_NONE; + +#ifdef MAPBASE + if (C_BasePlayer::GetLocalPlayer() && C_BasePlayer::GetLocalPlayer()->ShadowCastType() == SHADOWS_NONE) + return SHADOWS_NONE; +#endif + } return SHADOWS_RENDER_TO_TEXTURE; } @@ -458,7 +465,7 @@ bool C_BaseCombatWeapon::ShouldDraw( void ) #ifdef MAPBASE // We're drawing this in non-main views, handle it in DrawModel() - if ( pLocalPlayer->m_bDrawPlayerModelExternally ) + if ( pLocalPlayer->DrawingPlayerModelExternally() ) return true; #endif @@ -511,11 +518,10 @@ int C_BaseCombatWeapon::DrawModel( int flags ) if ( localplayer ) { #ifdef MAPBASE - if (localplayer->m_bDrawPlayerModelExternally) + if (GetOwner() == localplayer && localplayer->DrawingPlayerModelExternally()) { // If this isn't the main view, draw the weapon. - view_id_t viewID = CurrentViewID(); - if ( (!localplayer->InFirstPersonView() || (viewID != VIEW_MAIN && viewID != VIEW_INTRO_CAMERA)) && (viewID != VIEW_SHADOW_DEPTH_TEXTURE || !localplayer->IsEffectActive(EF_DIMLIGHT)) ) + if ( (!localplayer->InPerspectiveView() || !localplayer->InFirstPersonView()) && (CurrentViewID() != VIEW_SHADOW_DEPTH_TEXTURE || !localplayer->IsEffectActive(EF_DIMLIGHT))) { // TODO: Is this inefficient? int nModelIndex = GetModelIndex(); @@ -534,6 +540,10 @@ int C_BaseCombatWeapon::DrawModel( int flags ) return iDraw; } + else + { + return 0; + } } #endif if ( localplayer->IsObserver() && GetOwner() ) @@ -551,6 +561,24 @@ int C_BaseCombatWeapon::DrawModel( int flags ) return BaseClass::DrawModel( flags ); } +#ifdef MAPBASE +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool C_BaseCombatWeapon::DispatchMuzzleEffect( const char *options, bool isFirstPerson ) +{ + // Don't show muzzle flashes in first-person + C_BasePlayer *pPlayer = ToBasePlayer( GetOwner() ); + if (pPlayer) + { + if (pPlayer->DrawingPlayerModelExternally() && pPlayer->InFirstPersonView()) + return false; + } + + return BaseClass::DispatchMuzzleEffect( options, isFirstPerson ); +} +#endif + //----------------------------------------------------------------------------- // Allows the client-side entity to override what the network tells it to use for diff --git a/sp/src/game/client/c_baseplayer.cpp b/sp/src/game/client/c_baseplayer.cpp index 6e06834155..57606dd00c 100644 --- a/sp/src/game/client/c_baseplayer.cpp +++ b/sp/src/game/client/c_baseplayer.cpp @@ -125,6 +125,16 @@ ConVar demo_fov_override( "demo_fov_override", "0", FCVAR_CLIENTDLL | FCVAR_DONT // This value is found by hand, and a good value depends more on the in-game models than on actual human shapes. ConVar cl_meathook_neck_pivot_ingame_up( "cl_meathook_neck_pivot_ingame_up", "7.0" ); ConVar cl_meathook_neck_pivot_ingame_fwd( "cl_meathook_neck_pivot_ingame_fwd", "3.0" ); +#ifdef MAPBASE +ConVar cl_meathook_neck_pivot_override( "cl_meathook_neck_pivot_override", "0", FCVAR_NONE, "Overrides playermodel values for meathook and uses cvars only" ); + +//------------------------------------------------------------------------------------- + +ConVar cl_playermodel_draw_externally_override( "cl_playermodel_draw_externally_override", "-1", FCVAR_ARCHIVE, "Overrides developer-placed options to draw the player's model externally." ); + +ConVar cl_playermodel_legs_override( "cl_playermodel_legs_override", "-1", FCVAR_ARCHIVE, "Overrides developer-placed options to draw the player's model below the camera." ); +ConVar cl_playermodel_legs_scale_bones( "cl_playermodel_legs_scale_bones", "1" ); +#endif void RecvProxy_LocalVelocityX( const CRecvProxyData *pData, void *pStruct, void *pOut ); void RecvProxy_LocalVelocityY( const CRecvProxyData *pData, void *pStruct, void *pOut ); @@ -280,6 +290,7 @@ END_RECV_TABLE() // See baseplayer_shared.h for more details. RecvPropInt ( RECVINFO( m_spawnflags ), 0, RecvProxy_ShiftPlayerSpawnflags ), + RecvPropBool ( RECVINFO( m_bDrawPlayerLegs ) ), RecvPropBool ( RECVINFO( m_bDrawPlayerModelExternally ) ), RecvPropBool ( RECVINFO( m_bInTriggerFall ) ), #endif @@ -1475,13 +1486,186 @@ bool C_BasePlayer::ShouldInterpolate() } +#ifdef MAPBASE +bool C_BasePlayer::InPerspectiveView() const +{ + // VIEW_NONE is used by the water intersection view, see CAboveWaterView::CIntersectionView::Draw() + // (TODO: Consider changing the view ID at the source to VIEW_REFRACTION? VIEW_NONE could be an oversight) + view_id_t viewID = CurrentViewID(); + return (viewID == VIEW_MAIN || viewID == VIEW_INTRO_CAMERA || viewID == VIEW_REFRACTION || viewID == VIEW_NONE); +} + +bool C_BasePlayer::DrawingPlayerModelExternally() const +{ + if (cl_playermodel_draw_externally_override.GetInt() > -1) + return cl_playermodel_draw_externally_override.GetBool(); + + return m_bDrawPlayerModelExternally; +} + +bool C_BasePlayer::DrawingLegs() const +{ + if (cl_playermodel_legs_override.GetInt() > -1) + return cl_playermodel_legs_override.GetBool(); + + // For now, don't draw legs if looking up in any way + // (fixes issues with some animations causing clipping with chest) + if (GetAbsAngles().x < 0.0f) + return false; + + return m_bDrawPlayerLegs; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CStudioHdr *C_BasePlayer::OnNewModel( void ) +{ + CStudioHdr *hdr = BaseClass::OnNewModel(); + if (!hdr) + return NULL; + + KeyValues *modelKeyValues = new KeyValues( "" ); + CUtlBuffer buf( 1024, 0, CUtlBuffer::TEXT_BUFFER ); + + // Init values + m_FirstPersonModelData.Reset(); + + if (!modelinfo->GetModelKeyValue( GetModel(), buf )) + { + modelKeyValues->deleteThis(); + return hdr; + } + + if (modelKeyValues->LoadFromBuffer( modelinfo->GetModelName( GetModel() ), buf )) + { + CUtlVector iszUsedNames; + for (KeyValues *pkvModelBlock = modelKeyValues; pkvModelBlock != nullptr; pkvModelBlock = pkvModelBlock->GetNextKey()) + { + KeyValues *pkvPlayerModelData = pkvModelBlock->FindKey( "playermodel_data" ); + if (pkvPlayerModelData) + { + m_FirstPersonModelData.ParseModelData( this, pkvPlayerModelData ); + break; + } + } + } + + modelKeyValues->deleteThis(); + + return hdr; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_BasePlayer::FirstPersonModelData_t::ParseModelData( C_BasePlayer *pPlayer, KeyValues *pkvPlayerModelData ) +{ + m_flFirstPersonNeckPivotUp = pkvPlayerModelData->GetFloat( "neck_pivot_up", FLT_MAX ); + m_flFirstPersonNeckPivotFwd = pkvPlayerModelData->GetFloat( "neck_pivot_fwd", FLT_MAX ); + + m_flFirstPersonNeckPivotDuckUp = pkvPlayerModelData->GetFloat( "neck_pivot_duck_up", FLT_MAX ); + m_flFirstPersonNeckPivotDuckFwd = pkvPlayerModelData->GetFloat( "neck_pivot_duck_fwd", FLT_MAX ); + + KeyValues *pkvBoneScales = pkvPlayerModelData->FindKey( "bone_transforms" ); + if (pkvBoneScales) + { + KeyValues *pkvSpineTransforms = pkvBoneScales->FindKey( "spine" ); + if (pkvSpineTransforms) + { + for (KeyValues *pkvBone = pkvSpineTransforms->GetFirstSubKey(); pkvBone != nullptr; pkvBone = pkvBone->GetNextKey()) + { + int nBone = pPlayer->LookupBone( pkvBone->GetName() ); + if (nBone == -1) + continue; + + m_FirstPersonBoneScales[BoneScales_Spine].Insert(nBone, pkvBone->GetFloat()); + } + } + + KeyValues *pkvArmsTransforms = pkvBoneScales->FindKey( "arms" ); + if (pkvArmsTransforms) + { + for (KeyValues *pkvBone = pkvArmsTransforms->GetFirstSubKey(); pkvBone != nullptr; pkvBone = pkvBone->GetNextKey()) + { + int nBone = pPlayer->LookupBone( pkvBone->GetName() ); + if (nBone == -1) + continue; + + m_FirstPersonBoneScales[BoneScales_Arms].Insert( nBone, pkvBone->GetFloat() ); + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: move position and rotation transforms into global matrices +//----------------------------------------------------------------------------- +void C_BasePlayer::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quaternion *q, const matrix3x4_t &cameraTransform, int boneMask, CBoneBitList &boneComputed ) +{ + BaseClass::BuildTransformations( hdr, pos, q, cameraTransform, boneMask, boneComputed ); + + if (DrawingLegs() && InPerspectiveView() && InFirstPersonView()) + { + //BuildFirstPersonMeathookTransformations( hdr, pos, q, cameraTransform, boneMask, boneComputed, "ValveBiped.Bip01_Head1" ); + + if (cl_playermodel_legs_scale_bones.GetBool()) + { + // For now, only do transforms when we have an active weapon + // (since we typically just cull stuff influenced by viewmodels and upper-body weapon posture, like arms) + if ((GetActiveWeapon() && !GetActiveWeapon()->IsEffectActive( EF_NODRAW )) || GetUseEntity()) + { + matrix3x4_t *pFirstZero = NULL; + + for (int nMap = 0; nMap < FirstPersonModelData_t::BoneScales_Max; nMap++) + { + const CUtlMap &scaleMap = m_FirstPersonModelData.m_FirstPersonBoneScales[nMap]; + FOR_EACH_MAP( scaleMap, i ) + { + int nBone = scaleMap.Key(i); + if (nBone == -1) + continue; + + if (!(hdr->boneFlags( nBone ) & boneMask)) + continue; + + float flScale = scaleMap.Element(i); + + matrix3x4_t &mTransform = GetBoneForWrite( nBone ); + + if (flScale == 0.0f) + { + if (!pFirstZero) + { + MatrixScaleByZero( mTransform ); + pFirstZero = &mTransform; + } + else + { + // Keep zeroes in one place + MatrixCopy( *pFirstZero, mTransform ); + } + } + else + { + MatrixScaleBy( flScale, mTransform ); + } + } + } + } + } + } +} +#endif + + bool C_BasePlayer::ShouldDraw() { #ifdef MAPBASE // We have to "always draw" a player with m_bDrawPlayerModelExternally in order to show up in whatever rendering list all of the views use, // but we can't put this in ShouldDrawThisPlayer() because we would have no way of knowing if it stomps the other checks that draw the player model anyway. // As a result, we have to put it here in the central ShouldDraw() function. DrawModel() makes sure we only draw in non-main views and nothing's drawing the model anyway. - return (ShouldDrawThisPlayer() || m_bDrawPlayerModelExternally) && BaseClass::ShouldDraw(); + return (ShouldDrawThisPlayer() || DrawingPlayerModelExternally() || DrawingLegs()) && BaseClass::ShouldDraw(); #else return ShouldDrawThisPlayer() && BaseClass::ShouldDraw(); #endif @@ -1490,12 +1674,16 @@ bool C_BasePlayer::ShouldDraw() int C_BasePlayer::DrawModel( int flags ) { #ifdef MAPBASE - if (m_bDrawPlayerModelExternally) + if (DrawingLegs() && InFirstPersonView() && InPerspectiveView()) + { + return BaseClass::DrawModel( flags ); + } + + if (DrawingPlayerModelExternally()) { // Draw the player in any view except the main or "intro" view, both of which are default first-person views. // HACKHACK: Also don't draw in shadow depth textures if the player's flashlight is on, as that causes the playermodel to block it. - view_id_t viewID = CurrentViewID(); - if (viewID == VIEW_MAIN || viewID == VIEW_INTRO_CAMERA || (viewID == VIEW_SHADOW_DEPTH_TEXTURE && IsEffectActive(EF_DIMLIGHT))) + if (InPerspectiveView() || (CurrentViewID() == VIEW_SHADOW_DEPTH_TEXTURE && IsEffectActive(EF_DIMLIGHT))) { // Make sure the player model wouldn't draw anyway... if (!ShouldDrawThisPlayer()) @@ -3046,13 +3234,21 @@ void C_BasePlayer::BuildFirstPersonMeathookTransformations( CStudioHdr *hdr, Vec return; } +#ifdef MAPBASE + if ( !InPerspectiveView() ) +#else if ( !DrawingMainView() ) +#endif { return; } // If we aren't drawing the player anyway, don't mess with the bones. This can happen in Portal. +#ifdef MAPBASE + if ( !ShouldDrawThisPlayer() && !DrawingPlayerModelExternally() && !DrawingLegs() ) +#else if( !ShouldDrawThisPlayer() ) +#endif { return; } @@ -3073,6 +3269,63 @@ void C_BasePlayer::BuildFirstPersonMeathookTransformations( CStudioHdr *hdr, Vec Vector vHeadTransformTranslation ( mHeadTransform[0][3], mHeadTransform[1][3], mHeadTransform[2][3] ); + float flNeckPivotUp = cl_meathook_neck_pivot_ingame_up.GetFloat(); + float flNeckPivotFwd = cl_meathook_neck_pivot_ingame_fwd.GetFloat(); +#ifdef MAPBASE + if (DrawingLegs() && !cl_meathook_neck_pivot_override.GetBool()) + { + if (m_FirstPersonModelData.m_flFirstPersonNeckPivotUp != FLT_MAX || m_FirstPersonModelData.m_flFirstPersonNeckPivotFwd != FLT_MAX) + { + if (m_FirstPersonModelData.m_flFirstPersonNeckPivotUp != FLT_MAX) + flNeckPivotUp = m_FirstPersonModelData.m_flFirstPersonNeckPivotUp; + if (m_FirstPersonModelData.m_flFirstPersonNeckPivotFwd != FLT_MAX) + flNeckPivotFwd = m_FirstPersonModelData.m_flFirstPersonNeckPivotFwd; + + if (GetFlags() & FL_DUCKING || m_Local.m_flDucktime > 0.0f) + { + if (!IsLocalPlayer() || m_Local.m_flDucktime <= 0.0f) + { + if (m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckUp != FLT_MAX) + flNeckPivotUp = m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckUp; + if (m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckFwd != FLT_MAX) + flNeckPivotFwd = m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckFwd; + } + else + { + bool bDucking; + if (IsLocalPlayer()) + bDucking = input->GetButtonBits(0) & IN_DUCK; + else + bDucking = GetCurrentUserCommand()->buttons & IN_DUCK; + + // HACKHACK using constants from game movement + float flPerc = SimpleSpline( RemapValClamped( m_Local.m_flDucktime, bDucking ? 600.0f : 800.0f, 1000.0f, 0.0f, 1.0f ) ); + + if (bDucking) + { + // Ducking + //Msg( "Ducking with perc %f (%f)\n", flPerc, m_Local.m_flDucktime ); + if (m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckUp != FLT_MAX) + flNeckPivotUp = FLerp( m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckUp, flNeckPivotUp, flPerc ); + if (m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckFwd != FLT_MAX) + flNeckPivotFwd = FLerp( m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckFwd, flNeckPivotFwd, flPerc ); + } + else + { + // Unducking + //Msg( "Unducking with perc %f (%f)\n", flPerc, m_Local.m_flDucktime ); + if (m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckUp != FLT_MAX) + flNeckPivotUp = FLerp( flNeckPivotUp, m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckUp, flPerc ); + if (m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckFwd != FLT_MAX) + flNeckPivotFwd = FLerp( flNeckPivotFwd, m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckFwd, flPerc ); + } + } + } + } + } +#endif + + // Find out where the player's head (driven by the HMD) is in the world. // We can't move this with animations or effects without causing nausea, so we need to move // the whole body so that the animated head is in the right place to match the player-controlled head. @@ -3089,7 +3342,7 @@ void C_BasePlayer::BuildFirstPersonMeathookTransformations( CStudioHdr *hdr, Vec // The head bone is the neck pivot point of the in-game character. Vector vRealMidEyePos = mWorldFromMideye.GetTranslation(); - vRealPivotPoint = vRealMidEyePos - ( mWorldFromMideye.GetUp() * cl_meathook_neck_pivot_ingame_up.GetFloat() ) - ( mWorldFromMideye.GetForward() * cl_meathook_neck_pivot_ingame_fwd.GetFloat() ); + vRealPivotPoint = vRealMidEyePos - ( mWorldFromMideye.GetUp() * flNeckPivotUp ) - ( mWorldFromMideye.GetForward() * flNeckPivotFwd ); } else { @@ -3097,7 +3350,7 @@ void C_BasePlayer::BuildFirstPersonMeathookTransformations( CStudioHdr *hdr, Vec Vector vForward, vRight, vUp; AngleVectors( MainViewAngles(), &vForward, &vRight, &vUp ); - vRealPivotPoint = MainViewOrigin() - ( vUp * cl_meathook_neck_pivot_ingame_up.GetFloat() ) - ( vForward * cl_meathook_neck_pivot_ingame_fwd.GetFloat() ); + vRealPivotPoint = MainViewOrigin() - ( vUp * flNeckPivotUp ) - ( vForward * flNeckPivotFwd ); } Vector vDeltaToAdd = vRealPivotPoint - vHeadTransformTranslation; diff --git a/sp/src/game/client/c_baseplayer.h b/sp/src/game/client/c_baseplayer.h index bc8ca65419..e985158648 100644 --- a/sp/src/game/client/c_baseplayer.h +++ b/sp/src/game/client/c_baseplayer.h @@ -293,6 +293,15 @@ class C_BasePlayer : public C_BaseCombatCharacter, public CGameEventListener virtual bool ShouldInterpolate(); +#ifdef MAPBASE + bool InPerspectiveView() const; // In a view that renders directly from the player's perspective (and may, for example, render the playermodel) + bool DrawingPlayerModelExternally() const; + bool DrawingLegs() const; + + virtual CStudioHdr *OnNewModel( void ); + virtual void BuildTransformations( CStudioHdr *pStudioHdr, Vector *pos, Quaternion q[], const matrix3x4_t &cameraTransform, int boneMask, CBoneBitList &boneComputed ); +#endif + virtual bool ShouldDraw(); virtual int DrawModel( int flags ); @@ -468,6 +477,9 @@ class C_BasePlayer : public C_BaseCombatCharacter, public CGameEventListener inline void RemoveSpawnFlags( int flags ) { m_spawnflags &= ~flags; } inline void AddSpawnFlags( int flags ) { m_spawnflags |= flags; } + // Draws the player's model below the camera, visible when the player looks down. + bool m_bDrawPlayerLegs; + // Allows the player's model to draw on non-main views, like monitors or mirrors. bool m_bDrawPlayerModelExternally; @@ -502,6 +514,10 @@ class C_BasePlayer : public C_BaseCombatCharacter, public CGameEventListener virtual void FireGameEvent( IGameEvent *event ); +#ifdef MAPBASE + inline CUtlMap &GetFirstPersonArmScales() { return m_FirstPersonModelData.m_FirstPersonBoneScales[FirstPersonModelData_t::BoneScales_Arms]; } +#endif + protected: // Did we just enter a vehicle this frame? bool JustEnteredVehicle(); @@ -556,6 +572,41 @@ class C_BasePlayer : public C_BaseCombatCharacter, public CGameEventListener bool m_bFiredWeapon; +#ifdef MAPBASE + struct FirstPersonModelData_t + { + void Reset() + { + m_flFirstPersonNeckPivotUp = m_flFirstPersonNeckPivotFwd = FLT_MAX; + m_flFirstPersonNeckPivotDuckUp = m_flFirstPersonNeckPivotDuckFwd = FLT_MAX; + + for (int i = 0; i < BoneScales_Max; i++) + { + m_FirstPersonBoneScales[i].RemoveAll(); + m_FirstPersonBoneScales[i].SetLessFunc( DefLessFunc( int ) ); + } + } + + void ParseModelData( C_BasePlayer *pPlayer, KeyValues *pkvPlayerModelData ); + + enum + { + BoneScales_Spine, + BoneScales_Arms, + + BoneScales_Max + }; + + // Values to scale bones by when drawing playermodel in first person + CUtlMap m_FirstPersonBoneScales[BoneScales_Max]; + + float m_flFirstPersonNeckPivotUp, m_flFirstPersonNeckPivotFwd = FLT_MAX; + float m_flFirstPersonNeckPivotDuckUp, m_flFirstPersonNeckPivotDuckFwd = FLT_MAX; + }; + + FirstPersonModelData_t m_FirstPersonModelData; +#endif + // Player flashlight dynamic light pointers CFlashlightEffect *m_pFlashlight; diff --git a/sp/src/game/client/hl2/c_basehlplayer.cpp b/sp/src/game/client/hl2/c_basehlplayer.cpp index 15a33ea8c2..5486ae656e 100644 --- a/sp/src/game/client/hl2/c_basehlplayer.cpp +++ b/sp/src/game/client/hl2/c_basehlplayer.cpp @@ -11,6 +11,10 @@ #include "c_ai_basenpc.h" #include "in_buttons.h" #include "collisionutils.h" +#ifdef EZ2 +#include "view_scene.h" +#include "viewrender.h" +#endif // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -33,6 +37,10 @@ IMPLEMENT_CLIENTCLASS_DT(C_BaseHLPlayer, DT_HL2_Player, CHL2_Player) RecvPropBool( RECVINFO( m_fIsSprinting ) ), #ifdef SP_ANIM_STATE RecvPropFloat( RECVINFO( m_flAnimRenderYaw ) ), + RecvPropFloat( RECVINFO( m_flAnimRenderZ ) ), +#endif +#ifdef EZ2 + RecvPropFloat( RECVINFO( m_flNextKickAttack ) ), #endif END_RECV_TABLE() @@ -103,6 +111,22 @@ void C_BaseHLPlayer::OnDataChanged( DataUpdateType_t updateType ) BaseClass::OnDataChanged( updateType ); } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_BaseHLPlayer::AddEntity( void ) +{ + BaseClass::AddEntity(); + +#ifdef MAPBASE_MP + if (m_pPlayerAnimState) + { + QAngle angEyeAngles = EyeAngles(); + m_pPlayerAnimState->Update( angEyeAngles.y, angEyeAngles.x ); + } +#endif +} + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- @@ -664,24 +688,134 @@ bool C_BaseHLPlayer::CreateMove( float flInputSampleTime, CUserCmd *pCmd ) void C_BaseHLPlayer::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed ) { BaseClass::BuildTransformations( hdr, pos, q, cameraTransform, boneMask, boneComputed ); +/*#ifdef MAPBASE + // BuildFirstPersonMeathookTransformations is used prior to this when drawing legs + if (!DrawingLegs() || !InPerspectiveView() || !InFirstPersonView()) +#endif*/ BuildFirstPersonMeathookTransformations( hdr, pos, q, cameraTransform, boneMask, boneComputed, "ValveBiped.Bip01_Head1" ); + +#ifdef EZ2 + // While kicking or admiring gloves, retract the playermodel in a 0-1 parabola + if (InPerspectiveView() && InFirstPersonView() && DrawingLegs()) + { + if (m_flNextKickAttack > gpGlobals->curtime) + { + float flPerc = sin( (m_flNextKickAttack - gpGlobals->curtime) * M_PI_F ); + + Vector vDeltaToAdd; + GetVectors( &vDeltaToAdd, NULL, NULL ); + + vDeltaToAdd *= -(64.0f * flPerc); + + for (int i = 0; i < hdr->numbones(); i++) + { + // Only update bones reference by the bone mask. + if (!(hdr->boneFlags( i ) & boneMask)) + { + continue; + } + matrix3x4_t &bone = GetBoneForWrite( i ); + Vector vBonePos; + MatrixGetTranslation( bone, vBonePos ); + vBonePos += vDeltaToAdd; + MatrixSetTranslation( vBonePos, bone ); + } + } + else if (C_BaseViewModel *pVM = GetViewModel( 0 )) + { + if (!pVM->GetOwningWeapon() && pVM->GetCycle() < 1.0f) + { + float flPerc = sin( pVM->GetCycle() * M_PI_F ); + + Vector vDeltaToAdd; + GetVectors( &vDeltaToAdd, NULL, NULL ); + + vDeltaToAdd *= -(32.0f * flPerc); + + FOR_EACH_MAP_FAST( GetFirstPersonArmScales(), i ) + { + int nBone = GetFirstPersonArmScales().Key( i ); + if (nBone == -1) + continue; + + if (!(hdr->boneFlags( nBone ) & boneMask)) + continue; + + matrix3x4_t &bone = GetBoneForWrite( nBone ); + Vector vBonePos; + MatrixGetTranslation( bone, vBonePos ); + vBonePos += vDeltaToAdd; + MatrixSetTranslation( vBonePos, bone ); + } + } + } + } +#endif } #ifdef SP_ANIM_STATE +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +const Vector &C_BaseHLPlayer::GetRenderOrigin() +{ + if (m_flAnimRenderZ != 0.0f) + { + static Vector vecRender; + vecRender = BaseClass::GetRenderOrigin(); + vecRender.z += m_flAnimRenderZ; + return vecRender; + } + + return BaseClass::GetRenderOrigin(); +} + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- const QAngle& C_BaseHLPlayer::GetRenderAngles( void ) { +#ifdef MAPBASE_MP + if ( m_pPlayerAnimState ) + { + return m_pPlayerAnimState->GetRenderAngles(); + } +#else if ( m_flAnimRenderYaw != FLT_MAX ) { return m_angAnimRender; } +#endif else { return BaseClass::GetRenderAngles(); } } + +//----------------------------------------------------------------------------- +// Purpose: model-change notification. Fires on dynamic load completion as well +//----------------------------------------------------------------------------- +CStudioHdr *C_BaseHLPlayer::OnNewModel() +{ + CStudioHdr *hdr = BaseClass::OnNewModel(); + +#ifdef MAPBASE_MP + // Clears the animation state if we already have one. + if ( m_pPlayerAnimState != NULL ) + { + m_pPlayerAnimState->Release(); + m_pPlayerAnimState = NULL; + } + + 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); + } +#endif + + return hdr; +} #endif diff --git a/sp/src/game/client/hl2/c_basehlplayer.h b/sp/src/game/client/hl2/c_basehlplayer.h index a6fe684a0c..994df98257 100644 --- a/sp/src/game/client/hl2/c_basehlplayer.h +++ b/sp/src/game/client/hl2/c_basehlplayer.h @@ -29,6 +29,7 @@ class C_BaseHLPlayer : public C_BasePlayer C_BaseHLPlayer(); virtual void OnDataChanged( DataUpdateType_t updateType ); + virtual void AddEntity( void ); void Weapon_DropPrimary( void ); @@ -63,7 +64,9 @@ class C_BaseHLPlayer : public C_BasePlayer bool IsWeaponLowered( void ) { return m_HL2Local.m_bWeaponLowered; } #ifdef SP_ANIM_STATE + virtual const Vector& GetRenderOrigin(); virtual const QAngle& GetRenderAngles( void ); + virtual CStudioHdr *OnNewModel(); #endif public: @@ -87,13 +90,20 @@ class C_BaseHLPlayer : public C_BasePlayer float m_flSpeedMod; float m_flExitSpeedMod; -#ifdef SP_ANIM_STATE +#ifdef MAPBASE_MP + CSinglePlayerAnimState *m_pPlayerAnimState; +#elif MAPBASE // 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; + float m_flAnimRenderZ; QAngle m_angAnimRender; #endif +#ifdef EZ2 + float m_flNextKickAttack; +#endif + friend class CHL2GameMovement; }; diff --git a/sp/src/game/server/ai_activity.cpp b/sp/src/game/server/ai_activity.cpp index e20bfc48db..6c10d7ea16 100644 --- a/sp/src/game/server/ai_activity.cpp +++ b/sp/src/game/server/ai_activity.cpp @@ -2594,6 +2594,18 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) 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_GESTURE_RELAX ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_PISTOL ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_SHOTGUN ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_SMG1 ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_AR2 ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_PHYSGUN ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_GRENADE ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_RPG ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_CROSSBOW ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_MELEE ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_SLAM ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_REVOLVER ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_RUN_REVOLVER ); @@ -2603,6 +2615,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) 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_GESTURE_RELAX_REVOLVER ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_REVOLVER ); #if EXPANDED_HL2_UNUSED_WEAPON_ACTIVITIES @@ -2614,6 +2627,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_AR1 ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR1 ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_AR1 ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_AR1 ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_AR1 ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_AR3 ); @@ -2624,6 +2638,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_AR3 ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR3 ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_AR3 ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_AR3 ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_AR3 ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_SMG2 ); @@ -2634,6 +2649,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG2 ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG2 ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_SMG2 ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_SMG2 ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_SMG2 ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_SMG3 ); @@ -2644,6 +2660,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG3 ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG3 ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_SMG3 ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_SMG3 ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_SMG3 ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_HMG1 ); @@ -2654,6 +2671,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_HMG1 ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_HMG1 ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_HMG1 ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_HMG1 ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_HMG1 ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_SNIPER_RIFLE ); @@ -2664,6 +2682,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_SNIPER_RIFLE ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SNIPER_RIFLE ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_SNIPER_RIFLE ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_SNIPER_RIFLE ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_SNIPER_RIFLE ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_DUAL_PISTOLS ); @@ -2674,6 +2693,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_DUAL_PISTOLS ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_DUAL_PISTOLS ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_DUAL_PISTOLS ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_DUAL_PISTOLS ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_DUAL_PISTOLS ); #endif diff --git a/sp/src/game/server/hl2/hl2_player.cpp b/sp/src/game/server/hl2/hl2_player.cpp index cefdeeb41a..eb7ad336ff 100644 --- a/sp/src/game/server/hl2/hl2_player.cpp +++ b/sp/src/game/server/hl2/hl2_player.cpp @@ -121,6 +121,7 @@ ConVar player_autoswitch_enabled( "player_autoswitch_enabled", "1", FCVAR_NONE, #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)" ); +ConVar player_process_scene_events( "player_process_scene_events", "1", FCVAR_NONE, "Allows players to process scene events." ); #endif #endif @@ -267,6 +268,7 @@ class CLogicPlayerProxy : public CLogicalEntity void InputSetHandModelBodyGroup( inputdata_t &inputdata ); void InputSetPlayerModel( inputdata_t &inputdata ); + void InputSetPlayerDrawLegs( inputdata_t &inputdata ); void InputSetPlayerDrawExternally( inputdata_t &inputdata ); #endif @@ -674,6 +676,7 @@ IMPLEMENT_SERVERCLASS_ST(CHL2_Player, DT_HL2_Player) SendPropBool( SENDINFO(m_fIsSprinting) ), #ifdef SP_ANIM_STATE SendPropFloat( SENDINFO(m_flAnimRenderYaw), 0, SPROP_NOSCALE ), + SendPropFloat( SENDINFO(m_flAnimRenderZ), 0, SPROP_NOSCALE ), #endif END_SEND_TABLE() @@ -1166,6 +1169,18 @@ void CHL2_Player::PostThink( void ) m_pPlayerAnimState->Update( angEyeAngles.y, angEyeAngles.x ); m_flAnimRenderYaw.Set( m_pPlayerAnimState->GetRenderAngles().y ); + + if (m_pPlayerAnimState->IsJumping() && !m_pPlayerAnimState->IsDuckJumping()) + { + m_flAnimRenderZ.Set( -(GetViewOffset().z) ); + } + else + m_flAnimRenderZ.Set( 0.0f ); + + if (player_process_scene_events.GetBool()) + { + ProcessSceneEvents(); + } } #endif } @@ -1483,6 +1498,7 @@ CStudioHdr *CHL2_Player::OnNewModel() } extern char g_szDefaultPlayerModel[MAX_PATH]; +extern bool g_bDefaultPlayerLegs; extern bool g_bDefaultPlayerDrawExternally; #endif @@ -1515,6 +1531,7 @@ void CHL2_Player::Spawn(void) RemoveEffects( EF_NODRAW ); } + SetDrawPlayerLegs( g_bDefaultPlayerLegs ); SetDrawPlayerModelExternally( g_bDefaultPlayerDrawExternally ); #endif @@ -3349,6 +3366,11 @@ void CHL2_Player::Weapon_Equip( CBaseCombatWeapon *pWeapon ) if( GetActiveWeapon() == NULL ) { m_HL2Local.m_bWeaponLowered = false; + +#ifdef SP_ANIM_STATE + if (m_pPlayerAnimState) + m_pPlayerAnimState->StopWeaponRelax(); +#endif } BaseClass::Weapon_Equip( pWeapon ); @@ -3740,6 +3762,11 @@ bool CHL2_Player::Weapon_Lower( void ) m_HL2Local.m_bWeaponLowered = true; +#ifdef SP_ANIM_STATE + if (m_pPlayerAnimState) + m_pPlayerAnimState->StartWeaponRelax(); +#endif + CBaseCombatWeapon *pWeapon = dynamic_cast(GetActiveWeapon()); if ( pWeapon == NULL ) @@ -3762,6 +3789,11 @@ bool CHL2_Player::Weapon_Ready( void ) m_HL2Local.m_bWeaponLowered = false; +#ifdef SP_ANIM_STATE + if (m_pPlayerAnimState) + m_pPlayerAnimState->StopWeaponRelax(); +#endif + CBaseCombatWeapon *pWeapon = dynamic_cast(GetActiveWeapon()); if ( pWeapon == NULL ) @@ -3975,6 +4007,21 @@ void CHL2_Player::OnRestore() { BaseClass::OnRestore(); m_pPlayerAISquad = g_AI_SquadManager.FindCreateSquad(AllocPooledString(PLAYER_SQUADNAME)); + +#ifdef SP_ANIM_STATE + if ( m_pPlayerAnimState == NULL ) + { + if ( GetModelPtr() && GetModelPtr()->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 } //--------------------------------------------------------- @@ -4580,6 +4627,7 @@ BEGIN_DATADESC( CLogicPlayerProxy ) DEFINE_INPUTFUNC( FIELD_INTEGER, "SetHandModelSkin", InputSetHandModelSkin ), DEFINE_INPUTFUNC( FIELD_INTEGER, "SetHandModelBodyGroup", InputSetHandModelBodyGroup ), DEFINE_INPUTFUNC( FIELD_STRING, "SetPlayerModel", InputSetPlayerModel ), + DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetPlayerDrawLegs", InputSetPlayerDrawLegs ), DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetPlayerDrawExternally", InputSetPlayerDrawExternally ), DEFINE_INPUT( m_MaxArmor, FIELD_INTEGER, "SetMaxInputArmor" ), DEFINE_INPUT( m_SuitZoomFOV, FIELD_INTEGER, "SetSuitZoomFOV" ), @@ -5058,6 +5106,15 @@ void CLogicPlayerProxy::InputSetPlayerModel( inputdata_t &inputdata ) m_hPlayer->SetModel( STRING(iszModel) ); } +void CLogicPlayerProxy::InputSetPlayerDrawLegs( inputdata_t &inputdata ) +{ + if (!m_hPlayer) + return; + + CBasePlayer *pPlayer = static_cast(m_hPlayer.Get()); + pPlayer->SetDrawPlayerLegs( inputdata.value.Bool() ); +} + void CLogicPlayerProxy::InputSetPlayerDrawExternally( inputdata_t &inputdata ) { if (!m_hPlayer) diff --git a/sp/src/game/server/hl2/hl2_player.h b/sp/src/game/server/hl2/hl2_player.h index 8269a42826..0238524f58 100644 --- a/sp/src/game/server/hl2/hl2_player.h +++ b/sp/src/game/server/hl2/hl2_player.h @@ -448,6 +448,7 @@ class CHL2_Player : public CBasePlayer // 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 ); + CNetworkVar( float, m_flAnimRenderZ ); #endif }; diff --git a/sp/src/game/server/player.cpp b/sp/src/game/server/player.cpp index 28c767c5d4..969ef8eda2 100644 --- a/sp/src/game/server/player.cpp +++ b/sp/src/game/server/player.cpp @@ -8857,6 +8857,7 @@ void SendProxy_ShiftPlayerSpawnflags( const SendProp *pProp, const void *pStruct // See baseplayer_shared.h for more details. SendPropInt ( SENDINFO( m_spawnflags ), 3, SPROP_UNSIGNED, SendProxy_ShiftPlayerSpawnflags ), + SendPropBool ( SENDINFO( m_bDrawPlayerLegs ) ), SendPropBool ( SENDINFO( m_bDrawPlayerModelExternally ) ), SendPropBool ( SENDINFO( m_bInTriggerFall ) ), #endif diff --git a/sp/src/game/server/player.h b/sp/src/game/server/player.h index 72a1e38e38..6689a33236 100644 --- a/sp/src/game/server/player.h +++ b/sp/src/game/server/player.h @@ -1176,6 +1176,9 @@ class CBasePlayer : public CBaseCombatCharacter int m_nNumCrateHudHints; #ifdef MAPBASE + bool GetDrawPlayerLegs( void ) { return m_bDrawPlayerLegs; } + void SetDrawPlayerLegs( bool bToggle ) { m_bDrawPlayerLegs.Set( bToggle ); } + bool GetDrawPlayerModelExternally( void ) { return m_bDrawPlayerModelExternally; } void SetDrawPlayerModelExternally( bool bToggle ) { m_bDrawPlayerModelExternally.Set( bToggle ); } #endif @@ -1219,6 +1222,7 @@ class CBasePlayer : public CBaseCombatCharacter char m_szNetname[MAX_PLAYER_NAME_LENGTH]; #ifdef MAPBASE + CNetworkVar( bool, m_bDrawPlayerLegs ); CNetworkVar( bool, m_bDrawPlayerModelExternally ); #endif diff --git a/sp/src/game/shared/activitylist.cpp b/sp/src/game/shared/activitylist.cpp index 0b415d75df..4a8e097521 100644 --- a/sp/src/game/shared/activitylist.cpp +++ b/sp/src/game/shared/activitylist.cpp @@ -2694,6 +2694,18 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_MELEE ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SLAM ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_PISTOL ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_SHOTGUN ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_SMG1 ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_AR2 ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_PHYSGUN ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_GRENADE ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_RPG ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_CROSSBOW ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_MELEE ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_SLAM ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_REVOLVER ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_RUN_REVOLVER ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_WALK_REVOLVER ); @@ -2702,6 +2714,7 @@ void ActivityList_RegisterSharedActivities( void ) 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_GESTURE_RELAX_REVOLVER ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_REVOLVER ); #if EXPANDED_HL2_UNUSED_WEAPON_ACTIVITIES @@ -2713,6 +2726,7 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_AR1 ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR1 ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_AR1 ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_AR1 ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_AR1 ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_AR3 ); @@ -2723,6 +2737,7 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_AR3 ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR3 ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_AR3 ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_AR3 ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_AR3 ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_SMG2 ); @@ -2733,6 +2748,7 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG2 ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG2 ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_SMG2 ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_SMG2 ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_SMG2 ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_SMG3 ); @@ -2743,6 +2759,7 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG3 ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG3 ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_SMG3 ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_SMG3 ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_SMG3 ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_HMG1 ); @@ -2753,6 +2770,7 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_HMG1 ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_HMG1 ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_HMG1 ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_HMG1 ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_HMG1 ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_SNIPER_RIFLE ); @@ -2763,6 +2781,7 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_SNIPER_RIFLE ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SNIPER_RIFLE ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_SNIPER_RIFLE ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_SNIPER_RIFLE ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_SNIPER_RIFLE ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_DUAL_PISTOLS ); @@ -2773,6 +2792,7 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_DUAL_PISTOLS ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_DUAL_PISTOLS ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_DUAL_PISTOLS ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_DUAL_PISTOLS ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_DUAL_PISTOLS ); #endif diff --git a/sp/src/game/shared/ai_activity.h b/sp/src/game/shared/ai_activity.h index c8bf150a5c..35d584cf7e 100644 --- a/sp/src/game/shared/ai_activity.h +++ b/sp/src/game/shared/ai_activity.h @@ -2598,6 +2598,18 @@ typedef enum ACT_HL2MP_GESTURE_RANGE_ATTACK2_MELEE, ACT_HL2MP_GESTURE_RANGE_ATTACK2_SLAM, + ACT_HL2MP_GESTURE_RELAX, + ACT_HL2MP_GESTURE_RELAX_PISTOL, + ACT_HL2MP_GESTURE_RELAX_SHOTGUN, + ACT_HL2MP_GESTURE_RELAX_SMG1, + ACT_HL2MP_GESTURE_RELAX_AR2, + ACT_HL2MP_GESTURE_RELAX_PHYSGUN, + ACT_HL2MP_GESTURE_RELAX_GRENADE, + ACT_HL2MP_GESTURE_RELAX_RPG, + ACT_HL2MP_GESTURE_RELAX_CROSSBOW, + ACT_HL2MP_GESTURE_RELAX_MELEE, + ACT_HL2MP_GESTURE_RELAX_SLAM, + ACT_HL2MP_IDLE_REVOLVER, ACT_HL2MP_RUN_REVOLVER, ACT_HL2MP_WALK_REVOLVER, @@ -2606,6 +2618,7 @@ typedef enum ACT_HL2MP_GESTURE_RANGE_ATTACK_REVOLVER, ACT_HL2MP_GESTURE_RANGE_ATTACK2_REVOLVER, ACT_HL2MP_GESTURE_RELOAD_REVOLVER, + ACT_HL2MP_GESTURE_RELAX_REVOLVER, ACT_HL2MP_JUMP_REVOLVER, #if EXPANDED_HL2_UNUSED_WEAPON_ACTIVITIES @@ -2618,6 +2631,7 @@ typedef enum ACT_HL2MP_GESTURE_RANGE_ATTACK_AR1, ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR1, ACT_HL2MP_GESTURE_RELOAD_AR1, + ACT_HL2MP_GESTURE_RELAX_AR1, ACT_HL2MP_JUMP_AR1, ACT_HL2MP_IDLE_AR3, @@ -2628,6 +2642,7 @@ typedef enum ACT_HL2MP_GESTURE_RANGE_ATTACK_AR3, ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR3, ACT_HL2MP_GESTURE_RELOAD_AR3, + ACT_HL2MP_GESTURE_RELAX_AR3, ACT_HL2MP_JUMP_AR3, ACT_HL2MP_IDLE_SMG2, @@ -2638,6 +2653,7 @@ typedef enum ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG2, ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG2, ACT_HL2MP_GESTURE_RELOAD_SMG2, + ACT_HL2MP_GESTURE_RELAX_SMG2, ACT_HL2MP_JUMP_SMG2, ACT_HL2MP_IDLE_SMG3, @@ -2648,6 +2664,7 @@ typedef enum ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG3, ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG3, ACT_HL2MP_GESTURE_RELOAD_SMG3, + ACT_HL2MP_GESTURE_RELAX_SMG3, ACT_HL2MP_JUMP_SMG3, ACT_HL2MP_IDLE_HMG1, @@ -2658,6 +2675,7 @@ typedef enum ACT_HL2MP_GESTURE_RANGE_ATTACK_HMG1, ACT_HL2MP_GESTURE_RANGE_ATTACK2_HMG1, ACT_HL2MP_GESTURE_RELOAD_HMG1, + ACT_HL2MP_GESTURE_RELAX_HMG1, ACT_HL2MP_JUMP_HMG1, ACT_HL2MP_IDLE_SNIPER_RIFLE, @@ -2668,6 +2686,7 @@ typedef enum ACT_HL2MP_GESTURE_RANGE_ATTACK_SNIPER_RIFLE, ACT_HL2MP_GESTURE_RANGE_ATTACK2_SNIPER_RIFLE, ACT_HL2MP_GESTURE_RELOAD_SNIPER_RIFLE, + ACT_HL2MP_GESTURE_RELAX_SNIPER_RIFLE, ACT_HL2MP_JUMP_SNIPER_RIFLE, ACT_HL2MP_IDLE_DUAL_PISTOLS, @@ -2678,6 +2697,7 @@ typedef enum ACT_HL2MP_GESTURE_RANGE_ATTACK_DUAL_PISTOLS, ACT_HL2MP_GESTURE_RANGE_ATTACK2_DUAL_PISTOLS, ACT_HL2MP_GESTURE_RELOAD_DUAL_PISTOLS, + ACT_HL2MP_GESTURE_RELAX_DUAL_PISTOLS, ACT_HL2MP_JUMP_DUAL_PISTOLS, #endif diff --git a/sp/src/game/shared/base_playeranimstate.cpp b/sp/src/game/shared/base_playeranimstate.cpp index 82cb75aae2..d0426df46a 100644 --- a/sp/src/game/shared/base_playeranimstate.cpp +++ b/sp/src/game/shared/base_playeranimstate.cpp @@ -18,12 +18,12 @@ #include "c_baseplayer.h" #include "engine/ivdebugoverlay.h" - ConVar cl_showanimstate( "cl_showanimstate", "-1", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Show the (client) animation state for the specified entity (-1 for none)." ); - ConVar showanimstate_log( "cl_showanimstate_log", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "1 to output cl_showanimstate to Msg(). 2 to store in AnimStateClient.log. 3 for both." ); + ConVar cl_showanimstate( "cl_showanimstate", "-1", FCVAR_CHEAT /*| FCVAR_DEVELOPMENTONLY*/, "Show the (client) animation state for the specified entity (-1 for none)." ); + ConVar showanimstate_log( "cl_showanimstate_log", "0", FCVAR_CHEAT /*| FCVAR_DEVELOPMENTONLY*/, "1 to output cl_showanimstate to Msg(). 2 to store in AnimStateClient.log. 3 for both." ); #else #include "player.h" - ConVar sv_showanimstate( "sv_showanimstate", "-1", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Show the (server) animation state for the specified entity (-1 for none)." ); - ConVar showanimstate_log( "sv_showanimstate_log", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "1 to output sv_showanimstate to Msg(). 2 to store in AnimStateServer.log. 3 for both." ); + ConVar sv_showanimstate( "sv_showanimstate", "-1", FCVAR_CHEAT /*| FCVAR_DEVELOPMENTONLY*/, "Show the (server) animation state for the specified entity (-1 for none)." ); + ConVar showanimstate_log( "sv_showanimstate_log", "0", FCVAR_CHEAT /*| FCVAR_DEVELOPMENTONLY*/, "1 to output sv_showanimstate to Msg(). 2 to store in AnimStateServer.log. 3 for both." ); #endif @@ -654,9 +654,11 @@ void CBasePlayerAnimState::ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr ) if ( m_AnimConfig.m_LegAnimType == LEGANIM_9WAY ) { +#ifndef MAPBASE // This causes problems with entities that rely on the player having a pitch (TODO: gate behind virtual function?) #ifndef CLIENT_DLL //Adrian: Make the model's angle match the legs so the hitboxes match on both sides. GetOuter()->SetLocalAngles( QAngle( 0, m_flCurrentFeetYaw, 0 ) ); +#endif #endif int iMoveX = GetOuter()->LookupPoseParameter( pStudioHdr, "move_x" ); @@ -942,6 +944,15 @@ void CBasePlayerAnimState::GetOuterAbsVelocity( Vector& vel ) const #else vel = GetOuter()->GetAbsVelocity(); #endif + +#ifdef MAPBASE + if (GetOuter()->IsPlayer()) + { + CBasePlayer *pPlayer = ToBasePlayer( GetOuter() ); + if (pPlayer->GetLaggedMovementValue() != 1.0f) + vel *= pPlayer->GetLaggedMovementValue(); + } +#endif } @@ -1024,9 +1035,15 @@ void CBasePlayerAnimState::DebugShowAnimState( int iStartLine ) (float)pLayer->m_flWeight ); } +#ifdef MAPBASE + for ( int i=0; i < m_pOuter->GetNumAnimOverlays(); i++ ) + { + CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( i ); +#else for ( int i=0; i < m_pOuter->GetNumAnimOverlays()-1; i++ ) { CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( AIMSEQUENCE_LAYER + i ); +#endif #ifdef CLIENT_DLL AnimStatePrintf( iLine++, "%s(%d), weight: %.2f, cycle: %.2f, order (%d), aim (%d)", !pLayer->IsActive() ? "-- ": (pLayer->m_nSequence == 0 ? "-- " : GetSequenceName( m_pOuter->GetModelPtr(), pLayer->m_nSequence ) ), diff --git a/sp/src/game/shared/basecombatweapon_shared.h b/sp/src/game/shared/basecombatweapon_shared.h index 1b4119998e..75657542f3 100644 --- a/sp/src/game/shared/basecombatweapon_shared.h +++ b/sp/src/game/shared/basecombatweapon_shared.h @@ -307,6 +307,10 @@ class CBaseCombatWeapon : public BASECOMBATWEAPON_DERIVED_FROM virtual bool ShouldBlockPrimaryFire() { return false; } #ifdef CLIENT_DLL +#ifdef MAPBASE + virtual bool DispatchMuzzleEffect( const char *options, bool isFirstPerson ); +#endif + virtual void CreateMove( float flInputSampleTime, CUserCmd *pCmd, const QAngle &vecOldViewAngles ) {} virtual int CalcOverrideModelIndex() OVERRIDE; #endif diff --git a/sp/src/game/shared/mapbase/mapbase_playeranimstate.cpp b/sp/src/game/shared/mapbase/mapbase_playeranimstate.cpp index 0cbd4f4ff1..9046b644c6 100644 --- a/sp/src/game/shared/mapbase/mapbase_playeranimstate.cpp +++ b/sp/src/game/shared/mapbase/mapbase_playeranimstate.cpp @@ -23,19 +23,27 @@ #include "utldict.h" #include "filesystem.h" #include "in_buttons.h" +#include "gamemovement.h" #include "datacache/imdlcache.h" +#ifdef CLIENT_DLL +#include "input.h" +#endif -extern ConVar mp_facefronttime, mp_feetyawrate, mp_ik; +extern ConVar mp_facefronttime, mp_feetyawrate; ConVar sv_playeranimstate_animtype( "sv_playeranimstate_animtype", "0", FCVAR_NONE, "The leg animation type used by the Mapbase 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 Mapbase animation state." ); -ConVar sv_playeranimstate_use_aim_sequences( "sv_playeranimstate_use_aim_sequences", "1", FCVAR_NONE, "Allows the Mapbase animation state to use aim sequences." ); +ConVar sv_playeranimstate_use_aim_sequences( "sv_playeranimstate_use_aim_sequences", "0", FCVAR_NONE, "Allows the Mapbase animation state to use aim sequences." ); +ConVar sv_playeranimstate_use_walk_anims( "sv_playeranimstate_use_walk_anims", "0", FCVAR_NONE, "Allows the Mapbase animation state to use walk animations when the player is walking." ); #define MIN_TURN_ANGLE_REQUIRING_TURN_ANIMATION 15.0f +#define WEAPON_RELAX_TIME 0.5f + #define FIRESEQUENCE_LAYER (AIMSEQUENCE_LAYER+NUM_AIMSEQUENCE_LAYERS) #define RELOADSEQUENCE_LAYER (FIRESEQUENCE_LAYER + 1) -#define NUM_LAYERS_WANTED (RELOADSEQUENCE_LAYER + 1) +#define MISCSEQUENCE_LAYER (RELOADSEQUENCE_LAYER + 1) +#define NUM_LAYERS_WANTED (MISCSEQUENCE_LAYER + 1) CMapbasePlayerAnimState *CreatePlayerAnimationState( CBasePlayer *pPlayer ) { @@ -65,7 +73,6 @@ CMapbasePlayerAnimState *CreatePlayerAnimationState( CBasePlayer *pPlayer ) extern ConVar sv_backspeed; extern ConVar mp_feetyawrate; extern ConVar mp_facefronttime; -extern ConVar mp_ik; CMapbasePlayerAnimState::CMapbasePlayerAnimState( CBasePlayer *pPlayer ): m_pPlayer( pPlayer ) { @@ -76,11 +83,11 @@ CMapbasePlayerAnimState::CMapbasePlayerAnimState( CBasePlayer *pPlayer ): m_pPla //----------------------------------------------------------------------------- Activity CMapbasePlayerAnimState::CalcMainActivity() { -#ifdef CLIENT_DLL - return ACT_IDLE; -#else float speed = GetOuter()->GetAbsVelocity().Length2D(); + if (m_pPlayer->GetLaggedMovementValue() != 1.0f) + speed *= m_pPlayer->GetLaggedMovementValue(); + if ( HandleJumping() ) { return ACT_HL2MP_JUMP; @@ -95,7 +102,24 @@ Activity CMapbasePlayerAnimState::CalcMainActivity() } else { - if ( GetOuter()->GetFlags() & FL_DUCKING ) + bool bDucking = GetOuter()->GetFlags() & FL_DUCKING; + + // (currently singleplayer-exclusive since clients can't read whether other players are holding down IN_DUCK) + if (m_pPlayer->m_Local.m_flDucktime > 0 && gpGlobals->maxClients == 1) + { + // Consider ducking if half-way through duck time + bDucking = (m_pPlayer->m_Local.m_flDucktime < (GAMEMOVEMENT_DUCK_TIME * 0.9f)); + + // Unducking +#ifdef CLIENT_DLL + if (!((m_pPlayer->IsLocalPlayer() ? input->GetButtonBits( 0 ) : m_pPlayer->GetCurrentUserCommand()->buttons) & IN_DUCK)) +#else + if (!(m_pPlayer->m_nButtons & IN_DUCK)) +#endif + bDucking = !bDucking; + } + + if ( bDucking ) { if ( speed > 0 ) { @@ -111,7 +135,7 @@ Activity CMapbasePlayerAnimState::CalcMainActivity() if ( speed > 0 ) { #if EXPANDED_HL2DM_ACTIVITIES - if ( m_pPlayer->GetButtons() & IN_WALK ) + if ( m_pPlayer->m_nButtons & IN_WALK && sv_playeranimstate_use_walk_anims.GetBool() ) { idealActivity = ACT_HL2MP_WALK; } @@ -132,7 +156,6 @@ Activity CMapbasePlayerAnimState::CalcMainActivity() } //return m_pPlayer->GetActivity(); -#endif } //----------------------------------------------------------------------------- @@ -162,6 +185,7 @@ void CMapbasePlayerAnimState::SetPlayerAnimation( PLAYER_ANIM playerAnim ) if (!m_bJumping) { m_bJumping = true; + m_bDuckJumping = GetOuter()->GetFlags() & FL_DUCKING; //m_pPlayer->m_nButtons & IN_DUCK; m_bFirstJumpFrame = true; m_flJumpStartTime = gpGlobals->curtime; } @@ -184,13 +208,13 @@ void CMapbasePlayerAnimState::SetPlayerAnimation( PLAYER_ANIM playerAnim ) if (m_iWeaponSwitchSequence != -1) { // clear other events that might be playing in our layer - m_bPlayingMisc = false; + //m_bPlayingMisc = false; m_bReloading = false; m_bWeaponSwitching = true; m_flWeaponSwitchCycle = 0; - m_flMiscBlendOut = 0.1f; - m_flMiscBlendIn = 0.1f; + //m_flMiscBlendOut = 0.1f; + //m_flMiscBlendIn = 0.1f; m_bMiscNoOverride = false; } } @@ -230,6 +254,7 @@ bool CMapbasePlayerAnimState::HandleJumping() if ( m_pOuter->GetFlags() & FL_ONGROUND || GetOuter()->GetGroundEntity() != NULL) { m_bJumping = false; + m_bDuckJumping = false; RestartMainSequence(); // Reset the animation. } } @@ -249,7 +274,8 @@ void CMapbasePlayerAnimState::ComputeSequences( CStudioHdr *pStudioHdr ) ComputeFireSequence(); ComputeMiscSequence(); ComputeReloadSequence(); - ComputeWeaponSwitchSequence(); + ComputeWeaponSwitchSequence(); + ComputeRelaxSequence(); } //----------------------------------------------------------------------------- @@ -265,19 +291,42 @@ void CMapbasePlayerAnimState::AddMiscSequence( int iSequence, float flBlendIn, f m_bPlayingMisc = true; m_bMiscHoldAtEnd = bHoldAtEnd; - m_bReloading = false; + //m_bReloading = false; m_flMiscCycle = 0; m_bMiscOnlyWhenStill = bOnlyWhenStill; m_bMiscNoOverride = true; m_fMiscPlaybackRate = flPlaybackRate; } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMapbasePlayerAnimState::StartWeaponRelax() +{ + if (m_bWeaponRelaxing) + return; + + m_bWeaponRelaxing = true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMapbasePlayerAnimState::StopWeaponRelax() +{ + if (!m_bWeaponRelaxing) + return; + + m_bWeaponRelaxing = false; +} + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMapbasePlayerAnimState::ClearAnimationState() { m_bJumping = false; + m_bDuckJumping = false; m_bFiring = false; m_bReloading = false; m_bWeaponSwitching = false; @@ -298,6 +347,11 @@ void CMapbasePlayerAnimState::ClearAnimationLayers() m_pOuter->SetNumAnimOverlays( NUM_LAYERS_WANTED ); for ( int i=0; i < m_pOuter->GetNumAnimOverlays(); i++ ) { + // If we're not using aim sequences, leave the aim layers alone + // (allows them to be used outside of anim state) + if ( !m_AnimConfig.m_bUseAimSequences && i <= NUM_AIMSEQUENCE_LAYERS ) + continue; + m_pOuter->GetAnimOverlay( i )->SetOrder( CBaseAnimatingOverlay::MAX_OVERLAYS ); #ifndef CLIENT_DLL m_pOuter->GetAnimOverlay( i )->m_fFlags = 0; @@ -383,7 +437,7 @@ void CMapbasePlayerAnimState::UpdateLayerSequenceGeneric( int iLayer, bool &bEna pLayer->m_flPlaybackRate = fPlaybackRate; pLayer->m_flWeight = 1.0f; - if (iLayer == RELOADSEQUENCE_LAYER) + if (fBlendIn > 0.0f || fBlendOut > 0.0f) { // blend this layer in and out for smooth reloading if (flCurCycle < fBlendIn && fBlendIn>0) @@ -433,10 +487,76 @@ void CMapbasePlayerAnimState::ComputeWeaponSwitchSequence() UpdateLayerSequenceGeneric( RELOADSEQUENCE_LAYER, m_bWeaponSwitching, m_flWeaponSwitchCycle, m_iWeaponSwitchSequence, false, 0, 0.5f ); } +void CMapbasePlayerAnimState::ComputeRelaxSequence() +{ + bool bRelaxing = m_bWeaponRelaxing; + float flRelaxSpeed = 0.05f; + + if ((m_bFiring && m_flFireCycle < 1.0f) || m_bReloading) + { + // Keep weapon raised + bRelaxing = false; + flRelaxSpeed = 0.5f; + //GetOuter()->SetPoseParameter( GetOuter()->LookupPoseParameter( "weapon_lower" ), 0.0f ); + } + + if (bRelaxing ? m_flWeaponRelaxAmount != 1.0f : m_flWeaponRelaxAmount != 0.0f) + { + if (bRelaxing) + m_flWeaponRelaxAmount += flRelaxSpeed; + else + m_flWeaponRelaxAmount -= flRelaxSpeed; + + m_flWeaponRelaxAmount = clamp( m_flWeaponRelaxAmount, 0.0f, 1.0f ); + + GetOuter()->SetPoseParameter( GetOuter()->LookupPoseParameter( "weapon_lower" ), m_flWeaponRelaxAmount ); + + /*int nPose = GetOuter()->LookupPoseParameter( "weapon_lower" ); + if (nPose != -1) + { + float flValue = RemapValClamped( (m_flWeaponRelaxTime - gpGlobals->curtime), 0.0f, 0.5f, 0.0f, 1.0f ); + + if (flValue <= 0.0f) + { + // All done + m_flWeaponRelaxTime = FLT_MAX; + } + + if (m_bWeaponRelaxing) + flValue = 1.0f - flValue; + + GetOuter()->SetPoseParameter( nPose, SimpleSpline( flValue ) ); + }*/ + } + else if (bRelaxing) + { + GetOuter()->SetPoseParameter( GetOuter()->LookupPoseParameter( "weapon_lower" ), 1.0f ); + } + + /*bool bEnabled = m_bWeaponRelaxing; + bool bUpdateCycle = true; + if (bEnabled) + { + if (m_flWeaponRelaxCycle >= 0.5f) + { + // Pause at 0.5 + m_flWeaponRelaxCycle = 0.5f; + bUpdateCycle = false; + } + } + else if (m_flWeaponRelaxCycle < 1.0f) + { + // Make sure we exit the relax + bEnabled = true; + } + + UpdateLayerSequenceGeneric( AIMSEQUENCE_LAYER, bEnabled, m_flWeaponRelaxCycle, m_iWeaponRelaxSequence, false, 0.5f, 0.5f, false, 1.0f, bUpdateCycle );*/ +} + // does misc gestures if we're not firing void CMapbasePlayerAnimState::ComputeMiscSequence() { - UpdateLayerSequenceGeneric( RELOADSEQUENCE_LAYER, m_bPlayingMisc, m_flMiscCycle, m_iMiscSequence, m_bMiscHoldAtEnd, m_flMiscBlendIn, m_flMiscBlendOut, m_bMiscOnlyWhenStill, m_fMiscPlaybackRate ); + UpdateLayerSequenceGeneric( MISCSEQUENCE_LAYER, m_bPlayingMisc, m_flMiscCycle, m_iMiscSequence, m_bMiscHoldAtEnd, m_flMiscBlendIn, m_flMiscBlendOut, m_bMiscOnlyWhenStill, m_fMiscPlaybackRate ); } //----------------------------------------------------------------------------- @@ -481,6 +601,37 @@ float CMapbasePlayerAnimState::GetCurrentMaxGroundSpeed() return speed; } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline bool CMapbasePlayerAnimState::ShouldUseAimPoses( void ) const +{ + return GetAimPoseBlend() > 0.0f; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +float CMapbasePlayerAnimState::GetAimPoseBlend( void ) const +{ + if (!GetOuter()->MyCombatCharacterPointer() || !GetOuter()->MyCombatCharacterPointer()->GetActiveWeapon() + || GetOuter()->MyCombatCharacterPointer()->GetActiveWeapon()->IsEffectActive( EF_NODRAW )) + return 0.0f; + + return 1.0f - m_flWeaponRelaxAmount; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +float CMapbasePlayerAnimState::SetOuterBodyYaw( float flValue ) +{ + float flAimPoseBlend = GetAimPoseBlend(); + + GetOuter()->SetPoseParameter( GetOuter()->LookupPoseParameter( "aim_yaw" ), flValue * flAimPoseBlend ); + return CBasePlayerAnimState::SetOuterBodyYaw( flValue * (1.0f - flAimPoseBlend) ); +} + //----------------------------------------------------------------------------- // Purpose: Override for backpeddling // Input : dt - @@ -643,10 +794,13 @@ void CMapbasePlayerAnimState::ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr } flPitch = clamp( flPitch, -90, 90 ); + //float flAimPoseBlend = GetAimPoseBlend(); + // See if we have a blender for pitch GetOuter()->SetPoseParameter( pStudioHdr, "aim_pitch", flPitch ); + GetOuter()->SetPoseParameter( pStudioHdr, "head_pitch", flPitch ); - ComputePoseParam_HeadPitch( pStudioHdr ); + //ComputePoseParam_HeadPitch( pStudioHdr ); } //----------------------------------------------------------------------------- diff --git a/sp/src/game/shared/mapbase/mapbase_playeranimstate.h b/sp/src/game/shared/mapbase/mapbase_playeranimstate.h index 3d88820536..a8e99b551a 100644 --- a/sp/src/game/shared/mapbase/mapbase_playeranimstate.h +++ b/sp/src/game/shared/mapbase/mapbase_playeranimstate.h @@ -49,10 +49,16 @@ class CMapbasePlayerAnimState : public CBasePlayerAnimState 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 StartWeaponRelax(); + void StopWeaponRelax(); void ClearAnimationState(); void ClearAnimationLayers(); + inline bool IsJumping() const { return m_bJumping; } + inline bool IsDuckJumping() const { return m_bDuckJumping; } + private: bool HandleJumping(); @@ -60,13 +66,19 @@ class CMapbasePlayerAnimState : public CBasePlayerAnimState void ComputeFireSequence(); void ComputeReloadSequence(); void ComputeWeaponSwitchSequence(); + void ComputeRelaxSequence(); 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 fBlendIn=0.0f, float fBlendOut=0.0f, bool bMoveBlend = false, float fPlaybackRate=1.0f, bool bUpdateCycle = true ); + bool ShouldUseAimPoses() const; + float GetAimPoseBlend() const; + + float SetOuterBodyYaw( float flValue ); + void ComputePoseParam_BodyYaw( void ); void ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr ); void ComputePoseParam_BodyLookYaw( void ); @@ -76,6 +88,7 @@ class CMapbasePlayerAnimState : public CBasePlayerAnimState // Current state variables. bool m_bJumping; // Set on a jump event. + bool m_bDuckJumping; // Jump started while ducking float m_flJumpStartTime; bool m_bFirstJumpFrame; @@ -90,6 +103,9 @@ class CMapbasePlayerAnimState : public CBasePlayerAnimState float m_flWeaponSwitchCycle; int m_iWeaponSwitchSequence; + bool m_bWeaponRelaxing; + float m_flWeaponRelaxAmount; + bool m_bPlayingMisc; float m_flMiscCycle, m_flMiscBlendOut, m_flMiscBlendIn; int m_iMiscSequence; diff --git a/sp/src/game/shared/mapbase/mapbase_shared.cpp b/sp/src/game/shared/mapbase/mapbase_shared.cpp index 8c364b62ea..9e747a8733 100644 --- a/sp/src/game/shared/mapbase/mapbase_shared.cpp +++ b/sp/src/game/shared/mapbase/mapbase_shared.cpp @@ -85,6 +85,7 @@ char g_iszGameName[128]; #ifdef GAME_DLL // Default player configuration char g_szDefaultPlayerModel[MAX_PATH]; +bool g_bDefaultPlayerLegs; bool g_bDefaultPlayerDrawExternally; char g_szDefaultHandsModel[MAX_PATH]; @@ -235,6 +236,7 @@ class CMapbaseSystem : public CAutoGameSystem #ifdef GAME_DLL Q_strncpy( g_szDefaultPlayerModel, gameinfo->GetString( "player_default_model", "models/player.mdl" ), sizeof( g_szDefaultPlayerModel ) ); + g_bDefaultPlayerLegs = gameinfo->GetBool( "player_default_legs", false ); g_bDefaultPlayerDrawExternally = gameinfo->GetBool( "player_default_draw_externally", false ); Q_strncpy( g_szDefaultHandsModel, gameinfo->GetString( "player_default_hands", "models/weapons/v_hands.mdl" ), sizeof( g_szDefaultHandsModel ) );