/* * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as a special exception, the author gives permission to * link the code of this program with the Half-Life Game Engine ("HL * Engine") and Modified Game Libraries ("MODs") developed by Valve, * L.L.C ("Valve"). You must obey the GNU General Public License in all * respects for all of the code used other than the HL Engine and MODs * from Valve. If you modify this file, you may extend this exception * to your version of the file, but you are not obligated to do so. If * you do not wish to do so, delete this exception statement from your * version. * */ #pragma once // STL uses exceptions, but we are not compiling with them - ignore warning #pragma warning(disable : 4530) class CNavPath { public: CNavPath() { m_segmentCount = 0; } struct PathSegment { CNavArea *area; // the area along the path NavTraverseType how; // how to enter this area from the previous one Vector pos; // our movement goal position at this point in the path const CNavLadder *ladder; // if "how" refers to a ladder, this is it }; const PathSegment *operator[](int i) { return (i >= 0 && i < m_segmentCount) ? &m_path[i] : NULL; } int GetSegmentCount() const { return m_segmentCount; } const Vector &GetEndpoint() const { return m_path[ m_segmentCount - 1 ].pos; } bool IsValid() const { return (m_segmentCount > 0); } void Invalidate() { m_segmentCount = 0; } public: enum { MAX_PATH_SEGMENTS = 256 }; PathSegment m_path[ MAX_PATH_SEGMENTS ]; int m_segmentCount; bool ComputePathPositions(); // determine actual path positions bool BuildTrivialPath(const Vector *start, const Vector *goal); // utility function for when start and goal are in the same area int FindNextOccludedNode(int anchor_); // used by Optimize() }; // Monitor improv movement and determine if it becomes stuck class CStuckMonitor { public: bool IsStuck() const { return m_isStuck; } float GetDuration() const { return m_isStuck ? m_stuckTimer.GetElapsedTime() : 0.0f; } public: bool m_isStuck; // if true, we are stuck Vector m_stuckSpot; // the location where we became stuck IntervalTimer m_stuckTimer; // how long we have been stuck enum { MAX_VEL_SAMPLES = 5 }; float m_avgVel[ MAX_VEL_SAMPLES ]; int m_avgVelIndex; int m_avgVelCount; Vector m_lastCentroid; float m_lastTime; }; // The CNavPathFollower class implements path following behavior class CNavPathFollower { public: void SetImprov(CImprov *improv) { m_improv = improv; } void SetPath(CNavPath *path) { m_path = path; } void Debug(bool status) { m_isDebug = status; } // turn debugging on/off public: int FindOurPositionOnPath(Vector *close, bool local) const; // return the closest point to our current position on current path int FindPathPoint(float aheadRange, Vector *point, int *prevIndex); // compute a point a fixed distance ahead along our path. CImprov *m_improv; // who is doing the path following CNavPath *m_path; // the path being followed int m_segmentIndex; // the point on the path the improv is moving towards int m_behindIndex; // index of the node on the path just behind us Vector m_goal; // last computed follow goal bool m_isLadderStarted; bool m_isDebug; CStuckMonitor m_stuckMonitor; };