diff options
Diffstat (limited to 'mp/src/game')
132 files changed, 1575 insertions, 791 deletions
diff --git a/mp/src/game/client/c_baseanimating.cpp b/mp/src/game/client/c_baseanimating.cpp index c41ff46b..75c9d7a8 100644 --- a/mp/src/game/client/c_baseanimating.cpp +++ b/mp/src/game/client/c_baseanimating.cpp @@ -3531,7 +3531,7 @@ bool C_BaseAnimating::DispatchMuzzleEffect( const char *options, bool isFirstPer p = nexttoken( token, p, ' ' ); // Find the weapon type - if ( token ) + if ( token[0] ) { //TODO: Parse the type from a list instead if ( Q_stricmp( token, "COMBINE" ) == 0 ) @@ -3577,7 +3577,7 @@ bool C_BaseAnimating::DispatchMuzzleEffect( const char *options, bool isFirstPer int attachmentIndex = -1; // Find the attachment name - if ( token ) + if ( token[0] ) { attachmentIndex = LookupAttachment( token ); @@ -3684,29 +3684,25 @@ void C_BaseAnimating::FireEvent( const Vector& origin, const QAngle& angles, int // Get the particle effect name const char *p = options; p = nexttoken(token, p, ' '); - if ( token ) - { - const char* mtoken = ModifyEventParticles( token ); - if ( !mtoken || mtoken[0] == '\0' ) - return; - Q_strncpy( szParticleEffect, mtoken, sizeof(szParticleEffect) ); - } + + const char* mtoken = ModifyEventParticles( token ); + if ( !mtoken || mtoken[0] == '\0' ) + return; + Q_strncpy( szParticleEffect, mtoken, sizeof(szParticleEffect) ); // Get the attachment type p = nexttoken(token, p, ' '); - if ( token ) + + iAttachType = GetAttachTypeFromString( token ); + if ( iAttachType == -1 ) { - iAttachType = GetAttachTypeFromString( token ); - if ( iAttachType == -1 ) - { - Warning("Invalid attach type specified for particle effect anim event. Trying to spawn effect '%s' with attach type of '%s'\n", szParticleEffect, token ); - return; - } + Warning("Invalid attach type specified for particle effect anim event. Trying to spawn effect '%s' with attach type of '%s'\n", szParticleEffect, token ); + return; } // Get the attachment point index p = nexttoken(token, p, ' '); - if ( token ) + if ( token[0] ) { iAttachment = atoi(token); @@ -3902,26 +3898,19 @@ void C_BaseAnimating::FireEvent( const Vector& origin, const QAngle& angles, int case AE_CL_BODYGROUP_SET_VALUE: { - char szBodygroupName[256]; - int value = 0; - + int value; char token[256]; + char szBodygroupName[256]; const char *p = options; // Bodygroup Name p = nexttoken(token, p, ' '); - if ( token ) - { - Q_strncpy( szBodygroupName, token, sizeof(szBodygroupName) ); - } + Q_strncpy( szBodygroupName, token, sizeof(szBodygroupName) ); // Get the desired value p = nexttoken(token, p, ' '); - if ( token ) - { - value = atoi( token ); - } + value = token[0] ? atoi( token ) : 0; int index = FindBodygroupByName( szBodygroupName ); if ( index >= 0 ) @@ -3950,33 +3939,21 @@ void C_BaseAnimating::FireObsoleteEvent( const Vector& origin, const QAngle& ang // Obsolete. Use the AE_CL_CREATE_PARTICLE_EFFECT event instead, which uses the artist driven particle system & editor. case AE_CLIENT_EFFECT_ATTACH: { - int iAttachment = -1; - int iParam = 0; + int iAttachment; + int iParam; char token[128]; char effectFunc[128]; const char *p = options; p = nexttoken(token, p, ' '); - - if( token ) - { - Q_strncpy( effectFunc, token, sizeof(effectFunc) ); - } + Q_strncpy( effectFunc, token, sizeof(effectFunc) ); p = nexttoken(token, p, ' '); - - if( token ) - { - iAttachment = atoi(token); - } + iAttachment = token[0] ? atoi(token) : -1; p = nexttoken(token, p, ' '); - - if( token ) - { - iParam = atoi(token); - } + iParam = token[0] ? atoi(token) : 0; if ( iAttachment != -1 && m_Attachments.Count() >= iAttachment ) { @@ -5281,8 +5258,9 @@ float C_BaseAnimating::FrameAdvance( float flInterval ) // Stubs for weapon prediction void C_BaseAnimating::ResetSequenceInfo( void ) { - if (GetSequence() == -1) + if ( GetSequence() == -1 ) { + // This shouldn't happen. Setting m_nSequence blindly is a horrible coding practice. SetSequence( 0 ); } @@ -5294,7 +5272,7 @@ void C_BaseAnimating::ResetSequenceInfo( void ) CStudioHdr *pStudioHdr = GetModelPtr(); m_flGroundSpeed = GetSequenceGroundSpeed( pStudioHdr, GetSequence() ) * GetModelScale(); - m_bSequenceLoops = ((GetSequenceFlags( pStudioHdr, GetSequence() ) & STUDIO_LOOPING) != 0); + m_bSequenceLoops = ( ( GetSequenceFlags( pStudioHdr, GetSequence() ) & STUDIO_LOOPING ) != 0 ); // m_flAnimTime = gpGlobals->time; m_flPlaybackRate = 1.0; m_bSequenceFinished = false; @@ -5302,9 +5280,12 @@ void C_BaseAnimating::ResetSequenceInfo( void ) m_nNewSequenceParity = ( m_nNewSequenceParity + 1 ) & EF_PARITY_MASK; m_nResetEventsParity = ( m_nResetEventsParity + 1 ) & EF_PARITY_MASK; - + // FIXME: why is this called here? Nothing should have changed to make this nessesary - SetEventIndexForSequence( pStudioHdr->pSeqdesc( GetSequence() ) ); + if ( pStudioHdr ) + { + SetEventIndexForSequence( pStudioHdr->pSeqdesc( GetSequence() ) ); + } } //========================================================= diff --git a/mp/src/game/client/c_baseentity.cpp b/mp/src/game/client/c_baseentity.cpp index 8f40d7ef..25b089cd 100644 --- a/mp/src/game/client/c_baseentity.cpp +++ b/mp/src/game/client/c_baseentity.cpp @@ -571,7 +571,8 @@ void SpewInterpolatedVar( CInterpolatedVar< Vector > *pVar ) { Msg( "--------------------------------------------------\n" ); int i = pVar->GetHead(); - CApparentVelocity<Vector> apparent; + Vector v0(0, 0, 0); + CApparentVelocity<Vector> apparent(v0); float prevtime = 0.0f; while ( 1 ) { @@ -594,7 +595,8 @@ void SpewInterpolatedVar( CInterpolatedVar< Vector > *pVar, float flNow, float f Msg( "--------------------------------------------------\n" ); int i = pVar->GetHead(); - CApparentVelocity<Vector> apparent; + Vector v0(0, 0, 0); + CApparentVelocity<Vector> apparent(v0); float newtime = 999999.0f; Vector newVec( 0, 0, 0 ); bool bSpew = true; @@ -662,7 +664,7 @@ void SpewInterpolatedVar( CInterpolatedVar< float > *pVar ) { Msg( "--------------------------------------------------\n" ); int i = pVar->GetHead(); - CApparentVelocity<float> apparent; + CApparentVelocity<float> apparent(0.0f); while ( 1 ) { float changetime; @@ -684,7 +686,8 @@ void GetInterpolatedVarTimeRange( CInterpolatedVar<T> *pVar, float &flMin, float flMax = -1e23; int i = pVar->GetHead(); - CApparentVelocity<Vector> apparent; + Vector v0(0, 0, 0); + CApparentVelocity<Vector> apparent(v0); while ( 1 ) { float changetime; @@ -892,6 +895,8 @@ C_BaseEntity::C_BaseEntity() : m_iv_angRotation( "C_BaseEntity::m_iv_angRotation" ), m_iv_vecVelocity( "C_BaseEntity::m_iv_vecVelocity" ) { + m_pAttributes = NULL; + AddVar( &m_vecOrigin, &m_iv_vecOrigin, LATCH_SIMULATION_VAR ); AddVar( &m_angRotation, &m_iv_angRotation, LATCH_SIMULATION_VAR ); // Removing this until we figure out why velocity introduces view hitching. @@ -1299,19 +1304,6 @@ bool C_BaseEntity::VPhysicsIsFlesh( void ) return false; } -//----------------------------------------------------------------------------- -// Returns the health fraction -//----------------------------------------------------------------------------- -float C_BaseEntity::HealthFraction() const -{ - if (GetMaxHealth() == 0) - return 1.0f; - - float flFraction = (float)GetHealth() / (float)GetMaxHealth(); - flFraction = clamp( flFraction, 0.0f, 1.0f ); - return flFraction; -} - //----------------------------------------------------------------------------- // Purpose: Retrieves the coordinate frame for this entity. @@ -2625,6 +2617,25 @@ void C_BaseEntity::PostDataUpdate( DataUpdateType_t updateType ) } //----------------------------------------------------------------------------- +// Purpose: Latch simulation values when the entity has not changed +//----------------------------------------------------------------------------- +void C_BaseEntity::OnDataUnchangedInPVS() +{ + Interp_RestoreToLastNetworked( GetVarMapping() ); + + // For non-predicted and non-client only ents, we need to latch network values into the interpolation histories + if ( !GetPredictable() && !IsClientCreated() ) + { + OnLatchInterpolatedVariables( LATCH_SIMULATION_VAR ); + } + + Assert( m_hNetworkMoveParent.Get() || !m_hNetworkMoveParent.IsValid() ); + HierarchySetParent(m_hNetworkMoveParent); + + MarkMessageReceived(); +} + +//----------------------------------------------------------------------------- // Purpose: // Input : *context - //----------------------------------------------------------------------------- @@ -3741,7 +3752,7 @@ void C_BaseEntity::AddColoredDecal( const Vector& rayStart, const Vector& rayEnd case mod_brush: { - color32 cColor32 = { cColor.r(), cColor.g(), cColor.b(), cColor.a() }; + color32 cColor32 = { (byte)cColor.r(), (byte)cColor.g(), (byte)cColor.b(), (byte)cColor.a() }; effects->DecalColorShoot( decalIndex, index, model, GetAbsOrigin(), GetAbsAngles(), decalCenter, 0, 0, cColor32 ); } break; @@ -6309,6 +6320,9 @@ bool C_BaseEntity::ValidateEntityAttachedToPlayer( bool &bShouldRetry ) if ( FStrEq( pszModel, "models/props_lakeside_event/bomb_temp_hat.mdl" ) ) return true; + + if ( FStrEq( pszModel, "models/props_moonbase/powersupply_flag.mdl" ) ) + return true; } // Any entity that's not an item parented to a player is invalid. diff --git a/mp/src/game/client/c_baseentity.h b/mp/src/game/client/c_baseentity.h index c62b732f..f062760d 100644 --- a/mp/src/game/client/c_baseentity.h +++ b/mp/src/game/client/c_baseentity.h @@ -58,6 +58,7 @@ class C_BaseCombatCharacter; class CEntityMapData; class ConVar; class CDmgAccumulator; +class IHasAttributes; struct CSoundParameters; @@ -335,6 +336,7 @@ public: // save out interpolated values virtual void PreDataUpdate( DataUpdateType_t updateType ); virtual void PostDataUpdate( DataUpdateType_t updateType ); + virtual void OnDataUnchangedInPVS(); virtual void ValidateModelIndex( void ); @@ -516,6 +518,7 @@ public: // Used when the collision prop is told to ask game code for the world-space surrounding box virtual void ComputeWorldSpaceSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs ); + virtual float GetHealthBarHeightOffset() const { return 0.f; } // Returns the entity-to-world transform matrix3x4_t &EntityToWorldTransform(); @@ -686,7 +689,7 @@ public: virtual bool ShouldDraw(); inline bool IsVisible() const { return m_hRender != INVALID_CLIENT_RENDER_HANDLE; } - void UpdateVisibility(); + virtual void UpdateVisibility(); // Returns true if the entity changes its position every frame on the server but it doesn't // set animtime. In that case, the client returns true here so it copies the server time to @@ -743,7 +746,8 @@ public: virtual void SetHealth(int iHealth) {} virtual int GetHealth() const { return 0; } virtual int GetMaxHealth() const { return 1; } - virtual bool IsVisibleToTargetID( void ) { return false; } + virtual bool IsVisibleToTargetID( void ) const { return false; } + virtual bool IsHealthBarVisible( void ) const { return false; } // Returns the health fraction float HealthFraction() const; @@ -1172,7 +1176,17 @@ public: // Sets the origin + angles to match the last position received void MoveToLastReceivedPosition( bool force = false ); + // Return the IHasAttributes interface for this base entity. Removes the need for: + // dynamic_cast< IHasAttributes * >( pEntity ); + // Which is remarkably slow. + // GetAttribInterface( CBaseEntity *pEntity ) in attribute_manager.h uses + // this function, tests for NULL, and Asserts m_pAttributes == dynamic_cast. + inline IHasAttributes *GetHasAttributesInterfacePtr() const { return m_pAttributes; } + protected: + // NOTE: m_pAttributes needs to be set in the leaf class constructor. + IHasAttributes *m_pAttributes; + // Only meant to be called from subclasses void DestroyModelInstance(); diff --git a/mp/src/game/client/c_baseflex.cpp b/mp/src/game/client/c_baseflex.cpp index 6146b2dd..7e6c4bfc 100644 --- a/mp/src/game/client/c_baseflex.cpp +++ b/mp/src/game/client/c_baseflex.cpp @@ -562,11 +562,11 @@ Vector C_BaseFlex::SetViewTarget( CStudioHdr *pStudioHdr ) m_iEyeUpdown = FindFlexController( "eyes_updown" ); m_iEyeRightleft = FindFlexController( "eyes_rightleft" ); - if ( m_iEyeUpdown != -1 ) + if ( m_iEyeUpdown != LocalFlexController_t(-1) ) { pStudioHdr->pFlexcontroller( m_iEyeUpdown )->localToGlobal = AddGlobalFlexController( "eyes_updown" ); } - if ( m_iEyeRightleft != -1 ) + if ( m_iEyeRightleft != LocalFlexController_t(-1) ) { pStudioHdr->pFlexcontroller( m_iEyeRightleft )->localToGlobal = AddGlobalFlexController( "eyes_rightleft" ); } @@ -594,13 +594,13 @@ Vector C_BaseFlex::SetViewTarget( CStudioHdr *pStudioHdr ) // calculate animated eye deflection Vector eyeDeflect; QAngle eyeAng( 0, 0, 0 ); - if ( m_iEyeUpdown != -1 ) + if ( m_iEyeUpdown != LocalFlexController_t(-1) ) { mstudioflexcontroller_t *pflex = pStudioHdr->pFlexcontroller( m_iEyeUpdown ); eyeAng.x = g_flexweight[ pflex->localToGlobal ]; } - if ( m_iEyeRightleft != -1 ) + if ( m_iEyeRightleft != LocalFlexController_t(-1) ) { mstudioflexcontroller_t *pflex = pStudioHdr->pFlexcontroller( m_iEyeRightleft ); eyeAng.y = g_flexweight[ pflex->localToGlobal ]; @@ -1057,7 +1057,7 @@ void C_BaseFlex::GetToolRecordingState( KeyValues *msg ) Vector viewtarget = m_viewtarget; // Use the unfiltered value // HACK HACK: Unmap eyes right/left amounts - if (m_iEyeUpdown != -1 && m_iEyeRightleft != -1) + if (m_iEyeUpdown != LocalFlexController_t(-1) && m_iEyeRightleft != LocalFlexController_t(-1)) { mstudioflexcontroller_t *flexupdown = hdr->pFlexcontroller( m_iEyeUpdown ); mstudioflexcontroller_t *flexrightleft = hdr->pFlexcontroller( m_iEyeRightleft ); diff --git a/mp/src/game/client/c_basetempentity.h b/mp/src/game/client/c_basetempentity.h index d462461c..2f3740ea 100644 --- a/mp/src/game/client/c_basetempentity.h +++ b/mp/src/game/client/c_basetempentity.h @@ -55,6 +55,7 @@ public: virtual void NotifyShouldTransmit( ShouldTransmitState_t state ); virtual void PreDataUpdate( DataUpdateType_t updateType ); virtual void PostDataUpdate( DataUpdateType_t updateType ); + virtual void OnDataUnchangedInPVS( void ) { } virtual void OnPreDataChanged( DataUpdateType_t updateType ); virtual void OnDataChanged( DataUpdateType_t updateType ); virtual void SetDormant( bool bDormant ); diff --git a/mp/src/game/client/c_baseviewmodel.cpp b/mp/src/game/client/c_baseviewmodel.cpp index 98132bc9..8ae21f63 100644 --- a/mp/src/game/client/c_baseviewmodel.cpp +++ b/mp/src/game/client/c_baseviewmodel.cpp @@ -192,7 +192,7 @@ bool C_BaseViewModel::Interpolate( float currentTime ) } -inline bool C_BaseViewModel::ShouldFlipViewModel() +bool C_BaseViewModel::ShouldFlipViewModel() { #ifdef CSTRIKE_DLL // If cl_righthand is set, then we want them all right-handed. diff --git a/mp/src/game/client/c_entitydissolve.cpp b/mp/src/game/client/c_entitydissolve.cpp index 0c8dadc2..f61e2ac0 100644 --- a/mp/src/game/client/c_entitydissolve.cpp +++ b/mp/src/game/client/c_entitydissolve.cpp @@ -575,7 +575,10 @@ void C_EntityDissolve::ClientThink( void ) #ifdef TF_CLIENT_DLL else { - pEnt->Release(); + // Hide the ragdoll -- don't actually delete it or else things get unhappy when + // we get a message from the server telling us to delete it + pEnt->AddEffects( EF_NODRAW ); + pEnt->ParticleProp()->StopEmission(); } #endif } diff --git a/mp/src/game/client/c_particle_system.cpp b/mp/src/game/client/c_particle_system.cpp index 57f3c375..e0aee808 100644 --- a/mp/src/game/client/c_particle_system.cpp +++ b/mp/src/game/client/c_particle_system.cpp @@ -198,12 +198,19 @@ void ParticleEffectCallback( const CEffectData &data ) pEnt->ParticleProp()->StopEmission(); } - pEffect = pEnt->ParticleProp()->Create( pszName, (ParticleAttachment_t)data.m_nDamageType, data.m_nAttachmentIndex ); + Vector vOffset = vec3_origin; + ParticleAttachment_t iAttachType = (ParticleAttachment_t)data.m_nDamageType; + if ( iAttachType == PATTACH_ABSORIGIN_FOLLOW || iAttachType == PATTACH_POINT_FOLLOW || iAttachType == PATTACH_ROOTBONE_FOLLOW ) + { + vOffset = data.m_vStart; + } + + pEffect = pEnt->ParticleProp()->Create( pszName, iAttachType, data.m_nAttachmentIndex, vOffset ); AssertMsg2( pEffect.IsValid() && pEffect->IsValid(), "%s could not create particle effect %s", C_BaseEntity::Instance( data.m_hEntity )->GetDebugName(), pszName ); if ( pEffect.IsValid() && pEffect->IsValid() ) { - if ( (ParticleAttachment_t)data.m_nDamageType == PATTACH_CUSTOMORIGIN ) + if ( iAttachType == PATTACH_CUSTOMORIGIN ) { pEffect->SetSortOrigin( data.m_vOrigin ); pEffect->SetControlPoint( 0, data.m_vOrigin ); diff --git a/mp/src/game/client/c_rope.cpp b/mp/src/game/client/c_rope.cpp index 605f4750..9f11fc5d 100644 --- a/mp/src/game/client/c_rope.cpp +++ b/mp/src/game/client/c_rope.cpp @@ -193,7 +193,7 @@ public: if( pReturn == NULL ) { int iMaxSize = m_QueuedRopeMemory[m_nCurrentStack].GetMaxSize(); - Warning( "Overflowed rope queued rendering memory stack. Needed %d, have %d/%d\n", bytes, iMaxSize - m_QueuedRopeMemory[m_nCurrentStack].GetUsed(), iMaxSize ); + Warning( "Overflowed rope queued rendering memory stack. Needed %llu, have %d/%d\n", (uint64)bytes, iMaxSize - m_QueuedRopeMemory[m_nCurrentStack].GetUsed(), iMaxSize ); pReturn = malloc( bytes ); m_DeleteOnSwitch[m_nCurrentStack].AddToTail( pReturn ); } diff --git a/mp/src/game/client/c_sceneentity.cpp b/mp/src/game/client/c_sceneentity.cpp index b44b59fd..baf2770e 100644 --- a/mp/src/game/client/c_sceneentity.cpp +++ b/mp/src/game/client/c_sceneentity.cpp @@ -214,11 +214,11 @@ void C_SceneEntity::SetupClientOnlyScene( const char *pszFilename, C_BaseFlex *p V_strcpy( szFilename, szSceneHWM ); } - Assert( szFilename && szFilename[ 0 ] ); - if ( szFilename && szFilename[ 0 ] ) + Assert( szFilename[ 0 ] ); + if ( szFilename[ 0 ] ) { LoadSceneFromFile( szFilename ); - + if (!CommandLine()->FindParm("-hushasserts")) { Assert( m_pScene ); @@ -335,8 +335,8 @@ void C_SceneEntity::PostDataUpdate( DataUpdateType_t updateType ) if ( updateType == DATA_UPDATE_CREATED ) { - Assert( szFilename && szFilename[ 0 ] ); - if ( szFilename && szFilename[ 0 ] ) + Assert( szFilename[ 0 ] ); + if ( szFilename[ 0 ] ) { LoadSceneFromFile( szFilename ); @@ -373,6 +373,8 @@ void C_SceneEntity::PostDataUpdate( DataUpdateType_t updateType ) SetNextClientThink( CLIENT_THINK_ALWAYS ); } + + m_bWasPlaying = !m_bIsPlayingBack; // force it to be "changed" } // Playback state changed... diff --git a/mp/src/game/client/c_te_legacytempents.cpp b/mp/src/game/client/c_te_legacytempents.cpp index 3c8adf68..14f6d0e8 100644 --- a/mp/src/game/client/c_te_legacytempents.cpp +++ b/mp/src/game/client/c_te_legacytempents.cpp @@ -1539,7 +1539,7 @@ void CTempEnts::BloodSprite( const Vector &org, int r, int g, int b, int a, int { C_LocalTempEntity *pTemp; int frameCount = modelinfo->GetModelFrameCount( model ); - color32 impactcolor = { r, g, b, a }; + color32 impactcolor = { (byte)r, (byte)g, (byte)b, (byte)a }; //Large, single blood sprite is a high-priority tent if ( ( pTemp = TempEntAllocHigh( org, model ) ) != NULL ) diff --git a/mp/src/game/client/c_team_train_watcher.cpp b/mp/src/game/client/c_team_train_watcher.cpp index da3fa880..e58aafb1 100644 --- a/mp/src/game/client/c_team_train_watcher.cpp +++ b/mp/src/game/client/c_team_train_watcher.cpp @@ -163,18 +163,13 @@ void C_TeamTrainWatcher::OnDataChanged( DataUpdateType_t updateType ) int nNumHills = ObjectiveResource()->GetNumNodeHillData( GetTeamNumber() ); if ( nNumHills > 0 ) { - float flStart, flEnd; + float flStart = 0, flEnd = 0; for ( int i = 0 ; i < nNumHills ; i++ ) { ObjectiveResource()->GetHillData( GetTeamNumber(), i, flStart, flEnd ); - if ( m_flTotalProgress >= flStart && m_flTotalProgress<= flEnd ) - { - ObjectiveResource()->SetTrainOnHill( GetTeamNumber(), i, true ); - } - else - { - ObjectiveResource()->SetTrainOnHill( GetTeamNumber(), i, false ); - } + + bool state = ( m_flTotalProgress >= flStart && m_flTotalProgress <= flEnd ); + ObjectiveResource()->SetTrainOnHill( GetTeamNumber(), i, state ); } } } diff --git a/mp/src/game/client/client_base.vpc b/mp/src/game/client/client_base.vpc index 52dceb7e..309ffb8c 100644 --- a/mp/src/game/client/client_base.vpc +++ b/mp/src/game/client/client_base.vpc @@ -53,9 +53,8 @@ $Configuration { $AdditionalIncludeDirectories ".\;$BASE;$SRCDIR\vgui2\include;$SRCDIR\vgui2\controls;$SRCDIR\game\shared;.\game_controls;$SRCDIR\thirdparty\sixensesdk\include" $PreprocessorDefinitions "$BASE;NO_STRING_T;CLIENT_DLL;VECTOR;VERSION_SAFE_STEAM_API_INTERFACES;PROTECTED_THINGS_ENABLE;strncpy=use_Q_strncpy_instead;_snprintf=use_Q_snprintf_instead" - $PreprocessorDefinitions "$BASE;ENABLE_CHROMEHTMLWINDOW;fopen=dont_use_fopen" [$WIN32] - $PreprocessorDefinitions "$BASE;ENABLE_CHROMEHTMLWINDOW;" [$OSXALL] - $PreprocessorDefinitions "$BASE;ENABLE_CHROMEHTMLWINDOW;USE_WEBM_FOR_REPLAY;" [$LINUXALL] + $PreprocessorDefinitions "$BASE;fopen=dont_use_fopen" [$WIN32] + $PreprocessorDefinitions "$BASE;USE_WEBM_FOR_REPLAY;" [$LINUXALL] $PreprocessorDefinitions "$BASE;CURL_STATICLIB" [$WIN32 && $BUILD_REPLAY] $Create/UsePrecompiledHeader "Use Precompiled Header (/Yu)" $Create/UsePCHThroughFile "cbase.h" diff --git a/mp/src/game/client/client_virtualreality.cpp b/mp/src/game/client/client_virtualreality.cpp index fb6e4417..472fa6c1 100644 --- a/mp/src/game/client/client_virtualreality.cpp +++ b/mp/src/game/client/client_virtualreality.cpp @@ -213,6 +213,7 @@ void CalcFovFromProjection ( float *pFov, const VMatrix &proj ) Assert ( proj.m[3][2] == -1.0f ); Assert ( proj.m[3][3] == 0.0f ); + /* // The math here: // A view-space vector (x,y,z,1) is transformed by the projection matrix // / xscale 0 xoffset 0 \ @@ -227,6 +228,7 @@ void CalcFovFromProjection ( float *pFov, const VMatrix &proj ) // = xscale*(x/z) + xoffset (I flipped the signs of both sides) // => (+-1 - xoffset)/xscale = x/z // ...and x/z is tan(theta), and theta is the half-FOV. + */ float fov_px = 2.0f * RAD2DEG ( atanf ( fabsf ( ( 1.0f - xoffset ) / xscale ) ) ); float fov_nx = 2.0f * RAD2DEG ( atanf ( fabsf ( ( -1.0f - xoffset ) / xscale ) ) ); @@ -261,8 +263,6 @@ CClientVirtualReality::CClientVirtualReality() m_rtLastMotionSample = 0; m_bMotionUpdated = false; - m_bForceVRMode = false; - #if defined( USE_SDL ) m_nNonVRSDLDisplayIndex = 0; #endif @@ -1367,7 +1367,7 @@ void CClientVirtualReality::Activate() return; // These checks don't apply if we're in VR mode because Steam said so. - if ( !m_bForceVRMode ) + if ( !ShouldForceVRActive() ) { // see if VR mode is even enabled if ( materials->GetCurrentConfigForVideoCard().m_nVRModeAdapter == -1 ) @@ -1441,7 +1441,7 @@ void CClientVirtualReality::Activate() vgui::ivgui()->SetVRMode( true ); // we can skip this extra mode change if we've always been in VR mode - if ( !m_bForceVRMode ) + if ( !ShouldForceVRActive() ) { VRRect_t rect; if ( g_pSourceVR->GetDisplayBounds( &rect ) ) @@ -1510,10 +1510,7 @@ void CClientVirtualReality::Deactivate() // Called when startup is complete void CClientVirtualReality::StartupComplete() { - if ( g_pSourceVR ) - m_bForceVRMode = g_pSourceVR->ShouldForceVRMode(); - - if ( vr_activate_default.GetBool( ) || m_bForceVRMode ) + if ( vr_activate_default.GetBool() || ShouldForceVRActive() ) Activate(); } diff --git a/mp/src/game/client/client_virtualreality.h b/mp/src/game/client/client_virtualreality.h index 3a8c9469..9aadfeb3 100644 --- a/mp/src/game/client/client_virtualreality.h +++ b/mp/src/game/client/client_virtualreality.h @@ -147,7 +147,6 @@ private: int m_iAlignTorsoAndViewToWeaponCountdown; bool m_bMotionUpdated; - bool m_bForceVRMode; RTime32 m_rtLastMotionSample; diff --git a/mp/src/game/client/cliententitylist.cpp b/mp/src/game/client/cliententitylist.cpp index 294d4ff1..2f983e62 100644 --- a/mp/src/game/client/cliententitylist.cpp +++ b/mp/src/game/client/cliententitylist.cpp @@ -354,6 +354,67 @@ void CClientEntityList::OnAddEntity( IHandleEntity *pEnt, CBaseHandle handle ) } +#if defined( STAGING_ONLY ) + +// Defined in tier1 / interface.cpp for Windows and native for POSIX platforms. +extern "C" int backtrace( void **buffer, int size ); + +static struct +{ + int entnum; + float time; + C_BaseEntity *pBaseEntity; + void *backtrace_addrs[ 16 ]; +} g_RemoveEntityBacktraces[ 1024 ]; +static uint32 g_RemoveEntityBacktracesIndex = 0; + +static void OnRemoveEntityBacktraceHook( int entnum, C_BaseEntity *pBaseEntity ) +{ + int index = g_RemoveEntityBacktracesIndex++; + if ( g_RemoveEntityBacktracesIndex >= ARRAYSIZE( g_RemoveEntityBacktraces ) ) + g_RemoveEntityBacktracesIndex = 0; + + g_RemoveEntityBacktraces[ index ].entnum = entnum; + g_RemoveEntityBacktraces[ index ].time = gpGlobals->curtime; + g_RemoveEntityBacktraces[ index ].pBaseEntity = pBaseEntity; + + memset( g_RemoveEntityBacktraces[ index ].backtrace_addrs, 0, sizeof( g_RemoveEntityBacktraces[ index ].backtrace_addrs ) ); + backtrace( g_RemoveEntityBacktraces[ index ].backtrace_addrs, ARRAYSIZE( g_RemoveEntityBacktraces[ index ].backtrace_addrs ) ); +} + +// Should help us track down CL_PreserveExistingEntity Host_Error() issues: +// 1. Set cl_removeentity_backtrace_capture to 1. +// 2. When error hits, run "cl_removeentity_backtrace_dump [entnum]". +// 3. In debugger, track down what functions the spewed addresses refer to. +static ConVar cl_removeentity_backtrace_capture( "cl_removeentity_backtrace_capture", "0", 0, + "For debugging. Capture backtraces for CClientEntityList::OnRemoveEntity calls." ); + +CON_COMMAND( cl_removeentity_backtrace_dump, "Dump backtraces for client OnRemoveEntity calls." ) +{ + if ( !cl_removeentity_backtrace_capture.GetBool() ) + { + Msg( "cl_removeentity_backtrace_dump error: cl_removeentity_backtrace_capture not enabled. Backtraces not captured.\n" ); + return; + } + + int entnum = ( args.ArgC() >= 2 ) ? atoi( args[ 1 ] ) : -1; + + for ( int i = 0; i < ARRAYSIZE( g_RemoveEntityBacktraces ); i++ ) + { + if ( g_RemoveEntityBacktraces[ i ].time && + ( entnum == -1 || g_RemoveEntityBacktraces[ i ].entnum == entnum ) ) + { + Msg( "%d: time:%.2f pBaseEntity:%p\n", g_RemoveEntityBacktraces[i].entnum, + g_RemoveEntityBacktraces[ i ].time, g_RemoveEntityBacktraces[ i ].pBaseEntity ); + for ( int j = 0; j < ARRAYSIZE( g_RemoveEntityBacktraces[ i ].backtrace_addrs ); j++ ) + { + Msg( " %p\n", g_RemoveEntityBacktraces[ i ].backtrace_addrs[ j ] ); + } + } + } +} + +#endif // STAGING_ONLY void CClientEntityList::OnRemoveEntity( IHandleEntity *pEnt, CBaseHandle handle ) { @@ -380,6 +441,13 @@ void CClientEntityList::OnRemoveEntity( IHandleEntity *pEnt, CBaseHandle handle C_BaseEntity *pBaseEntity = pUnknown->GetBaseEntity(); +#if defined( STAGING_ONLY ) + if ( cl_removeentity_backtrace_capture.GetBool() ) + { + OnRemoveEntityBacktraceHook( entnum, pBaseEntity ); + } +#endif // STAGING_ONLY + if ( pBaseEntity ) { if ( pBaseEntity->ObjectCaps() & FCAP_SAVE_NON_NETWORKABLE ) @@ -502,4 +570,4 @@ C_BaseEntity* C_BaseEntityIterator::Next() } return NULL; -}
\ No newline at end of file +} diff --git a/mp/src/game/client/clientmode_shared.cpp b/mp/src/game/client/clientmode_shared.cpp index 5d10db6c..68bc89cb 100644 --- a/mp/src/game/client/clientmode_shared.cpp +++ b/mp/src/game/client/clientmode_shared.cpp @@ -470,8 +470,17 @@ bool ClientModeShared::ShouldDrawEntity(C_BaseEntity *pEnt) return true; } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- bool ClientModeShared::ShouldDrawParticles( ) { +#ifdef TF_CLIENT_DLL + C_TFPlayer *pTFPlayer = C_TFPlayer::GetLocalTFPlayer(); + if ( pTFPlayer && !pTFPlayer->ShouldPlayerDrawParticles() ) + return false; +#endif // TF_CLIENT_DLL + return true; } diff --git a/mp/src/game/client/game_controls/baseviewport.cpp b/mp/src/game/client/game_controls/baseviewport.cpp index 0b99ef63..f239cde8 100644 --- a/mp/src/game/client/game_controls/baseviewport.cpp +++ b/mp/src/game/client/game_controls/baseviewport.cpp @@ -229,12 +229,11 @@ void CBaseViewport::CreateDefaultPanels( void ) AddNewPanel( CreatePanelByName( PANEL_SCOREBOARD ), "PANEL_SCOREBOARD" ); AddNewPanel( CreatePanelByName( PANEL_INFO ), "PANEL_INFO" ); AddNewPanel( CreatePanelByName( PANEL_SPECGUI ), "PANEL_SPECGUI" ); +#if !defined( TF_CLIENT_DLL ) AddNewPanel( CreatePanelByName( PANEL_SPECMENU ), "PANEL_SPECMENU" ); AddNewPanel( CreatePanelByName( PANEL_NAV_PROGRESS ), "PANEL_NAV_PROGRESS" ); - // AddNewPanel( CreatePanelByName( PANEL_TEAM ), "PANEL_TEAM" ); - // AddNewPanel( CreatePanelByName( PANEL_CLASS ), "PANEL_CLASS" ); - // AddNewPanel( CreatePanelByName( PANEL_BUY ), "PANEL_BUY" ); -#endif +#endif // !TF_CLIENT_DLL +#endif // !_XBOX } void CBaseViewport::UpdateAllPanels( void ) diff --git a/mp/src/game/client/game_controls/teammenu.cpp b/mp/src/game/client/game_controls/teammenu.cpp index c242c936..6b98afd7 100644 --- a/mp/src/game/client/game_controls/teammenu.cpp +++ b/mp/src/game/client/game_controls/teammenu.cpp @@ -190,6 +190,7 @@ void CTeamMenu::LoadMapPage( const char *mapName ) char mapRES[ MAX_PATH ]; char uilanguage[ 64 ]; + uilanguage[0] = 0; engine->GetUILanguage( uilanguage, sizeof( uilanguage ) ); Q_snprintf( mapRES, sizeof( mapRES ), "resource/maphtml/%s_%s.html", mapName, uilanguage ); diff --git a/mp/src/game/client/game_controls/vguitextwindow.cpp b/mp/src/game/client/game_controls/vguitextwindow.cpp index 5cdc2532..3c641859 100644 --- a/mp/src/game/client/game_controls/vguitextwindow.cpp +++ b/mp/src/game/client/game_controls/vguitextwindow.cpp @@ -102,11 +102,7 @@ CTextWindow::CTextWindow(IViewPort *pViewPort) : Frame(NULL, PANEL_INFO ) SetTitleBarVisible( false ); m_pTextMessage = new TextEntry( this, "TextMessage" ); -#if defined( ENABLE_CHROMEHTMLWINDOW ) m_pHTMLMessage = new CMOTDHTML( this,"HTMLMessage" ); -#else - m_pHTMLMessage = NULL; -#endif m_pTitleLabel = new Label( this, "MessageTitle", "Message Title" ); m_pOK = new Button(this, "ok", "#PropertyDialog_OK"); @@ -165,7 +161,6 @@ void CTextWindow::ShowText( const char *text ) void CTextWindow::ShowURL( const char *URL, bool bAllowUserToDisable ) { -#if defined( ENABLE_CHROMEHTMLWINDOW ) #ifdef _DEBUG Msg( "CTextWindow::ShowURL( %s )\n", URL ); #endif @@ -196,8 +191,6 @@ void CTextWindow::ShowURL( const char *URL, bool bAllowUserToDisable ) m_pHTMLMessage->SetVisible( true ); m_pHTMLMessage->OpenURL( URL, NULL ); m_bShownURL = true; - -#endif } void CTextWindow::ShowIndex( const char *entry ) @@ -286,9 +279,8 @@ void CTextWindow::Update( void ) m_pTitleLabel->SetText( m_szTitle ); -#if defined( ENABLE_CHROMEHTMLWINDOW ) - m_pHTMLMessage->SetVisible( false ); -#endif + if ( m_pHTMLMessage ) + m_pHTMLMessage->SetVisible( false ); m_pTextMessage->SetVisible( false ); if ( m_nContentType == TYPE_INDEX ) @@ -427,13 +419,11 @@ void CTextWindow::ShowPanel( bool bShow ) SetVisible( false ); SetMouseInputEnabled( false ); -#if defined( ENABLE_CHROMEHTMLWINDOW ) - if ( m_bUnloadOnDismissal && m_bShownURL ) + if ( m_bUnloadOnDismissal && m_bShownURL && m_pHTMLMessage ) { m_pHTMLMessage->OpenURL( "about:blank", NULL ); m_bShownURL = false; } -#endif } } diff --git a/mp/src/game/client/hl2/hud_damageindicator.cpp b/mp/src/game/client/hl2/hud_damageindicator.cpp index 48dd9b62..9de538a0 100644 --- a/mp/src/game/client/hl2/hud_damageindicator.cpp +++ b/mp/src/game/client/hl2/hud_damageindicator.cpp @@ -178,7 +178,7 @@ void CHudDamageIndicator::DrawDamageIndicator(int side) int x1 = m_flDmgX; int x2 = m_flDmgX + m_flDmgWide; - int y[4] = { m_flDmgY, m_flDmgY + insetY, m_flDmgY + m_flDmgTall1 - insetY, m_flDmgY + m_flDmgTall1 }; + int y[4] = { (int)m_flDmgY, (int)(m_flDmgY + insetY), (int)(m_flDmgY + m_flDmgTall1 - insetY), (int)(m_flDmgY + m_flDmgTall1) }; int alpha[4] = { 0.0f, 1.0f, 1.0f, 0.0f }; // see if we're high damage diff --git a/mp/src/game/client/hud_basechat.h b/mp/src/game/client/hud_basechat.h index 90de8fbf..cf5c3f1f 100644 --- a/mp/src/game/client/hud_basechat.h +++ b/mp/src/game/client/hud_basechat.h @@ -241,7 +241,7 @@ public: void MsgFunc_TextMsg(const char *pszName, int iSize, void *pbuf); virtual void Printf( int iFilter, PRINTF_FORMAT_STRING const char *fmt, ... ); - virtual void ChatPrintf( int iPlayerIndex, int iFilter, PRINTF_FORMAT_STRING const char *fmt, ... ); + virtual void ChatPrintf( int iPlayerIndex, int iFilter, PRINTF_FORMAT_STRING const char *fmt, ... ) FMTFUNCTION( 4, 5 ); virtual void StartMessageMode( int iMessageModeType ); virtual void StopMessageMode( void ); diff --git a/mp/src/game/client/hud_basedeathnotice.cpp b/mp/src/game/client/hud_basedeathnotice.cpp index d732bd05..c7499ac6 100644 --- a/mp/src/game/client/hud_basedeathnotice.cpp +++ b/mp/src/game/client/hud_basedeathnotice.cpp @@ -65,6 +65,7 @@ void CHudBaseDeathNotice::Init( void ) ListenForGameEvent( "teamplay_point_captured" ); ListenForGameEvent( "teamplay_capture_blocked" ); ListenForGameEvent( "teamplay_flag_event" ); + ListenForGameEvent( "rd_robot_killed" ); } //----------------------------------------------------------------------------- diff --git a/mp/src/game/client/hud_closecaption.cpp b/mp/src/game/client/hud_closecaption.cpp index f72b9fc1..c1a1fa29 100644 --- a/mp/src/game/client/hud_closecaption.cpp +++ b/mp/src/game/client/hud_closecaption.cpp @@ -844,6 +844,7 @@ CHudCloseCaption::CHudCloseCaption( const char *pElementName ) HOOK_HUD_MESSAGE( CHudCloseCaption, CloseCaption ); char uilanguage[ 64 ]; + uilanguage[0] = 0; engine->GetUILanguage( uilanguage, sizeof( uilanguage ) ); if ( !Q_stricmp( uilanguage, "english" ) ) @@ -2752,6 +2753,7 @@ void OnCaptionLanguageChanged( IConVar *pConVar, const char *pOldString, float f } char uilanguage[ 64 ]; + uilanguage[0] = 0; engine->GetUILanguage( uilanguage, sizeof( uilanguage ) ); CHudCloseCaption *hudCloseCaption = GET_HUDELEMENT( CHudCloseCaption ); diff --git a/mp/src/game/client/hud_vote.cpp b/mp/src/game/client/hud_vote.cpp index 659669a0..64d3e76e 100644 --- a/mp/src/game/client/hud_vote.cpp +++ b/mp/src/game/client/hud_vote.cpp @@ -983,6 +983,12 @@ void CHudVote::MsgFunc_CallVoteFailed( bf_read &msg ) char szTime[256]; wchar_t wszTime[256]; + bool bMinutes = ( nTime > 65 ); + if ( bMinutes ) + { + nTime /= 60; + } + const char *pszTimeString = ( bMinutes ) ? ( ( nTime < 2 ) ? "#GameUI_vote_failed_recently_min" : "#GameUI_vote_failed_recently_mins" ) : "#GameUI_vote_failed_recently"; Q_snprintf( szTime, sizeof ( szTime), "%i", nTime ); g_pVGuiLocalize->ConvertANSIToUnicode( szTime, wszTime, sizeof( wszTime ) ); @@ -1021,8 +1027,8 @@ void CHudVote::MsgFunc_CallVoteFailed( bf_read &msg ) m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_map_name_required" ); break; - case VOTE_FAILED_FAILED_RECENTLY: - g_pVGuiLocalize->ConstructString( wszHeaderString, sizeof(wszHeaderString), g_pVGuiLocalize->Find( "#GameUI_vote_failed_recently" ), 1, wszTime ); + case VOTE_FAILED_ON_COOLDOWN: + g_pVGuiLocalize->ConstructString( wszHeaderString, sizeof( wszHeaderString ), g_pVGuiLocalize->Find( pszTimeString ), 1, wszTime ); pwszHeaderString = wszHeaderString; m_pCallVoteFailed->SetDialogVariable( "FailedReason", pwszHeaderString ); break; diff --git a/mp/src/game/client/particlemgr.cpp b/mp/src/game/client/particlemgr.cpp index d62c6e73..f79d17a6 100644 --- a/mp/src/game/client/particlemgr.cpp +++ b/mp/src/game/client/particlemgr.cpp @@ -97,8 +97,8 @@ CParticleSubTextureGroup::~CParticleSubTextureGroup() CParticleSubTexture::CParticleSubTexture() { - m_tCoordMins[0] = m_tCoordMins[0] = 0; - m_tCoordMaxs[0] = m_tCoordMaxs[0] = 1; + m_tCoordMins[0] = m_tCoordMins[1] = 0; + m_tCoordMaxs[0] = m_tCoordMaxs[1] = 1; m_pGroup = &m_DefaultGroup; m_pMaterial = NULL; diff --git a/mp/src/game/client/replay/vgui/replayperformanceeditor.cpp b/mp/src/game/client/replay/vgui/replayperformanceeditor.cpp index 99178f6e..be274ccb 100644 --- a/mp/src/game/client/replay/vgui/replayperformanceeditor.cpp +++ b/mp/src/game/client/replay/vgui/replayperformanceeditor.cpp @@ -576,7 +576,7 @@ public: BaseClass::PerformLayout(); int nWidth = XRES( 140 ); - int nMargins[2] = { XRES( 5 ), YRES( 5 ) }; + int nMargins[2] = { (int)XRES( 5 ), (int)YRES( 5 ) }; int nVBuf = YRES( 0 ); int nLastY = -1; int nY = nMargins[1]; @@ -1969,7 +1969,7 @@ void CReplayPerformanceEditorPanel::PerformLayout() dynamic_cast< CExLabel * >( m_pPlayerCellsPanel->FindChildByName( "RedLabel" ) ), dynamic_cast< CExLabel * >( m_pPlayerCellsPanel->FindChildByName( "BlueLabel" ) ) }; - int nMargins[2] = { XRES( 5 ), YRES( 2 ) }; + int nMargins[2] = { (int)XRES( 5 ), (int)YRES( 2 ) }; for ( int i = 0; i < 2; ++i ) { pRedBlueLabels[i]->SizeToContents(); diff --git a/mp/src/game/client/vgui_fpspanel.cpp b/mp/src/game/client/vgui_fpspanel.cpp index aec28add..a1e88875 100644 --- a/mp/src/game/client/vgui_fpspanel.cpp +++ b/mp/src/game/client/vgui_fpspanel.cpp @@ -18,6 +18,7 @@ #include "filesystem.h" #include "../common/xbox/xboxstubs.h" #include "steam/steam_api.h" +#include "tier0/cpumonitoring.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -209,6 +210,28 @@ void GetFPSColor( int nFps, unsigned char ucColor[3] ) } //----------------------------------------------------------------------------- +// Purpose: Set the color appropriately based on the CPU's frequency percentage +//----------------------------------------------------------------------------- +void GetCPUColor( float cpuPercentage, unsigned char ucColor[3] ) +{ + // These colors are for poor CPU performance + ucColor[0] = 255; ucColor[1] = 0; ucColor[2] = 0; + + if ( cpuPercentage >= kCPUMonitoringWarning1 ) + { + // Excellent CPU performance + ucColor[0] = 10; + ucColor[1] = 200; + } + else if ( cpuPercentage >= kCPUMonitoringWarning2 ) + { + // Medium CPU performance + ucColor[0] = 220; + ucColor[1] = 220; + } +} + +//----------------------------------------------------------------------------- // Purpose: // Input : //----------------------------------------------------------------------------- @@ -272,6 +295,17 @@ void CFPSPanel::Paint() GetFPSColor( nFps, ucColor ); g_pMatSystemSurface->DrawColoredText( m_hFont, x, 2, ucColor[0], ucColor[1], ucColor[2], 255, "%3i fps on %s", nFps, engine->GetLevelName() ); } + + const CPUFrequencyResults frequency = GetCPUFrequencyResults(); + double currentTime = Plat_FloatTime(); + const double displayTime = 5.0f; // Display frequency results for this long. + if ( frequency.m_GHz > 0 && frequency.m_timeStamp + displayTime > currentTime ) + { + int lineHeight = vgui::surface()->GetFontTall( m_hFont ); + // Optionally print out the CPU frequency monitoring data. + GetCPUColor( frequency.m_percentage, ucColor ); + g_pMatSystemSurface->DrawColoredText( m_hFont, x, lineHeight + 2, ucColor[0], ucColor[1], ucColor[2], 255, "CPU frequency percent: %3.1f%% Min percent: %3.1f%%", frequency.m_percentage, frequency.m_lowestPercentage ); + } } } m_lastRealTime = gpGlobals->realtime; diff --git a/mp/src/game/client/vgui_netgraphpanel.cpp b/mp/src/game/client/vgui_netgraphpanel.cpp index d3837c03..0f601438 100644 --- a/mp/src/game/client/vgui_netgraphpanel.cpp +++ b/mp/src/game/client/vgui_netgraphpanel.cpp @@ -20,6 +20,7 @@ #include <vgui/IScheme.h> #include <vgui/ILocalize.h> #include "tier0/vprof.h" +#include "tier0/cpumonitoring.h" #include "cdll_bounded_cvars.h" #include "materialsystem/imaterialsystem.h" @@ -761,7 +762,7 @@ void CNetGraphPanel::DrawTextFields( int graphvalue, int x, int y, int w, netban Q_snprintf( sz, sizeof( sz ), "lerp: %5.1f ms", GetClientInterpAmount() * 1000.0f ); - int interpcolor[ 3 ] = { GRAPH_RED, GRAPH_GREEN, GRAPH_BLUE }; + int interpcolor[ 3 ] = { (int)GRAPH_RED, (int)GRAPH_GREEN, (int)GRAPH_BLUE }; float flInterp = GetClientInterpAmount(); if ( flInterp > 0.001f ) { @@ -817,7 +818,7 @@ void CNetGraphPanel::DrawTextFields( int graphvalue, int x, int y, int w, netban { Q_snprintf( sz, sizeof( sz ), "sv : %5.1f var: %4.2f msec", m_flServerFramerate, m_flServerFramerateStdDeviation * 1000.0f ); - int servercolor[ 3 ] = { GRAPH_RED, GRAPH_GREEN, GRAPH_BLUE }; + int servercolor[ 3 ] = { (int)GRAPH_RED, (int)GRAPH_GREEN, (int)GRAPH_BLUE }; if ( m_flServerFramerate < 10.0f ) { @@ -876,6 +877,35 @@ void CNetGraphPanel::DrawTextFields( int graphvalue, int x, int y, int w, netban g_pMatSystemSurface->DrawColoredText( m_hFontSmall, x, y, 0, 0, 128, 255, "voice" ); y -= textTall; } + else + { + const CPUFrequencyResults frequency = GetCPUFrequencyResults(); + double currentTime = Plat_FloatTime(); + const double displayTime = 5.0f; // Display frequency results for this long. + if ( frequency.m_GHz > 0 && frequency.m_timeStamp + displayTime > currentTime ) + { + // Optionally print out the CPU frequency monitoring data. + uint8 cpuColor[4] = { (uint8)GRAPH_RED, (uint8)GRAPH_GREEN, (uint8)GRAPH_BLUE, 255 }; + + if ( frequency.m_percentage < kCPUMonitoringWarning2 ) + { + cpuColor[0] = 255; + cpuColor[1] = 31; + cpuColor[2] = 31; + } + else if ( frequency.m_percentage < kCPUMonitoringWarning1 ) + { + cpuColor[0] = 255; + cpuColor[1] = 125; + cpuColor[2] = 31; + } + // Experimental fading out as data becomes stale. Probably too distracting. + //float age = currentTime - frequency.m_timeStamp; + //cpuColor.a *= ( displayTime - age ) / displayTime; + g_pMatSystemSurface->DrawColoredText( font, x, y, cpuColor[0], cpuColor[1], cpuColor[2], cpuColor[3], + "CPU freq: %3.1f%% Min: %3.1f%%", frequency.m_percentage, frequency.m_lowestPercentage ); + } + } } //----------------------------------------------------------------------------- diff --git a/mp/src/game/client/vgui_schemevisualizer.cpp b/mp/src/game/client/vgui_schemevisualizer.cpp index 12070f29..b2a6f774 100644 --- a/mp/src/game/client/vgui_schemevisualizer.cpp +++ b/mp/src/game/client/vgui_schemevisualizer.cpp @@ -177,7 +177,7 @@ void CSchemeVisualizer::AddBordersToList() void CSchemeVisualizer::AddFontsToList() { #ifdef POSIX - const char strOAccent[] = { 0xc3, 0x93, 0x00 }; // UTF-8 for U+00D3 (LATIN CAPITAL LETTER O WITH ACUTE) + const char strOAccent[] = { (char)0xc3, (char)0x93, 0x00 }; // UTF-8 for U+00D3 (LATIN CAPITAL LETTER O WITH ACUTE) #else const uint8 strOAccent[] = { 0xd3, 0x00 }; #endif diff --git a/mp/src/game/client/viewrender.cpp b/mp/src/game/client/viewrender.cpp index a629071b..67a8307c 100644 --- a/mp/src/game/client/viewrender.cpp +++ b/mp/src/game/client/viewrender.cpp @@ -1435,8 +1435,8 @@ static void GetFogColorTransition( fogparams_t *pFogParams, float *pColorPrimary { float flPercent = 1.0f - (( pFogParams->lerptime - gpGlobals->curtime ) / pFogParams->duration ); - float flPrimaryColorLerp[3] = { pFogParams->colorPrimaryLerpTo.GetR(), pFogParams->colorPrimaryLerpTo.GetG(), pFogParams->colorPrimaryLerpTo.GetB() }; - float flSecondaryColorLerp[3] = { pFogParams->colorSecondaryLerpTo.GetR(), pFogParams->colorSecondaryLerpTo.GetG(), pFogParams->colorSecondaryLerpTo.GetB() }; + float flPrimaryColorLerp[3] = { (float)pFogParams->colorPrimaryLerpTo.GetR(), (float)pFogParams->colorPrimaryLerpTo.GetG(), (float)pFogParams->colorPrimaryLerpTo.GetB() }; + float flSecondaryColorLerp[3] = { (float)pFogParams->colorSecondaryLerpTo.GetR(), (float)pFogParams->colorSecondaryLerpTo.GetG(), (float)pFogParams->colorSecondaryLerpTo.GetB() }; CheckAndTransitionColor( flPercent, pColorPrimary, flPrimaryColorLerp ); CheckAndTransitionColor( flPercent, pColorSecondary, flSecondaryColorLerp ); @@ -1459,8 +1459,8 @@ static void GetFogColor( fogparams_t *pFogParams, float *pColor ) } else { - float flPrimaryColor[3] = { pFogParams->colorPrimary.GetR(), pFogParams->colorPrimary.GetG(), pFogParams->colorPrimary.GetB() }; - float flSecondaryColor[3] = { pFogParams->colorSecondary.GetR(), pFogParams->colorSecondary.GetG(), pFogParams->colorSecondary.GetB() }; + float flPrimaryColor[3] = { (float)pFogParams->colorPrimary.GetR(), (float)pFogParams->colorPrimary.GetG(), (float)pFogParams->colorPrimary.GetB() }; + float flSecondaryColor[3] = { (float)pFogParams->colorSecondary.GetR(), (float)pFogParams->colorSecondary.GetG(), (float)pFogParams->colorSecondary.GetB() }; GetFogColorTransition( pFogParams, flPrimaryColor, flSecondaryColor ); diff --git a/mp/src/game/server/AI_Criteria.cpp b/mp/src/game/server/AI_Criteria.cpp index ff84decd..128e9d32 100644 --- a/mp/src/game/server/AI_Criteria.cpp +++ b/mp/src/game/server/AI_Criteria.cpp @@ -27,13 +27,8 @@ AI_CriteriaSet::AI_CriteriaSet() : m_Lookup( 0, 0, CritEntry_t::LessFunc ) //----------------------------------------------------------------------------- AI_CriteriaSet::AI_CriteriaSet( const AI_CriteriaSet& src ) : m_Lookup( 0, 0, CritEntry_t::LessFunc ) { - m_Lookup.Purge(); - for ( short i = src.m_Lookup.FirstInorder(); - i != src.m_Lookup.InvalidIndex(); - i = src.m_Lookup.NextInorder( i ) ) - { - m_Lookup.Insert( src.m_Lookup[ i ] ); - } + // Use fast Copy CUtlRBTree CopyFrom. WARNING: It only handles POD. + m_Lookup.CopyFrom( src.m_Lookup ); } //----------------------------------------------------------------------------- @@ -162,7 +157,6 @@ void AI_CriteriaSet::Describe() { for ( short i = m_Lookup.FirstInorder(); i != m_Lookup.InvalidIndex(); i = m_Lookup.NextInorder( i ) ) { - CritEntry_t *entry = &m_Lookup[ i ]; if ( entry->weight != 1.0f ) @@ -199,9 +193,9 @@ AI_Response::AI_Response() { m_Type = RESPONSE_NONE; m_szResponseName[0] = 0; + m_szMatchingRule[0] = 0; + m_pCriteria = NULL; - m_szMatchingRule[0]=0; - m_szContext = NULL; m_bApplyContextToWorld = false; } @@ -209,13 +203,8 @@ AI_Response::AI_Response() //----------------------------------------------------------------------------- AI_Response::AI_Response( const AI_Response &from ) { - Assert( (void*)(&m_Type) == (void*)this ); m_pCriteria = NULL; - memcpy( this, &from, sizeof(*this) ); - m_pCriteria = NULL; - m_szContext = NULL; - SetContext( from.m_szContext ); - m_bApplyContextToWorld = from.m_bApplyContextToWorld; + *this = from; } //----------------------------------------------------------------------------- @@ -224,20 +213,34 @@ AI_Response::AI_Response( const AI_Response &from ) AI_Response::~AI_Response() { delete m_pCriteria; - delete[] m_szContext; + m_pCriteria = NULL; } //----------------------------------------------------------------------------- AI_Response &AI_Response::operator=( const AI_Response &from ) { Assert( (void*)(&m_Type) == (void*)this ); + + if (this == &from) + return *this; + + m_Type = from.m_Type; + + V_strcpy_safe( m_szResponseName, from.m_szResponseName ); + V_strcpy_safe( m_szMatchingRule, from.m_szMatchingRule ); + delete m_pCriteria; m_pCriteria = NULL; - memcpy( this, &from, sizeof(*this) ); - m_pCriteria = NULL; - m_szContext = NULL; - SetContext( from.m_szContext ); + + // Copy criteria. + if (from.m_pCriteria) + m_pCriteria = new AI_CriteriaSet(*from.m_pCriteria); + + m_Params = from.m_Params; + + m_szContext = from.m_szContext; m_bApplyContextToWorld = from.m_bApplyContextToWorld; + return *this; } @@ -246,15 +249,22 @@ AI_Response &AI_Response::operator=( const AI_Response &from ) // Input : *response - // *criteria - //----------------------------------------------------------------------------- -void AI_Response::Init( ResponseType_t type, const char *responseName, const AI_CriteriaSet& criteria, const AI_ResponseParams& responseparams, const char *ruleName, const char *applyContext, bool bApplyContextToWorld ) +void AI_Response::Init( ResponseType_t type, const char *responseName, const AI_CriteriaSet& criteria, + const AI_ResponseParams& responseparams, const char *ruleName, const char *applyContext, + bool bApplyContextToWorld ) { m_Type = type; - Q_strncpy( m_szResponseName, responseName, sizeof( m_szResponseName ) ); + + V_strcpy_safe( m_szResponseName, responseName ); + V_strcpy_safe( m_szMatchingRule, ruleName ? ruleName : "NULL" ); + // Copy underlying criteria + Assert( !m_pCriteria ); m_pCriteria = new AI_CriteriaSet( criteria ); - Q_strncpy( m_szMatchingRule, ruleName ? ruleName : "NULL", sizeof( m_szMatchingRule ) ); + m_Params = responseparams; - SetContext( applyContext ); + + m_szContext = applyContext; m_bApplyContextToWorld = bApplyContextToWorld; } @@ -269,35 +279,29 @@ void AI_Response::Describe() m_pCriteria->Describe(); } if ( m_szMatchingRule[ 0 ] ) - { DevMsg( "Matched rule '%s', ", m_szMatchingRule ); - } - if ( m_szContext ) - { - DevMsg( "Contexts to set '%s' on %s, ", m_szContext, m_bApplyContextToWorld ? "world" : "speaker" ); - } + if ( m_szContext.Length() ) + DevMsg( "Contexts to set '%s' on %s, ", m_szContext.Get(), m_bApplyContextToWorld ? "world" : "speaker" ); - DevMsg( "response %s = '%s'\n", DescribeResponse( (ResponseType_t)m_Type ), m_szResponseName ); + DevMsg( "response %s = '%s'\n", DescribeResponse( (ResponseType_t)m_Type ), m_szResponseName ); } //----------------------------------------------------------------------------- // Purpose: -// Output : char const //----------------------------------------------------------------------------- -void AI_Response::GetName( char *buf, size_t buflen ) const +const char * AI_Response::GetNamePtr() const { - Q_strncpy( buf, m_szResponseName, buflen ); + return m_szResponseName; } - //----------------------------------------------------------------------------- // Purpose: -// Output : char const //----------------------------------------------------------------------------- -void AI_Response::GetResponse( char *buf, size_t buflen ) const +const char * AI_Response::GetResponsePtr() const { - GetName( buf, buflen ); + return m_szResponseName; } + //----------------------------------------------------------------------------- // Purpose: // Input : type - @@ -313,25 +317,15 @@ const char *AI_Response::DescribeResponse( ResponseType_t type ) switch( type ) { - default: - { - Assert( 0 ); - } - // Fall through - case RESPONSE_NONE: - return "RESPONSE_NONE"; - case RESPONSE_SPEAK: - return "RESPONSE_SPEAK"; - case RESPONSE_SENTENCE: - return "RESPONSE_SENTENCE"; - case RESPONSE_SCENE: - return "RESPONSE_SCENE"; - case RESPONSE_RESPONSE: - return "RESPONSE_RESPONSE"; - case RESPONSE_PRINT: - return "RESPONSE_PRINT"; + case RESPONSE_NONE: return "RESPONSE_NONE"; + case RESPONSE_SPEAK: return "RESPONSE_SPEAK"; + case RESPONSE_SENTENCE: return "RESPONSE_SENTENCE"; + case RESPONSE_SCENE: return "RESPONSE_SCENE"; + case RESPONSE_RESPONSE: return "RESPONSE_RESPONSE"; + case RESPONSE_PRINT: return "RESPONSE_PRINT"; } + Assert( 0 ); return "RESPONSE_NONE"; } @@ -447,16 +441,7 @@ float AI_Response::GetPreDelay() const //----------------------------------------------------------------------------- void AI_Response::SetContext( const char *context ) { - delete[] m_szContext; - m_szContext = NULL; - - if ( context ) - { - int len = Q_strlen( context ); - m_szContext = new char[ len + 1 ]; - Q_memcpy( m_szContext, context, len ); - m_szContext[ len ] = 0; - } + m_szContext = context; } //----------------------------------------------------------------------------- diff --git a/mp/src/game/server/AI_Criteria.h b/mp/src/game/server/AI_Criteria.h index 72c54080..f10c2d05 100644 --- a/mp/src/game/server/AI_Criteria.h +++ b/mp/src/game/server/AI_Criteria.h @@ -84,8 +84,10 @@ private: Q_strncpy( value, str, sizeof( value ) ); } } - - CUtlSymbol criterianame; + + // We use CUtlRBTree CopyFrom() in ctor, so CritEntry_t must be POD. If you add + // CUtlString or something then you must change AI_CriteriaSet copy ctor. + CUtlSymbol criterianame; char value[ 64 ]; float weight; }; @@ -178,10 +180,10 @@ public: ~AI_Response(); AI_Response &operator=( const AI_Response &from ); - void Release(); + void Release(); - void GetName( char *buf, size_t buflen ) const; - void GetResponse( char *buf, size_t buflen ) const; + const char * GetNamePtr() const; + const char * GetResponsePtr() const; const AI_ResponseParams *GetParams() const { return &m_Params; } ResponseType_t GetType() const { return (ResponseType_t)m_Type; } soundlevel_t GetSoundLevel() const; @@ -195,7 +197,7 @@ public: float GetPreDelay() const; void SetContext( const char *context ); - const char * GetContext( void ) const { return m_szContext; } + const char * GetContext( void ) const { return m_szContext.Length() ? m_szContext.Get() : NULL; } bool IsApplyContextToWorld( void ) { return m_bApplyContextToWorld; } @@ -230,7 +232,7 @@ private: AI_ResponseParams m_Params; - char * m_szContext; + CUtlString m_szContext; bool m_bApplyContextToWorld; }; diff --git a/mp/src/game/server/MaterialModifyControl.cpp b/mp/src/game/server/MaterialModifyControl.cpp index 05d8714f..130a10bb 100644 --- a/mp/src/game/server/MaterialModifyControl.cpp +++ b/mp/src/game/server/MaterialModifyControl.cpp @@ -271,7 +271,7 @@ void CMaterialModifyControl::InputStartFloatLerp( inputdata_t &inputdata ) { bool bWrap = atoi(pszParam) != 0; // We don't implement wrap currently. - bWrap = bWrap; + NOTE_UNUSED( bWrap ); // Got all the parameters. Save 'em and return; m_flFloatLerpStartValue = flStartValue; diff --git a/mp/src/game/server/ServerNetworkProperty.cpp b/mp/src/game/server/ServerNetworkProperty.cpp index 5bd93c18..50641b2d 100644 --- a/mp/src/game/server/ServerNetworkProperty.cpp +++ b/mp/src/game/server/ServerNetworkProperty.cpp @@ -108,6 +108,9 @@ IHandleEntity *CServerNetworkProperty::GetEntityHandle( ) void CServerNetworkProperty::Release() { delete m_pOuter; + // Don't zero m_pOuter or reference any member variables after + // the delete call because the object may be deleted. + //m_pOuter = NULL; } diff --git a/mp/src/game/server/ai_activity.cpp b/mp/src/game/server/ai_activity.cpp index a476a9f3..e7ba1761 100644 --- a/mp/src/game/server/ai_activity.cpp +++ b/mp/src/game/server/ai_activity.cpp @@ -2157,4 +2157,33 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_SPELL_VM_IDLE ); ADD_ACTIVITY_TO_SR( ACT_SPELL_VM_ARM ); ADD_ACTIVITY_TO_SR( ACT_SPELL_VM_FIRE ); + + ADD_ACTIVITY_TO_SR( ACT_BREADSAPPER_VM_DRAW ); + ADD_ACTIVITY_TO_SR( ACT_BREADSAPPER_VM_IDLE ); + + ADD_ACTIVITY_TO_SR( ACT_BREADGLOVES_VM_HITLEFT ); + ADD_ACTIVITY_TO_SR( ACT_BREADGLOVES_VM_HITRIGHT ); + ADD_ACTIVITY_TO_SR( ACT_BREADGLOVES_VM_SWINGHARD ); + ADD_ACTIVITY_TO_SR( ACT_BREADGLOVES_VM_IDLE ); + ADD_ACTIVITY_TO_SR( ACT_BREADGLOVES_VM_DRAW ); + + ADD_ACTIVITY_TO_SR( ACT_BREADMONSTER_GLOVES_IDLE ); + ADD_ACTIVITY_TO_SR( ACT_BREADMONSTER_GLOVES_HITRIGHT ); + ADD_ACTIVITY_TO_SR( ACT_BREADMONSTER_GLOVES_HITUP ); + + ADD_ACTIVITY_TO_SR( ACT_BREADMONSTER_VM_DRAW ); + ADD_ACTIVITY_TO_SR( ACT_BREADMONSTER_VM_IDLE ); + ADD_ACTIVITY_TO_SR( ACT_BREADMONSTER_VM_PRIMARYATTACK ); + + ADD_ACTIVITY_TO_SR( ACT_PARACHUTE_DEPLOY ); + ADD_ACTIVITY_TO_SR( ACT_PARACHUTE_DEPLOY_IDLE ); + ADD_ACTIVITY_TO_SR( ACT_PARACHUTE_RETRACT ); + ADD_ACTIVITY_TO_SR( ACT_PARACHUTE_RETRACT_IDLE ); + + ADD_ACTIVITY_TO_SR( ACT_BOT_SPAWN ); + ADD_ACTIVITY_TO_SR( ACT_BOT_PANIC ); + ADD_ACTIVITY_TO_SR( ACT_BOT_PRIMARY_MOVEMENT ); + ADD_ACTIVITY_TO_SR( ACT_BOT_GESTURE_FLINCH ); + ADD_ACTIVITY_TO_SR( ACT_BOT_PANIC_START ); + ADD_ACTIVITY_TO_SR( ACT_BOT_PANIC_END ); } diff --git a/mp/src/game/server/ai_basenpc.cpp b/mp/src/game/server/ai_basenpc.cpp index 1db9eab1..b4442260 100644 --- a/mp/src/game/server/ai_basenpc.cpp +++ b/mp/src/game/server/ai_basenpc.cpp @@ -7710,7 +7710,9 @@ CBaseEntity *CAI_BaseNPC::BestEnemy( void ) if (!pEnemy || !pEnemy->IsAlive()) { if ( pEnemy ) + { DbgEnemyMsg( this, " %s rejected: dead\n", pEnemy->GetDebugName() ); + } continue; } @@ -7785,7 +7787,9 @@ CBaseEntity *CAI_BaseNPC::BestEnemy( void ) { DbgEnemyMsg( this, " %s accepted (1)\n", pEnemy->GetDebugName() ); if ( pBestEnemy ) + { DbgEnemyMsg( this, " (%s displaced)\n", pBestEnemy->GetDebugName() ); + } iBestPriority = IRelationPriority ( pEnemy ); iBestDistSq = (pEnemy->GetAbsOrigin() - GetAbsOrigin() ).LengthSqr(); @@ -7799,7 +7803,9 @@ CBaseEntity *CAI_BaseNPC::BestEnemy( void ) { DbgEnemyMsg( this, " %s accepted\n", pEnemy->GetDebugName() ); if ( pBestEnemy ) + { DbgEnemyMsg( this, " (%s displaced due to priority, %d > %d )\n", pBestEnemy->GetDebugName(), IRelationPriority( pEnemy ), iBestPriority ); + } // this entity is disliked MORE than the entity that we // currently think is the best visible enemy. No need to do // a distance check, just get mad at this one for now. @@ -7933,7 +7939,9 @@ CBaseEntity *CAI_BaseNPC::BestEnemy( void ) DbgEnemyMsg( this, " %s accepted\n", pEnemy->GetDebugName() ); if ( pBestEnemy ) + { DbgEnemyMsg( this, " (%s displaced due to distance/visibility)\n", pBestEnemy->GetDebugName() ); + } fBestSeen = fCurSeen; fBestVisible = fCurVisible; iBestDistSq = iDistSq; @@ -7942,7 +7950,9 @@ CBaseEntity *CAI_BaseNPC::BestEnemy( void ) bBestUnreachable = bUnreachable; } else + { DbgEnemyMsg( this, " %s rejected: lower priority\n", pEnemy->GetDebugName() ); + } } DbgEnemyMsg( this, "} == %s\n", pBestEnemy->GetDebugName() ); @@ -8033,6 +8043,7 @@ float CAI_BaseNPC::CalcIdealYaw( const Vector &vecTarget ) { vecProjection.x = -vecTarget.y; vecProjection.y = vecTarget.x; + vecProjection.z = 0; return UTIL_VecToYaw( vecProjection - GetLocalOrigin() ); } @@ -8040,6 +8051,7 @@ float CAI_BaseNPC::CalcIdealYaw( const Vector &vecTarget ) { vecProjection.x = vecTarget.y; vecProjection.y = vecTarget.x; + vecProjection.z = 0; return UTIL_VecToYaw( vecProjection - GetLocalOrigin() ); } diff --git a/mp/src/game/server/ai_basenpc.h b/mp/src/game/server/ai_basenpc.h index 2131a0f4..7c65c0cc 100644 --- a/mp/src/game/server/ai_basenpc.h +++ b/mp/src/game/server/ai_basenpc.h @@ -1761,7 +1761,6 @@ public: virtual Activity GetFlinchActivity( bool bHeavyDamage, bool bGesture ); - virtual bool ShouldGib( const CTakeDamageInfo &info ) { return false; } // Always ragdoll, unless specified by the leaf class virtual bool Event_Gibbed( const CTakeDamageInfo &info ); virtual void Event_Killed( const CTakeDamageInfo &info ); diff --git a/mp/src/game/server/ai_behavior_lead.cpp b/mp/src/game/server/ai_behavior_lead.cpp index 6a316c1e..9cee1951 100644 --- a/mp/src/game/server/ai_behavior_lead.cpp +++ b/mp/src/game/server/ai_behavior_lead.cpp @@ -269,7 +269,7 @@ bool CAI_LeadBehavior::GetClosestPointOnRoute( const Vector &targetPos, Vector * float flNearestDist = 999999999; float flPathDist, flPathDist2D; - Vector vecNearestPoint; + Vector vecNearestPoint(0, 0, 0); Vector vecPrevPos = GetOuter()->GetAbsOrigin(); for ( ; (waypoint != NULL) ; waypoint = waypoint->GetNext() ) { diff --git a/mp/src/game/server/ai_blended_movement.cpp b/mp/src/game/server/ai_blended_movement.cpp index d1b32d14..7c4ba8af 100644 --- a/mp/src/game/server/ai_blended_movement.cpp +++ b/mp/src/game/server/ai_blended_movement.cpp @@ -1864,7 +1864,7 @@ float ChangeDistance( float flInterval, float flGoalDistance, float flGoalVeloci // I need to speed up flNewVelocity = flCurVelocity + flGoalAccel * flInterval; if (flNewVelocity > flGoalVelocity) - flGoalVelocity = flGoalVelocity; + flNewVelocity = flGoalVelocity; } else if (flNewVelocity < flIdealVelocity) { diff --git a/mp/src/game/server/ai_debug.h b/mp/src/game/server/ai_debug.h index 8a438d70..3f5c47fb 100644 --- a/mp/src/game/server/ai_debug.h +++ b/mp/src/game/server/ai_debug.h @@ -51,8 +51,8 @@ enum AIMsgFlags AIMF_IGNORE_SELECTED = 0x01 }; -void DevMsg( CAI_BaseNPC *pAI, unsigned flags, PRINTF_FORMAT_STRING const char *pszFormat, ... ); -void DevMsg( CAI_BaseNPC *pAI, PRINTF_FORMAT_STRING const char *pszFormat, ... ); +void DevMsg( CAI_BaseNPC *pAI, unsigned flags, PRINTF_FORMAT_STRING const char *pszFormat, ... ) FMTFUNCTION( 3, 4 ); +void DevMsg( CAI_BaseNPC *pAI, PRINTF_FORMAT_STRING const char *pszFormat, ... ) FMTFUNCTION( 2, 3 ); //----------------------------------------------------------------------------- diff --git a/mp/src/game/server/ai_movesolver.cpp b/mp/src/game/server/ai_movesolver.cpp index 101056a7..2f06a5b8 100644 --- a/mp/src/game/server/ai_movesolver.cpp +++ b/mp/src/game/server/ai_movesolver.cpp @@ -114,7 +114,7 @@ bool CAI_MoveSolver::Solve( const AI_MoveSuggestion_t *pSuggestions, int nSugges AI_MoveSuggestion_t *pHighSuggestion; }; - Solution_t solutions[NUM_SOLUTIONS] = { 0 }; + Solution_t solutions[NUM_SOLUTIONS] = { { 0, 0, NULL } }; //--------------------------------- diff --git a/mp/src/game/server/ai_navigator.h b/mp/src/game/server/ai_navigator.h index a2100943..c84932be 100644 --- a/mp/src/game/server/ai_navigator.h +++ b/mp/src/game/server/ai_navigator.h @@ -43,7 +43,7 @@ extern ConVar ai_debug_nav; do \ { \ if (DbgNav()) \ - DevMsg( pAI, CFmtStr( "[Nav] %s", static_cast<const char *>(pszMsg) ) ); \ + DevMsg( pAI, "[Nav] %s", static_cast<const char *>(pszMsg) ); \ } while (0) #define DbgNavMsg1( pAI, pszMsg, a ) DbgNavMsg( pAI, CFmtStr(static_cast<const char *>(pszMsg), (a) ) ) #define DbgNavMsg2( pAI, pszMsg, a, b ) DbgNavMsg( pAI, CFmtStr(static_cast<const char *>(pszMsg), (a), (b) ) ) diff --git a/mp/src/game/server/ai_playerally.cpp b/mp/src/game/server/ai_playerally.cpp index 1f371fc9..1ce4da31 100644 --- a/mp/src/game/server/ai_playerally.cpp +++ b/mp/src/game/server/ai_playerally.cpp @@ -548,10 +548,11 @@ void CAI_PlayerAlly::PrescheduleThink( void ) if ( m_flNextIdleSpeechTime && m_flNextIdleSpeechTime < gpGlobals->curtime ) { AISpeechSelection_t selection; + if ( SelectNonCombatSpeech( &selection ) ) { SetSpeechTarget( selection.hSpeechTarget ); - SpeakDispatchResponse( selection.concept.c_str(), selection.pResponse ); + SpeakDispatchResponse( selection.concept.c_str(), selection.Response ); m_flNextIdleSpeechTime = gpGlobals->curtime + RandomFloat( 20,30 ); } else @@ -593,22 +594,23 @@ bool CAI_PlayerAlly::SelectSpeechResponse( AIConcept_t concept, const char *pszM { if ( IsAllowedToSpeak( concept ) ) { - AI_Response *pResponse = SpeakFindResponse( concept, pszModifiers ); - if ( pResponse ) + bool result = SpeakFindResponse( pSelection->Response, concept, pszModifiers ); + if ( result ) { - pSelection->Set( concept, pResponse, pTarget ); + pSelection->concept = concept; + pSelection->hSpeechTarget = pTarget; return true; } } + return false; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -void CAI_PlayerAlly::SetPendingSpeech( AIConcept_t concept, AI_Response *pResponse ) +void CAI_PlayerAlly::SetPendingSpeech( AIConcept_t concept, AI_Response &Response ) { - m_PendingResponse = *pResponse; - pResponse->Release(); + m_PendingResponse = Response; m_PendingConcept = concept; m_TimePendingSet = gpGlobals->curtime; } @@ -690,7 +692,7 @@ bool CAI_PlayerAlly::SelectInterjection() if ( SelectIdleSpeech( &selection ) ) { SetSpeechTarget( selection.hSpeechTarget ); - SpeakDispatchResponse( selection.concept.c_str(), selection.pResponse ); + SpeakDispatchResponse( selection.concept.c_str(), selection.Response ); return true; } } @@ -889,9 +891,8 @@ void CAI_PlayerAlly::AnswerQuestion( CAI_PlayerAlly *pQuestioner, int iQARandomN } } - Assert( selection.pResponse ); SetSpeechTarget( selection.hSpeechTarget ); - SpeakDispatchResponse( selection.concept.c_str(), selection.pResponse ); + SpeakDispatchResponse( selection.concept.c_str(), selection.Response ); // Prevent idle speech for a while DeferAllIdleSpeech( random->RandomFloat( TALKER_DEFER_IDLE_SPEAK_MIN, TALKER_DEFER_IDLE_SPEAK_MAX ), GetSpeechTarget()->MyNPCPointer() ); @@ -939,11 +940,11 @@ int CAI_PlayerAlly::SelectNonCombatSpeechSchedule() if ( !HasPendingSpeech() ) { AISpeechSelection_t selection; + if ( SelectNonCombatSpeech( &selection ) ) { - Assert( selection.pResponse ); SetSpeechTarget( selection.hSpeechTarget ); - SetPendingSpeech( selection.concept.c_str(), selection.pResponse ); + SetPendingSpeech( selection.concept.c_str(), selection.Response ); } } @@ -1018,14 +1019,14 @@ void CAI_PlayerAlly::StartTask( const Task_t *pTask ) case TASK_TALKER_SPEAK_PENDING: if ( !m_PendingConcept.empty() ) { - AI_Response *pResponse = new AI_Response; - *pResponse = m_PendingResponse; - SpeakDispatchResponse( m_PendingConcept.c_str(), pResponse ); + SpeakDispatchResponse( m_PendingConcept.c_str(), m_PendingResponse ); m_PendingConcept.erase(); TaskComplete(); } else + { TaskFail( FAIL_NO_SOUND ); + } break; default: @@ -1692,15 +1693,15 @@ bool CAI_PlayerAlly::RespondedTo( const char *ResponseConcept, bool bForce, bool { // We're being forced to respond to the event, probably because it's the // player dying or something equally important. - AI_Response *result = SpeakFindResponse( ResponseConcept, NULL ); + AI_Response response; + bool result = SpeakFindResponse( response, ResponseConcept, NULL ); if ( result ) { // We've got something to say. Stop any scenes we're in, and speak the response. if ( bCancelScene ) RemoveActorFromScriptedScenes( this, false ); - bool spoke = SpeakDispatchResponse( ResponseConcept, result ); - return spoke; + return SpeakDispatchResponse( ResponseConcept, response ); } return false; diff --git a/mp/src/game/server/ai_playerally.h b/mp/src/game/server/ai_playerally.h index 173b045a..bd1e5ab4 100644 --- a/mp/src/game/server/ai_playerally.h +++ b/mp/src/game/server/ai_playerally.h @@ -248,21 +248,9 @@ enum AISpeechTargetSearchFlags_t struct AISpeechSelection_t { - AISpeechSelection_t() - : pResponse(NULL) - { - } - - void Set( AIConcept_t newConcept, AI_Response *pNewResponse, CBaseEntity *pTarget = NULL ) - { - pResponse = pNewResponse; - concept = newConcept; - hSpeechTarget = pTarget; - } - - std::string concept; - AI_Response * pResponse; - EHANDLE hSpeechTarget; + std::string concept; + AI_Response Response; + EHANDLE hSpeechTarget; }; //------------------------------------- @@ -347,7 +335,7 @@ public: //--------------------------------- bool SelectSpeechResponse( AIConcept_t concept, const char *pszModifiers, CBaseEntity *pTarget, AISpeechSelection_t *pSelection ); - void SetPendingSpeech( AIConcept_t concept, AI_Response *pResponse ); + void SetPendingSpeech( AIConcept_t concept, AI_Response &Response ); void ClearPendingSpeech(); bool HasPendingSpeech() { return !m_PendingConcept.empty(); } diff --git a/mp/src/game/server/ai_speech.cpp b/mp/src/game/server/ai_speech.cpp index d98fe7b8..da85fdd9 100644 --- a/mp/src/game/server/ai_speech.cpp +++ b/mp/src/game/server/ai_speech.cpp @@ -38,10 +38,7 @@ CAI_TimedSemaphore g_AIFoesTalkSemaphore; ConceptHistory_t::~ConceptHistory_t() { - if ( response ) - { - delete response; - } + delete response; response = NULL; } @@ -57,14 +54,16 @@ ConceptHistory_t::ConceptHistory_t( const ConceptHistory_t& src ) ConceptHistory_t& ConceptHistory_t::operator =( const ConceptHistory_t& src ) { - if ( this == &src ) - return *this; - - timeSpoken = src.timeSpoken; - response = NULL; - if ( src.response ) + if ( this != &src ) { - response = new AI_Response( *src.response ); + timeSpoken = src.timeSpoken; + + delete response; + response = NULL; + if ( src.response ) + { + response = new AI_Response( *src.response ); + } } return *this; @@ -89,14 +88,14 @@ public: pSave->StartBlock(); { - // Write element name pSave->WriteString( ch->GetElementName( i ) ); // Write data pSave->WriteAll( pHistory ); + // Write response blob - bool hasresponse = pHistory->response != NULL ? true : false; + bool hasresponse = !!pHistory->response; pSave->WriteBool( &hasresponse ); if ( hasresponse ) { @@ -118,6 +117,7 @@ public: { char conceptname[ 512 ]; conceptname[ 0 ] = 0; + ConceptHistory_t history; pRestore->StartBlock(); @@ -127,7 +127,6 @@ public: pRestore->ReadAll( &history ); bool hasresponse = false; - pRestore->ReadBool( &hasresponse ); if ( hasresponse ) { @@ -151,7 +150,7 @@ public: } } } - + virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) { } @@ -251,14 +250,14 @@ void CAI_Expresser::TestAllResponses() if ( pResponseSystem ) { CUtlVector<AI_Response *> responses; + pResponseSystem->GetAllResponses( &responses ); for ( int i = 0; i < responses.Count(); i++ ) { - char response[ 256 ]; - responses[i]->GetResponse( response, sizeof( response ) ); + const char *szResponse = responses[i]->GetResponsePtr(); - Msg( "Response: %s\n", response ); - SpeakDispatchResponse( "", responses[i] ); + Msg( "Response: %s\n", szResponse ); + SpeakDispatchResponse( "", *responses[i] ); } } } @@ -273,13 +272,13 @@ static const int LEN_SPECIFIC_SCENE_MODIFIER = strlen( AI_SPECIFIC_SCENE_MODIFIE // NULL - // Output : AI_Response //----------------------------------------------------------------------------- -AI_Response *CAI_Expresser::SpeakFindResponse( AIConcept_t concept, const char *modifiers /*= NULL*/ ) +bool CAI_Expresser::SpeakFindResponse( AI_Response &outResponse, AIConcept_t concept, const char *modifiers /*= NULL*/ ) { IResponseSystem *rs = GetOuter()->GetResponseSystem(); if ( !rs ) { Assert( !"No response system installed for CAI_Expresser::GetOuter()!!!" ); - return NULL; + return false; } AI_CriteriaSet set; @@ -287,7 +286,7 @@ AI_Response *CAI_Expresser::SpeakFindResponse( AIConcept_t concept, const char * set.AppendCriteria( "concept", concept, CONCEPT_WEIGHT ); // Always include any optional modifiers - if ( modifiers != NULL ) + if ( modifiers ) { char copy_modifiers[ 255 ]; const char *pCopy; @@ -320,30 +319,19 @@ AI_Response *CAI_Expresser::SpeakFindResponse( AIConcept_t concept, const char * } // Now that we have a criteria set, ask for a suitable response - AI_Response *result = new AI_Response; - Assert( result && "new AI_Response: Returned a NULL AI_Response!" ); - bool found = rs->FindBestResponse( set, *result, this ); + bool found = rs->FindBestResponse( set, outResponse, this ); if ( rr_debugresponses.GetInt() == 3 ) { if ( ( GetOuter()->MyNPCPointer() && GetOuter()->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT ) || GetOuter()->IsPlayer() ) { - const char *pszName; - if ( GetOuter()->IsPlayer() ) - { - pszName = ((CBasePlayer*)GetOuter())->GetPlayerName(); - } - else - { - pszName = GetOuter()->GetDebugName(); - } + const char *pszName = GetOuter()->IsPlayer() ? + ((CBasePlayer*)GetOuter())->GetPlayerName() : GetOuter()->GetDebugName(); if ( found ) { - char response[ 256 ]; - result->GetResponse( response, sizeof( response ) ); - - Warning( "RESPONSERULES: %s spoke '%s'. Found response '%s'.\n", pszName, concept, response ); + const char *szReponse = outResponse.GetResponsePtr(); + Warning( "RESPONSERULES: %s spoke '%s'. Found response '%s'.\n", pszName, concept, szReponse ); } else { @@ -353,44 +341,28 @@ AI_Response *CAI_Expresser::SpeakFindResponse( AIConcept_t concept, const char * } if ( !found ) - { - //Assert( !"rs->FindBestResponse: Returned a NULL AI_Response!" ); - delete result; - return NULL; - } - - char response[ 256 ]; - result->GetResponse( response, sizeof( response ) ); + return false; - if ( !response[0] ) - { - delete result; - return NULL; - } + const char *szReponse = outResponse.GetResponsePtr(); + if ( !szReponse[0] ) + return false; - if ( result->GetOdds() < 100 && random->RandomInt( 1, 100 ) <= result->GetOdds() ) - { - delete result; - return NULL; - } + if ( ( outResponse.GetOdds() < 100 ) && ( random->RandomInt( 1, 100 ) <= outResponse.GetOdds() ) ) + return false; - return result; + return true; } //----------------------------------------------------------------------------- // Purpose: Dispatches the result // Input : *response - //----------------------------------------------------------------------------- -bool CAI_Expresser::SpeakDispatchResponse( AIConcept_t concept, AI_Response *result, IRecipientFilter *filter /* = NULL */ ) +bool CAI_Expresser::SpeakDispatchResponse( AIConcept_t concept, AI_Response& response, IRecipientFilter *filter /* = NULL */ ) { - char response[ 256 ]; - result->GetResponse( response, sizeof( response ) ); - - float delay = result->GetDelay(); - bool spoke = false; - - soundlevel_t soundlevel = result->GetSoundLevel(); + float delay = response.GetDelay(); + const char *szResponse = response.GetResponsePtr(); + soundlevel_t soundlevel = response.GetSoundLevel(); if ( IsSpeaking() && concept[0] != 0 ) { @@ -404,63 +376,52 @@ bool CAI_Expresser::SpeakDispatchResponse( AIConcept_t concept, AI_Response *res if ( IsRunningScriptedScene( GetOuter() ) ) { DevMsg( "SpeakDispatchResponse: Entity ( %i/%s ) refusing to speak due to scene entity, tossing '%s'\n", GetOuter()->entindex(), STRING( GetOuter()->GetEntityName() ), concept ); - delete result; return false; } } - switch ( result->GetType() ) + switch ( response.GetType() ) { default: case RESPONSE_NONE: break; case RESPONSE_SPEAK: + if ( !response.ShouldntUseScene() ) { - if ( !result->ShouldntUseScene() ) - { - // This generates a fake CChoreoScene wrapping the sound.txt name - spoke = SpeakAutoGeneratedScene( response, delay ); - } - else - { - float speakTime = GetResponseDuration( result ); - GetOuter()->EmitSound( response ); + // This generates a fake CChoreoScene wrapping the sound.txt name + spoke = SpeakAutoGeneratedScene( szResponse, delay ); + } + else + { + float speakTime = GetResponseDuration( response ); + GetOuter()->EmitSound( szResponse ); - DevMsg( "SpeakDispatchResponse: Entity ( %i/%s ) playing sound '%s'\n", GetOuter()->entindex(), STRING( GetOuter()->GetEntityName() ), response ); - NoteSpeaking( speakTime, delay ); - spoke = true; - } + DevMsg( "SpeakDispatchResponse: Entity ( %i/%s ) playing sound '%s'\n", GetOuter()->entindex(), STRING( GetOuter()->GetEntityName() ), szResponse ); + NoteSpeaking( speakTime, delay ); + spoke = true; } break; case RESPONSE_SENTENCE: - { - spoke = ( -1 != SpeakRawSentence( response, delay, VOL_NORM, soundlevel ) ) ? true : false; - } + spoke = ( -1 != SpeakRawSentence( szResponse, delay, VOL_NORM, soundlevel ) ) ? true : false; break; case RESPONSE_SCENE: - { - spoke = SpeakRawScene( response, delay, result, filter ); - } + spoke = SpeakRawScene( szResponse, delay, &response, filter ); break; case RESPONSE_RESPONSE: - { - // This should have been recursively resolved already - Assert( 0 ); - } + // This should have been recursively resolved already + Assert( 0 ); break; case RESPONSE_PRINT: + if ( g_pDeveloper->GetInt() > 0 ) { - if ( g_pDeveloper->GetInt() > 0 ) - { - Vector vPrintPos; - GetOuter()->CollisionProp()->NormalizedToWorldSpace( Vector(0.5,0.5,1.0f), &vPrintPos ); - NDebugOverlay::Text( vPrintPos, response, true, 1.5 ); - spoke = true; - } + Vector vPrintPos; + GetOuter()->CollisionProp()->NormalizedToWorldSpace( Vector(0.5,0.5,1.0f), &vPrintPos ); + NDebugOverlay::Text( vPrintPos, szResponse, true, 1.5 ); + spoke = true; } break; } @@ -468,30 +429,27 @@ bool CAI_Expresser::SpeakDispatchResponse( AIConcept_t concept, AI_Response *res if ( spoke ) { m_flLastTimeAcceptedSpeak = gpGlobals->curtime; - if ( DebuggingSpeech() && g_pDeveloper->GetInt() > 0 && response && result->GetType() != RESPONSE_PRINT ) + if ( DebuggingSpeech() && g_pDeveloper->GetInt() > 0 && response.GetType() != RESPONSE_PRINT ) { Vector vPrintPos; GetOuter()->CollisionProp()->NormalizedToWorldSpace( Vector(0.5,0.5,1.0f), &vPrintPos ); - NDebugOverlay::Text( vPrintPos, CFmtStr( "%s: %s", concept, response ), true, 1.5 ); + NDebugOverlay::Text( vPrintPos, CFmtStr( "%s: %s", concept, szResponse ), true, 1.5 ); } - if ( result->IsApplyContextToWorld() ) + if ( response.IsApplyContextToWorld() ) { CBaseEntity *pEntity = CBaseEntity::Instance( engine->PEntityOfEntIndex( 0 ) ); if ( pEntity ) { - pEntity->AddContext( result->GetContext() ); + pEntity->AddContext( response.GetContext() ); } } else { - GetOuter()->AddContext( result->GetContext() ); + GetOuter()->AddContext( response.GetContext() ); } - SetSpokeConcept( concept, result ); - } - else - { - delete result; + + SetSpokeConcept( concept, &response ); } return spoke; @@ -502,44 +460,33 @@ bool CAI_Expresser::SpeakDispatchResponse( AIConcept_t concept, AI_Response *res // Input : *response - // Output : float //----------------------------------------------------------------------------- -float CAI_Expresser::GetResponseDuration( AI_Response *result ) +float CAI_Expresser::GetResponseDuration( AI_Response& response ) { - Assert( result ); - char response[ 256 ]; - result->GetResponse( response, sizeof( response ) ); + const char *szResponse = response.GetResponsePtr(); - switch ( result->GetType() ) + switch ( response.GetType() ) { default: case RESPONSE_NONE: break; + case RESPONSE_SPEAK: - { - return GetOuter()->GetSoundDuration( response, STRING( GetOuter()->GetModelName() ) ); - } - break; + return GetOuter()->GetSoundDuration( szResponse, STRING( GetOuter()->GetModelName() ) ); + case RESPONSE_SENTENCE: - { - Assert( 0 ); - return 999.0f; - } - break; + Assert( 0 ); + return 999.0f; + case RESPONSE_SCENE: - { - return GetSceneDuration( response ); - } - break; + return GetSceneDuration( szResponse ); + case RESPONSE_RESPONSE: - { - // This should have been recursively resolved already - Assert( 0 ); - } + // This should have been recursively resolved already + Assert( 0 ); break; + case RESPONSE_PRINT: - { - return 1.0; - } - break; + return 1.0; } return 0.0f; @@ -552,18 +499,18 @@ float CAI_Expresser::GetResponseDuration( AI_Response *result ) //----------------------------------------------------------------------------- bool CAI_Expresser::Speak( AIConcept_t concept, const char *modifiers /*= NULL*/, char *pszOutResponseChosen /* = NULL*/, size_t bufsize /* = 0 */, IRecipientFilter *filter /* = NULL */ ) { - AI_Response *result = SpeakFindResponse( concept, modifiers ); + AI_Response response; + bool result = SpeakFindResponse( response, concept, modifiers ); if ( !result ) - { return false; - } SpeechMsg( GetOuter(), "%s (%p) spoke %s (%f)\n", STRING(GetOuter()->GetEntityName()), GetOuter(), concept, gpGlobals->curtime ); - bool spoke = SpeakDispatchResponse( concept, result, filter ); + bool spoke = SpeakDispatchResponse( concept, response, filter ); if ( pszOutResponseChosen ) { - result->GetResponse( pszOutResponseChosen, bufsize ); + const char *szResponse = response.GetResponsePtr(); + Q_strncpy( pszOutResponseChosen, szResponse, bufsize ); } return spoke; @@ -808,17 +755,12 @@ void CAI_Expresser::SetSpokeConcept( AIConcept_t concept, AI_Response *response, ConceptHistory_t *slot = &m_ConceptHistories[ idx ]; slot->timeSpoken = gpGlobals->curtime; + // Update response info if ( response ) { - AI_Response *r = slot->response; - if ( r ) - { - delete r; - } - - // FIXME: Are we leaking AI_Responses? - slot->response = response; + delete slot->response; + slot->response = new AI_Response( *response ); } if ( bCallback ) @@ -885,13 +827,13 @@ void CAI_Expresser::SpeechMsg( CBaseEntity *pFlex, const char *pszFormat, ... ) if ( pFlex->MyNPCPointer() ) { - DevMsg( pFlex->MyNPCPointer(), string ); + DevMsg( pFlex->MyNPCPointer(), "%s", string ); } else { DevMsg( "%s", string ); } - UTIL_LogPrintf( string ); + UTIL_LogPrintf( "%s", string ); } diff --git a/mp/src/game/server/ai_speech.h b/mp/src/game/server/ai_speech.h index 683b4e62..fa173c1e 100644 --- a/mp/src/game/server/ai_speech.h +++ b/mp/src/game/server/ai_speech.h @@ -135,7 +135,7 @@ struct ConceptHistory_t ConceptHistory_t& operator = ( const ConceptHistory_t& src ); ~ConceptHistory_t(); - + float timeSpoken; AI_Response *response; }; @@ -159,9 +159,9 @@ public: bool Speak( AIConcept_t concept, const char *modifiers = NULL, char *pszOutResponseChosen = NULL, size_t bufsize = 0, IRecipientFilter *filter = NULL ); // These two methods allow looking up a response and dispatching it to be two different steps - AI_Response *SpeakFindResponse( AIConcept_t concept, const char *modifiers = NULL ); - bool SpeakDispatchResponse( AIConcept_t concept, AI_Response *response, IRecipientFilter *filter = NULL ); - float GetResponseDuration( AI_Response *response ); + bool SpeakFindResponse( AI_Response &response, AIConcept_t concept, const char *modifiers = NULL ); + bool SpeakDispatchResponse( AIConcept_t concept, AI_Response &response, IRecipientFilter *filter = NULL ); + float GetResponseDuration( AI_Response &response ); virtual int SpeakRawSentence( const char *pszSentence, float delay, float volume = VOL_NORM, soundlevel_t soundlevel = SNDLVL_TALKING, CBaseEntity *pListener = NULL ); @@ -283,10 +283,10 @@ public: virtual bool Speak( AIConcept_t concept, const char *modifiers = NULL, char *pszOutResponseChosen = NULL, size_t bufsize = 0, IRecipientFilter *filter = NULL ); // These two methods allow looking up a response and dispatching it to be two different steps - AI_Response * SpeakFindResponse( AIConcept_t concept, const char *modifiers = NULL ); - bool SpeakDispatchResponse( AIConcept_t concept, AI_Response *response ); - virtual void PostSpeakDispatchResponse( AIConcept_t concept, AI_Response *response ) { return; } - float GetResponseDuration( AI_Response *response ); + bool SpeakFindResponse( AI_Response& response, AIConcept_t concept, const char *modifiers = NULL ); + bool SpeakDispatchResponse( AIConcept_t concept, AI_Response& response ); + virtual void PostSpeakDispatchResponse( AIConcept_t concept, AI_Response& response ) { return; } + float GetResponseDuration( AI_Response& response ); float GetTimeSpeechComplete() const { return this->GetExpresser()->GetTimeSpeechComplete(); } @@ -360,15 +360,15 @@ inline IResponseSystem *CAI_ExpresserHost<BASE_NPC>::GetResponseSystem() //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- template <class BASE_NPC> -inline AI_Response *CAI_ExpresserHost<BASE_NPC>::SpeakFindResponse( AIConcept_t concept, const char *modifiers /*= NULL*/ ) +inline bool CAI_ExpresserHost<BASE_NPC>::SpeakFindResponse( AI_Response& response, AIConcept_t concept, const char *modifiers /*= NULL*/ ) { - return this->GetExpresser()->SpeakFindResponse( concept, modifiers ); + return this->GetExpresser()->SpeakFindResponse( response, concept, modifiers ); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- template <class BASE_NPC> -inline bool CAI_ExpresserHost<BASE_NPC>::SpeakDispatchResponse( AIConcept_t concept, AI_Response *response ) +inline bool CAI_ExpresserHost<BASE_NPC>::SpeakDispatchResponse( AIConcept_t concept, AI_Response& response ) { if ( this->GetExpresser()->SpeakDispatchResponse( concept, response ) ) { @@ -382,7 +382,7 @@ inline bool CAI_ExpresserHost<BASE_NPC>::SpeakDispatchResponse( AIConcept_t conc //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- template <class BASE_NPC> -inline float CAI_ExpresserHost<BASE_NPC>::GetResponseDuration( AI_Response *response ) +inline float CAI_ExpresserHost<BASE_NPC>::GetResponseDuration( AI_Response& response ) { return this->GetExpresser()->GetResponseDuration( response ); } diff --git a/mp/src/game/server/baseentity.cpp b/mp/src/game/server/baseentity.cpp index b42f2abe..7a7a7e6c 100644 --- a/mp/src/game/server/baseentity.cpp +++ b/mp/src/game/server/baseentity.cpp @@ -344,6 +344,8 @@ void CBaseEntityModelLoadProxy::Handler::OnModelLoadComplete( const model_t *pMo CBaseEntity::CBaseEntity( bool bServerOnly ) { + m_pAttributes = NULL; + COMPILE_TIME_ASSERT( MOVETYPE_LAST < (1 << MOVETYPE_MAX_BITS) ); COMPILE_TIME_ASSERT( MOVECOLLIDE_COUNT < (1 << MOVECOLLIDE_MAX_BITS) ); @@ -4822,7 +4824,7 @@ void CBaseEntity::PrecacheModelComponents( int nModelIndex ) char token[256]; const char *pOptions = pEvent->pszOptions(); nexttoken( token, pOptions, ' ' ); - if ( token ) + if ( token[0] ) { PrecacheParticleSystem( token ); } @@ -4908,7 +4910,9 @@ int CBaseEntity::PrecacheModel( const char *name, bool bPreload ) { if ( !name || !*name ) { +#ifdef STAGING_ONLY Msg( "Attempting to precache model, but model name is NULL\n"); +#endif return -1; } @@ -4917,8 +4921,7 @@ int CBaseEntity::PrecacheModel( const char *name, bool bPreload ) { if ( !engine->IsModelPrecached( name ) ) { - Assert( !"CBaseEntity::PrecacheModel: too late" ); - Warning( "Late precache of %s\n", name ); + DevMsg( "Late precache of %s -- not necessarily a bug now that we allow ~everything to be dynamically loaded.\n", name ); } } #if defined( WATCHACCESS ) @@ -5316,11 +5319,6 @@ void CC_Ent_FireTarget( const CCommand& args ) } static ConCommand firetarget("firetarget", CC_Ent_FireTarget, 0, FCVAR_CHEAT); -static bool UtlStringLessFunc( const CUtlString &lhs, const CUtlString &rhs ) -{ - return Q_stricmp( lhs.String(), rhs.String() ) < 0; -} - class CEntFireAutoCompletionFunctor : public ICommandCallback, public ICommandCompletionCallback { public: @@ -6656,23 +6654,19 @@ void CBaseEntity::DispatchResponse( const char *conceptName ) AI_Response result; bool found = rs->FindBestResponse( set, result ); if ( !found ) - { return; - } // Handle the response here... - char response[ 256 ]; - result.GetResponse( response, sizeof( response ) ); + const char *szResponse = result.GetResponsePtr(); switch ( result.GetType() ) { case RESPONSE_SPEAK: - { - EmitSound( response ); - } + EmitSound( szResponse ); break; + case RESPONSE_SENTENCE: { - int sentenceIndex = SENTENCEG_Lookup( response ); + int sentenceIndex = SENTENCEG_Lookup( szResponse ); if( sentenceIndex == -1 ) { // sentence not found @@ -6684,16 +6678,13 @@ void CBaseEntity::DispatchResponse( const char *conceptName ) CBaseEntity::EmitSentenceByIndex( filter, entindex(), CHAN_VOICE, sentenceIndex, 1, result.GetSoundLevel(), 0, PITCH_NORM ); } break; + case RESPONSE_SCENE: - { - // Try to fire scene w/o an actor - InstancedScriptedScene( NULL, response ); - } + // Try to fire scene w/o an actor + InstancedScriptedScene( NULL, szResponse ); break; - case RESPONSE_PRINT: - { - } + case RESPONSE_PRINT: break; default: // Don't know how to handle .vcds!!! @@ -7051,7 +7042,7 @@ void CBaseEntity::SetRefEHandle( const CBaseHandle &handle ) if ( edict() ) { COMPILE_TIME_ASSERT( NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS <= 8*sizeof( edict()->m_NetworkSerialNumber ) ); - edict()->m_NetworkSerialNumber = (m_RefEHandle.GetSerialNumber() & (1 << NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS) - 1); + edict()->m_NetworkSerialNumber = m_RefEHandle.GetSerialNumber() & ( (1 << NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS) - 1 ); } } diff --git a/mp/src/game/server/baseentity.h b/mp/src/game/server/baseentity.h index c5843015..7261e0a8 100644 --- a/mp/src/game/server/baseentity.h +++ b/mp/src/game/server/baseentity.h @@ -83,7 +83,7 @@ class CUserCmd; class CSkyCamera; class CEntityMapData; class INextBot; - +class IHasAttributes; typedef CUtlVector< CBaseEntity* > EntityList_t; @@ -1087,49 +1087,57 @@ public: int GetHealth() const { return m_iHealth; } void SetHealth( int amt ) { m_iHealth = amt; } + float HealthFraction() const; + // Ugly code to lookup all functions to make sure they are in the table when set. #ifdef _DEBUG - void FunctionCheck( void *pFunction, const char *name ); - ENTITYFUNCPTR TouchSet( ENTITYFUNCPTR func, char *name ) - { #ifdef GNUC - COMPILE_TIME_ASSERT( sizeof(func) == 8 ); +#define ENTITYFUNCPTR_SIZE 8 #else - COMPILE_TIME_ASSERT( sizeof(func) == 4 ); +#define ENTITYFUNCPTR_SIZE 4 #endif + + void FunctionCheck( void *pFunction, const char *name ); + ENTITYFUNCPTR TouchSet( ENTITYFUNCPTR func, char *name ) + { + COMPILE_TIME_ASSERT( sizeof(func) == ENTITYFUNCPTR_SIZE ); m_pfnTouch = func; FunctionCheck( *(reinterpret_cast<void **>(&m_pfnTouch)), name ); return func; } USEPTR UseSet( USEPTR func, char *name ) { -#ifdef GNUC - COMPILE_TIME_ASSERT( sizeof(func) == 8 ); -#else - COMPILE_TIME_ASSERT( sizeof(func) == 4 ); -#endif + COMPILE_TIME_ASSERT( sizeof(func) == ENTITYFUNCPTR_SIZE ); m_pfnUse = func; FunctionCheck( *(reinterpret_cast<void **>(&m_pfnUse)), name ); return func; } ENTITYFUNCPTR BlockedSet( ENTITYFUNCPTR func, char *name ) { -#ifdef GNUC - COMPILE_TIME_ASSERT( sizeof(func) == 8 ); -#else - COMPILE_TIME_ASSERT( sizeof(func) == 4 ); -#endif + COMPILE_TIME_ASSERT( sizeof(func) == ENTITYFUNCPTR_SIZE ); m_pfnBlocked = func; FunctionCheck( *(reinterpret_cast<void **>(&m_pfnBlocked)), name ); return func; } -#endif +#endif // _DEBUG + virtual void ModifyOrAppendCriteria( AI_CriteriaSet& set ); void AppendContextToCriteria( AI_CriteriaSet& set, const char *prefix = "" ); void DumpResponseCriteria( void ); - + + // Return the IHasAttributes interface for this base entity. Removes the need for: + // dynamic_cast< IHasAttributes * >( pEntity ); + // Which is remarkably slow. + // GetAttribInterface( CBaseEntity *pEntity ) in attribute_manager.h uses + // this function, tests for NULL, and Asserts m_pAttributes == dynamic_cast. + inline IHasAttributes *GetHasAttributesInterfacePtr() const { return m_pAttributes; } + +protected: + // NOTE: m_pAttributes needs to be set in the leaf class constructor. + IHasAttributes *m_pAttributes; + private: friend class CAI_Senses; CBaseEntity *m_pLink;// used for temporary link-list operations. diff --git a/mp/src/game/server/baseflex.cpp b/mp/src/game/server/baseflex.cpp index 4e6b4629..5c435d73 100644 --- a/mp/src/game/server/baseflex.cpp +++ b/mp/src/game/server/baseflex.cpp @@ -2555,7 +2555,7 @@ void CFlexCycler::Think( void ) { m_flexnum = LookupFlex( szTemp ); - if (m_flexnum != -1 && m_flextarget[m_flexnum] != 1) + if (m_flexnum != LocalFlexController_t(-1) && m_flextarget[m_flexnum] != 1) { m_flextarget[m_flexnum] = 1.0; // SetFlexTarget( m_flexnum ); diff --git a/mp/src/game/server/basemultiplayerplayer.cpp b/mp/src/game/server/basemultiplayerplayer.cpp index b6ecd44c..fee7515d 100644 --- a/mp/src/game/server/basemultiplayerplayer.cpp +++ b/mp/src/game/server/basemultiplayerplayer.cpp @@ -87,10 +87,11 @@ IResponseSystem *CBaseMultiplayerPlayer::GetResponseSystem() //----------------------------------------------------------------------------- // Purpose: Doesn't actually speak the concept. Just finds a response in the system. You then have to play it yourself. //----------------------------------------------------------------------------- -AI_Response *CBaseMultiplayerPlayer::SpeakConcept( int iConcept ) +bool CBaseMultiplayerPlayer::SpeakConcept( AI_Response &response, int iConcept ) { + // Save the current concept. m_iCurrentConcept = iConcept; - return SpeakFindResponse( g_pszMPConcepts[iConcept] ); + return SpeakFindResponse( response, g_pszMPConcepts[iConcept] ); } //----------------------------------------------------------------------------- diff --git a/mp/src/game/server/basemultiplayerplayer.h b/mp/src/game/server/basemultiplayerplayer.h index 06a0e00d..a1ea58f8 100644 --- a/mp/src/game/server/basemultiplayerplayer.h +++ b/mp/src/game/server/basemultiplayerplayer.h @@ -28,7 +28,7 @@ public: virtual bool SpeakIfAllowed( AIConcept_t concept, const char *modifiers = NULL, char *pszOutResponseChosen = NULL, size_t bufsize = 0, IRecipientFilter *filter = NULL ); virtual IResponseSystem *GetResponseSystem(); - AI_Response *SpeakConcept( int iConcept ); + bool SpeakConcept( AI_Response& response, int iConcept ); virtual bool SpeakConceptIfAllowed( int iConcept, const char *modifiers = NULL, char *pszOutResponseChosen = NULL, size_t bufsize = 0, IRecipientFilter *filter = NULL ); virtual bool CanHearAndReadChatFrom( CBasePlayer *pPlayer ); diff --git a/mp/src/game/server/cbase.cpp b/mp/src/game/server/cbase.cpp index d748a1dd..d6627b4b 100644 --- a/mp/src/game/server/cbase.cpp +++ b/mp/src/game/server/cbase.cpp @@ -281,7 +281,11 @@ void CBaseEntityOutput::FireOutput(variant_t Value, CBaseEntity *pActivator, CBa Q_snprintf( szBuffer, sizeof(szBuffer), "(%0.2f) output: (%s,%s) -> (%s,%s,%.1f)(%s)\n", +#ifdef TF_DLL engine->GetServerTime(), +#else + gpGlobals->curtime, +#endif pCaller ? STRING(pCaller->m_iClassname) : "NULL", pCaller ? STRING(pCaller->GetEntityName()) : "NULL", STRING(ev->m_iTarget), @@ -298,7 +302,11 @@ void CBaseEntityOutput::FireOutput(variant_t Value, CBaseEntity *pActivator, CBa Q_snprintf( szBuffer, sizeof(szBuffer), "(%0.2f) output: (%s,%s) -> (%s,%s)(%s)\n", +#ifdef TF_DLL engine->GetServerTime(), +#else + gpGlobals->curtime, +#endif pCaller ? STRING(pCaller->m_iClassname) : "NULL", pCaller ? STRING(pCaller->GetEntityName()) : "NULL", STRING(ev->m_iTarget), STRING(ev->m_iTargetInput), @@ -459,7 +467,7 @@ void CBaseEntityOutput::DeleteAllElements( void ) m_ActionList = NULL; while (pNext) { - register CEventAction *strikeThis = pNext; + CEventAction *strikeThis = pNext; pNext = pNext->m_pNext; delete strikeThis; } @@ -767,7 +775,13 @@ void CEventQueue::Dump( void ) { EventQueuePrioritizedEvent_t *pe = m_Events.m_pNext; - Msg( "Dumping event queue. Current time is: %.2f\n", engine->GetServerTime() ); + Msg("Dumping event queue. Current time is: %.2f\n", +#ifdef TF_DLL + engine->GetServerTime() +#else + gpGlobals->curtime +#endif + ); while ( pe != NULL ) { @@ -795,7 +809,11 @@ void CEventQueue::AddEvent( const char *target, const char *targetInput, variant { // build the new event EventQueuePrioritizedEvent_t *newEvent = new EventQueuePrioritizedEvent_t; +#ifdef TF_DLL newEvent->m_flFireTime = engine->GetServerTime() + fireDelay; // priority key in the priority queue +#else + newEvent->m_flFireTime = gpGlobals->curtime + fireDelay; // priority key in the priority queue +#endif newEvent->m_iTarget = MAKE_STRING( target ); newEvent->m_pEntTarget = NULL; newEvent->m_iTargetInput = MAKE_STRING( targetInput ); @@ -814,7 +832,11 @@ void CEventQueue::AddEvent( CBaseEntity *target, const char *targetInput, varian { // build the new event EventQueuePrioritizedEvent_t *newEvent = new EventQueuePrioritizedEvent_t; +#ifdef TF_DLL newEvent->m_flFireTime = engine->GetServerTime() + fireDelay; // primary priority key in the priority queue +#else + newEvent->m_flFireTime = gpGlobals->curtime + fireDelay; // primary priority key in the priority queue +#endif newEvent->m_iTarget = NULL_STRING; newEvent->m_pEntTarget = target; newEvent->m_iTargetInput = MAKE_STRING( targetInput ); @@ -885,7 +907,11 @@ void CEventQueue::ServiceEvents( void ) EventQueuePrioritizedEvent_t *pe = m_Events.m_pNext; +#ifdef TF_DLL while ( pe != NULL && pe->m_flFireTime <= engine->GetServerTime() ) +#else + while ( pe != NULL && pe->m_flFireTime <= gpGlobals->curtime ) +#endif { MDLCACHE_CRITICAL_SECTION(); @@ -1171,7 +1197,11 @@ int CEventQueue::Restore( IRestore &restore ) AddEvent( tmpEvent.m_pEntTarget, STRING(tmpEvent.m_iTargetInput), tmpEvent.m_VariantValue, +#ifdef TF_DLL tmpEvent.m_flFireTime - engine->GetServerTime(), +#else + tmpEvent.m_flFireTime - gpGlobals->curtime, +#endif tmpEvent.m_pActivator, tmpEvent.m_pCaller, tmpEvent.m_iOutputID ); @@ -1181,7 +1211,11 @@ int CEventQueue::Restore( IRestore &restore ) AddEvent( STRING(tmpEvent.m_iTarget), STRING(tmpEvent.m_iTargetInput), tmpEvent.m_VariantValue, +#ifdef TF_DLL tmpEvent.m_flFireTime - engine->GetServerTime(), +#else + tmpEvent.m_flFireTime - gpGlobals->curtime, +#endif tmpEvent.m_pActivator, tmpEvent.m_pCaller, tmpEvent.m_iOutputID ); diff --git a/mp/src/game/server/client.cpp b/mp/src/game/server/client.cpp index 357f0f22..f500ad5e 100644 --- a/mp/src/game/server/client.cpp +++ b/mp/src/game/server/client.cpp @@ -1349,6 +1349,7 @@ void CC_HurtMe_f(const CCommand &args) static ConCommand hurtme("hurtme", CC_HurtMe_f, "Hurts the player.\n\tArguments: <health to lose>", FCVAR_CHEAT); +#ifdef DBGFLAG_ASSERT static bool IsInGroundList( CBaseEntity *ent, CBaseEntity *ground ) { if ( !ground || !ent ) @@ -1368,8 +1369,8 @@ static bool IsInGroundList( CBaseEntity *ent, CBaseEntity *ground ) } return false; - } +#endif static int DescribeGroundList( CBaseEntity *ent ) { diff --git a/mp/src/game/server/entity_tools_server.cpp b/mp/src/game/server/entity_tools_server.cpp index 5032ca04..b08d0754 100644 --- a/mp/src/game/server/entity_tools_server.cpp +++ b/mp/src/game/server/entity_tools_server.cpp @@ -53,7 +53,27 @@ public: virtual void ApplyMultiDamage( void ); virtual void AddMultiDamage( const CTakeDamageInfo &pTakeDamageInfo, CBaseEntity *pEntity ); virtual void RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore ); + virtual ITempEntsSystem *GetTempEntsSystem( void ); + virtual CBaseTempEntity *GetTempEntList( void ); + virtual CGlobalEntityList *GetEntityList( void ); + virtual bool IsEntityPtr( void *pTest ); + virtual CBaseEntity *FindEntityByClassname( CBaseEntity *pStartEntity, const char *szName ); + virtual CBaseEntity *FindEntityByName( CBaseEntity *pStartEntity, const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL, IEntityFindFilter *pFilter = NULL ); + virtual CBaseEntity *FindEntityInSphere( CBaseEntity *pStartEntity, const Vector &vecCenter, float flRadius ); + virtual CBaseEntity *FindEntityByTarget( CBaseEntity *pStartEntity, const char *szName ); + virtual CBaseEntity *FindEntityByModel( CBaseEntity *pStartEntity, const char *szModelName ); + virtual CBaseEntity *FindEntityByNameNearest( const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); + virtual CBaseEntity *FindEntityByNameWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); + virtual CBaseEntity *FindEntityByClassnameNearest( const char *szName, const Vector &vecSrc, float flRadius ); + virtual CBaseEntity *FindEntityByClassnameWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius ); + virtual CBaseEntity *FindEntityByClassnameWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecMins, const Vector &vecMaxs ); + virtual CBaseEntity *FindEntityGeneric( CBaseEntity *pStartEntity, const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); + virtual CBaseEntity *FindEntityGenericWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); + virtual CBaseEntity *FindEntityGenericNearest( const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); + virtual CBaseEntity *FindEntityNearestFacing( const Vector &origin, const Vector &facing, float threshold ); + virtual CBaseEntity *FindEntityClassNearestFacing( const Vector &origin, const Vector &facing, float threshold, char *classname ); + virtual CBaseEntity *FindEntityProcedural( const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); }; @@ -64,10 +84,11 @@ static CServerTools g_ServerTools; // VSERVERTOOLS_INTERFACE_VERSION_1 is compatible with the latest since we're only adding things to the end, so expose that as well. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CServerTools, IServerTools001, VSERVERTOOLS_INTERFACE_VERSION_1, g_ServerTools ); +EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CServerTools, IServerTools002, VSERVERTOOLS_INTERFACE_VERSION_2, g_ServerTools ); EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CServerTools, IServerTools, VSERVERTOOLS_INTERFACE_VERSION, g_ServerTools ); // When bumping the version to this interface, check that our assumption is still valid and expose the older version in the same way -COMPILE_TIME_ASSERT( VSERVERTOOLS_INTERFACE_VERSION_INT == 2 ); +COMPILE_TIME_ASSERT( VSERVERTOOLS_INTERFACE_VERSION_INT == 3 ); IServerEntity *CServerTools::GetIServerEntity( IClientEntity *pClientEntity ) @@ -347,6 +368,101 @@ ITempEntsSystem *CServerTools::GetTempEntsSystem( void ) return (ITempEntsSystem *)te; } +CBaseTempEntity *CServerTools::GetTempEntList( void ) +{ + return CBaseTempEntity::GetList(); +} + +CGlobalEntityList *CServerTools::GetEntityList( void ) +{ + return &gEntList; +} + +bool CServerTools::IsEntityPtr( void *pTest ) +{ + return gEntList.IsEntityPtr( pTest ); +} + +CBaseEntity *CServerTools::FindEntityByClassname( CBaseEntity *pStartEntity, const char *szName ) +{ + return gEntList.FindEntityByClassname( pStartEntity, szName ); +} + +CBaseEntity *CServerTools::FindEntityByName( CBaseEntity *pStartEntity, const char *szName, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller, IEntityFindFilter *pFilter ) +{ + return gEntList.FindEntityByName( pStartEntity, szName, pSearchingEntity, pActivator, pCaller, pFilter ); +} + +CBaseEntity *CServerTools::FindEntityInSphere( CBaseEntity *pStartEntity, const Vector &vecCenter, float flRadius ) +{ + return gEntList.FindEntityInSphere( pStartEntity, vecCenter, flRadius ); +} + +CBaseEntity *CServerTools::FindEntityByTarget( CBaseEntity *pStartEntity, const char *szName ) +{ + return gEntList.FindEntityByTarget( pStartEntity, szName ); +} + +CBaseEntity *CServerTools::FindEntityByModel( CBaseEntity *pStartEntity, const char *szModelName ) +{ + return gEntList.FindEntityByModel( pStartEntity, szModelName ); +} + +CBaseEntity *CServerTools::FindEntityByNameNearest( const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller ) +{ + return gEntList.FindEntityByNameNearest( szName, vecSrc, flRadius, pSearchingEntity, pActivator, pCaller ); +} + +CBaseEntity *CServerTools::FindEntityByNameWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller ) +{ + return gEntList.FindEntityByNameWithin( pStartEntity, szName, vecSrc, flRadius, pSearchingEntity, pActivator, pCaller ); +} + +CBaseEntity *CServerTools::FindEntityByClassnameNearest( const char *szName, const Vector &vecSrc, float flRadius ) +{ + return gEntList.FindEntityByClassnameNearest( szName, vecSrc, flRadius ); +} + +CBaseEntity *CServerTools::FindEntityByClassnameWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius ) +{ + return gEntList.FindEntityByClassnameWithin( pStartEntity, szName, vecSrc, flRadius ); +} + +CBaseEntity *CServerTools::FindEntityByClassnameWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecMins, const Vector &vecMaxs ) +{ + return gEntList.FindEntityByClassnameWithin( pStartEntity, szName, vecMins, vecMaxs ); +} + +CBaseEntity *CServerTools::FindEntityGeneric( CBaseEntity *pStartEntity, const char *szName, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller ) +{ + return gEntList.FindEntityGeneric( pStartEntity, szName, pSearchingEntity, pActivator, pCaller ); +} + +CBaseEntity *CServerTools::FindEntityGenericWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller ) +{ + return gEntList.FindEntityGenericWithin( pStartEntity, szName, vecSrc, flRadius, pSearchingEntity, pActivator, pCaller ); +} + +CBaseEntity *CServerTools::FindEntityGenericNearest( const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller ) +{ + return gEntList.FindEntityGenericNearest( szName, vecSrc, flRadius, pSearchingEntity, pActivator, pCaller ); +} + +CBaseEntity *CServerTools::FindEntityNearestFacing( const Vector &origin, const Vector &facing, float threshold ) +{ + return gEntList.FindEntityNearestFacing( origin, facing, threshold ); +} + +CBaseEntity *CServerTools::FindEntityClassNearestFacing( const Vector &origin, const Vector &facing, float threshold, char *classname ) +{ + return gEntList.FindEntityClassNearestFacing( origin, facing, threshold, classname ); +} + +CBaseEntity *CServerTools::FindEntityProcedural( const char *szName, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller ) +{ + return gEntList.FindEntityProcedural( szName, pSearchingEntity, pActivator, pCaller ); +} + // Interface from engine to tools for manipulating entities class CServerChoreoTools : public IServerChoreoTools diff --git a/mp/src/game/server/entitylist.cpp b/mp/src/game/server/entitylist.cpp index 6244fa7d..d1afa218 100644 --- a/mp/src/game/server/entitylist.cpp +++ b/mp/src/game/server/entitylist.cpp @@ -1105,7 +1105,7 @@ void CGlobalEntityList::OnAddEntity( IHandleEntity *pEnt, CBaseHandle handle ) void CGlobalEntityList::OnRemoveEntity( IHandleEntity *pEnt, CBaseHandle handle ) { -#ifdef DEBUG +#ifdef DBGFLAG_ASSERT if ( !g_fInCleanupDelete ) { int i; diff --git a/mp/src/game/server/entitylist.h b/mp/src/game/server/entitylist.h index bd9412c5..540e2d50 100644 --- a/mp/src/game/server/entitylist.h +++ b/mp/src/game/server/entitylist.h @@ -155,7 +155,6 @@ public: CBaseEntity *FindEntityNearestFacing( const Vector &origin, const Vector &facing, float threshold); CBaseEntity *FindEntityClassNearestFacing( const Vector &origin, const Vector &facing, float threshold, char *classname); - CBaseEntity *FindEntityByNetname( CBaseEntity *pStartEntity, const char *szModelName ); CBaseEntity *FindEntityProcedural( const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); diff --git a/mp/src/game/server/func_breakablesurf.cpp b/mp/src/game/server/func_breakablesurf.cpp index 4b8e0ba5..902722b5 100644 --- a/mp/src/game/server/func_breakablesurf.cpp +++ b/mp/src/game/server/func_breakablesurf.cpp @@ -109,8 +109,6 @@ void CWindowPane::PaneTouch( CBaseEntity *pOther ) //------------------------------------------------------------------------------ void CWindowPane::Die( void ) { - Vector flForce = -1 * GetAbsVelocity(); - CPASFilter filter( GetAbsOrigin() ); te->ShatterSurface( filter, 0.0, &GetAbsOrigin(), &GetAbsAngles(), diff --git a/mp/src/game/server/func_dust.cpp b/mp/src/game/server/func_dust.cpp index 3e3fcb21..a06265ea 100644 --- a/mp/src/game/server/func_dust.cpp +++ b/mp/src/game/server/func_dust.cpp @@ -162,7 +162,7 @@ void CFunc_Dust::Spawn() //Since keyvalues can arrive in any order, and UTIL_StringToColor32 stomps alpha, //install the alpha value here. - color32 clr = { m_Color.m_Value.r, m_Color.m_Value.g, m_Color.m_Value.b, m_iAlpha }; + color32 clr = { m_Color.m_Value.r, m_Color.m_Value.g, m_Color.m_Value.b, (byte)m_iAlpha }; m_Color.Set( clr ); BaseClass::Spawn(); diff --git a/mp/src/game/server/gameinterface.cpp b/mp/src/game/server/gameinterface.cpp index ff077ea5..b20daf08 100644 --- a/mp/src/game/server/gameinterface.cpp +++ b/mp/src/game/server/gameinterface.cpp @@ -1928,6 +1928,15 @@ const char *CServerGameDLL::GetServerBrowserGameData() } //----------------------------------------------------------------------------- +void CServerGameDLL::Status( void (*print) (const char *fmt, ...) ) +{ + if ( g_pGameRules ) + { + g_pGameRules->Status( print ); + } +} + +//----------------------------------------------------------------------------- // Purpose: Called during a transition, to build a map adjacency list //----------------------------------------------------------------------------- void CServerGameDLL::BuildAdjacentMapList( void ) @@ -3332,7 +3341,7 @@ void MessageWriteEHandle( CBaseEntity *pEntity ) { EHANDLE hEnt = pEntity; - int iSerialNum = hEnt.GetSerialNumber() & (1 << NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS) - 1; + int iSerialNum = hEnt.GetSerialNumber() & ( (1 << NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS) - 1 ); iEncodedEHandle = hEnt.GetEntryIndex() | (iSerialNum << MAX_EDICT_BITS); } else diff --git a/mp/src/game/server/gameinterface.h b/mp/src/game/server/gameinterface.h index c0d7a6da..91d6534c 100644 --- a/mp/src/game/server/gameinterface.h +++ b/mp/src/game/server/gameinterface.h @@ -28,35 +28,35 @@ extern INetworkStringTable *g_pStringTableServerPopFiles; class CServerGameClients : public IServerGameClients { public: - virtual bool ClientConnect( edict_t *pEntity, char const* pszName, char const* pszAddress, char *reject, int maxrejectlen ); - virtual void ClientActive( edict_t *pEntity, bool bLoadGame ); - virtual void ClientDisconnect( edict_t *pEntity ); - virtual void ClientPutInServer( edict_t *pEntity, const char *playername ); - virtual void ClientCommand( edict_t *pEntity, const CCommand &args ); - virtual void ClientSettingsChanged( edict_t *pEntity ); - virtual void ClientSetupVisibility( edict_t *pViewEntity, edict_t *pClient, unsigned char *pvs, int pvssize ); + virtual bool ClientConnect( edict_t *pEntity, char const* pszName, char const* pszAddress, char *reject, int maxrejectlen ) OVERRIDE; + virtual void ClientActive( edict_t *pEntity, bool bLoadGame ) OVERRIDE; + virtual void ClientDisconnect( edict_t *pEntity ) OVERRIDE; + virtual void ClientPutInServer( edict_t *pEntity, const char *playername ) OVERRIDE; + virtual void ClientCommand( edict_t *pEntity, const CCommand &args ) OVERRIDE; + virtual void ClientSettingsChanged( edict_t *pEntity ) OVERRIDE; + virtual void ClientSetupVisibility( edict_t *pViewEntity, edict_t *pClient, unsigned char *pvs, int pvssize ) OVERRIDE; virtual float ProcessUsercmds( edict_t *player, bf_read *buf, int numcmds, int totalcmds, - int dropped_packets, bool ignore, bool paused ); + int dropped_packets, bool ignore, bool paused ) OVERRIDE; // Player is running a command - virtual void PostClientMessagesSent_DEPRECIATED( void ); - virtual void SetCommandClient( int index ); - virtual CPlayerState *GetPlayerState( edict_t *player ); - virtual void ClientEarPosition( edict_t *pEntity, Vector *pEarOrigin ); + virtual void PostClientMessagesSent_DEPRECIATED( void ) OVERRIDE; + virtual void SetCommandClient( int index ) OVERRIDE; + virtual CPlayerState *GetPlayerState( edict_t *player ) OVERRIDE; + virtual void ClientEarPosition( edict_t *pEntity, Vector *pEarOrigin ) OVERRIDE; - virtual void GetPlayerLimits( int& minplayers, int& maxplayers, int &defaultMaxPlayers ) const; + virtual void GetPlayerLimits( int& minplayers, int& maxplayers, int &defaultMaxPlayers ) const OVERRIDE; // returns number of delay ticks if player is in Replay mode (0 = no delay) - virtual int GetReplayDelay( edict_t *player, int& entity ); + virtual int GetReplayDelay( edict_t *player, int& entity ) OVERRIDE; // Anything this game .dll wants to add to the bug reporter text (e.g., the entity/model under the picker crosshair) // can be added here - virtual void GetBugReportInfo( char *buf, int buflen ); - virtual void NetworkIDValidated( const char *pszUserName, const char *pszNetworkID ); + virtual void GetBugReportInfo( char *buf, int buflen ) OVERRIDE; + virtual void NetworkIDValidated( const char *pszUserName, const char *pszNetworkID ) OVERRIDE; // The client has submitted a keyvalues command - virtual void ClientCommandKeyValues( edict_t *pEntity, KeyValues *pKeyValues ); + virtual void ClientCommandKeyValues( edict_t *pEntity, KeyValues *pKeyValues ) OVERRIDE; // Notify that the player is spawned - virtual void ClientSpawned( edict_t *pPlayer ); + virtual void ClientSpawned( edict_t *pPlayer ) OVERRIDE; }; @@ -64,73 +64,73 @@ class CServerGameDLL : public IServerGameDLL { public: virtual bool DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, - CreateInterfaceFn fileSystemFactory, CGlobalVars *pGlobals); - virtual void DLLShutdown( void ); + CreateInterfaceFn fileSystemFactory, CGlobalVars *pGlobals) OVERRIDE; + virtual void DLLShutdown( void ) OVERRIDE; // Get the simulation interval (must be compiled with identical values into both client and game .dll for MOD!!!) - virtual bool ReplayInit( CreateInterfaceFn fnReplayFactory ); - virtual float GetTickInterval( void ) const; - virtual bool GameInit( void ); - virtual void GameShutdown( void ); - virtual bool LevelInit( const char *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background ); - virtual void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax ); - virtual void LevelShutdown( void ); - virtual void GameFrame( bool simulating ); // could be called multiple times before sending data to clients - virtual void PreClientUpdate( bool simulating ); // called after all GameFrame() calls, before sending data to clients - - virtual ServerClass* GetAllServerClasses( void ); - virtual const char *GetGameDescription( void ); - virtual void CreateNetworkStringTables( void ); + virtual bool ReplayInit( CreateInterfaceFn fnReplayFactory ) OVERRIDE; + virtual float GetTickInterval( void ) const OVERRIDE; + virtual bool GameInit( void ) OVERRIDE; + virtual void GameShutdown( void ) OVERRIDE; + virtual bool LevelInit( const char *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background ) OVERRIDE; + virtual void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax ) OVERRIDE; + virtual void LevelShutdown( void ) OVERRIDE; + virtual void GameFrame( bool simulating ) OVERRIDE; // could be called multiple times before sending data to clients + virtual void PreClientUpdate( bool simulating ) OVERRIDE; // called after all GameFrame() calls, before sending data to clients + + virtual ServerClass* GetAllServerClasses( void ) OVERRIDE; + virtual const char *GetGameDescription( void ) OVERRIDE; + virtual void CreateNetworkStringTables( void ) OVERRIDE; // Save/restore system hooks - virtual CSaveRestoreData *SaveInit( int size ); - virtual void SaveWriteFields( CSaveRestoreData *, char const* , void *, datamap_t *, typedescription_t *, int ); - virtual void SaveReadFields( CSaveRestoreData *, char const* , void *, datamap_t *, typedescription_t *, int ); - virtual void SaveGlobalState( CSaveRestoreData * ); - virtual void RestoreGlobalState( CSaveRestoreData * ); - virtual int CreateEntityTransitionList( CSaveRestoreData *, int ); - virtual void BuildAdjacentMapList( void ); - - virtual void PreSave( CSaveRestoreData * ); - virtual void Save( CSaveRestoreData * ); - virtual void GetSaveComment( char *comment, int maxlength, float flMinutes, float flSeconds, bool bNoTime = false ); + virtual CSaveRestoreData *SaveInit( int size ) OVERRIDE; + virtual void SaveWriteFields( CSaveRestoreData *, char const* , void *, datamap_t *, typedescription_t *, int ) OVERRIDE; + virtual void SaveReadFields( CSaveRestoreData *, char const* , void *, datamap_t *, typedescription_t *, int ) OVERRIDE; + virtual void SaveGlobalState( CSaveRestoreData * ) OVERRIDE; + virtual void RestoreGlobalState( CSaveRestoreData * ) OVERRIDE; + virtual int CreateEntityTransitionList( CSaveRestoreData *, int ) OVERRIDE; + virtual void BuildAdjacentMapList( void ) OVERRIDE; + + virtual void PreSave( CSaveRestoreData * ) OVERRIDE; + virtual void Save( CSaveRestoreData * ) OVERRIDE; + virtual void GetSaveComment( char *comment, int maxlength, float flMinutes, float flSeconds, bool bNoTime = false ) OVERRIDE; #ifdef _XBOX - virtual void GetTitleName( const char *pMapName, char* pTitleBuff, int titleBuffSize ); + virtual void GetTitleName( const char *pMapName, char* pTitleBuff, int titleBuffSize ) OVERRIDE; #endif - virtual void WriteSaveHeaders( CSaveRestoreData * ); + virtual void WriteSaveHeaders( CSaveRestoreData * ) OVERRIDE; - virtual void ReadRestoreHeaders( CSaveRestoreData * ); - virtual void Restore( CSaveRestoreData *, bool ); - virtual bool IsRestoring(); + virtual void ReadRestoreHeaders( CSaveRestoreData * ) OVERRIDE; + virtual void Restore( CSaveRestoreData *, bool ) OVERRIDE; + virtual bool IsRestoring() OVERRIDE; // Retrieve info needed for parsing the specified user message - virtual bool GetUserMessageInfo( int msg_type, char *name, int maxnamelength, int& size ); + virtual bool GetUserMessageInfo( int msg_type, char *name, int maxnamelength, int& size ) OVERRIDE; - virtual CStandardSendProxies* GetStandardSendProxies(); + virtual CStandardSendProxies* GetStandardSendProxies() OVERRIDE; - virtual void PostInit(); - virtual void Think( bool finalTick ); + virtual void PostInit() OVERRIDE; + virtual void Think( bool finalTick ) OVERRIDE; - virtual void OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue ); + virtual void OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue ) OVERRIDE; - virtual void PreSaveGameLoaded( char const *pSaveName, bool bInGame ); + virtual void PreSaveGameLoaded( char const *pSaveName, bool bInGame ) OVERRIDE; // Returns true if the game DLL wants the server not to be made public. // Used by commentary system to hide multiplayer commentary servers from the master. - virtual bool ShouldHideServer( void ); + virtual bool ShouldHideServer( void ) OVERRIDE; - virtual void InvalidateMdlCache(); + virtual void InvalidateMdlCache() OVERRIDE; - virtual void SetServerHibernation( bool bHibernating ); + virtual void SetServerHibernation( bool bHibernating ) OVERRIDE; float m_fAutoSaveDangerousTime; float m_fAutoSaveDangerousMinHealthToCommit; bool m_bIsHibernating; // Called after the steam API has been activated post-level startup - virtual void GameServerSteamAPIActivated( void ); + virtual void GameServerSteamAPIActivated( void ) OVERRIDE; // Called after the steam API has been shutdown post-level startup - virtual void GameServerSteamAPIShutdown( void ); + virtual void GameServerSteamAPIShutdown( void ) OVERRIDE; // interface to the new GC based lobby system virtual IServerGCLobby *GetServerGCLobby() OVERRIDE; @@ -138,6 +138,9 @@ public: virtual const char *GetServerBrowserMapOverride() OVERRIDE; virtual const char *GetServerBrowserGameData() OVERRIDE; + // Called to add output to the status command + virtual void Status( void (*print) (const char *fmt, ...) ); + private: // This can just be a wrapper on MapEntity_ParseAllEntities, but CS does some tricks in here diff --git a/mp/src/game/server/genericactor.cpp b/mp/src/game/server/genericactor.cpp index 6f104887..dd518a4e 100644 --- a/mp/src/game/server/genericactor.cpp +++ b/mp/src/game/server/genericactor.cpp @@ -372,7 +372,7 @@ void CFlextalkActor::ProcessSceneEvents( void ) { m_flexnum = LookupFlex( szTemp ); - if (m_flexnum != -1 && m_flextarget[m_flexnum] != 1) + if (m_flexnum != LocalFlexController_t(-1) && m_flextarget[m_flexnum] != 1) { m_flextarget[m_flexnum] = 1.0; // SetFlexTarget( m_flexnum ); diff --git a/mp/src/game/server/globalstate.cpp b/mp/src/game/server/globalstate.cpp index 7d50d5ce..d8da390c 100644 --- a/mp/src/game/server/globalstate.cpp +++ b/mp/src/game/server/globalstate.cpp @@ -131,6 +131,7 @@ public: entity.name = m_nameList.AddString( pGlobalname ); entity.levelName = m_nameList.AddString( pMapName ); entity.state = state; + entity.counter = 0; int index = GetIndex( m_nameList.String( entity.name ) ); if ( index >= 0 ) diff --git a/mp/src/game/server/hl2/npc_citizen17.cpp b/mp/src/game/server/hl2/npc_citizen17.cpp index d48cf6c2..adb9eb8c 100644 --- a/mp/src/game/server/hl2/npc_citizen17.cpp +++ b/mp/src/game/server/hl2/npc_citizen17.cpp @@ -143,23 +143,23 @@ struct citizen_expression_list_t // Scared citizen_expression_list_t ScaredExpressions[STATES_WITH_EXPRESSIONS] = { - { "scenes/Expressions/citizen_scared_idle_01.vcd" }, - { "scenes/Expressions/citizen_scared_alert_01.vcd" }, - { "scenes/Expressions/citizen_scared_combat_01.vcd" }, + { { "scenes/Expressions/citizen_scared_idle_01.vcd" } }, + { { "scenes/Expressions/citizen_scared_alert_01.vcd" } }, + { { "scenes/Expressions/citizen_scared_combat_01.vcd" } }, }; // Normal citizen_expression_list_t NormalExpressions[STATES_WITH_EXPRESSIONS] = { - { "scenes/Expressions/citizen_normal_idle_01.vcd" }, - { "scenes/Expressions/citizen_normal_alert_01.vcd" }, - { "scenes/Expressions/citizen_normal_combat_01.vcd" }, + { { "scenes/Expressions/citizen_normal_idle_01.vcd" } }, + { { "scenes/Expressions/citizen_normal_alert_01.vcd" } }, + { { "scenes/Expressions/citizen_normal_combat_01.vcd" } }, }; // Angry citizen_expression_list_t AngryExpressions[STATES_WITH_EXPRESSIONS] = { - { "scenes/Expressions/citizen_angry_idle_01.vcd" }, - { "scenes/Expressions/citizen_angry_alert_01.vcd" }, - { "scenes/Expressions/citizen_angry_combat_01.vcd" }, + { { "scenes/Expressions/citizen_angry_idle_01.vcd" } }, + { { "scenes/Expressions/citizen_angry_alert_01.vcd" } }, + { { "scenes/Expressions/citizen_angry_combat_01.vcd" } }, }; //----------------------------------------------------------------------------- @@ -4197,8 +4197,6 @@ void CNPC_Citizen::AddInsignia() void CNPC_Citizen::RemoveInsignia() { - // This is crap right now. - CBaseEntity *FirstEnt(); CBaseEntity *pEntity = gEntList.FirstEnt(); while( pEntity ) diff --git a/mp/src/game/server/hl2/npc_metropolice.cpp b/mp/src/game/server/hl2/npc_metropolice.cpp index 01d66258..833318d4 100644 --- a/mp/src/game/server/hl2/npc_metropolice.cpp +++ b/mp/src/game/server/hl2/npc_metropolice.cpp @@ -1675,7 +1675,7 @@ float CNPC_MetroPolice::AimBurstAtReactionTime( float flReactionTime, float flDi #define AIM_AT_SHOT_SPEED_COUNT 6 #define AIM_AT_SHOT_DIST_COUNT 6 -static int s_pShotCountFraction[AIM_AT_TIME_DIST_COUNT][AIM_AT_TIME_SPEED_COUNT] = +static float s_pShotCountFraction[AIM_AT_TIME_DIST_COUNT][AIM_AT_TIME_SPEED_COUNT] = { { 3.0f, 3.0f, 2.5f, 1.5f, 1.0f, 0.0f }, { 3.0f, 3.0f, 2.5f, 1.25f, 0.5f, 0.0f }, diff --git a/mp/src/game/server/hl2/npc_scanner.cpp b/mp/src/game/server/hl2/npc_scanner.cpp index 031ce6d9..86cfcad2 100644 --- a/mp/src/game/server/hl2/npc_scanner.cpp +++ b/mp/src/game/server/hl2/npc_scanner.cpp @@ -1988,7 +1988,7 @@ void CNPC_CScanner::BlindFlashTarget( CBaseEntity *pTarget ) if ( tr.startsolid == false && tr.fraction == 1.0) { - color32 white = { 255, 255, 255, SCANNER_FLASH_MAX_VALUE * dotPr }; + color32 white = { 255, 255, 255, (byte)(SCANNER_FLASH_MAX_VALUE * dotPr) }; if ( ( g_pMaterialSystemHardwareConfig != NULL ) && ( g_pMaterialSystemHardwareConfig->GetHDRType() != HDR_TYPE_NONE ) ) { diff --git a/mp/src/game/server/ilagcompensationmanager.h b/mp/src/game/server/ilagcompensationmanager.h index 507d29bf..b8749040 100644 --- a/mp/src/game/server/ilagcompensationmanager.h +++ b/mp/src/game/server/ilagcompensationmanager.h @@ -23,6 +23,7 @@ public: // Called during player movement to set up/restore after lag compensation virtual void StartLagCompensation( CBasePlayer *player, CUserCmd *cmd ) = 0; virtual void FinishLagCompensation( CBasePlayer *player ) = 0; + virtual bool IsCurrentlyDoingLagCompensation() const = 0; }; extern ILagCompensationManager *lagcompensation; diff --git a/mp/src/game/server/modelentities.cpp b/mp/src/game/server/modelentities.cpp index 3b6e3e3b..0c565ac4 100644 --- a/mp/src/game/server/modelentities.cpp +++ b/mp/src/game/server/modelentities.cpp @@ -191,7 +191,7 @@ void CFuncBrush::TurnOn( void ) } -bool CFuncBrush::IsOn( void ) +bool CFuncBrush::IsOn( void ) const { return !IsEffectActive( EF_NODRAW ); } diff --git a/mp/src/game/server/modelentities.h b/mp/src/game/server/modelentities.h index a8003b2d..36cf5a7d 100644 --- a/mp/src/game/server/modelentities.h +++ b/mp/src/game/server/modelentities.h @@ -18,7 +18,7 @@ //----------------------------------------------------------------------------- // Purpose: basic solid geometry // enabled state: brush is visible -// disabled staute: brush not visible +// disabled state: brush not visible //----------------------------------------------------------------------------- class CFuncBrush : public CBaseEntity { @@ -32,8 +32,8 @@ public: virtual int DrawDebugTextOverlays( void ); - void TurnOff( void ); - void TurnOn( void ); + virtual void TurnOff( void ); + virtual void TurnOn( void ); // Input handlers void InputTurnOff( inputdata_t &inputdata ); @@ -56,7 +56,7 @@ public: DECLARE_DATADESC(); - virtual bool IsOn( void ); + virtual bool IsOn( void ) const; }; diff --git a/mp/src/game/server/nav.h b/mp/src/game/server/nav.h index 0319991a..a955c3a8 100644 --- a/mp/src/game/server/nav.h +++ b/mp/src/game/server/nav.h @@ -334,11 +334,11 @@ inline void DirectionToVector2D( NavDirType dir, Vector2D *v ) { switch( dir ) { + default: Assert(0); case NORTH: v->x = 0.0f; v->y = -1.0f; break; case SOUTH: v->x = 0.0f; v->y = 1.0f; break; case EAST: v->x = 1.0f; v->y = 0.0f; break; case WEST: v->x = -1.0f; v->y = 0.0f; break; - default: break; } } @@ -348,11 +348,11 @@ inline void CornerToVector2D( NavCornerType dir, Vector2D *v ) { switch( dir ) { + default: Assert(0); case NORTH_WEST: v->x = -1.0f; v->y = -1.0f; break; case NORTH_EAST: v->x = 1.0f; v->y = -1.0f; break; case SOUTH_EAST: v->x = 1.0f; v->y = 1.0f; break; case SOUTH_WEST: v->x = -1.0f; v->y = 1.0f; break; - default: break; } v->NormalizeInPlace(); @@ -365,6 +365,8 @@ inline void GetCornerTypesInDirection( NavDirType dir, NavCornerType *first, Nav { switch ( dir ) { + default: + Assert(0); case NORTH: *first = NORTH_WEST; *second = NORTH_EAST; @@ -381,8 +383,6 @@ inline void GetCornerTypesInDirection( NavDirType dir, NavCornerType *first, Nav *first = NORTH_WEST; *second = SOUTH_WEST; break; - default: - break; } } diff --git a/mp/src/game/server/nav_area.cpp b/mp/src/game/server/nav_area.cpp index 73379f15..335e6c3b 100644 --- a/mp/src/game/server/nav_area.cpp +++ b/mp/src/game/server/nav_area.cpp @@ -192,6 +192,8 @@ CNavArea::CNavArea( void ) m_avoidanceObstacleHeight = 0.0f; m_totalCost = 0.0f; + m_costSoFar = 0.0f; + m_pathLengthSoFar = 0.0f; ResetNodes(); @@ -244,6 +246,8 @@ CNavArea::CNavArea( void ) m_isInheritedFrom = false; m_funcNavCostVector.RemoveAll(); + + m_nVisTestCounter = (uint32)-1; } //-------------------------------------------------------------------------------------------------------------- @@ -3381,16 +3385,10 @@ void CNavArea::AddToOpenList( void ) } // insert self in ascending cost order - // Since costs are positive, IEEE754 let's us compare as integers (see http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm) CNavArea *area, *last = NULL; - int thisCostBits = *reinterpret_cast<const int *>(&m_totalCost); - - Assert ( m_totalCost >= 0.0f ); for( area = m_openList; area; area = area->m_nextOpen ) { - Assert ( area->GetTotalCost() >= 0.0f ); - int thoseCostBits = *reinterpret_cast<const int *>(&area->m_totalCost); - if ( thisCostBits < thoseCostBits ) + if ( GetTotalCost() < area->GetTotalCost() ) { break; } @@ -5630,7 +5628,7 @@ void CNavArea::ComputeVisibilityToMesh( void ) /** * The center and all four corners must ALL be visible */ -bool CNavArea::IsEntirelyVisible( const Vector &eye, CBaseEntity *ignore ) const +bool CNavArea::IsEntirelyVisible( const Vector &eye, const CBaseEntity *ignore ) const { Vector corner; trace_t result; @@ -5663,7 +5661,7 @@ bool CNavArea::IsEntirelyVisible( const Vector &eye, CBaseEntity *ignore ) const /** * The center or any of the four corners may be visible */ -bool CNavArea::IsPartiallyVisible( const Vector &eye, CBaseEntity *ignore ) const +bool CNavArea::IsPartiallyVisible( const Vector &eye, const CBaseEntity *ignore ) const { Vector corner; trace_t result; diff --git a/mp/src/game/server/nav_area.h b/mp/src/game/server/nav_area.h index 7c18a5e0..3defa888 100644 --- a/mp/src/game/server/nav_area.h +++ b/mp/src/game/server/nav_area.h @@ -18,6 +18,15 @@ // BOTPORT: Clean up relationship between team index and danger storage in nav areas enum { MAX_NAV_TEAMS = 2 }; +#ifdef STAGING_ONLY +inline void DebuggerBreakOnNaN_StagingOnly( float val ) +{ + if ( IS_NAN( val ) ) + DebuggerBreak(); +} +#else +#define DebuggerBreakOnNaN_StagingOnly( _val ) +#endif class CFuncElevator; class CFuncNavPrerequisite; @@ -445,14 +454,14 @@ public: static void ClearSearchLists( void ); // clears the open and closed lists for a new search - void SetTotalCost( float value ) { Assert( value >= 0.0 && !IS_NAN(value) ); m_totalCost = value; } - float GetTotalCost( void ) const { return m_totalCost; } + void SetTotalCost( float value ) { DebuggerBreakOnNaN_StagingOnly( value ); Assert( value >= 0.0 && !IS_NAN(value) ); m_totalCost = value; } + float GetTotalCost( void ) const { DebuggerBreakOnNaN_StagingOnly( m_totalCost ); return m_totalCost; } - void SetCostSoFar( float value ) { Assert( value >= 0.0 && !IS_NAN(value) ); m_costSoFar = value; } - float GetCostSoFar( void ) const { return m_costSoFar; } + void SetCostSoFar( float value ) { DebuggerBreakOnNaN_StagingOnly( value ); Assert( value >= 0.0 && !IS_NAN(value) ); m_costSoFar = value; } + float GetCostSoFar( void ) const { DebuggerBreakOnNaN_StagingOnly( m_costSoFar ); return m_costSoFar; } - void SetPathLengthSoFar( float value ) { Assert( value >= 0.0 && !IS_NAN(value) ); m_pathLengthSoFar = value; } - float GetPathLengthSoFar( void ) const { return m_pathLengthSoFar; } + void SetPathLengthSoFar( float value ) { DebuggerBreakOnNaN_StagingOnly( value ); Assert( value >= 0.0 && !IS_NAN(value) ); m_pathLengthSoFar = value; } + float GetPathLengthSoFar( void ) const { DebuggerBreakOnNaN_StagingOnly( m_pathLengthSoFar ); return m_pathLengthSoFar; } //- editing ----------------------------------------------------------------------------------------- virtual void Draw( void ) const; // draw area for debugging & editing @@ -515,8 +524,8 @@ public: } }; - virtual bool IsEntirelyVisible( const Vector &eye, CBaseEntity *ignore = NULL ) const; // return true if entire area is visible from given eyepoint (CPU intensive) - virtual bool IsPartiallyVisible( const Vector &eye, CBaseEntity *ignore = NULL ) const; // return true if any portion of the area is visible from given eyepoint (CPU intensive) + virtual bool IsEntirelyVisible( const Vector &eye, const CBaseEntity *ignore = NULL ) const; // return true if entire area is visible from given eyepoint (CPU intensive) + virtual bool IsPartiallyVisible( const Vector &eye, const CBaseEntity *ignore = NULL ) const; // return true if any portion of the area is visible from given eyepoint (CPU intensive) virtual bool IsPotentiallyVisible( const CNavArea *area ) const; // return true if given area is potentially visible from somewhere in this area (very fast) virtual bool IsPotentiallyVisibleToTeam( int team ) const; // return true if any portion of this area is visible to anyone on the given team (very fast) diff --git a/mp/src/game/server/nav_generate.cpp b/mp/src/game/server/nav_generate.cpp index c9d2ea4b..be9ce6b5 100644 --- a/mp/src/game/server/nav_generate.cpp +++ b/mp/src/game/server/nav_generate.cpp @@ -1809,6 +1809,8 @@ void CNavMesh::StitchAreaIntoMesh( CNavArea *area, NavDirType dir, Functor &func Vector corner1, corner2; switch ( dir ) { + default: + Assert(0); case NORTH: corner1 = area->GetCorner( NORTH_WEST ); corner2 = area->GetCorner( NORTH_EAST ); diff --git a/mp/src/game/server/nav_mesh.cpp b/mp/src/game/server/nav_mesh.cpp index 8a15b39e..4c38a6f5 100644 --- a/mp/src/game/server/nav_mesh.cpp +++ b/mp/src/game/server/nav_mesh.cpp @@ -49,7 +49,9 @@ ConVar nav_max_vis_delta_list_length( "nav_max_vis_delta_list_length", "64", FCV extern ConVar nav_show_potentially_visible; +#ifdef STAGING_ONLY int g_DebugPathfindCounter = 0; +#endif bool FindGroundForNode( Vector *pos, Vector *normal ); diff --git a/mp/src/game/server/nav_mesh.h b/mp/src/game/server/nav_mesh.h index 24faed41..a69cdc03 100644 --- a/mp/src/game/server/nav_mesh.h +++ b/mp/src/game/server/nav_mesh.h @@ -1259,8 +1259,10 @@ extern CNavMesh *TheNavMesh; // factory for creating the Navigation Mesh extern CNavMesh *NavMeshFactory( void ); +#ifdef STAGING_ONLY // for debugging the A* algorithm, if nonzero, show debug display and decrement for each pathfind extern int g_DebugPathfindCounter; +#endif //-------------------------------------------------------------------------------------------------------------- diff --git a/mp/src/game/server/nav_pathfind.h b/mp/src/game/server/nav_pathfind.h index b06b46a0..e9c2d7ec 100644 --- a/mp/src/game/server/nav_pathfind.h +++ b/mp/src/game/server/nav_pathfind.h @@ -16,7 +16,9 @@ #include "mathlib/ssemath.h" #include "nav_area.h" +#ifdef STAGING_ONLY extern int g_DebugPathfindCounter; +#endif //------------------------------------------------------------------------------------------------------------------- @@ -108,7 +110,9 @@ bool NavAreaBuildPath( CNavArea *startArea, CNavArea *goalArea, const Vector *go *closestArea = startArea; } +#ifdef STAGING_ONLY bool isDebug = ( g_DebugPathfindCounter-- > 0 ); +#endif if (startArea == NULL) return false; @@ -154,10 +158,12 @@ bool NavAreaBuildPath( CNavArea *startArea, CNavArea *goalArea, const Vector *go // get next area to check CNavArea *area = CNavArea::PopOpenList(); +#ifdef STAGING_ONLY if ( isDebug ) { area->DrawFilled( 0, 255, 0, 128, 30.0f ); } +#endif // don't consider blocked areas if ( area->IsBlocked( teamID, ignoreNavBlockers ) ) @@ -339,7 +345,13 @@ bool NavAreaBuildPath( CNavArea *startArea, CNavArea *goalArea, const Vector *go continue; float newCostSoFar = costFunc( newArea, area, ladder, elevator, length ); - + + // NaNs really mess this function up causing tough to track down hangs. If + // we get inf back, clamp it down to a really high number. + DebuggerBreakOnNaN_StagingOnly( newCostSoFar ); + if ( IS_NAN( newCostSoFar ) ) + newCostSoFar = 1e30f; + // check if cost functor says this area is a dead-end if ( newCostSoFar < 0.0f ) continue; @@ -352,7 +364,7 @@ bool NavAreaBuildPath( CNavArea *startArea, CNavArea *goalArea, const Vector *go // Make sure that any jump to a new area incurs some pathfinsing // cost, to avoid us spinning our wheels over insignificant cost // benefit, floating point precision bug, or busted cost functor. - float minNewCostSoFar = area->GetCostSoFar() * 1.00001 + 0.00001; + float minNewCostSoFar = area->GetCostSoFar() * 1.00001f + 0.00001f; newCostSoFar = Max( newCostSoFar, minNewCostSoFar ); // stop if path length limit reached diff --git a/mp/src/game/server/networkstringtable_gamedll.h b/mp/src/game/server/networkstringtable_gamedll.h index 903c7c6c..9dbce97a 100644 --- a/mp/src/game/server/networkstringtable_gamedll.h +++ b/mp/src/game/server/networkstringtable_gamedll.h @@ -24,7 +24,7 @@ class CStringTableSaveRestoreOps; #define MAX_MATERIAL_STRINGS ( 1 << MAX_MATERIAL_STRING_BITS ) #define OVERLAY_MATERIAL_INVALID_STRING ( MAX_MATERIAL_STRINGS - 1 ) -#define MAX_CHOREO_SCENES_STRING_BITS 12 +#define MAX_CHOREO_SCENES_STRING_BITS 13 #define MAX_CHOREO_SCENES_STRINGS ( 1 << MAX_CHOREO_SCENES_STRING_BITS ) #define CHOREO_SCENES_INVALID_STRING ( MAX_CHOREO_SCENES_STRINGS - 1 ) diff --git a/mp/src/game/server/physics_main.cpp b/mp/src/game/server/physics_main.cpp index b0b2d867..a27a669a 100644 --- a/mp/src/game/server/physics_main.cpp +++ b/mp/src/game/server/physics_main.cpp @@ -742,7 +742,9 @@ void CPhysicsPushedEntities::GenerateBlockingEntityListAddBox( const Vector &vec } } - +#ifdef TF_DLL +#include "tf_logic_robot_destruction.h" +#endif //----------------------------------------------------------------------------- // Purpose: Gets a list of all entities hierarchically attached to the root //----------------------------------------------------------------------------- @@ -1841,7 +1843,9 @@ void CBaseEntity::PhysicsStepRunTimestep( float timestep ) { bool wasonground; bool inwater; +#if 0 bool hitsound = false; +#endif float speed, newspeed, control; float friction; @@ -1862,10 +1866,12 @@ void CBaseEntity::PhysicsStepRunTimestep( float timestep ) { if ( !( ( GetFlags() & FL_SWIM ) && ( GetWaterLevel() > 0 ) ) ) { +#if 0 if ( GetAbsVelocity()[2] < ( GetCurrentGravity() * -0.1 ) ) { hitsound = true; } +#endif if ( !inwater ) { diff --git a/mp/src/game/server/player.cpp b/mp/src/game/server/player.cpp index 0538f90a..a44ee551 100644 --- a/mp/src/game/server/player.cpp +++ b/mp/src/game/server/player.cpp @@ -635,6 +635,8 @@ CBasePlayer::CBasePlayer( ) m_flLastUserCommandTime = 0.f; m_flMovementTimeForUserCmdProcessingRemaining = 0.0f; + + m_flLastObjectiveTime = -1.f; } CBasePlayer::~CBasePlayer( ) @@ -2473,6 +2475,7 @@ void CBasePlayer::ValidateCurrentObserverTarget( void ) } else { +#if !defined( TF_DLL ) // couldn't find new target, switch to temporary mode if ( mp_forcecamera.GetInt() == OBS_ALLOW_ALL ) { @@ -2480,10 +2483,11 @@ void CBasePlayer::ValidateCurrentObserverTarget( void ) ForceObserverMode( OBS_MODE_ROAMING ); } else +#endif { // fix player view right where it is ForceObserverMode( OBS_MODE_FIXED ); - m_hObserverTarget.Set( NULL ); // no traget to follow + m_hObserverTarget.Set( NULL ); // no target to follow } } } @@ -7379,7 +7383,7 @@ void CBasePlayer::EquipWearable( CEconWearable *pItem ) pItem->Equip( this ); } -#ifdef DEBUG +#ifdef DBGFLAG_ASSERT // Double check list integrity. for ( int i = m_hMyWearables.Count()-1; i >= 0; --i ) { @@ -7418,7 +7422,7 @@ void CBasePlayer::RemoveWearable( CEconWearable *pItem ) } } -#ifdef DEBUG +#ifdef DBGFLAG_ASSERT // Double check list integrity. for ( int i = m_hMyWearables.Count()-1; i >= 0; --i ) { @@ -8853,6 +8857,8 @@ void CBasePlayer::SetPlayerName( const char *name ) Assert( strlen(name) > 0 ); Q_strncpy( m_szNetname, name, sizeof(m_szNetname) ); + // Be extra thorough + Q_RemoveAllEvilCharacters( m_szNetname ); } } @@ -8947,8 +8953,27 @@ void CBasePlayer::HandleAnimEvent( animevent_t *pEvent ) BaseClass::HandleAnimEvent( pEvent ); } + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CBasePlayer::ShouldAnnounceAchievement( void ) +{ + m_flAchievementTimes.AddToTail( gpGlobals->curtime ); + if ( m_flAchievementTimes.Count() > 3 ) + { + m_flAchievementTimes.Remove( 0 ); + if ( m_flAchievementTimes.Tail() - m_flAchievementTimes.Head() <= 60.0 ) + { + return false; + } + } + + return true; +} + //----------------------------------------------------------------------------- -// CPlayerInfo functions (simple passthroughts to get around the CBasePlayer multiple inheritence limitation) +// CPlayerInfo functions (simple pass-through to get around the CBasePlayer multiple inheritance limitation) //----------------------------------------------------------------------------- const char *CPlayerInfo::GetName() { diff --git a/mp/src/game/server/player.h b/mp/src/game/server/player.h index ddbd4416..8edefff3 100644 --- a/mp/src/game/server/player.h +++ b/mp/src/game/server/player.h @@ -612,7 +612,7 @@ public: virtual void HandleAnimEvent( animevent_t *pEvent ); - virtual bool ShouldAnnounceAchievement( void ){ return true; } + virtual bool ShouldAnnounceAchievement( void ); #if defined USES_ECON_ITEMS // Wearables @@ -820,7 +820,9 @@ private: public: - + // How long since this player last interacted with something the game considers an objective/target/goal + float GetTimeSinceLastObjective( void ) const { return ( m_flLastObjectiveTime == -1.f ) ? 999.f : gpGlobals->curtime - m_flLastObjectiveTime; } + void SetLastObjectiveTime( float flTime ) { m_flLastObjectiveTime = flTime; } // Used by gamemovement to check if the entity is stuck. int m_StuckLast; @@ -895,6 +897,7 @@ public: private: Activity m_Activity; + float m_flLastObjectiveTime; // Last curtime player touched/killed something the gamemode considers an objective protected: @@ -1210,6 +1213,9 @@ private: // Store the last time we successfully processed a usercommand float m_flLastUserCommandTime; + // used to prevent achievement announcement spam + CUtlVector< float > m_flAchievementTimes; + 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 diff --git a/mp/src/game/server/player_lagcompensation.cpp b/mp/src/game/server/player_lagcompensation.cpp index 08503652..37f322e5 100644 --- a/mp/src/game/server/player_lagcompensation.cpp +++ b/mp/src/game/server/player_lagcompensation.cpp @@ -172,6 +172,7 @@ class CLagCompensationManager : public CAutoGameSystemPerFrame, public ILagCompe public: CLagCompensationManager( char const *name ) : CAutoGameSystemPerFrame( name ), m_flTeleportDistanceSqr( 64 *64 ) { + m_isCurrentlyDoingCompensation = false; } // IServerSystem stuff @@ -194,6 +195,8 @@ public: void StartLagCompensation( CBasePlayer *player, CUserCmd *cmd ); void FinishLagCompensation( CBasePlayer *player ); + bool IsCurrentlyDoingLagCompensation() const OVERRIDE { return m_isCurrentlyDoingCompensation; } + private: void BacktrackPlayer( CBasePlayer *player, float flTargetTime ); @@ -216,6 +219,8 @@ private: CBasePlayer *m_pCurrentPlayer; // The player we are doing lag compensation for float m_flTeleportDistanceSqr; + + bool m_isCurrentlyDoingCompensation; // Sentinel to prevent calling StartLagCompensation a second time before a Finish. }; static CLagCompensationManager g_LagCompensationManager( "CLagCompensationManager" ); @@ -322,6 +327,8 @@ void CLagCompensationManager::FrameUpdatePostEntityThink() // Called during player movement to set up/restore after lag compensation void CLagCompensationManager::StartLagCompensation( CBasePlayer *player, CUserCmd *cmd ) { + Assert( !m_isCurrentlyDoingCompensation ); + //DONT LAG COMP AGAIN THIS FRAME IF THERES ALREADY ONE IN PROGRESS //IF YOU'RE HITTING THIS THEN IT MEANS THERES A CODE BUG if ( m_pCurrentPlayer ) @@ -350,6 +357,8 @@ void CLagCompensationManager::StartLagCompensation( CBasePlayer *player, CUserCm Q_memset( m_RestoreData, 0, sizeof( m_RestoreData ) ); Q_memset( m_ChangeData, 0, sizeof( m_ChangeData ) ); + m_isCurrentlyDoingCompensation = true; + // Get true latency // correct is the amout of time we have to correct game time @@ -734,7 +743,10 @@ void CLagCompensationManager::FinishLagCompensation( CBasePlayer *player ) m_pCurrentPlayer = NULL; if ( !m_bNeedToRestore ) + { + m_isCurrentlyDoingCompensation = false; return; // no player was changed at all + } // Iterate all active players for ( int i = 1; i <= gpGlobals->maxClients; i++ ) @@ -828,6 +840,8 @@ void CLagCompensationManager::FinishLagCompensation( CBasePlayer *player ) pPlayer->SetSimulationTime( restore->m_flSimulationTime ); } } + + m_isCurrentlyDoingCompensation = false; } diff --git a/mp/src/game/server/recipientfilter.cpp b/mp/src/game/server/recipientfilter.cpp index b7687fbe..d39419c3 100644 --- a/mp/src/game/server/recipientfilter.cpp +++ b/mp/src/game/server/recipientfilter.cpp @@ -98,7 +98,7 @@ void CRecipientFilter::AddAllPlayers( void ) } } -void CRecipientFilter::AddRecipient( CBasePlayer *player ) +void CRecipientFilter::AddRecipient( const CBasePlayer *player ) { Assert( player ); diff --git a/mp/src/game/server/recipientfilter.h b/mp/src/game/server/recipientfilter.h index 3f48e4fa..30af93ac 100644 --- a/mp/src/game/server/recipientfilter.h +++ b/mp/src/game/server/recipientfilter.h @@ -46,7 +46,7 @@ public: void AddRecipientsByPVS( const Vector& origin ); void RemoveRecipientsByPVS( const Vector& origin ); void AddRecipientsByPAS( const Vector& origin ); - void AddRecipient( CBasePlayer *player ); + void AddRecipient( const CBasePlayer *player ); void RemoveAllRecipients( void ); void RemoveRecipient( CBasePlayer *player ); void RemoveRecipientByPlayerIndex( int playerindex ); @@ -82,7 +82,7 @@ private: class CSingleUserRecipientFilter : public CRecipientFilter { public: - CSingleUserRecipientFilter( CBasePlayer *player ) + CSingleUserRecipientFilter( const CBasePlayer *player ) { AddRecipient( player ); } diff --git a/mp/src/game/server/sceneentity.cpp b/mp/src/game/server/sceneentity.cpp index 495aa004..ccdc4cd4 100644 --- a/mp/src/game/server/sceneentity.cpp +++ b/mp/src/game/server/sceneentity.cpp @@ -2163,11 +2163,6 @@ void CSceneEntity::InputTriggerEvent( inputdata_t &inputdata ) } } -struct NPCInterjection -{ - AI_Response *response; - CAI_BaseActor *npc; -}; //----------------------------------------------------------------------------- // Purpose: // Input : &inputdata - @@ -2176,93 +2171,62 @@ void CSceneEntity::InputInterjectResponse( inputdata_t &inputdata ) { // Not currently playing a scene if ( !m_pScene ) - { return; - } - CUtlVector< CAI_BaseActor * > candidates; - int i; - for ( i = 0 ; i < m_pScene->GetNumActors(); i++ ) + CUtlVector<CAI_BaseActor *> candidates; + + for ( int i = 0 ; i < m_pScene->GetNumActors(); i++ ) { CBaseFlex *pTestActor = FindNamedActor( i ); if ( !pTestActor ) continue; - CAI_BaseActor *pBaseActor = dynamic_cast<CAI_BaseActor*>(pTestActor); - if ( !pBaseActor ) - continue; - - if ( !pBaseActor->IsAlive() ) + CAI_BaseActor *pBaseActor = dynamic_cast<CAI_BaseActor *>(pTestActor); + if ( !pBaseActor || !pBaseActor->IsAlive() ) continue; candidates.AddToTail( pBaseActor ); } int c = candidates.Count(); - if ( !c ) - { return; - } - - int useIndex = 0; + if ( !m_bIsPlayingBack ) { // Use any actor if not playing a scene - useIndex = RandomInt( 0, c - 1 ); + // int useIndex = RandomInt( 0, c - 1 ); + Assert( !"m_bIsPlayBack is false and this code does nothing. Should it?"); } else { - CUtlVector< NPCInterjection > validResponses; + CUtlString modifiers("scene:"); + modifiers += STRING( GetEntityName() ); - char modifiers[ 512 ]; - Q_snprintf( modifiers, sizeof( modifiers ), "scene:%s", STRING( GetEntityName() ) ); - - for ( int i = 0; i < c; i++ ) + while (candidates.Count() > 0) { - CAI_BaseActor *npc = candidates[ i ]; - Assert( npc ); + // Pick a random slot in the candidates array. + int slot = RandomInt( 0, candidates.Count() - 1 ); - AI_Response *response = npc->SpeakFindResponse( inputdata.value.String(), modifiers ); - if ( !response ) - continue; - - float duration = npc->GetResponseDuration( response ); - // Couldn't look it up - if ( duration <= 0.0f ) - continue; + CAI_BaseActor *npc = candidates[ slot ]; - if ( !npc->PermitResponse( duration ) ) + // Try to find the response for this slot. + AI_Response response; + bool result = npc->SpeakFindResponse( response, inputdata.value.String(), modifiers.Get() ); + if ( result ) { - delete response; - continue; - } - - // - NPCInterjection inter; - inter.response = response; - inter.npc = npc; - - validResponses.AddToTail( inter ); - } + float duration = npc->GetResponseDuration( response ); - int rcount = validResponses.Count(); - if ( rcount >= 1 ) - { - int slot = RandomInt( 0, rcount - 1 ); - - for ( int i = 0; i < rcount; i++ ) - { - NPCInterjection *pInterjection = &validResponses[ i ]; - if ( i == slot ) + if ( ( duration > 0.0f ) && npc->PermitResponse( duration ) ) { - pInterjection->npc->SpeakDispatchResponse( inputdata.value.String(), pInterjection->response ); - } - else - { - delete pInterjection->response; + // If we could look it up, dispatch it and bail. + npc->SpeakDispatchResponse( inputdata.value.String(), response ); + return; } } + + // Remove this entry and look for another one. + candidates.FastRemove(slot); } } } @@ -2783,12 +2747,12 @@ void CSceneEntity::QueueResumePlayback( void ) CAI_BaseActor *pBaseActor = dynamic_cast<CAI_BaseActor*>(pActor); if ( pBaseActor ) { - AI_Response *result = pBaseActor->SpeakFindResponse( STRING(m_iszResumeSceneFile), NULL ); + AI_Response response; + bool result = pBaseActor->SpeakFindResponse( response, STRING(m_iszResumeSceneFile), NULL ); if ( result ) { - char response[ 256 ]; - result->GetResponse( response, sizeof( response ) ); - bStartedScene = InstancedScriptedScene( NULL, response, &m_hWaitingForThisResumeScene, 0, false ) != 0; + const char *szResponse = response.GetResponsePtr(); + bStartedScene = InstancedScriptedScene( NULL, szResponse, &m_hWaitingForThisResumeScene, 0, false ) != 0; } } } diff --git a/mp/src/game/server/sendproxy.cpp b/mp/src/game/server/sendproxy.cpp index ad017c64..71e2a071 100644 --- a/mp/src/game/server/sendproxy.cpp +++ b/mp/src/game/server/sendproxy.cpp @@ -27,7 +27,7 @@ void SendProxy_EHandleToInt( const SendProp *pProp, const void *pStruct, const v if ( pHandle && pHandle->Get() ) { - int iSerialNum = pHandle->GetSerialNumber() & (1 << NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS) - 1; + int iSerialNum = pHandle->GetSerialNumber() & ( (1 << NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS) - 1 ); pOut->m_Int = pHandle->GetEntryIndex() | (iSerialNum << MAX_EDICT_BITS); } else @@ -106,6 +106,7 @@ REGISTER_SEND_PROXY_NON_MODIFIED_POINTER( SendProxy_OnlyToTeam ); #define TIME_BITS 24 // This table encodes edict data. +#if 0 static void SendProxy_Time( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID ) { float clock_base = floor( gpGlobals->curtime ); @@ -119,6 +120,7 @@ static void SendProxy_Time( const SendProp *pProp, const void *pStruct, const vo pOut->m_Int = addt; } +#endif //----------------------------------------------------------------------------- // Purpose: diff --git a/mp/src/game/server/sound.cpp b/mp/src/game/server/sound.cpp index 160ba1c0..1a83fafd 100644 --- a/mp/src/game/server/sound.cpp +++ b/mp/src/game/server/sound.cpp @@ -1187,7 +1187,7 @@ int SENTENCEG_PlayRndI(edict_t *entity, int isentenceg, name[0] = 0; ipick = engine->SentenceGroupPick( isentenceg, name, sizeof( name ) ); - if (ipick > 0 && name) + if ( ( ipick > 0 ) && name[0] ) { int sentenceIndex = SENTENCEG_Lookup( name ); CPASAttenuationFilter filter( GetContainingEntity( entity ), soundlevel ); diff --git a/mp/src/game/server/team_control_point_master.cpp b/mp/src/game/server/team_control_point_master.cpp index 8ad9796d..956f7ddb 100644 --- a/mp/src/game/server/team_control_point_master.cpp +++ b/mp/src/game/server/team_control_point_master.cpp @@ -1267,7 +1267,7 @@ float CTeamControlPointMaster::GetPartialCapturePointRate( void ) return m_flPartialCapturePointsRate; } -/* +#ifdef STAGING_ONLY //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- @@ -1344,4 +1344,4 @@ void cc_PlayRound( const CCommand& args ) } static ConCommand playround( "playround", cc_PlayRound, "Play the selected round\n\tArgument: {round name given by \"listrounds\" command}", FCVAR_CHEAT ); -*/
\ No newline at end of file +#endif
\ No newline at end of file diff --git a/mp/src/game/server/team_control_point_master.h b/mp/src/game/server/team_control_point_master.h index b6a7d35d..0c229a05 100644 --- a/mp/src/game/server/team_control_point_master.h +++ b/mp/src/game/server/team_control_point_master.h @@ -121,14 +121,18 @@ public: bool ShouldScorePerCapture( void ){ return m_bScorePerCapture; } bool ShouldPlayAllControlPointRounds( void ){ return m_bPlayAllRounds; } int NumPlayableControlPointRounds( void ); // checks to see if there are any more rounds to play (but doesn't actually "get" one to play) - -// void ListRounds( void ); + +#ifdef STAGING_ONLY + void ListRounds( void ); +#endif float GetPartialCapturePointRate( void ); void SetLastOwnershipChangeTime( float m_flTime ) { m_flLastOwnershipChangeTime = m_flTime; } float GetLastOwnershipChangeTime( void ) { return m_flLastOwnershipChangeTime; } + int GetCurrentRoundIndex() { return m_iCurrentRoundIndex; } + private: void EXPORT CPMThink( void ); diff --git a/mp/src/game/server/team_train_watcher.cpp b/mp/src/game/server/team_train_watcher.cpp index b8ef36c3..0d6ebdbd 100644 --- a/mp/src/game/server/team_train_watcher.cpp +++ b/mp/src/game/server/team_train_watcher.cpp @@ -73,6 +73,7 @@ BEGIN_DATADESC( CTeamTrainWatcher ) DEFINE_INPUTFUNC( FIELD_FLOAT, "SetSpeedForwardModifier", InputSetSpeedForwardModifier ), DEFINE_INPUTFUNC( FIELD_INTEGER, "SetTrainRecedeTime", InputSetTrainRecedeTime ), DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetTrainCanRecede", InputSetTrainCanRecede ), + DEFINE_INPUTFUNC( FIELD_INTEGER, "SetTrainRecedeTimeAndUpdate", InputSetTrainRecedeTimeAndUpdate ), // Outputs DEFINE_OUTPUT( m_OnTrainStartRecede, "OnTrainStartRecede" ), @@ -714,6 +715,24 @@ void CTeamTrainWatcher::InputSetTrainRecedeTime( inputdata_t &inputdata ) } } +void CTeamTrainWatcher::InputSetTrainRecedeTimeAndUpdate(inputdata_t &inputdata) +{ + InputSetTrainRecedeTime( inputdata ); + + // update our time if we're already counting down + if ( m_flRecedeTime > 0 ) + { + m_flRecedeTotalTime = tf_escort_recede_time.GetFloat(); + if ( m_nTrainRecedeTime > 0 ) + { + m_flRecedeTotalTime = m_nTrainRecedeTime; + } + + m_flRecedeStartTime = gpGlobals->curtime; + m_flRecedeTime = m_flRecedeStartTime + m_flRecedeTotalTime; + } +} + void CTeamTrainWatcher::InputSetTrainCanRecede( inputdata_t &inputdata ) { m_bTrainCanRecede = inputdata.value.Bool(); diff --git a/mp/src/game/server/team_train_watcher.h b/mp/src/game/server/team_train_watcher.h index 22b82c6f..663b6141 100644 --- a/mp/src/game/server/team_train_watcher.h +++ b/mp/src/game/server/team_train_watcher.h @@ -58,6 +58,7 @@ public: void InputSetSpeedForwardModifier( inputdata_t &inputdata ); void InputSetTrainRecedeTime( inputdata_t &inputdata ); void InputSetTrainCanRecede( inputdata_t &inputdata ); + void InputSetTrainRecedeTimeAndUpdate( inputdata_t &inputdata ); // ========================================================== // given a start node and a list of goal nodes @@ -94,6 +95,8 @@ public: void DumpStats( void ); #endif // STAGING_ONLY && TF_DLL + float GetTrainProgress() { return m_flTotalProgress; } + private: void StartCaptureAlarm( CTeamControlPoint *pPoint ); diff --git a/mp/src/game/server/trigger_area_capture.cpp b/mp/src/game/server/trigger_area_capture.cpp index 2839200b..648a3b86 100644 --- a/mp/src/game/server/trigger_area_capture.cpp +++ b/mp/src/game/server/trigger_area_capture.cpp @@ -366,6 +366,7 @@ void CTriggerAreaCapture::CaptureThink( void ) } iNumBlockablePlayers[iTeam] += TeamplayGameRules()->GetCaptureValueForPlayer( pPlayer ); + pPlayer->SetLastObjectiveTime( gpGlobals->curtime ); } continue; } @@ -378,6 +379,7 @@ void CTriggerAreaCapture::CaptureThink( void ) } iNumPlayers[iTeam] += TeamplayGameRules()->GetCaptureValueForPlayer( pPlayer ); + pPlayer->SetLastObjectiveTime( gpGlobals->curtime ); } } } diff --git a/mp/src/game/server/triggers.cpp b/mp/src/game/server/triggers.cpp index 295e826a..742976fb 100644 --- a/mp/src/game/server/triggers.cpp +++ b/mp/src/game/server/triggers.cpp @@ -33,6 +33,7 @@ #include "ai_behavior_follow.h" #include "ai_behavior_lead.h" #include "gameinterface.h" +#include "ilagcompensationmanager.h" #ifdef HL2_DLL #include "hl2_player.h" @@ -2269,7 +2270,7 @@ void CTriggerPush::Touch( CBaseEntity *pOther ) #endif Vector vecPush = (m_flPushSpeed * vecAbsDir); - if ( pOther->GetFlags() & FL_BASEVELOCITY ) + if ( ( pOther->GetFlags() & FL_BASEVELOCITY ) && !lagcompensation->IsCurrentlyDoingLagCompensation() ) { vecPush = vecPush + pOther->GetBaseVelocity(); } diff --git a/mp/src/game/server/util.cpp b/mp/src/game/server/util.cpp index aba6f327..8cd8f989 100644 --- a/mp/src/game/server/util.cpp +++ b/mp/src/game/server/util.cpp @@ -200,7 +200,7 @@ void CEntityFactoryDictionary::ReportEntitySizes() { for ( int i = m_Factories.First(); i != m_Factories.InvalidIndex(); i = m_Factories.Next( i ) ) { - Msg( " %s: %d", m_Factories.GetElementName( i ), m_Factories[i]->GetEntitySize() ); + Msg( " %s: %llu", m_Factories.GetElementName( i ), (uint64)(m_Factories[i]->GetEntitySize()) ); } } @@ -1348,7 +1348,7 @@ void UTIL_SnapDirectionToAxis( Vector &direction, float epsilon ) } } -char *UTIL_VarArgs( const char *format, ... ) +const char *UTIL_VarArgs( const char *format, ... ) { va_list argptr; static char string[1024]; diff --git a/mp/src/game/server/util.h b/mp/src/game/server/util.h index a788da6c..92c341d8 100644 --- a/mp/src/game/server/util.h +++ b/mp/src/game/server/util.h @@ -365,7 +365,7 @@ void UTIL_Beam( Vector &Start, Vector &End, int nModelIndex, int nHaloIndex, un float Life, unsigned char Width, unsigned char EndWidth, unsigned char FadeLength, unsigned char Noise, unsigned char Red, unsigned char Green, unsigned char Blue, unsigned char Brightness, unsigned char Speed); -char *UTIL_VarArgs( PRINTF_FORMAT_STRING const char *format, ... ); +const char *UTIL_VarArgs( PRINTF_FORMAT_STRING const char *format, ... ) FMTFUNCTION( 1, 2 ); bool UTIL_IsValidEntity( CBaseEntity *pEnt ); bool UTIL_TeamsMatch( const char *pTeamName1, const char *pTeamName2 ); @@ -475,7 +475,7 @@ void UTIL_HudMessage( CBasePlayer *pToPlayer, const hudtextparms_t &textparms, void UTIL_HudHintText( CBaseEntity *pEntity, const char *pMessage ); // Writes message to console with timestamp and FragLog header. -void UTIL_LogPrintf( PRINTF_FORMAT_STRING const char *fmt, ... ); +void UTIL_LogPrintf( PRINTF_FORMAT_STRING const char *fmt, ... ) FMTFUNCTION( 1, 2 ); // Sorta like FInViewCone, but for nonNPCs. float UTIL_DotPoints ( const Vector &vecSrc, const Vector &vecCheck, const Vector &vecDir ); diff --git a/mp/src/game/server/vote_controller.cpp b/mp/src/game/server/vote_controller.cpp index 316974ad..7dab54bb 100644 --- a/mp/src/game/server/vote_controller.cpp +++ b/mp/src/game/server/vote_controller.cpp @@ -10,6 +10,7 @@ #include "eiface.h" #include "team.h" #include "gameinterface.h" +#include "fmtstr.h" #ifdef TF_DLL #include "tf/tf_gamerules.h" @@ -39,15 +40,105 @@ CVoteController *g_voteController = NULL; ConVar sv_vote_timer_duration("sv_vote_timer_duration", "15", FCVAR_DEVELOPMENTONLY, "How long to allow voting on an issue"); ConVar sv_vote_command_delay("sv_vote_command_delay", "2", FCVAR_DEVELOPMENTONLY, "How long after a vote passes until the action happens", false, 0, true, 4.5); -ConVar sv_allow_votes("sv_allow_votes", "1", 0, "Allow voting?"); -ConVar sv_vote_failure_timer("sv_vote_failure_timer", "300", 0, "A vote that fails cannot be re-submitted for this long"); +ConVar sv_allow_votes("sv_allow_votes", "1", FCVAR_NONE, "Allow voting?"); +ConVar sv_vote_failure_timer( "sv_vote_failure_timer", "300", FCVAR_NONE, "A vote that fails cannot be re-submitted for this long" ); #ifdef TF_DLL -ConVar sv_vote_failure_timer_mvm( "sv_vote_failure_timer_mvm", "120", 0, "A vote that fails in MvM cannot be re-submitted for this long" ); +ConVar sv_vote_failure_timer_mvm( "sv_vote_failure_timer_mvm", "120", FCVAR_NONE, "A vote that fails in MvM cannot be re-submitted for this long" ); #endif // TF_DLL ConVar sv_vote_creation_timer("sv_vote_creation_timer", "120", FCVAR_DEVELOPMENTONLY, "How often someone can individually call a vote."); -ConVar sv_vote_quorum_ratio( "sv_vote_quorum_ratio", "0.6", 1, "The minimum ratio of players needed to vote on an issue to resolve it.", true, 0.1, true, 1.0 ); -ConVar sv_vote_allow_spectators( "sv_vote_allow_spectators", "0", 0, "Allow spectators to vote?" ); -ConVar sv_vote_ui_hide_disabled_issues( "sv_vote_ui_hide_disabled_issues", "1", 0, "Suppress listing of disabled issues in the vote setup screen." ); +ConVar sv_vote_quorum_ratio( "sv_vote_quorum_ratio", "0.6", FCVAR_HIDDEN, "The minimum ratio of players needed to vote on an issue to resolve it.", true, 0.1, true, 1.0 ); +ConVar sv_vote_allow_spectators( "sv_vote_allow_spectators", "0", FCVAR_NONE, "Allow spectators to vote?" ); +ConVar sv_vote_ui_hide_disabled_issues( "sv_vote_ui_hide_disabled_issues", "1", FCVAR_NONE, "Suppress listing of disabled issues in the vote setup screen." ); + +static const int k_nKickWatchListMaxDuration = 300; + +//----------------------------------------------------------------------------- +// Purpose: Game system to detect maps without cameras in them, and move on +//----------------------------------------------------------------------------- +class CVoteControllerSystem : public CAutoGameSystemPerFrame +{ +public: + CVoteControllerSystem( char const *name ) : CAutoGameSystemPerFrame( name ) + { + SetDefLessFunc( m_mapKickWatchList ); + m_flNextKickCheckTime = 0.f; + } + + virtual void LevelInitPreEntity() + { + } + + virtual void FrameUpdatePostEntityThink( void ) + { + // Executing the vote controller command needs to happen in the PostEntityThink as it can restart levels and + // blast entities, etc. If you're doing this during a regular think, this can cause entities thinking after + // you in Physics_RunThinkFunctions() to get grumpy and crash. + if ( g_voteController ) + { + // Vote passed - execute the command + if ( g_voteController->m_executeCommandTimer.HasStarted() && g_voteController->m_executeCommandTimer.IsElapsed() ) + { + g_voteController->m_executeCommandTimer.Invalidate(); + g_voteController->m_potentialIssues[g_voteController->m_iActiveIssueIndex]->ExecuteCommand(); + } + + // Kick watch + if ( m_flNextKickCheckTime < gpGlobals->curtime ) + { + FOR_EACH_MAP( m_mapKickWatchList, i ) + { + if ( gpGlobals->curtime > m_mapKickWatchList[i] ) + { + m_mapKickWatchList.RemoveAt( i ); + break; // Constantly called code - resume on next pass + } + + CBasePlayer *pTarget = NULL; + CSteamID steamIDPlayer; + for ( int j = 1; j <= gpGlobals->maxClients; j++ ) + { + CBasePlayer *pPlayer = UTIL_PlayerByIndex( j ); + if ( !pPlayer ) + continue; + + if ( pPlayer->GetSteamID( &steamIDPlayer ) == false ) + continue; + + if ( steamIDPlayer == m_mapKickWatchList.Key( i ) ) + { + pTarget = pPlayer; + break; + } + } + + if ( pTarget ) + { + // Welcome back + engine->ServerCommand( CFmtStr( "kickid %d %s;", pTarget->GetUserID(), "Kicked by server." ) ); + } + } + + m_flNextKickCheckTime = gpGlobals->curtime + 0.2f; + } + } + } + + void AddPlayerToKickWatchList( CSteamID steamID, float flDuration ) + { + flDuration = clamp( flDuration, 1.f, (float)k_nKickWatchListMaxDuration ); + if ( m_mapKickWatchList.Find( steamID ) == m_mapKickWatchList.InvalidIndex() ) + { + m_mapKickWatchList.Insert( steamID, ( gpGlobals->curtime + flDuration ) ); + } + } + +private: + + CUtlMap< CSteamID, float > m_mapKickWatchList; + float m_flNextKickCheckTime; +}; + +CVoteControllerSystem VoteControllerSystem( "CVoteControllerSystem" ); //----------------------------------------------------------------------------- // Purpose: @@ -101,7 +192,7 @@ CON_COMMAND( callvote, "Start a vote on an issue." ) { if ( pVoteCaller->GetTeamNumber() == TEAM_SPECTATOR ) { - g_voteController->SendVoteFailedMessage( VOTE_FAILED_SPECTATOR, pVoteCaller ); + g_voteController->SendVoteCreationFailedMessage( VOTE_FAILED_SPECTATOR, pVoteCaller ); return; } } @@ -111,7 +202,7 @@ CON_COMMAND( callvote, "Start a vote on an issue." ) int nCooldown = 0; if ( !g_voteController->CanEntityCallVote( pVoteCaller, nCooldown ) ) { - g_voteController->SendVoteFailedMessage( VOTE_FAILED_RATE_EXCEEDED, pVoteCaller, nCooldown ); + g_voteController->SendVoteCreationFailedMessage( VOTE_FAILED_RATE_EXCEEDED, pVoteCaller, nCooldown ); return; } #endif @@ -381,7 +472,7 @@ bool CVoteController::CreateVote( int iEntIndex, const char *pszTypeString, cons { if ( !bDedicatedServer ) { - SendVoteFailedMessage( nErrorCode, pVoteCaller, nTime ); + SendVoteCreationFailedMessage( nErrorCode, pVoteCaller, nTime ); } } } @@ -391,35 +482,43 @@ bool CVoteController::CreateVote( int iEntIndex, const char *pszTypeString, cons } //----------------------------------------------------------------------------- -// Purpose: Sent to everyone, unless we pass a player pointer +// Purpose: The vote failed to start - let the caller know why //----------------------------------------------------------------------------- -void CVoteController::SendVoteFailedMessage( vote_create_failed_t nReason, CBasePlayer *pVoteCaller, int nTime ) +void CVoteController::SendVoteCreationFailedMessage( vote_create_failed_t nReason, CBasePlayer *pVoteCaller, int nTime /*= -1*/ ) { - // driller: need to merge all failure case stuff into a single path - if ( pVoteCaller ) - { - CSingleUserRecipientFilter user( pVoteCaller ); - user.MakeReliable(); + Assert( pVoteCaller ); + if ( !pVoteCaller ) + return; - UserMessageBegin( user, "CallVoteFailed" ); - WRITE_BYTE( nReason ); - WRITE_SHORT( nTime ); - MessageEnd(); - } - else - { - UTIL_LogPrintf("Vote failed \"%s %s\" \n", - m_potentialIssues[m_iActiveIssueIndex]->GetTypeString(), - m_potentialIssues[m_iActiveIssueIndex]->GetDetailsString() ); + CSingleUserRecipientFilter user( pVoteCaller ); + user.MakeReliable(); - CBroadcastRecipientFilter filter; - filter.MakeReliable(); + UserMessageBegin( user, "CallVoteFailed" ); + WRITE_BYTE( nReason ); + WRITE_SHORT( nTime ); + MessageEnd(); +} - UserMessageBegin( filter, "VoteFailed" ); - WRITE_BYTE( m_iOnlyTeamToVote ); - WRITE_BYTE( nReason ); - MessageEnd(); - } +//----------------------------------------------------------------------------- +// Purpose: The vote was called, but failed to pass - let everyone know why +//----------------------------------------------------------------------------- +void CVoteController::SendVoteFailedToPassMessage( vote_create_failed_t nReason ) +{ + Assert( m_potentialIssues[m_iActiveIssueIndex] ); + + // See if we have a player target. + CBasePlayer *pVoteTarget = m_potentialIssues[m_iActiveIssueIndex]->m_hPlayerTarget; + bool bFakeClient = ( pVoteTarget && ( pVoteTarget->IsFakeClient() || pVoteTarget->IsHLTV() || pVoteTarget->IsReplay() ) ); + + UTIL_LogPrintf( "Vote failed \"%s %s\" with code %i (proxy: %i) \n", m_potentialIssues[m_iActiveIssueIndex]->GetTypeString(), m_potentialIssues[m_iActiveIssueIndex]->GetDetailsString(), (int)nReason, bFakeClient ); + + CBroadcastRecipientFilter filter; + filter.MakeReliable(); + + UserMessageBegin( filter, "VoteFailed" ); + WRITE_BYTE( m_iOnlyTeamToVote ); + WRITE_BYTE( nReason ); + MessageEnd(); } //----------------------------------------------------------------------------- @@ -577,7 +676,7 @@ void CVoteController::VoteControllerThink( void ) // Option1 is Yes if ( nWinningVoteOption != VOTE_OPTION1 ) { - SendVoteFailedMessage( VOTE_FAILED_YES_MUST_EXCEED_NO ); + SendVoteFailedToPassMessage( VOTE_FAILED_YES_MUST_EXCEED_NO ); bVotePassed = false; } } @@ -592,7 +691,7 @@ void CVoteController::VoteControllerThink( void ) } else { - SendVoteFailedMessage( VOTE_FAILED_QUORUM_FAILURE ); + SendVoteFailedToPassMessage( VOTE_FAILED_QUORUM_FAILURE ); bVotePassed = false; } @@ -601,9 +700,11 @@ void CVoteController::VoteControllerThink( void ) m_executeCommandTimer.Start( sv_vote_command_delay.GetFloat() ); m_resetVoteTimer.Start( 5.0 ); - UTIL_LogPrintf("Vote succeeded \"%s %s\"\n", - m_potentialIssues[m_iActiveIssueIndex]->GetTypeString(), - m_potentialIssues[m_iActiveIssueIndex]->GetDetailsString() ); + // Target is not always a player (changelevel, etc) + CBasePlayer *pVoteTarget = m_potentialIssues[m_iActiveIssueIndex]->m_hPlayerTarget; + bool bFakeClient = ( pVoteTarget && ( pVoteTarget->IsFakeClient() || pVoteTarget->IsHLTV() || pVoteTarget->IsReplay() ) ); + + UTIL_LogPrintf( "Vote succeeded \"%s %s\" (proxy: %i) \n", m_potentialIssues[m_iActiveIssueIndex]->GetTypeString(), m_potentialIssues[m_iActiveIssueIndex]->GetDetailsString(), bFakeClient ); CBroadcastRecipientFilter filter; filter.MakeReliable(); @@ -822,6 +923,14 @@ bool CVoteController::CanEntityCallVote( CBasePlayer *pPlayer, int &nCooldown ) }; //----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CVoteController::AddPlayerToKickWatchList( CSteamID steamID, float flDuration ) +{ + VoteControllerSystem.AddPlayerToKickWatchList( steamID, flDuration ); +} + +//----------------------------------------------------------------------------- // Purpose: BaseIssue //----------------------------------------------------------------------------- CBaseIssue::CBaseIssue( const char *pszTypeString ) @@ -831,6 +940,7 @@ CBaseIssue::CBaseIssue( const char *pszTypeString ) m_iNumYesVotes = 0; m_iNumNoVotes = 0; m_iNumPotentialVotes = 0; + m_flNextCallTime = -1.f; ASSERT( g_voteController ); g_voteController->RegisterIssue( this ); @@ -943,9 +1053,18 @@ bool CBaseIssue::CanCallVote( int iEntIndex, const char *pszDetails, vote_create return true; // Bogus player - if( iEntIndex == -1 ) + if ( iEntIndex == -1 ) return false; + // Note: Issue timers reset on level change because the class is created/destroyed during transitions. + // It'd be nice to refactor the basic framework of the system to get rid of side-effects like this. + if ( m_flNextCallTime != -1.f && gpGlobals->curtime < m_flNextCallTime ) + { + nFailCode = VOTE_FAILED_ON_COOLDOWN; + nTime = m_flNextCallTime - gpGlobals->curtime; + return false; + } + #ifdef TF_DLL if ( TFGameRules() && TFGameRules()->IsInWaitingForPlayers() && !TFGameRules()->IsInTournamentMode() ) { @@ -955,14 +1074,14 @@ bool CBaseIssue::CanCallVote( int iEntIndex, const char *pszDetails, vote_create #endif // TF_DLL CBaseEntity *pVoteCaller = UTIL_EntityByIndex( iEntIndex ); - if( pVoteCaller && !CanTeamCallVote( GetVoterTeam( pVoteCaller ) ) ) + if ( pVoteCaller && !CanTeamCallVote( GetVoterTeam( pVoteCaller ) ) ) { nFailCode = VOTE_FAILED_TEAM_CANT_CALL; return false; } // Did this fail recently? - for( int iIndex = 0; iIndex < m_FailedVotes.Count(); iIndex++ ) + for ( int iIndex = 0; iIndex < m_FailedVotes.Count(); iIndex++ ) { FailedVote *pCurrentFailure = m_FailedVotes[iIndex]; int nTimeRemaining = pCurrentFailure->flLockoutTime - gpGlobals->curtime; @@ -988,7 +1107,7 @@ bool CBaseIssue::CanCallVote( int iEntIndex, const char *pszDetails, vote_create if ( bFailed ) { - nFailCode = VOTE_FAILED_FAILED_RECENTLY; + nFailCode = VOTE_FAILED_ON_COOLDOWN; nTime = nTimeRemaining; return false; } @@ -1065,36 +1184,4 @@ bool CBaseIssue::GetVoteOptions( CUtlVector <const char*> &vecNames ) return true; } -//----------------------------------------------------------------------------- -// Purpose: Game system to detect maps without cameras in them, and move on -//----------------------------------------------------------------------------- -class CVoteControllerSystem : public CAutoGameSystemPerFrame -{ -public: - CVoteControllerSystem( char const *name ) : CAutoGameSystemPerFrame( name ) - { - } - - virtual void LevelInitPreEntity() - { - } - - virtual void FrameUpdatePostEntityThink( void ) - { - // Executing the vote controller command needs to happen in the PostEntityThink as it can restart levels and - // blast entities, etc. If you're doing this during a regular think, this can cause entities thinking after - // you in Physics_RunThinkFunctions() to get grumpy and crash. - if( g_voteController ) - { - // Vote passed - execute the command - if( g_voteController->m_executeCommandTimer.HasStarted() && g_voteController->m_executeCommandTimer.IsElapsed() ) - { - g_voteController->m_executeCommandTimer.Invalidate(); - g_voteController->m_potentialIssues[ g_voteController->m_iActiveIssueIndex ]->ExecuteCommand(); - } - } - } -}; - -CVoteControllerSystem VoteControllerSystem( "CVoteControllerSystem" ); diff --git a/mp/src/game/server/vote_controller.h b/mp/src/game/server/vote_controller.h index 0376d6a6..ccc55cd5 100644 --- a/mp/src/game/server/vote_controller.h +++ b/mp/src/game/server/vote_controller.h @@ -17,7 +17,7 @@ #define MAX_COMMAND_LENGTH 64 #define MAX_CREATE_ERROR_STRING 96 -class CBaseIssue // Abstract base class for all things-that-can-be-voted-on. +class CBaseIssue // Base class concept for vote issues (i.e. Kick Player). Created per level-load and destroyed by CVoteController's dtor. { public: CBaseIssue(const char *typeString); @@ -41,6 +41,9 @@ public: virtual void SetYesNoVoteCount( int iNumYesVotes, int iNumNoVotes, int iNumPotentialVotes ); virtual bool GetVoteOptions( CUtlVector <const char*> &vecNames ); // We use this to generate options for voting virtual bool BRecordVoteFailureEventForEntity( int iVoteCallingEntityIndex ) const { return iVoteCallingEntityIndex != DEDICATED_SERVER; } + void SetIssueCooldownDuration( float flDuration ) { m_flNextCallTime = gpGlobals->curtime + flDuration; } // The issue can not be raised again for this period of time (in seconds) + + CHandle< CBasePlayer > m_hPlayerTarget; // If the target of the issue is a player, we should store them here protected: static void ListStandardNoArgCommand( CBasePlayer *forWhom, const char *issueString ); // List a Yes vote command @@ -59,6 +62,7 @@ protected: int m_iNumYesVotes; int m_iNumNoVotes; int m_iNumPotentialVotes; + float m_flNextCallTime; }; class CVoteController : public CBaseEntity @@ -93,7 +97,8 @@ public: void ListIssues( CBasePlayer *pForWhom ); bool IsValidVoter( CBasePlayer *pWhom ); bool CanTeamCastVote( int iTeam ) const; - void SendVoteFailedMessage( vote_create_failed_t nReason = VOTE_FAILED_GENERIC, CBasePlayer *pVoteCaller = NULL, int nTime = -1 ); + void SendVoteCreationFailedMessage( vote_create_failed_t nReason, CBasePlayer *pVoteCaller, int nTime = -1 ); + void SendVoteFailedToPassMessage( vote_create_failed_t nReason ); void VoteChoice_Increment( int nVoteChoice ); void VoteChoice_Decrement( int nVoteChoice ); int GetWinningVoteOption( void ); @@ -101,6 +106,8 @@ public: bool CanEntityCallVote( CBasePlayer *pPlayer, int &nCooldown ); bool IsVoteActive( void ) { return m_iActiveIssueIndex != INVALID_ISSUE; } + void AddPlayerToKickWatchList( CSteamID steamID, float flDuration ); + protected: void ResetData( void ); void VoteControllerThink( void ); diff --git a/mp/src/game/shared/GameStats.cpp b/mp/src/game/shared/GameStats.cpp index 695dc553..d01e56fb 100644 --- a/mp/src/game/shared/GameStats.cpp +++ b/mp/src/game/shared/GameStats.cpp @@ -1199,6 +1199,7 @@ void CBaseGameStats_Driver::ResetData() pKV->SetInt( "Height", dest_height ); const MaterialSystem_Config_t &config = materials->GetCurrentConfigForVideoCard(); pKV->SetInt( "Windowed", config.Windowed() == true ); + pKV->SetInt( "MaxDxLevel", g_pMaterialSystemHardwareConfig->GetMaxDXSupportLevel() ); engine->SetGamestatsData( m_pGamestatsData ); #endif diff --git a/mp/src/game/shared/SoundEmitterSystem.cpp b/mp/src/game/shared/SoundEmitterSystem.cpp index 6d27fde9..7b641c20 100644 --- a/mp/src/game/shared/SoundEmitterSystem.cpp +++ b/mp/src/game/shared/SoundEmitterSystem.cpp @@ -465,7 +465,6 @@ public: { return; } -#endif // STAGING_ONLY if ( !Q_strncasecmp( params.soundname, "vo", 2 ) && !( params.channel == CHAN_STREAM || @@ -475,6 +474,7 @@ public: DevMsg( "EmitSound: Voice wave file %s doesn't specify CHAN_VOICE, CHAN_VOICE2 or CHAN_STREAM for sound %s\n", params.soundname, ep.m_pSoundName ); } +#endif // STAGING_ONLY // handle SND_CHANGEPITCH/SND_CHANGEVOL and other sound flags.etc. if( ep.m_nFlags & SND_CHANGE_PITCH ) diff --git a/mp/src/game/shared/activitylist.cpp b/mp/src/game/shared/activitylist.cpp index 2b421252..4c882d47 100644 --- a/mp/src/game/shared/activitylist.cpp +++ b/mp/src/game/shared/activitylist.cpp @@ -2275,6 +2275,35 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_SPELL_VM_ARM ); REGISTER_SHARED_ACTIVITY( ACT_SPELL_VM_FIRE ); + REGISTER_SHARED_ACTIVITY( ACT_BREADSAPPER_VM_DRAW ); + REGISTER_SHARED_ACTIVITY( ACT_BREADSAPPER_VM_IDLE ); + + REGISTER_SHARED_ACTIVITY( ACT_BREADGLOVES_VM_HITLEFT ); + REGISTER_SHARED_ACTIVITY( ACT_BREADGLOVES_VM_HITRIGHT ); + REGISTER_SHARED_ACTIVITY( ACT_BREADGLOVES_VM_SWINGHARD ); + REGISTER_SHARED_ACTIVITY( ACT_BREADGLOVES_VM_IDLE ); + REGISTER_SHARED_ACTIVITY( ACT_BREADGLOVES_VM_DRAW ); + + REGISTER_SHARED_ACTIVITY( ACT_BREADMONSTER_GLOVES_IDLE ); + REGISTER_SHARED_ACTIVITY( ACT_BREADMONSTER_GLOVES_HITRIGHT ); + REGISTER_SHARED_ACTIVITY( ACT_BREADMONSTER_GLOVES_HITUP ); + + REGISTER_SHARED_ACTIVITY( ACT_BREADMONSTER_VM_DRAW ); + REGISTER_SHARED_ACTIVITY( ACT_BREADMONSTER_VM_IDLE ); + REGISTER_SHARED_ACTIVITY( ACT_BREADMONSTER_VM_PRIMARYATTACK ); + + REGISTER_SHARED_ACTIVITY( ACT_PARACHUTE_DEPLOY ); + REGISTER_SHARED_ACTIVITY( ACT_PARACHUTE_DEPLOY_IDLE ); + REGISTER_SHARED_ACTIVITY( ACT_PARACHUTE_RETRACT ); + REGISTER_SHARED_ACTIVITY( ACT_PARACHUTE_RETRACT_IDLE ); + + REGISTER_SHARED_ACTIVITY( ACT_BOT_SPAWN ); + REGISTER_SHARED_ACTIVITY( ACT_BOT_PANIC ); + REGISTER_SHARED_ACTIVITY( ACT_BOT_PRIMARY_MOVEMENT ); + REGISTER_SHARED_ACTIVITY( ACT_BOT_GESTURE_FLINCH ); + REGISTER_SHARED_ACTIVITY( ACT_BOT_PANIC_START ); + REGISTER_SHARED_ACTIVITY( ACT_BOT_PANIC_END ); + AssertMsg( g_HighestActivity == LAST_SHARED_ACTIVITY - 1, "Not all activities from ai_activity.h registered in activitylist.cpp" ); } diff --git a/mp/src/game/shared/ai_activity.h b/mp/src/game/shared/ai_activity.h index fbd10c39..3d3207c9 100644 --- a/mp/src/game/shared/ai_activity.h +++ b/mp/src/game/shared/ai_activity.h @@ -2107,6 +2107,37 @@ typedef enum ACT_SPELL_VM_ARM, ACT_SPELL_VM_FIRE, + // Bread Monster Sapper + ACT_BREADSAPPER_VM_DRAW, + ACT_BREADSAPPER_VM_IDLE, + + // Bread Gloves + ACT_BREADGLOVES_VM_HITLEFT, + ACT_BREADGLOVES_VM_HITRIGHT, + ACT_BREADGLOVES_VM_SWINGHARD, + ACT_BREADGLOVES_VM_IDLE, + ACT_BREADGLOVES_VM_DRAW, + + ACT_BREADMONSTER_GLOVES_IDLE, + ACT_BREADMONSTER_GLOVES_HITRIGHT, + ACT_BREADMONSTER_GLOVES_HITUP, + + ACT_BREADMONSTER_VM_DRAW, + ACT_BREADMONSTER_VM_IDLE, + ACT_BREADMONSTER_VM_PRIMARYATTACK, + + ACT_PARACHUTE_DEPLOY, + ACT_PARACHUTE_DEPLOY_IDLE, + ACT_PARACHUTE_RETRACT, + ACT_PARACHUTE_RETRACT_IDLE, + + ACT_BOT_SPAWN, + ACT_BOT_PANIC, + ACT_BOT_PRIMARY_MOVEMENT, + ACT_BOT_GESTURE_FLINCH, + ACT_BOT_PANIC_START, + ACT_BOT_PANIC_END, + // this is the end of the global activities, private per-monster activities start here. LAST_SHARED_ACTIVITY, } Activity; diff --git a/mp/src/game/shared/apparent_velocity_helper.h b/mp/src/game/shared/apparent_velocity_helper.h index 765a419d..65e28fbd 100644 --- a/mp/src/game/shared/apparent_velocity_helper.h +++ b/mp/src/game/shared/apparent_velocity_helper.h @@ -46,9 +46,10 @@ template< class T, class Functor=CDefaultCalcDistance<T> > class CApparentVelocity { public: - CApparentVelocity() + CApparentVelocity(const T& t0) { m_LastTime = -1; + m_LastValue = t0; } float AddSample( float time, T value ) diff --git a/mp/src/game/shared/basecombatweapon_shared.cpp b/mp/src/game/shared/basecombatweapon_shared.cpp index 754919d3..4ab20c12 100644 --- a/mp/src/game/shared/basecombatweapon_shared.cpp +++ b/mp/src/game/shared/basecombatweapon_shared.cpp @@ -38,6 +38,8 @@ #endif +#include "vprof.h" + // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -164,8 +166,20 @@ void CBaseCombatWeapon::GiveDefaultAmmo( void ) //----------------------------------------------------------------------------- void CBaseCombatWeapon::Spawn( void ) { + bool bPrecacheAllowed = CBaseEntity::IsPrecacheAllowed(); + if (!bPrecacheAllowed) + { + tmEnter( TELEMETRY_LEVEL1, TMZF_NONE, "LateWeaponPrecache" ); + } + Precache(); + if (!bPrecacheAllowed) + { + tmLeave( TELEMETRY_LEVEL1 ); + } + + BaseClass::Spawn(); SetSolid( SOLID_BBOX ); @@ -1643,6 +1657,11 @@ void CBaseCombatWeapon::ItemPreFrame( void ) #endif } +bool CBaseCombatWeapon::CanPerformSecondaryAttack() const +{ + return m_flNextSecondaryAttack <= gpGlobals->curtime; +} + //==================================================================================== // WEAPON BEHAVIOUR //==================================================================================== @@ -1667,7 +1686,7 @@ void CBaseCombatWeapon::ItemPostFrame( void ) bool bFired = false; // Secondary attack has priority - if ((pOwner->m_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime)) + if ((pOwner->m_nButtons & IN_ATTACK2) && CanPerformSecondaryAttack() ) { if (UsesSecondaryAmmo() && pOwner->GetAmmoCount(m_iSecondaryAmmoType)<=0 ) { diff --git a/mp/src/game/shared/basecombatweapon_shared.h b/mp/src/game/shared/basecombatweapon_shared.h index 701403a0..2c712923 100644 --- a/mp/src/game/shared/basecombatweapon_shared.h +++ b/mp/src/game/shared/basecombatweapon_shared.h @@ -247,6 +247,7 @@ public: virtual void HandleFireOnEmpty(); // Called when they have the attack button down // but they are out of ammo. The default implementation // either reloads, switches weapons, or plays an empty sound. + virtual bool CanPerformSecondaryAttack() const; virtual bool ShouldBlockPrimaryFire() { return false; } diff --git a/mp/src/game/shared/baseentity_shared.cpp b/mp/src/game/shared/baseentity_shared.cpp index 43348cb1..a843543f 100644 --- a/mp/src/game/shared/baseentity_shared.cpp +++ b/mp/src/game/shared/baseentity_shared.cpp @@ -2250,6 +2250,15 @@ int CBaseEntity::GetTracerAttachment( void ) return iAttachment; } +float CBaseEntity::HealthFraction() const +{ + if ( GetMaxHealth() == 0 ) + return 1.0f; + + float flFraction = ( float )GetHealth() / ( float )GetMaxHealth(); + flFraction = clamp( flFraction, 0.0f, 1.0f ); + return flFraction; +} int CBaseEntity::BloodColor() { diff --git a/mp/src/game/shared/baseprojectile.cpp b/mp/src/game/shared/baseprojectile.cpp index c695db93..54a0e9bc 100644 --- a/mp/src/game/shared/baseprojectile.cpp +++ b/mp/src/game/shared/baseprojectile.cpp @@ -12,6 +12,11 @@ IMPLEMENT_NETWORKCLASS_ALIASED( BaseProjectile, DT_BaseProjectile ) BEGIN_NETWORK_TABLE( CBaseProjectile, DT_BaseProjectile ) +#if !defined( CLIENT_DLL ) + SendPropEHandle( SENDINFO( m_hOriginalLauncher ) ), +#else + RecvPropEHandle( RECVINFO( m_hOriginalLauncher ) ), +#endif // CLIENT_DLL END_NETWORK_TABLE() @@ -22,5 +27,63 @@ CBaseProjectile::CBaseProjectile() { #ifdef GAME_DLL m_iDestroyableHitCount = 0; + + m_bCanCollideWithTeammates = false; #endif + m_hOriginalLauncher = NULL; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseProjectile::SetLauncher( CBaseEntity *pLauncher ) +{ + if ( m_hOriginalLauncher == NULL ) + { + m_hOriginalLauncher = pLauncher; + } + +#ifdef GAME_DLL + ResetCollideWithTeammates(); +#endif // GAME_DLL +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseProjectile::Spawn() +{ + BaseClass::Spawn(); + +#ifdef GAME_DLL + ResetCollideWithTeammates(); +#endif // GAME_DLL } + + +#ifdef GAME_DLL + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseProjectile::CollideWithTeammatesThink() +{ + m_bCanCollideWithTeammates = true; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseProjectile::ResetCollideWithTeammates() +{ + // Don't collide with players on the owner's team for the first bit of our life + m_bCanCollideWithTeammates = false; + + SetContextThink( &CBaseProjectile::CollideWithTeammatesThink, gpGlobals->curtime + GetCollideWithTeammatesDelay(), "CollideWithTeammates" ); +} + +#endif // GAME_DLL + diff --git a/mp/src/game/shared/baseprojectile.h b/mp/src/game/shared/baseprojectile.h index 2ff00fc5..d87b9fdd 100644 --- a/mp/src/game/shared/baseprojectile.h +++ b/mp/src/game/shared/baseprojectile.h @@ -36,18 +36,37 @@ public: CBaseProjectile(); + virtual void Spawn(); + #ifdef GAME_DLL virtual int GetDestroyableHitCount( void ) const { return m_iDestroyableHitCount; } void IncrementDestroyableHitCount( void ) { ++m_iDestroyableHitCount; } + + bool CanCollideWithTeammates() const { return m_bCanCollideWithTeammates; } + virtual float GetCollideWithTeammatesDelay() const { return 0.25f; } #endif // GAME_DLL virtual bool IsDestroyable( void ) { return false; } virtual void Destroy( bool bBlinkOut = true, bool bBreakRocket = false ) {} + virtual void SetLauncher( CBaseEntity *pLauncher ); + CBaseEntity *GetOriginalLauncher() const { return m_hOriginalLauncher; } protected: #ifdef GAME_DLL + void CollideWithTeammatesThink(); + int m_iDestroyableHitCount; #endif // GAME_DLL + +private: + +#ifdef GAME_DLL + void ResetCollideWithTeammates(); + + bool m_bCanCollideWithTeammates; +#endif // GAME_DLL + + CNetworkHandle( CBaseEntity, m_hOriginalLauncher ); }; #endif // BASEPROJECTILE_H diff --git a/mp/src/game/shared/choreoevent.cpp b/mp/src/game/shared/choreoevent.cpp index 50755f04..9afb938b 100644 --- a/mp/src/game/shared/choreoevent.cpp +++ b/mp/src/game/shared/choreoevent.cpp @@ -2076,8 +2076,8 @@ public: { if ( ARRAYSIZE( g_NameMap ) != CChoreoEvent::NUM_TYPES ) { - Error( "g_NameMap contains %i entries, CChoreoEvent::NUM_TYPES == %i!", - ARRAYSIZE( g_NameMap ), CChoreoEvent::NUM_TYPES ); + Error( "g_NameMap contains %llu entries, CChoreoEvent::NUM_TYPES == %i!", + (uint64)(ARRAYSIZE( g_NameMap )), CChoreoEvent::NUM_TYPES ); } for ( int i = 0; i < CChoreoEvent::NUM_TYPES; ++i ) { @@ -2158,8 +2158,8 @@ public: { if ( ARRAYSIZE( g_CCNameMap ) != CChoreoEvent::NUM_CC_TYPES ) { - Error( "g_CCNameMap contains %i entries, CChoreoEvent::NUM_CC_TYPES == %i!", - ARRAYSIZE( g_CCNameMap ), CChoreoEvent::NUM_CC_TYPES ); + Error( "g_CCNameMap contains %llu entries, CChoreoEvent::NUM_CC_TYPES == %i!", + (uint64)(ARRAYSIZE( g_CCNameMap )), CChoreoEvent::NUM_CC_TYPES ); } for ( int i = 0; i < CChoreoEvent::NUM_CC_TYPES; ++i ) { diff --git a/mp/src/game/shared/choreoscene.cpp b/mp/src/game/shared/choreoscene.cpp index 734e89be..b77c94b8 100644 --- a/mp/src/game/shared/choreoscene.cpp +++ b/mp/src/game/shared/choreoscene.cpp @@ -156,6 +156,7 @@ CChoreoScene& CChoreoScene::operator=( const CChoreoScene& src ) m_pTokenizer = src.m_pTokenizer; m_flCurrentTime = src.m_flCurrentTime; + m_flStartLoopTime = src.m_flStartLoopTime; m_flStartTime = src.m_flStartTime; m_flEndTime = src.m_flEndTime; m_flSoundSystemLatency = src.m_flSoundSystemLatency; @@ -234,6 +235,7 @@ void CChoreoScene::Init( IChoreoEventCallback *callback ) m_szMapname[ 0 ] = 0; m_flCurrentTime = 0.0f; + m_flStartLoopTime = -1.f; m_flStartTime = 0.0f; m_flEndTime = 0.0f; m_flSoundSystemLatency = 0.0f; @@ -2312,6 +2314,8 @@ void CChoreoScene::ResetSimulation( bool forward /*= true*/, float starttime /*= m_flCurrentTime = forward ? m_flEarliestTime : m_flLatestTime; + m_flStartLoopTime = -1.f; + // choreoprintf( 0, "Start time %f\n", m_flCurrentTime ); m_flLastActiveTime = 0.0f; @@ -2473,6 +2477,15 @@ int CChoreoScene::EventThink( CChoreoEvent *e, float frame_start_time, float fra } } */ + + if ( !suppressed ) + { + // if this SPEAK event starts before the beginning of the current loop, don't play the SPEAK event again in the loop + if ( m_flStartLoopTime >= 0.f && starttime < m_flStartLoopTime ) + { + return iret; + } + } } break; case CChoreoEvent::SUBSCENE: @@ -2836,6 +2849,8 @@ void CChoreoScene::SetTime( float t ) void CChoreoScene::LoopToTime( float t ) { m_flCurrentTime = t; + + m_flStartLoopTime = t; } //----------------------------------------------------------------------------- diff --git a/mp/src/game/shared/choreoscene.h b/mp/src/game/shared/choreoscene.h index e4d22871..d8203c14 100644 --- a/mp/src/game/shared/choreoscene.h +++ b/mp/src/game/shared/choreoscene.h @@ -326,6 +326,8 @@ private: // Current simulation time float m_flCurrentTime; + float m_flStartLoopTime; + float m_flStartTime; float m_flEndTime; diff --git a/mp/src/game/shared/effect_color_tables.h b/mp/src/game/shared/effect_color_tables.h index 322d0e08..348e894f 100644 --- a/mp/src/game/shared/effect_color_tables.h +++ b/mp/src/game/shared/effect_color_tables.h @@ -33,10 +33,10 @@ enum // Commander mode table static colorentry_t commandercolors[] = { - { COMMAND_POINT_RED, 1.0, 0.0, 0.0 }, - { COMMAND_POINT_BLUE, 0.0, 0.0, 1.0 }, - { COMMAND_POINT_GREEN, 0.0, 1.0, 0.0 }, - { COMMAND_POINT_YELLOW, 1.0, 1.0, 0.0 }, + { COMMAND_POINT_RED, 1, 0, 0 }, + { COMMAND_POINT_BLUE, 0, 0, 1 }, + { COMMAND_POINT_GREEN, 0, 1, 0 }, + { COMMAND_POINT_YELLOW, 1, 1, 0 }, }; static colorentry_t bloodcolors[] = diff --git a/mp/src/game/shared/eventlist.cpp b/mp/src/game/shared/eventlist.cpp index e5b01fed..84014b49 100644 --- a/mp/src/game/shared/eventlist.cpp +++ b/mp/src/game/shared/eventlist.cpp @@ -248,4 +248,5 @@ void EventList_RegisterSharedEvents( void ) REGISTER_SHARED_ANIMEVENT( AE_WPN_UNHIDE, AE_TYPE_CLIENT | AE_TYPE_SERVER ); REGISTER_SHARED_ANIMEVENT( AE_WPN_PLAYWPNSOUND, AE_TYPE_CLIENT | AE_TYPE_SERVER ); + REGISTER_SHARED_ANIMEVENT( AE_RD_ROBOT_POP_PANELS_OFF, AE_TYPE_CLIENT | AE_TYPE_SERVER ); }
\ No newline at end of file diff --git a/mp/src/game/shared/eventlist.h b/mp/src/game/shared/eventlist.h index 1ce83a4c..c4944616 100644 --- a/mp/src/game/shared/eventlist.h +++ b/mp/src/game/shared/eventlist.h @@ -85,6 +85,8 @@ typedef enum AE_WPN_PLAYWPNSOUND, // Play a weapon sound from the weapon script file + AE_RD_ROBOT_POP_PANELS_OFF, + LAST_SHARED_ANIMEVENT, } Animevent; diff --git a/mp/src/game/shared/gamemovement.cpp b/mp/src/game/shared/gamemovement.cpp index 8de6fc32..8b5921bd 100644 --- a/mp/src/game/shared/gamemovement.cpp +++ b/mp/src/game/shared/gamemovement.cpp @@ -518,7 +518,7 @@ void CGameMovement::DiffPrint( char const *fmt, ... ) #endif // !PREDICTION_ERROR_CHECK_LEVEL #ifndef _XBOX -void COM_Log( char *pszFile, const char *fmt, ...) +void COM_Log( const char *pszFile, const char *fmt, ...) { va_list argptr; char string[1024]; diff --git a/mp/src/game/shared/gamerules.h b/mp/src/game/shared/gamerules.h index 4b2f5124..347f7941 100644 --- a/mp/src/game/shared/gamerules.h +++ b/mp/src/game/shared/gamerules.h @@ -205,6 +205,8 @@ public: #else + virtual void Status( void (*print) (const char *fmt, ...) ) {} + virtual void GetTaggedConVarList( KeyValues *pCvarTagList ) {} // NVNT see if the client of the player entered is using a haptic device. diff --git a/mp/src/game/shared/mapentities_shared.cpp b/mp/src/game/shared/mapentities_shared.cpp index 420c3e1d..2cd6fe01 100644 --- a/mp/src/game/shared/mapentities_shared.cpp +++ b/mp/src/game/shared/mapentities_shared.cpp @@ -125,7 +125,7 @@ const char *MapEntity_ParseToken( const char *data, char *newToken ) for ( const char *c = s_BraceChars; *c; c++ ) { - s_BraceCharacters[*c] = true; + s_BraceCharacters[(unsigned)*c] = true; } } diff --git a/mp/src/game/shared/mp_shareddefs.cpp b/mp/src/game/shared/mp_shareddefs.cpp index b555a88f..66a5e0e3 100644 --- a/mp/src/game/shared/mp_shareddefs.cpp +++ b/mp/src/game/shared/mp_shareddefs.cpp @@ -185,6 +185,10 @@ const char *g_pszMPConcepts[] = "TLK_MVM_LOOT_RARE", // MP_CONCEPT_MVM_LOOT_RARE "TLK_MVM_LOOT_ULTRARARE", // MP_CONCEPT_MVM_LOOT_ULTRARARE "TLK_MEDIC_HEAL_SHIELD", // MP_CONCEPT_MEDIC_HEAL_SHIELD + + "TLK_TAUNT_EUREKA_EFFECT", // MP_CONCEPT_TAUNT_EUREKA_EFFECT_TELEPORT + + "TLK_COMBO_KILLED", // MP_CONCEPT_COMBO_KILLED }; COMPILE_TIME_ASSERT( ARRAYSIZE( g_pszMPConcepts ) == MP_TF_CONCEPT_COUNT ); diff --git a/mp/src/game/shared/mp_shareddefs.h b/mp/src/game/shared/mp_shareddefs.h index 8ad6011b..d0fa99c8 100644 --- a/mp/src/game/shared/mp_shareddefs.h +++ b/mp/src/game/shared/mp_shareddefs.h @@ -195,6 +195,10 @@ enum MP_CONCEPT_MVM_LOOT_ULTRARARE, // "TLK_MVM_LOOT_ULTRARARE" MP_CONCEPT_MEDIC_HEAL_SHIELD, // "TLK_MEDIC_HEAL_SHIELD" + MP_CONCEPT_TAUNT_EUREKA_EFFECT_TELEPORT,// "TLK_TAUNT_EUREKA_EFFECT" + + MP_CONCEPT_COMBO_KILLED, // "TLK_COMBO_KILLED" + MP_TF_CONCEPT_COUNT // Other MP_CONCEPT_* start he using MP_TF_CONCEPT_COUNT + 1 as start. diff --git a/mp/src/game/shared/multiplay_gamerules.cpp b/mp/src/game/shared/multiplay_gamerules.cpp index abecba9e..16cfe297 100644 --- a/mp/src/game/shared/multiplay_gamerules.cpp +++ b/mp/src/game/shared/multiplay_gamerules.cpp @@ -1149,14 +1149,17 @@ ConVarRef suitcharger( "sk_suitcharger" ); } } - void StripChar(char *szBuffer, const char cWhiteSpace ) + // Strip ' ' and '\n' characters from string. + static void StripWhitespaceChars( char *szBuffer ) { + char *szOut = szBuffer; - while ( char *pSpace = strchr( szBuffer, cWhiteSpace ) ) + for ( char *szIn = szOut; *szIn; szIn++ ) { - char *pNextChar = pSpace + sizeof(char); - V_strcpy( pSpace, pNextChar ); + if ( *szIn != ' ' && *szIn != '\r' ) + *szOut++ = *szIn; } + *szOut = '\0'; } void CMultiplayRules::GetNextLevelName( char *pszNextMap, int bufsize, bool bRandom /* = false */ ) @@ -1283,9 +1286,8 @@ ConVarRef suitcharger( "sk_suitcharger" ); { bool bIgnore = false; - // Strip out the spaces in the name - StripChar( mapList[i] , '\r'); - StripChar( mapList[i] , ' '); + // Strip out ' ' and '\r' chars. + StripWhitespaceChars( mapList[i] ); if ( !Q_strncmp( mapList[i], "//", 2 ) || mapList[i][0] == '\0' ) { diff --git a/mp/src/game/shared/particle_property.cpp b/mp/src/game/shared/particle_property.cpp index c1c44a1a..5b5c2603 100644 --- a/mp/src/game/shared/particle_property.cpp +++ b/mp/src/game/shared/particle_property.cpp @@ -365,7 +365,7 @@ void CParticleProperty::StopParticlesInvolving( CBaseEntity *pEntity ) // Purpose: Stop all effects that were created using the given definition // name. //----------------------------------------------------------------------------- -void CParticleProperty::StopParticlesNamed( const char *pszEffectName, bool bForceRemoveInstantly /* =false */ ) +void CParticleProperty::StopParticlesNamed( const char *pszEffectName, bool bForceRemoveInstantly /* =false */, bool bInverse /*= false*/ ) { CParticleSystemDefinition *pDef = g_pParticleSystemMgr->FindParticleSystem( pszEffectName ); AssertMsg1(pDef, "Could not find particle definition %s", pszEffectName ); @@ -384,13 +384,15 @@ void CParticleProperty::StopParticlesNamed( const char *pszEffectName, bool bFor { // for each effect... CNewParticleEffect *pParticleEffect = m_ParticleEffects[i].pParticleEffect.GetObject(); - if (pParticleEffect->m_pDef() == pDef) + bool bMatches = pParticleEffect->m_pDef() == pDef; + if ( bMatches == !bInverse ) { pParticleEffect->StopEmission( false, bRemoveInstantly ); } } } + void CParticleProperty::StopParticlesWithNameAndAttachment( const char *pszEffectName, int iAttachmentPoint, bool bForceRemoveInstantly /* =false */ ) { CParticleSystemDefinition *pDef = g_pParticleSystemMgr->FindParticleSystem( pszEffectName ); @@ -562,7 +564,7 @@ void CParticleProperty::UpdateControlPoint( ParticleEffectList_t *pEffect, int i #ifdef TF_CLIENT_DLL CBaseEntity *pWearable = (CBaseEntity*) pPoint->hEntity.Get(); - if ( pWearable && dynamic_cast<IHasAttributes*>( pWearable ) && !pWearable->IsPlayer() ) + if ( pWearable && GetAttribInterface( pWearable ) && !pWearable->IsPlayer() ) { C_BaseAnimating *pAnimating = pPoint->hEntity->GetBaseAnimating(); if ( pAnimating ) diff --git a/mp/src/game/shared/particle_property.h b/mp/src/game/shared/particle_property.h index 30d62e9e..7978d8e7 100644 --- a/mp/src/game/shared/particle_property.h +++ b/mp/src/game/shared/particle_property.h @@ -90,7 +90,7 @@ public: // kill all particle systems involving a given entity for their control points void StopParticlesInvolving( CBaseEntity *pEntity ); - void StopParticlesNamed( const char *pszEffectName, bool bForceRemoveInstantly = false ); ///< kills all particles using the given definition name + void StopParticlesNamed( const char *pszEffectName, bool bForceRemoveInstantly = false, bool bInverse = false ); ///< kills all particles using the given definition name void StopParticlesWithNameAndAttachment( const char *pszEffectName, int iAttachmentPoint, bool bForceRemoveInstantly = false ); ///< kills all particles using the given definition name // Particle System hooks diff --git a/mp/src/game/shared/particlesystemquery.cpp b/mp/src/game/shared/particlesystemquery.cpp index b97a334b..abd33c77 100644 --- a/mp/src/game/shared/particlesystemquery.cpp +++ b/mp/src/game/shared/particlesystemquery.cpp @@ -231,7 +231,7 @@ void CParticleSystemQuery::GetRandomPointsOnControllingObjectHitBox( { bSucesss = true; - Vector vecWorldPosition; + Vector vecWorldPosition(0, 0, 0); float u = 0, v = 0, w = 0; int nHitbox = 0; int nNumIters = nNumTrysToGetAPointInsideTheModel; @@ -308,7 +308,7 @@ void CParticleSystemQuery::GetRandomPointsOnControllingObjectHitBox( - Vector vecWorldPosition; + Vector vecWorldPosition(0, 0, 0); float u = 0, v = 0, w = 0; int nHitbox = 0; int nNumIters = nNumTrysToGetAPointInsideTheModel; diff --git a/mp/src/game/shared/predictioncopy.cpp b/mp/src/game/shared/predictioncopy.cpp index 72c3ae52..9721326e 100644 --- a/mp/src/game/shared/predictioncopy.cpp +++ b/mp/src/game/shared/predictioncopy.cpp @@ -514,7 +514,7 @@ void CPredictionCopy::DescribeQuaternion( difftype_t dt, Quaternion* outValue, c for ( int j = 0; j < 4; j++ ) { - delta[i] = outValue[i][j] - inValue[i][j]; + delta[j] = outValue[i][j] - inValue[i][j]; } ReportFieldsDiffer( "quaternion[] differs (1st diff) (net %f %f %f %f - pred %f %f %f %f) delta(%f %f %f %f)\n", @@ -933,7 +933,7 @@ CPredictionCopy::difftype_t CPredictionCopy::CompareQuaternion( Quaternion* outV for ( int j = 0; j < 4; j++ ) { - delta[i] = outValue[i][j] - inValue[i][j]; + delta[j] = outValue[i][j] - inValue[i][j]; } if ( tolerance > 0.0f ) diff --git a/mp/src/game/shared/props_shared.cpp b/mp/src/game/shared/props_shared.cpp index 6d0f9209..7bb0c03b 100644 --- a/mp/src/game/shared/props_shared.cpp +++ b/mp/src/game/shared/props_shared.cpp @@ -600,6 +600,10 @@ public: pModel->mpBreakMode = MULTIPLAYER_BREAK_CLIENTSIDE; } } + else if ( !strcmpi( pKey, "velocity" ) ) + { + UTIL_StringToVector( pModel->velocity.Base(), pValue ); + } } virtual void SetDefaults( void *pData ) { @@ -617,6 +621,7 @@ public: pModel->placementName[0] = 0; pModel->placementIsBone = false; pModel->mpBreakMode = MULTIPLAYER_BREAK_DEFAULT; + pModel->velocity = vec3_origin; m_wroteCollisionGroup = false; } @@ -626,7 +631,7 @@ private: bool m_wroteCollisionGroup; }; -void BreakModelList( CUtlVector<breakmodel_t> &list, int modelindex, float defBurstScale, int defCollisionGroup ) +void BuildPropList( const char *pszBlockName, CUtlVector<breakmodel_t> &list, int modelindex, float defBurstScale, int defCollisionGroup ) { vcollide_t *pCollide = modelinfo->GetVCollide( modelindex ); if ( !pCollide ) @@ -638,7 +643,7 @@ void BreakModelList( CUtlVector<breakmodel_t> &list, int modelindex, float defBu CBreakParser breakParser( defBurstScale, defCollisionGroup ); const char *pBlock = pParse->GetCurrentBlockName(); - if ( !strcmpi( pBlock, "break" ) ) + if ( !strcmpi( pBlock, pszBlockName ) ) { int index = list.AddToTail(); breakmodel_t &breakModel = list[index]; @@ -652,6 +657,11 @@ void BreakModelList( CUtlVector<breakmodel_t> &list, int modelindex, float defBu physcollision->VPhysicsKeyParserDestroy( pParse ); } +void BreakModelList( CUtlVector<breakmodel_t> &list, int modelindex, float defBurstScale, int defCollisionGroup ) +{ + BuildPropList( "break", list, modelindex, defBurstScale, defCollisionGroup ); +} + #if !defined(_STATIC_LINKED) || defined(CLIENT_DLL) int GetAutoMultiplayerPhysicsMode( Vector size, float mass ) { @@ -1226,9 +1236,8 @@ void PropBreakableCreateAll( int modelindex, IPhysicsObject *pPhysics, const Vec // Purpose: // Input : modelindex - //----------------------------------------------------------------------------- -void PrecacheGibsForModel( int iModel ) +void PrecachePropsForModel( int iModel, const char *pszBlockName ) { - VPROF_BUDGET( "PrecacheGibsForModel", VPROF_BUDGETGROUP_PLAYER ); vcollide_t *pCollide = modelinfo->GetVCollide( iModel ); if ( !pCollide ) return; @@ -1241,7 +1250,7 @@ void PrecacheGibsForModel( int iModel ) while ( !pParse->Finished() ) { const char *pBlock = pParse->GetCurrentBlockName(); - if ( !strcmpi( pBlock, "break" ) ) + if ( !strcmpi( pBlock, pszBlockName ) ) { breakmodel_t breakModel; pParse->ParseCustom( &breakModel, &breakParser ); @@ -1257,6 +1266,12 @@ void PrecacheGibsForModel( int iModel ) physcollision->VPhysicsKeyParserDestroy( pParse ); } +void PrecacheGibsForModel( int iModel ) +{ + VPROF_BUDGET( "PrecacheGibsForModel", VPROF_BUDGETGROUP_PLAYER ); + PrecachePropsForModel( iModel, "break" ); +} + //----------------------------------------------------------------------------- // Purpose: // Input : &list - @@ -1448,12 +1463,21 @@ CBaseEntity *CreateGibsFromList( CUtlVector<breakmodel_t> &list, int modelindex, } Vector objectVelocity = params.velocity; - float flScale = VectorNormalize( objectVelocity ); - objectVelocity.x += RandomFloat( -1.f, 1.0f ); - objectVelocity.y += RandomFloat( -1.0f, 1.0f ); - objectVelocity.z += RandomFloat( 0.0f, 1.0f ); - VectorNormalize( objectVelocity ); - objectVelocity *= flScale; + Vector gibVelocity = vec3_origin; + if ( !list[i].velocity.IsZero() ) + { + VectorRotate( list[i].velocity, matrix, gibVelocity ); + objectVelocity = gibVelocity; + } + else + { + float flScale = VectorNormalize( objectVelocity ); + objectVelocity.x += RandomFloat( -1.f, 1.0f ); + objectVelocity.y += RandomFloat( -1.0f, 1.0f ); + objectVelocity.z += RandomFloat( 0.0f, 1.0f ); + VectorNormalize( objectVelocity ); + objectVelocity *= flScale; + } if (pPhysics) { diff --git a/mp/src/game/shared/props_shared.h b/mp/src/game/shared/props_shared.h index c63cb212..07878d82 100644 --- a/mp/src/game/shared/props_shared.h +++ b/mp/src/game/shared/props_shared.h @@ -217,6 +217,7 @@ struct breakmodel_t bool placementIsBone; bool isMotionDisabled; mp_break_t mpBreakMode; + Vector velocity; }; struct breakablepropparams_t @@ -242,11 +243,13 @@ struct breakablepropparams_t const char *GetMassEquivalent(float flMass); int GetAutoMultiplayerPhysicsMode( Vector size, float mass ); +void BuildPropList( const char *pszBlockName, CUtlVector<breakmodel_t> &list, int modelindex, float defBurstScale, int defCollisionGroup ); void BreakModelList( CUtlVector<breakmodel_t> &list, int modelindex, float defBurstScale, int defCollisionGroup ); void PropBreakableCreateAll( int modelindex, IPhysicsObject *pPhysics, const breakablepropparams_t ¶ms, CBaseEntity *pEntity, int iPrecomputedBreakableCount, bool bIgnoreGibLImit, bool defaultLocation = true ); void PropBreakableCreateAll( int modelindex, IPhysicsObject *pPhysics, const Vector &origin, const QAngle &angles, const Vector &velocity, const AngularImpulse &angularVelocity, float impactEnergyScale, float burstScale, int collisionGroup, CBaseEntity *pEntity = NULL, bool defaultLocation = true ); // Player gibs. +void PrecachePropsForModel( int iModel, const char *pszBlockName ); void PrecacheGibsForModel( int iModel ); void BuildGibList( CUtlVector<breakmodel_t> &list, int modelindex, float defBurstScale, int defCollisionGroup ); CBaseEntity *CreateGibsFromList( CUtlVector<breakmodel_t> &list, int modelindex, IPhysicsObject *pPhysics, const breakablepropparams_t ¶ms, CBaseEntity *pEntity, int iPrecomputedBreakableCount, bool bIgnoreGibLImit, bool defaultLocation = true, CUtlVector<EHANDLE> *pGibList = NULL, bool bBurning = false ); diff --git a/mp/src/game/shared/sceneimage.cpp b/mp/src/game/shared/sceneimage.cpp index 55426008..053d0506 100644 --- a/mp/src/game/shared/sceneimage.cpp +++ b/mp/src/game/shared/sceneimage.cpp @@ -368,7 +368,7 @@ bool CSceneImage::CreateSceneImageFile( CUtlBuffer &targetBuffer, char const *pc if ( !bQuiet ) { - Msg( "Scenes: String Table: %d bytes\n", stringOffsets.Count() * sizeof( int ) ); + Msg( "Scenes: String Table: %llu bytes\n", (uint64)(stringOffsets.Count() * sizeof( int )) ); Msg( "Scenes: String Pool: %d bytes\n", stringPool.TellMaxPut() ); } diff --git a/mp/src/game/shared/shareddefs.h b/mp/src/game/shared/shareddefs.h index 842d2f06..11156a36 100644 --- a/mp/src/game/shared/shareddefs.h +++ b/mp/src/game/shared/shareddefs.h @@ -140,7 +140,7 @@ typedef enum VOTE_FAILED_ISSUE_DISABLED, VOTE_FAILED_MAP_NOT_FOUND, VOTE_FAILED_MAP_NAME_REQUIRED, - VOTE_FAILED_FAILED_RECENTLY, + VOTE_FAILED_ON_COOLDOWN, VOTE_FAILED_TEAM_CANT_CALL, VOTE_FAILED_WAITINGFORPLAYERS, VOTE_FAILED_PLAYERNOTFOUND, diff --git a/mp/src/game/shared/takedamageinfo.h b/mp/src/game/shared/takedamageinfo.h index 702e9322..a18493e0 100644 --- a/mp/src/game/shared/takedamageinfo.h +++ b/mp/src/game/shared/takedamageinfo.h @@ -55,7 +55,8 @@ public: void AddDamage( float flAddAmount ); void SubtractDamage( float flSubtractAmount ); float GetDamageBonus() const; - void SetDamageBonus( float flBonus ); + CBaseEntity *GetDamageBonusProvider() const; + void SetDamageBonus( float flBonus, CBaseEntity *pProvider = NULL ); float GetBaseDamage() const; bool BaseDamageIsValid() const; @@ -125,6 +126,7 @@ protected: int m_iDamagedOtherPlayers; int m_iPlayerPenetrationCount; float m_flDamageBonus; // Anything that increases damage (crit) - store the delta + EHANDLE m_hDamageBonusProvider; // Who gave us the ability to do extra damage? bool m_bForceFriendlyFire; // Ideally this would be a dmg type, but we can't add more DECLARE_SIMPLE_DATADESC(); @@ -247,9 +249,15 @@ inline float CTakeDamageInfo::GetDamageBonus() const return m_flDamageBonus; } -inline void CTakeDamageInfo::SetDamageBonus( float flBonus ) +inline CBaseEntity *CTakeDamageInfo::GetDamageBonusProvider() const +{ + return m_hDamageBonusProvider; +} + +inline void CTakeDamageInfo::SetDamageBonus( float flBonus, CBaseEntity *pProvider /*= NULL*/ ) { m_flDamageBonus = flBonus; + m_hDamageBonusProvider = pProvider; } inline float CTakeDamageInfo::GetBaseDamage() const diff --git a/mp/src/game/shared/teamplay_round_timer.cpp b/mp/src/game/shared/teamplay_round_timer.cpp index f993749a..6c6ccb77 100644 --- a/mp/src/game/shared/teamplay_round_timer.cpp +++ b/mp/src/game/shared/teamplay_round_timer.cpp @@ -245,6 +245,7 @@ CTeamRoundTimer::CTeamRoundTimer( void ) m_bResetTimeOnRoundStart = false; m_nTimeToUseAfterSetupFinished = 0; m_flNextOvertimeNag = 0; + m_flLastTime = 0.f; #endif } @@ -781,6 +782,9 @@ void CTeamRoundTimer::SetTimerThink( int nType ) //----------------------------------------------------------------------------- void CTeamRoundTimer::RoundTimerSetupThink( void ) { + float flLastTime = m_flLastTime; + m_flLastTime = GetTimeRemaining(); + if ( TeamplayRoundBasedRules()->IsInPreMatch() == true && IsDisabled() == false ) { inputdata_t data; @@ -797,6 +801,22 @@ void CTeamRoundTimer::RoundTimerSetupThink( void ) float flTime = GetTimeRemaining(); TeamplayRoundBasedRules()->SetOvertime( false ); + if ( m_flLastTime > 0.f ) + { + int nLastSecond = floor( flLastTime ); + int nThisSecond = floor( flTime ); + + if ( nLastSecond != nThisSecond ) + { + IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_pre_round_time_left" ); + if ( event ) + { + event->SetInt( "time", nThisSecond ); + gameeventmanager->FireEvent( event ); + } + } + } + if ( flTime <= 0.0f && m_bFireFinished ) { IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_setup_finished" ); @@ -1291,14 +1311,14 @@ void CTeamRoundTimer::InputAddTeamTime( inputdata_t &input ) // get the team p = nexttoken( token, p, ' ' ); - if ( token ) + if ( token[0] ) { nTeam = Q_atoi( token ); } // get the time p = nexttoken( token, p, ' ' ); - if ( token ) + if ( token[0] ) { nSeconds = Q_atoi( token ); } diff --git a/mp/src/game/shared/teamplay_round_timer.h b/mp/src/game/shared/teamplay_round_timer.h index 103b2546..fd2e7613 100644 --- a/mp/src/game/shared/teamplay_round_timer.h +++ b/mp/src/game/shared/teamplay_round_timer.h @@ -158,6 +158,7 @@ private: COutputEvent m_OnSetupFinished; float m_flNextOvertimeNag; + float m_flLastTime; DECLARE_DATADESC(); diff --git a/mp/src/game/shared/teamplayroundbased_gamerules.cpp b/mp/src/game/shared/teamplayroundbased_gamerules.cpp index 26a75b18..3930798d 100644 --- a/mp/src/game/shared/teamplayroundbased_gamerules.cpp +++ b/mp/src/game/shared/teamplayroundbased_gamerules.cpp @@ -90,6 +90,7 @@ BEGIN_NETWORK_TABLE_NOBASE( CTeamplayRoundBasedRules, DT_TeamplayRoundBasedRules RecvPropBool( RECVINFO( m_bStopWatch ) ), RecvPropBool( RECVINFO( m_bMultipleTrains ) ), RecvPropArray3( RECVINFO_ARRAY(m_bPlayerReady), RecvPropBool( RECVINFO(m_bPlayerReady[0]) ) ), + RecvPropBool( RECVINFO( m_bCheatsEnabledDuringLevel ) ), #else SendPropInt( SENDINFO( m_iRoundState ), 5 ), @@ -107,6 +108,7 @@ BEGIN_NETWORK_TABLE_NOBASE( CTeamplayRoundBasedRules, DT_TeamplayRoundBasedRules SendPropBool( SENDINFO( m_bStopWatch ) ), SendPropBool( SENDINFO( m_bMultipleTrains ) ), SendPropArray3( SENDINFO_ARRAY3(m_bPlayerReady), SendPropBool( SENDINFO_ARRAY(m_bPlayerReady) ) ), + SendPropBool( SENDINFO( m_bCheatsEnabledDuringLevel ) ), #endif END_NETWORK_TABLE() @@ -184,7 +186,7 @@ ConVar tf_arena_round_time( "tf_arena_round_time", "0", FCVAR_NOTIFY | FCVAR_REP ConVar tf_arena_max_streak( "tf_arena_max_streak", "3", FCVAR_NOTIFY | FCVAR_REPLICATED, "Teams will be scrambled if one team reaches this streak" ); ConVar tf_arena_use_queue( "tf_arena_use_queue", "1", FCVAR_REPLICATED | FCVAR_NOTIFY, "Enables the spectator queue system for Arena." ); -ConVar mp_teams_unbalance_limit( "mp_teams_unbalance_limit", "1", FCVAR_REPLICATED | FCVAR_NOTIFY, +ConVar mp_teams_unbalance_limit( "mp_teams_unbalance_limit", "1", FCVAR_REPLICATED, "Teams are unbalanced when one team has this many more players than the other team. (0 disables check)", true, 0, // min value true, 30 // max value @@ -421,6 +423,7 @@ CTeamplayRoundBasedRules::CTeamplayRoundBasedRules( void ) m_nAutoBalanceQueuePlayerScore = -1; SetDefLessFunc( m_GameTeams ); + m_bCheatsEnabledDuringLevel = false; #endif } @@ -554,6 +557,18 @@ float CTeamplayRoundBasedRules::GetMinTimeWhenPlayerMaySpawn( CBasePlayer *pPlay //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- +void CTeamplayRoundBasedRules::LevelInitPostEntity( void ) +{ + BaseClass::LevelInitPostEntity(); + +#ifdef GAME_DLL + m_bCheatsEnabledDuringLevel = sv_cheats && sv_cheats->GetBool(); +#endif // GAME_DLL +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- float CTeamplayRoundBasedRules::GetRespawnTimeScalar( int iTeam ) { // For long respawn times, scale the time as the number of players drops @@ -631,6 +646,12 @@ void CTeamplayRoundBasedRules::Think( void ) m_flNextPeriodicThink = gpGlobals->curtime + 1.0; } + // Watch dog for cheats ever being enabled during a level + if ( !m_bCheatsEnabledDuringLevel && sv_cheats && sv_cheats->GetBool() ) + { + m_bCheatsEnabledDuringLevel = true; + } + // Bypass teamplay think. CGameRules::Think(); } @@ -954,7 +975,11 @@ void CTeamplayRoundBasedRules::CheckRestartRound( void ) int iDelayMax = 60; #if defined(TF_CLIENT_DLL) || defined(TF_DLL) +#ifdef STAGING_ONLY + if ( TFGameRules() && ( TFGameRules()->IsMannVsMachineMode() || TFGameRules()->IsRatedTournamentMode() ) ) +#else if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() ) +#endif // STAGING_ONLY { iDelayMax = 180; } @@ -1415,6 +1440,12 @@ void CTeamplayRoundBasedRules::State_Enter_PREROUND( void ) State_Transition( GR_STATE_BETWEEN_RNDS ); TFObjectiveResource()->SetMannVsMachineBetweenWaves( true ); } +#ifdef STAGING_ONLY + else if ( TFGameRules() && TFGameRules()->IsRatedTournamentMode() ) + { + State_Transition( GR_STATE_BETWEEN_RNDS ); + } +#endif // STAGING_ONLY #endif // #if defined(TF_CLIENT_DLL) || defined(TF_DLL) else { @@ -1501,14 +1532,23 @@ void CTeamplayRoundBasedRules::CheckReadyRestart( void ) m_flRestartRoundTime = -1; #ifdef TF_DLL - if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() && g_pPopulationManager ) + if ( TFGameRules() ) { - if ( TFObjectiveResource()->GetMannVsMachineIsBetweenWaves() ) + if ( TFGameRules()->IsMannVsMachineMode() && g_pPopulationManager ) + { + if ( TFObjectiveResource()->GetMannVsMachineIsBetweenWaves() ) + { + g_pPopulationManager->StartCurrentWave(); + return; + } + } +#ifdef STAGING_ONLY + else if ( TFGameRules()->IsRatedTournamentMode() ) { - g_pPopulationManager->StartCurrentWave(); + TFGameRules()->StartRatedTournamentMatch(); + return; } - - return; +#endif // STAGING_ONLY } #endif // TF_DLL @@ -1703,6 +1743,19 @@ void CTeamplayRoundBasedRules::State_Enter_TEAM_WIN( void ) InternalHandleTeamWin( m_iWinningTeam ); SendWinPanelInfo(); + +#ifdef STAGING_ONLY +#ifdef TF_DLL + if ( TFGameRules() && TFGameRules()->IsRatedTournamentMode() ) + { + // Do this now, so players don't leave before the usual CheckWinLimit() call happens + if ( CheckWinLimit() ) + { + TFGameRules()->SkillRating_CalculateAdjustmentForTeams( m_iWinningTeam ); + } + } +#endif // TF_DLL +#endif // STAGING_ONLY } //----------------------------------------------------------------------------- @@ -1710,8 +1763,16 @@ void CTeamplayRoundBasedRules::State_Enter_TEAM_WIN( void ) //----------------------------------------------------------------------------- void CTeamplayRoundBasedRules::State_Think_TEAM_WIN( void ) { - if( gpGlobals->curtime > m_flStateTransitionTime ) + if ( gpGlobals->curtime > m_flStateTransitionTime ) { +#ifdef TF_DLL + IGameEvent *event = gameeventmanager->CreateEvent( "scorestats_accumulated_update" ); + if ( event ) + { + gameeventmanager->FireEvent( event ); + } +#endif // TF_DLL + bool bDone = !(!CheckTimeLimit() && !CheckWinLimit() && !CheckMaxRounds() && !CheckNextLevelCvar()); // check the win limit, max rounds, time limit and nextlevel cvar before starting the next round @@ -2632,6 +2693,10 @@ void CTeamplayRoundBasedRules::RoundRespawn( void ) } #endif + // Free any edicts that were marked deleted. This should hopefully clear some out + // so the below function can use the now freed ones. + engine->AllowImmediateEdictReuse(); + RespawnPlayers( true ); // reset per-round scores for each player @@ -3020,6 +3085,14 @@ void CTeamplayRoundBasedRules::ResetScores( void ) m_bResetPlayerScores = true; m_bResetRoundsPlayed = true; //m_flStopWatchTime = -1.0f; + +#ifdef TF_DLL + IGameEvent *event = gameeventmanager->CreateEvent( "scorestats_accumulated_reset" ); + if ( event ) + { + gameeventmanager->FireEvent( event ); + } +#endif // TF_DLL } //----------------------------------------------------------------------------- diff --git a/mp/src/game/shared/teamplayroundbased_gamerules.h b/mp/src/game/shared/teamplayroundbased_gamerules.h index cf584092..ddf6e791 100644 --- a/mp/src/game/shared/teamplayroundbased_gamerules.h +++ b/mp/src/game/shared/teamplayroundbased_gamerules.h @@ -88,6 +88,11 @@ enum { WINREASON_TIMELIMIT, WINREASON_WINLIMIT, WINREASON_WINDIFFLIMIT, +#if defined(TF_CLIENT_DLL) || defined(TF_DLL) + WINREASON_RD_REACTOR_CAPTURED, + WINREASON_RD_CORES_COLLECTED, + WINREASON_RD_REACTOR_RETURNED, +#endif }; enum stalemate_reasons_t @@ -183,6 +188,7 @@ public: virtual float GetNextRespawnWave( int iTeam, CBasePlayer *pPlayer ); virtual bool HasPassedMinRespawnTime( CBasePlayer *pPlayer ); + virtual void LevelInitPostEntity( void ); virtual float GetRespawnTimeScalar( int iTeam ); virtual float GetRespawnWaveMaxLength( int iTeam, bool bScaleWithNumPlayers = true ); virtual bool ShouldRespawnQuickly( CBasePlayer *pPlayer ) { return false; } @@ -541,6 +547,7 @@ private: public: bool WouldChangeUnbalanceTeams( int iNewTeam, int iCurrentTeam ); bool AreTeamsUnbalanced( int &iHeaviestTeam, int &iLightestTeam ); + virtual bool HaveCheatsBeenEnabledDuringLevel( void ) { return m_bCheatsEnabledDuringLevel; } protected: CNetworkVar( gamerules_roundstate_t, m_iRoundState ); @@ -557,10 +564,11 @@ protected: CNetworkVar( float, m_flMapResetTime ); // Time that the map was reset CNetworkArray( float, m_flNextRespawnWave, MAX_TEAMS ); // Minor waste, but cleaner code CNetworkArray( bool, m_bTeamReady, MAX_TEAMS ); - CNetworkVar( bool, m_bStopWatch ); - CNetworkVar( bool, m_bMultipleTrains ); // two trains in this map? + CNetworkVar( bool, m_bStopWatch ); + CNetworkVar( bool, m_bMultipleTrains ); // two trains in this map? CNetworkArray( bool, m_bPlayerReady, MAX_PLAYERS ); - + CNetworkVar( bool, m_bCheatsEnabledDuringLevel ); + public: CNetworkArray( float, m_TeamRespawnWaveTimes, MAX_TEAMS ); // Time between each team's respawn wave diff --git a/mp/src/game/shared/voice_gamemgr.cpp b/mp/src/game/shared/voice_gamemgr.cpp index 2feb048d..15523859 100644 --- a/mp/src/game/shared/voice_gamemgr.cpp +++ b/mp/src/game/shared/voice_gamemgr.cpp @@ -48,6 +48,7 @@ CVoiceGameMgr g_VoiceGameMgr; // ------------------------------------------------------------------------ // // Find a player with a case-insensitive name search. +#if 0 static CBasePlayer* FindPlayerByName(const char *pTestName) { for(int i=1; i <= gpGlobals->maxClients; i++) @@ -69,6 +70,7 @@ static CBasePlayer* FindPlayerByName(const char *pTestName) return NULL; } +#endif static void VoiceServerDebug( const char *pFmt, ... ) { |