aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/server
diff options
context:
space:
mode:
authorMichael Sartain <[email protected]>2014-10-02 08:25:55 -0700
committerMichael Sartain <[email protected]>2014-10-02 08:25:55 -0700
commit55ed12f8d1eb6887d348be03aee5573d44177ffb (patch)
tree3686f7ca78c780cd9a3d367b79a9d9250c1be7c0 /mp/src/game/server
parent* Added support for Visual C++ 2013 Express to VPC (diff)
downloadsource-sdk-2013-55ed12f8d1eb6887d348be03aee5573d44177ffb.tar.xz
source-sdk-2013-55ed12f8d1eb6887d348be03aee5573d44177ffb.zip
Updated the SDK with the latest code from the TF and HL2 branches.
Diffstat (limited to 'mp/src/game/server')
-rw-r--r--mp/src/game/server/AI_Criteria.cpp117
-rw-r--r--mp/src/game/server/AI_Criteria.h16
-rw-r--r--mp/src/game/server/MaterialModifyControl.cpp2
-rw-r--r--mp/src/game/server/ServerNetworkProperty.cpp3
-rw-r--r--mp/src/game/server/ai_activity.cpp29
-rw-r--r--mp/src/game/server/ai_basenpc.cpp12
-rw-r--r--mp/src/game/server/ai_basenpc.h1
-rw-r--r--mp/src/game/server/ai_behavior_lead.cpp2
-rw-r--r--mp/src/game/server/ai_blended_movement.cpp2
-rw-r--r--mp/src/game/server/ai_debug.h4
-rw-r--r--mp/src/game/server/ai_movesolver.cpp2
-rw-r--r--mp/src/game/server/ai_navigator.h2
-rw-r--r--mp/src/game/server/ai_playerally.cpp37
-rw-r--r--mp/src/game/server/ai_playerally.h20
-rw-r--r--mp/src/game/server/ai_speech.cpp238
-rw-r--r--mp/src/game/server/ai_speech.h24
-rw-r--r--mp/src/game/server/baseentity.cpp39
-rw-r--r--mp/src/game/server/baseentity.h44
-rw-r--r--mp/src/game/server/baseflex.cpp2
-rw-r--r--mp/src/game/server/basemultiplayerplayer.cpp5
-rw-r--r--mp/src/game/server/basemultiplayerplayer.h2
-rw-r--r--mp/src/game/server/cbase.cpp38
-rw-r--r--mp/src/game/server/client.cpp3
-rw-r--r--mp/src/game/server/entity_tools_server.cpp118
-rw-r--r--mp/src/game/server/entitylist.cpp2
-rw-r--r--mp/src/game/server/entitylist.h1
-rw-r--r--mp/src/game/server/func_breakablesurf.cpp2
-rw-r--r--mp/src/game/server/func_dust.cpp2
-rw-r--r--mp/src/game/server/gameinterface.cpp11
-rw-r--r--mp/src/game/server/gameinterface.h123
-rw-r--r--mp/src/game/server/genericactor.cpp2
-rw-r--r--mp/src/game/server/globalstate.cpp1
-rw-r--r--mp/src/game/server/hl2/npc_citizen17.cpp20
-rw-r--r--mp/src/game/server/hl2/npc_metropolice.cpp2
-rw-r--r--mp/src/game/server/hl2/npc_scanner.cpp2
-rw-r--r--mp/src/game/server/ilagcompensationmanager.h1
-rw-r--r--mp/src/game/server/modelentities.cpp2
-rw-r--r--mp/src/game/server/modelentities.h8
-rw-r--r--mp/src/game/server/nav.h8
-rw-r--r--mp/src/game/server/nav_area.cpp16
-rw-r--r--mp/src/game/server/nav_area.h25
-rw-r--r--mp/src/game/server/nav_generate.cpp2
-rw-r--r--mp/src/game/server/nav_mesh.cpp2
-rw-r--r--mp/src/game/server/nav_mesh.h2
-rw-r--r--mp/src/game/server/nav_pathfind.h16
-rw-r--r--mp/src/game/server/networkstringtable_gamedll.h2
-rw-r--r--mp/src/game/server/physics_main.cpp8
-rw-r--r--mp/src/game/server/player.cpp33
-rw-r--r--mp/src/game/server/player.h10
-rw-r--r--mp/src/game/server/player_lagcompensation.cpp14
-rw-r--r--mp/src/game/server/recipientfilter.cpp2
-rw-r--r--mp/src/game/server/recipientfilter.h4
-rw-r--r--mp/src/game/server/sceneentity.cpp96
-rw-r--r--mp/src/game/server/sendproxy.cpp4
-rw-r--r--mp/src/game/server/sound.cpp2
-rw-r--r--mp/src/game/server/team_control_point_master.cpp4
-rw-r--r--mp/src/game/server/team_control_point_master.h8
-rw-r--r--mp/src/game/server/team_train_watcher.cpp19
-rw-r--r--mp/src/game/server/team_train_watcher.h3
-rw-r--r--mp/src/game/server/trigger_area_capture.cpp2
-rw-r--r--mp/src/game/server/triggers.cpp3
-rw-r--r--mp/src/game/server/util.cpp4
-rw-r--r--mp/src/game/server/util.h4
-rw-r--r--mp/src/game/server/vote_controller.cpp235
-rw-r--r--mp/src/game/server/vote_controller.h11
65 files changed, 883 insertions, 597 deletions
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 );