// Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #ifndef RYAI_PATH_BEHAVIOR_H #define RYAI_PATH_BEHAVIOR_H #include "world_container.h" #include "ai_entity_physical.h" #include "ai_entity_physical_inline.h" #include "ai_instance.h" #include "time_interface.h" #include "nel/misc/variable.h" extern NLMISC::CVariable LogAcceptablePos; ////////////////////////////////////////////////////////////////////////////// // CAIPath // ////////////////////////////////////////////////////////////////////////////// class CAIPath : public NLMISC::CRefCount { public: /// @name Accessors std::vector const& topologiesPath() const { return _TopologiesPath; } std::vector& topologiesPathForCalc() { return _TopologiesPath; } RYAI_MAP_CRUNCH::CWorldPosition const& getStartPos() const { return _Start; } void setStartPos(RYAI_MAP_CRUNCH::CWorldPosition const& pos) { _Start = pos; } RYAI_MAP_CRUNCH::CWorldPosition const& getEndPos() const { return _End; } void setEndPos(RYAI_MAP_CRUNCH::CWorldPosition const& pos) { _End = pos; } //@} private: RYAI_MAP_CRUNCH::CWorldPosition _Start; RYAI_MAP_CRUNCH::CWorldPosition _End; std::vector _TopologiesPath; }; ////////////////////////////////////////////////////////////////////////////// // CInsidePath // ////////////////////////////////////////////////////////////////////////////// class CInsidePath : public NLMISC::CRefCount { public: std::vector _DirectionPath; }; ////////////////////////////////////////////////////////////////////////////// // CPathPosition // ////////////////////////////////////////////////////////////////////////////// class CPathCont; class CPathPosition { public: enum TPathPosState { NOT_INITIALIZED, FOLLOWING_TOPO, FOLLOWING_INSIDE_TOPO, REACH_END, NO_PATH }; /// @name Constructor and destructor //@{ CPathPosition(CAngle const& angle); virtual ~CPathPosition() { } // Defined coz no base class //@} /// @name Accessors //@{ NLMISC::CSmartPtr const& getPath() const { return _Path; } RYAI_MAP_CRUNCH::CTopology::TTopologyRef const& getTopology() const; RYAI_MAP_CRUNCH::CTopology::TTopologyRef const& getNextTopology() const; //@} bool isPathValid() const; bool isFinished() const; bool nextTopology(); bool haveNextTopology(uint nbTopo = 1); NLMISC::CSmartPtr _Path; NLMISC::CSmartPtr _InsidePath; RYAI_MAP_CRUNCH::CMapPosition _InsideStartPos; RYAI_MAP_CRUNCH::CMapPosition _InsideDestPos; uint _InsideIndex; TPathPosState _PathState; uint32 _TimeTopoChanged; uint32 _TimeDestChanged; CAngle _Angle; private: friend class CPathCont; uint _Index; }; ////////////////////////////////////////////////////////////////////////////// // CPathCont // ////////////////////////////////////////////////////////////////////////////// class CPathCont : public NLMISC::CDbgRefCount { public: /// @name Constructors //@{ CPathCont(RYAI_MAP_CRUNCH::TAStarFlag denyFlags); CPathCont(CPathCont const& pathCont); //@} /// @name Accessors //@{ RYAI_MAP_CRUNCH::TAStarFlag const& denyFlags() const { return _denyFlags; } RYAI_MAP_CRUNCH::TAStarFlag const& getDenyFlags() const { return _denyFlags; } void setDenyFlags(RYAI_MAP_CRUNCH::TAStarFlag denyFlags) { _denyFlags = denyFlags; } CAIVector const& getDestination() const { return _Destination; } RYAI_MAP_CRUNCH::CWorldPosition const& getDestPos() const { return _DestPos; } void setDestination(RYAI_MAP_CRUNCH::CWorldPosition const& destPos); void setDestination(AITYPES::TVerticalPos verticalPos, CAIVector const& destPos); //@} void clearPaths(); bool getPathForSource(CPathPosition& pathPos, RYAI_MAP_CRUNCH::CWorldPosition const& startPos) const; bool calcPathForSource(CPathPosition& pathPos, RYAI_MAP_CRUNCH::CWorldPosition const& startPos); bool getCalcPathForSource(CPathPosition& pathPos, RYAI_MAP_CRUNCH::CWorldPosition const& startPos); uint32 _TimeTopoChanged; uint32 _TimeDestChanged; private: CAIVector _Destination; RYAI_MAP_CRUNCH::CMapPosition _DestinationMapPos; AITYPES::TVerticalPos _VerticalPos; RYAI_MAP_CRUNCH::CTopology::TTopologyRef _TopoRef; RYAI_MAP_CRUNCH::CWorldPosition _DestPos; std::vector > _SourcePaths; RYAI_MAP_CRUNCH::TAStarFlag _denyFlags; }; ////////////////////////////////////////////////////////////////////////////// // CFollowPathContext // ////////////////////////////////////////////////////////////////////////////// class CFollowPathContext { public: // ctor // - This method adds the new object to the top of the CFollowPath singleton's context stack // parameters: // - contextName : an arbitrary string naming the context // - maxSearchDepth : the value that the path finder search depth should be limitted to (default to std::numeric_limits::max() meaning no limit) // - forceMaxDepth : set this flag true to override previous limit with larger value // example: // - ... Before we begin ... CFollowPath::_MaxSearchDepth = std::numeric_limits::max() // - CFollowPathContext context1("tata") : CFollowPath::_MaxSearchDepth => std::numeric_limits::max() // - CFollowPathContext context2("tete",456) : CFollowPath::_MaxSearchDepth => 456 // - CFollowPathContext context3("titi",123) : CFollowPath::_MaxSearchDepth => 123 // - CFollowPathContext context4("toto",456) : CFollowPath::_MaxSearchDepth => 123 // - CFollowPathContext context5("tutu") : CFollowPath::_MaxSearchDepth => 123 // - CFollowPathContext context6("dada",456,true) : CFollowPath::_MaxSearchDepth => 456 // - CFollowPathContext context6.~CFollowPathContext() : CFollowPath::_MaxSearchDepth => 123 // - CFollowPathContext context5.~CFollowPathContext() : CFollowPath::_MaxSearchDepth => 123 // - CFollowPathContext context4.~CFollowPathContext() : CFollowPath::_MaxSearchDepth => 123 // - CFollowPathContext context3.~CFollowPathContext() : CFollowPath::_MaxSearchDepth => 456 // - CFollowPathContext context2.~CFollowPathContext() : CFollowPath::_MaxSearchDepth => std::numeric_limits::max() // - CFollowPathContext context1.~CFollowPathContext() : CFollowPath::_MaxSearchDepth => std::numeric_limits::max() CFollowPathContext(const char* contextName, uint32 maxSearchDepth=std::numeric_limits::max(), bool forceMaxDepth=false); // dtor // - This method removes the destroyed object from the CFollowPath singleton's context stack // - Out of order destruction is supported ok, but the _MaxSearchDepth values of higher stack entries are not recalculated ~CFollowPathContext(); // getter for _MaxSearchDepth uint32 getMaxSearchDepth() const { return _MaxSearchDepth; } // simple accessor for contructing the full context name of this object by concatenating own name with names of previous context stack entries void buildContextName(std::string &result) const; private: CFollowPathContext* _PrevContext; CFollowPathContext* _NextContext; const char* _ContextName; uint32 _MaxSearchDepth; }; ////////////////////////////////////////////////////////////////////////////// // CFollowPath // ////////////////////////////////////////////////////////////////////////////// class CFollowPath { private: static CFollowPath* _Instance; public: static CFollowPath* getInstance(); static void destroyInstance(); CFollowPath(); enum TFollowStatus { FOLLOWING, // normal FOLLOW_NO_PATH, // no path found FOLLOW_ARRIVED, // arrived FOLLOW_BLOCKED // Is blocked by someone(s), cannot move. }; enum TFollowReason { NO_REASON = -1, // FOLLOW_NO_PATH FNP_NOT_INITIALIZED, FNP_NO_INSIDE_ASTAR_PATH }; private: TFollowReason _LastReason; RYAI_MAP_CRUNCH::CWorldMap::TFindInsideAStarPathReason _LastFIASPReason; public: static std::string toString(TFollowReason reason, RYAI_MAP_CRUNCH::CWorldMap::TFindInsideAStarPathReason fIASPReason = RYAI_MAP_CRUNCH::CWorldMap::FIASPR_NO_REASON) { switch (reason) { case FNP_NOT_INITIALIZED: return "FOLLOW_NO_PATH::NOT_INITIALIZED"; case FNP_NO_INSIDE_ASTAR_PATH: return "FOLLOW_NO_PATH::NO_INSIDE_ASTAR_PATH::" + RYAI_MAP_CRUNCH::CWorldMap::toString(fIASPReason); default: return "UnknownReason(" + NLMISC::toString((int)reason) + ")"; } } TFollowReason lastReason() { return _LastReason; } RYAI_MAP_CRUNCH::CWorldMap::TFindInsideAStarPathReason lastFIASPReason() { return _LastFIASPReason; } public: NLMISC::CMustConsume followPath( CModEntityPhysical* bot, CPathPosition& pathPos, CPathCont& pathCont, float dist, float modecalageDist, float angleAmort = 1.f, bool focusOnTargetDirection = true, CAIVector* realDestination = NULL, float repulsSpeed = 0.025f, bool updateOrient = true); private: friend class CFollowPathContext; CFollowPathContext* _TopFollowPathContext; public: uint32 getMaxSearchDepth() const { return (_TopFollowPathContext==NULL)? std::numeric_limits::max(): _TopFollowPathContext->getMaxSearchDepth(); } const char* getContextName() const; }; #endif