From 98189136088fed5f6c4e642a5a0693ac9f199ef7 Mon Sep 17 00:00:00 2001 From: squeek Date: Tue, 29 Oct 2013 02:56:08 +0000 Subject: [PATCH] Our very own player class! (CFF_SH_Player, CFF_CL_Player, CFF_SV_Player) - Note: FFPlayer still derives from CBaseHLPlayer, which has HL-style sprinting code and whatnot, will probably want to end up removing that inheritance - All references to the old HL2MP player have been switched to our FF player (temporarily if we end up replacing those files) --- mp/src/game/client/client_ff.vpc | 21 +- mp/src/game/client/ff/ff_cl_player.cpp | 985 ++++++++++ mp/src/game/client/ff/ff_cl_player.h | 173 ++ mp/src/game/client/hl2mp/hl2mp_hud_chat.cpp | 2 +- .../game/client/hl2mp/hl2mp_hud_target_id.cpp | 4 +- mp/src/game/client/hl2mp/hl2mp_hud_team.cpp | 2 +- .../client/hl2mp/ui/hl2mpclientscoreboard.cpp | 2 +- mp/src/game/server/ff/ff_sv_client.cpp | 10 +- mp/src/game/server/ff/ff_sv_player.cpp | 1634 +++++++++++++++++ mp/src/game/server/ff/ff_sv_player.h | 176 ++ mp/src/game/server/hl2mp/hl2mp_bot_temp.cpp | 12 +- mp/src/game/server/server_ff.vpc | 19 +- mp/src/game/shared/ff/ff_sh_gamerules.cpp | 36 +- mp/src/game/shared/ff/ff_sh_gamerules.h | 4 +- mp/src/game/shared/ff/ff_sh_player.cpp | 577 ++++++ mp/src/game/shared/ff/ff_sh_player.h | 99 + mp/src/game/shared/ff/ff_shared.vpc | 13 +- mp/src/game/shared/hl2mp/weapon_357.cpp | 4 +- mp/src/game/shared/hl2mp/weapon_ar2.cpp | 4 +- mp/src/game/shared/hl2mp/weapon_crossbow.cpp | 4 +- mp/src/game/shared/hl2mp/weapon_crowbar.cpp | 4 +- mp/src/game/shared/hl2mp/weapon_frag.cpp | 6 +- mp/src/game/shared/hl2mp/weapon_hl2mpbase.cpp | 8 +- mp/src/game/shared/hl2mp/weapon_hl2mpbase.h | 6 +- .../hl2mp/weapon_hl2mpbase_machinegun.cpp | 10 +- .../hl2mp/weapon_hl2mpbasebasebludgeon.cpp | 6 +- .../weapon_hl2mpbasehlmpcombatweapon.cpp | 4 +- .../hl2mp/weapon_hl2mpbasehlmpcombatweapon.h | 4 +- .../game/shared/hl2mp/weapon_physcannon.cpp | 12 +- mp/src/game/shared/hl2mp/weapon_pistol.cpp | 4 +- mp/src/game/shared/hl2mp/weapon_rpg.cpp | 4 +- mp/src/game/shared/hl2mp/weapon_shotgun.cpp | 4 +- mp/src/game/shared/hl2mp/weapon_slam.cpp | 8 +- mp/src/game/shared/hl2mp/weapon_smg1.cpp | 4 +- 34 files changed, 3774 insertions(+), 91 deletions(-) create mode 100644 mp/src/game/client/ff/ff_cl_player.cpp create mode 100644 mp/src/game/client/ff/ff_cl_player.h create mode 100644 mp/src/game/server/ff/ff_sv_player.cpp create mode 100644 mp/src/game/server/ff/ff_sv_player.h create mode 100644 mp/src/game/shared/ff/ff_sh_player.cpp create mode 100644 mp/src/game/shared/ff/ff_sh_player.h diff --git a/mp/src/game/client/client_ff.vpc b/mp/src/game/client/client_ff.vpc index f4b27460..b2ba40b5 100644 --- a/mp/src/game/client/client_ff.vpc +++ b/mp/src/game/client/client_ff.vpc @@ -30,6 +30,16 @@ $Project "Client (FF)" // for FF Shared, see game\shared\ff\ff_shared.vpc $Folder "FF" { + $Folder "Game" + { + + } + $Folder "Player" + { + $File "ff\ff_cl_player.cpp" + $File "ff\ff_cl_player.h" + } + $Folder "Libraries" { $Lib lua @@ -39,11 +49,20 @@ $Project "Client (FF)" // IMPORTANT: remove conflicting hl2dm SDK stuff as we implement our own!! // done for us in HL2DM sdk vpc: -$File "$SRCDIR\game\shared\weapon_parse_default.cpp" - + $Folder "HL2 DLL" { -$File "$SRCDIR\game\shared\hl2\hl_gamemovement.cpp" -$File "$SRCDIR\game\shared\hl2\hl_gamemovement.h" } + + $Folder "HL2MP" + { + // Player + -$File "hl2mp\c_hl2mp_player.cpp" + -$File "hl2mp\c_hl2mp_player.h" + -$File "$SRCDIR\game\shared\hl2mp\hl2mp_player_shared.cpp" + -$File "$SRCDIR\game\shared\hl2mp\hl2mp_player_shared.h" + } } } diff --git a/mp/src/game/client/ff/ff_cl_player.cpp b/mp/src/game/client/ff/ff_cl_player.cpp new file mode 100644 index 00000000..46fce071 --- /dev/null +++ b/mp/src/game/client/ff/ff_cl_player.cpp @@ -0,0 +1,985 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Player for FF. +// +//=============================================================================// + +#include "cbase.h" +#include "vcollide_parse.h" +#include "ff_cl_player.h" +#include "view.h" +#include "takedamageinfo.h" +#include "ff_sh_gamerules.h" +#include "in_buttons.h" +#include "iviewrender_beams.h" // flashlight beam +#include "r_efx.h" +#include "dlight.h" + +// Don't alias here +#if defined( CFF_SH_Player ) +#undef CFF_SH_Player +#endif + +LINK_ENTITY_TO_CLASS( player, CFF_CL_Player ); + +IMPLEMENT_CLIENTCLASS_DT(CFF_CL_Player, DT_FF_Player, CFF_SV_Player) + RecvPropFloat( RECVINFO( m_angEyeAngles[0] ) ), + RecvPropFloat( RECVINFO( m_angEyeAngles[1] ) ), + RecvPropEHandle( RECVINFO( m_hRagdoll ) ), + RecvPropInt( RECVINFO( m_iSpawnInterpCounter ) ), + RecvPropInt( RECVINFO( m_iPlayerSoundType) ), + + RecvPropBool( RECVINFO( m_fIsWalking ) ), +END_RECV_TABLE() + +BEGIN_PREDICTION_DATA( CFF_CL_Player ) + DEFINE_PRED_FIELD( m_fIsWalking, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), +END_PREDICTION_DATA() + +#define HL2_WALK_SPEED 150 +#define HL2_NORM_SPEED 190 +#define HL2_SPRINT_SPEED 320 + +static ConVar cl_playermodel( "cl_playermodel", "none", FCVAR_USERINFO | FCVAR_ARCHIVE | FCVAR_SERVER_CAN_EXECUTE, "Default Player Model"); +static ConVar cl_defaultweapon( "cl_defaultweapon", "weapon_physcannon", FCVAR_USERINFO | FCVAR_ARCHIVE, "Default Spawn Weapon"); + +void SpawnBlood (Vector vecSpot, const Vector &vecDir, int bloodColor, float flDamage); + +CFF_CL_Player::CFF_CL_Player() : m_PlayerAnimState( this ), m_iv_angEyeAngles( "CFF_CL_Player::m_iv_angEyeAngles" ) +{ + m_iIDEntIndex = 0; + m_iSpawnInterpCounterCache = 0; + + m_angEyeAngles.Init(); + + AddVar( &m_angEyeAngles, &m_iv_angEyeAngles, LATCH_SIMULATION_VAR ); + + m_EntClientFlags |= ENTCLIENTFLAG_DONTUSEIK; + m_blinkTimer.Invalidate(); + + m_pFlashlightBeam = NULL; +} + +CFF_CL_Player::~CFF_CL_Player( void ) +{ + ReleaseFlashlight(); +} + +int CFF_CL_Player::GetIDTarget() const +{ + return m_iIDEntIndex; +} + +//----------------------------------------------------------------------------- +// Purpose: Update this client's target entity +//----------------------------------------------------------------------------- +void CFF_CL_Player::UpdateIDTarget() +{ + if ( !IsLocalPlayer() ) + return; + + // Clear old target and find a new one + m_iIDEntIndex = 0; + + // don't show IDs in chase spec mode + if ( GetObserverMode() == OBS_MODE_CHASE || + GetObserverMode() == OBS_MODE_DEATHCAM ) + return; + + trace_t tr; + Vector vecStart, vecEnd; + VectorMA( MainViewOrigin(), 1500, MainViewForward(), vecEnd ); + VectorMA( MainViewOrigin(), 10, MainViewForward(), vecStart ); + UTIL_TraceLine( vecStart, vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); + + if ( !tr.startsolid && tr.DidHitNonWorldEntity() ) + { + C_BaseEntity *pEntity = tr.m_pEnt; + + if ( pEntity && (pEntity != this) ) + { + m_iIDEntIndex = pEntity->entindex(); + } + } +} + +void CFF_CL_Player::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator ) +{ + Vector vecOrigin = ptr->endpos - vecDir * 4; + + float flDistance = 0.0f; + + if ( info.GetAttacker() ) + { + flDistance = (ptr->endpos - info.GetAttacker()->GetAbsOrigin()).Length(); + } + + if ( m_takedamage ) + { + AddMultiDamage( info, this ); + + int blood = BloodColor(); + + CBaseEntity *pAttacker = info.GetAttacker(); + + if ( pAttacker ) + { + if ( FFRules()->IsTeamplay() && pAttacker->InSameTeam( this ) == true ) + return; + } + + if ( blood != DONT_BLEED ) + { + SpawnBlood( vecOrigin, vecDir, blood, flDistance );// a little surface blood. + TraceBleed( flDistance, vecDir, ptr, info.GetDamageType() ); + } + } +} + + +CFF_CL_Player* CFF_CL_Player::GetLocalFFPlayer() +{ + return (CFF_CL_Player*)C_BasePlayer::GetLocalPlayer(); +} + +void CFF_CL_Player::Initialize( void ) +{ + m_headYawPoseParam = LookupPoseParameter( "head_yaw" ); + GetPoseParameterRange( m_headYawPoseParam, m_headYawMin, m_headYawMax ); + + m_headPitchPoseParam = LookupPoseParameter( "head_pitch" ); + GetPoseParameterRange( m_headPitchPoseParam, m_headPitchMin, m_headPitchMax ); + + CStudioHdr *hdr = GetModelPtr(); + for ( int i = 0; i < hdr->GetNumPoseParameters() ; i++ ) + { + SetPoseParameter( hdr, i, 0.0 ); + } +} + +CStudioHdr *CFF_CL_Player::OnNewModel( void ) +{ + CStudioHdr *hdr = BaseClass::OnNewModel(); + + Initialize( ); + + return hdr; +} + +//----------------------------------------------------------------------------- +/** + * Orient head and eyes towards m_lookAt. + */ +void CFF_CL_Player::UpdateLookAt( void ) +{ + // head yaw + if (m_headYawPoseParam < 0 || m_headPitchPoseParam < 0) + return; + + // orient eyes + m_viewtarget = m_vLookAtTarget; + + // blinking + if (m_blinkTimer.IsElapsed()) + { + m_blinktoggle = !m_blinktoggle; + m_blinkTimer.Start( RandomFloat( 1.5f, 4.0f ) ); + } + + // Figure out where we want to look in world space. + QAngle desiredAngles; + Vector to = m_vLookAtTarget - EyePosition(); + VectorAngles( to, desiredAngles ); + + // Figure out where our body is facing in world space. + QAngle bodyAngles( 0, 0, 0 ); + bodyAngles[YAW] = GetLocalAngles()[YAW]; + + + float flBodyYawDiff = bodyAngles[YAW] - m_flLastBodyYaw; + m_flLastBodyYaw = bodyAngles[YAW]; + + + // Set the head's yaw. + float desired = AngleNormalize( desiredAngles[YAW] - bodyAngles[YAW] ); + desired = clamp( desired, m_headYawMin, m_headYawMax ); + m_flCurrentHeadYaw = ApproachAngle( desired, m_flCurrentHeadYaw, 130 * gpGlobals->frametime ); + + // Counterrotate the head from the body rotation so it doesn't rotate past its target. + m_flCurrentHeadYaw = AngleNormalize( m_flCurrentHeadYaw - flBodyYawDiff ); + desired = clamp( desired, m_headYawMin, m_headYawMax ); + + SetPoseParameter( m_headYawPoseParam, m_flCurrentHeadYaw ); + + + // Set the head's yaw. + desired = AngleNormalize( desiredAngles[PITCH] ); + desired = clamp( desired, m_headPitchMin, m_headPitchMax ); + + m_flCurrentHeadPitch = ApproachAngle( desired, m_flCurrentHeadPitch, 130 * gpGlobals->frametime ); + m_flCurrentHeadPitch = AngleNormalize( m_flCurrentHeadPitch ); + SetPoseParameter( m_headPitchPoseParam, m_flCurrentHeadPitch ); +} + +void CFF_CL_Player::ClientThink( void ) +{ + bool bFoundViewTarget = false; + + Vector vForward; + AngleVectors( GetLocalAngles(), &vForward ); + + for( int iClient = 1; iClient <= gpGlobals->maxClients; ++iClient ) + { + CBaseEntity *pEnt = UTIL_PlayerByIndex( iClient ); + if(!pEnt || !pEnt->IsPlayer()) + continue; + + if ( pEnt->entindex() == entindex() ) + continue; + + Vector vTargetOrigin = pEnt->GetAbsOrigin(); + Vector vMyOrigin = GetAbsOrigin(); + + Vector vDir = vTargetOrigin - vMyOrigin; + + if ( vDir.Length() > 128 ) + continue; + + VectorNormalize( vDir ); + + if ( DotProduct( vForward, vDir ) < 0.0f ) + continue; + + m_vLookAtTarget = pEnt->EyePosition(); + bFoundViewTarget = true; + break; + } + + if ( bFoundViewTarget == false ) + { + m_vLookAtTarget = GetAbsOrigin() + vForward * 512; + } + + UpdateIDTarget(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CFF_CL_Player::DrawModel( int flags ) +{ + if ( !m_bReadyToDraw ) + return 0; + + return BaseClass::DrawModel(flags); +} + +//----------------------------------------------------------------------------- +// Should this object receive shadows? +//----------------------------------------------------------------------------- +bool CFF_CL_Player::ShouldReceiveProjectedTextures( int flags ) +{ + Assert( flags & SHADOW_FLAGS_PROJECTED_TEXTURE_TYPE_MASK ); + + if ( IsEffectActive( EF_NODRAW ) ) + return false; + + if( flags & SHADOW_FLAGS_FLASHLIGHT ) + { + return true; + } + + return BaseClass::ShouldReceiveProjectedTextures( flags ); +} + +void CFF_CL_Player::DoImpactEffect( trace_t &tr, int nDamageType ) +{ + if ( GetActiveWeapon() ) + { + GetActiveWeapon()->DoImpactEffect( tr, nDamageType ); + return; + } + + BaseClass::DoImpactEffect( tr, nDamageType ); +} + +void CFF_CL_Player::PreThink( void ) +{ + 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(); + + HandleSpeedChanges(); + + if ( m_HL2Local.m_flSuitPower <= 0.0f ) + { + if( IsSprinting() ) + { + StopSprinting(); + } + } +} + +const QAngle &CFF_CL_Player::EyeAngles() +{ + if( IsLocalPlayer() ) + { + return BaseClass::EyeAngles(); + } + else + { + return m_angEyeAngles; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CFF_CL_Player::AddEntity( void ) +{ + BaseClass::AddEntity(); + + QAngle vTempAngles = GetLocalAngles(); + vTempAngles[PITCH] = m_angEyeAngles[PITCH]; + + SetLocalAngles( vTempAngles ); + + m_PlayerAnimState.Update(); + + // Zero out model pitch, blending takes care of all of it. + SetLocalAnglesDim( X_INDEX, 0 ); + + if( this != C_BasePlayer::GetLocalPlayer() ) + { + if ( IsEffectActive( EF_DIMLIGHT ) ) + { + int iAttachment = LookupAttachment( "anim_attachment_RH" ); + + if ( iAttachment < 0 ) + return; + + Vector vecOrigin; + QAngle eyeAngles = m_angEyeAngles; + + GetAttachment( iAttachment, vecOrigin, eyeAngles ); + + Vector vForward; + AngleVectors( eyeAngles, &vForward ); + + trace_t tr; + UTIL_TraceLine( vecOrigin, vecOrigin + (vForward * 200), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); + + if( !m_pFlashlightBeam ) + { + BeamInfo_t beamInfo; + beamInfo.m_nType = TE_BEAMPOINTS; + beamInfo.m_vecStart = tr.startpos; + beamInfo.m_vecEnd = tr.endpos; + beamInfo.m_pszModelName = "sprites/glow01.vmt"; + beamInfo.m_pszHaloName = "sprites/glow01.vmt"; + beamInfo.m_flHaloScale = 3.0; + beamInfo.m_flWidth = 8.0f; + beamInfo.m_flEndWidth = 35.0f; + beamInfo.m_flFadeLength = 300.0f; + beamInfo.m_flAmplitude = 0; + beamInfo.m_flBrightness = 60.0; + beamInfo.m_flSpeed = 0.0f; + beamInfo.m_nStartFrame = 0.0; + beamInfo.m_flFrameRate = 0.0; + beamInfo.m_flRed = 255.0; + beamInfo.m_flGreen = 255.0; + beamInfo.m_flBlue = 255.0; + beamInfo.m_nSegments = 8; + beamInfo.m_bRenderable = true; + beamInfo.m_flLife = 0.5; + beamInfo.m_nFlags = FBEAM_FOREVER | FBEAM_ONLYNOISEONCE | FBEAM_NOTILE | FBEAM_HALOBEAM; + + m_pFlashlightBeam = beams->CreateBeamPoints( beamInfo ); + } + + if( m_pFlashlightBeam ) + { + BeamInfo_t beamInfo; + beamInfo.m_vecStart = tr.startpos; + beamInfo.m_vecEnd = tr.endpos; + beamInfo.m_flRed = 255.0; + beamInfo.m_flGreen = 255.0; + beamInfo.m_flBlue = 255.0; + + beams->UpdateBeamInfo( m_pFlashlightBeam, beamInfo ); + + dlight_t *el = effects->CL_AllocDlight( 0 ); + el->origin = tr.endpos; + el->radius = 50; + el->color.r = 200; + el->color.g = 200; + el->color.b = 200; + el->die = gpGlobals->curtime + 0.1; + } + } + else if ( m_pFlashlightBeam ) + { + ReleaseFlashlight(); + } + } +} + +ShadowType_t CFF_CL_Player::ShadowCastType( void ) +{ + if ( !IsVisible() ) + return SHADOWS_NONE; + + return SHADOWS_RENDER_TO_TEXTURE_DYNAMIC; +} + + +const QAngle& CFF_CL_Player::GetRenderAngles() +{ + if ( IsRagdoll() ) + { + return vec3_angle; + } + else + { + return m_PlayerAnimState.GetRenderAngles(); + } +} + +bool CFF_CL_Player::ShouldDraw( void ) +{ + // If we're dead, our ragdoll will be drawn for us instead. + if ( !IsAlive() ) + return false; + +// if( GetTeamNumber() == TEAM_SPECTATOR ) +// return false; + + if( IsLocalPlayer() && IsRagdoll() ) + return true; + + if ( IsRagdoll() ) + return false; + + return BaseClass::ShouldDraw(); +} + +void CFF_CL_Player::NotifyShouldTransmit( ShouldTransmitState_t state ) +{ + if ( state == SHOULDTRANSMIT_END ) + { + if( m_pFlashlightBeam != NULL ) + { + ReleaseFlashlight(); + } + } + + BaseClass::NotifyShouldTransmit( state ); +} + +void CFF_CL_Player::OnDataChanged( DataUpdateType_t type ) +{ + BaseClass::OnDataChanged( type ); + + if ( type == DATA_UPDATE_CREATED ) + { + SetNextClientThink( CLIENT_THINK_ALWAYS ); + } + + UpdateVisibility(); +} + +void CFF_CL_Player::PostDataUpdate( DataUpdateType_t updateType ) +{ + if ( m_iSpawnInterpCounter != m_iSpawnInterpCounterCache ) + { + MoveToLastReceivedPosition( true ); + ResetLatched(); + m_iSpawnInterpCounterCache = m_iSpawnInterpCounter; + } + + BaseClass::PostDataUpdate( updateType ); +} + +void CFF_CL_Player::ReleaseFlashlight( void ) +{ + if( m_pFlashlightBeam ) + { + m_pFlashlightBeam->flags = 0; + m_pFlashlightBeam->die = gpGlobals->curtime - 1; + + m_pFlashlightBeam = NULL; + } +} + +float CFF_CL_Player::GetFOV( void ) +{ + //Find our FOV with offset zoom value + float flFOVOffset = C_BasePlayer::GetFOV() + GetZoom(); + + // Clamp FOV in MP + int min_fov = GetMinFOV(); + + // Don't let it go too low + flFOVOffset = MAX( min_fov, flFOVOffset ); + + return flFOVOffset; +} + +//========================================================= +// Autoaim +// set crosshair position to point to enemey +//========================================================= +Vector CFF_CL_Player::GetAutoaimVector( float flDelta ) +{ + // Never autoaim a predicted weapon (for now) + Vector forward; + AngleVectors( EyeAngles() + m_Local.m_vecPunchAngle, &forward ); + return forward; +} + +//----------------------------------------------------------------------------- +// Purpose: Returns whether or not we are allowed to sprint now. +//----------------------------------------------------------------------------- +bool CFF_CL_Player::CanSprint( void ) +{ + return ( (!m_Local.m_bDucked && !m_Local.m_bDucking) && (GetWaterLevel() != 3) ); +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CFF_CL_Player::StartSprinting( void ) +{ + if( m_HL2Local.m_flSuitPower < 10 ) + { + // Don't sprint unless there's a reasonable + // amount of suit power. + CPASAttenuationFilter filter( this ); + filter.UsePredictionRules(); + EmitSound( filter, entindex(), "HL2Player.SprintNoPower" ); + return; + } + + CPASAttenuationFilter filter( this ); + filter.UsePredictionRules(); + EmitSound( filter, entindex(), "HL2Player.SprintStart" ); + + SetMaxSpeed( HL2_SPRINT_SPEED ); + m_fIsSprinting = true; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CFF_CL_Player::StopSprinting( void ) +{ + SetMaxSpeed( HL2_NORM_SPEED ); + m_fIsSprinting = false; +} + +void CFF_CL_Player::HandleSpeedChanges( void ) +{ + int buttonsChanged = m_afButtonPressed | m_afButtonReleased; + + if( buttonsChanged & IN_SPEED ) + { + // The state of the sprint/run button has changed. + if ( IsSuitEquipped() ) + { + if ( !(m_afButtonPressed & IN_SPEED) && IsSprinting() ) + { + StopSprinting(); + } + else if ( (m_afButtonPressed & IN_SPEED) && !IsSprinting() ) + { + if ( CanSprint() ) + { + StartSprinting(); + } + else + { + // Reset key, so it will be activated post whatever is suppressing it. + m_nButtons &= ~IN_SPEED; + } + } + } + } + else if( buttonsChanged & IN_WALK ) + { + if ( IsSuitEquipped() ) + { + // The state of the WALK button has changed. + if( IsWalking() && !(m_afButtonPressed & IN_WALK) ) + { + StopWalking(); + } + else if( !IsWalking() && !IsSprinting() && (m_afButtonPressed & IN_WALK) && !(m_nButtons & IN_DUCK) ) + { + StartWalking(); + } + } + } + + if ( IsSuitEquipped() && m_fIsWalking && !(m_nButtons & IN_WALK) ) + StopWalking(); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CFF_CL_Player::StartWalking( void ) +{ + SetMaxSpeed( HL2_WALK_SPEED ); + m_fIsWalking = true; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CFF_CL_Player::StopWalking( void ) +{ + SetMaxSpeed( HL2_NORM_SPEED ); + m_fIsWalking = false; +} + +void CFF_CL_Player::ItemPreFrame( void ) +{ + if ( GetFlags() & FL_FROZEN ) + return; + + // Disallow shooting while zooming + if ( m_nButtons & IN_ZOOM ) + { + //FIXME: Held weapons like the grenade get sad when this happens + m_nButtons &= ~(IN_ATTACK|IN_ATTACK2); + } + + BaseClass::ItemPreFrame(); + +} + +void CFF_CL_Player::ItemPostFrame( void ) +{ + if ( GetFlags() & FL_FROZEN ) + return; + + BaseClass::ItemPostFrame(); +} + +C_BaseAnimating *CFF_CL_Player::BecomeRagdollOnClient() +{ + // Let the C_CSRagdoll entity do this. + // m_builtRagdoll = true; + return NULL; +} + +void CFF_CL_Player::CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov ) +{ + if ( m_lifeState != LIFE_ALIVE && !IsObserver() ) + { + 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* CFF_CL_Player::GetRepresentativeRagdoll() const +{ + if ( m_hRagdoll.Get() ) + { + CFF_CL_Ragdoll *pRagdoll = (CFF_CL_Ragdoll*)m_hRagdoll.Get(); + + return pRagdoll->GetIRagdoll(); + } + else + { + return NULL; + } +} + +//FFRAGDOLL + + +IMPLEMENT_CLIENTCLASS_DT_NOBASE( CFF_CL_Ragdoll, DT_FFRagdoll, CFF_SV_Ragdoll ) + 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() + + + +CFF_CL_Ragdoll::CFF_CL_Ragdoll() +{ + +} + +CFF_CL_Ragdoll::~CFF_CL_Ragdoll() +{ + PhysCleanupFrictionSounds( this ); + + if ( m_hPlayer ) + { + m_hPlayer->CreateModelInstance(); + } +} + +void CFF_CL_Ragdoll::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 CFF_CL_Ragdoll::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 ); + + // Blood spray! +// FX_CS_BloodSpray( hitpos, dir, 10 ); + } + + m_pRagdoll->ResetRagdollSleepAfterTime(); +} + + +void CFF_CL_Ragdoll::CreateFFRagdoll( 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. + CFF_CL_Player *pPlayer = dynamic_cast< CFF_CL_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 CFF_CL_Ragdoll::OnDataChanged( DataUpdateType_t type ) +{ + BaseClass::OnDataChanged( type ); + + if ( type == DATA_UPDATE_CREATED ) + { + CreateFFRagdoll(); + } +} + +IRagdoll* CFF_CL_Ragdoll::GetIRagdoll() const +{ + return m_pRagdoll; +} + +void CFF_CL_Ragdoll::UpdateOnRemove( void ) +{ + VPhysicsSetObject( NULL ); + + BaseClass::UpdateOnRemove(); +} + +//----------------------------------------------------------------------------- +// Purpose: clear out any face/eye values stored in the material system +//----------------------------------------------------------------------------- +void CFF_CL_Ragdoll::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 ); + } + } +} + +void CFF_CL_Player::PostThink( void ) +{ + BaseClass::PostThink(); + + // Store the eye angles pitch so the client can compute its animation state correctly. + m_angEyeAngles = EyeAngles(); +} \ No newline at end of file diff --git a/mp/src/game/client/ff/ff_cl_player.h b/mp/src/game/client/ff/ff_cl_player.h new file mode 100644 index 00000000..acfab38c --- /dev/null +++ b/mp/src/game/client/ff/ff_cl_player.h @@ -0,0 +1,173 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#ifndef FF_CL_PLAYER_H +#define FF_CL_PLAYER_H +#pragma once + +class CFF_CL_Player; +#include "c_basehlplayer.h" +#include "ff_sh_player.h" +#include "beamdraw.h" + +//============================================================================= +// >> FF_Player +//============================================================================= +class CFF_CL_Player : public C_BaseHLPlayer +{ +public: + DECLARE_CLASS( CFF_CL_Player, C_BaseHLPlayer ); + + DECLARE_CLIENTCLASS(); + DECLARE_PREDICTABLE(); + DECLARE_INTERPOLATION(); + + + CFF_CL_Player(); + ~CFF_CL_Player( void ); + + void ClientThink( void ); + + static CFF_CL_Player* GetLocalFFPlayer(); + + virtual int DrawModel( int flags ); + virtual void AddEntity( void ); + + QAngle GetAnimEyeAngles( void ) { return m_angEyeAngles; } + Vector GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget = NULL ); + + + // Should this object cast shadows? + virtual ShadowType_t ShadowCastType( void ); + virtual C_BaseAnimating *BecomeRagdollOnClient(); + virtual const QAngle& GetRenderAngles(); + virtual bool ShouldDraw( void ); + virtual void OnDataChanged( DataUpdateType_t type ); + virtual float GetFOV( void ); + virtual CStudioHdr *OnNewModel( void ); + virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator ); + virtual void ItemPreFrame( void ); + virtual void ItemPostFrame( void ); + virtual float GetMinFOV() const { return 5.0f; } + virtual Vector GetAutoaimVector( float flDelta ); + virtual void NotifyShouldTransmit( ShouldTransmitState_t state ); + virtual void CreateLightEffects( void ) {} + virtual bool ShouldReceiveProjectedTextures( int flags ); + virtual void PostDataUpdate( DataUpdateType_t updateType ); + virtual void PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool force ); + virtual void PreThink( void ); + virtual void DoImpactEffect( trace_t &tr, int nDamageType ); + IRagdoll* GetRepresentativeRagdoll() const; + virtual void CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov ); + virtual const QAngle& EyeAngles( void ); + + + bool CanSprint( void ); + void StartSprinting( void ); + void StopSprinting( void ); + void HandleSpeedChanges( void ); + void UpdateLookAt( void ); + void Initialize( void ); + int GetIDTarget() const; + void UpdateIDTarget( void ); + void PrecacheFootStepSounds( void ); + const char *GetPlayerModelSoundPrefix( void ); + + FFPlayerState State_Get() const; + + // Walking + void StartWalking( void ); + void StopWalking( void ); + bool IsWalking( void ) { return m_fIsWalking; } + + virtual void PostThink( void ); + +private: + + CFF_CL_Player( const CFF_CL_Player & ); + + CPlayerAnimState m_PlayerAnimState; + + QAngle m_angEyeAngles; + + CInterpolatedVar< QAngle > m_iv_angEyeAngles; + + EHANDLE m_hRagdoll; + + int m_headYawPoseParam; + int m_headPitchPoseParam; + float m_headYawMin; + float m_headYawMax; + float m_headPitchMin; + float m_headPitchMax; + + bool m_isInit; + Vector m_vLookAtTarget; + + float m_flLastBodyYaw; + float m_flCurrentHeadYaw; + float m_flCurrentHeadPitch; + + int m_iIDEntIndex; + + CountdownTimer m_blinkTimer; + + int m_iSpawnInterpCounter; + int m_iSpawnInterpCounterCache; + + int m_iPlayerSoundType; + + void ReleaseFlashlight( void ); + Beam_t *m_pFlashlightBeam; + + CNetworkVar( FFPlayerState, m_iPlayerState ); + + bool m_fIsWalking; +}; + +inline CFF_CL_Player *ToFFPlayer( CBaseEntity *pEntity ) +{ + if ( !pEntity || !pEntity->IsPlayer() ) + return NULL; + + return dynamic_cast( pEntity ); +} + + +class CFF_CL_Ragdoll : public C_BaseAnimatingOverlay +{ +public: + DECLARE_CLASS( CFF_CL_Ragdoll, C_BaseAnimatingOverlay ); + DECLARE_CLIENTCLASS(); + + CFF_CL_Ragdoll(); + ~CFF_CL_Ragdoll(); + + virtual void OnDataChanged( DataUpdateType_t type ); + + int GetPlayerEntIndex() const; + IRagdoll* GetIRagdoll() const; + + void ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName ); + void UpdateOnRemove( void ); + virtual void SetupWeights( const matrix3x4_t *pBoneToWorld, int nFlexWeightCount, float *pFlexWeights, float *pFlexDelayedWeights ); + +private: + + CFF_CL_Ragdoll( const CFF_CL_Ragdoll & ) {} + + void Interp_Copy( C_BaseAnimatingOverlay *pDestinationEntity ); + void CreateFFRagdoll( void ); + +private: + + EHANDLE m_hPlayer; + CNetworkVector( m_vecRagdollVelocity ); + CNetworkVector( m_vecRagdollOrigin ); +}; + +#endif //FF_CL_PLAYER_H diff --git a/mp/src/game/client/hl2mp/hl2mp_hud_chat.cpp b/mp/src/game/client/hl2mp/hl2mp_hud_chat.cpp index 84c17e61..a060838e 100644 --- a/mp/src/game/client/hl2mp/hl2mp_hud_chat.cpp +++ b/mp/src/game/client/hl2mp/hl2mp_hud_chat.cpp @@ -12,7 +12,7 @@ #include "vgui/ILocalize.h" #include "c_team.h" #include "c_playerresource.h" -#include "c_hl2mp_player.h" +#include "ff_cl_player.h" #include "ff_sh_gamerules.h" #include "ihudlcd.h" diff --git a/mp/src/game/client/hl2mp/hl2mp_hud_target_id.cpp b/mp/src/game/client/hl2mp/hl2mp_hud_target_id.cpp index 791ebcac..1c85b84c 100644 --- a/mp/src/game/client/hl2mp/hl2mp_hud_target_id.cpp +++ b/mp/src/game/client/hl2mp/hl2mp_hud_target_id.cpp @@ -7,7 +7,7 @@ #include "cbase.h" #include "hud.h" #include "hudelement.h" -#include "c_hl2mp_player.h" +#include "ff_cl_player.h" #include "c_playerresource.h" #include "vgui_entitypanel.h" #include "iclientmode.h" @@ -106,7 +106,7 @@ void CTargetID::Paint() wchar_t sIDString[ MAX_ID_STRING ]; sIDString[0] = 0; - C_HL2MP_Player *pPlayer = C_HL2MP_Player::GetLocalHL2MPPlayer(); + CFF_CL_Player *pPlayer = CFF_CL_Player::GetLocalFFPlayer(); if ( !pPlayer ) return; diff --git a/mp/src/game/client/hl2mp/hl2mp_hud_team.cpp b/mp/src/game/client/hl2mp/hl2mp_hud_team.cpp index 98ef1695..bc5b6a16 100644 --- a/mp/src/game/client/hl2mp/hl2mp_hud_team.cpp +++ b/mp/src/game/client/hl2mp/hl2mp_hud_team.cpp @@ -7,7 +7,7 @@ #include "cbase.h" #include "hud.h" #include "hudelement.h" -#include "c_hl2mp_player.h" +#include "ff_cl_player.h" #include "c_playerresource.h" #include "vgui_entitypanel.h" #include "iclientmode.h" diff --git a/mp/src/game/client/hl2mp/ui/hl2mpclientscoreboard.cpp b/mp/src/game/client/hl2mp/ui/hl2mpclientscoreboard.cpp index 6f4d266c..aaf18816 100644 --- a/mp/src/game/client/hl2mp/ui/hl2mpclientscoreboard.cpp +++ b/mp/src/game/client/hl2mp/ui/hl2mpclientscoreboard.cpp @@ -10,7 +10,7 @@ #include "hl2mpclientscoreboard.h" #include "c_team.h" #include "c_playerresource.h" -#include "c_hl2mp_player.h" +#include "ff_cl_player.h" #include "ff_sh_gamerules.h" #include diff --git a/mp/src/game/server/ff/ff_sv_client.cpp b/mp/src/game/server/ff/ff_sv_client.cpp index 7c330d3b..e6e4484d 100644 --- a/mp/src/game/server/ff/ff_sv_client.cpp +++ b/mp/src/game/server/ff/ff_sv_client.cpp @@ -14,7 +14,7 @@ */ #include "cbase.h" -#include "hl2mp_player.h" +#include "ff_sv_player.h" #include "ff_sh_gamerules.h" #include "gamerules.h" #include "teamplay_gamerules.h" @@ -38,7 +38,7 @@ ConVar sv_motd_unload_on_dismissal( "sv_motd_unload_on_dismissal", "0", 0, "If e extern CBaseEntity* FindPickerEntityClass( CBasePlayer *pPlayer, char *classname ); extern bool g_fGameOver; -void FinishClientPutInServer( CHL2MP_Player *pPlayer ) +void FinishClientPutInServer( CFF_SV_Player *pPlayer ) { pPlayer->InitialSpawn(); pPlayer->Spawn(); @@ -87,7 +87,7 @@ called each time a player is spawned into the game void ClientPutInServer( edict_t *pEdict, const char *playername ) { // Allocate a CBaseTFPlayer for pev, and call spawn - CHL2MP_Player *pPlayer = CHL2MP_Player::CreatePlayer( "player", pEdict ); + CFF_SV_Player *pPlayer = CFF_SV_Player::CreatePlayer( "player", pEdict ); pPlayer->SetPlayerName( playername ); } @@ -97,7 +97,7 @@ void ClientActive( edict_t *pEdict, bool bLoadGame ) // Can't load games in CS! Assert( !bLoadGame ); - CHL2MP_Player *pPlayer = ToHL2MPPlayer( CBaseEntity::Instance( pEdict ) ); + CFF_SV_Player *pPlayer = ToFFPlayer( CBaseEntity::Instance( pEdict ) ); FinishClientPutInServer( pPlayer ); } @@ -160,7 +160,7 @@ void ClientGamePrecache( void ) // called by ClientKill and DeadThink void respawn( CBaseEntity *pEdict, bool fCopyCorpse ) { - CHL2MP_Player *pPlayer = ToHL2MPPlayer( pEdict ); + CFF_SV_Player *pPlayer = ToFFPlayer( pEdict ); if ( pPlayer ) { diff --git a/mp/src/game/server/ff/ff_sv_player.cpp b/mp/src/game/server/ff/ff_sv_player.cpp new file mode 100644 index 00000000..8a9a1a27 --- /dev/null +++ b/mp/src/game/server/ff/ff_sv_player.cpp @@ -0,0 +1,1634 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Player for FF. +// +//=============================================================================// + +#include "cbase.h" +#include "weapon_hl2mpbasehlmpcombatweapon.h" +#include "ff_sv_player.h" +#include "globalstate.h" +#include "game.h" +#include "gamerules.h" +#include "ff_sh_player.h" +#include "predicted_viewmodel.h" +#include "in_buttons.h" +#include "ff_sh_gamerules.h" +#include "KeyValues.h" +#include "team.h" +#include "weapon_hl2mpbase.h" +#include "grenade_satchel.h" +#include "eventqueue.h" +#include "gamestats.h" + +#include "engine/IEngineSound.h" +#include "SoundEmitterSystem/isoundemittersystembase.h" + +#include "ilagcompensationmanager.h" + +// Don't alias here +#if defined( CFF_SH_Player ) +#undef CFF_SH_Player +#endif + +int g_iLastCitizenModel = 0; +int g_iLastCombineModel = 0; + +CBaseEntity *g_pLastCombineSpawn = NULL; +CBaseEntity *g_pLastRebelSpawn = NULL; +extern CBaseEntity *g_pLastSpawn; + +#define FF_COMMAND_MAX_RATE 0.3 + +void DropPrimedFragGrenade( CFF_SV_Player *pPlayer, CBaseCombatWeapon *pGrenade ); + +LINK_ENTITY_TO_CLASS( player, CFF_SV_Player ); + +LINK_ENTITY_TO_CLASS( info_player_combine, CPointEntity ); +LINK_ENTITY_TO_CLASS( info_player_rebel, CPointEntity ); + +IMPLEMENT_SERVERCLASS_ST(CFF_SV_Player, DT_FF_Player) + SendPropAngle( SENDINFO_VECTORELEM(m_angEyeAngles, 0), 11, SPROP_CHANGES_OFTEN ), + SendPropAngle( SENDINFO_VECTORELEM(m_angEyeAngles, 1), 11, SPROP_CHANGES_OFTEN ), + SendPropEHandle( SENDINFO( m_hRagdoll ) ), + SendPropInt( SENDINFO( m_iSpawnInterpCounter), 4 ), + SendPropInt( SENDINFO( m_iPlayerSoundType), 3 ), + + SendPropExclude( "DT_BaseAnimating", "m_flPoseParameter" ), + SendPropExclude( "DT_BaseFlex", "m_viewtarget" ), + +// SendPropExclude( "DT_ServerAnimationData" , "m_flCycle" ), +// SendPropExclude( "DT_AnimTimeMustBeFirst" , "m_flAnimTime" ), + +END_SEND_TABLE() + +BEGIN_DATADESC( CFF_SV_Player ) +END_DATADESC() + +const char *g_ppszRandomCitizenModels[] = +{ + "models/humans/group03/male_01.mdl", + "models/humans/group03/male_02.mdl", + "models/humans/group03/female_01.mdl", + "models/humans/group03/male_03.mdl", + "models/humans/group03/female_02.mdl", + "models/humans/group03/male_04.mdl", + "models/humans/group03/female_03.mdl", + "models/humans/group03/male_05.mdl", + "models/humans/group03/female_04.mdl", + "models/humans/group03/male_06.mdl", + "models/humans/group03/female_06.mdl", + "models/humans/group03/male_07.mdl", + "models/humans/group03/female_07.mdl", + "models/humans/group03/male_08.mdl", + "models/humans/group03/male_09.mdl", +}; + +const char *g_ppszRandomCombineModels[] = +{ + "models/combine_soldier.mdl", + "models/combine_soldier_prisonguard.mdl", + "models/combine_super_soldier.mdl", + "models/police.mdl", +}; + + +#define MAX_COMBINE_MODELS 4 +#define MODEL_CHANGE_INTERVAL 5.0f +#define TEAM_CHANGE_INTERVAL 5.0f + +#define FFPLAYER_PHYSDAMAGE_SCALE 4.0f + +#pragma warning( disable : 4355 ) + +CFF_SV_Player::CFF_SV_Player() : m_PlayerAnimState( this ) +{ + m_angEyeAngles.Init(); + + m_iLastWeaponFireUsercmd = 0; + + m_flNextModelChangeTime = 0.0f; + m_flNextTeamChangeTime = 0.0f; + + m_iSpawnInterpCounter = 0; + + m_bEnterObserver = false; + m_bReady = false; + + BaseClass::ChangeTeam( 0 ); + +// UseClientSideAnimation(); +} + +CFF_SV_Player::~CFF_SV_Player( void ) +{ + +} + +void CFF_SV_Player::UpdateOnRemove( void ) +{ + if ( m_hRagdoll ) + { + UTIL_RemoveImmediate( m_hRagdoll ); + m_hRagdoll = NULL; + } + + BaseClass::UpdateOnRemove(); +} + +void CFF_SV_Player::Precache( void ) +{ + BaseClass::Precache(); + + PrecacheModel ( "sprites/glow01.vmt" ); + + //Precache Citizen models + int nHeads = ARRAYSIZE( g_ppszRandomCitizenModels ); + int i; + + for ( i = 0; i < nHeads; ++i ) + PrecacheModel( g_ppszRandomCitizenModels[i] ); + + //Precache Combine Models + nHeads = ARRAYSIZE( g_ppszRandomCombineModels ); + + for ( i = 0; i < nHeads; ++i ) + PrecacheModel( g_ppszRandomCombineModels[i] ); + + PrecacheFootStepSounds(); + + PrecacheScriptSound( "NPC_MetroPolice.Die" ); + PrecacheScriptSound( "NPC_CombineS.Die" ); + PrecacheScriptSound( "NPC_Citizen.die" ); +} + +void CFF_SV_Player::GiveAllItems( void ) +{ + EquipSuit(); + + CBasePlayer::GiveAmmo( 255, "Pistol"); + CBasePlayer::GiveAmmo( 255, "AR2" ); + CBasePlayer::GiveAmmo( 5, "AR2AltFire" ); + CBasePlayer::GiveAmmo( 255, "SMG1"); + CBasePlayer::GiveAmmo( 1, "smg1_grenade"); + CBasePlayer::GiveAmmo( 255, "Buckshot"); + CBasePlayer::GiveAmmo( 32, "357" ); + CBasePlayer::GiveAmmo( 3, "rpg_round"); + + CBasePlayer::GiveAmmo( 1, "grenade" ); + CBasePlayer::GiveAmmo( 2, "slam" ); + + GiveNamedItem( "weapon_crowbar" ); + GiveNamedItem( "weapon_stunstick" ); + GiveNamedItem( "weapon_pistol" ); + GiveNamedItem( "weapon_357" ); + + GiveNamedItem( "weapon_smg1" ); + GiveNamedItem( "weapon_ar2" ); + + GiveNamedItem( "weapon_shotgun" ); + GiveNamedItem( "weapon_frag" ); + + GiveNamedItem( "weapon_crossbow" ); + + GiveNamedItem( "weapon_rpg" ); + + GiveNamedItem( "weapon_slam" ); + + GiveNamedItem( "weapon_physcannon" ); + +} + +void CFF_SV_Player::GiveDefaultItems( void ) +{ + EquipSuit(); + + CBasePlayer::GiveAmmo( 255, "Pistol"); + CBasePlayer::GiveAmmo( 45, "SMG1"); + CBasePlayer::GiveAmmo( 1, "grenade" ); + CBasePlayer::GiveAmmo( 6, "Buckshot"); + CBasePlayer::GiveAmmo( 6, "357" ); + + if ( GetPlayerModelType() == PLAYER_SOUNDS_METROPOLICE || GetPlayerModelType() == PLAYER_SOUNDS_COMBINESOLDIER ) + { + GiveNamedItem( "weapon_stunstick" ); + } + else if ( GetPlayerModelType() == PLAYER_SOUNDS_CITIZEN ) + { + GiveNamedItem( "weapon_crowbar" ); + } + + GiveNamedItem( "weapon_pistol" ); + GiveNamedItem( "weapon_smg1" ); + GiveNamedItem( "weapon_frag" ); + GiveNamedItem( "weapon_physcannon" ); + + const char *szDefaultWeaponName = engine->GetClientConVarValue( engine->IndexOfEdict( edict() ), "cl_defaultweapon" ); + + CBaseCombatWeapon *pDefaultWeapon = Weapon_OwnsThisType( szDefaultWeaponName ); + + if ( pDefaultWeapon ) + { + Weapon_Switch( pDefaultWeapon ); + } + else + { + Weapon_Switch( Weapon_OwnsThisType( "weapon_physcannon" ) ); + } +} + +void CFF_SV_Player::PickDefaultSpawnTeam( void ) +{ + if ( GetTeamNumber() == 0 ) + { + if ( FFRules()->IsTeamplay() == false ) + { + if ( GetModelPtr() == NULL ) + { + const char *szModelName = NULL; + szModelName = engine->GetClientConVarValue( engine->IndexOfEdict( edict() ), "cl_playermodel" ); + + if ( ValidatePlayerModel( szModelName ) == false ) + { + char szReturnString[512]; + + Q_snprintf( szReturnString, sizeof (szReturnString ), "cl_playermodel models/combine_soldier.mdl\n" ); + engine->ClientCommand ( edict(), szReturnString ); + } + + ChangeTeam( TEAM_UNASSIGNED ); + } + } + else + { + CTeam *pCombine = g_Teams[TEAM_COMBINE]; + CTeam *pRebels = g_Teams[TEAM_REBELS]; + + if ( pCombine == NULL || pRebels == NULL ) + { + ChangeTeam( random->RandomInt( TEAM_COMBINE, TEAM_REBELS ) ); + } + else + { + if ( pCombine->GetNumPlayers() > pRebels->GetNumPlayers() ) + { + ChangeTeam( TEAM_REBELS ); + } + else if ( pCombine->GetNumPlayers() < pRebels->GetNumPlayers() ) + { + ChangeTeam( TEAM_COMBINE ); + } + else + { + ChangeTeam( random->RandomInt( TEAM_COMBINE, TEAM_REBELS ) ); + } + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Sets HL2 specific defaults. +//----------------------------------------------------------------------------- +void CFF_SV_Player::Spawn(void) +{ + m_flNextModelChangeTime = 0.0f; + m_flNextTeamChangeTime = 0.0f; + + PickDefaultSpawnTeam(); + + BaseClass::Spawn(); + + if ( !IsObserver() ) + { + pl.deadflag = false; + RemoveSolidFlags( FSOLID_NOT_SOLID ); + + RemoveEffects( EF_NODRAW ); + + GiveDefaultItems(); + } + + SetNumAnimOverlays( 3 ); + ResetAnimation(); + + m_nRenderFX = kRenderNormal; + + m_Local.m_iHideHUD = 0; + + AddFlag(FL_ONGROUND); // set the player on the ground at the start of the round. + + m_impactEnergyScale = FFPLAYER_PHYSDAMAGE_SCALE; + + if ( FFRules()->IsIntermission() ) + { + AddFlag( FL_FROZEN ); + } + else + { + RemoveFlag( FL_FROZEN ); + } + + m_iSpawnInterpCounter = (m_iSpawnInterpCounter + 1) % 8; + + m_Local.m_bDucked = false; + + SetPlayerUnderwater(false); + + m_bReady = false; +} + +void CFF_SV_Player::PickupObject( CBaseEntity *pObject, bool bLimitMassAndSize ) +{ + +} + +bool CFF_SV_Player::ValidatePlayerModel( const char *pModel ) +{ + int iModels = ARRAYSIZE( g_ppszRandomCitizenModels ); + int i; + + for ( i = 0; i < iModels; ++i ) + { + if ( !Q_stricmp( g_ppszRandomCitizenModels[i], pModel ) ) + { + return true; + } + } + + iModels = ARRAYSIZE( g_ppszRandomCombineModels ); + + for ( i = 0; i < iModels; ++i ) + { + if ( !Q_stricmp( g_ppszRandomCombineModels[i], pModel ) ) + { + return true; + } + } + + return false; +} + +void CFF_SV_Player::SetPlayerTeamModel( void ) +{ + const char *szModelName = NULL; + szModelName = engine->GetClientConVarValue( engine->IndexOfEdict( edict() ), "cl_playermodel" ); + + int modelIndex = modelinfo->GetModelIndex( szModelName ); + + if ( modelIndex == -1 || ValidatePlayerModel( szModelName ) == false ) + { + szModelName = "models/Combine_Soldier.mdl"; + m_iModelType = TEAM_COMBINE; + + char szReturnString[512]; + + Q_snprintf( szReturnString, sizeof (szReturnString ), "cl_playermodel %s\n", szModelName ); + engine->ClientCommand ( edict(), szReturnString ); + } + + if ( GetTeamNumber() == TEAM_COMBINE ) + { + if ( Q_stristr( szModelName, "models/human") ) + { + int nHeads = ARRAYSIZE( g_ppszRandomCombineModels ); + + g_iLastCombineModel = ( g_iLastCombineModel + 1 ) % nHeads; + szModelName = g_ppszRandomCombineModels[g_iLastCombineModel]; + } + + m_iModelType = TEAM_COMBINE; + } + else if ( GetTeamNumber() == TEAM_REBELS ) + { + if ( !Q_stristr( szModelName, "models/human") ) + { + int nHeads = ARRAYSIZE( g_ppszRandomCitizenModels ); + + g_iLastCitizenModel = ( g_iLastCitizenModel + 1 ) % nHeads; + szModelName = g_ppszRandomCitizenModels[g_iLastCitizenModel]; + } + + m_iModelType = TEAM_REBELS; + } + + SetModel( szModelName ); + SetupPlayerSoundsByModel( szModelName ); + + m_flNextModelChangeTime = gpGlobals->curtime + MODEL_CHANGE_INTERVAL; +} + +void CFF_SV_Player::SetPlayerModel( void ) +{ + const char *szModelName = NULL; + const char *pszCurrentModelName = modelinfo->GetModelName( GetModel()); + + szModelName = engine->GetClientConVarValue( engine->IndexOfEdict( edict() ), "cl_playermodel" ); + + if ( ValidatePlayerModel( szModelName ) == false ) + { + char szReturnString[512]; + + if ( ValidatePlayerModel( pszCurrentModelName ) == false ) + { + pszCurrentModelName = "models/Combine_Soldier.mdl"; + } + + Q_snprintf( szReturnString, sizeof (szReturnString ), "cl_playermodel %s\n", pszCurrentModelName ); + engine->ClientCommand ( edict(), szReturnString ); + + szModelName = pszCurrentModelName; + } + + if ( GetTeamNumber() == TEAM_COMBINE ) + { + int nHeads = ARRAYSIZE( g_ppszRandomCombineModels ); + + g_iLastCombineModel = ( g_iLastCombineModel + 1 ) % nHeads; + szModelName = g_ppszRandomCombineModels[g_iLastCombineModel]; + + m_iModelType = TEAM_COMBINE; + } + else if ( GetTeamNumber() == TEAM_REBELS ) + { + int nHeads = ARRAYSIZE( g_ppszRandomCitizenModels ); + + g_iLastCitizenModel = ( g_iLastCitizenModel + 1 ) % nHeads; + szModelName = g_ppszRandomCitizenModels[g_iLastCitizenModel]; + + m_iModelType = TEAM_REBELS; + } + else + { + if ( Q_strlen( szModelName ) == 0 ) + { + szModelName = g_ppszRandomCitizenModels[0]; + } + + if ( Q_stristr( szModelName, "models/human") ) + { + m_iModelType = TEAM_REBELS; + } + else + { + m_iModelType = TEAM_COMBINE; + } + } + + int modelIndex = modelinfo->GetModelIndex( szModelName ); + + if ( modelIndex == -1 ) + { + szModelName = "models/Combine_Soldier.mdl"; + m_iModelType = TEAM_COMBINE; + + char szReturnString[512]; + + Q_snprintf( szReturnString, sizeof (szReturnString ), "cl_playermodel %s\n", szModelName ); + engine->ClientCommand ( edict(), szReturnString ); + } + + SetModel( szModelName ); + SetupPlayerSoundsByModel( szModelName ); + + m_flNextModelChangeTime = gpGlobals->curtime + MODEL_CHANGE_INTERVAL; +} + +void CFF_SV_Player::SetupPlayerSoundsByModel( const char *pModelName ) +{ + if ( Q_stristr( pModelName, "models/human") ) + { + m_iPlayerSoundType = (int)PLAYER_SOUNDS_CITIZEN; + } + else if ( Q_stristr(pModelName, "police" ) ) + { + m_iPlayerSoundType = (int)PLAYER_SOUNDS_METROPOLICE; + } + else if ( Q_stristr(pModelName, "combine" ) ) + { + m_iPlayerSoundType = (int)PLAYER_SOUNDS_COMBINESOLDIER; + } +} + +void CFF_SV_Player::ResetAnimation( void ) +{ + 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 ); + } +} + + +bool CFF_SV_Player::Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex ) +{ + bool bRet = BaseClass::Weapon_Switch( pWeapon, viewmodelindex ); + + if ( bRet == true ) + { + ResetAnimation(); + } + + return bRet; +} + +void CFF_SV_Player::PreThink( void ) +{ + QAngle vOldAngles = GetLocalAngles(); + QAngle vTempAngles = GetLocalAngles(); + + vTempAngles = EyeAngles(); + + if ( vTempAngles[PITCH] > 180.0f ) + { + vTempAngles[PITCH] -= 360.0f; + } + + SetLocalAngles( vTempAngles ); + + BaseClass::PreThink(); + State_PreThink(); + + //Reset bullet force accumulator, only lasts one frame + m_vecTotalBulletForce = vec3_origin; + SetLocalAngles( vOldAngles ); +} + +void CFF_SV_Player::PostThink( void ) +{ + BaseClass::PostThink(); + + if ( GetFlags() & FL_DUCKING ) + { + SetCollisionBounds( VEC_CROUCH_TRACE_MIN, VEC_CROUCH_TRACE_MAX ); + } + + m_PlayerAnimState.Update(); + + // Store the eye angles pitch so the client can compute its animation state correctly. + m_angEyeAngles = EyeAngles(); + + QAngle angles = GetLocalAngles(); + angles[PITCH] = 0; + SetLocalAngles( angles ); +} + +void CFF_SV_Player::PlayerDeathThink() +{ + if( !IsObserver() ) + { + BaseClass::PlayerDeathThink(); + } +} + +void CFF_SV_Player::FireBullets ( const FireBulletsInfo_t &info ) +{ + // Move other players back to history positions based on local player's lag + lagcompensation->StartLagCompensation( this, this->GetCurrentCommand() ); + + FireBulletsInfo_t modinfo = info; + + CWeaponHL2MPBase *pWeapon = dynamic_cast( GetActiveWeapon() ); + + if ( pWeapon ) + { + modinfo.m_iPlayerDamage = modinfo.m_flDamage = pWeapon->GetHL2MPWpnData().m_iPlayerDamage; + } + + NoteWeaponFired(); + + BaseClass::FireBullets( modinfo ); + + // Move other players back to history positions based on local player's lag + lagcompensation->FinishLagCompensation( this ); +} + +void CFF_SV_Player::NoteWeaponFired( void ) +{ + Assert( m_pCurrentCommand ); + if( m_pCurrentCommand ) + { + m_iLastWeaponFireUsercmd = m_pCurrentCommand->command_number; + } +} + +extern ConVar sv_maxunlag; + +bool CFF_SV_Player::WantsLagCompensationOnEntity( const CBasePlayer *pPlayer, const CUserCmd *pCmd, const CBitVec *pEntityTransmitBits ) const +{ + // No need to lag compensate at all if we're not attacking in this command and + // we haven't attacked recently. + if ( !( pCmd->buttons & IN_ATTACK ) && (pCmd->command_number - m_iLastWeaponFireUsercmd > 5) ) + return false; + + // If this entity hasn't been transmitted to us and acked, then don't bother lag compensating it. + if ( pEntityTransmitBits && !pEntityTransmitBits->Get( pPlayer->entindex() ) ) + return false; + + const Vector &vMyOrigin = GetAbsOrigin(); + const Vector &vHisOrigin = pPlayer->GetAbsOrigin(); + + // get max distance player could have moved within max lag compensation time, + // multiply by 1.5 to to avoid "dead zones" (sqrt(2) would be the exact value) + float maxDistance = 1.5 * pPlayer->MaxSpeed() * sv_maxunlag.GetFloat(); + + // If the player is within this distance, lag compensate them in case they're running past us. + if ( vHisOrigin.DistTo( vMyOrigin ) < maxDistance ) + return true; + + // If their origin is not within a 45 degree cone in front of us, no need to lag compensate. + Vector vForward; + AngleVectors( pCmd->viewangles, &vForward ); + + Vector vDiff = vHisOrigin - vMyOrigin; + VectorNormalize( vDiff ); + + float flCosAngle = 0.707107f; // 45 degree angle + if ( vForward.Dot( vDiff ) < flCosAngle ) + return false; + + return true; +} + +Activity CFF_SV_Player::TranslateTeamActivity( Activity ActToTranslate ) +{ + if ( m_iModelType == TEAM_COMBINE ) + return ActToTranslate; + + if ( ActToTranslate == ACT_RUN ) + return ACT_RUN_AIM_AGITATED; + + if ( ActToTranslate == ACT_IDLE ) + return ACT_IDLE_AIM_AGITATED; + + if ( ActToTranslate == ACT_WALK ) + return ACT_WALK_AIM_AGITATED; + + return ActToTranslate; +} + +extern ConVar hl2_normspeed; + +// Set the activity based on an event or current state +void CFF_SV_Player::SetAnimation( PLAYER_ANIM playerAnim ) +{ + int animDesired; + + 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; + } + } + } + + idealActivity = TranslateTeamActivity( idealActivity ); + } + + 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 ) + return; + + m_flPlaybackRate = 1.0; + ResetSequence( animDesired ); + SetCycle( 0 ); + return; + } + + // Already using the desired animation? + if ( GetSequence() == animDesired ) + return; + + //Msg( "Set animation to %d\n", animDesired ); + // Reset to first frame of desired animation + ResetSequence( animDesired ); + SetCycle( 0 ); +} + + +extern int gEvilImpulse101; +//----------------------------------------------------------------------------- +// Purpose: Player reacts to bumping a weapon. +// Input : pWeapon - the weapon that the player bumped into. +// Output : Returns true if player picked up the weapon +//----------------------------------------------------------------------------- +bool CFF_SV_Player::BumpWeapon( CBaseCombatWeapon *pWeapon ) +{ + CBaseCombatCharacter *pOwner = pWeapon->GetOwner(); + + // Can I have this weapon type? + if ( !IsAllowedToPickupWeapons() ) + return false; + + if ( pOwner || !Weapon_CanUse( pWeapon ) || !g_pGameRules->CanHavePlayerItem( this, pWeapon ) ) + { + if ( gEvilImpulse101 ) + { + UTIL_Remove( pWeapon ); + } + return false; + } + + // Don't let the player fetch weapons through walls (use MASK_SOLID so that you can't pickup through windows) + if( !pWeapon->FVisible( this, MASK_SOLID ) && !(GetFlags() & FL_NOTARGET) ) + { + return false; + } + + bool bOwnsWeaponAlready = !!Weapon_OwnsThisType( pWeapon->GetClassname(), pWeapon->GetSubType()); + + if ( bOwnsWeaponAlready == true ) + { + //If we have room for the ammo, then "take" the weapon too. + if ( Weapon_EquipAmmoOnly( pWeapon ) ) + { + pWeapon->CheckRespawn(); + + UTIL_Remove( pWeapon ); + return true; + } + else + { + return false; + } + } + + pWeapon->CheckRespawn(); + Weapon_Equip( pWeapon ); + + return true; +} + +void CFF_SV_Player::ChangeTeam( int iTeam ) +{ +/* if ( GetNextTeamChangeTime() >= gpGlobals->curtime ) + { + char szReturnString[128]; + Q_snprintf( szReturnString, sizeof( szReturnString ), "Please wait %d more seconds before trying to switch teams again.\n", (int)(GetNextTeamChangeTime() - gpGlobals->curtime) ); + + ClientPrint( this, HUD_PRINTTALK, szReturnString ); + return; + }*/ + + bool bKill = false; + + if ( FFRules()->IsTeamplay() != true && iTeam != TEAM_SPECTATOR ) + { + //don't let them try to join combine or rebels during deathmatch. + iTeam = TEAM_UNASSIGNED; + } + + if ( FFRules()->IsTeamplay() == true ) + { + if ( iTeam != GetTeamNumber() && GetTeamNumber() != TEAM_UNASSIGNED ) + { + bKill = true; + } + } + + BaseClass::ChangeTeam( iTeam ); + + m_flNextTeamChangeTime = gpGlobals->curtime + TEAM_CHANGE_INTERVAL; + + if ( FFRules()->IsTeamplay() == true ) + { + SetPlayerTeamModel(); + } + else + { + SetPlayerModel(); + } + + if ( iTeam == TEAM_SPECTATOR ) + { + RemoveAllItems( true ); + + State_Transition( STATE_OBSERVER_MODE ); + } + + if ( bKill == true ) + { + CommitSuicide(); + } +} + +bool CFF_SV_Player::HandleCommand_JoinTeam( int team ) +{ + if ( !GetGlobalTeam( team ) || team == 0 ) + { + Warning( "HandleCommand_JoinTeam( %d ) - invalid team index.\n", team ); + return false; + } + + if ( team == TEAM_SPECTATOR ) + { + // Prevent this is the cvar is set + if ( !mp_allowspectators.GetInt() ) + { + ClientPrint( this, HUD_PRINTCENTER, "#Cannot_Be_Spectator" ); + return false; + } + + if ( GetTeamNumber() != TEAM_UNASSIGNED && !IsDead() ) + { + m_fNextSuicideTime = gpGlobals->curtime; // allow the suicide to work + + CommitSuicide(); + + // add 1 to frags to balance out the 1 subtracted for killing yourself + IncrementFragCount( 1 ); + } + + ChangeTeam( TEAM_SPECTATOR ); + + return true; + } + else + { + StopObserverMode(); + State_Transition(STATE_ACTIVE); + } + + // Switch their actual team... + ChangeTeam( team ); + + return true; +} + +bool CFF_SV_Player::ClientCommand( const CCommand &args ) +{ + if ( FStrEq( args[0], "spectate" ) ) + { + if ( ShouldRunRateLimitedCommand( args ) ) + { + // instantly join spectators + HandleCommand_JoinTeam( TEAM_SPECTATOR ); + } + return true; + } + else if ( FStrEq( args[0], "jointeam" ) ) + { + if ( args.ArgC() < 2 ) + { + Warning( "Player sent bad jointeam syntax\n" ); + } + + if ( ShouldRunRateLimitedCommand( args ) ) + { + int iTeam = atoi( args[1] ); + HandleCommand_JoinTeam( iTeam ); + } + return true; + } + else if ( FStrEq( args[0], "joingame" ) ) + { + return true; + } + + return BaseClass::ClientCommand( args ); +} + +void CFF_SV_Player::CheatImpulseCommands( int iImpulse ) +{ + switch ( iImpulse ) + { + case 101: + { + if( sv_cheats->GetBool() ) + { + GiveAllItems(); + } + } + break; + + default: + BaseClass::CheatImpulseCommands( iImpulse ); + } +} + +bool CFF_SV_Player::ShouldRunRateLimitedCommand( const CCommand &args ) +{ + int i = m_RateLimitLastCommandTimes.Find( args[0] ); + if ( i == m_RateLimitLastCommandTimes.InvalidIndex() ) + { + m_RateLimitLastCommandTimes.Insert( args[0], gpGlobals->curtime ); + return true; + } + else if ( (gpGlobals->curtime - m_RateLimitLastCommandTimes[i]) < FF_COMMAND_MAX_RATE ) + { + // Too fast. + return false; + } + else + { + m_RateLimitLastCommandTimes[i] = gpGlobals->curtime; + return true; + } +} + +void CFF_SV_Player::CreateViewModel( int index /*=0*/ ) +{ + Assert( index >= 0 && index < MAX_VIEWMODELS ); + + if ( GetViewModel( index ) ) + return; + + CPredictedViewModel *vm = ( CPredictedViewModel * )CreateEntityByName( "predicted_viewmodel" ); + if ( vm ) + { + vm->SetAbsOrigin( GetAbsOrigin() ); + vm->SetOwner( this ); + vm->SetIndex( index ); + DispatchSpawn( vm ); + vm->FollowEntity( this, false ); + m_hViewModel.Set( index, vm ); + } +} + +bool CFF_SV_Player::BecomeRagdollOnClient( const Vector &force ) +{ + return true; +} + +// -------------------------------------------------------------------------------- // +// Ragdoll entities. +// -------------------------------------------------------------------------------- // + +class CFF_SV_Ragdoll : public CBaseAnimatingOverlay +{ +public: + DECLARE_CLASS( CFF_SV_Ragdoll, CBaseAnimatingOverlay ); + DECLARE_SERVERCLASS(); + + // Transmit ragdolls to everyone. + virtual int UpdateTransmitState() + { + return SetTransmitState( FL_EDICT_ALWAYS ); + } + +public: + // In case the client has the player entity, we transmit the player index. + // In case the client doesn't have it, we transmit the player's model index, origin, and angles + // so they can create a ragdoll in the right place. + CNetworkHandle( CBaseEntity, m_hPlayer ); // networked entity handle + CNetworkVector( m_vecRagdollVelocity ); + CNetworkVector( m_vecRagdollOrigin ); +}; + +LINK_ENTITY_TO_CLASS( ff_ragdoll, CFF_SV_Ragdoll ); + +IMPLEMENT_SERVERCLASS_ST_NOBASE( CFF_SV_Ragdoll, DT_FFRagdoll ) + SendPropVector( SENDINFO(m_vecRagdollOrigin), -1, SPROP_COORD ), + SendPropEHandle( SENDINFO( m_hPlayer ) ), + SendPropModelIndex( SENDINFO( m_nModelIndex ) ), + SendPropInt ( SENDINFO(m_nForceBone), 8, 0 ), + SendPropVector ( SENDINFO(m_vecForce), -1, SPROP_NOSCALE ), + SendPropVector( SENDINFO( m_vecRagdollVelocity ) ) +END_SEND_TABLE() + + +void CFF_SV_Player::CreateRagdollEntity( void ) +{ + if ( m_hRagdoll ) + { + UTIL_RemoveImmediate( m_hRagdoll ); + m_hRagdoll = NULL; + } + + // If we already have a ragdoll, don't make another one. + CFF_SV_Ragdoll *pRagdoll = dynamic_cast< CFF_SV_Ragdoll* >( m_hRagdoll.Get() ); + + if ( !pRagdoll ) + { + // create a new one + pRagdoll = dynamic_cast< CFF_SV_Ragdoll* >( CreateEntityByName( "ff_ragdoll" ) ); + } + + if ( pRagdoll ) + { + pRagdoll->m_hPlayer = this; + pRagdoll->m_vecRagdollOrigin = GetAbsOrigin(); + pRagdoll->m_vecRagdollVelocity = GetAbsVelocity(); + pRagdoll->m_nModelIndex = m_nModelIndex; + pRagdoll->m_nForceBone = m_nForceBone; + pRagdoll->m_vecForce = m_vecTotalBulletForce; + pRagdoll->SetAbsOrigin( GetAbsOrigin() ); + } + + // ragdolls will be removed on round restart automatically + m_hRagdoll = pRagdoll; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +int CFF_SV_Player::FlashlightIsOn( void ) +{ + return IsEffectActive( EF_DIMLIGHT ); +} + +extern ConVar flashlight; + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CFF_SV_Player::FlashlightTurnOn( void ) +{ + if( flashlight.GetInt() > 0 && IsAlive() ) + { + AddEffects( EF_DIMLIGHT ); + EmitSound( "HL2Player.FlashlightOn" ); + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CFF_SV_Player::FlashlightTurnOff( void ) +{ + RemoveEffects( EF_DIMLIGHT ); + + if( IsAlive() ) + { + EmitSound( "HL2Player.FlashlightOff" ); + } +} + +void CFF_SV_Player::Weapon_Drop( CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity ) +{ + //Drop a grenade if it's primed. + if ( GetActiveWeapon() ) + { + CBaseCombatWeapon *pGrenade = Weapon_OwnsThisType("weapon_frag"); + + if ( GetActiveWeapon() == pGrenade ) + { + if ( ( m_nButtons & IN_ATTACK ) || (m_nButtons & IN_ATTACK2) ) + { + DropPrimedFragGrenade( this, pGrenade ); + return; + } + } + } + + BaseClass::Weapon_Drop( pWeapon, pvecTarget, pVelocity ); +} + + +void CFF_SV_Player::DetonateTripmines( void ) +{ + CBaseEntity *pEntity = NULL; + + while ((pEntity = gEntList.FindEntityByClassname( pEntity, "npc_satchel" )) != NULL) + { + CSatchelCharge *pSatchel = dynamic_cast(pEntity); + if (pSatchel->m_bIsLive && pSatchel->GetThrower() == this ) + { + g_EventQueue.AddEvent( pSatchel, "Explode", 0.20, this, this ); + } + } + + // Play sound for pressing the detonator + EmitSound( "Weapon_SLAM.SatchelDetonate" ); +} + +void CFF_SV_Player::Event_Killed( const CTakeDamageInfo &info ) +{ + //update damage info with our accumulated physics force + CTakeDamageInfo subinfo = info; + subinfo.SetDamageForce( m_vecTotalBulletForce ); + + SetNumAnimOverlays( 0 ); + + // Note: since we're dead, it won't draw us on the client, but we don't set EF_NODRAW + // because we still want to transmit to the clients in our PVS. + CreateRagdollEntity(); + + DetonateTripmines(); + + BaseClass::Event_Killed( subinfo ); + + if ( info.GetDamageType() & DMG_DISSOLVE ) + { + if ( m_hRagdoll ) + { + m_hRagdoll->GetBaseAnimating()->Dissolve( NULL, gpGlobals->curtime, false, ENTITY_DISSOLVE_NORMAL ); + } + } + + CBaseEntity *pAttacker = info.GetAttacker(); + + if ( pAttacker ) + { + int iScoreToAdd = 1; + + if ( pAttacker == this ) + { + iScoreToAdd = -1; + } + + GetGlobalTeam( pAttacker->GetTeamNumber() )->AddScore( iScoreToAdd ); + } + + FlashlightTurnOff(); + + m_lifeState = LIFE_DEAD; + + RemoveEffects( EF_NODRAW ); // still draw player body + StopZooming(); +} + +int CFF_SV_Player::OnTakeDamage( const CTakeDamageInfo &inputInfo ) +{ + //return here if the player is in the respawn grace period vs. slams. + if ( gpGlobals->curtime < m_flSlamProtectTime && (inputInfo.GetDamageType() == DMG_BLAST ) ) + return 0; + + m_vecTotalBulletForce += inputInfo.GetDamageForce(); + + gamestats->Event_PlayerDamage( this, inputInfo ); + + return BaseClass::OnTakeDamage( inputInfo ); +} + +void CFF_SV_Player::DeathSound( const CTakeDamageInfo &info ) +{ + if ( m_hRagdoll && m_hRagdoll->GetBaseAnimating()->IsDissolving() ) + return; + + char szStepSound[128]; + + Q_snprintf( szStepSound, sizeof( szStepSound ), "%s.Die", GetPlayerModelSoundPrefix() ); + + const char *pModelName = STRING( GetModelName() ); + + CSoundParameters params; + if ( GetParametersForSound( szStepSound, params, pModelName ) == false ) + return; + + Vector vecOrigin = GetAbsOrigin(); + + CRecipientFilter filter; + filter.AddRecipientsByPAS( vecOrigin ); + + EmitSound_t ep; + ep.m_nChannel = params.channel; + ep.m_pSoundName = params.soundname; + ep.m_flVolume = params.volume; + ep.m_SoundLevel = params.soundlevel; + ep.m_nFlags = 0; + ep.m_nPitch = params.pitch; + ep.m_pOrigin = &vecOrigin; + + EmitSound( filter, entindex(), ep ); +} + +CBaseEntity* CFF_SV_Player::EntSelectSpawnPoint( void ) +{ + CBaseEntity *pSpot = NULL; + CBaseEntity *pLastSpawnPoint = g_pLastSpawn; + edict_t *player = edict(); + const char *pSpawnpointName = "info_player_deathmatch"; + + if ( FFRules()->IsTeamplay() == true ) + { + if ( GetTeamNumber() == TEAM_COMBINE ) + { + pSpawnpointName = "info_player_combine"; + pLastSpawnPoint = g_pLastCombineSpawn; + } + else if ( GetTeamNumber() == TEAM_REBELS ) + { + pSpawnpointName = "info_player_rebel"; + pLastSpawnPoint = g_pLastRebelSpawn; + } + + if ( gEntList.FindEntityByClassname( NULL, pSpawnpointName ) == NULL ) + { + pSpawnpointName = "info_player_deathmatch"; + pLastSpawnPoint = g_pLastSpawn; + } + } + + pSpot = pLastSpawnPoint; + // Randomize the start spot + for ( int i = random->RandomInt(1,5); i > 0; i-- ) + pSpot = gEntList.FindEntityByClassname( pSpot, pSpawnpointName ); + if ( !pSpot ) // skip over the null point + pSpot = gEntList.FindEntityByClassname( pSpot, pSpawnpointName ); + + CBaseEntity *pFirstSpot = pSpot; + + do + { + if ( pSpot ) + { + // check if pSpot is valid + if ( g_pGameRules->IsSpawnPointValid( pSpot, this ) ) + { + if ( pSpot->GetLocalOrigin() == vec3_origin ) + { + pSpot = gEntList.FindEntityByClassname( pSpot, pSpawnpointName ); + continue; + } + + // if so, go to pSpot + goto ReturnSpot; + } + } + // increment pSpot + pSpot = gEntList.FindEntityByClassname( pSpot, pSpawnpointName ); + } while ( pSpot != pFirstSpot ); // loop if we're not back to the start + + // we haven't found a place to spawn yet, so kill any guy at the first spawn point and spawn there + if ( pSpot ) + { + CBaseEntity *ent = NULL; + for ( CEntitySphereQuery sphere( pSpot->GetAbsOrigin(), 128 ); (ent = sphere.GetCurrentEntity()) != NULL; sphere.NextEntity() ) + { + // if ent is a client, kill em (unless they are ourselves) + if ( ent->IsPlayer() && !(ent->edict() == player) ) + ent->TakeDamage( CTakeDamageInfo( GetContainingEntity(INDEXENT(0)), GetContainingEntity(INDEXENT(0)), 300, DMG_GENERIC ) ); + } + goto ReturnSpot; + } + + if ( !pSpot ) + { + pSpot = gEntList.FindEntityByClassname( pSpot, "info_player_start" ); + + if ( pSpot ) + goto ReturnSpot; + } + +ReturnSpot: + + if ( FFRules()->IsTeamplay() == true ) + { + if ( GetTeamNumber() == TEAM_COMBINE ) + { + g_pLastCombineSpawn = pSpot; + } + else if ( GetTeamNumber() == TEAM_REBELS ) + { + g_pLastRebelSpawn = pSpot; + } + } + + g_pLastSpawn = pSpot; + + m_flSlamProtectTime = gpGlobals->curtime + 0.5; + + return pSpot; +} + + +CON_COMMAND( timeleft, "prints the time remaining in the match" ) +{ + CFF_SV_Player *pPlayer = ToFFPlayer( UTIL_GetCommandClient() ); + + int iTimeRemaining = (int)FFRules()->GetMapRemainingTime(); + + if ( iTimeRemaining == 0 ) + { + if ( pPlayer ) + { + ClientPrint( pPlayer, HUD_PRINTTALK, "This game has no timelimit." ); + } + else + { + Msg( "* No Time Limit *\n" ); + } + } + else + { + int iMinutes, iSeconds; + iMinutes = iTimeRemaining / 60; + iSeconds = iTimeRemaining % 60; + + char minutes[8]; + char seconds[8]; + + Q_snprintf( minutes, sizeof(minutes), "%d", iMinutes ); + Q_snprintf( seconds, sizeof(seconds), "%2.2d", iSeconds ); + + if ( pPlayer ) + { + ClientPrint( pPlayer, HUD_PRINTTALK, "Time left in map: %s1:%s2", minutes, seconds ); + } + else + { + Msg( "Time Remaining: %s:%s\n", minutes, seconds ); + } + } +} + + +void CFF_SV_Player::Reset() +{ + ResetDeathCount(); + ResetFragCount(); +} + +bool CFF_SV_Player::IsReady() +{ + return m_bReady; +} + +void CFF_SV_Player::SetReady( bool bReady ) +{ + m_bReady = bReady; +} + +void CFF_SV_Player::CheckChatText( char *p, int bufsize ) +{ + //Look for escape sequences and replace + + char *buf = new char[bufsize]; + int pos = 0; + + // Parse say text for escape sequences + for ( char *pSrc = p; pSrc != NULL && *pSrc != 0 && pos < bufsize-1; pSrc++ ) + { + // copy each char across + buf[pos] = *pSrc; + pos++; + } + + buf[pos] = '\0'; + + // copy buf back into p + Q_strncpy( p, buf, bufsize ); + + delete[] buf; + + const char *pReadyCheck = p; + + FFRules()->CheckChatForReadySignal( this, pReadyCheck ); +} + +void CFF_SV_Player::State_Transition( FFPlayerState newState ) +{ + State_Leave(); + State_Enter( newState ); +} + + +void CFF_SV_Player::State_Enter( FFPlayerState newState ) +{ + m_iPlayerState = newState; + m_pCurStateInfo = State_LookupInfo( newState ); + + // Initialize the new state. + if ( m_pCurStateInfo && m_pCurStateInfo->pfnEnterState ) + (this->*m_pCurStateInfo->pfnEnterState)(); +} + + +void CFF_SV_Player::State_Leave() +{ + if ( m_pCurStateInfo && m_pCurStateInfo->pfnLeaveState ) + { + (this->*m_pCurStateInfo->pfnLeaveState)(); + } +} + + +void CFF_SV_Player::State_PreThink() +{ + if ( m_pCurStateInfo && m_pCurStateInfo->pfnPreThink ) + { + (this->*m_pCurStateInfo->pfnPreThink)(); + } +} + + +CFFPlayerStateInfo *CFF_SV_Player::State_LookupInfo( FFPlayerState state ) +{ + // This table MUST match the + static CFFPlayerStateInfo playerStateInfos[] = + { + { STATE_ACTIVE, "STATE_ACTIVE", &CFF_SV_Player::State_Enter_ACTIVE, NULL, &CFF_SV_Player::State_PreThink_ACTIVE }, + { STATE_OBSERVER_MODE, "STATE_OBSERVER_MODE", &CFF_SV_Player::State_Enter_OBSERVER_MODE, NULL, &CFF_SV_Player::State_PreThink_OBSERVER_MODE } + }; + + for ( int i=0; i < ARRAYSIZE( playerStateInfos ); i++ ) + { + if ( playerStateInfos[i].m_iPlayerState == state ) + return &playerStateInfos[i]; + } + + return NULL; +} + +bool CFF_SV_Player::StartObserverMode(int mode) +{ + //we only want to go into observer mode if the player asked to, not on a death timeout + if ( m_bEnterObserver == true ) + { + VPhysicsDestroyObject(); + return BaseClass::StartObserverMode( mode ); + } + return false; +} + +void CFF_SV_Player::StopObserverMode() +{ + m_bEnterObserver = false; + BaseClass::StopObserverMode(); +} + +void CFF_SV_Player::State_Enter_OBSERVER_MODE() +{ + int observerMode = m_iObserverLastMode; + if ( IsNetClient() ) + { + const char *pIdealMode = engine->GetClientConVarValue( engine->IndexOfEdict( edict() ), "cl_spec_mode" ); + if ( pIdealMode ) + { + observerMode = atoi( pIdealMode ); + if ( observerMode <= OBS_MODE_FIXED || observerMode > OBS_MODE_ROAMING ) + { + observerMode = m_iObserverLastMode; + } + } + } + m_bEnterObserver = true; + StartObserverMode( observerMode ); +} + +void CFF_SV_Player::State_PreThink_OBSERVER_MODE() +{ + // Make sure nobody has changed any of our state. + // Assert( GetMoveType() == MOVETYPE_FLY ); + Assert( m_takedamage == DAMAGE_NO ); + Assert( IsSolidFlagSet( FSOLID_NOT_SOLID ) ); + // Assert( IsEffectActive( EF_NODRAW ) ); + + // Must be dead. + Assert( m_lifeState == LIFE_DEAD ); + Assert( pl.deadflag ); +} + + +void CFF_SV_Player::State_Enter_ACTIVE() +{ + SetMoveType( MOVETYPE_WALK ); + + // md 8/15/07 - They'll get set back to solid when they actually respawn. If we set them solid now and mp_forcerespawn + // is false, then they'll be spectating but blocking live players from moving. + // RemoveSolidFlags( FSOLID_NOT_SOLID ); + + m_Local.m_iHideHUD = 0; +} + + +void CFF_SV_Player::State_PreThink_ACTIVE() +{ + //we don't really need to do anything here. + //This state_prethink structure came over from CS:S and was doing an assert check that fails the way hl2dm handles death +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CFF_SV_Player::CanHearAndReadChatFrom( CBasePlayer *pPlayer ) +{ + // can always hear the console unless we're ignoring all chat + if ( !pPlayer ) + return false; + + return true; +} diff --git a/mp/src/game/server/ff/ff_sv_player.h b/mp/src/game/server/ff/ff_sv_player.h new file mode 100644 index 00000000..f96bee4c --- /dev/null +++ b/mp/src/game/server/ff/ff_sv_player.h @@ -0,0 +1,176 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#ifndef FF_SV_PLAYER_H +#define FF_SV_PLAYER_H +#pragma once + +class CFF_SV_Player; + +#include "basemultiplayerplayer.h" +#include "hl2_playerlocaldata.h" +#include "hl2_player.h" +#include "simtimer.h" +#include "soundenvelope.h" +#include "ff_sh_player.h" +#include "ff_sh_gamerules.h" +#include "utldict.h" + +//============================================================================= +// >> FF_Player +//============================================================================= +class CFFPlayerStateInfo +{ +public: + FFPlayerState m_iPlayerState; + const char *m_pStateName; + + void (CFF_SV_Player::*pfnEnterState)(); // Init and deinit the state. + void (CFF_SV_Player::*pfnLeaveState)(); + + void (CFF_SV_Player::*pfnPreThink)(); // Do a PreThink() in this state. +}; + +class CFF_SV_Player : public CHL2_Player +{ +public: + DECLARE_CLASS( CFF_SV_Player, CHL2_Player ); + + CFF_SV_Player(); + ~CFF_SV_Player( void ); + + static CFF_SV_Player *CreatePlayer( const char *className, edict_t *ed ) + { + CFF_SV_Player::s_PlayerEdict = ed; + return (CFF_SV_Player*)CreateEntityByName( className ); + } + + DECLARE_SERVERCLASS(); + DECLARE_DATADESC(); + + virtual void Precache( void ); + virtual void Spawn( void ); + virtual void PostThink( void ); + virtual void PreThink( void ); + virtual void PlayerDeathThink( void ); + virtual void SetAnimation( PLAYER_ANIM playerAnim ); + virtual bool HandleCommand_JoinTeam( int team ); + virtual bool ClientCommand( const CCommand &args ); + virtual void CreateViewModel( int viewmodelindex = 0 ); + virtual bool BecomeRagdollOnClient( const Vector &force ); + virtual void Event_Killed( const CTakeDamageInfo &info ); + virtual int OnTakeDamage( const CTakeDamageInfo &inputInfo ); + virtual bool WantsLagCompensationOnEntity( const CBasePlayer *pPlayer, const CUserCmd *pCmd, const CBitVec *pEntityTransmitBits ) const; + virtual void FireBullets ( const FireBulletsInfo_t &info ); + virtual bool Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex = 0); + virtual bool BumpWeapon( CBaseCombatWeapon *pWeapon ); + virtual void ChangeTeam( int iTeam ); + virtual void PickupObject ( CBaseEntity *pObject, bool bLimitMassAndSize ); + virtual void PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool force ); + virtual void Weapon_Drop( CBaseCombatWeapon *pWeapon, const Vector *pvecTarget = NULL, const Vector *pVelocity = NULL ); + virtual void UpdateOnRemove( void ); + virtual void DeathSound( const CTakeDamageInfo &info ); + virtual CBaseEntity* EntSelectSpawnPoint( void ); + + int FlashlightIsOn( void ); + void FlashlightTurnOn( void ); + void FlashlightTurnOff( void ); + void PrecacheFootStepSounds( void ); + bool ValidatePlayerModel( const char *pModel ); + + QAngle GetAnimEyeAngles( void ) { return m_angEyeAngles.Get(); } + + Vector GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget = NULL ); + + void CheatImpulseCommands( int iImpulse ); + void CreateRagdollEntity( void ); + void GiveAllItems( void ); + void GiveDefaultItems( void ); + + void NoteWeaponFired( void ); + + void ResetAnimation( void ); + void SetPlayerModel( void ); + void SetPlayerTeamModel( void ); + Activity TranslateTeamActivity( Activity ActToTranslate ); + + float GetNextModelChangeTime( void ) { return m_flNextModelChangeTime; } + float GetNextTeamChangeTime( void ) { return m_flNextTeamChangeTime; } + void PickDefaultSpawnTeam( void ); + void SetupPlayerSoundsByModel( const char *pModelName ); + const char *GetPlayerModelSoundPrefix( void ); + int GetPlayerModelType( void ) { return m_iPlayerSoundType; } + + void DetonateTripmines( void ); + + void Reset(); + + bool IsReady(); + void SetReady( bool bReady ); + + void CheckChatText( char *p, int bufsize ); + + void State_Transition( FFPlayerState newState ); + void State_Enter( FFPlayerState newState ); + void State_Leave(); + void State_PreThink(); + CFFPlayerStateInfo *State_LookupInfo( FFPlayerState state ); + + void State_Enter_ACTIVE(); + void State_PreThink_ACTIVE(); + void State_Enter_OBSERVER_MODE(); + void State_PreThink_OBSERVER_MODE(); + + + virtual bool StartObserverMode( int mode ); + virtual void StopObserverMode( void ); + + + Vector m_vecTotalBulletForce; //Accumulator for bullet force in a single frame + + // Tracks our ragdoll entity. + CNetworkHandle( CBaseEntity, m_hRagdoll ); // networked entity handle + + virtual bool CanHearAndReadChatFrom( CBasePlayer *pPlayer ); + + +private: + + CNetworkQAngle( m_angEyeAngles ); + CPlayerAnimState m_PlayerAnimState; + + int m_iLastWeaponFireUsercmd; + int m_iModelType; + CNetworkVar( int, m_iSpawnInterpCounter ); + CNetworkVar( int, m_iPlayerSoundType ); + + float m_flNextModelChangeTime; + float m_flNextTeamChangeTime; + + float m_flSlamProtectTime; + + FFPlayerState m_iPlayerState; + CFFPlayerStateInfo *m_pCurStateInfo; + + bool ShouldRunRateLimitedCommand( const CCommand &args ); + + // This lets us rate limit the commands the players can execute so they don't overflow things like reliable buffers. + CUtlDict m_RateLimitLastCommandTimes; + + bool m_bEnterObserver; + bool m_bReady; +}; + +inline CFF_SV_Player *ToFFPlayer( CBaseEntity *pEntity ) +{ + if ( !pEntity || !pEntity->IsPlayer() ) + return NULL; + + return dynamic_cast( pEntity ); +} + +#endif //FF_SV_PLAYER_H diff --git a/mp/src/game/server/hl2mp/hl2mp_bot_temp.cpp b/mp/src/game/server/hl2mp/hl2mp_bot_temp.cpp index 3aab7a12..1b008632 100644 --- a/mp/src/game/server/hl2mp/hl2mp_bot_temp.cpp +++ b/mp/src/game/server/hl2mp/hl2mp_bot_temp.cpp @@ -14,12 +14,12 @@ #include "cbase.h" #include "player.h" -#include "hl2mp_player.h" +#include "ff_sv_player.h" #include "in_buttons.h" #include "movehelper_server.h" void ClientPutInServer( edict_t *pEdict, const char *playername ); -void Bot_Think( CHL2MP_Player *pBot ); +void Bot_Think( CFF_SV_Player *pBot ); #ifdef DEBUG @@ -91,7 +91,7 @@ CBasePlayer *BotPutInServer( bool bFrozen, int iTeam ) // Allocate a CBasePlayer for the bot, and call spawn //ClientPutInServer( pEdict, botname ); - CHL2MP_Player *pPlayer = ((CHL2MP_Player *)CBaseEntity::Instance( pEdict )); + CFF_SV_Player *pPlayer = ((CFF_SV_Player *)CBaseEntity::Instance( pEdict )); pPlayer->ClearFlags(); pPlayer->AddFlag( FL_CLIENT | FL_FAKECLIENT ); @@ -113,7 +113,7 @@ void Bot_RunAll( void ) { for ( int i = 1; i <= gpGlobals->maxClients; i++ ) { - CHL2MP_Player *pPlayer = ToHL2MPPlayer( UTIL_PlayerByIndex( i ) ); + CFF_SV_Player *pPlayer = ToFFPlayer( UTIL_PlayerByIndex( i ) ); if ( pPlayer && (pPlayer->GetFlags() & FL_FAKECLIENT) ) { @@ -156,7 +156,7 @@ bool RunMimicCommand( CUserCmd& cmd ) // msec - // Output : virtual void //----------------------------------------------------------------------------- -static void RunPlayerMove( CHL2MP_Player *fakeclient, const QAngle& viewangles, float forwardmove, float sidemove, float upmove, unsigned short buttons, byte impulse, float frametime ) +static void RunPlayerMove( CFF_SV_Player *fakeclient, const QAngle& viewangles, float forwardmove, float sidemove, float upmove, unsigned short buttons, byte impulse, float frametime ) { if ( !fakeclient ) return; @@ -206,7 +206,7 @@ static void RunPlayerMove( CHL2MP_Player *fakeclient, const QAngle& viewangles, //----------------------------------------------------------------------------- // Purpose: Run this Bot's AI for one frame. //----------------------------------------------------------------------------- -void Bot_Think( CHL2MP_Player *pBot ) +void Bot_Think( CFF_SV_Player *pBot ) { // Make sure we stay being a bot pBot->AddFlag( FL_FAKECLIENT ); diff --git a/mp/src/game/server/server_ff.vpc b/mp/src/game/server/server_ff.vpc index 647352e8..e310cf46 100644 --- a/mp/src/game/server/server_ff.vpc +++ b/mp/src/game/server/server_ff.vpc @@ -34,9 +34,17 @@ $Project "Server (FF)" // for FF Shared, see game\shared\ff\ff_shared.vpc $Folder "FF" { - $File "FF\ff_sv_client.cpp" - $File "FF\ff_sv_gameinterface.cpp" - $File "FF\ff_sv_gameinterface.h" + $Folder "Game" + { + $File "FF\ff_sv_client.cpp" + $File "FF\ff_sv_gameinterface.cpp" + $File "FF\ff_sv_gameinterface.h" + } + $Folder "Player" + { + $File "ff\ff_sv_player.cpp" + $File "ff\ff_sv_player.h" + } $Folder "Libraries" { @@ -59,6 +67,11 @@ $Project "Server (FF)" -$File "hl2mp\hl2mp_client.cpp" -$File "hl2mp\hl2mp_gameinterface.cpp" -$File "hl2mp\hl2mp_gameinterface.h" + // Player + -$File "hl2mp\hl2mp_player.cpp" + -$File "hl2mp\hl2mp_player.h" + -$File "$SRCDIR\game\shared\hl2mp\hl2mp_player_shared.cpp" + -$File "$SRCDIR\game\shared\hl2mp\hl2mp_player_shared.h" } } } diff --git a/mp/src/game/shared/ff/ff_sh_gamerules.cpp b/mp/src/game/shared/ff/ff_sh_gamerules.cpp index 4f4cca71..1fdbf881 100644 --- a/mp/src/game/shared/ff/ff_sh_gamerules.cpp +++ b/mp/src/game/shared/ff/ff_sh_gamerules.cpp @@ -12,7 +12,7 @@ #include "ammodef.h" #ifdef CLIENT_DLL - #include "c_hl2mp_player.h" + #include "ff_cl_player.h" #else #include "eventqueue.h" @@ -26,7 +26,7 @@ #include #include "voice_gamemgr.h" #include "iscorer.h" - #include "hl2mp_player.h" + #include "ff_sv_player.h" #include "weapon_hl2mpbasehlmpcombatweapon.h" #include "team.h" #include "voice_gamemgr.h" @@ -764,9 +764,9 @@ void CFF_SH_Rules::ClientSettingsChanged( CBasePlayer *pPlayer ) { #ifndef CLIENT_DLL - CHL2MP_Player *pHL2Player = ToHL2MPPlayer( pPlayer ); + CFF_SH_Player *pFFPlayer = ToFFPlayer( pPlayer ); - if ( pHL2Player == NULL ) + if ( pFFPlayer == NULL ) return; const char *pCurrentModel = modelinfo->GetModelName( pPlayer->GetModel() ); @@ -778,44 +778,44 @@ void CFF_SH_Rules::ClientSettingsChanged( CBasePlayer *pPlayer ) //Too soon, set the cvar back to what it was. //Note: this will make this function be called again //but since our models will match it'll just skip this whole dealio. - if ( pHL2Player->GetNextModelChangeTime() >= gpGlobals->curtime ) + if ( pFFPlayer->GetNextModelChangeTime() >= gpGlobals->curtime ) { char szReturnString[512]; Q_snprintf( szReturnString, sizeof (szReturnString ), "cl_playermodel %s\n", pCurrentModel ); - engine->ClientCommand ( pHL2Player->edict(), szReturnString ); + engine->ClientCommand ( pFFPlayer->edict(), szReturnString ); - Q_snprintf( szReturnString, sizeof( szReturnString ), "Please wait %d more seconds before trying to switch.\n", (int)(pHL2Player->GetNextModelChangeTime() - gpGlobals->curtime) ); - ClientPrint( pHL2Player, HUD_PRINTTALK, szReturnString ); + Q_snprintf( szReturnString, sizeof( szReturnString ), "Please wait %d more seconds before trying to switch.\n", (int)(pFFPlayer->GetNextModelChangeTime() - gpGlobals->curtime) ); + ClientPrint( pFFPlayer, HUD_PRINTTALK, szReturnString ); return; } if (FFRules()->IsTeamplay() == false ) { - pHL2Player->SetPlayerModel(); + pFFPlayer->SetPlayerModel(); - const char *pszCurrentModelName = modelinfo->GetModelName( pHL2Player->GetModel() ); + const char *pszCurrentModelName = modelinfo->GetModelName( pFFPlayer->GetModel() ); char szReturnString[128]; Q_snprintf( szReturnString, sizeof( szReturnString ), "Your player model is: %s\n", pszCurrentModelName ); - ClientPrint( pHL2Player, HUD_PRINTTALK, szReturnString ); + ClientPrint( pFFPlayer, HUD_PRINTTALK, szReturnString ); } else { if ( Q_stristr( szModelName, "models/human") ) { - pHL2Player->ChangeTeam( TEAM_REBELS ); + pFFPlayer->ChangeTeam( TEAM_REBELS ); } else { - pHL2Player->ChangeTeam( TEAM_COMBINE ); + pFFPlayer->ChangeTeam( TEAM_COMBINE ); } } } if ( sv_report_client_settings.GetInt() == 1 ) { - UTIL_LogPrintf( "\"%s\" cl_cmdrate = \"%s\"\n", pHL2Player->GetPlayerName(), engine->GetClientConVarValue( pHL2Player->entindex(), "cl_cmdrate" )); + UTIL_LogPrintf( "\"%s\" cl_cmdrate = \"%s\"\n", pFFPlayer->GetPlayerName(), engine->GetClientConVarValue( pFFPlayer->entindex(), "cl_cmdrate" )); } BaseClass::ClientSettingsChanged( pPlayer ); @@ -899,7 +899,7 @@ bool CFF_SH_Rules::ClientCommand( CBaseEntity *pEdict, const CCommand &args ) return true; - CHL2MP_Player *pPlayer = (CHL2MP_Player *) pEdict; + CFF_SH_Player *pPlayer = (CFF_SH_Player *) pEdict; if ( pPlayer->ClientCommand( args ) ) return true; @@ -1018,7 +1018,7 @@ void CFF_SH_Rules::RestartGame() // now respawn all players for (int i = 1; i <= gpGlobals->maxClients; i++ ) { - CHL2MP_Player *pPlayer = (CHL2MP_Player*) UTIL_PlayerByIndex( i ); + CFF_SH_Player *pPlayer = (CFF_SH_Player*) UTIL_PlayerByIndex( i ); if ( !pPlayer ) continue; @@ -1160,7 +1160,7 @@ void CFF_SH_Rules::CleanUpMap() MapEntity_ParseAllEntities( engine->GetMapEntitiesString(), &filter, true ); } -void CFF_SH_Rules::CheckChatForReadySignal( CHL2MP_Player *pPlayer, const char *chatmsg ) +void CFF_SH_Rules::CheckChatForReadySignal( CFF_SH_Player *pPlayer, const char *chatmsg ) { if( m_bAwaitingReadyRestart && FStrEq( chatmsg, mp_ready_signal.GetString() ) ) { @@ -1223,7 +1223,7 @@ void CFF_SH_Rules::CheckAllPlayersReady( void ) { for (int i = 1; i <= gpGlobals->maxClients; i++ ) { - CHL2MP_Player *pPlayer = (CHL2MP_Player*) UTIL_PlayerByIndex( i ); + CFF_SH_Player *pPlayer = (CFF_SH_Player*) UTIL_PlayerByIndex( i ); if ( !pPlayer ) continue; diff --git a/mp/src/game/shared/ff/ff_sh_gamerules.h b/mp/src/game/shared/ff/ff_sh_gamerules.h index b3f00fc2..0d525503 100644 --- a/mp/src/game/shared/ff/ff_sh_gamerules.h +++ b/mp/src/game/shared/ff/ff_sh_gamerules.h @@ -20,7 +20,7 @@ #include "gamevars_shared.h" #ifndef CLIENT_DLL -#include "hl2mp_player.h" +#include "ff_sv_player.h" #endif #define VEC_CROUCH_TRACE_MIN FFRules()->GetFFViewVectors()->m_vCrouchTraceMin @@ -134,7 +134,7 @@ public: void AddLevelDesignerPlacedObject( CBaseEntity *pEntity ); void RemoveLevelDesignerPlacedObject( CBaseEntity *pEntity ); void ManageObjectRelocation( void ); - void CheckChatForReadySignal( CHL2MP_Player *pPlayer, const char *chatmsg ); + void CheckChatForReadySignal( CFF_SH_Player *pPlayer, const char *chatmsg ); const char *GetChatFormat( bool bTeamOnly, CBasePlayer *pPlayer ); #endif diff --git a/mp/src/game/shared/ff/ff_sh_player.cpp b/mp/src/game/shared/ff/ff_sh_player.cpp new file mode 100644 index 00000000..fc2925ab --- /dev/null +++ b/mp/src/game/shared/ff/ff_sh_player.cpp @@ -0,0 +1,577 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#include "cbase.h" + +#ifdef CLIENT_DLL +#include "ff_cl_player.h" +#include "prediction.h" +#define CRecipientFilter C_RecipientFilter +#else +#include "ff_sv_player.h" +#endif + +#include "engine/IEngineSound.h" +#include "SoundEmitterSystem/isoundemittersystembase.h" + +extern ConVar sv_footsteps; + +const char *g_ppszPlayerSoundPrefixNames[PLAYER_SOUNDS_MAX] = +{ + "NPC_Citizen", + "NPC_CombineS", + "NPC_MetroPolice", +}; + +const char *CFF_SH_Player::GetPlayerModelSoundPrefix( void ) +{ + return g_ppszPlayerSoundPrefixNames[m_iPlayerSoundType]; +} + +void CFF_SH_Player::PrecacheFootStepSounds( void ) +{ + int iFootstepSounds = ARRAYSIZE( g_ppszPlayerSoundPrefixNames ); + int i; + + for ( i = 0; i < iFootstepSounds; ++i ) + { + char szFootStepName[128]; + + Q_snprintf( szFootStepName, sizeof( szFootStepName ), "%s.RunFootstepLeft", g_ppszPlayerSoundPrefixNames[i] ); + PrecacheScriptSound( szFootStepName ); + + Q_snprintf( szFootStepName, sizeof( szFootStepName ), "%s.RunFootstepRight", g_ppszPlayerSoundPrefixNames[i] ); + PrecacheScriptSound( szFootStepName ); + } +} + +//----------------------------------------------------------------------------- +// Consider the weapon's built-in accuracy, this character's proficiency with +// the weapon, and the status of the target. Use this information to determine +// how accurately to shoot at the target. +//----------------------------------------------------------------------------- +Vector CFF_SH_Player::GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget ) +{ + if ( pWeapon ) + return pWeapon->GetBulletSpread( WEAPON_PROFICIENCY_PERFECT ); + + return VECTOR_CONE_15DEGREES; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : step - +// fvol - +// force - force sound to play +//----------------------------------------------------------------------------- +void CFF_SH_Player::PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool force ) +{ + if ( gpGlobals->maxClients > 1 && !sv_footsteps.GetFloat() ) + return; + +#if defined( CLIENT_DLL ) + // during prediction play footstep sounds only once + if ( !prediction->IsFirstTimePredicted() ) + return; +#endif + + if ( GetFlags() & FL_DUCKING ) + return; + + m_Local.m_nStepside = !m_Local.m_nStepside; + + char szStepSound[128]; + + if ( m_Local.m_nStepside ) + { + Q_snprintf( szStepSound, sizeof( szStepSound ), "%s.RunFootstepLeft", g_ppszPlayerSoundPrefixNames[m_iPlayerSoundType] ); + } + else + { + Q_snprintf( szStepSound, sizeof( szStepSound ), "%s.RunFootstepRight", g_ppszPlayerSoundPrefixNames[m_iPlayerSoundType] ); + } + + CSoundParameters params; + if ( GetParametersForSound( szStepSound, params, NULL ) == false ) + return; + + CRecipientFilter filter; + filter.AddRecipientsByPAS( vecOrigin ); + +#ifndef CLIENT_DLL + // im MP, server removed all players in origins PVS, these players + // generate the footsteps clientside + if ( gpGlobals->maxClients > 1 ) + filter.RemoveRecipientsByPVS( vecOrigin ); +#endif + + EmitSound_t ep; + ep.m_nChannel = CHAN_BODY; + ep.m_pSoundName = params.soundname; + ep.m_flVolume = fvol; + ep.m_SoundLevel = params.soundlevel; + ep.m_nFlags = 0; + ep.m_nPitch = params.pitch; + ep.m_pOrigin = &vecOrigin; + + EmitSound( filter, entindex(), ep ); +} + + +//========================== +// ANIMATION CODE +//========================== + + +// 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; + +CPlayerAnimState::CPlayerAnimState( CFF_SH_Player *outer ) + : m_pOuter( outer ) +{ + m_flGaitYaw = 0.0f; + m_flGoalFeetYaw = 0.0f; + m_flCurrentFeetYaw = 0.0f; + m_flCurrentTorsoYaw = 0.0f; + m_flLastYaw = 0.0f; + m_flLastTurnTime = 0.0f; + m_flTurnCorrectionTime = 0.0f; +}; + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPlayerAnimState::Update() +{ + m_angRender = GetOuter()->GetLocalAngles(); + m_angRender[ PITCH ] = m_angRender[ ROLL ] = 0.0f; + + ComputePoseParam_BodyYaw(); + ComputePoseParam_BodyPitch(GetOuter()->GetModelPtr()); + ComputePoseParam_BodyLookYaw(); + + ComputePlaybackRate(); + +#ifdef CLIENT_DLL + GetOuter()->UpdateLookAt(); +#endif + +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPlayerAnimState::ComputePlaybackRate() +{ + // Determine ideal playback rate + Vector vel; + GetOuterAbsVelocity( vel ); + + float speed = vel.Length2D(); + + bool isMoving = ( speed > 0.5f ) ? true : false; + + float maxspeed = GetOuter()->GetSequenceGroundSpeed( GetOuter()->GetSequence() ); + + if ( isMoving && ( maxspeed > 0.0f ) ) + { + float flFactor = 1.0f; + + // Note this gets set back to 1.0 if sequence changes due to ResetSequenceInfo below + GetOuter()->SetPlaybackRate( ( speed * flFactor ) / maxspeed ); + + // BUG BUG: + // This stuff really should be m_flPlaybackRate = speed / m_flGroundSpeed + } + else + { + GetOuter()->SetPlaybackRate( 1.0f ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : CBasePlayer +//----------------------------------------------------------------------------- +CFF_SH_Player *CPlayerAnimState::GetOuter() +{ + return m_pOuter; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : dt - +//----------------------------------------------------------------------------- +void CPlayerAnimState::EstimateYaw( void ) +{ + float dt = gpGlobals->frametime; + + if ( !dt ) + { + return; + } + + Vector est_velocity; + QAngle angles; + + GetOuterAbsVelocity( est_velocity ); + + angles = GetOuter()->GetLocalAngles(); + + if ( est_velocity[1] == 0 && est_velocity[0] == 0 ) + { + float flYawDiff = angles[YAW] - m_flGaitYaw; + flYawDiff = flYawDiff - (int)(flYawDiff / 360) * 360; + if (flYawDiff > 180) + flYawDiff -= 360; + if (flYawDiff < -180) + flYawDiff += 360; + + if (dt < 0.25) + flYawDiff *= dt * 4; + else + flYawDiff *= dt; + + m_flGaitYaw += flYawDiff; + m_flGaitYaw = m_flGaitYaw - (int)(m_flGaitYaw / 360) * 360; + } + else + { + m_flGaitYaw = (atan2(est_velocity[1], est_velocity[0]) * 180 / M_PI); + + if (m_flGaitYaw > 180) + m_flGaitYaw = 180; + else if (m_flGaitYaw < -180) + m_flGaitYaw = -180; + } +} + +//----------------------------------------------------------------------------- +// Purpose: Override for backpeddling +// Input : dt - +//----------------------------------------------------------------------------- +void CPlayerAnimState::ComputePoseParam_BodyYaw( void ) +{ + int iYaw = GetOuter()->LookupPoseParameter( "move_yaw" ); + if ( iYaw < 0 ) + return; + + // view direction relative to movement + float flYaw; + + EstimateYaw(); + + QAngle angles = GetOuter()->GetLocalAngles(); + float ang = angles[ YAW ]; + if ( ang > 180.0f ) + { + ang -= 360.0f; + } + else if ( ang < -180.0f ) + { + ang += 360.0f; + } + + // calc side to side turning + flYaw = ang - m_flGaitYaw; + // Invert for mapping into 8way blend + flYaw = -flYaw; + flYaw = flYaw - (int)(flYaw / 360) * 360; + + if (flYaw < -180) + { + flYaw = flYaw + 360; + } + else if (flYaw > 180) + { + flYaw = flYaw - 360; + } + + GetOuter()->SetPoseParameter( iYaw, flYaw ); + +#ifndef CLIENT_DLL + //Adrian: Make the model's angle match the legs so the hitboxes match on both sides. + GetOuter()->SetLocalAngles( QAngle( GetOuter()->GetAnimEyeAngles().x, m_flCurrentFeetYaw, 0 ) ); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPlayerAnimState::ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr ) +{ + // Get pitch from v_angle + float flPitch = GetOuter()->GetLocalAngles()[ PITCH ]; + + if ( flPitch > 180.0f ) + { + flPitch -= 360.0f; + } + flPitch = clamp( flPitch, -90, 90 ); + + QAngle absangles = GetOuter()->GetAbsAngles(); + absangles.x = 0.0f; + m_angRender = absangles; + m_angRender[ PITCH ] = m_angRender[ ROLL ] = 0.0f; + + // See if we have a blender for pitch + GetOuter()->SetPoseParameter( pStudioHdr, "aim_pitch", flPitch ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : goal - +// maxrate - +// dt - +// current - +// Output : int +//----------------------------------------------------------------------------- +int CPlayerAnimState::ConvergeAngles( float goal,float maxrate, float dt, float& current ) +{ + int direction = TURN_NONE; + + float anglediff = goal - current; + float anglediffabs = fabs( anglediff ); + + anglediff = AngleNormalize( anglediff ); + + float scale = 1.0f; + if ( anglediffabs <= FADE_TURN_DEGREES ) + { + scale = anglediffabs / FADE_TURN_DEGREES; + // Always do at least a bit of the turn ( 1% ) + scale = clamp( scale, 0.01f, 1.0f ); + } + + float maxmove = maxrate * dt * scale; + + if ( fabs( anglediff ) < maxmove ) + { + current = goal; + } + else + { + if ( anglediff > 0 ) + { + current += maxmove; + direction = TURN_LEFT; + } + else + { + current -= maxmove; + direction = TURN_RIGHT; + } + } + + current = AngleNormalize( current ); + + return direction; +} + +void CPlayerAnimState::ComputePoseParam_BodyLookYaw( void ) +{ + QAngle absangles = GetOuter()->GetAbsAngles(); + absangles.y = AngleNormalize( absangles.y ); + m_angRender = absangles; + m_angRender[ PITCH ] = m_angRender[ ROLL ] = 0.0f; + + // 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()->GetAnimEyeAngles().y; + // Snap feet to be perfectly aligned with torso/eyes + m_flGoalFeetYaw = GetOuter()->GetAnimEyeAngles().y; + m_flCurrentFeetYaw = m_flGoalFeetYaw; + m_nTurningInPlace = TURN_NONE; + } + + // If rotating in place, update stasis timer + if ( m_flLastYaw != GetOuter()->GetAnimEyeAngles().y ) + { + m_flLastTurnTime = gpGlobals->curtime; + m_flLastYaw = GetOuter()->GetAnimEyeAngles().y; + } + + if ( m_flGoalFeetYaw != m_flCurrentFeetYaw ) + { + m_flLastTurnTime = gpGlobals->curtime; + } + + turning = ConvergeAngles( m_flGoalFeetYaw, turnrate, gpGlobals->frametime, m_flCurrentFeetYaw ); + + QAngle eyeAngles = GetOuter()->GetAnimEyeAngles(); + QAngle vAngle = GetOuter()->GetLocalAngles(); + + // See how far off current feetyaw is from true yaw + float yawdelta = GetOuter()->GetAnimEyeAngles().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()->GetAnimEyeAngles().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()->GetAnimEyeAngles().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()->GetAnimEyeAngles().y; + flGoalTorsoYaw = 0.0f; + m_flCurrentTorsoYaw = GetOuter()->GetAnimEyeAngles().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; + } + } + + // Rotate entire body into position + absangles = GetOuter()->GetAbsAngles(); + absangles.y = m_flCurrentFeetYaw; + m_angRender = absangles; + m_angRender[ PITCH ] = m_angRender[ ROLL ] = 0.0f; + + 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: +// Input : activity - +// Output : Activity +//----------------------------------------------------------------------------- +Activity CPlayerAnimState::BodyYawTranslateActivity( Activity activity ) +{ + // Not even standing still, sigh + if ( activity != ACT_IDLE ) + return activity; + + // Not turning + switch ( m_nTurningInPlace ) + { + default: + case TURN_NONE: + return activity; + /* + case TURN_RIGHT: + return ACT_TURNRIGHT45; + case TURN_LEFT: + return ACT_TURNLEFT45; + */ + case TURN_RIGHT: + case TURN_LEFT: + return mp_ik.GetBool() ? ACT_TURN : activity; + } + + Assert( 0 ); + return activity; +} + +const QAngle& CPlayerAnimState::GetRenderAngles() +{ + return m_angRender; +} + + +void CPlayerAnimState::GetOuterAbsVelocity( Vector& vel ) +{ +#if defined( CLIENT_DLL ) + GetOuter()->EstimateAbsVelocity( vel ); +#else + vel = GetOuter()->GetAbsVelocity(); +#endif +} \ No newline at end of file diff --git a/mp/src/game/shared/ff/ff_sh_player.h b/mp/src/game/shared/ff/ff_sh_player.h new file mode 100644 index 00000000..cb512fbf --- /dev/null +++ b/mp/src/game/shared/ff/ff_sh_player.h @@ -0,0 +1,99 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#ifndef FF_SH_PLAYER_H +#define FF_SH_PLAYER_H +#pragma once + +#define FF_PUSHAWAY_THINK_INTERVAL (1.0f / 20.0f) +#include "studio.h" + + +enum +{ + PLAYER_SOUNDS_CITIZEN = 0, + PLAYER_SOUNDS_COMBINESOLDIER, + PLAYER_SOUNDS_METROPOLICE, + PLAYER_SOUNDS_MAX, +}; + +enum FFPlayerState +{ + // Happily running around in the game. + STATE_ACTIVE=0, + STATE_OBSERVER_MODE, // Noclipping around, watching players, etc. + NUM_PLAYER_STATES +}; + + +#if defined( CLIENT_DLL ) + #define CFF_SH_Player CFF_CL_Player +#else + #define CFF_SH_Player CFF_SV_Player +#endif + +class CPlayerAnimState +{ +public: + enum + { + TURN_NONE = 0, + TURN_LEFT, + TURN_RIGHT + }; + + CPlayerAnimState( CFF_SH_Player *outer ); + + Activity BodyYawTranslateActivity( Activity activity ); + + void Update(); + + const QAngle& GetRenderAngles(); + + void GetPoseParameters( CStudioHdr *pStudioHdr, float poseParameter[MAXSTUDIOPOSEPARAM] ); + + CFF_SH_Player *GetOuter(); + +private: + void GetOuterAbsVelocity( Vector& vel ); + + int ConvergeAngles( float goal,float maxrate, float dt, float& current ); + + void EstimateYaw( void ); + void ComputePoseParam_BodyYaw( void ); + void ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr ); + void ComputePoseParam_BodyLookYaw( void ); + + void ComputePlaybackRate(); + + CFF_SH_Player *m_pOuter; + + float m_flGaitYaw; + float m_flStoredCycle; + + // The following variables are used for tweaking the yaw of the upper body when standing still and + // making sure that it smoothly blends in and out once the player starts moving + // Direction feet were facing when we stopped moving + float m_flGoalFeetYaw; + float m_flCurrentFeetYaw; + + float m_flCurrentTorsoYaw; + + // To check if they are rotating in place + float m_flLastYaw; + // Time when we stopped moving + float m_flLastTurnTime; + + // One of the above enums + int m_nTurningInPlace; + + QAngle m_angRender; + + float m_flTurnCorrectionTime; +}; + +#endif //FF_SH_PLAYER_H diff --git a/mp/src/game/shared/ff/ff_shared.vpc b/mp/src/game/shared/ff/ff_shared.vpc index 9275376a..558db65a 100644 --- a/mp/src/game/shared/ff/ff_shared.vpc +++ b/mp/src/game/shared/ff/ff_shared.vpc @@ -17,9 +17,16 @@ $Project $File "$SRCDIR\game\shared\ff\ff_sh_gamemovement.cpp" $File "$SRCDIR\game\shared\ff\ff_sh_gamemovement.h" } - - $File "$SRCDIR\game\shared\ff\ff_sh_gamerules.cpp" - $File "$SRCDIR\game\shared\ff\ff_sh_gamerules.h" + $Folder "Player" + { + $File "$SRCDIR\game\shared\ff\ff_sh_player.cpp" + $File "$SRCDIR\game\shared\ff\ff_sh_player.h" + } + $Folder "Game" + { + $File "$SRCDIR\game\shared\ff\ff_sh_gamerules.cpp" + $File "$SRCDIR\game\shared\ff\ff_sh_gamerules.h" + } } diff --git a/mp/src/game/shared/hl2mp/weapon_357.cpp b/mp/src/game/shared/hl2mp/weapon_357.cpp index f5d444d5..5ee1db36 100644 --- a/mp/src/game/shared/hl2mp/weapon_357.cpp +++ b/mp/src/game/shared/hl2mp/weapon_357.cpp @@ -10,9 +10,9 @@ #include "in_buttons.h" #ifdef CLIENT_DLL - #include "c_hl2mp_player.h" + #include "ff_cl_player.h" #else - #include "hl2mp_player.h" + #include "ff_sv_player.h" #endif #include "weapon_hl2mpbasehlmpcombatweapon.h" diff --git a/mp/src/game/shared/hl2mp/weapon_ar2.cpp b/mp/src/game/shared/hl2mp/weapon_ar2.cpp index 90ed6a5b..df8021cd 100644 --- a/mp/src/game/shared/hl2mp/weapon_ar2.cpp +++ b/mp/src/game/shared/hl2mp/weapon_ar2.cpp @@ -9,10 +9,10 @@ #include "npcevent.h" #ifdef CLIENT_DLL - #include "c_hl2mp_player.h" + #include "ff_cl_player.h" #include "c_te_effect_dispatch.h" #else - #include "hl2mp_player.h" + #include "ff_sv_player.h" #include "te_effect_dispatch.h" #include "prop_combine_ball.h" #endif diff --git a/mp/src/game/shared/hl2mp/weapon_crossbow.cpp b/mp/src/game/shared/hl2mp/weapon_crossbow.cpp index a22b0529..a4874e6b 100644 --- a/mp/src/game/shared/hl2mp/weapon_crossbow.cpp +++ b/mp/src/game/shared/hl2mp/weapon_crossbow.cpp @@ -9,10 +9,10 @@ #include "in_buttons.h" #ifdef CLIENT_DLL - #include "c_hl2mp_player.h" + #include "ff_cl_player.h" #include "c_te_effect_dispatch.h" #else - #include "hl2mp_player.h" + #include "ff_sv_player.h" #include "te_effect_dispatch.h" #include "IEffects.h" #include "Sprite.h" diff --git a/mp/src/game/shared/hl2mp/weapon_crowbar.cpp b/mp/src/game/shared/hl2mp/weapon_crowbar.cpp index 800e1036..0ebc3524 100644 --- a/mp/src/game/shared/hl2mp/weapon_crowbar.cpp +++ b/mp/src/game/shared/hl2mp/weapon_crowbar.cpp @@ -16,9 +16,9 @@ #include "npcevent.h" #if defined( CLIENT_DLL ) - #include "c_hl2mp_player.h" + #include "ff_cl_player.h" #else - #include "hl2mp_player.h" + #include "ff_sv_player.h" #include "ai_basenpc.h" #endif diff --git a/mp/src/game/shared/hl2mp/weapon_frag.cpp b/mp/src/game/shared/hl2mp/weapon_frag.cpp index 9319b869..04ea9692 100644 --- a/mp/src/game/shared/hl2mp/weapon_frag.cpp +++ b/mp/src/game/shared/hl2mp/weapon_frag.cpp @@ -9,10 +9,10 @@ #include "in_buttons.h" #ifdef CLIENT_DLL - #include "c_hl2mp_player.h" + #include "ff_cl_player.h" #include "c_te_effect_dispatch.h" #else - #include "hl2mp_player.h" + #include "ff_sv_player.h" #include "te_effect_dispatch.h" #include "grenade_frag.h" #endif @@ -405,7 +405,7 @@ void CWeaponFrag::CheckThrowPosition( CBasePlayer *pPlayer, const Vector &vecEye } } -void DropPrimedFragGrenade( CHL2MP_Player *pPlayer, CBaseCombatWeapon *pGrenade ) +void DropPrimedFragGrenade( CFF_SH_Player *pPlayer, CBaseCombatWeapon *pGrenade ) { CWeaponFrag *pWeaponFrag = dynamic_cast( pGrenade ); diff --git a/mp/src/game/shared/hl2mp/weapon_hl2mpbase.cpp b/mp/src/game/shared/hl2mp/weapon_hl2mpbase.cpp index 18f8a1a3..b7dab9a9 100644 --- a/mp/src/game/shared/hl2mp/weapon_hl2mpbase.cpp +++ b/mp/src/game/shared/hl2mp/weapon_hl2mpbase.cpp @@ -23,12 +23,12 @@ extern IVModelInfo* modelinfo; #include "vgui/ISurface.h" #include "vgui_controls/Controls.h" - #include "c_hl2mp_player.h" + #include "ff_cl_player.h" #include "hud_crosshair.h" #else - #include "hl2mp_player.h" + #include "ff_sv_player.h" #include "vphysics/constraints.h" #endif @@ -131,9 +131,9 @@ CBasePlayer* CWeaponHL2MPBase::GetPlayerOwner() const return dynamic_cast< CBasePlayer* >( GetOwner() ); } -CHL2MP_Player* CWeaponHL2MPBase::GetHL2MPPlayerOwner() const +CFF_SH_Player* CWeaponHL2MPBase::GetFFPlayerOwner() const { - return dynamic_cast< CHL2MP_Player* >( GetOwner() ); + return dynamic_cast< CFF_SH_Player* >( GetOwner() ); } #ifdef CLIENT_DLL diff --git a/mp/src/game/shared/hl2mp/weapon_hl2mpbase.h b/mp/src/game/shared/hl2mp/weapon_hl2mpbase.h index ea909a07..67e510b0 100644 --- a/mp/src/game/shared/hl2mp/weapon_hl2mpbase.h +++ b/mp/src/game/shared/hl2mp/weapon_hl2mpbase.h @@ -10,7 +10,7 @@ #pragma once #endif -#include "hl2mp_player_shared.h" +#include "ff_sh_player.h" #include "basecombatweapon_shared.h" #include "hl2mp_weapon_parse.h" @@ -19,7 +19,7 @@ void UTIL_ClipPunchAngleOffset( QAngle &in, const QAngle &punch, const QAngle &clip ); #endif -class CHL2MP_Player; +class CFF_SH_Player; // These are the names of the ammo types that go in the CAmmoDefs and that the // weapon script files reference. @@ -51,7 +51,7 @@ public: virtual bool IsPredicted() const; CBasePlayer* GetPlayerOwner() const; - CHL2MP_Player* GetHL2MPPlayerOwner() const; + CFF_SH_Player* GetFFPlayerOwner() const; void WeaponSound( WeaponSound_t sound_type, float soundtime = 0.0f ); diff --git a/mp/src/game/shared/hl2mp/weapon_hl2mpbase_machinegun.cpp b/mp/src/game/shared/hl2mp/weapon_hl2mpbase_machinegun.cpp index b6cedc1f..0fbc37d5 100644 --- a/mp/src/game/shared/hl2mp/weapon_hl2mpbase_machinegun.cpp +++ b/mp/src/game/shared/hl2mp/weapon_hl2mpbase_machinegun.cpp @@ -7,9 +7,9 @@ #include "cbase.h" #if defined( CLIENT_DLL ) - #include "c_hl2mp_player.h" + #include "ff_cl_player.h" #else - #include "hl2mp_player.h" + #include "ff_sv_player.h" #endif #include "weapon_hl2mpbase_machinegun.h" @@ -91,14 +91,14 @@ void CHL2MPMachineGun::PrimaryAttack( void ) m_iClip1 -= iBulletsToFire; } - CHL2MP_Player *pHL2MPPlayer = ToHL2MPPlayer( pPlayer ); + CFF_SH_Player *pFFPlayer = ToFFPlayer( pPlayer ); // Fire the bullets FireBulletsInfo_t info; info.m_iShots = iBulletsToFire; - info.m_vecSrc = pHL2MPPlayer->Weapon_ShootPosition( ); + info.m_vecSrc = pFFPlayer->Weapon_ShootPosition( ); info.m_vecDirShooting = pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES ); - info.m_vecSpread = pHL2MPPlayer->GetAttackSpread( this ); + info.m_vecSpread = pFFPlayer->GetAttackSpread( this ); info.m_flDistance = MAX_TRACE_LENGTH; info.m_iAmmoType = m_iPrimaryAmmoType; info.m_iTracerFreq = 2; diff --git a/mp/src/game/shared/hl2mp/weapon_hl2mpbasebasebludgeon.cpp b/mp/src/game/shared/hl2mp/weapon_hl2mpbasebasebludgeon.cpp index e5306a63..5d496493 100644 --- a/mp/src/game/shared/hl2mp/weapon_hl2mpbasebasebludgeon.cpp +++ b/mp/src/game/shared/hl2mp/weapon_hl2mpbasebasebludgeon.cpp @@ -15,9 +15,9 @@ #include "animation.h" #if defined( CLIENT_DLL ) - #include "c_hl2mp_player.h" + #include "ff_cl_player.h" #else - #include "hl2mp_player.h" + #include "ff_sv_player.h" #include "ndebugoverlay.h" #include "te_effect_dispatch.h" #include "ilagcompensationmanager.h" @@ -103,7 +103,7 @@ void CBaseHL2MPBludgeonWeapon::PrimaryAttack() { #ifndef CLIENT_DLL - CHL2MP_Player *pPlayer = ToHL2MPPlayer( GetPlayerOwner() ); + CFF_SH_Player *pPlayer = ToFFPlayer( GetPlayerOwner() ); // Move other players back to history positions based on local player's lag lagcompensation->StartLagCompensation( pPlayer, pPlayer->GetCurrentCommand() ); #endif diff --git a/mp/src/game/shared/hl2mp/weapon_hl2mpbasehlmpcombatweapon.cpp b/mp/src/game/shared/hl2mp/weapon_hl2mpbasehlmpcombatweapon.cpp index 42a2e0e3..261ce82c 100644 --- a/mp/src/game/shared/hl2mp/weapon_hl2mpbasehlmpcombatweapon.cpp +++ b/mp/src/game/shared/hl2mp/weapon_hl2mpbasehlmpcombatweapon.cpp @@ -7,7 +7,7 @@ #include "cbase.h" #include "weapon_hl2mpbasehlmpcombatweapon.h" -#include "hl2mp_player_shared.h" +#include "ff_sh_player.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -115,7 +115,7 @@ bool CBaseHL2MPCombatWeapon::Deploy( void ) // We have to ask the player if the last time it checked, the weapon was lowered if ( GetOwner() && GetOwner()->IsPlayer() ) { - CHL2MP_Player *pPlayer = assert_cast( GetOwner() ); + CFF_SH_Player *pPlayer = assert_cast( GetOwner() ); if ( pPlayer->IsWeaponLowered() ) { if ( SelectWeightedSequence( ACT_VM_IDLE_LOWERED ) != ACTIVITY_NOT_AVAILABLE ) diff --git a/mp/src/game/shared/hl2mp/weapon_hl2mpbasehlmpcombatweapon.h b/mp/src/game/shared/hl2mp/weapon_hl2mpbasehlmpcombatweapon.h index 25ca520c..38334fe7 100644 --- a/mp/src/game/shared/hl2mp/weapon_hl2mpbasehlmpcombatweapon.h +++ b/mp/src/game/shared/hl2mp/weapon_hl2mpbasehlmpcombatweapon.h @@ -6,9 +6,9 @@ #endif #ifdef CLIENT_DLL - #include "c_hl2mp_player.h" + #include "ff_cl_player.h" #else - #include "hl2mp_player.h" + #include "ff_sv_player.h" #endif #include "weapon_hl2mpbase.h" diff --git a/mp/src/game/shared/hl2mp/weapon_physcannon.cpp b/mp/src/game/shared/hl2mp/weapon_physcannon.cpp index 97245b14..0ccb6c39 100644 --- a/mp/src/game/shared/hl2mp/weapon_physcannon.cpp +++ b/mp/src/game/shared/hl2mp/weapon_physcannon.cpp @@ -7,7 +7,7 @@ #include "cbase.h" #ifdef CLIENT_DLL - #include "c_hl2mp_player.h" + #include "ff_cl_player.h" #include "vcollide_parse.h" #include "engine/ivdebugoverlay.h" #include "iviewrender_beams.h" @@ -17,7 +17,7 @@ #include "clienteffectprecachesystem.h" #include "fx_interpvalue.h" #else - #include "hl2mp_player.h" + #include "ff_sv_player.h" #include "soundent.h" #include "ndebugoverlay.h" #include "ai_basenpc.h" @@ -760,7 +760,7 @@ void CPlayerPickupController::Init( CBasePlayer *pPlayer, CBaseEntity *pObject ) } - CHL2MP_Player *pOwner = (CHL2MP_Player *)ToBasePlayer( pPlayer ); + CFF_SH_Player *pOwner = (CFF_SH_Player *)ToBasePlayer( pPlayer ); if ( pOwner ) { pOwner->EnableSprint( false ); @@ -813,7 +813,7 @@ void CPlayerPickupController::Shutdown( bool bThrown ) if ( m_pPlayer ) { - CHL2MP_Player *pOwner = (CHL2MP_Player *)ToBasePlayer( m_pPlayer ); + CFF_SH_Player *pOwner = (CFF_SH_Player *)ToBasePlayer( m_pPlayer ); if ( pOwner ) { pOwner->EnableSprint( true ); @@ -2015,7 +2015,7 @@ bool CWeaponPhysCannon::AttachObject( CBaseEntity *pObject, const Vector &vPosit if ( !pPhysics ) return false; - CHL2MP_Player *pOwner = (CHL2MP_Player *)ToBasePlayer( GetOwner() ); + CFF_SH_Player *pOwner = (CFF_SH_Player *)ToBasePlayer( GetOwner() ); m_bActive = true; if( pOwner ) @@ -2375,7 +2375,7 @@ void CWeaponPhysCannon::DetachObject( bool playSound, bool wasLaunched ) if ( m_bActive == false ) return; - CHL2MP_Player *pOwner = (CHL2MP_Player *)ToBasePlayer( GetOwner() ); + CFF_SH_Player *pOwner = (CFF_SH_Player *)ToBasePlayer( GetOwner() ); if( pOwner != NULL ) { pOwner->EnableSprint( true ); diff --git a/mp/src/game/shared/hl2mp/weapon_pistol.cpp b/mp/src/game/shared/hl2mp/weapon_pistol.cpp index 83edb76b..576e17b3 100644 --- a/mp/src/game/shared/hl2mp/weapon_pistol.cpp +++ b/mp/src/game/shared/hl2mp/weapon_pistol.cpp @@ -9,9 +9,9 @@ #include "in_buttons.h" #ifdef CLIENT_DLL - #include "c_hl2mp_player.h" + #include "ff_cl_player.h" #else - #include "hl2mp_player.h" + #include "ff_sv_player.h" #endif #include "weapon_hl2mpbasehlmpcombatweapon.h" diff --git a/mp/src/game/shared/hl2mp/weapon_rpg.cpp b/mp/src/game/shared/hl2mp/weapon_rpg.cpp index 89af513d..73f170db 100644 --- a/mp/src/game/shared/hl2mp/weapon_rpg.cpp +++ b/mp/src/game/shared/hl2mp/weapon_rpg.cpp @@ -10,7 +10,7 @@ #include "weapon_rpg.h" #ifdef CLIENT_DLL - #include "c_hl2mp_player.h" + #include "ff_cl_player.h" #include "model_types.h" #include "beamdraw.h" #include "fx_line.h" @@ -2226,7 +2226,7 @@ int CLaserDot::DrawModel( int flags ) float scale; Vector endPos; - C_HL2MP_Player *pOwner = ToHL2MPPlayer( GetOwnerEntity() ); + CFF_CL_Player *pOwner = ToFFPlayer( GetOwnerEntity() ); if ( pOwner != NULL && pOwner->IsDormant() == false ) { diff --git a/mp/src/game/shared/hl2mp/weapon_shotgun.cpp b/mp/src/game/shared/hl2mp/weapon_shotgun.cpp index 504f267a..2b4dd4a9 100644 --- a/mp/src/game/shared/hl2mp/weapon_shotgun.cpp +++ b/mp/src/game/shared/hl2mp/weapon_shotgun.cpp @@ -9,9 +9,9 @@ #include "in_buttons.h" #ifdef CLIENT_DLL - #include "c_hl2mp_player.h" + #include "ff_cl_player.h" #else - #include "hl2mp_player.h" + #include "ff_sv_player.h" #endif #include "weapon_hl2mpbasehlmpcombatweapon.h" diff --git a/mp/src/game/shared/hl2mp/weapon_slam.cpp b/mp/src/game/shared/hl2mp/weapon_slam.cpp index 4e5bff29..7b684179 100644 --- a/mp/src/game/shared/hl2mp/weapon_slam.cpp +++ b/mp/src/game/shared/hl2mp/weapon_slam.cpp @@ -11,9 +11,9 @@ #include "engine/IEngineSound.h" #if defined( CLIENT_DLL ) - #include "c_hl2mp_player.h" + #include "ff_cl_player.h" #else - #include "hl2mp_player.h" + #include "ff_sv_player.h" #include "grenade_tripmine.h" #include "grenade_satchel.h" #include "entitylist.h" @@ -339,7 +339,7 @@ void CWeapon_SLAM::StartSatchelDetonate() //----------------------------------------------------------------------------- void CWeapon_SLAM::TripmineAttach( void ) { - CHL2MP_Player *pOwner = ToHL2MPPlayer( GetOwner() ); + CFF_SH_Player *pOwner = ToFFPlayer( GetOwner() ); if (!pOwner) { return; @@ -698,7 +698,7 @@ void CWeapon_SLAM::SLAMThink( void ) //----------------------------------------------------------------------------- bool CWeapon_SLAM::CanAttachSLAM( void ) { - CHL2MP_Player *pOwner = ToHL2MPPlayer( GetOwner() ); + CFF_SH_Player *pOwner = ToFFPlayer( GetOwner() ); if (!pOwner) { diff --git a/mp/src/game/shared/hl2mp/weapon_smg1.cpp b/mp/src/game/shared/hl2mp/weapon_smg1.cpp index bc1b3c66..83041444 100644 --- a/mp/src/game/shared/hl2mp/weapon_smg1.cpp +++ b/mp/src/game/shared/hl2mp/weapon_smg1.cpp @@ -9,10 +9,10 @@ #include "in_buttons.h" #ifdef CLIENT_DLL - #include "c_hl2mp_player.h" + #include "ff_cl_player.h" #else #include "grenade_ar2.h" - #include "hl2mp_player.h" + #include "ff_sv_player.h" #include "basegrenade_shared.h" #endif