Reworked cl_show* commands to use game events instead

This commit is contained in:
Kamay Xutax 2024-07-25 18:10:35 +02:00
parent 73845dfe4c
commit 542b2c2711
25 changed files with 481 additions and 472 deletions

View file

@ -912,8 +912,9 @@ void DrawOverlay( OverlayBase_t *pOverlay )
case OVERLAY_SWEPT_BOX: case OVERLAY_SWEPT_BOX:
{ {
OverlaySweptBox_t *pBox = static_cast<OverlaySweptBox_t*>(pOverlay); OverlaySweptBox_t* pBox = static_cast<OverlaySweptBox_t*>(pOverlay);
RenderWireframeSweptBox( pBox->start, pBox->end, pBox->angles, pBox->mins, pBox->maxs, Color( pBox->r, pBox->g, pBox->b, pBox->a ), true ); 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; break;

View file

@ -9,6 +9,7 @@
#include "c_baseanimating.h" #include "c_baseanimating.h"
#include "c_sprite.h" #include "c_sprite.h"
#include "cdll_client_int.h" #include "cdll_client_int.h"
#include "convar.h"
#include "iconvar.h" #include "iconvar.h"
#include "interpolatedvar.h" #include "interpolatedvar.h"
#include "model_types.h" #include "model_types.h"
@ -200,9 +201,7 @@ IMPLEMENT_CLIENTCLASS_DT(C_BaseAnimating, DT_BaseAnimating, CBaseAnimating)
RecvPropFloat( RECVINFO( m_fadeMinDist ) ), RecvPropFloat( RECVINFO( m_fadeMinDist ) ),
RecvPropFloat( RECVINFO( m_fadeMaxDist ) ), RecvPropFloat( RECVINFO( m_fadeMaxDist ) ),
RecvPropFloat( RECVINFO( m_flFadeScale ) ), RecvPropFloat( RECVINFO( m_flFadeScale ) )
RecvPropArray3( RECVINFO_ARRAY(m_vecHitboxServerPositions), RecvPropVector(RECVINFO(m_vecHitboxServerPositions[0]))),
RecvPropArray3( RECVINFO_ARRAY(m_angHitboxServerAngles), RecvPropQAngles(RECVINFO(m_angHitboxServerAngles[0])))
END_RECV_TABLE() END_RECV_TABLE()
@ -4994,8 +4993,6 @@ void C_BaseAnimating::UpdateClientSideAnimation()
} }
} }
ConVar cl_showhitboxes("cl_showhitboxes", "0", FCVAR_CHEAT);
void C_BaseAnimating::Simulate() void C_BaseAnimating::Simulate()
{ {
if ( m_bInitModelEffects ) if ( m_bInitModelEffects )
@ -5574,25 +5571,40 @@ static Vector hullcolor[8] =
Vector( 1.0, 1.0, 1.0 ) 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 ) if ( !pStudioHdr )
return; return;
mstudiohitboxset_t *set =pStudioHdr->pHitboxSet( m_nHitboxSet ); mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( m_nHitboxSet );
if ( !set ) if ( !set )
return; return;
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, 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(); CStudioHdr *pStudioHdr = GetModelPtr();
if ( !pStudioHdr ) if ( !pStudioHdr )
@ -5609,34 +5621,6 @@ void C_BaseAnimating::DrawClientRecordedHitboxes( float duration /*= 0.0f*/, boo
int g = 255; int g = 255;
int b = 0; 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++ ) for ( int i = 0; i < set->numhitboxes; i++ )
{ {
mstudiobbox_t *pbox = set->pHitbox( 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: // Purpose:
// Input : activity - // Input : activity -

View file

@ -369,10 +369,8 @@ public:
int GetHitboxSet( void ); int GetHitboxSet( void );
char const *GetHitboxSetName( void ); char const *GetHitboxSetName( void );
int GetHitboxSetCount( 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 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(); C_BaseAnimating* FindFollowedEntity();
@ -642,12 +640,6 @@ private:
mutable CStudioHdr *m_pStudioHdr; mutable CStudioHdr *m_pStudioHdr;
mutable MDLHandle_t m_hStudioHdr; mutable MDLHandle_t m_hStudioHdr;
CThreadFastMutex m_StudioHdrInitLock; CThreadFastMutex m_StudioHdrInitLock;
public:
Vector m_vecHitboxServerPositions[MAXSTUDIOBONES];
QAngle m_angHitboxServerAngles[MAXSTUDIOBONES];
Vector m_vecHitboxClientPositions[MAXSTUDIOBONES];
QAngle m_angHitboxClientAngles[MAXSTUDIOBONES];
}; };
enum enum

View file

@ -252,11 +252,7 @@ END_RECV_TABLE()
RecvPropFloat ( RECVINFO( m_flDeathTime )), RecvPropFloat ( RECVINFO( m_flDeathTime )),
RecvPropInt ( RECVINFO( m_nWaterLevel ) ), RecvPropInt ( RECVINFO( m_nWaterLevel ) ),
RecvPropFloat ( RECVINFO( m_flLaggedMovementValue )), 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) ),
END_RECV_TABLE() END_RECV_TABLE()
@ -451,9 +447,6 @@ C_BasePlayer::C_BasePlayer() : m_iv_vecViewOffset( "C_BasePlayer::m_iv_vecViewOf
m_nForceVisionFilterFlags = 0; m_nForceVisionFilterFlags = 0;
ListenForGameEvent( "base_player_teleported" ); ListenForGameEvent( "base_player_teleported" );
m_lastBulletDiameter = 1.0f;
m_bDebugServerBullets = false;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -2141,196 +2134,6 @@ void C_BasePlayer::Simulate()
{ {
ResetLatched(); 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);
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View file

@ -639,14 +639,6 @@ public:
bool ShouldGoSouth( Vector vNPCForward, Vector vNPCRight ); //Such a bad name. bool ShouldGoSouth( Vector vNPCForward, Vector vNPCRight ); //Such a bad name.
void SetOldPlayerZ( float flOld ) { m_flOldPlayerZ = flOld; } void SetOldPlayerZ( float flOld ) { m_flOldPlayerZ = flOld; }
float m_lastBulletDiameter;
bool m_bDebugServerBullets;
CUtlVector<Vector> m_vecBulletServerPositions;
CUtlVector<Vector> m_vecServerShootPositions;
CUtlVector<int> m_touchedEntitiesWithBullet;
CUtlVector<Vector> m_vecBulletClientPositions;
CUtlVector<Vector> m_vecClientShootPositions;
}; };
EXTERN_RECV_TABLE(DT_BasePlayer); EXTERN_RECV_TABLE(DT_BasePlayer);

View file

@ -4,15 +4,19 @@
// //
//=============================================================================// //=============================================================================//
#include "KeyValues.h"
#include "cbase.h" #include "cbase.h"
#include "c_cs_player.h" #include "c_cs_player.h"
#include "c_user_message_register.h" #include "c_user_message_register.h"
#include "cdll_client_int.h" #include "cdll_client_int.h"
#include "convar.h"
#include "dt_recv.h" #include "dt_recv.h"
#include "iconvar.h" #include "iconvar.h"
#include "interpolatedvar.h" #include "interpolatedvar.h"
#include "mathlib/vector.h"
#include "shareddefs.h" #include "shareddefs.h"
#include "studio.h" #include "studio.h"
#include "util_shared.h"
#include "view.h" #include "view.h"
#include "iclientvehicle.h" #include "iclientvehicle.h"
#include "ivieweffects.h" #include "ivieweffects.h"
@ -79,6 +83,9 @@ extern ConVar spec_freeze_distance_max;
//============================================================================= //=============================================================================
// HPE_END // 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." ); 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_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_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 ); 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_delay;
extern ConVar mp_playerid_hold; extern ConVar mp_playerid_hold;
@ -783,6 +789,26 @@ C_CSPlayer::C_CSPlayer() :
view->SetScreenOverlayMaterial( NULL ); view->SetScreenOverlayMaterial( NULL );
m_bPlayingFreezeCamSound = false; 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 ); 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 ) void C_CSPlayer::SetActivity( Activity eActivity )
{ {
@ -2231,6 +2351,11 @@ void C_CSPlayer::Simulate( void )
} }
BaseClass::Simulate(); BaseClass::Simulate();
if ((cl_showhitboxes.GetInt() == 1 || cl_showhitboxes.GetInt() == 2) && !IsLocalPlayer())
{
DrawClientHitboxes(-1.0f, true);
}
} }
void C_CSPlayer::PostThink() void C_CSPlayer::PostThink()

View file

@ -123,6 +123,7 @@ public:
void PlayReloadEffect(); void PlayReloadEffect();
virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options ); virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
virtual void FireGameEvent(IGameEvent* event);
bool HasC4( void ); bool HasC4( void );
@ -380,7 +381,16 @@ private:
// HPE_END // 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 & ); C_CSPlayer( const C_CSPlayer & );
}; };

View file

@ -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 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 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; extern ConVar cl_mouselook;
#define UsingMouselook() cl_mouselook.GetBool() #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; cmd->simulationdata[pEntity->index].m_flSimulationTime = pEntity->m_flSimulationTime;
} }
#ifdef CSTRIKE_DLL
static ConVarRef cl_showhitboxes("cl_showhitboxes"); static ConVarRef cl_showhitboxes("cl_showhitboxes");
static ConVarRef debug_screenshot_bullet_position("debug_screenshot_bullet_position"); 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; cmd->debug_hitboxes = CUserCmd::DEBUG_HITBOXES_OFF;
if (cl_showhitboxes.GetBool()) 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; cmd->debug_hitboxes |= CUserCmd::DEBUG_HITBOXES_ON_HIT;
} }
#endif
pVerified->m_cmd = *cmd; pVerified->m_cmd = *cmd;
pVerified->m_crc = cmd->GetChecksum(); pVerified->m_crc = cmd->GetChecksum();

View file

@ -156,79 +156,6 @@ int CInfoLightingRelative::UpdateTransmitState( void )
return SetTransmitState( FL_EDICT_ALWAYS ); 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; static CIKSaveRestoreOps s_IKSaveRestoreOp;
@ -334,9 +261,7 @@ IMPLEMENT_SERVERCLASS_ST(CBaseAnimating, DT_BaseAnimating)
// Fading // Fading
SendPropFloat( SENDINFO( m_fadeMinDist ), 0, SPROP_NOSCALE ), SendPropFloat( SENDINFO( m_fadeMinDist ), 0, SPROP_NOSCALE ),
SendPropFloat( SENDINFO( m_fadeMaxDist ), 0, SPROP_NOSCALE ), SendPropFloat( SENDINFO( m_fadeMaxDist ), 0, SPROP_NOSCALE ),
SendPropFloat( SENDINFO( m_flFadeScale ), 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),
END_SEND_TABLE() END_SEND_TABLE()
@ -364,15 +289,6 @@ CBaseAnimating::CBaseAnimating()
m_fadeMaxDist = 0; m_fadeMaxDist = 0;
m_flFadeScale = 0.0f; m_flFadeScale = 0.0f;
m_fBoneCacheFlags = 0; 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() CBaseAnimating::~CBaseAnimating()
@ -3074,29 +2990,30 @@ static Vector hullcolor[8] =
Vector( 1.0, 1.0, 1.0 ) 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 ) if ( !pStudioHdr )
return; return 0;
mstudiohitboxset_t *set =pStudioHdr->pHitboxSet( m_nHitboxSet ); mstudiohitboxset_t *set =pStudioHdr->pHitboxSet( m_nHitboxSet );
if ( !set ) if ( !set )
return; return 0;
Vector position; int r = 0;
QAngle angles; int g = 0;
const auto localPlayerIndex = localPlayer->entindex(); 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; GetBonePosition( pbox->bone, position[pbox->bone], angles[pbox->bone] );
m_angHitboxServerAngles[localPlayerIndex][i] = angles; }
}
return set->numhitboxes;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View file

@ -6,6 +6,7 @@
#ifndef BASEANIMATING_H #ifndef BASEANIMATING_H
#define BASEANIMATING_H #define BASEANIMATING_H
#include "mathlib/vector.h"
#include "networkvar.h" #include "networkvar.h"
#include "shareddefs.h" #include "shareddefs.h"
#ifdef _WIN32 #ifdef _WIN32
@ -265,7 +266,7 @@ public:
virtual int DrawDebugTextOverlays( void ); virtual int DrawDebugTextOverlays( void );
// See note in code re: bandwidth usage!!! // 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 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 ); 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 ); CNetworkVar( int, m_nSequence );
CNetworkArray( float, m_flPoseParameter, NUM_POSEPAREMETERS ); // must be private so manual mode works! CNetworkArray( float, m_flPoseParameter, NUM_POSEPAREMETERS ); // must be private so manual mode works!
CNetworkArray( float, m_flEncodedController, NUM_BONECTRLS ); // bone controller setting (0..1) 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) // Client-side animation (useful for looping animation objects)
CNetworkVar( bool, m_bClientSideAnimation ); CNetworkVar( bool, m_bClientSideAnimation );

View file

@ -877,6 +877,9 @@ public:
void OnWeaponZoom( IGameEvent *event ); void OnWeaponZoom( IGameEvent *event );
void OnBulletImpact( IGameEvent *event ); void OnBulletImpact( IGameEvent *event );
void OnBulletHitPlayer( IGameEvent *event );
void OnBulletPlayerHitboxes( IGameEvent *event );
void OnPlayerLagHitboxes( IGameEvent *event );
void OnHEGrenadeDetonate( IGameEvent *event ); void OnHEGrenadeDetonate( IGameEvent *event );
void OnFlashbangDetonate( IGameEvent *event ); void OnFlashbangDetonate( IGameEvent *event );

View file

@ -198,6 +198,17 @@ void CCSBot::OnBulletImpact( IGameEvent *event )
//OnAudibleEvent( event, player, 1100.0f, PRIORITY_MEDIUM, true, false, &actualOrigin ); // bullet_impact //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 ) void CCSBot::OnBreakProp( IGameEvent *event )

View file

@ -116,7 +116,10 @@ CCSBotManager::CCSBotManager()
m_commonEventListeners.AddToTail( &m_WeaponFireOnEmptyEvent ); m_commonEventListeners.AddToTail( &m_WeaponFireOnEmptyEvent );
m_commonEventListeners.AddToTail( &m_WeaponReloadEvent ); m_commonEventListeners.AddToTail( &m_WeaponReloadEvent );
m_commonEventListeners.AddToTail( &m_WeaponZoomEvent ); 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_GrenadeBounceEvent );
m_commonEventListeners.AddToTail( &m_NavBlockedEvent ); m_commonEventListeners.AddToTail( &m_NavBlockedEvent );
@ -2004,6 +2007,20 @@ void CCSBotManager::OnBulletImpact( IGameEvent *event )
CCSBOTMANAGER_ITERATE_BOTS( OnBulletImpact, 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 ) void CCSBotManager::OnHEGrenadeDetonate( IGameEvent *event )

View file

@ -362,6 +362,9 @@ private:
DECLARE_CSBOTMANAGER_EVENT_LISTENER( WeaponZoom, weapon_zoom ) DECLARE_CSBOTMANAGER_EVENT_LISTENER( WeaponZoom, weapon_zoom )
DECLARE_CSBOTMANAGER_EVENT_LISTENER( BulletImpact, bullet_impact ) 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( HEGrenadeDetonate, hegrenade_detonate )
DECLARE_CSBOTMANAGER_EVENT_LISTENER( FlashbangDetonate, flashbang_detonate ) DECLARE_CSBOTMANAGER_EVENT_LISTENER( FlashbangDetonate, flashbang_detonate )

View file

@ -50,7 +50,6 @@ public:
ListenForGameEvent( "hostage_killed" ); ListenForGameEvent( "hostage_killed" );
ListenForGameEvent( "hostage_follows" ); ListenForGameEvent( "hostage_follows" );
ListenForGameEvent( "player_hurt" ); ListenForGameEvent( "player_hurt" );
ListenForGameEvent( "bullet_impact" );
return true; return true;
} }

View file

@ -57,6 +57,7 @@
#include "gamestats.h" #include "gamestats.h"
#include "holiday_gift.h" #include "holiday_gift.h"
#include "../../shared/cstrike/cs_achievement_constants.h" #include "../../shared/cstrike/cs_achievement_constants.h"
#include "ilagcompensationmanager.h"
//============================================================================= //=============================================================================
// HPE_BEGIN // HPE_BEGIN
@ -506,7 +507,6 @@ CCSPlayer::CCSPlayer()
m_vLastHitLocationObjectSpace = Vector(0,0,0); m_vLastHitLocationObjectSpace = Vector(0,0,0);
m_wasNotKilledNaturally = false; m_wasNotKilledNaturally = false;
//============================================================================= //=============================================================================
// HPE_END // HPE_END
//============================================================================= //=============================================================================
@ -1585,7 +1585,57 @@ void CCSPlayer::UpdateMouseoverHints()
} }
void CCSPlayer::PostThink() 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(); BaseClass::PostThink();
UpdateAddonBits(); UpdateAddonBits();

View file

@ -294,7 +294,7 @@ public:
virtual CWeaponCSBase* CSAnim_GetActiveWeapon(); virtual CWeaponCSBase* CSAnim_GetActiveWeapon();
virtual bool CSAnim_CanMove(); virtual bool CSAnim_CanMove();
virtual float GetPlayerMaxSpeed(); virtual float GetPlayerMaxSpeed();
void FireBullet( void FireBullet(
int iBullet, int iBullet,
@ -1037,7 +1037,6 @@ private:
// HPE_END // HPE_END
//============================================================================= //=============================================================================
int m_iDeathFlags; // Flags holding revenge and domination info about a death int m_iDeathFlags; // Flags holding revenge and domination info about a death
//============================================================================= //=============================================================================
// HPE_END // HPE_END
//============================================================================= //=============================================================================

View file

@ -4522,7 +4522,6 @@ void CBasePlayer::ForceOrigin( const Vector &vecOrigin )
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CBasePlayer::PostThink() void CBasePlayer::PostThink()
{ {
m_bDebugServerBullets = false;
m_vecSmoothedVelocity = m_vecSmoothedVelocity * SMOOTHING_FACTOR + GetAbsVelocity() * ( 1 - SMOOTHING_FACTOR ); m_vecSmoothedVelocity = m_vecSmoothedVelocity * SMOOTHING_FACTOR + GetAbsVelocity() * ( 1 - SMOOTHING_FACTOR );
if ( !g_fGameOver && !m_iPlayerLocked ) if ( !g_fGameOver && !m_iPlayerLocked )
@ -7973,11 +7972,7 @@ void CMovementSpeedMod::InputSpeedMod(inputdata_t &data)
SendPropFloat ( SENDINFO( m_flDeathTime ), 0, SPROP_NOSCALE ), SendPropFloat ( SENDINFO( m_flDeathTime ), 0, SPROP_NOSCALE ),
SendPropInt ( SENDINFO( m_nWaterLevel ), 2, SPROP_UNSIGNED ), SendPropInt ( SENDINFO( m_nWaterLevel ), 2, SPROP_UNSIGNED ),
SendPropFloat ( SENDINFO( m_flLaggedMovementValue ), 0, SPROP_NOSCALE ), 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)),
END_SEND_TABLE() END_SEND_TABLE()

View file

@ -1211,10 +1211,6 @@ private:
public: 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 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<Vector> m_vecBulletServerPositions;
CUtlVector<Vector> m_vecServerShootPositions;
CUtlVector<int> m_touchedEntitiesWithBullet;
}; };
typedef CHandle<CBasePlayer> CBasePlayerHandle; typedef CHandle<CBasePlayer> CBasePlayerHandle;

View file

@ -346,23 +346,6 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper
g_pGameMovement->StartTrackPredictionErrors( player ); 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 ); RunPostThink( player );
// Prevent hacked clients from sending us invalid view angles to try to get leaf server code to crash // Prevent hacked clients from sending us invalid view angles to try to get leaf server code to crash

View file

@ -6,6 +6,7 @@
#include "cbase.h" #include "cbase.h"
#include "debugoverlay_shared.h" #include "debugoverlay_shared.h"
#include "strtools.h"
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
#include "player.h" #include "player.h"
#else #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( void CCSPlayer::FireBullet(
int iBullet, // bullet number int iBullet, // bullet number
Vector vecSrc, // shooting postion Vector vecSrc, // shooting postion
@ -450,8 +467,8 @@ void CCSPlayer::FireBullet(
float flBulletRadius = flBulletDiameter / 2.0f; float flBulletRadius = flBulletDiameter / 2.0f;
Vector vecBulletRadiusMaxs(flBulletRadius, flBulletRadius, flBulletRadius); Vector vecBulletRadiusMaxs(flBulletRadius);
Vector vecBulletRadiusMins(-flBulletRadius, -flBulletRadius, -flBulletRadius); Vector vecBulletRadiusMins(-flBulletRadius);
if ( !pevAttacker ) if ( !pevAttacker )
pevAttacker = this; // the default attacker is ourselves pevAttacker = this; // the default attacker is ourselves
@ -489,27 +506,68 @@ void CCSPlayer::FireBullet(
CBasePlayer *lastPlayerHit = NULL; CBasePlayer *lastPlayerHit = NULL;
MDLCACHE_CRITICAL_SECTION(); MDLCACHE_CRITICAL_SECTION();
bool shouldTakeAllPlayers = m_pCurrentCommand->debug_hitboxes & CUserCmd::DEBUG_HITBOXES_ON_FIRE; bool shouldDebugHitboxesOnFire = m_pCurrentCommand->debug_hitboxes & CUserCmd::DEBUG_HITBOXES_ON_FIRE;
bool shouldTakeHitPlayer = m_pCurrentCommand->debug_hitboxes & CUserCmd::DEBUG_HITBOXES_ON_HIT; 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++) for (int i = 1; i <= gpGlobals->maxClients; i++)
{ {
CBasePlayer* lagPlayer = UTIL_PlayerByIndex(i); CBasePlayer* lagPlayer = UTIL_PlayerByIndex(i);
if (lagPlayer && lagPlayer != this)
if( lagPlayer )
{ {
#ifdef CLIENT_DLL #ifdef CLIENT_DLL
if (!m_pCurrentCommand->hasbeenpredicted) if (!m_pCurrentCommand->hasbeenpredicted)
{ {
lagPlayer->RecordClientHitboxes(); lagPlayer->DrawClientHitboxes(m_flDebugDuration, true);
} }
#else #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 #endif
} }
} }
} }
while ( fCurrentDamage > 0 ) while ( fCurrentDamage > 0 )
@ -556,32 +614,80 @@ void CCSPlayer::FireBullet(
flDamageModifier = 0.99f; flDamageModifier = 0.99f;
} }
if (shouldTakeHitPlayer) if (shouldDebugHitboxesOnHit)
{ {
#ifndef CLIENT_DLL #ifdef CLIENT_DLL
m_vecBulletServerPositions.AddToTail(tr.endpos); if (!m_pCurrentCommand->hasbeenpredicted)
m_vecServerShootPositions.AddToTail(vecSrc);
#else
m_vecBulletClientPositions.AddToTail(tr.endpos);
m_vecClientShootPositions.AddToTail(vecSrc);
#endif
if (tr.m_pEnt)
{ {
#ifndef CLIENT_DLL DrawBullet(vecSrc,
m_touchedEntitiesWithBullet.AddToTail(tr.m_pEnt->entindex()); 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 #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); lagPlayer->DrawClientHitboxes(m_flDebugDuration, true);
#ifdef CLIENT_DLL
if (!m_pCurrentCommand->hasbeenpredicted)
{
player->RecordClientHitboxes();
}
#else
player->RecordServerHitboxes(this);
#endif
} }
#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
} }
} }

View file

@ -291,18 +291,9 @@ void FX_FireBullets(
y1[iBullet] = fRadius1 * sinf(fTheta1); 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++ ) 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 #ifdef CLIENT_DLL
static ConVarRef debug_screenshot_bullet_position("debug_screenshot_bullet_position");
if (pPlayer->IsLocalPlayer() && debug_screenshot_bullet_position.GetBool()) if (pPlayer->IsLocalPlayer() && debug_screenshot_bullet_position.GetBool())
{ {
gpGlobals->client_taking_screenshot = true; gpGlobals->client_taking_screenshot = true;

View file

@ -134,6 +134,7 @@ public:
// write/read event to/from bitbuffer // write/read event to/from bitbuffer
virtual bool SerializeEvent( IGameEvent *event, bf_write *buf ) = 0; virtual bool SerializeEvent( IGameEvent *event, bf_write *buf ) = 0;
virtual IGameEvent *UnserializeEvent( bf_read *buf ) = 0; // create new KeyValues, must be deleted 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: // the old game event manager interface, don't use it. Rest is legacy support:

View file

@ -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 ); void RenderWireframeBox( const Vector &vOrigin, const QAngle& angles, const Vector &vMins, const Vector &vMaxs, Color c, bool bZBuffer );
// Renders a swept wireframe box // 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 ); 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 // Renders a solid box

View file

@ -664,6 +664,73 @@ static void DrawExtrusionFace( const Vector& start, const Vector& end,
meshBuilder.AdvanceVertex(); 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 ) void RenderWireframeSweptBox( const Vector &vStart, const Vector &vEnd, const QAngle &angles, const Vector &vMins, const Vector &vMaxs, Color c, bool bZBuffer )
{ {
InitializeStandardMaterials(); InitializeStandardMaterials();