|
|
// FunctorUtils.h
// Useful functors
// Author: Michael Booth, August 2005, Copyright 2005 Turtle Rock Studios, Inc.
#ifndef _FUNCTOR_UTILS_H_
#define _FUNCTOR_UTILS_H_
#ifdef SERVER_NEXT_BOTS
#include "NextBotInterface.h"
#include "NextBotManager.h"
#else
class INextBot; #endif
//--------------------------------------------------------------------------------------------------------
/**
* 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 SERVER_NEXT_BOTS
// skip bots - ForEachCombatCharacter will catch them
INextBot *bot = player->MyNextBotPointer(); if ( bot ) { continue; } #endif
if ( func( player ) == false ) { return false; } }
#ifdef SERVER_NEXT_BOTS
// iterate all NextBots
return TheNextBots().ForEachCombatCharacter( func ); #else
return true; #endif
}
//--------------------------------------------------------------------------------------------------------------
/**
* 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 SERVER_NEXT_BOTS
// skip bots - ForEachCombatCharacter will catch them
INextBot *bot = dynamic_cast< INextBot * >( player ); if ( bot ) { continue; } #endif
if ( func( player ) == false ) { isComplete = false; break; } }
#ifdef SERVER_NEXT_BOTS
if ( !isComplete ) { // iterate all NextBots
isComplete = TheNextBots().ForEachCombatCharacter( func ); } #endif
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_
|