//========= Copyright 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 }; // ---------------------------------------------------------------------------- // 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; // 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; } 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; } } // ---------------------------------------------------------------------------- // 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