diff options
Diffstat (limited to 'game/server/ai_movesolver.h')
| -rw-r--r-- | game/server/ai_movesolver.h | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/game/server/ai_movesolver.h b/game/server/ai_movesolver.h new file mode 100644 index 0000000..8f6826b --- /dev/null +++ b/game/server/ai_movesolver.h @@ -0,0 +1,312 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: "Force-field" obstacle avoidance & steering +// +// @Note (toml 06-18-02): Currently only controls direction. Ultimately could +// also incorporate body facing (yaw), speed, and translational/rotational +// acceleration. +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef AI_MOVESOLVER_H +#define AI_MOVESOLVER_H + +#if defined( _WIN32 ) +#pragma once +#endif + +#include "utlvector.h" +#include "ai_obstacle_type.h" + + +//----------------------------------------------------------------------------- + +inline float NormalizeAngle( float angle ) +{ + if ( angle < 0.0 ) + angle += 360.0; + else if ( angle >= 360.0 ) + angle -= 360.0; + return angle; +} + +//----------------------------------------------------------------------------- +// ENUMERATIONS +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// STRUCTURES +//----------------------------------------------------------------------------- + +//------------------------------------- +// AI_Arc_t +// +// Purpose: Represents an arc. +// +//------------------------------------- +struct AI_Arc_t +{ + AI_Arc_t() + : center( 0 ), + span( 0 ) + { + } + + // Set by center and span + void Set( float newCenter, float newSpan ); + + // Set by the right and left extremes (coordinates run counter clockwise) + void SetByLimits( float yawRight, float yawLeft ); + + // Center of the arc (as "yaw") + float center; + + // Span of the arc (in degrees) + float span; +}; + +//------------------------------------- +// AI_MoveSuggestion_t +// +// Purpose: Suggests a possible move/avoidance, with a range of acceptable alternatives +// +// @Note (toml 06-20-02): this probably will eventually want to incorporate facing and +// destination of the motivating goal. +// +//------------------------------------- + +enum AI_MoveSuggestionFlags_t +{ + AIMS_FAVOR_LEFT = 0x01, + AIMS_FAVOR_RIGHT = 0x02 +}; + +//----------------- + +struct AI_MoveSuggestion_t +{ + AI_MoveSuggestion_t(); + AI_MoveSuggestion_t( AI_MoveSuggType_t newType, float newWeight, float newDir, float newSpan, CBaseEntity *pEntity = NULL ); + AI_MoveSuggestion_t( AI_MoveSuggType_t newType, float newWeight, const AI_Arc_t &arc, CBaseEntity *pEntity = NULL ); + + void Set( AI_MoveSuggType_t newType, float newWeight, float newDir, float newSpan, CBaseEntity *pEntity = NULL ); + void Set( AI_MoveSuggType_t newType, float newWeight, const AI_Arc_t &arc, CBaseEntity *pEntity = NULL ); + + //--------------------------------- + + // The kind of suggestion + AI_MoveSuggType_t type; + + // The unadjusted weight of the suggestion [0..1], although [-1..1] within the solver + float weight; + + // The desired direction to move/avoid + AI_Arc_t arc; + + // The causing entity, if any + EHANDLE hObstacleEntity; + + // Flags + unsigned flags; + +}; + +//----------------- + +typedef CUtlVector<AI_MoveSuggestion_t> CAI_MoveSuggestions; + +//------------------------------------- +// AI_MoveSolution_t +// +// Purpose: The result of resolving suggestions +// +// @Note (toml 06-18-02): Currently, this is a very dopey little structure. +// However, it will probably eventually incorporate much of the info +// passed or calculated piecemeal between Move...() and Move...Execute() +// functions. Once suggestions incorprate more information, the solution +// may want to include a copy of the winning suggestion, so that the +// caller need retain less state. If this is not the case, reduce it to just +// a yaw. +// +//------------------------------------- +struct AI_MoveSolution_t +{ + AI_MoveSolution_t() + : dir(0) + { + } + + // The direction to move + float dir; +}; + +//----------------------------------------------------------------------------- +// class CAI_MoveSolver +// +// Purpose: Given a set of precalculated "regulations" (typically negative), +// and a set of instantaneous suggestions (usually positive) +//----------------------------------------------------------------------------- + +class CAI_MoveSolver +{ +public: + CAI_MoveSolver(); + + //--------------------------------- + // Purpose: A regulation is a suggestion that is kept around as a rule until + // cleared. They are generally negative suggestions. + //--------------------------------- + void AddRegulation( const AI_MoveSuggestion_t &suggestion ); + void AddRegulations( const AI_MoveSuggestion_t *pSuggestion, int nSuggestions ); + + bool HaveRegulations() const; + void ClearRegulations(); + + //--------------------------------- + // Purpose: Solve the move, picking the best direction from a set of suggestions, + // after applying the regulations + //--------------------------------- + bool Solve( const AI_MoveSuggestion_t *pSuggestions, int nSuggestions, AI_MoveSolution_t *pResult ); + bool Solve( const AI_MoveSuggestion_t &suggestion, AI_MoveSolution_t *pResult ); + + //--------------------------------- + bool HaveRegulationForObstacle( CBaseEntity *pEntity); + + //--------------------------------- + // Visualization + void VisualizeRegulations( const Vector& origin ); + +private: + enum + { + REGS_RESERVE = 8, + }; + + //--------------------------------- + void NormalizeSuggestions( AI_MoveSuggestion_t *pBegin, AI_MoveSuggestion_t *pEnd ); + + //--------------------------------- + CAI_MoveSuggestions m_Regulations; +}; + +//----------------------------------------------------------------------------- +// AI_Arc_t inline methods +//----------------------------------------------------------------------------- + +inline void AI_Arc_t::Set( float newCenter, float newSpan ) +{ + center = NormalizeAngle( newCenter ); + span = NormalizeAngle( newSpan ); +} + +//------------------------------------- + +inline void AI_Arc_t::SetByLimits( float yawRight, float yawLeft ) +{ + // Yaw runs counter-clockwise + span = yawLeft - yawRight; + + if ( span < 0 ) + span += 360; + + center = yawRight + span * 0.5; + + if ( center >= 360 ) + center -= 360; +} + +//----------------------------------------------------------------------------- +// AI_MoveSuggestion_t inline methods +//----------------------------------------------------------------------------- + +inline void AI_MoveSuggestion_t::Set( AI_MoveSuggType_t newType, float newWeight, float newDir, float newSpan, CBaseEntity *pEntity ) +{ + type = newType; + weight = newWeight; + hObstacleEntity = pEntity; + flags = 0; + + arc.Set( newDir, newSpan ); +} + +//------------------------------------- + +inline AI_MoveSuggestion_t::AI_MoveSuggestion_t() + : type( AIMS_INVALID ), + weight( 0 ), + flags( 0 ) +{ +} + +//------------------------------------- + +inline AI_MoveSuggestion_t::AI_MoveSuggestion_t( AI_MoveSuggType_t newType, float newWeight, float newDir, float newSpan, CBaseEntity *pEntity ) +{ + Set( newType, newWeight, newDir, newSpan, pEntity ); +} + +//------------------------------------- + +inline AI_MoveSuggestion_t::AI_MoveSuggestion_t( AI_MoveSuggType_t newType, float newWeight, const AI_Arc_t &arc, CBaseEntity *pEntity ) +{ + Set( newType, newWeight, arc.center, arc.span, pEntity ); +} + +//------------------------------------- + +inline void AI_MoveSuggestion_t::Set( AI_MoveSuggType_t newType, float newWeight, const AI_Arc_t &arc, CBaseEntity *pEntity ) +{ + Set( newType, newWeight, arc.center, arc.span, pEntity ); +} + +//----------------------------------------------------------------------------- +// CAI_MoveSolver inline methods +//----------------------------------------------------------------------------- + +inline CAI_MoveSolver::CAI_MoveSolver() +{ + m_Regulations.EnsureCapacity( REGS_RESERVE ); +} + +//------------------------------------- + +inline void CAI_MoveSolver::AddRegulation( const AI_MoveSuggestion_t &suggestion ) +{ + m_Regulations.AddToTail( suggestion ); +} + +//------------------------------------- + +inline void CAI_MoveSolver::AddRegulations( const AI_MoveSuggestion_t *pSuggestions, int nSuggestions ) +{ + for (int i = 0; i < nSuggestions; ++i) + { + m_Regulations.AddToTail( pSuggestions[i] ); + } +} + +//------------------------------------- + +inline bool CAI_MoveSolver::HaveRegulations() const +{ + return (m_Regulations.Count() > 0); +} + +//------------------------------------- + +inline void CAI_MoveSolver::ClearRegulations() +{ + m_Regulations.RemoveAll(); +} + +//------------------------------------- + +inline bool CAI_MoveSolver::Solve( const AI_MoveSuggestion_t &suggestion, AI_MoveSolution_t *pResult) +{ + return Solve( &suggestion, 1, pResult); +} + +//============================================================================= + +#endif // AI_MOVESOLVER_H |