//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #ifndef AI_WAYPOINT_H #define AI_WAYPOINT_H #if defined( _WIN32 ) #pragma once #endif #include // ---------------------------------------------------------------------------- // Forward declarations // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // Flags used in the flags field in AI_Waypoint_T // ---------------------------------------------------------------------------- enum WaypointFlags_t { // The type of waypoint bits_WP_TO_DETOUR = 0x01, // move to detour point. bits_WP_TO_PATHCORNER = 0x02, // move to a path corner bits_WP_TO_NODE = 0x04, // move to a node bits_WP_TO_GOAL = 0x08, // move to an arbitrary point bits_WP_TO_DOOR = 0x10, // move to position to open a door // Other flags for waypoint bits_WP_DONT_SIMPLIFY = 0x20, // Don't let the route code simplify this waypoint bits_WP_PRECISE_MOVEMENT = 0x40, // Precise movement is necessary near this waypoint }; // ---------------------------------------------------------------------------- // Purpose: Waypoints that make up an NPC's route. // ---------------------------------------------------------------------------- struct AI_Waypoint_t { public: AI_Waypoint_t(); AI_Waypoint_t( const Vector &vecPosition, float flYaw, Navigation_t navType, int fWaypointFlags, int nNodeID ); AI_Waypoint_t( const AI_Waypoint_t &from ) { memcpy( this, &from, sizeof(*this) ); flPathDistGoal = -1; pNext = pPrev = NULL; } AI_Waypoint_t &operator=( const AI_Waypoint_t &from ) { memcpy( this, &from, sizeof(*this) ); flPathDistGoal = -1; pNext = pPrev = NULL; return *this; } ~AI_Waypoint_t() { AssertValid(); if ( pNext ) { pNext->AssertValid(); pNext->pPrev = pPrev; } if ( pPrev ) { pPrev->AssertValid(); pPrev->pNext = pNext; } } //--------------------------------- void AssertValid() const { #ifdef DEBUG Assert( !pNext || pNext->pPrev == this ); Assert( !pPrev || pPrev->pNext == this ); #endif } //--------------------------------- int Flags() const; Navigation_t NavType() const; void SetNavType( Navigation_t type ) { m_iWPType = type; } // Flag modification method void ModifyFlags( int fFlags, bool bEnable ); bool IsReducible() { return (pNext && m_iWPType == pNext->m_iWPType && !(m_fWaypointFlags & (bits_WP_TO_GOAL | bits_WP_TO_PATHCORNER | bits_WP_DONT_SIMPLIFY)) ); } //--------------------------------- void SetNext( AI_Waypoint_t *p ); AI_Waypoint_t * GetNext() { return pNext; } const AI_Waypoint_t *GetNext() const { return pNext; } void SetPrev( AI_Waypoint_t *p ); AI_Waypoint_t * GetPrev() { return pPrev; } const AI_Waypoint_t *GetPrev() const { return pPrev; } AI_Waypoint_t * GetLast(); //--------------------------------- const Vector & GetPos() const { return vecLocation; } void SetPos(const Vector &newPos) { vecLocation = newPos; } EHANDLE GetEHandleData() { return m_hData; } //--------------------------------- // // Basic info // Vector vecLocation; float flYaw; // Waypoint facing dir int iNodeID; // If waypoint is a node, which one //--------------------------------- // // Precalculated distances // float flPathDistGoal; //--------------------------------- // // If following a designer laid path, the path-corner entity (if any) // EHANDLE hPathCorner; // Data specific to the waypoint type: // // PATHCORNER: The path corner entity. // DOOR: If moving to position to open a door, the handle of the door to open. EHANDLE m_hData; private: int m_fWaypointFlags; // See WaypointFlags_t Navigation_t m_iWPType; // The type of waypoint AI_Waypoint_t *pNext; AI_Waypoint_t *pPrev; DECLARE_FIXEDSIZE_ALLOCATOR(AI_Waypoint_t); public: DECLARE_SIMPLE_DATADESC(); }; // ---------------------------------------------------------------------------- // Inline methods associated with AI_Waypoint_t // ---------------------------------------------------------------------------- inline int AI_Waypoint_t::Flags() const { return m_fWaypointFlags; } inline Navigation_t AI_Waypoint_t::NavType() const { return m_iWPType; } inline void AI_Waypoint_t::ModifyFlags( int fFlags, bool bEnable ) { if (bEnable) m_fWaypointFlags |= fFlags; else m_fWaypointFlags &= ~fFlags; } inline void AI_Waypoint_t::SetNext( AI_Waypoint_t *p ) { if (pNext) { pNext->pPrev = NULL; } pNext = p; if ( pNext ) { if ( pNext->pPrev ) pNext->pPrev->pNext = NULL; pNext->pPrev = this; } } inline void AI_Waypoint_t::SetPrev( AI_Waypoint_t *p ) { if ( pPrev ) { pPrev->pNext = NULL; } pPrev = p; if ( pPrev ) { if ( pPrev->pNext ) pPrev->pNext->pPrev = NULL; pPrev->pNext = this; } } // ---------------------------------------------------------------------------- // Purpose: Holds an maintains a chain of waypoints class CAI_WaypointList { public: CAI_WaypointList() : m_pFirstWaypoint( NULL ) { } CAI_WaypointList( AI_Waypoint_t *pFirstWaypoint) : m_pFirstWaypoint( pFirstWaypoint ) { } void Set(AI_Waypoint_t* route); void PrependWaypoints( AI_Waypoint_t *pWaypoints ); void PrependWaypoint( const Vector &newPoint, Navigation_t navType, unsigned waypointFlags, float flYaw = 0 ); bool IsEmpty() const { return ( m_pFirstWaypoint == NULL ); } AI_Waypoint_t * GetFirst() { return m_pFirstWaypoint; } const AI_Waypoint_t *GetFirst() const { return m_pFirstWaypoint; } AI_Waypoint_t * GetLast(); const AI_Waypoint_t *GetLast() const; void RemoveAll(); private: AI_Waypoint_t* m_pFirstWaypoint; // Linked list of waypoints }; // ---------------------------------------------------------------------------- #ifdef DEBUG void AssertRouteValid( AI_Waypoint_t* route ); #else #define AssertRouteValid( route ) ((void)0) #endif // ---------------------------------------------------------------------------- // Utilities void DeleteAll( AI_Waypoint_t *pWaypointList ); // ------------------------------------ inline void DeleteAll( AI_Waypoint_t **ppWaypointList ) { DeleteAll( *ppWaypointList ); *ppWaypointList = NULL; } // ------------------------------------ void AddWaypointLists(AI_Waypoint_t *pLeft, AI_Waypoint_t *pRight); // ---------------------------------------------------------------------------- #endif // AI_WAYPOINT_H