diff --git a/src/game/server/hl2mp/hl2mp_player.cpp b/src/game/server/hl2mp/hl2mp_player.cpp index 9457928a0c5..784f1ef6b61 100644 --- a/src/game/server/hl2mp/hl2mp_player.cpp +++ b/src/game/server/hl2mp/hl2mp_player.cpp @@ -166,6 +166,12 @@ CHL2MP_Player::~CHL2MP_Player( void ) void CHL2MP_Player::UpdateOnRemove( void ) { + if ( auto p = GetLadderMove() ) + { + UTIL_Remove( ( CBaseEntity * ) ( p->m_hReservedSpot.Get() ) ); + p->m_hReservedSpot = NULL; + } + if ( m_hRagdoll ) { UTIL_RemoveImmediate( m_hRagdoll ); @@ -955,6 +961,22 @@ bool CHL2MP_Player::BumpWeapon( CBaseCombatWeapon *pWeapon ) return true; } +void CHL2MP_Player::LadderRespawnFix() +{ + if ( auto lm = GetLadderMove() ) + { + if ( lm->m_bForceLadderMove ) + { + lm->m_bForceLadderMove = false; + if ( lm->m_hReservedSpot ) + { + UTIL_Remove( ( CBaseEntity * ) lm->m_hReservedSpot.Get() ); + lm->m_hReservedSpot = NULL; + } + } + } +} + void CHL2MP_Player::ChangeTeam( int iTeam ) { /* if ( GetNextTeamChangeTime() >= gpGlobals->curtime ) @@ -966,6 +988,8 @@ void CHL2MP_Player::ChangeTeam( int iTeam ) return; }*/ + LadderRespawnFix(); + bool bKill = false; if ( HL2MPRules()->IsTeamplay() != true && iTeam != TEAM_SPECTATOR ) @@ -1298,6 +1322,8 @@ void CHL2MP_Player::DetonateTripmines( void ) void CHL2MP_Player::Event_Killed( const CTakeDamageInfo &info ) { + LadderRespawnFix(); + //update damage info with our accumulated physics force CTakeDamageInfo subinfo = info; subinfo.SetDamageForce( m_vecTotalBulletForce ); diff --git a/src/game/server/hl2mp/hl2mp_player.h b/src/game/server/hl2mp/hl2mp_player.h index 5fad238637f..2895c8db8b9 100644 --- a/src/game/server/hl2mp/hl2mp_player.h +++ b/src/game/server/hl2mp/hl2mp_player.h @@ -143,6 +143,8 @@ class CHL2MP_Player : public CHL2_Player bool IsThreatAimingTowardMe( CBaseEntity* threat, float cosTolerance = 0.8f ) const; bool IsThreatFiringAtMe( CBaseEntity* threat ) const; + + void LadderRespawnFix(); private: CNetworkQAngle( m_angEyeAngles ); diff --git a/src/game/server/player.h b/src/game/server/player.h index 902e0e627ca..6a0c4b6fcf4 100644 --- a/src/game/server/player.h +++ b/src/game/server/player.h @@ -823,6 +823,9 @@ class CBasePlayer : public CBaseCombatCharacter } } + float GetLadderCooldownTime() const { return m_flLadderCooldownTime; } + void SetLadderCooldownTime( float cooldownTime ) { m_flLadderCooldownTime = cooldownTime; } + private: // How much of a movement time buffer can we process from this user? int m_nMovementTicksForUserCmdProcessingRemaining; @@ -838,6 +841,7 @@ class CBasePlayer : public CBaseCombatCharacter int DetermineSimulationTicks( void ); void AdjustPlayerTimeBase( int simulation_ticks ); + float m_flLadderCooldownTime; public: diff --git a/src/game/shared/hl2/hl_gamemovement.cpp b/src/game/shared/hl2/hl_gamemovement.cpp index e54f63d060e..51dc5fec05c 100644 --- a/src/game/shared/hl2/hl_gamemovement.cpp +++ b/src/game/shared/hl2/hl_gamemovement.cpp @@ -468,8 +468,27 @@ bool CHL2GameMovement::ExitLadderViaDismountNode( CFuncLadder *ladder, bool stri continue; } + // Now perform a trace to ensure there is a clear line of sight + // between the player and the dismount node + trace_t losTrace; + Vector playerPos = mv->GetAbsOrigin() + player->GetViewOffset(); // Player's view position + + UTIL_TraceLine( playerPos, org, MASK_PLAYERSOLID, player, COLLISION_GROUP_PLAYER_MOVEMENT, &losTrace ); + + // Peter: If there's an obstruction (a wall or other object) + // between the player and the dismount node, skip it. + // There is an option in Hammer to prevent this, but + // level designer tend to forget to properly set this, so maps + // like dm_assault that have two ladders on either side means + // players can clip through walls and I fail to see + // why this should be a gameplay feature. + if ( losTrace.fraction != 1.0f ) + { + continue; + } + // Find the best dot product - Vector vecToSpot = org - ( mv->GetAbsOrigin() + player->GetViewOffset() ); + Vector vecToSpot = org - playerPos; vecToSpot.z = 0.0f; float d = VectorNormalize( vecToSpot ); @@ -964,6 +983,14 @@ bool CHL2GameMovement::LadderMove( void ) if ( !ladder ) { +#ifdef GAME_DLL + // Check if the player is still in the cooldown period after dismounting the ladder + if ( gpGlobals->curtime < GetHL2Player()->GetLadderCooldownTime() ) + { + // Player is still in cooldown, prevent mounting + return false; + } +#endif Findladder( 64.0f, &bestLadder, bestOrigin, NULL ); } @@ -1083,6 +1110,11 @@ bool CHL2GameMovement::LadderMove( void ) { mv->m_vecVelocity.z = mv->m_vecVelocity.z + 50; } + +#ifdef GAME_DLL + // Set cooldown time for remounting the ladder (0.5 seconds) - server-side only + GetHL2Player()->SetLadderCooldownTime( gpGlobals->curtime + 0.5f ); +#endif return false; } @@ -1188,9 +1220,7 @@ bool CHL2GameMovement::CanAccelerate() } #endif - BaseClass::CanAccelerate(); - - return true; + return BaseClass::CanAccelerate(); } @@ -1200,4 +1230,4 @@ bool CHL2GameMovement::CanAccelerate() IGameMovement *g_pGameMovement = ( IGameMovement * )&g_GameMovement; EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CGameMovement, IGameMovement,INTERFACENAME_GAMEMOVEMENT, g_GameMovement ); -#endif +#endif \ No newline at end of file diff --git a/src/game/shared/hl2mp/hl2mp_gamerules.cpp b/src/game/shared/hl2mp/hl2mp_gamerules.cpp index 87a3cf6e3b3..f9fb3d3edd4 100644 --- a/src/game/shared/hl2mp/hl2mp_gamerules.cpp +++ b/src/game/shared/hl2mp/hl2mp_gamerules.cpp @@ -1026,6 +1026,7 @@ void CHL2MPRules::RestartGame() pPlayer->GetActiveWeapon()->Holster(); } pPlayer->RemoveAllItems( true ); + pPlayer->LadderRespawnFix(); respawn( pPlayer, false ); pPlayer->Reset(); }