diff --git a/game/client/c_baseanimating.cpp b/game/client/c_baseanimating.cpp index d3d921b15a..8fcb517532 100644 --- a/game/client/c_baseanimating.cpp +++ b/game/client/c_baseanimating.cpp @@ -5636,8 +5636,8 @@ void C_BaseAnimating::DrawServerHitboxes( float duration /*= 0.0f*/, bool monoco QAngle angles; int r = 0; - int g = 255; - int b = 0; + int g = 0; + int b = 255; for ( int i = 0; i < set->numhitboxes; i++ ) { diff --git a/game/client/c_baseplayer.cpp b/game/client/c_baseplayer.cpp index 00356c5b82..3bc3942822 100644 --- a/game/client/c_baseplayer.cpp +++ b/game/client/c_baseplayer.cpp @@ -7,6 +7,8 @@ //===========================================================================// #include "cbase.h" #include "c_baseplayer.h" +#include "convar.h" +#include "dt_recv.h" #include "flashlighteffect.h" #include "weapon_selection.h" #include "history_resource.h" @@ -24,6 +26,7 @@ #include "view_shared.h" #include "movevars_shared.h" #include "prediction.h" +#include "engine/ivdebugoverlay.h" #include "tier0/vprof.h" #include "filesystem.h" #include "bitbuf.h" @@ -244,7 +247,8 @@ END_RECV_TABLE() RecvPropInt ( RECVINFO( m_nWaterLevel ) ), RecvPropFloat ( RECVINFO( m_flLaggedMovementValue )), - + RecvPropArray3 ( RECVINFO_ARRAY(m_vecBulletPositions), RecvPropVector( RECVINFO(m_vecBulletPositions[0])) ), + RecvPropInt(RECVINFO(m_iBulletPositionCount)), END_RECV_TABLE() @@ -2131,7 +2135,30 @@ void C_BasePlayer::Simulate() if (m_nTickBaseFireBullet <= m_nTickBase && m_nTickBaseFireBullet != -1) { DrawServerHitboxes(60.0f, true); - m_nTickBaseFireBullet = -1; + static ConVarRef cl_showimpacts("cl_showimpacts"); + + if (cl_showimpacts.GetInt() == 1 || cl_showimpacts.GetInt() == 3) + { + extern float g_bulletDiameter; + for (int i = 0; i < m_iBulletPositionCount; i++) + { + debugoverlay->AddBoxOverlay(m_vecBulletPositions[i], + Vector(-g_bulletDiameter, + -g_bulletDiameter, + -g_bulletDiameter), + Vector(g_bulletDiameter, + g_bulletDiameter, + g_bulletDiameter), + QAngle(0, 0, 0), + 0, + 0, + 255, + 127, + 60); + } + } + + m_nTickBaseFireBullet = -1; } } diff --git a/game/client/c_baseplayer.h b/game/client/c_baseplayer.h index eb8c5ef394..12ebed8cdf 100644 --- a/game/client/c_baseplayer.h +++ b/game/client/c_baseplayer.h @@ -638,6 +638,8 @@ public: void SetOldPlayerZ( float flOld ) { m_flOldPlayerZ = flOld; } int m_nTickBaseFireBullet; + Vector m_vecBulletPositions[MAX_PLAYER_BULLET_POSITIONS]; + int m_iBulletPositionCount; }; EXTERN_RECV_TABLE(DT_BasePlayer); diff --git a/game/client/in_main.cpp b/game/client/in_main.cpp index 04ce6b3cbe..e4323f5294 100644 --- a/game/client/in_main.cpp +++ b/game/client/in_main.cpp @@ -98,7 +98,8 @@ 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", FCVAR_NONE, "Shows client (red) and server (blue) bullet impact point (1=both, 2=client-only, 3=server-only)" ); +ConVar cl_showfirebullethitboxes( "cl_showfirebullethitboxes", "0" ); extern ConVar cl_mouselook; #define UsingMouselook() cl_mouselook.GetBool() @@ -1333,17 +1334,25 @@ void CInput::CreateMove ( int sequence_number, float input_sample_frametime, boo } static ConVarRef cl_showhitboxes("cl_showhitboxes"); - static ConVarRef cl_showfirebullethitboxes("cl_showfirebullethitboxes"); - - if (cl_showhitboxes.GetBool() || cl_showfirebullethitboxes.GetBool()) + + if (cl_showhitboxes.GetBool()) { - cmd->debug_hitboxes = true; + cmd->debug_hitboxes = CUserCmd::DEBUG_HITBOXES_ALWAYS_ON; + } + else if (cl_showfirebullethitboxes.GetBool()) + { + cmd->debug_hitboxes = CUserCmd::DEBUG_HITBOXES_ON_BULLET; + } + else if (cl_showimpacts.GetInt() == 1 || cl_showimpacts.GetInt() == 3) + { + cmd->debug_hitboxes = CUserCmd::DEBUG_HITBOXES_ON_HIT; } else { - cmd->debug_hitboxes = false; + cmd->debug_hitboxes = CUserCmd::DEBUG_HITBOXES_OFF; } + pVerified->m_cmd = *cmd; pVerified->m_crc = cmd->GetChecksum(); } diff --git a/game/server/baseanimating.cpp b/game/server/baseanimating.cpp index 4226300a23..533dd19629 100644 --- a/game/server/baseanimating.cpp +++ b/game/server/baseanimating.cpp @@ -3049,7 +3049,7 @@ static Vector hullcolor[8] = Vector( 1.0, 1.0, 1.0 ) }; -void CBaseAnimating::RecordServerHitboxes( CBasePlayer* player ) +void CBaseAnimating::RecordServerHitboxes( CBasePlayer* localPlayer ) { CStudioHdr *pStudioHdr = GetModelPtr(); if ( !pStudioHdr ) @@ -3061,7 +3061,7 @@ void CBaseAnimating::RecordServerHitboxes( CBasePlayer* player ) Vector position; QAngle angles; - const auto localPlayerIndex = player->entindex(); + const auto localPlayerIndex = localPlayer->entindex(); for ( int i = 0; i < set->numhitboxes; i++ ) { diff --git a/game/server/baseanimating.h b/game/server/baseanimating.h index 99465f0f51..a8757a3d0b 100644 --- a/game/server/baseanimating.h +++ b/game/server/baseanimating.h @@ -263,7 +263,7 @@ public: virtual int DrawDebugTextOverlays( void ); // See note in code re: bandwidth usage!!! - void RecordServerHitboxes( CBasePlayer* player ); + void RecordServerHitboxes( CBasePlayer* localPlayer ); 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 ); diff --git a/game/server/player.cpp b/game/server/player.cpp index ba71d9820c..a85d06f43f 100644 --- a/game/server/player.cpp +++ b/game/server/player.cpp @@ -7,6 +7,7 @@ #include "cbase.h" #include "const.h" #include "baseplayer_shared.h" +#include "dt_send.h" #include "trains.h" #include "soundent.h" #include "gib.h" @@ -633,6 +634,7 @@ CBasePlayer::CBasePlayer( ) m_flLastUserCommandTime = 0.f; m_flMovementTimeForUserCmdProcessingRemaining = 0.0f; + m_iBulletPositionCount.Set(0); } CBasePlayer::~CBasePlayer( ) @@ -7968,7 +7970,8 @@ void CMovementSpeedMod::InputSpeedMod(inputdata_t &data) SendPropInt ( SENDINFO( m_nWaterLevel ), 2, SPROP_UNSIGNED ), SendPropFloat ( SENDINFO( m_flLaggedMovementValue ), 0, SPROP_NOSCALE ), - + SendPropArray3( SENDINFO_ARRAY3(m_vecBulletPositions), SendPropVector(SENDINFO_ARRAY(m_vecBulletPositions))), + SendPropInt(SENDINFO(m_iBulletPositionCount)), END_SEND_TABLE() diff --git a/game/server/player.h b/game/server/player.h index 898d4bfc0d..ad00d1de41 100644 --- a/game/server/player.h +++ b/game/server/player.h @@ -233,7 +233,6 @@ private: CBasePlayer *m_pParent; }; - class CBasePlayer : public CBaseCombatCharacter { public: @@ -1211,7 +1210,8 @@ 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 - + CNetworkArray(Vector, m_vecBulletPositions, MAX_PLAYER_BULLET_POSITIONS); + CNetworkVar(int, m_iBulletPositionCount); }; typedef CHandle CBasePlayerHandle; diff --git a/game/server/player_command.cpp b/game/server/player_command.cpp index 6e88218dba..f4137db009 100644 --- a/game/server/player_command.cpp +++ b/game/server/player_command.cpp @@ -346,7 +346,7 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper g_pGameMovement->StartTrackPredictionErrors( player ); - if (ucmd->debug_hitboxes) + if (ucmd->debug_hitboxes == CUserCmd::DEBUG_HITBOXES_ALWAYS_ON) { lagcompensation->StartLagCompensation( player, player->GetCurrentCommand() ); diff --git a/game/shared/cstrike/cs_player_shared.cpp b/game/shared/cstrike/cs_player_shared.cpp index 6b652bd636..303f6fee27 100644 --- a/game/shared/cstrike/cs_player_shared.cpp +++ b/game/shared/cstrike/cs_player_shared.cpp @@ -6,6 +6,9 @@ #include "cbase.h" #include "debugoverlay_shared.h" +#ifndef CLIENT_DLL +#include "player.h" +#endif #include "weapon_csbase.h" #include "decals.h" #include "cs_gamerules.h" @@ -33,10 +36,8 @@ #include "obstacle_pushaway.h" #include "props_shared.h" -ConVar sv_showimpacts("sv_showimpacts", "0", FCVAR_REPLICATED, "Shows client (red) and server (blue) bullet impact point (1=both, 2=client-only, 3=server-only)" ); -ConVar weapon_accuracy_nospread( "weapon_accuracy_nospread", "0", FCVAR_REPLICATED ); -ConVar cl_showfirebullethitboxes( "cl_showfirebullethitboxes", "0" ); +ConVar weapon_accuracy_nospread( "weapon_accuracy_nospread", "0", FCVAR_REPLICATED ); #define CS_MASK_SHOOT (MASK_SOLID|CONTENTS_DEBRIS) void DispatchEffect( const char *pName, const CEffectData &data ); @@ -407,6 +408,8 @@ void CCSPlayer::FireBullet( if ( !pevAttacker ) pevAttacker = this; // the default attacker is ourselves + int iPenetrationCount = 0; + if ( weapon_accuracy_nospread.GetBool() ) { xSpread = 0.0f; @@ -461,22 +464,26 @@ void CCSPlayer::FireBullet( bool bFirstHit = true; CBasePlayer *lastPlayerHit = NULL; -#ifdef CLIENT_DLL - static ConVarRef cl_showhitboxes("cl_showhitboxes"); - if( cl_showhitboxes.GetBool() || cl_showfirebullethitboxes.GetBool() ) + if ( m_pCurrentCommand->debug_hitboxes == CUserCmd::DEBUG_HITBOXES_ON_BULLET ) { for (int i = 1; i <= gpGlobals->maxClients; i++) { - CBasePlayer *lagPlayer = UTIL_PlayerByIndex( i ); + CBasePlayer* lagPlayer = UTIL_PlayerByIndex(i); +#ifdef CLIENT_DLL if( lagPlayer && !lagPlayer->IsLocalPlayer() && IsLocalPlayer()) { lagPlayer->DrawClientHitboxes(60, true); lagPlayer->m_nTickBaseFireBullet = int(lagPlayer->GetTimeBase() / TICK_INTERVAL); } +#else + if( lagPlayer ) + { + lagPlayer->RecordServerHitboxes(this); + } +#endif } } -#endif MDLCACHE_CRITICAL_SECTION(); while ( fCurrentDamage > 0 ) { @@ -536,33 +543,33 @@ void CCSPlayer::FireBullet( // If we're a concrete grate (TOOLS/TOOLSINVISIBLE texture) allow more penetrating power. flPenetrationModifier = 1.0f; flDamageModifier = 0.99f; - } + } -#ifdef CLIENT_DLL - if ( sv_showimpacts.GetInt() == 1 || sv_showimpacts.GetInt() == 2 ) + if ( m_pCurrentCommand->debug_hitboxes == CUserCmd::DEBUG_HITBOXES_ON_HIT ) { +#ifdef CLIENT_DLL // draw red client impact markers - debugoverlay->AddBoxOverlay( tr.endpos, Vector(-g_bulletDiameter,-g_bulletDiameter,-g_bulletDiameter), Vector(g_bulletDiameter,g_bulletDiameter,g_bulletDiameter), QAngle( 0, 0, 0), 255,0,0,127, 4 ); + debugoverlay->AddBoxOverlay( tr.endpos, Vector(-g_bulletDiameter,-g_bulletDiameter,-g_bulletDiameter), Vector(g_bulletDiameter,g_bulletDiameter,g_bulletDiameter), QAngle( 0, 0, 0), 255,0,0,127, 60 ); if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) { C_BasePlayer *player = ToBasePlayer( tr.m_pEnt ); player->DrawClientHitboxes( 60, true ); + player->m_nTickBaseFireBullet = int(player->GetTimeBase() / TICK_INTERVAL); } - } + #else - if ( sv_showimpacts.GetInt() == 1 || sv_showimpacts.GetInt() == 3 ) - { - // draw blue server impact markers - NDebugOverlay::Box( tr.endpos, Vector(-g_bulletDiameter,-g_bulletDiameter,-g_bulletDiameter), Vector(g_bulletDiameter,g_bulletDiameter,g_bulletDiameter), 0,0,255,127, 4 ); + m_vecBulletPositions.Set(iPenetrationCount, tr.endpos); + iPenetrationCount++; + m_iBulletPositionCount.Set(iPenetrationCount); if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) { CBasePlayer *player = ToBasePlayer( tr.m_pEnt ); - player->DrawServerHitboxes( 60, true ); + player->RecordServerHitboxes( this ); } - } #endif + } //calculate the damage based on the distance the bullet travelled. flCurrentDistance += tr.fraction * flDistance; diff --git a/game/shared/usercmd.cpp b/game/shared/usercmd.cpp index 75a705ac3e..fc8ba9f292 100644 --- a/game/shared/usercmd.cpp +++ b/game/shared/usercmd.cpp @@ -10,6 +10,7 @@ #include "bitbuf.h" #include "checksum_md5.h" #include "const.h" +#include "platform.h" // memdbgon must be the last include file in a .cpp file!!! #ifdef CLIENT_DLL @@ -218,7 +219,7 @@ void WriteUsercmd( bf_write *buf, const CUserCmd *to, const CUserCmd *from ) if ( to->debug_hitboxes != from->debug_hitboxes ) { buf->WriteOneBit( 1 ); - buf->WriteOneBit( to->debug_hitboxes ); + buf->WriteByte( to->debug_hitboxes ); } else { @@ -376,7 +377,7 @@ void ReadUsercmd( bf_read *buf, CUserCmd *move, CUserCmd *from ) if ( buf->ReadOneBit() ) { - move->debug_hitboxes = buf->ReadOneBit(); + move->debug_hitboxes = (CUserCmd::debug_hitboxes_t)buf->ReadByte(); } #if defined( HL2_DLL ) diff --git a/game/shared/usercmd.h b/game/shared/usercmd.h index 0ecefca07a..161241d3db 100644 --- a/game/shared/usercmd.h +++ b/game/shared/usercmd.h @@ -106,7 +106,7 @@ public: { animationdata[i] = {}; } - debug_hitboxes = false; + debug_hitboxes = DEBUG_HITBOXES_OFF; #if defined( HL2_DLL ) || defined( HL2_CLIENT_DLL ) entitygroundcontact.RemoveAll(); #endif @@ -194,7 +194,7 @@ public: upmove = 0.f; buttons = 0; impulse = 0; - debug_hitboxes = false; + debug_hitboxes = DEBUG_HITBOXES_OFF; } // For matching server and client commands for debugging @@ -234,7 +234,16 @@ public: bool has_animation[MAX_EDICTS]; float simulationtimes[MAX_EDICTS]; ClientSideAnimationData animationdata[MAX_PLAYERS+1]; - bool debug_hitboxes; + + enum debug_hitboxes_t : uint8 + { + DEBUG_HITBOXES_OFF, + DEBUG_HITBOXES_ALWAYS_ON, + DEBUG_HITBOXES_ON_BULLET, + DEBUG_HITBOXES_ON_HIT + }; + + debug_hitboxes_t debug_hitboxes; // Back channel to communicate IK state #if defined( HL2_DLL ) || defined( HL2_CLIENT_DLL ) diff --git a/game/shared/util_shared.h b/game/shared/util_shared.h index 18f066c35d..ad0059703e 100644 --- a/game/shared/util_shared.h +++ b/game/shared/util_shared.h @@ -26,6 +26,8 @@ #include "portal_util_shared.h" #endif +#define MAX_PLAYER_BULLET_POSITIONS 128 + //----------------------------------------------------------------------------- // Forward declarations //-----------------------------------------------------------------------------