summaryrefslogtreecommitdiff
path: root/game/server/functorutils.h
diff options
context:
space:
mode:
Diffstat (limited to 'game/server/functorutils.h')
-rw-r--r--game/server/functorutils.h450
1 files changed, 450 insertions, 0 deletions
diff --git a/game/server/functorutils.h b/game/server/functorutils.h
new file mode 100644
index 0000000..4816664
--- /dev/null
+++ b/game/server/functorutils.h
@@ -0,0 +1,450 @@
+// FunctorUtils.h
+// Useful functors
+//========= Copyright Valve Corporation, All rights reserved. ============//
+
+#ifndef _FUNCTOR_UTILS_H_
+#define _FUNCTOR_UTILS_H_
+
+#ifdef NEXT_BOT
+#include "NextBotInterface.h"
+#include "NextBotManager.h"
+#endif // NEXT_BOT
+
+//--------------------------------------------------------------------------------------------------------
+/**
+ * NOTE: The functors in this file should ideally be game-independent,
+ * and work for any Source based game
+ */
+//--------------------------------------------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------------------------------------------
+/**
+ * Count the number of living players on a given team (or TEAM_ANY)
+ */
+class LivePlayerCounter
+{
+public:
+ static const bool EXCLUDE_BOTS = false;
+ LivePlayerCounter( int team, bool includeBots = true )
+ {
+ m_team = team;
+ m_includeBots = includeBots;
+ m_count = 0;
+ }
+
+ bool operator() ( CBasePlayer *player )
+ {
+ if (player->IsAlive() && (m_team == TEAM_ANY || player->GetTeamNumber() == m_team))
+ {
+ if (m_includeBots || !player->IsBot())
+ {
+ ++m_count;
+ }
+ }
+ return true;
+ }
+
+ int GetCount( void ) const
+ {
+ return m_count;
+ }
+
+ int m_team;
+ bool m_includeBots;
+ int m_count;
+};
+
+
+//--------------------------------------------------------------------------------------------------------
+/**
+* Count the number of dead players on a given team (or TEAM_ANY)
+*/
+class DeadPlayerCounter
+{
+public:
+ static const bool EXCLUDE_BOTS = false;
+ DeadPlayerCounter( int team, bool includeBots = true )
+ {
+ m_team = team;
+ m_includeBots = includeBots;
+ m_count = 0;
+ }
+
+ bool operator() ( CBasePlayer *player )
+ {
+ if (!player->IsAlive() && (m_team == TEAM_ANY || player->GetTeamNumber() == m_team))
+ {
+ if (m_includeBots || !player->IsBot())
+ {
+ ++m_count;
+ }
+ }
+ return true;
+ }
+
+ int GetCount( void ) const
+ {
+ return m_count;
+ }
+
+ int m_team;
+ bool m_includeBots;
+ int m_count;
+};
+
+
+//--------------------------------------------------------------------------------------------------------
+/**
+* Count the number of players on a given team (or TEAM_ANY)
+*/
+class PlayerCounter
+{
+public:
+ static const bool EXCLUDE_BOTS = false;
+ PlayerCounter( int team, int lifeState = -1, bool includeBots = true )
+ {
+ m_team = team;
+ m_includeBots = includeBots;
+ m_count = 0;
+ m_lifeState = lifeState;
+ }
+
+ bool operator() ( CBasePlayer *player )
+ {
+ if ((player->m_lifeState == m_lifeState || m_lifeState == -1) && (m_team == TEAM_ANY || player->GetTeamNumber() == m_team))
+ {
+ if (m_includeBots || !player->IsBot())
+ {
+ ++m_count;
+ }
+ }
+ return true;
+ }
+
+ int GetCount( void ) const
+ {
+ return m_count;
+ }
+
+ int m_lifeState;
+ int m_team;
+ bool m_includeBots;
+ int m_count;
+};
+
+
+//--------------------------------------------------------------------------------------------------------
+/**
+ * Return the closest living player on the given team (or TEAM_ANY)
+ */
+class ClosestPlayerScan
+{
+public:
+ static const bool EXCLUDE_BOTS = false;
+ ClosestPlayerScan( const Vector &spot, int team, float maxRange = 0.0f, CBasePlayer *ignore = NULL, bool includeBots = true )
+ {
+ m_spot = spot;
+ m_team = team;
+ m_includeBots = includeBots;
+ m_close = NULL;
+
+ if ( maxRange > 0.0f )
+ {
+ m_closeRangeSq = maxRange * maxRange;
+ }
+ else
+ {
+ m_closeRangeSq = 999999999.9f;
+ }
+
+ m_ignore = ignore;
+ }
+
+ bool operator() ( CBasePlayer *player )
+ {
+ if (player == m_ignore)
+ return true;
+
+ if (player->IsAlive() && (m_team == TEAM_ANY || player->GetTeamNumber() == m_team))
+ {
+ if ( !m_includeBots && player->IsBot() )
+ return true;
+
+ Vector to = player->WorldSpaceCenter() - m_spot;
+ float rangeSq = to.LengthSqr();
+ if (rangeSq < m_closeRangeSq)
+ {
+ m_closeRangeSq = rangeSq;
+ m_close = player;
+ }
+ }
+ return true;
+ }
+
+ CBasePlayer *GetPlayer( void ) const
+ {
+ return m_close;
+ }
+
+ bool IsCloserThan( float range )
+ {
+ return (m_closeRangeSq < (range * range));
+ }
+
+ bool IsFartherThan( float range )
+ {
+ return (m_closeRangeSq > (range * range));
+ }
+
+ Vector m_spot;
+ int m_team;
+ bool m_includeBots;
+ CBasePlayer *m_close;
+ float m_closeRangeSq;
+ CBasePlayer *m_ignore;
+};
+
+
+//--------------------------------------------------------------------------------------------------------
+/**
+* Return the closest living BaseCombatCharacter on the given team (or TEAM_ANY)
+*/
+class ClosestActorScan
+{
+public:
+ ClosestActorScan( const Vector &spot, int team, float maxRange = 0.0f, CBaseCombatCharacter *ignore = NULL )
+ {
+ m_spot = spot;
+ m_team = team;
+ m_close = NULL;
+
+ if ( maxRange > 0.0f )
+ {
+ m_closeRangeSq = maxRange * maxRange;
+ }
+ else
+ {
+ m_closeRangeSq = 999999999.9f;
+ }
+
+ m_ignore = ignore;
+ }
+
+ bool operator() ( CBaseCombatCharacter *actor )
+ {
+ if (actor == m_ignore)
+ return true;
+
+ if (actor->IsAlive() && (m_team == TEAM_ANY || actor->GetTeamNumber() == m_team))
+ {
+ Vector to = actor->WorldSpaceCenter() - m_spot;
+ float rangeSq = to.LengthSqr();
+ if (rangeSq < m_closeRangeSq)
+ {
+ m_closeRangeSq = rangeSq;
+ m_close = actor;
+ }
+ }
+ return true;
+ }
+
+ CBaseCombatCharacter *GetClosestActor( void ) const
+ {
+ return m_close;
+ }
+
+ bool IsClosestActorCloserThan( float range )
+ {
+ return (m_closeRangeSq < (range * range));
+ }
+
+ bool IsClosestActorFartherThan( float range )
+ {
+ return (m_closeRangeSq > (range * range));
+ }
+
+ Vector m_spot;
+ int m_team;
+ CBaseCombatCharacter *m_close;
+ float m_closeRangeSq;
+ CBaseCombatCharacter *m_ignore;
+};
+
+
+//--------------------------------------------------------------------------------------------------------
+class CShowViewportPanel
+{
+ int m_team;
+ const char *m_panelName;
+ bool m_show;
+ KeyValues *m_data;
+
+public:
+ CShowViewportPanel( int team, const char *panelName, bool show, KeyValues *data = NULL )
+ {
+ m_team = team;
+ m_panelName = panelName;
+ m_show = show;
+ m_data = data;
+ }
+
+ bool operator() ( CBasePlayer *player )
+ {
+ if ( m_team != TEAM_ANY && m_team != player->GetTeamNumber() )
+ return true;
+
+ player->ShowViewPortPanel( m_panelName, m_show, m_data );
+ return true;
+ }
+};
+
+//--------------------------------------------------------------------------------------------------------------
+/**
+ * Iterate each "actor" in the game, where an actor is a Player or NextBot
+ */
+template < typename Functor >
+inline bool ForEachActor( Functor &func )
+{
+ // iterate all non-bot players
+ for( int i=1; i<=gpGlobals->maxClients; ++i )
+ {
+ CBasePlayer *player = UTIL_PlayerByIndex( i );
+
+ if ( player == NULL )
+ continue;
+
+ if ( FNullEnt( player->edict() ) )
+ continue;
+
+ if ( !player->IsPlayer() )
+ continue;
+
+ if ( !player->IsConnected() )
+ continue;
+
+#ifdef NEXT_BOT
+ // skip bots - ForEachCombatCharacter will catch them
+ INextBot *bot = player->MyNextBotPointer();
+ if ( bot )
+ {
+ continue;
+ }
+#endif // NEXT_BOT
+
+ if ( func( player ) == false )
+ {
+ return false;
+ }
+ }
+
+#ifdef NEXT_BOT
+ // iterate all NextBots
+ return TheNextBots().ForEachCombatCharacter( func );
+#else
+ return true;
+#endif // NEXT_BOT
+}
+
+
+//--------------------------------------------------------------------------------------------------------------
+/**
+ * The interface for functors for use with ForEachActor() that
+ * want notification before iteration starts and after interation
+ * is complete (successful or not).
+ */
+class IActorFunctor
+{
+public:
+ virtual void OnBeginIteration( void ) { } // invoked once before iteration begins
+
+ virtual bool operator() ( CBaseCombatCharacter *them ) = 0;
+
+ virtual void OnEndIteration( bool allElementsIterated ) { } // invoked once after iteration is complete whether successful or not
+};
+
+
+//--------------------------------------------------------------------------------------------------------------
+/**
+ * Iterate each "actor" in the game, where an actor is a Player or NextBot
+ * Template specialization for IActorFunctors.
+ */
+template <>
+inline bool ForEachActor( IActorFunctor &func )
+{
+ func.OnBeginIteration();
+
+ bool isComplete = true;
+
+ // iterate all non-bot players
+ for( int i=1; i<=gpGlobals->maxClients; ++i )
+ {
+ CBasePlayer *player = UTIL_PlayerByIndex( i );
+
+ if ( player == NULL )
+ continue;
+
+ if ( FNullEnt( player->edict() ) )
+ continue;
+
+ if ( !player->IsPlayer() )
+ continue;
+
+ if ( !player->IsConnected() )
+ continue;
+
+#ifdef NEXT_BOT
+ // skip bots - ForEachCombatCharacter will catch them
+ INextBot *bot = dynamic_cast< INextBot * >( player );
+ if ( bot )
+ {
+ continue;
+ }
+#endif // NEXT_BOT
+
+ if ( func( player ) == false )
+ {
+ isComplete = false;
+ break;
+ }
+ }
+
+#ifdef NEXT_BOT
+ if ( !isComplete )
+ {
+ // iterate all NextBots
+ isComplete = TheNextBots().ForEachCombatCharacter( func );
+ }
+#endif // NEXT_BOT
+
+ func.OnEndIteration( isComplete );
+
+ return isComplete;
+}
+
+
+//--------------------------------------------------------------------------------------------------------
+class CTraceFilterOnlyClassname : public CTraceFilterSimple
+{
+public:
+ CTraceFilterOnlyClassname( const IHandleEntity *passentity, const char *pchClassname, int collisionGroup ) :
+ CTraceFilterSimple( passentity, collisionGroup ), m_pchClassname( pchClassname )
+ {
+ }
+
+ virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
+ {
+ CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
+ if ( !pEntity )
+ return false;
+
+ return FClassnameIs( pEntity, m_pchClassname ) && CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask );
+ }
+
+private:
+
+ const char *m_pchClassname;
+};
+
+
+#endif // _FUNCTOR_UTILS_H_