mirror of
https://github.com/celisej567/source-engine.git
synced 2026-01-04 18:09:53 +03:00
1
This commit is contained in:
278
game/server/NextBot/NextBotUtil.h
Normal file
278
game/server/NextBot/NextBotUtil.h
Normal file
@@ -0,0 +1,278 @@
|
||||
// NextBotUtil.h
|
||||
// Utilities for the NextBot system
|
||||
// Author: Michael Booth, May 2006
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
|
||||
#ifndef _NEXT_BOT_UTIL_H_
|
||||
#define _NEXT_BOT_UTIL_H_
|
||||
|
||||
#include "NextBotLocomotionInterface.h"
|
||||
#include "nav_area.h"
|
||||
#include "nav_mesh.h"
|
||||
#include "nav_pathfind.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* A simple filter interface for various NextBot queries
|
||||
*/
|
||||
class INextBotEntityFilter
|
||||
{
|
||||
public:
|
||||
// return true if the given entity passes this filter
|
||||
virtual bool IsAllowed( CBaseEntity *entity ) const = 0;
|
||||
};
|
||||
|
||||
|
||||
// trace filter callback functions. needed for use with the querycache/optimization functionality
|
||||
bool VisionTraceFilterFunction( IHandleEntity *pServerEntity, int contentsMask );
|
||||
bool IgnoreActorsTraceFilterFunction( IHandleEntity *pServerEntity, int contentsMask );
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* Trace filter that skips all players and NextBots
|
||||
*/
|
||||
class NextBotTraceFilterIgnoreActors : public CTraceFilterSimple
|
||||
{
|
||||
public:
|
||||
NextBotTraceFilterIgnoreActors( const IHandleEntity *passentity, int collisionGroup ) : CTraceFilterSimple( passentity, collisionGroup, IgnoreActorsTraceFilterFunction )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* Trace filter that skips all players, NextBots, and non-LOS blockers
|
||||
*/
|
||||
class NextBotVisionTraceFilter : public CTraceFilterSimple
|
||||
{
|
||||
public:
|
||||
NextBotVisionTraceFilter( const IHandleEntity *passentity, int collisionGroup ) : CTraceFilterSimple( passentity, collisionGroup, VisionTraceFilterFunction )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* Trace filter that skips all NextBots, but includes Players
|
||||
*/
|
||||
class NextBotTraceFilterIgnoreNextBots : public CTraceFilterSimple
|
||||
{
|
||||
public:
|
||||
NextBotTraceFilterIgnoreNextBots( const IHandleEntity *passentity, int collisionGroup )
|
||||
: CTraceFilterSimple( passentity, collisionGroup )
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask )
|
||||
{
|
||||
if ( CTraceFilterSimple::ShouldHitEntity( pServerEntity, contentsMask ) )
|
||||
{
|
||||
CBaseEntity *entity = EntityFromEntityHandle( pServerEntity );
|
||||
#ifdef TERROR
|
||||
CBasePlayer *player = ToBasePlayer( entity );
|
||||
if ( player && player->IsGhost() )
|
||||
return false;
|
||||
#endif // TERROR
|
||||
|
||||
return ( entity->MyNextBotPointer() == NULL );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* Trace filter that obeys INextBot::IsAbleToBlockMovementOf()
|
||||
*/
|
||||
class NextBotTraceFilter : public CTraceFilterSimple
|
||||
{
|
||||
public:
|
||||
NextBotTraceFilter( const IHandleEntity *passentity, int collisionGroup )
|
||||
: CTraceFilterSimple( passentity, collisionGroup )
|
||||
{
|
||||
CBaseEntity *entity = const_cast<CBaseEntity *>(EntityFromEntityHandle( passentity ));
|
||||
m_passBot = entity->MyNextBotPointer();
|
||||
}
|
||||
|
||||
virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask )
|
||||
{
|
||||
if ( CTraceFilterSimple::ShouldHitEntity( pServerEntity, contentsMask ) )
|
||||
{
|
||||
CBaseEntity *entity = EntityFromEntityHandle( pServerEntity );
|
||||
#ifdef TERROR
|
||||
CBasePlayer *player = ToBasePlayer( entity );
|
||||
if ( player && player->IsGhost() )
|
||||
return false;
|
||||
#endif // TERROR
|
||||
|
||||
// Skip players on the same team - they're not solid to us, and we'll avoid them
|
||||
if ( entity->IsPlayer() && m_passBot && m_passBot->GetEntity() &&
|
||||
m_passBot->GetEntity()->GetTeamNumber() == entity->GetTeamNumber() )
|
||||
return false;
|
||||
|
||||
INextBot *bot = entity->MyNextBotPointer();
|
||||
|
||||
return ( !bot || bot->IsAbleToBlockMovementOf( m_passBot ) );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const INextBot *m_passBot;
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* Trace filter that only hits players and NextBots
|
||||
*/
|
||||
class NextBotTraceFilterOnlyActors : public CTraceFilterSimple
|
||||
{
|
||||
public:
|
||||
NextBotTraceFilterOnlyActors( const IHandleEntity *passentity, int collisionGroup )
|
||||
: CTraceFilterSimple( passentity, collisionGroup )
|
||||
{
|
||||
}
|
||||
|
||||
virtual TraceType_t GetTraceType() const
|
||||
{
|
||||
return TRACE_ENTITIES_ONLY;
|
||||
}
|
||||
|
||||
virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask )
|
||||
{
|
||||
if ( CTraceFilterSimple::ShouldHitEntity( pServerEntity, contentsMask ) )
|
||||
{
|
||||
CBaseEntity *entity = EntityFromEntityHandle( pServerEntity );
|
||||
|
||||
#ifdef TERROR
|
||||
CBasePlayer *player = ToBasePlayer( entity );
|
||||
if ( player && player->IsGhost() )
|
||||
return false;
|
||||
#endif // TERROR
|
||||
|
||||
return ( entity->MyNextBotPointer() || entity->IsPlayer() );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* Trace filter that skips "traversable" entities. The "when" argument creates
|
||||
* a temporal context for asking if an entity is IMMEDIATELY traversable (like thin
|
||||
* glass that just breaks as we walk through it) or EVENTUALLY traversable (like a
|
||||
* breakable object that will take some time to break through)
|
||||
*/
|
||||
class NextBotTraversableTraceFilter : public CTraceFilterSimple
|
||||
{
|
||||
public:
|
||||
NextBotTraversableTraceFilter( INextBot *bot, ILocomotion::TraverseWhenType when = ILocomotion::EVENTUALLY ) : CTraceFilterSimple( bot->GetEntity(), COLLISION_GROUP_NONE )
|
||||
{
|
||||
m_bot = bot;
|
||||
m_when = when;
|
||||
}
|
||||
|
||||
virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask )
|
||||
{
|
||||
CBaseEntity *entity = EntityFromEntityHandle( pServerEntity );
|
||||
|
||||
if ( m_bot->IsSelf( entity ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( CTraceFilterSimple::ShouldHitEntity( pServerEntity, contentsMask ) )
|
||||
{
|
||||
return !m_bot->GetLocomotionInterface()->IsEntityTraversable( entity, m_when );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
INextBot *m_bot;
|
||||
ILocomotion::TraverseWhenType m_when;
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* Given a vector of entities, a nav area, and a max travel distance, return
|
||||
* the entity that has the shortest travel distance.
|
||||
*/
|
||||
inline CBaseEntity *SelectClosestEntityByTravelDistance( INextBot *me, const CUtlVector< CBaseEntity * > &candidateEntities, CNavArea *startArea, float travelRange )
|
||||
{
|
||||
// collect nearby walkable areas within travelRange
|
||||
CUtlVector< CNavArea * > nearbyAreaVector;
|
||||
CollectSurroundingAreas( &nearbyAreaVector, startArea, travelRange, me->GetLocomotionInterface()->GetStepHeight(), me->GetLocomotionInterface()->GetDeathDropHeight() );
|
||||
|
||||
// find closest entity in the collected area set
|
||||
CBaseEntity *closeEntity = NULL;
|
||||
float closeTravelRange = FLT_MAX;
|
||||
|
||||
for( int i=0; i<candidateEntities.Count(); ++i )
|
||||
{
|
||||
CBaseEntity *candidate = candidateEntities[i];
|
||||
|
||||
CNavArea *area = TheNavMesh->GetNearestNavArea( candidate, GETNAVAREA_CHECK_LOS, 500.0f );
|
||||
|
||||
if ( area && area->IsMarked() && area->GetCostSoFar() < closeTravelRange )
|
||||
{
|
||||
closeEntity = candidate;
|
||||
closeTravelRange = area->GetCostSoFar();
|
||||
}
|
||||
}
|
||||
|
||||
return closeEntity;
|
||||
}
|
||||
|
||||
|
||||
#ifdef OBSOLETE
|
||||
//--------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* Trace filter that skips "traversable" entities, but hits other Actors.
|
||||
* Used for obstacle avoidance.
|
||||
*/
|
||||
class NextBotMovementAvoidanceTraceFilter : public CTraceFilterSimple
|
||||
{
|
||||
public:
|
||||
NextBotMovementAvoidanceTraceFilter( INextBot *bot ) : CTraceFilterSimple( bot->GetEntity(), COLLISION_GROUP_NONE )
|
||||
{
|
||||
m_bot = bot;
|
||||
}
|
||||
|
||||
virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask )
|
||||
{
|
||||
CBaseEntity *entity = EntityFromEntityHandle( pServerEntity );
|
||||
|
||||
#ifdef TERROR
|
||||
CBasePlayer *player = ToBasePlayer( entity );
|
||||
if ( player && player->IsGhost() )
|
||||
return false;
|
||||
#endif // TERROR
|
||||
|
||||
if ( m_bot->IsSelf( entity ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( CTraceFilterSimple::ShouldHitEntity( pServerEntity, contentsMask ) )
|
||||
{
|
||||
return !m_bot->GetLocomotionInterface()->IsEntityTraversable( entity, ILocomotion::IMMEDIATELY );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
INextBot *m_bot;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif // _NEXT_BOT_UTIL_H_
|
||||
Reference in New Issue
Block a user