diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/hl1/c_hl1mp_player.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/client/hl1/c_hl1mp_player.cpp')
| -rw-r--r-- | game/client/hl1/c_hl1mp_player.cpp | 602 |
1 files changed, 602 insertions, 0 deletions
diff --git a/game/client/hl1/c_hl1mp_player.cpp b/game/client/hl1/c_hl1mp_player.cpp new file mode 100644 index 0000000..53bfbbc --- /dev/null +++ b/game/client/hl1/c_hl1mp_player.cpp @@ -0,0 +1,602 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#include "cbase.h" +#include "c_hl1mp_player.h" +#include "c_basetempentity.h" +#include "iinput.h" + +// Don't alias here +#if defined( CHL1MP_Player ) +#undef CHL1MP_Player +#endif + + +////////////////////////////////////////////////////////////////////// + + +class C_TEPlayerAnimEvent : public C_BaseTempEntity +{ +public: + DECLARE_CLASS( C_TEPlayerAnimEvent, C_BaseTempEntity ); + DECLARE_CLIENTCLASS(); + + virtual void PostDataUpdate( DataUpdateType_t updateType ) + { + // Create the effect. + C_HL1MP_Player *pPlayer = dynamic_cast< C_HL1MP_Player* >( m_hPlayer.Get() ); + if ( pPlayer && !pPlayer->IsDormant() ) + { + pPlayer->DoAnimationEvent( (PlayerAnimEvent_t)m_iEvent.Get(), m_nData ); + } + } + +public: + CNetworkHandle( CBasePlayer, m_hPlayer ); + CNetworkVar( int, m_iEvent ); + CNetworkVar( int, m_nData ); +}; + +IMPLEMENT_CLIENTCLASS_EVENT( C_TEPlayerAnimEvent, DT_TEPlayerAnimEvent, CTEPlayerAnimEvent ); + +// ------------------------------------------------------------------------------------------ // +// Data tables and prediction tables. +// ------------------------------------------------------------------------------------------ // + +BEGIN_RECV_TABLE_NOBASE( C_TEPlayerAnimEvent, DT_TEPlayerAnimEvent ) + RecvPropEHandle( RECVINFO( m_hPlayer ) ), + RecvPropInt( RECVINFO( m_iEvent ) ), + RecvPropInt( RECVINFO( m_nData ) ) +END_RECV_TABLE() + +IMPLEMENT_CLIENTCLASS_DT( C_HL1MP_Player, DT_HL1MP_Player, CHL1MP_Player ) + RecvPropFloat( RECVINFO( m_angEyeAngles[0] ) ), + RecvPropFloat( RECVINFO( m_angEyeAngles[1] ) ), + RecvPropEHandle( RECVINFO( m_hRagdoll ) ), + RecvPropInt( RECVINFO( m_iSpawnInterpCounter ) ), + RecvPropInt( RECVINFO( m_iRealSequence ) ), +// RecvPropDataTable( RECVINFO_DT( m_Shared ), 0, &REFERENCE_RECV_TABLE( DT_TFCPlayerShared ) ) +END_RECV_TABLE() + +BEGIN_PREDICTION_DATA( C_HL1MP_Player ) +END_PREDICTION_DATA() + +///////////////////////////////////////////////////////////////////// + +static ConVar cl_playermodel( "cl_playermodel", "none", FCVAR_USERINFO | FCVAR_ARCHIVE | FCVAR_SERVER_CAN_EXECUTE, "Default Player Model"); + +C_HL1MP_Player::C_HL1MP_Player( void ) : + m_iv_angEyeAngles( "C_HL1MP_Player::m_iv_angEyeAngles" ) +{ + m_PlayerAnimState = CreatePlayerAnimState( this ); + m_angEyeAngles.Init(); + + m_fLastPredFreeze = -1; + +// cant interpolate ... buggy? it keeps resetting the angle to 0,0,0 +// AddVar( &m_angEyeAngles, &m_iv_angEyeAngles, LATCH_SIMULATION_VAR ); +} + +C_HL1MP_Player::~C_HL1MP_Player() +{ + m_PlayerAnimState->Release(); +} + +const QAngle& C_HL1MP_Player::GetRenderAngles() +{ + if ( IsRagdoll() ) + { + return vec3_angle; + } + else + { + return m_PlayerAnimState->GetRenderAngles(); + } +} + +void C_HL1MP_Player::UpdateClientSideAnimation() +{ + // Update the animation data. It does the local check here so this works when using + // a third-person camera (and we don't have valid player angles). + if ( this == C_BasePlayer::GetLocalPlayer() ) + m_PlayerAnimState->Update( EyeAngles()[YAW], m_angEyeAngles[PITCH] ); + else + m_PlayerAnimState->Update( m_angEyeAngles[YAW], m_angEyeAngles[PITCH] ); + + BaseClass::UpdateClientSideAnimation(); +} + + +void C_HL1MP_Player::DoAnimationEvent( PlayerAnimEvent_t event, int nData ) +{ + m_PlayerAnimState->DoAnimationEvent( event, nData ); +} + + +void C_HL1MP_Player::ProcessMuzzleFlashEvent() +{ +#if 0 + // Reenable when the weapons have muzzle flash attachments in the right spot. + if ( this != C_BasePlayer::GetLocalPlayer() ) + { + Vector vAttachment; + QAngle dummyAngles; + + C_WeaponTFCBase *pWeapon = m_Shared.GetActiveTFCWeapon(); + + if ( pWeapon ) + { + int iAttachment = pWeapon->LookupAttachment( "muzzle_flash" ); + + if ( iAttachment > 0 ) + { + float flScale = 1; + pWeapon->GetAttachment( iAttachment, vAttachment, dummyAngles ); + + // The way the models are setup, the up vector points along the barrel. + Vector vForward, vRight, vUp; + AngleVectors( dummyAngles, &vForward, &vRight, &vUp ); + VectorAngles( vUp, dummyAngles ); + + FX_MuzzleEffect( vAttachment, dummyAngles, flScale, 0, NULL, true ); + } + } + } + + Vector vAttachment; + QAngle dummyAngles; + + bool bFoundAttachment = GetAttachment( 1, vAttachment, dummyAngles ); + // If we have an attachment, then stick a light on it. + if ( bFoundAttachment ) + { + dlight_t *el = effects->CL_AllocDlight( LIGHT_INDEX_MUZZLEFLASH + index ); + el->origin = vAttachment; + el->radius = 24; + el->decay = el->radius / 0.05f; + el->die = gpGlobals->curtime + 0.05f; + el->color.r = 255; + el->color.g = 192; + el->color.b = 64; + el->color.exponent = 5; + } +#endif +} + + +void C_HL1MP_Player::Spawn( void ) +{ + BaseClass::Spawn(); + +// SetModel( "models/player/mp/barney/barney.mdl" ); + + m_iSpawnInterpCounterCache = 0; + + UpdateVisibility(); +} + +void C_HL1MP_Player::AddEntity( void ) +{ + BaseClass::AddEntity(); + + //m_PlayerAnimState.Update(); + +// SetLocalAnglesDim( X_INDEX, 0 ); +} + +void C_HL1MP_Player::OnDataChanged( DataUpdateType_t type ) +{ + BaseClass::OnDataChanged( type ); + + if ( type == DATA_UPDATE_CREATED ) + { + SetNextClientThink( CLIENT_THINK_ALWAYS ); + } + + UpdateVisibility(); +} + +C_BaseAnimating *C_HL1MP_Player::BecomeRagdollOnClient() +{ + // Handled elsewhere + return NULL; +} + +void C_HL1MP_Player::PreThink( void ) +{ + BaseClass::PreThink(); + return; + + QAngle vTempAngles = GetLocalAngles(); + + if ( GetLocalPlayer() == this ) + { + vTempAngles[PITCH] = EyeAngles()[PITCH]; + } + else + { + vTempAngles[PITCH] = m_angEyeAngles[PITCH]; + } + + if ( vTempAngles[YAW] < 0.0f ) + { + vTempAngles[YAW] += 360.0f; + } + + SetLocalAngles( vTempAngles ); + + BaseClass::PreThink(); +#if 0 + HandleSpeedChanges(); + + if ( m_HL2Local.m_flSuitPower <= 0.0f ) + { + if( IsSprinting() ) + { + StopSprinting(); + } + } +#endif +} + +void C_HL1MP_Player::PostDataUpdate( DataUpdateType_t updateType ) +{ + // C_BaseEntity assumes we're networking the entity's angles, so pretend that it + // networked the same value we already have. + SetNetworkAngles( GetLocalAngles() ); + + BaseClass::PostDataUpdate( updateType ); +} + + +void C_HL1MP_Player::ClientThink( void ) +{ + BaseClass::ClientThink(); +// m_PlayerAnimState.Update(); +} + + +//HL1MPRAGDOLL + + +IMPLEMENT_CLIENTCLASS_DT_NOBASE( C_HL1MPRagdoll, DT_HL1MPRagdoll, CHL1MPRagdoll ) + RecvPropVector( RECVINFO(m_vecRagdollOrigin) ), + RecvPropEHandle( RECVINFO( m_hPlayer ) ), + RecvPropInt( RECVINFO( m_nModelIndex ) ), + RecvPropInt( RECVINFO(m_nForceBone) ), + RecvPropVector( RECVINFO(m_vecForce) ), + RecvPropVector( RECVINFO( m_vecRagdollVelocity ) ) +END_RECV_TABLE() + + + +C_HL1MPRagdoll::C_HL1MPRagdoll() +{ + +} + +C_HL1MPRagdoll::~C_HL1MPRagdoll() +{ + PhysCleanupFrictionSounds( this ); + + if ( m_hPlayer ) + { + m_hPlayer->CreateModelInstance(); + } +} + +void C_HL1MPRagdoll::Interp_Copy( C_BaseAnimatingOverlay *pSourceEntity ) +{ + if ( !pSourceEntity ) + return; + + VarMapping_t *pSrc = pSourceEntity->GetVarMapping(); + VarMapping_t *pDest = GetVarMapping(); + + // Find all the VarMapEntry_t's that represent the same variable. + for ( int i = 0; i < pDest->m_Entries.Count(); i++ ) + { + VarMapEntry_t *pDestEntry = &pDest->m_Entries[i]; + const char *pszName = pDestEntry->watcher->GetDebugName(); + for ( int j=0; j < pSrc->m_Entries.Count(); j++ ) + { + VarMapEntry_t *pSrcEntry = &pSrc->m_Entries[j]; + if ( !Q_strcmp( pSrcEntry->watcher->GetDebugName(), pszName ) ) + { + pDestEntry->watcher->Copy( pSrcEntry->watcher ); + break; + } + } + } +} + +void C_HL1MPRagdoll::ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName ) +{ + IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); + + if( !pPhysicsObject ) + return; + + Vector dir = pTrace->endpos - pTrace->startpos; + + if ( iDamageType == DMG_BLAST ) + { + dir *= 4000; // adjust impact strenght + + // apply force at object mass center + pPhysicsObject->ApplyForceCenter( dir ); + } + else + { + Vector hitpos; + + VectorMA( pTrace->startpos, pTrace->fraction, dir, hitpos ); + VectorNormalize( dir ); + + dir *= 4000; // adjust impact strenght + + // apply force where we hit it + pPhysicsObject->ApplyForceOffset( dir, hitpos ); + + } + + m_pRagdoll->ResetRagdollSleepAfterTime(); +} + + +void C_HL1MP_Player::CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov ) +{ + if ( m_lifeState != LIFE_ALIVE ) + { + Vector origin = EyePosition(); + + IRagdoll *pRagdoll = GetRepresentativeRagdoll(); + + if ( pRagdoll ) + { + origin = pRagdoll->GetRagdollOrigin(); + origin.z += VEC_DEAD_VIEWHEIGHT_SCALED( this ).z; // look over ragdoll, not through + } + + BaseClass::CalcView( eyeOrigin, eyeAngles, zNear, zFar, fov ); + + eyeOrigin = origin; + + Vector vForward; + AngleVectors( eyeAngles, &vForward ); + + VectorNormalize( vForward ); + VectorMA( origin, -CHASE_CAM_DISTANCE_MAX, vForward, eyeOrigin ); + + Vector WALL_MIN( -WALL_OFFSET, -WALL_OFFSET, -WALL_OFFSET ); + Vector WALL_MAX( WALL_OFFSET, WALL_OFFSET, WALL_OFFSET ); + + trace_t trace; // clip against world + C_BaseEntity::PushEnableAbsRecomputations( false ); // HACK don't recompute positions while doing RayTrace + UTIL_TraceHull( origin, eyeOrigin, WALL_MIN, WALL_MAX, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trace ); + C_BaseEntity::PopEnableAbsRecomputations(); + + if (trace.fraction < 1.0) + { + eyeOrigin = trace.endpos; + } + + return; + } + + BaseClass::CalcView( eyeOrigin, eyeAngles, zNear, zFar, fov ); +} + +IRagdoll* C_HL1MP_Player::GetRepresentativeRagdoll() const +{ + if ( m_hRagdoll.Get() ) + { + C_HL1MPRagdoll *pRagdoll = (C_HL1MPRagdoll*)m_hRagdoll.Get(); + + return pRagdoll->GetIRagdoll(); + } + else + { + return NULL; + } +} + +void C_HL1MPRagdoll::CreateHL1MPRagdoll( void ) +{ + // First, initialize all our data. If we have the player's entity on our client, + // then we can make ourselves start out exactly where the player is. + C_HL1MP_Player *pPlayer = dynamic_cast< C_HL1MP_Player* >( m_hPlayer.Get() ); + + if ( pPlayer && !pPlayer->IsDormant() ) + { + // move my current model instance to the ragdoll's so decals are preserved. + pPlayer->SnatchModelInstance( this ); + + VarMapping_t *varMap = GetVarMapping(); + + // Copy all the interpolated vars from the player entity. + // The entity uses the interpolated history to get bone velocity. + bool bRemotePlayer = (pPlayer != C_BasePlayer::GetLocalPlayer()); + if ( bRemotePlayer ) + { + Interp_Copy( pPlayer ); + + SetAbsAngles( pPlayer->GetRenderAngles() ); + GetRotationInterpolator().Reset(); + + m_flAnimTime = pPlayer->m_flAnimTime; + SetSequence( pPlayer->GetSequence() ); + m_flPlaybackRate = pPlayer->GetPlaybackRate(); + } + else + { + // This is the local player, so set them in a default + // pose and slam their velocity, angles and origin + SetAbsOrigin( m_vecRagdollOrigin ); + + SetAbsAngles( pPlayer->GetRenderAngles() ); + + SetAbsVelocity( m_vecRagdollVelocity ); + + int iSeq = pPlayer->GetSequence(); + if ( iSeq == -1 ) + { + Assert( false ); // missing walk_lower? + iSeq = 0; + } + + SetSequence( iSeq ); // walk_lower, basic pose + SetCycle( 0.0 ); + + Interp_Reset( varMap ); + } + } + else + { + // overwrite network origin so later interpolation will + // use this position + SetNetworkOrigin( m_vecRagdollOrigin ); + + SetAbsOrigin( m_vecRagdollOrigin ); + SetAbsVelocity( m_vecRagdollVelocity ); + + Interp_Reset( GetVarMapping() ); + + } + + SetModelIndex( m_nModelIndex ); + + // Make us a ragdoll.. + m_nRenderFX = kRenderFxRagdoll; + + matrix3x4_t boneDelta0[MAXSTUDIOBONES]; + matrix3x4_t boneDelta1[MAXSTUDIOBONES]; + matrix3x4_t currentBones[MAXSTUDIOBONES]; + const float boneDt = 0.05f; + + if ( pPlayer && !pPlayer->IsDormant() ) + { + pPlayer->GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt ); + } + else + { + GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt ); + } + + InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt ); +} + + +void C_HL1MPRagdoll::OnDataChanged( DataUpdateType_t type ) +{ + BaseClass::OnDataChanged( type ); + + if ( type == DATA_UPDATE_CREATED ) + { + CreateHL1MPRagdoll(); + } +} + +IRagdoll* C_HL1MPRagdoll::GetIRagdoll() const +{ + return m_pRagdoll; +} + +void C_HL1MPRagdoll::UpdateOnRemove( void ) +{ + VPhysicsSetObject( NULL ); + + BaseClass::UpdateOnRemove(); +} + +//----------------------------------------------------------------------------- +// Purpose: clear out any face/eye values stored in the material system +//----------------------------------------------------------------------------- +void C_HL1MPRagdoll::SetupWeights( const matrix3x4_t *pBoneToWorld, int nFlexWeightCount, float *pFlexWeights, float *pFlexDelayedWeights ) +{ + BaseClass::SetupWeights( pBoneToWorld, nFlexWeightCount, pFlexWeights, pFlexDelayedWeights ); + + static float destweight[128]; + static bool bIsInited = false; + + CStudioHdr *hdr = GetModelPtr(); + if ( !hdr ) + return; + + int nFlexDescCount = hdr->numflexdesc(); + if ( nFlexDescCount ) + { + Assert( !pFlexDelayedWeights ); + memset( pFlexWeights, 0, nFlexWeightCount * sizeof(float) ); + } + + if ( m_iEyeAttachment > 0 ) + { + matrix3x4_t attToWorld; + if (GetAttachment( m_iEyeAttachment, attToWorld )) + { + Vector local, tmp; + local.Init( 1000.0f, 0.0f, 0.0f ); + VectorTransform( local, attToWorld, tmp ); + modelrender->SetViewTarget( GetModelPtr(), GetBody(), tmp ); + } + } +} + +bool C_HL1MP_Player::ShouldDraw( void ) +{ + if ( !IsAlive() ) + return false; + + if ( IsLocalPlayer() && IsRagdoll() ) + return true; + + if ( IsRagdoll() ) + return false; + + return BaseClass::ShouldDraw(); +} + +bool C_HL1MP_Player::ShouldPredict( void ) +{ + // Do this before calling into baseclass so prediction data block gets allocated + if ( IsLocalPlayer() ) + { +#if 0 + // Disable prediction when player hops onto a moving train or elevator :-/ + if ( GetGroundEntity() && GetGroundEntity()->GetMoveType() == MOVETYPE_PUSH ) + { + Vector vel = GetGroundEntity()->GetLocalVelocity(); + if ( vel.Length() > 0.002f ) + { + m_fLastPredFreeze = gpGlobals->curtime; + } + } + + // disable prediction for 3 seconds after touching a moving entity + if ( ( gpGlobals->curtime - m_fLastPredFreeze ) < 3 ) + { + if ( GetPredictable() ) + { + QuickShutdownPredictable(); + } + + return false; + } + + if ( !GetPredictable() && IsIntermediateDataAllocated() ) + { + QuickInitPredictable(); + } +#endif + + return true; + } + + return false; +} |