diff --git a/engine/debugoverlay.cpp b/engine/debugoverlay.cpp index cef04799ab..364496cfc2 100644 --- a/engine/debugoverlay.cpp +++ b/engine/debugoverlay.cpp @@ -912,8 +912,9 @@ void DrawOverlay( OverlayBase_t *pOverlay ) case OVERLAY_SWEPT_BOX: { - OverlaySweptBox_t *pBox = static_cast(pOverlay); - RenderWireframeSweptBox( pBox->start, pBox->end, pBox->angles, pBox->mins, pBox->maxs, Color( pBox->r, pBox->g, pBox->b, pBox->a ), true ); + OverlaySweptBox_t* pBox = static_cast(pOverlay); + RenderSweptBox( pBox->start, pBox->end, pBox->angles, pBox->mins, pBox->maxs, Color( pBox->r, pBox->g, pBox->b, pBox->a ), false ); + RenderWireframeSweptBox( pBox->start, pBox->end, pBox->angles, pBox->mins, pBox->maxs, Color( pBox->r, pBox->g, pBox->b, pBox->a ), false ); } break; diff --git a/game/client/c_baseanimating.cpp b/game/client/c_baseanimating.cpp index 3b8f76b14e..97634c31ae 100644 --- a/game/client/c_baseanimating.cpp +++ b/game/client/c_baseanimating.cpp @@ -9,6 +9,7 @@ #include "c_baseanimating.h" #include "c_sprite.h" #include "cdll_client_int.h" +#include "convar.h" #include "iconvar.h" #include "interpolatedvar.h" #include "model_types.h" @@ -200,9 +201,7 @@ IMPLEMENT_CLIENTCLASS_DT(C_BaseAnimating, DT_BaseAnimating, CBaseAnimating) RecvPropFloat( RECVINFO( m_fadeMinDist ) ), RecvPropFloat( RECVINFO( m_fadeMaxDist ) ), - RecvPropFloat( RECVINFO( m_flFadeScale ) ), - RecvPropArray3( RECVINFO_ARRAY(m_vecHitboxServerPositions), RecvPropVector(RECVINFO(m_vecHitboxServerPositions[0]))), - RecvPropArray3( RECVINFO_ARRAY(m_angHitboxServerAngles), RecvPropQAngles(RECVINFO(m_angHitboxServerAngles[0]))) + RecvPropFloat( RECVINFO( m_flFadeScale ) ) END_RECV_TABLE() @@ -4994,8 +4993,6 @@ void C_BaseAnimating::UpdateClientSideAnimation() } } -ConVar cl_showhitboxes("cl_showhitboxes", "0", FCVAR_CHEAT); - void C_BaseAnimating::Simulate() { if ( m_bInitModelEffects ) @@ -5574,25 +5571,40 @@ static Vector hullcolor[8] = Vector( 1.0, 1.0, 1.0 ) }; -void C_BaseAnimating::RecordClientHitboxes() +void C_BaseAnimating::DrawServerHitboxes( Vector position[MAXSTUDIOBONES], QAngle angles[MAXSTUDIOBONES], float duration /*= 0.0f*/, bool monocolor /*= false*/ ) { - CStudioHdr *pStudioHdr = GetModelPtr(); + CStudioHdr *pStudioHdr = GetModelPtr(); if ( !pStudioHdr ) return; - mstudiohitboxset_t *set =pStudioHdr->pHitboxSet( m_nHitboxSet ); + mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( m_nHitboxSet ); if ( !set ) return; + int r = 0; + int g = 0; + int b = 255; + for ( int i = 0; i < set->numhitboxes; i++ ) { mstudiobbox_t *pbox = set->pHitbox( i ); - GetBonePosition( pbox->bone, m_vecHitboxClientPositions[pbox->bone], m_angHitboxClientAngles[pbox->bone] ); + if ( !monocolor ) + { + int j = (pbox->group % 8); + r = ( int ) ( 255.0f * hullcolor[j][0] ); + g = ( int ) ( 255.0f * hullcolor[j][1] ); + b = ( int ) ( 255.0f * hullcolor[j][2] ); + } + + debugoverlay->AddBoxOverlay( position[pbox->bone], pbox->bbmin, pbox->bbmax, angles[pbox->bone], r, g, b, 127, duration ); } } -void C_BaseAnimating::DrawClientRecordedHitboxes( float duration /*= 0.0f*/, bool monocolor /*= false*/ ) +//----------------------------------------------------------------------------- +// Purpose: Draw the current hitboxes +//----------------------------------------------------------------------------- +void C_BaseAnimating::DrawClientHitboxes( float duration /*= 0.0f*/, bool monocolor /*= false*/ ) { CStudioHdr *pStudioHdr = GetModelPtr(); if ( !pStudioHdr ) @@ -5609,34 +5621,6 @@ void C_BaseAnimating::DrawClientRecordedHitboxes( float duration /*= 0.0f*/, boo int g = 255; int b = 0; - for ( int i = 0; i < set->numhitboxes; i++ ) - { - mstudiobbox_t *pbox = set->pHitbox( i ); - - debugoverlay->AddBoxOverlay( m_vecHitboxClientPositions[pbox->bone], pbox->bbmin, pbox->bbmax, m_angHitboxClientAngles[pbox->bone], r, g, b, 127 ,duration ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draw the current hitboxes -//----------------------------------------------------------------------------- -void C_BaseAnimating::DrawClientHitboxes( float duration /*= 0.0f*/, bool monocolor /*= false*/ ) -{ - CStudioHdr *pStudioHdr = GetModelPtr(); - if ( !pStudioHdr ) - return; - - mstudiohitboxset_t *set =pStudioHdr->pHitboxSet( m_nHitboxSet ); - if ( !set ) - return; - - Vector position; - QAngle angles; - - int r = 255; - int g = 0; - int b = 0; - for ( int i = 0; i < set->numhitboxes; i++ ) { mstudiobbox_t *pbox = set->pHitbox( i ); @@ -5655,43 +5639,6 @@ void C_BaseAnimating::DrawClientHitboxes( float duration /*= 0.0f*/, bool monoco } } -//----------------------------------------------------------------------------- -// Purpose: Draw the current hitboxes -//----------------------------------------------------------------------------- -void C_BaseAnimating::DrawServerHitboxes( float duration /*= 0.0f*/, bool monocolor /*= false*/ ) -{ - CStudioHdr *pStudioHdr = GetModelPtr(); - if ( !pStudioHdr ) - return; - - mstudiohitboxset_t *set =pStudioHdr->pHitboxSet( m_nHitboxSet ); - if ( !set ) - return; - - Vector position; - QAngle angles; - - int r = 0; - int g = 0; - int b = 255; - - for ( int i = 0; i < set->numhitboxes; i++ ) - { - mstudiobbox_t *pbox = set->pHitbox( i ); - - if ( !monocolor ) - { - int j = (pbox->group % 8); - r = ( int ) ( 255.0f * hullcolor[j][0] ); - g = ( int ) ( 255.0f * hullcolor[j][1] ); - b = ( int ) ( 255.0f * hullcolor[j][2] ); - } - - debugoverlay->AddBoxOverlay( m_vecHitboxServerPositions[i], pbox->bbmin, pbox->bbmax, m_angHitboxServerAngles[i], r, g, b, 127 ,duration ); - } -} - - //----------------------------------------------------------------------------- // Purpose: // Input : activity - diff --git a/game/client/c_baseanimating.h b/game/client/c_baseanimating.h index 2fd3465e97..0d9fb02190 100644 --- a/game/client/c_baseanimating.h +++ b/game/client/c_baseanimating.h @@ -369,10 +369,8 @@ public: int GetHitboxSet( void ); char const *GetHitboxSetName( void ); int GetHitboxSetCount( void ); - void RecordClientHitboxes(); + void DrawServerHitboxes( Vector position[MAXSTUDIOBONES], QAngle angles[MAXSTUDIOBONES], float duration = 0.0f, bool monocolor = false ); void DrawClientHitboxes( float duration = 0.0f, bool monocolor = false ); - void DrawClientRecordedHitboxes( float duration = 0.0f, bool monocolor = false ); - void DrawServerHitboxes( float duration = 0.0f, bool monocolor = false ); C_BaseAnimating* FindFollowedEntity(); @@ -642,12 +640,6 @@ private: mutable CStudioHdr *m_pStudioHdr; mutable MDLHandle_t m_hStudioHdr; CThreadFastMutex m_StudioHdrInitLock; - - public: - Vector m_vecHitboxServerPositions[MAXSTUDIOBONES]; - QAngle m_angHitboxServerAngles[MAXSTUDIOBONES]; - Vector m_vecHitboxClientPositions[MAXSTUDIOBONES]; - QAngle m_angHitboxClientAngles[MAXSTUDIOBONES]; }; enum diff --git a/game/client/c_baseplayer.cpp b/game/client/c_baseplayer.cpp index 32ddb896fd..0addb99d9e 100644 --- a/game/client/c_baseplayer.cpp +++ b/game/client/c_baseplayer.cpp @@ -252,11 +252,7 @@ END_RECV_TABLE() RecvPropFloat ( RECVINFO( m_flDeathTime )), RecvPropInt ( RECVINFO( m_nWaterLevel ) ), - RecvPropFloat ( RECVINFO( m_flLaggedMovementValue )), - RecvPropUtlVector ( RECVINFO_UTLVECTOR(m_vecBulletServerPositions), MAX_PLAYER_BULLET_SERVER_POSITIONS,RecvPropVector(NULL, 0) ), - RecvPropUtlVector ( RECVINFO_UTLVECTOR(m_vecServerShootPositions) ,MAX_PLAYER_BULLET_SERVER_POSITIONS, RecvPropVector(NULL, 0) ), - RecvPropBool (RECVINFO(m_bDebugServerBullets)), - RecvPropUtlVector ( RECVINFO_UTLVECTOR(m_touchedEntitiesWithBullet) ,MAX_PLAYER_BULLET_SERVER_POSITIONS, RecvPropVector(NULL, 0) ), + RecvPropFloat ( RECVINFO( m_flLaggedMovementValue )) END_RECV_TABLE() @@ -451,9 +447,6 @@ C_BasePlayer::C_BasePlayer() : m_iv_vecViewOffset( "C_BasePlayer::m_iv_vecViewOf m_nForceVisionFilterFlags = 0; ListenForGameEvent( "base_player_teleported" ); - - m_lastBulletDiameter = 1.0f; - m_bDebugServerBullets = false; } //----------------------------------------------------------------------------- @@ -2141,196 +2134,6 @@ void C_BasePlayer::Simulate() { ResetLatched(); } - - static ConVarRef cl_showfirebullethitboxes("cl_showfirebullethitboxes"); - static ConVarRef cl_showimpacts("cl_showimpacts"); - static ConVarRef cl_showhitboxes("cl_showhitboxes"); - static ConVarRef debug_screenshot_bullet_position("debug_screenshot_bullet_position"); - - static auto DrawBullet = [&](Vector src, Vector endpos, int r, int g, int b, int a, float duration) - { - NDebugOverlay::SweptBox(src, - endpos, - Vector(-m_lastBulletDiameter, -m_lastBulletDiameter, -m_lastBulletDiameter) / 2, - Vector(m_lastBulletDiameter, m_lastBulletDiameter, m_lastBulletDiameter) / 2, - QAngle(0, 0, 0), - r, - g, - b, - a, - duration); - NDebugOverlay::Box(endpos, - Vector(-m_lastBulletDiameter, -m_lastBulletDiameter, -m_lastBulletDiameter) / 2, - Vector(m_lastBulletDiameter, m_lastBulletDiameter, m_lastBulletDiameter) / 2, - r, - g, - b, - a, - duration); - }; - - // HACK: Server var is always more delayed than client, should be safe. - if (m_bDebugServerBullets && IsLocalPlayer()) - { - bool shouldDrawClientBullets = cl_showimpacts.GetInt() == 1 || cl_showimpacts.GetInt() == 3; - bool shouldDrawServerBullets = cl_showimpacts.GetInt() == 1 || cl_showimpacts.GetInt() == 2; - static constexpr float flShowDuration = 60.f; - - if (shouldDrawClientBullets) - { - for (int i = 0; i < m_vecClientShootPositions.Count(); i++) - { - DrawBullet(m_vecClientShootPositions[i], - m_vecBulletClientPositions[i], - 0, - 255, - 0, - 127, - flShowDuration); - } - } - - if (shouldDrawServerBullets) - { - for (int i = 0; i < m_vecServerShootPositions.Count(); i++) - { - DrawBullet(m_vecServerShootPositions[i], - m_vecBulletServerPositions[i], - 0, - 0, - 255, - 127, - flShowDuration); - } - } - - bool shouldDrawClientSS = debug_screenshot_bullet_position.GetInt() == 1 || debug_screenshot_bullet_position.GetInt() == 3; - bool shouldDrawServerSS = debug_screenshot_bullet_position.GetInt() == 1 || debug_screenshot_bullet_position.GetInt() == 2; - - if (shouldDrawClientSS) - { - for (int i = 0; i < m_vecClientShootPositions.Count(); i++) - { - DrawBullet(m_vecClientShootPositions[i], - m_vecBulletClientPositions[i], - 0, - 255, - 0, - 127, - gpGlobals->frametime); - } - } - - if (shouldDrawServerSS) - { - for (int i = 0; i < m_vecServerShootPositions.Count(); i++) - { - DrawBullet(m_vecServerShootPositions[i], - m_vecBulletServerPositions[i], - 0, - 0, - 255, - 127, - gpGlobals->frametime); - } - } - - bool shouldDrawClientBulletPlayerHitbox = cl_showfirebullethitboxes.GetInt() == 1 || cl_showfirebullethitboxes.GetInt() == 3; - bool shouldDrawServerBulletPlayerHitbox = cl_showfirebullethitboxes.GetInt() == 1 || cl_showfirebullethitboxes.GetInt() == 2; - - if (shouldDrawClientBulletPlayerHitbox || shouldDrawServerBulletPlayerHitbox) - { - for (int i = 1; i <= gpGlobals->maxClients; i++) - { - auto player = UTIL_PlayerByIndex(i); - - if (!player || player->IsLocalPlayer()) - { - continue; - } - - if (shouldDrawClientBulletPlayerHitbox) - { - player->DrawClientRecordedHitboxes(flShowDuration, true); - } - - if (shouldDrawServerBulletPlayerHitbox) - { - player->DrawServerHitboxes(flShowDuration, true); - } - } - } - else if (shouldDrawClientBullets || shouldDrawServerBullets) - { - for (auto&& entityIndex : m_touchedEntitiesWithBullet) - { - auto player = UTIL_PlayerByIndex(entityIndex); - - if (!player || player->IsLocalPlayer()) - { - continue; - } - - if (shouldDrawClientBullets) - { - player->DrawClientRecordedHitboxes(flShowDuration, true); - } - - if (shouldDrawServerBullets) - { - player->DrawServerHitboxes(flShowDuration, true); - } - } - } - - if (shouldDrawClientSS || shouldDrawServerSS) - { - for (auto&& entityIndex : m_touchedEntitiesWithBullet) - { - auto player = UTIL_PlayerByIndex(entityIndex); - - if (!player || player->IsLocalPlayer()) - { - continue; - } - - if (shouldDrawClientSS) - { - player->DrawClientRecordedHitboxes(gpGlobals->frametime, true); - } - - if (shouldDrawServerSS) - { - player->DrawServerHitboxes(gpGlobals->frametime, true); - } - } - } - - if (shouldDrawClientSS || shouldDrawServerSS) - { - gpGlobals->client_taking_screenshot = true; - } - - // Remove accumulated client bullets. - m_vecBulletClientPositions.RemoveAll(); - m_vecClientShootPositions.RemoveAll(); - m_bDebugServerBullets = false; - } - - bool shouldShowClientHitboxes = cl_showhitboxes.GetInt() == 1 || cl_showhitboxes.GetInt() == 3; - bool shouldShowServerHitboxes = cl_showhitboxes.GetInt() == 1 || cl_showhitboxes.GetInt() == 2; - bool shouldShowHitboxes = IsPlayer() && this != GetLocalPlayer(); - - if (shouldShowClientHitboxes && shouldShowHitboxes) - { - RecordClientHitboxes(); - DrawClientRecordedHitboxes(gpGlobals->frametime, true); - } - - if (shouldShowServerHitboxes && shouldShowHitboxes) - { - DrawServerHitboxes(gpGlobals->frametime, true); - } } //----------------------------------------------------------------------------- diff --git a/game/client/c_baseplayer.h b/game/client/c_baseplayer.h index 2aceac4f04..6a034009a2 100644 --- a/game/client/c_baseplayer.h +++ b/game/client/c_baseplayer.h @@ -639,14 +639,6 @@ public: bool ShouldGoSouth( Vector vNPCForward, Vector vNPCRight ); //Such a bad name. void SetOldPlayerZ( float flOld ) { m_flOldPlayerZ = flOld; } - - float m_lastBulletDiameter; - bool m_bDebugServerBullets; - CUtlVector m_vecBulletServerPositions; - CUtlVector m_vecServerShootPositions; - CUtlVector m_touchedEntitiesWithBullet; - CUtlVector m_vecBulletClientPositions; - CUtlVector m_vecClientShootPositions; }; EXTERN_RECV_TABLE(DT_BasePlayer); diff --git a/game/client/cstrike/c_cs_player.cpp b/game/client/cstrike/c_cs_player.cpp index e10916273f..b24c36f47c 100644 --- a/game/client/cstrike/c_cs_player.cpp +++ b/game/client/cstrike/c_cs_player.cpp @@ -4,15 +4,19 @@ // //=============================================================================// +#include "KeyValues.h" #include "cbase.h" #include "c_cs_player.h" #include "c_user_message_register.h" #include "cdll_client_int.h" +#include "convar.h" #include "dt_recv.h" #include "iconvar.h" #include "interpolatedvar.h" +#include "mathlib/vector.h" #include "shareddefs.h" #include "studio.h" +#include "util_shared.h" #include "view.h" #include "iclientvehicle.h" #include "ivieweffects.h" @@ -79,6 +83,9 @@ extern ConVar spec_freeze_distance_max; //============================================================================= // HPE_END //============================================================================= +ConVar cl_showhitboxes("cl_showhitboxes", "0", FCVAR_CHEAT); +ConVar cl_showimpacts("cl_showimpacts", "0"); +ConVar cl_showfirebullethitboxes("cl_showfirebullethitboxes", "0"); ConVar cl_left_hand_ik( "cl_left_hand_ik", "0", 0, "Attach player's left hand to rifle with IK." ); @@ -87,7 +94,6 @@ ConVar cl_ragdoll_physics_enable( "cl_ragdoll_physics_enable", "1", 0, "Enable/d ConVar cl_minmodels( "cl_minmodels", "0", 0, "Uses one player model for each team." ); ConVar cl_min_ct( "cl_min_ct", "1", 0, "Controls which CT model is used when cl_minmodels is set.", true, 1, true, 4 ); ConVar cl_min_t( "cl_min_t", "1", 0, "Controls which Terrorist model is used when cl_minmodels is set.", true, 1, true, 4 ); -const float CycleLatchTolerance = 0.15; // amount we can diverge from the server's cycle before we're corrected extern ConVar mp_playerid_delay; extern ConVar mp_playerid_hold; @@ -783,6 +789,26 @@ C_CSPlayer::C_CSPlayer() : view->SetScreenOverlayMaterial( NULL ); m_bPlayingFreezeCamSound = false; + + // HACK_ENHANCED: + static bool bDoOnce = false; + if (!bDoOnce) + { + static auto bullet_impact_kv = new KeyValues("bullet_impact"); + gameeventmanager->RegisterEvent(bullet_impact_kv); + static auto bullet_hit_player_kv = new KeyValues("bullet_hit_player"); + gameeventmanager->RegisterEvent(bullet_hit_player_kv); + static auto bullet_player_hitboxes_kv = new KeyValues("bullet_player_hitboxes"); + gameeventmanager->RegisterEvent(bullet_player_hitboxes_kv); + static auto player_lag_hitboxes_kv = new KeyValues("player_lag_hitboxes"); + gameeventmanager->RegisterEvent(player_lag_hitboxes_kv); + bDoOnce = true; + } + + ListenForGameEvent( "bullet_impact" ); + ListenForGameEvent( "bullet_hit_player" ); + ListenForGameEvent( "bullet_player_hitboxes" ); + ListenForGameEvent( "player_lag_hitboxes" ); } @@ -2129,6 +2155,100 @@ void C_CSPlayer::FireEvent( const Vector& origin, const QAngle& angles, int even BaseClass::FireEvent( origin, angles, event, options ); } +void C_CSPlayer::FireGameEvent(IGameEvent* event) +{ + static ConVarRef cl_showfirebullethitboxes("cl_showfirebullethitboxes"); + static ConVarRef cl_showimpacts("cl_showimpacts"); + static ConVarRef debug_screenshot_bullet_position("debug_screenshot_bullet_position"); + + BaseClass::FireGameEvent(event); + + bool shouldShowImpacts = cl_showimpacts.GetInt() == 1 || cl_showimpacts.GetInt() == 3; + bool shouldShowFireBulletHitboxes = cl_showfirebullethitboxes.GetInt() == 1 || cl_showfirebullethitboxes.GetInt() == 3; + bool shouldShowHitboxes = cl_showhitboxes.GetInt() == 1 || cl_showhitboxes.GetInt() == 3; + + const auto showEventHitboxes = [&](float flDuration) + { + const int index = event->GetInt("userid"); + if (index == GetUserID() && IsLocalPlayer()) + { + const auto playerIndex = event->GetInt("player_index"); + const auto player = UTIL_PlayerByIndex(playerIndex); + + if (player && !player->IsLocalPlayer()) + { + const auto numhitboxes = event->GetInt("num_hitboxes"); + QAngle angles[MAXSTUDIOBONES]; + Vector positions[MAXSTUDIOBONES]; + + for (int i = 0; i < numhitboxes; i++) + { + char buffer[256]; + V_sprintf_safe(buffer, "hitbox_index_%i", i); + const auto hitboxIndex = event->GetInt(buffer); + + V_sprintf_safe(buffer, "hitbox_position_x_%i", i); + positions[hitboxIndex].x = event->GetFloat(buffer); + V_sprintf_safe(buffer, "hitbox_position_y_%i", i); + positions[hitboxIndex].y = event->GetFloat(buffer); + V_sprintf_safe(buffer, "hitbox_position_z_%i", i); + positions[hitboxIndex].z = event->GetFloat(buffer); + + V_sprintf_safe(buffer, "hitbox_angle_x_%i", i); + angles[hitboxIndex].x = event->GetFloat(buffer); + V_sprintf_safe(buffer, "hitbox_angle_y_%i", i); + angles[hitboxIndex].y = event->GetFloat(buffer); + V_sprintf_safe(buffer, "hitbox_angle_z_%i", i); + angles[hitboxIndex].z = event->GetFloat(buffer); + + } + + player->DrawServerHitboxes(positions, angles, flDuration, true); + } + } + }; + + if ( FStrEq( event->GetName(), "bullet_impact" ) && shouldShowImpacts ) + { + const int index = event->GetInt( "userid" ); + if ( index == GetUserID() && IsLocalPlayer() ) + { + Vector src(event->GetFloat("src_x"), event->GetFloat("src_y"), event->GetFloat("src_z")); + Vector dst(event->GetFloat("dst_x"), event->GetFloat("dst_y"), event->GetFloat("dst_z")); + float flBulletRadius = event->GetFloat("radius"); + + Vector mins(-flBulletRadius); + Vector maxs(flBulletRadius); + + DrawBullet(src, dst, mins, maxs, 0, 0, 255, 127, m_flDebugDuration); + + // If both happens to be on the same frame, let it be. + if (debug_screenshot_bullet_position.GetBool()) + { + gpGlobals->client_taking_screenshot = true; + } + } + } + else if (FStrEq(event->GetName(), "bullet_hit_player") && shouldShowImpacts) + { + showEventHitboxes(m_flDebugDuration); + + // If both happens to be on the same frame, let it be. + if (debug_screenshot_bullet_position.GetBool()) + { + gpGlobals->client_taking_screenshot = true; + } + } + else if (FStrEq(event->GetName(), "bullet_player_hitboxes") && shouldShowFireBulletHitboxes) + { + showEventHitboxes(m_flDebugDuration); + } + else if (FStrEq(event->GetName(), "player_lag_hitboxes") && shouldShowHitboxes) + { + showEventHitboxes(-1.0f); + } +} + void C_CSPlayer::SetActivity( Activity eActivity ) { @@ -2231,6 +2351,11 @@ void C_CSPlayer::Simulate( void ) } BaseClass::Simulate(); + + if ((cl_showhitboxes.GetInt() == 1 || cl_showhitboxes.GetInt() == 2) && !IsLocalPlayer()) + { + DrawClientHitboxes(-1.0f, true); + } } void C_CSPlayer::PostThink() diff --git a/game/client/cstrike/c_cs_player.h b/game/client/cstrike/c_cs_player.h index e1ca29c5c5..938441db7d 100644 --- a/game/client/cstrike/c_cs_player.h +++ b/game/client/cstrike/c_cs_player.h @@ -123,6 +123,7 @@ public: void PlayReloadEffect(); virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options ); + virtual void FireGameEvent(IGameEvent* event); bool HasC4( void ); @@ -380,7 +381,16 @@ private: // HPE_END //============================================================================= - + static constexpr auto m_flDebugDuration = 60.f; + void DrawBullet(const Vector& src, + const Vector& endpos, + const Vector& mins, + const Vector& maxs, + int r, + int g, + int b, + int a, + float duration); C_CSPlayer( const C_CSPlayer & ); }; diff --git a/game/client/in_main.cpp b/game/client/in_main.cpp index e44e544f83..73aec63e2b 100644 --- a/game/client/in_main.cpp +++ b/game/client/in_main.cpp @@ -100,8 +100,6 @@ ConVar thirdperson_platformer( "thirdperson_platformer", "0", 0, "Player will ai ConVar thirdperson_screenspace( "thirdperson_screenspace", "0", 0, "Movement will be relative to the camera, eg: left means screen-left" ); ConVar sv_noclipduringpause( "sv_noclipduringpause", "0", FCVAR_REPLICATED | FCVAR_CHEAT, "If cheats are enabled, then you can noclip with the game paused (for doing screenshots, etc.)." ); -ConVar cl_showimpacts("cl_showimpacts", "0"); -ConVar cl_showfirebullethitboxes( "cl_showfirebullethitboxes", "0" ); extern ConVar cl_mouselook; #define UsingMouselook() cl_mouselook.GetBool() @@ -1314,9 +1312,12 @@ void CInput::CreateMove ( int sequence_number, float input_sample_frametime, boo cmd->simulationdata[pEntity->index].m_flSimulationTime = pEntity->m_flSimulationTime; } +#ifdef CSTRIKE_DLL static ConVarRef cl_showhitboxes("cl_showhitboxes"); static ConVarRef debug_screenshot_bullet_position("debug_screenshot_bullet_position"); - + static ConVarRef cl_showfirebullethitboxes("cl_showfirebullethitboxes"); + static ConVarRef cl_showimpacts("cl_showimpacts"); + cmd->debug_hitboxes = CUserCmd::DEBUG_HITBOXES_OFF; if (cl_showhitboxes.GetBool()) @@ -1333,6 +1334,7 @@ void CInput::CreateMove ( int sequence_number, float input_sample_frametime, boo { cmd->debug_hitboxes |= CUserCmd::DEBUG_HITBOXES_ON_HIT; } +#endif pVerified->m_cmd = *cmd; pVerified->m_crc = cmd->GetChecksum(); diff --git a/game/server/baseanimating.cpp b/game/server/baseanimating.cpp index dd84b2fa63..5b3d3a11c4 100644 --- a/game/server/baseanimating.cpp +++ b/game/server/baseanimating.cpp @@ -156,79 +156,6 @@ int CInfoLightingRelative::UpdateTransmitState( void ) return SetTransmitState( FL_EDICT_ALWAYS ); } -void* SendTableProxy_HitboxServerPositions( - const SendProp* pProp, - const void* pStructBase, - const void* pData, - CSendProxyRecipients* pRecipients, - int objectID) -{ - auto index = engine->GetSendTableCurrentEntityIndex(); - - if (index == -1) - { - return (void*)pData; - } - - CBaseEntity* entity = UTIL_EntityByIndex(index); - - if (!entity) - { - return (void*)pData; - } - - return ((Vector*)pData + entity->entindex() * MAXSTUDIOBONES); -} - -void* SendTableProxy_HitboxServerAngles(const SendProp* pProp, - const void* pStructBase, - const void* pData, - CSendProxyRecipients* pRecipients, - int objectID) -{ - auto index = engine->GetSendTableCurrentEntityIndex(); - - if (index == -1) - { - return (void*)pData; - } - - CBaseEntity* entity = UTIL_EntityByIndex(index); - - if (!entity) - { - return (void*)pData; - } - - return ((QAngle*)pData + entity->entindex() * MAXSTUDIOBONES); -} - -void SendProxy_ShouldShowServerHitboxesOnFire(const SendProp* pProp, - const void* pStructBase, - const void* pData, - DVariant* pOut, - int iElement, - int objectID) -{ - auto index = engine->GetSendTableCurrentEntityIndex(); - - if (index == -1) - { - pOut->m_Int = false; - return; - } - - CBaseEntity* entity = UTIL_EntityByIndex(index); - - if (!entity) - { - pOut->m_Int = false; - return; - } - - pOut->m_Int = *((bool*)pData + entity->entindex()); -} - static CIKSaveRestoreOps s_IKSaveRestoreOp; @@ -334,9 +261,7 @@ IMPLEMENT_SERVERCLASS_ST(CBaseAnimating, DT_BaseAnimating) // Fading SendPropFloat( SENDINFO( m_fadeMinDist ), 0, SPROP_NOSCALE ), SendPropFloat( SENDINFO( m_fadeMaxDist ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO( m_flFadeScale ), 0, SPROP_NOSCALE ), - SendPropArray3 (SENDINFO_NAME(m_vecHitboxServerPositions[0][0], m_vecHitboxServerPositions), MAXSTUDIOBONES, SendPropVector(SENDINFO_NAME(m_vecHitboxServerPositions[0][0], m_vecHitboxServerPositions[0]) ), SendTableProxy_HitboxServerPositions), - SendPropArray3 (SENDINFO_NAME(m_angHitboxServerAngles[0][0], m_angHitboxServerAngles), MAXSTUDIOBONES, SendPropQAngles(SENDINFO_NAME(m_angHitboxServerAngles[0][0], m_angHitboxServerAngles[0]) ), SendTableProxy_HitboxServerAngles), + SendPropFloat( SENDINFO( m_flFadeScale ), 0, SPROP_NOSCALE ) END_SEND_TABLE() @@ -364,15 +289,6 @@ CBaseAnimating::CBaseAnimating() m_fadeMaxDist = 0; m_flFadeScale = 0.0f; m_fBoneCacheFlags = 0; - - for (int i = 0; i <= MAX_PLAYERS; i++) - { - for (int j = 0; j < MAXSTUDIOBONES; j++) - { - m_vecHitboxServerPositions[i][j] = vec3_origin; - m_angHitboxServerAngles[i][j] = vec3_angle; - } - } } CBaseAnimating::~CBaseAnimating() @@ -3074,29 +2990,30 @@ static Vector hullcolor[8] = Vector( 1.0, 1.0, 1.0 ) }; -void CBaseAnimating::RecordServerHitboxes( CBasePlayer* localPlayer ) +int CBaseAnimating::GetServerHitboxes(Vector position[MAXSTUDIOBONES], QAngle angles[MAXSTUDIOBONES], int indexes[MAXSTUDIOBONES]) { - CStudioHdr *pStudioHdr = GetModelPtr(); + CStudioHdr *pStudioHdr = GetModelPtr(); if ( !pStudioHdr ) - return; + return 0; mstudiohitboxset_t *set =pStudioHdr->pHitboxSet( m_nHitboxSet ); if ( !set ) - return; + return 0; - Vector position; - QAngle angles; - const auto localPlayerIndex = localPlayer->entindex(); + int r = 0; + int g = 0; + int b = 255; - for ( int i = 0; i < set->numhitboxes; i++ ) + for ( int i = 0; i < set->numhitboxes; i++ ) { - mstudiobbox_t *pbox = set->pHitbox( i ); + mstudiobbox_t* pbox = set->pHitbox(i); - GetBonePosition(pbox->bone, position, angles); + indexes[i] = pbox->bone; - m_vecHitboxServerPositions[localPlayerIndex][i] = position; - m_angHitboxServerAngles[localPlayerIndex][i] = angles; - } + GetBonePosition( pbox->bone, position[pbox->bone], angles[pbox->bone] ); + } + + return set->numhitboxes; } //----------------------------------------------------------------------------- diff --git a/game/server/baseanimating.h b/game/server/baseanimating.h index 0e9f1ad474..d96d01e697 100644 --- a/game/server/baseanimating.h +++ b/game/server/baseanimating.h @@ -6,6 +6,7 @@ #ifndef BASEANIMATING_H #define BASEANIMATING_H +#include "mathlib/vector.h" #include "networkvar.h" #include "shareddefs.h" #ifdef _WIN32 @@ -265,7 +266,7 @@ public: virtual int DrawDebugTextOverlays( void ); // See note in code re: bandwidth usage!!! - void RecordServerHitboxes( CBasePlayer* localPlayer ); + int GetServerHitboxes( Vector position[MAXSTUDIOBONES], QAngle angles[MAXSTUDIOBONES], int indexes[MAXSTUDIOBONES] ); void DrawServerHitboxes( float duration = 0.0f, bool monocolor = false ); void DrawRawSkeleton( matrix3x4_t boneToWorld[], int boneMask, bool noDepthTest = true, float duration = 0.0f, bool monocolor = false ); @@ -392,9 +393,6 @@ private: CNetworkVar( int, m_nSequence ); CNetworkArray( float, m_flPoseParameter, NUM_POSEPAREMETERS ); // must be private so manual mode works! CNetworkArray( float, m_flEncodedController, NUM_BONECTRLS ); // bone controller setting (0..1) - - Vector m_vecHitboxServerPositions[MAX_PLAYERS+1][MAXSTUDIOBONES]; - QAngle m_angHitboxServerAngles[MAX_PLAYERS +1][MAXSTUDIOBONES]; // Client-side animation (useful for looping animation objects) CNetworkVar( bool, m_bClientSideAnimation ); diff --git a/game/server/cstrike/bot/cs_bot.h b/game/server/cstrike/bot/cs_bot.h index e9530d5db1..472ff3f3fb 100644 --- a/game/server/cstrike/bot/cs_bot.h +++ b/game/server/cstrike/bot/cs_bot.h @@ -877,6 +877,9 @@ public: void OnWeaponZoom( IGameEvent *event ); void OnBulletImpact( IGameEvent *event ); + void OnBulletHitPlayer( IGameEvent *event ); + void OnBulletPlayerHitboxes( IGameEvent *event ); + void OnPlayerLagHitboxes( IGameEvent *event ); void OnHEGrenadeDetonate( IGameEvent *event ); void OnFlashbangDetonate( IGameEvent *event ); diff --git a/game/server/cstrike/bot/cs_bot_event.cpp b/game/server/cstrike/bot/cs_bot_event.cpp index 24bdae43e1..72d500b920 100644 --- a/game/server/cstrike/bot/cs_bot_event.cpp +++ b/game/server/cstrike/bot/cs_bot_event.cpp @@ -198,6 +198,17 @@ void CCSBot::OnBulletImpact( IGameEvent *event ) //OnAudibleEvent( event, player, 1100.0f, PRIORITY_MEDIUM, true, false, &actualOrigin ); // bullet_impact } +void CCSBot::OnBulletHitPlayer( IGameEvent *event ) +{ +} + +void CCSBot::OnBulletPlayerHitboxes( IGameEvent *event ) +{ +} + +void CCSBot::OnPlayerLagHitboxes( IGameEvent *event ) +{ +} //-------------------------------------------------------------------------------------------------------------- void CCSBot::OnBreakProp( IGameEvent *event ) diff --git a/game/server/cstrike/bot/cs_bot_manager.cpp b/game/server/cstrike/bot/cs_bot_manager.cpp index aec0ef3642..8962c62565 100644 --- a/game/server/cstrike/bot/cs_bot_manager.cpp +++ b/game/server/cstrike/bot/cs_bot_manager.cpp @@ -116,7 +116,10 @@ CCSBotManager::CCSBotManager() m_commonEventListeners.AddToTail( &m_WeaponFireOnEmptyEvent ); m_commonEventListeners.AddToTail( &m_WeaponReloadEvent ); m_commonEventListeners.AddToTail( &m_WeaponZoomEvent ); - m_commonEventListeners.AddToTail( &m_BulletImpactEvent ); + m_commonEventListeners.AddToTail( &m_BulletImpactEvent ); + m_commonEventListeners.AddToTail( &m_BulletHitPlayerEvent ); + m_commonEventListeners.AddToTail( &m_BulletPlayerHitboxesEvent ); + m_commonEventListeners.AddToTail( &m_PlayerLagHitboxesEvent ); m_commonEventListeners.AddToTail( &m_GrenadeBounceEvent ); m_commonEventListeners.AddToTail( &m_NavBlockedEvent ); @@ -2004,6 +2007,20 @@ void CCSBotManager::OnBulletImpact( IGameEvent *event ) CCSBOTMANAGER_ITERATE_BOTS( OnBulletImpact, event ); } +void CCSBotManager::OnBulletHitPlayer( IGameEvent *event ) +{ + CCSBOTMANAGER_ITERATE_BOTS( OnBulletHitPlayer, event ); +} + +void CCSBotManager::OnBulletPlayerHitboxes( IGameEvent *event ) +{ + CCSBOTMANAGER_ITERATE_BOTS( OnBulletPlayerHitboxes, event ); +} + +void CCSBotManager::OnPlayerLagHitboxes( IGameEvent *event ) +{ + CCSBOTMANAGER_ITERATE_BOTS( OnPlayerLagHitboxes, event ); +} //-------------------------------------------------------------------------------------------------------------- void CCSBotManager::OnHEGrenadeDetonate( IGameEvent *event ) diff --git a/game/server/cstrike/bot/cs_bot_manager.h b/game/server/cstrike/bot/cs_bot_manager.h index 3f1da76644..c8c682c446 100644 --- a/game/server/cstrike/bot/cs_bot_manager.h +++ b/game/server/cstrike/bot/cs_bot_manager.h @@ -362,6 +362,9 @@ private: DECLARE_CSBOTMANAGER_EVENT_LISTENER( WeaponZoom, weapon_zoom ) DECLARE_CSBOTMANAGER_EVENT_LISTENER( BulletImpact, bullet_impact ) + DECLARE_CSBOTMANAGER_EVENT_LISTENER( BulletHitPlayer, bullet_hit_player ) + DECLARE_CSBOTMANAGER_EVENT_LISTENER( BulletPlayerHitboxes, bullet_player_hitboxes ) + DECLARE_CSBOTMANAGER_EVENT_LISTENER( PlayerLagHitboxes, player_lag_hitboxes ) DECLARE_CSBOTMANAGER_EVENT_LISTENER( HEGrenadeDetonate, hegrenade_detonate ) DECLARE_CSBOTMANAGER_EVENT_LISTENER( FlashbangDetonate, flashbang_detonate ) diff --git a/game/server/cstrike/cs_eventlog.cpp b/game/server/cstrike/cs_eventlog.cpp index 6ad09f4119..e51165b729 100644 --- a/game/server/cstrike/cs_eventlog.cpp +++ b/game/server/cstrike/cs_eventlog.cpp @@ -50,7 +50,6 @@ public: ListenForGameEvent( "hostage_killed" ); ListenForGameEvent( "hostage_follows" ); ListenForGameEvent( "player_hurt" ); - ListenForGameEvent( "bullet_impact" ); return true; } diff --git a/game/server/cstrike/cs_player.cpp b/game/server/cstrike/cs_player.cpp index 1f3277c367..13b4dbfb28 100644 --- a/game/server/cstrike/cs_player.cpp +++ b/game/server/cstrike/cs_player.cpp @@ -57,6 +57,7 @@ #include "gamestats.h" #include "holiday_gift.h" #include "../../shared/cstrike/cs_achievement_constants.h" +#include "ilagcompensationmanager.h" //============================================================================= // HPE_BEGIN @@ -506,7 +507,6 @@ CCSPlayer::CCSPlayer() m_vLastHitLocationObjectSpace = Vector(0,0,0); m_wasNotKilledNaturally = false; - //============================================================================= // HPE_END //============================================================================= @@ -1585,7 +1585,57 @@ void CCSPlayer::UpdateMouseoverHints() } void CCSPlayer::PostThink() -{ +{ + if (m_pCurrentCommand->debug_hitboxes & CUserCmd::DEBUG_HITBOXES_ALWAYS_ON) + { + lagcompensation->StartLagCompensation( this, GetCurrentCommand() ); + + for (int i = 1; i <= gpGlobals->maxClients; i++) + { + CBasePlayer* lagPlayer = UTIL_PlayerByIndex(i); + + if (!lagPlayer) + continue; + + IGameEvent* event = gameeventmanager->CreateEvent("player_lag_hitboxes"); + if (event) + { + event->SetInt("userid", GetUserID()); + event->SetInt("player_index", lagPlayer->entindex()); + + Vector positions[MAXSTUDIOBONES]; + QAngle angles[MAXSTUDIOBONES]; + int indexes[MAXSTUDIOBONES]; + + int numhitboxes = lagPlayer->GetServerHitboxes(positions, angles, indexes); + event->SetInt("num_hitboxes", numhitboxes); + + for (int i = 0; i < numhitboxes; i++) + { + char buffer[256]; + V_sprintf_safe(buffer, "hitbox_index_%i", i); + event->SetInt(buffer, indexes[i]); + V_sprintf_safe(buffer, "hitbox_position_x_%i", i); + event->SetFloat(buffer, positions[indexes[i]].x); + V_sprintf_safe(buffer, "hitbox_position_y_%i", i); + event->SetFloat(buffer, positions[indexes[i]].y); + V_sprintf_safe(buffer, "hitbox_position_z_%i", i); + event->SetFloat(buffer, positions[indexes[i]].z); + V_sprintf_safe(buffer, "hitbox_angle_x_%i", i); + event->SetFloat(buffer, angles[indexes[i]].x); + V_sprintf_safe(buffer, "hitbox_angle_y_%i", i); + event->SetFloat(buffer, angles[indexes[i]].y); + V_sprintf_safe(buffer, "hitbox_angle_z_%i", i); + event->SetFloat(buffer, angles[indexes[i]].z); + } + + gameeventmanager->FireEventClientSide(event); + } + } + + lagcompensation->FinishLagCompensation( this ); + } + BaseClass::PostThink(); UpdateAddonBits(); diff --git a/game/server/cstrike/cs_player.h b/game/server/cstrike/cs_player.h index 0d77106142..0b67f22dd7 100644 --- a/game/server/cstrike/cs_player.h +++ b/game/server/cstrike/cs_player.h @@ -294,7 +294,7 @@ public: virtual CWeaponCSBase* CSAnim_GetActiveWeapon(); virtual bool CSAnim_CanMove(); - virtual float GetPlayerMaxSpeed(); + virtual float GetPlayerMaxSpeed(); void FireBullet( int iBullet, @@ -1037,7 +1037,6 @@ private: // HPE_END //============================================================================= int m_iDeathFlags; // Flags holding revenge and domination info about a death - //============================================================================= // HPE_END //============================================================================= diff --git a/game/server/player.cpp b/game/server/player.cpp index 49a6425fc3..3c88dcee1e 100644 --- a/game/server/player.cpp +++ b/game/server/player.cpp @@ -4522,7 +4522,6 @@ void CBasePlayer::ForceOrigin( const Vector &vecOrigin ) //----------------------------------------------------------------------------- void CBasePlayer::PostThink() { - m_bDebugServerBullets = false; m_vecSmoothedVelocity = m_vecSmoothedVelocity * SMOOTHING_FACTOR + GetAbsVelocity() * ( 1 - SMOOTHING_FACTOR ); if ( !g_fGameOver && !m_iPlayerLocked ) @@ -7973,11 +7972,7 @@ void CMovementSpeedMod::InputSpeedMod(inputdata_t &data) SendPropFloat ( SENDINFO( m_flDeathTime ), 0, SPROP_NOSCALE ), SendPropInt ( SENDINFO( m_nWaterLevel ), 2, SPROP_UNSIGNED ), - SendPropFloat ( SENDINFO( m_flLaggedMovementValue ), 0, SPROP_NOSCALE ), - SendPropUtlVector( SENDINFO_UTLVECTOR(m_vecBulletServerPositions), MAX_PLAYER_BULLET_SERVER_POSITIONS, SendPropVector(NULL, 0)), - SendPropUtlVector( SENDINFO_UTLVECTOR(m_vecServerShootPositions), MAX_PLAYER_BULLET_SERVER_POSITIONS, SendPropVector(NULL, 0)), - SendPropBool(SENDINFO(m_bDebugServerBullets)), - SendPropUtlVector( SENDINFO_UTLVECTOR(m_touchedEntitiesWithBullet), MAX_PLAYER_BULLET_SERVER_POSITIONS, SendPropVector(NULL, 0)), + SendPropFloat ( SENDINFO( m_flLaggedMovementValue ), 0, SPROP_NOSCALE ) END_SEND_TABLE() diff --git a/game/server/player.h b/game/server/player.h index 3c51a6869d..d9d412bac9 100644 --- a/game/server/player.h +++ b/game/server/player.h @@ -1211,10 +1211,6 @@ private: public: virtual unsigned int PlayerSolidMask( bool brushOnly = false ) const; // returns the solid mask for the given player, so bots can have a more-restrictive set - CNetworkVar(bool, m_bDebugServerBullets); - CUtlVector m_vecBulletServerPositions; - CUtlVector m_vecServerShootPositions; - CUtlVector m_touchedEntitiesWithBullet; }; typedef CHandle CBasePlayerHandle; diff --git a/game/server/player_command.cpp b/game/server/player_command.cpp index a7961e0c8c..4d0d430b7d 100644 --- a/game/server/player_command.cpp +++ b/game/server/player_command.cpp @@ -346,23 +346,6 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper g_pGameMovement->StartTrackPredictionErrors( player ); - if (ucmd->debug_hitboxes & CUserCmd::DEBUG_HITBOXES_ALWAYS_ON) - { - lagcompensation->StartLagCompensation( player, player->GetCurrentCommand() ); - - for (int i = 1; i <= gpGlobals->maxClients; i++) - { - CBasePlayer* lagPlayer = UTIL_PlayerByIndex(i); - - if (!lagPlayer) - continue; - - lagPlayer->RecordServerHitboxes( player ); - } - - lagcompensation->FinishLagCompensation( player ); - } - RunPostThink( player ); // Prevent hacked clients from sending us invalid view angles to try to get leaf server code to crash diff --git a/game/shared/cstrike/cs_player_shared.cpp b/game/shared/cstrike/cs_player_shared.cpp index 012cb2454b..4951a82825 100644 --- a/game/shared/cstrike/cs_player_shared.cpp +++ b/game/shared/cstrike/cs_player_shared.cpp @@ -6,6 +6,7 @@ #include "cbase.h" #include "debugoverlay_shared.h" +#include "strtools.h" #ifndef CLIENT_DLL #include "player.h" #else @@ -419,6 +420,22 @@ inline void UTIL_TraceLineIgnoreTwoEntities(const Vector& vecAbsStart, const Vec } } +#ifdef CLIENT_DLL +void CCSPlayer::DrawBullet(const Vector& src, + const Vector& endpos, + const Vector& mins, + const Vector& maxs, + int r, + int g, + int b, + int a, + float duration) +{ + NDebugOverlay::SweptBox(src, endpos, mins, maxs, QAngle(0, 0, 0), r, g, b, a, duration); + NDebugOverlay::Box(endpos, mins, maxs, r, g, b, a, duration); +} +#endif + void CCSPlayer::FireBullet( int iBullet, // bullet number Vector vecSrc, // shooting postion @@ -450,8 +467,8 @@ void CCSPlayer::FireBullet( float flBulletRadius = flBulletDiameter / 2.0f; - Vector vecBulletRadiusMaxs(flBulletRadius, flBulletRadius, flBulletRadius); - Vector vecBulletRadiusMins(-flBulletRadius, -flBulletRadius, -flBulletRadius); + Vector vecBulletRadiusMaxs(flBulletRadius); + Vector vecBulletRadiusMins(-flBulletRadius); if ( !pevAttacker ) pevAttacker = this; // the default attacker is ourselves @@ -489,27 +506,68 @@ void CCSPlayer::FireBullet( CBasePlayer *lastPlayerHit = NULL; MDLCACHE_CRITICAL_SECTION(); - bool shouldTakeAllPlayers = m_pCurrentCommand->debug_hitboxes & CUserCmd::DEBUG_HITBOXES_ON_FIRE; - bool shouldTakeHitPlayer = m_pCurrentCommand->debug_hitboxes & CUserCmd::DEBUG_HITBOXES_ON_HIT; + bool shouldDebugHitboxesOnFire = m_pCurrentCommand->debug_hitboxes & CUserCmd::DEBUG_HITBOXES_ON_FIRE; + bool shouldDebugHitboxesOnHit = m_pCurrentCommand->debug_hitboxes & CUserCmd::DEBUG_HITBOXES_ON_HIT; - if ( shouldTakeAllPlayers && !shouldTakeHitPlayer ) + // TODO_ENHANCED: + // Send only to only one client, + // others clients don't need the information on how other players lag compensated players. +#ifdef CLIENT_DLL + static ConVarRef cl_showfirebullethitboxes("cl_showfirebullethitboxes"); + static ConVarRef cl_showimpacts("cl_showimpacts"); + shouldDebugHitboxesOnHit = shouldDebugHitboxesOnHit && (cl_showimpacts.GetInt() == 1 || cl_showimpacts.GetInt() == 2); + shouldDebugHitboxesOnFire = shouldDebugHitboxesOnFire && (cl_showfirebullethitboxes.GetInt() == 1 || cl_showfirebullethitboxes.GetInt() == 2); +#endif + if ( shouldDebugHitboxesOnFire && !shouldDebugHitboxesOnHit ) { for (int i = 1; i <= gpGlobals->maxClients; i++) { CBasePlayer* lagPlayer = UTIL_PlayerByIndex(i); - - if( lagPlayer ) + if (lagPlayer && lagPlayer != this) { #ifdef CLIENT_DLL if (!m_pCurrentCommand->hasbeenpredicted) { - lagPlayer->RecordClientHitboxes(); + lagPlayer->DrawClientHitboxes(m_flDebugDuration, true); } #else - lagPlayer->RecordServerHitboxes(this); + IGameEvent* event = gameeventmanager->CreateEvent("bullet_player_hitboxes"); + if (event) + { + event->SetInt("userid", GetUserID()); + event->SetInt("player_index", lagPlayer->entindex()); + + Vector positions[MAXSTUDIOBONES]; + QAngle angles[MAXSTUDIOBONES]; + int indexes[MAXSTUDIOBONES]; + + int numhitboxes = lagPlayer->GetServerHitboxes(positions, angles, indexes); + event->SetInt("num_hitboxes", numhitboxes); + + for (int i = 0; i < numhitboxes; i++) + { + char buffer[256]; + V_sprintf_safe(buffer, "hitbox_index_%i", i); + event->SetInt(buffer, indexes[i]); + V_sprintf_safe(buffer, "hitbox_position_x_%i", i); + event->SetFloat(buffer, positions[indexes[i]].x); + V_sprintf_safe(buffer, "hitbox_position_y_%i", i); + event->SetFloat(buffer, positions[indexes[i]].y); + V_sprintf_safe(buffer, "hitbox_position_z_%i", i); + event->SetFloat(buffer, positions[indexes[i]].z); + V_sprintf_safe(buffer, "hitbox_angle_x_%i", i); + event->SetFloat(buffer, angles[indexes[i]].x); + V_sprintf_safe(buffer, "hitbox_angle_y_%i", i); + event->SetFloat(buffer, angles[indexes[i]].y); + V_sprintf_safe(buffer, "hitbox_angle_z_%i", i); + event->SetFloat(buffer, angles[indexes[i]].z); + } + + gameeventmanager->FireEventClientSide(event); + } #endif } - } + } } while ( fCurrentDamage > 0 ) @@ -556,32 +614,80 @@ void CCSPlayer::FireBullet( flDamageModifier = 0.99f; } - if (shouldTakeHitPlayer) + if (shouldDebugHitboxesOnHit) { -#ifndef CLIENT_DLL - m_vecBulletServerPositions.AddToTail(tr.endpos); - m_vecServerShootPositions.AddToTail(vecSrc); -#else - m_vecBulletClientPositions.AddToTail(tr.endpos); - m_vecClientShootPositions.AddToTail(vecSrc); -#endif - if (tr.m_pEnt) +#ifdef CLIENT_DLL + if (!m_pCurrentCommand->hasbeenpredicted) { -#ifndef CLIENT_DLL - m_touchedEntitiesWithBullet.AddToTail(tr.m_pEnt->entindex()); + DrawBullet(vecSrc, + tr.endpos, + vecBulletRadiusMins, + vecBulletRadiusMaxs, + 0, + 255, + 0, + 127, + m_flDebugDuration); + } +#else + IGameEvent* event = gameeventmanager->CreateEvent("bullet_impact"); + if (event) + { + event->SetInt("userid", GetUserID()); + event->SetFloat("src_x", vecSrc.x); + event->SetFloat("src_y", vecSrc.y); + event->SetFloat("src_z", vecSrc.z); + event->SetFloat("dst_x", tr.endpos.x); + event->SetFloat("dst_y", tr.endpos.y); + event->SetFloat("dst_z", tr.endpos.z); + event->SetFloat("radius", flBulletRadius); + gameeventmanager->FireEventClientSide(event); + } #endif - if (tr.m_pEnt->IsPlayer() && !shouldTakeAllPlayers) + if (tr.m_pEnt && tr.m_pEnt->IsPlayer() && !shouldDebugHitboxesOnFire) + { + const auto lagPlayer = UTIL_PlayerByIndex(tr.m_pEnt->entindex()); +#ifdef CLIENT_DLL + if (!m_pCurrentCommand->hasbeenpredicted) { - CBasePlayer* player = ToBasePlayer(tr.m_pEnt); - #ifdef CLIENT_DLL - if (!m_pCurrentCommand->hasbeenpredicted) - { - player->RecordClientHitboxes(); - } - #else - player->RecordServerHitboxes(this); - #endif + lagPlayer->DrawClientHitboxes(m_flDebugDuration, true); } +#else + IGameEvent* eventHit = gameeventmanager->CreateEvent("bullet_hit_player"); + if (eventHit) + { + eventHit->SetInt("userid", GetUserID()); + eventHit->SetInt("player_index", lagPlayer->entindex()); + + Vector positions[MAXSTUDIOBONES]; + QAngle angles[MAXSTUDIOBONES]; + int indexes[MAXSTUDIOBONES]; + + int numhitboxes = lagPlayer->GetServerHitboxes(positions, angles, indexes); + eventHit->SetInt("num_hitboxes", numhitboxes); + + for (int i = 0; i < numhitboxes; i++) + { + char buffer[256]; + V_sprintf_safe(buffer, "hitbox_index_%i", i); + eventHit->SetInt(buffer, indexes[i]); + V_sprintf_safe(buffer, "hitbox_position_x_%i", i); + eventHit->SetFloat(buffer, positions[indexes[i]].x); + V_sprintf_safe(buffer, "hitbox_position_y_%i", i); + eventHit->SetFloat(buffer, positions[indexes[i]].y); + V_sprintf_safe(buffer, "hitbox_position_z_%i", i); + eventHit->SetFloat(buffer, positions[indexes[i]].z); + V_sprintf_safe(buffer, "hitbox_angle_x_%i", i); + eventHit->SetFloat(buffer, angles[indexes[i]].x); + V_sprintf_safe(buffer, "hitbox_angle_y_%i", i); + eventHit->SetFloat(buffer, angles[indexes[i]].y); + V_sprintf_safe(buffer, "hitbox_angle_z_%i", i); + eventHit->SetFloat(buffer, angles[indexes[i]].z); + } + + gameeventmanager->FireEventClientSide(eventHit); + } +#endif } } diff --git a/game/shared/cstrike/fx_cs_shared.cpp b/game/shared/cstrike/fx_cs_shared.cpp index 4ee714f987..71625a9b5f 100644 --- a/game/shared/cstrike/fx_cs_shared.cpp +++ b/game/shared/cstrike/fx_cs_shared.cpp @@ -291,18 +291,9 @@ void FX_FireBullets( y1[iBullet] = fRadius1 * sinf(fTheta1); } -#ifndef CLIENT_DLL - pPlayer->m_vecBulletServerPositions.RemoveAll(); - pPlayer->m_vecServerShootPositions.RemoveAll(); - pPlayer->m_touchedEntitiesWithBullet.RemoveAll(); - pPlayer->m_bDebugServerBullets = true; -#endif - for ( int iBullet=0; iBullet < pWeaponInfo->m_iBullets; iBullet++ ) { - // Still take the screenshot where we shooted, make a screenshot when we received the server bullet hits too. #ifdef CLIENT_DLL - static ConVarRef debug_screenshot_bullet_position("debug_screenshot_bullet_position"); if (pPlayer->IsLocalPlayer() && debug_screenshot_bullet_position.GetBool()) { gpGlobals->client_taking_screenshot = true; diff --git a/public/igameevents.h b/public/igameevents.h index 7d5465ecd6..c2c28261b0 100644 --- a/public/igameevents.h +++ b/public/igameevents.h @@ -134,6 +134,7 @@ public: // write/read event to/from bitbuffer virtual bool SerializeEvent( IGameEvent *event, bf_write *buf ) = 0; virtual IGameEvent *UnserializeEvent( bf_read *buf ) = 0; // create new KeyValues, must be deleted + virtual bool RegisterEvent( KeyValues * keys ) = 0; }; // the old game event manager interface, don't use it. Rest is legacy support: diff --git a/public/tier2/renderutils.h b/public/tier2/renderutils.h index fe3d87ce8e..e1c1223ad0 100644 --- a/public/tier2/renderutils.h +++ b/public/tier2/renderutils.h @@ -34,6 +34,7 @@ void RenderSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi, void RenderWireframeBox( const Vector &vOrigin, const QAngle& angles, const Vector &vMins, const Vector &vMaxs, Color c, bool bZBuffer ); // Renders a swept wireframe box +void RenderSweptBox( const Vector &vStart, const Vector &vEnd, const QAngle &angles, const Vector &vMins, const Vector &vMaxs, Color c, bool bZBuffer ); void RenderWireframeSweptBox( const Vector &vStart, const Vector &vEnd, const QAngle &angles, const Vector &vMins, const Vector &vMaxs, Color c, bool bZBuffer ); // Renders a solid box diff --git a/tier2/renderutils.cpp b/tier2/renderutils.cpp index faf50f6e21..0dcf1d43de 100644 --- a/tier2/renderutils.cpp +++ b/tier2/renderutils.cpp @@ -664,6 +664,73 @@ static void DrawExtrusionFace( const Vector& start, const Vector& end, meshBuilder.AdvanceVertex(); } +void RenderSweptBox( const Vector &vStart, const Vector &vEnd, const QAngle &angles, const Vector &vMins, const Vector &vMaxs, Color c, bool bZBuffer ) +{ + InitializeStandardMaterials(); + + CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); + pRenderContext->Bind( bZBuffer ? s_pVertexColor : s_pVertexColorIgnoreZ ); + + Color cActual( c.r(), c.g(), c.b(), c.a() ); + + // Build a rotation matrix from angles + matrix3x4_t fRotateMatrix; + AngleMatrix( angles, fRotateMatrix ); + + IMesh *pMesh = pRenderContext->GetDynamicMesh( ); + CMeshBuilder meshBuilder; + meshBuilder.Begin( pMesh, MATERIAL_LINES, 30 ); + + Vector vDelta; + VectorSubtract( vEnd, vStart, vDelta ); + + // Compute the box points, rotated but without the origin added + Vector temp; + Vector pts[8]; + float dot[8]; + int minidx = 0; + for ( int i = 0; i < 8; ++i ) + { + temp.x = (i & 0x1) ? vMaxs[0] : vMins[0]; + temp.y = (i & 0x2) ? vMaxs[1] : vMins[1]; + temp.z = (i & 0x4) ? vMaxs[2] : vMins[2]; + + // Rotate the corner point + VectorRotate( temp, fRotateMatrix, pts[i] ); + + // Find the dot product with dir + dot[i] = DotProduct( pts[i], vDelta ); + if ( dot[i] < dot[minidx] ) + { + minidx = i; + } + } + + // Choose opposite corner + int maxidx = minidx ^ 0x7; + + // Draw the start + end axes... + DrawAxes( vStart, pts, minidx, cActual, meshBuilder ); + DrawAxes( vEnd, pts, maxidx, cActual, meshBuilder ); + + // Draw the extrusion faces + for (int j = 0; j < 3; ++j ) + { + int dirflag1 = ( 1 << ((j+1)%3) ); + int dirflag2 = ( 1 << ((j+2)%3) ); + + int idx1, idx2, idx3; + idx1 = (minidx & dirflag1) ? minidx - dirflag1 : minidx + dirflag1; + idx2 = (minidx & dirflag2) ? minidx - dirflag2 : minidx + dirflag2; + idx3 = (minidx & dirflag2) ? idx1 - dirflag2 : idx1 + dirflag2; + + DrawExtrusionFace( vStart, vEnd, pts, idx1, idx3, cActual, meshBuilder ); + DrawExtrusionFace( vStart, vEnd, pts, idx2, idx3, cActual, meshBuilder ); + } + meshBuilder.End(); + pMesh->Draw(); +} + void RenderWireframeSweptBox( const Vector &vStart, const Vector &vEnd, const QAngle &angles, const Vector &vMins, const Vector &vMaxs, Color c, bool bZBuffer ) { InitializeStandardMaterials();