Improved show hitboxes commands and networked m_fFlags from animoverlays

This commit is contained in:
Kamay Xutax 2024-09-01 23:55:01 +02:00
parent 867f106584
commit be7d8cc228
16 changed files with 465 additions and 285 deletions

View file

@ -19,16 +19,16 @@
#include "proto_version.h"
// Flow control bytes per second limits
#define MAX_RATE (16777216)
#define MAX_RATE (67108864)
#define MIN_RATE 1000
#define DEFAULT_RATE 80000
#define DEFAULT_RATE 67108864
#define SIGNON_TIME_OUT 300.0f // signon disconnect timeout
#define FRAGMENT_BITS 8
#define FRAGMENT_SIZE (1<<FRAGMENT_BITS)
#define MAX_FILE_SIZE_BITS 26
#define MAX_FILE_SIZE ((1<<MAX_FILE_SIZE_BITS)-1) // maximum transferable size is 64MB
#define MAX_FILE_SIZE_BITS 30
#define MAX_FILE_SIZE ((1<<MAX_FILE_SIZE_BITS)-1) // maximum transferable size is 1GB
// 0 == regular, 1 == file stream
#define MAX_STREAMS 2

View file

@ -56,8 +56,8 @@ ConVar engine_no_focus_sleep( "engine_no_focus_sleep", "50", FCVAR_ARCHIVE );
// sleep time when not focus
#define NOT_FOCUS_SLEEP 50
#define DEFAULT_FPS_MAX 300
#define DEFAULT_FPS_MAX_S "300"
#define DEFAULT_FPS_MAX 0
#define DEFAULT_FPS_MAX_S "0"
static int s_nDesiredFPSMax = DEFAULT_FPS_MAX;
static bool s_bFPSMaxDrivenByPowerSavings = false;

View file

@ -15,6 +15,13 @@
#include "lerp_functions.h"
#include "networkvar.h"
#define ANIM_LAYER_ACTIVE 0x0001
#define ANIM_LAYER_AUTOKILL 0x0002
#define ANIM_LAYER_KILLME 0x0004
#define ANIM_LAYER_DONTRESTORE 0x0008
#define ANIM_LAYER_CHECKACCESS 0x0010
#define ANIM_LAYER_DYING 0x0020
class C_AnimationLayer
{
public:
@ -29,12 +36,20 @@ public:
public:
bool IsActive( void );
bool IsActive( void ) { return ((m_fFlags & ANIM_LAYER_ACTIVE) != 0); }
bool IsAutokill( void ) { return ((m_fFlags & ANIM_LAYER_AUTOKILL) != 0); }
bool IsKillMe( void ) { return ((m_fFlags & ANIM_LAYER_KILLME) != 0); }
bool IsAutoramp( void ) { return (m_flBlendIn != 0.0 || m_flBlendOut != 0.0); }
void KillMe( void ) { m_fFlags |= ANIM_LAYER_KILLME; }
void Dying( void ) { m_fFlags |= ANIM_LAYER_DYING; }
bool IsDying( void ) { return ((m_fFlags & ANIM_LAYER_DYING) != 0); }
void Dead( void ) { m_fFlags &= ~ANIM_LAYER_DYING; }
CRangeCheckedVar<int, -1, 65535, 0> m_nSequence;
CRangeCheckedVar<float, -2, 2, 0> m_flPrevCycle;
CRangeCheckedVar<float, -5, 5, 0> m_flWeight;
int m_nOrder;
CRangeCheckedVar< int, -1, 65535, 0 > m_nSequence;
CRangeCheckedVar< float, -2, 2, 0 > m_flPrevCycle;
CRangeCheckedVar< float, -5, 5, 0 > m_flWeight;
int m_nOrder;
int m_fFlags;
// used for automatic crossfades between sequence changes
CRangeCheckedVar<float, -50, 50, 1> m_flPlaybackRate;
@ -75,7 +90,6 @@ inline void C_AnimationLayer::Reset()
m_bClientBlend = false;
}
inline void C_AnimationLayer::SetOrder( int order )
{
m_nOrder = order;
@ -85,15 +99,15 @@ inline float C_AnimationLayer::GetFadeout( float flCurTime )
{
float s;
if (m_flLayerFadeOuttime <= 0.0f)
if ( m_flLayerFadeOuttime <= 0.0f )
{
s = 0;
}
else
{
// blend in over 0.2 seconds
s = 1.0 - (flCurTime - m_flLayerAnimtime) / m_flLayerFadeOuttime;
if (s > 0 && s <= 1.0)
s = 1.0 - ( flCurTime - m_flLayerAnimtime ) / m_flLayerFadeOuttime;
if ( s > 0 && s <= 1.0 )
{
// do a nice spline curve
s = 3 * s * s - 2 * s * s * s;
@ -107,7 +121,6 @@ inline float C_AnimationLayer::GetFadeout( float flCurTime )
return s;
}
inline C_AnimationLayer LoopingLerp( float flPercent, C_AnimationLayer& from, C_AnimationLayer& to )
{
C_AnimationLayer output;

View file

@ -96,11 +96,6 @@ void VCollideWireframe_ChangeCallback( IConVar *pConVar, char const *pOldString,
ConVar vcollide_wireframe( "vcollide_wireframe", "0", FCVAR_CHEAT, "Render physics collision models in wireframe", VCollideWireframe_ChangeCallback );
bool C_AnimationLayer::IsActive( void )
{
return (m_nOrder != C_BaseAnimatingOverlay::MAX_OVERLAYS);
}
//-----------------------------------------------------------------------------
// Relative lighting entity
//-----------------------------------------------------------------------------
@ -3433,7 +3428,7 @@ void C_BaseAnimating::DoAnimationEvents( CStudioHdr *pStudioHdr )
if ( nSeqNum >= nStudioNumSeq )
{
// This can happen e.g. while reloading Heavy's shotgun, switch to the minigun.
Warning( "%s[%d]: Playing sequence %d but there's only %d in total?\n", GetDebugName(), entindex(), nSeqNum, nStudioNumSeq );
DevMsg( "%s[%d]: Playing sequence %d but there's only %d in total?\n", GetDebugName(), entindex(), nSeqNum, nStudioNumSeq );
return;
}
@ -5552,20 +5547,47 @@ void C_BaseAnimating::DrawClientHitboxes( float duration /*= 0.0f*/, bool monoco
int g = 255;
int b = 0;
if ( !monocolor )
{
g = 0;
r = 255;
}
// printf( "got sequence: %i, cycle: %f\n", GetSequence(), GetCycle() );
// for ( int i = 0; i < pStudioHdr->GetNumPoseParameters(); i++ )
// {
// printf( "pose_param_%i: %f\n", i, GetPoseParameter( i ) );
// }
// float bc[MAXSTUDIOBONECTRLS];
// GetBoneControllers(bc);
// for ( int i = 0; i < pStudioHdr->GetNumBoneControllers(); i++ )
// {
// printf( "bone_controller_%i: %f\n", i, bc[i] );
// }
// C_BasePlayer* player = ( C_BasePlayer* )this;
// if ( player->IsPlayer() )
// {
// for ( int i = 0; i < player->GetNumAnimOverlays(); i++ )
// {
// auto animOverlay = player->GetAnimOverlay( i );
// printf( "anim_overlay_cycle_%i: %f\n", i, animOverlay->m_flCycle.GetRaw() );
// printf( "anim_overlay_sequence_%i: %i\n", i, animOverlay->m_nSequence.GetRaw() );
// printf( "anim_overlay_weight_%i: %f\n", i, animOverlay->m_flWeight.GetRaw() );
// printf( "anim_overlay_order_%i: %i\n", i, animOverlay->m_nOrder );
// }
// }
for ( int i = 0; i < set->numhitboxes; i++ )
{
mstudiobbox_t *pbox = set->pHitbox( i );
GetBonePosition( pbox->bone, position, angles );
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->bbmin, pbox->bbmax, angles, r, g, b, 127 ,duration );
}
}

View file

@ -44,7 +44,8 @@ BEGIN_RECV_TABLE_NOBASE(CAnimationLayer, DT_Animationlayer)
RecvPropFloat( RECVINFO_NAME(m_flCycle, m_flCycle)),
RecvPropFloat( RECVINFO_NAME(m_flPrevCycle, m_flPrevCycle)),
RecvPropFloat( RECVINFO_NAME(m_flWeight, m_flWeight)),
RecvPropInt( RECVINFO_NAME(m_nOrder, m_nOrder))
RecvPropInt( RECVINFO_NAME(m_nOrder, m_nOrder)),
RecvPropInt( RECVINFO_NAME(m_fFlags, m_fFlags)),
END_RECV_TABLE()
const char *s_m_iv_AnimOverlayNames[C_BaseAnimatingOverlay::MAX_OVERLAYS] =

View file

@ -2113,93 +2113,218 @@ void C_CSPlayer::FireEvent( const Vector& origin, const QAngle& angles, int even
BaseClass::FireEvent( origin, angles, event, options );
}
void C_CSPlayer::FireGameEvent(IGameEvent* event)
ConVar cl_debug_duration( "cl_debug_duration", "60" );
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");
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;
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);
BaseClass::FireGameEvent( event );
if (player && !player->IsLocalPlayer())
{
const auto numhitboxes = event->GetInt("num_hitboxes");
QAngle angles[MAXSTUDIOBONES];
Vector positions[MAXSTUDIOBONES];
bool shouldShowImpacts = cl_showimpacts.GetInt() == 1 || cl_showimpacts.GetInt() == 3;
bool shouldShowFireBulletHitboxes = cl_showfirebullethitboxes.GetInt() == 1
|| cl_showfirebullethitboxes.GetInt() == 3;
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 auto ShowEventHitboxes = [&]( float flDuration )
{
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");
{
const auto playerIndex = event->GetInt( "player_index" );
const auto player = UTIL_PlayerByIndex( playerIndex );
Vector mins(-flBulletRadius);
Vector maxs(flBulletRadius);
if ( player && !player->IsLocalPlayer() )
{
const auto numhitboxes = event->GetInt( "num_hitboxes" );
QAngle angles[MAXSTUDIOBONES];
Vector positions[MAXSTUDIOBONES];
DrawBullet(src, dst, mins, maxs, 0, 0, 255, 127, m_flDebugDuration);
for ( int i = 0; i < numhitboxes; i++ )
{
char buffer[256];
V_sprintf_safe( buffer, "hitbox_index_%i", i );
const auto hitboxIndex = event->GetInt( buffer );
// 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);
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 );
// 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);
}
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 );
// Let's see what the client thinks to check if there's any problems with hitboxes
float flBackupPoseParams[MAXSTUDIOPOSEPARAM];
float flBackupBoneControllers[MAXSTUDIOBONECTRLS];
C_AnimationLayer backupAnimLayers[C_BaseAnimatingOverlay::MAX_OVERLAYS];
Vector vecBackupPosition = player->GetAbsOrigin();
QAngle angBackupAngles = player->GetAbsAngles();
auto flOldCycle = GetCycle();
auto iOldSequence = GetSequence();
auto pStudioHdr = GetModelPtr();
player->GetPoseParameters( pStudioHdr, flBackupPoseParams );
player->GetBoneControllers( flBackupBoneControllers );
for ( int i = 0; i < GetNumAnimOverlays(); i++ )
{
backupAnimLayers[i] = m_AnimOverlay[i];
}
player->SetSequence( event->GetInt( "sequence" ) );
player->SetCycle( event->GetFloat( "cycle" ) );
// printf("was sequence: %i, cycle: %f\n", player->GetSequence(), player->GetCycle() );
// Set setup bones modifiers
player->SetAbsOrigin( Vector( event->GetFloat( "position_x" ),
event->GetFloat( "position_y" ),
event->GetFloat( "position_z" ) ) );
player->SetAbsAngles( QAngle( event->GetFloat( "angle_x" ),
event->GetFloat( "angle_y" ),
event->GetFloat( "angle_z" ) ) );
const auto numposeparams = event->GetInt( "num_poseparams" );
Assert( numposeparams == pStudioHdr->GetNumPoseParameters() );
for ( int i = 0; i < numposeparams; i++ )
{
char buffer[256];
V_sprintf_safe( buffer, "pose_param_%i", i );
player->SetPoseParameter( i, event->GetFloat( buffer ) );
// printf("pose_param_%i: %f\n", i, player->GetPoseParameter(i) );
}
const auto numbonecontrollers = event->GetInt( "num_bonecontrollers" );
Assert( numbonecontrollers == pStudioHdr->GetNumBoneControllers() );
for ( int i = 0; i < numbonecontrollers; i++ )
{
char buffer[256];
V_sprintf_safe( buffer, "bone_controller_%i", i );
player->SetBoneController( i, event->GetFloat( buffer ) );
float tmp[MAXSTUDIOBONECTRLS];
player->GetBoneControllers( tmp );
// printf( "bone_controller_%i: %f\n", i, tmp[i] );
}
auto numanimoverlays = event->GetInt( "num_anim_overlays" );
Assert( num_anim_overlays == player->GetNumAnimOverlays() );
for ( int i = 0; i < numanimoverlays; i++ )
{
auto animOverlay = player->GetAnimOverlay( i );
char buffer[256];
V_sprintf_safe( buffer, "anim_overlay_cycle_%i", i );
animOverlay->m_flCycle = event->GetFloat( buffer );
// printf( "anim_overlay_cycle_%i: %f\n", i, animOverlay->m_flCycle.GetRaw() );
V_sprintf_safe( buffer, "anim_overlay_sequence_%i", i );
animOverlay->m_nSequence = event->GetInt( buffer );
// printf( "anim_overlay_sequence_%i: %i\n", i, animOverlay->m_nSequence.GetRaw() );
V_sprintf_safe( buffer, "anim_overlay_weight_%i", i );
animOverlay->m_flWeight = event->GetFloat( buffer );
// printf( "anim_overlay_weight_%i: %f\n", i,animOverlay->m_flWeight.GetRaw() );
V_sprintf_safe( buffer, "anim_overlay_order_%i", i );
animOverlay->m_nOrder = event->GetInt( buffer );
// printf( "anim_overlay_order_%i: %i\n", i, animOverlay->m_nOrder );
}
PushAllowBoneAccess( true, false, "Lag compensation context" );
// Be sure we setup the bones again.
player->InvalidateBoneCache();
player->SetupBones( NULL,
MAXSTUDIOBONES,
BONE_USED_BY_HITBOX | BONE_USED_BY_ATTACHMENT | BONE_USED_BY_BONE_MERGE,
gpGlobals->curtime );
player->DrawClientHitboxes( cl_debug_duration.GetFloat(), false );
// Re-invalidate bone cache for the next frame
player->InvalidateBoneCache();
PopBoneAccess( "Lag compensation context" );
// Set back original stuff.
player->SetSequence( iOldSequence );
player->SetCycle( flOldCycle );
player->SetAbsOrigin( vecBackupPosition );
player->SetAbsAngles( angBackupAngles );
for ( int i = 0; i < numposeparams; i++ )
{
player->SetPoseParameter( i, flBackupPoseParams[i] );
}
for ( int i = 0; i < numbonecontrollers; i++ )
{
player->SetBoneController( i, flBackupBoneControllers[i] );
}
for ( int i = 0; i < numanimoverlays; i++ )
{
auto animOverlay = player->GetAnimOverlay( i );
animOverlay->m_flCycle = backupAnimLayers[i].m_flCycle;
animOverlay->m_nSequence = backupAnimLayers[i].m_nSequence;
animOverlay->m_flWeight = backupAnimLayers[i].m_flWeight;
animOverlay->m_nOrder = backupAnimLayers[i].m_nOrder;
}
}
}
};
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, cl_debug_duration.GetFloat() );
// 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( cl_debug_duration.GetFloat() );
// 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( cl_debug_duration.GetFloat() );
}
}
@ -2574,9 +2699,17 @@ float C_CSPlayer::GetDeathCamInterpolationTime()
}
bool C_CSPlayer::SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, int boneMask, float currentTime )
bool C_CSPlayer::SetupBones( matrix3x4_t* pBoneToWorldOut, int nMaxBones, int boneMask, float currentTime )
{
return BaseClass::SetupBones( pBoneToWorldOut, nMaxBones, boneMask, currentTime );
// Just in case.
float oldCurtime = gpGlobals->curtime;
gpGlobals->curtime = currentTime;
auto ret = BaseClass::SetupBones( pBoneToWorldOut, nMaxBones, boneMask, currentTime );
gpGlobals->curtime = oldCurtime;
return ret;
}
//=============================================================================

View file

@ -381,7 +381,6 @@ private:
// HPE_END
//=============================================================================
static constexpr auto m_flDebugDuration = 60.f;
void DrawBullet(const Vector& src,
const Vector& endpos,
const Vector& mins,

View file

@ -1320,7 +1320,7 @@ void CInput::CreateMove ( int sequence_number, float input_sample_frametime, boo
}
cmd->simulationdata[pEntity->index].lerp_time = pEntity->m_flInterpolatedSimulationTime;
cmd->simulationdata[pEntity->index].animated_sim_time = pEntity->m_flSimulationTime;
cmd->simulationdata[pEntity->index].animated_sim_time = pEntity->m_flAnimTime;
cmd->simulationdata[pEntity->index].entityexists = true;
}

View file

@ -67,6 +67,7 @@ BEGIN_SEND_TABLE_NOBASE(CAnimationLayer, DT_Animationlayer)
SendPropFloat (SENDINFO(m_flPrevCycle)),
SendPropFloat (SENDINFO(m_flWeight)),
SendPropInt (SENDINFO(m_nOrder)),
SendPropInt (SENDINFO(m_fFlags)),
END_SEND_TABLE()

View file

@ -44,7 +44,7 @@ public:
#define ANIM_LAYER_CHECKACCESS 0x0010
#define ANIM_LAYER_DYING 0x0020
int m_fFlags;
CNetworkVar( int, m_fFlags );
bool m_bSequenceFinished;
bool m_bLooping;

View file

@ -2805,23 +2805,14 @@ CBoneCache *CBaseAnimating::GetBoneCache( void )
CStudioHdr *pStudioHdr = GetModelPtr( );
Assert(pStudioHdr);
// Use this for lag compensation
float oldcurtime = gpGlobals->curtime;
gpGlobals->curtime = m_flSimulationTime;
CBoneCache *pcache = Studio_GetBoneCache( m_boneCacheHandle );
int boneMask = BONE_USED_BY_ANYTHING;
int boneMask = BONE_USED_BY_BONE_MERGE | BONE_USED_BY_HITBOX | BONE_USED_BY_ATTACHMENT;
// TF queries these bones to position weapons when players are killed
#if defined( TF_DLL )
boneMask |= BONE_USED_BY_BONE_MERGE;
#endif
if ( pcache )
{
// Only validate for current time.
if ( (pcache->m_boneMask & boneMask) == boneMask && pcache->m_timeValid == gpGlobals->curtime)
{
gpGlobals->curtime = oldcurtime;
// Msg("%s:%s:%s (%x:%x:%8.4f) cache\n", GetClassname(), GetDebugName(), STRING(GetModelName()), boneMask, pcache->m_boneMask, pcache->m_timeValid );
// in memory and still valid, use it!
return pcache;
@ -2856,7 +2847,6 @@ CBoneCache *CBaseAnimating::GetBoneCache( void )
}
Assert(pcache);
gpGlobals->curtime = oldcurtime;
return pcache;
}

View file

@ -1,6 +1,6 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
@ -41,6 +41,24 @@ ConVar sv_lagflushbonecache( "sv_lagflushbonecache", "0", 0, "Flushes entity bon
// Purpose:
//-----------------------------------------------------------------------------
struct LayerRecord
{
int m_sequence;
float m_cycle;
float m_weight;
int m_order;
int m_flags;
LayerRecord()
{
m_sequence = 0;
m_cycle = 0;
m_weight = 0;
m_order = 0;
m_flags = 0;
}
};
struct LagRecord
{
public:
@ -86,7 +104,7 @@ struct LagRecord
{
m_layerRecords[layerIndex] = src.m_layerRecords[layerIndex];
}
m_masterSequence = src.m_masterSequence;
m_masterCycle = src.m_masterCycle;
@ -280,6 +298,7 @@ void CLagCompensationManager::TrackPlayerData( CBasePlayer* pPlayer )
record.m_layerRecords[layerIndex].m_order = currentLayer->m_nOrder;
record.m_layerRecords[layerIndex].m_sequence = currentLayer->m_nSequence;
record.m_layerRecords[layerIndex].m_weight = currentLayer->m_flWeight;
record.m_layerRecords[layerIndex].m_flags = currentLayer->m_fFlags;
}
}
@ -412,7 +431,7 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer* pPlayer, CUserCmd* c
break;
}
if ( recordAnim->m_flSimulationTime == flTargetAnimatedSimulationTime )
if ( recordAnim->m_flAnimTime == flTargetAnimatedSimulationTime )
{
break;
}
@ -528,11 +547,13 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer* pPlayer, CUserCmd* c
restore->m_layerRecords[layerIndex].m_order = currentLayer->m_nOrder;
restore->m_layerRecords[layerIndex].m_sequence = currentLayer->m_nSequence;
restore->m_layerRecords[layerIndex].m_weight = currentLayer->m_flWeight;
restore->m_layerRecords[layerIndex].m_flags = currentLayer->m_fFlags;
currentLayer->m_flCycle = recordAnim->m_layerRecords[layerIndex].m_cycle;
currentLayer->m_nOrder = recordAnim->m_layerRecords[layerIndex].m_order;
currentLayer->m_nSequence = recordAnim->m_layerRecords[layerIndex].m_sequence;
currentLayer->m_flWeight = recordAnim->m_layerRecords[layerIndex].m_weight;
currentLayer->m_fFlags = recordAnim->m_layerRecords[layerIndex].m_flags;
}
}
@ -558,7 +579,7 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer* pPlayer, CUserCmd* c
for ( int encIndex = 0; encIndex < hdr->GetNumBoneControllers(); encIndex++ )
{
restore->m_encodedControllers[encIndex] = pPlayer->GetBoneControllerArray()[encIndex];
float encodedController = recordAnim->m_encodedControllers[encIndex];
float encodedController = recordAnim->m_encodedControllers[encIndex];
pPlayer->SetBoneControllerRaw( encIndex, encodedController );
}
@ -662,6 +683,7 @@ void CLagCompensationManager::FinishLagCompensation( CBasePlayer* player )
currentLayer->m_nOrder = restore->m_layerRecords[layerIndex].m_order;
currentLayer->m_nSequence = restore->m_layerRecords[layerIndex].m_sequence;
currentLayer->m_flWeight = restore->m_layerRecords[layerIndex].m_weight;
currentLayer->m_fFlags = restore->m_layerRecords[layerIndex].m_flags;
}
}
}

View file

@ -39,7 +39,6 @@
#include "engine/ivdebugoverlay.h"
#include "obstacle_pushaway.h"
#include "props_shared.h"
// #include <iostream>
ConVar weapon_accuracy_nospread( "weapon_accuracy_nospread", "0", FCVAR_REPLICATED );
#define CS_MASK_SHOOT (MASK_SOLID|CONTENTS_DEBRIS)
@ -422,6 +421,7 @@ inline void UTIL_TraceLineIgnoreTwoEntities(const Vector& vecAbsStart, const Vec
}
#ifdef CLIENT_DLL
extern ConVar cl_debug_duration;
void CCSPlayer::DrawBullet(const Vector& src,
const Vector& endpos,
const Vector& mins,
@ -522,79 +522,127 @@ void CCSPlayer::FireBullet(
shouldDebugHitboxesOnHit = shouldDebugHitboxesOnHit && (cl_showimpacts.GetInt() == 1 || cl_showimpacts.GetInt() == 2);
shouldDebugHitboxesOnFire = shouldDebugHitboxesOnFire && (cl_showfirebullethitboxes.GetInt() == 1 || cl_showfirebullethitboxes.GetInt() == 2);
#endif
if ( shouldDebugHitboxesOnFire )
{
for (int i = 1; i <= gpGlobals->maxClients; i++)
{
CBasePlayer* lagPlayer = UTIL_PlayerByIndex(i);
if (lagPlayer && lagPlayer != this)
#ifndef CLIENT_DLL
auto WritePlayerHitboxEvent = [&]( CBasePlayer* lagPlayer )
{
if ( IsBot() )
{
return;
}
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];
auto angle = lagPlayer->GetAbsAngles();
auto position = lagPlayer->GetAbsOrigin();
event->SetFloat( "position_x", position.x );
event->SetFloat( "position_y", position.y );
event->SetFloat( "position_z", position.z );
event->SetFloat( "angle_x", angle.x );
event->SetFloat( "angle_y", angle.y );
event->SetFloat( "angle_z", angle.z );
event->SetFloat( "cycle", lagPlayer->GetCycle() );
event->SetInt( "sequence", lagPlayer->GetSequence() );
int numhitboxes = lagPlayer->GetServerHitboxes( positions, angles, indexes );
event->SetInt( "num_hitboxes", numhitboxes );
for ( int i = 0; i < numhitboxes; i++ )
{
// #ifdef CLIENT_DLL
// if ( !m_pCurrentCommand->hasbeenpredicted )
// {
// std::string text = "client:\n";
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 );
}
// auto angles = lagPlayer->GetRenderAngles();
auto model = lagPlayer->GetModelPtr();
// text += "x: " + std::to_string(angles.x) + ", y: " + std::to_string(angles.y) + ", z: " + std::to_string(angles.z) + '\n';
auto numposeparams = model->GetNumPoseParameters();
event->SetInt( "num_poseparams", numposeparams );
// NDebugOverlay::EntityBounds( lagPlayer, 255, 0, 0, 32, 60 );
// std::cout << text;
// }
// #else
// std::string text = "server:\n";
for ( int i = 0; i < numposeparams; i++ )
{
char buffer[256];
V_sprintf_safe( buffer, "pose_param_%i", i );
event->SetFloat( buffer, lagPlayer->GetPoseParameterArray()[i] );
}
// auto angles = lagPlayer->GetAbsAngles();
auto numbonecontrollers = model->GetNumBoneControllers();
event->SetInt( "num_bonecontrollers", numbonecontrollers );
// text += "x: " + std::to_string(angles.x) + ", y: " + std::to_string(angles.y) + ", z: " + std::to_string(angles.z) + '\n';
// NDebugOverlay::EntityBounds( lagPlayer, 0, 255, 0, 32, 60 );
// std::cout << text;
// #endif
#ifdef CLIENT_DLL
if (!m_pCurrentCommand->hasbeenpredicted)
{
lagPlayer->DrawClientHitboxes(m_flDebugDuration, true);
}
#else
IGameEvent* event = gameeventmanager->CreateEvent("bullet_player_hitboxes");
if (event)
{
event->SetInt("userid", GetUserID());
event->SetInt("player_index", lagPlayer->entindex());
for ( int i = 0; i < numbonecontrollers; i++ )
{
char buffer[256];
V_sprintf_safe( buffer, "bone_controller_%i", i );
event->SetFloat( buffer, lagPlayer->GetBoneControllerArray()[i] );
}
Vector positions[MAXSTUDIOBONES];
QAngle angles[MAXSTUDIOBONES];
int indexes[MAXSTUDIOBONES];
auto numanimoverlays = lagPlayer->GetNumAnimOverlays();
event->SetInt( "num_anim_overlays", numanimoverlays );
int numhitboxes = lagPlayer->GetServerHitboxes(positions, angles, indexes);
event->SetInt("num_hitboxes", numhitboxes);
for ( int i = 0; i < numanimoverlays; i++ )
{
auto animOverlay = lagPlayer->GetAnimOverlay( i );
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);
}
char buffer[256];
V_sprintf_safe( buffer, "anim_overlay_cycle_%i", i );
event->SetFloat( buffer, animOverlay->m_flCycle.Get() );
gameeventmanager->FireEvent(event);
}
V_sprintf_safe( buffer, "anim_overlay_sequence_%i", i );
event->SetInt( buffer, animOverlay->m_nSequence.Get() );
V_sprintf_safe( buffer, "anim_overlay_weight_%i", i );
event->SetFloat( buffer, animOverlay->m_flWeight.Get() );
V_sprintf_safe( buffer, "anim_overlay_order_%i", i );
event->SetInt( buffer, animOverlay->m_nOrder.Get() );
}
gameeventmanager->FireEvent( event );
}
};
#endif
}
}
}
if ( shouldDebugHitboxesOnFire )
{
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
{
CBasePlayer* lagPlayer = UTIL_PlayerByIndex( i );
if ( lagPlayer && lagPlayer != this )
{
#ifdef CLIENT_DLL
if ( !m_pCurrentCommand->hasbeenpredicted )
{
lagPlayer->DrawClientHitboxes( cl_debug_duration.GetFloat(), true );
}
#else
WritePlayerHitboxEvent( lagPlayer );
#endif
}
}
}
while ( fCurrentDamage > 0 )
{
@ -640,84 +688,51 @@ void CCSPlayer::FireBullet(
flDamageModifier = 0.99f;
}
if (shouldDebugHitboxesOnHit)
{
if ( shouldDebugHitboxesOnHit )
{
#ifdef CLIENT_DLL
if (!m_pCurrentCommand->hasbeenpredicted)
{
DrawBullet(vecSrc,
tr.endpos,
vecBulletRadiusMins,
vecBulletRadiusMaxs,
0,
255,
0,
127,
m_flDebugDuration);
}
if ( !m_pCurrentCommand->hasbeenpredicted )
{
DrawBullet( vecSrc,
tr.endpos,
vecBulletRadiusMins,
vecBulletRadiusMaxs,
0,
255,
0,
127,
cl_debug_duration.GetFloat() );
}
#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->FireEvent(event);
}
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->FireEvent( event );
}
#endif
if (tr.m_pEnt && tr.m_pEnt->IsPlayer() && !shouldDebugHitboxesOnFire)
{
const auto lagPlayer = UTIL_PlayerByIndex(tr.m_pEnt->entindex());
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)
{
lagPlayer->DrawClientHitboxes(m_flDebugDuration, true);
}
if ( !m_pCurrentCommand->hasbeenpredicted )
{
lagPlayer->DrawClientHitboxes( cl_debug_duration.GetFloat(), 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->FireEvent(eventHit);
}
WritePlayerHitboxEvent( lagPlayer );
#endif
}
}
}
}
//calculate the damage based on the distance the bullet travelled.
//calculate the damage based on the distance the bullet travelled.
flCurrentDistance += tr.fraction * flDistance;
fCurrentDamage *= pow (flRangeModifier, (flCurrentDistance / 500));

View file

@ -144,8 +144,8 @@ void FX_FireBullets(
// #endif
CUserCmd* playerCmd = NULL;
if (pPlayer)
{
if ( pPlayer )
{
#ifdef CLIENT_DLL
playerCmd = pPlayer->m_pCurrentCommand;
#else
@ -153,9 +153,9 @@ void FX_FireBullets(
#endif
}
if (playerCmd)
if ( playerCmd )
{
vHookedOrigin = VectorLerp(pPlayer->m_vecPreviousShootPosition, vOrigin, playerCmd->interpolated_amount);
vHookedOrigin = VectorLerp( pPlayer->m_vecPreviousShootPosition, vOrigin, playerCmd->interpolated_amount );
}
// #ifndef CLIENT_DLL

View file

@ -36,22 +36,6 @@
class bf_read;
class bf_write;
struct LayerRecord
{
int m_sequence;
float m_cycle;
float m_weight;
int m_order;
LayerRecord()
{
m_sequence = 0;
m_cycle = 0;
m_weight = 0;
m_order = 0;
}
};
struct SimulationData
{
// TODO_ENHANCED:

View file

@ -54,10 +54,10 @@ data field should not be broadcasted to clients, use the type "local".
*/
#define MAX_EVENT_NAME_LENGTH 32 // max game event name length
#define MAX_EVENT_BITS 9 // max bits needed for an event index
#define MAX_EVENT_NAME_LENGTH 64 // max game event name length
#define MAX_EVENT_BITS 14 // max bits needed for an event index
#define MAX_EVENT_NUMBER (1<<MAX_EVENT_BITS) // max number of events allowed
#define MAX_EVENT_BYTES (1<<12) // max size in bytes for a serialized event
#define MAX_EVENT_BYTES (1<<26) // max size in bytes for a serialized event
class KeyValues;
class CGameEvent;