diff options
Diffstat (limited to 'src/Mobs/Path.h')
-rw-r--r-- | src/Mobs/Path.h | 64 |
1 files changed, 39 insertions, 25 deletions
diff --git a/src/Mobs/Path.h b/src/Mobs/Path.h index ac71968bd..c6f47ada3 100644 --- a/src/Mobs/Path.h +++ b/src/Mobs/Path.h @@ -7,6 +7,7 @@ enum class ePathFinderStatus; class cPath; */ + #include "../FastRandom.h" #ifdef COMPILING_PATHFIND_DEBUGGER /* Note: the COMPILING_PATHFIND_DEBUGGER flag is used by Native / WiseOldMan95 to debug @@ -19,22 +20,40 @@ class cPath; //fwd: ../Chunk.h class cChunk; + /* Various little structs and classes */ enum class ePathFinderStatus {CALCULATING, PATH_FOUND, PATH_NOT_FOUND, NEARBY_FOUND}; enum class eCellStatus {OPENLIST, CLOSEDLIST, NOLIST}; +/** The pathfinder has 3 types of cells (cPathCell). +1 - empty. m_IsSolid is false, m_IsSpecial is false. Air cells are always traversable by A*. +2 - occupied / solid. m_IsSolid is true, m_IsSpecial is false. Air cells are never traversable by A*. +3 - Special. m_IsSolid is true, m_IsSpecial is true. These cells are special: They may either behave as empty +or as occupied / solid, depending on the mob's direction of movement. For instance, an airblock above a fence is a special cell, +because when mobs attempt to travel to it by jumping, it acts as a solid. But when mobs fall and land on top of a fence, +it acts as air. Special cells include: Doors, ladders, trapdoors, water, gates. + +The main function which handles special blocks is SpecialIsSolidFromThisDirection. +This function receives a BlockType, a meta, and a direction of travel, +then it uses those 3 parameters to decide whether the special block should behave as a solid or as air in this +particular direction of travel. + +Currently, only fences and water are handled properly. The function always returns "true" (meaning: treat as occuiped/solid) for +the rest of the blocks. This will be fixed once the physics engine issues are fixed. */ struct cPathCell { Vector3i m_Location; // Location of the cell in the world. int m_F, m_G, m_H; // F, G, H as defined in regular A*. eCellStatus m_Status; // Which list is the cell in? Either non, open, or closed. cPathCell * m_Parent; // Cell's parent, as defined in regular A*. - bool m_IsSolid; // Is the cell an air or a solid? Partial solids are currently considered solids. + bool m_IsSolid; // Is the cell an air or a solid? Partial solids are considered solids. If m_IsSpecial is true, this is always true. + bool m_IsSpecial; // The cell is special - it acts as "solid" or "air" depending on direction, e.g. door or top of fence. + BLOCKTYPE m_BlockType; + NIBBLETYPE m_BlockMeta; }; - class compareHeuristics { public: @@ -48,32 +67,22 @@ public: class cPath { public: - /** Creates a pathfinder instance. A Mob will probably need a single pathfinder instance for its entire life. - - Note that if you have a man-sized mob (1x1x2, zombies, etc), you are advised to call this function without parameters - because the declaration might change in later version of the pathFinder, and a parameter-less call always assumes a man-sized mob. + /** Creates a pathfinder instance. + After calling this, you are expected to call CalculationStep() once per tick or once per several ticks + until it returns something other than CALCULATING. - If your mob is not man-sized, you are advised to use cPath(width, height), this would be compatible with future versions, - but please be aware that as of now those parameters will be ignored and your mob will be assumed to be man sized. - - @param a_BoundingBoxWidth the character's boundingbox width in blocks. Currently the parameter is ignored and 1 is assumed. - @param a_BoundingBoxHeight the character's boundingbox width in blocks. Currently the parameter is ignored and 2 is assumed. - @param a_MaxUp the character's max jump height in blocks. Currently the parameter is ignored and 1 is assumed. - @param a_MaxDown How far is the character willing to fall? Currently the parameter is ignored and 1 is assumed. */ - /** Attempts to find a path starting from source to destination. - After calling this, you are expected to call Step() once per tick or once per several ticks until it returns true. You should then call getPath() to obtain the path. - Calling this before a path is found resets the current path and starts another search. @param a_StartingPoint The function expects this position to be the lowest block the mob is in, a rule of thumb: "The block where the Zombie's knees are at". @param a_EndingPoint "The block where the Zombie's knees want to be". - @param a_MaxSteps The maximum steps before giving up. */ + @param a_MaxSteps The maximum steps before giving up. + @param a_BoundingBoxWidth the character's boundingbox width in blocks. Currently the parameter is ignored and 1 is assumed. + @param a_BoundingBoxHeight the character's boundingbox width in blocks. Currently the parameter is ignored and 2 is assumed. */ cPath( cChunk & a_Chunk, const Vector3d & a_StartingPoint, const Vector3d & a_EndingPoint, int a_MaxSteps, - double a_BoundingBoxWidth, double a_BoundingBoxHeight, - int a_MaxUp = 1, int a_MaxDown = 1 + double a_BoundingBoxWidth, double a_BoundingBoxHeight ); - /** Creates a dummy path which does nothing except returning false when isValid is called. */ + /** Creates an invalid path which is not usable. You shouldn't call any method other than isValid on such a path. */ cPath(); /** delete default constructors */ @@ -84,9 +93,11 @@ public: cPath & operator=(cPath && a_other) = delete; /** Performs part of the path calculation and returns the appropriate status. + If PATH_FOUND is returned, the path was found, and you can call query the instance for waypoints via GetNextWayPoint, etc. If NEARBY_FOUND is returned, it means that the destination is not reachable, but a nearby destination is reachable. If the user likes the alternative destination, they can call AcceptNearbyPath to treat the path as found, - and to make consequent calls to step return PATH_FOUND */ + and to make consequent calls to step return PATH_FOUND + If PATH_NOT_FOUND is returned, then no path was found. */ ePathFinderStatus CalculationStep(cChunk & a_Chunk); /** Called after the PathFinder's step returns NEARBY_FOUND. @@ -142,7 +153,6 @@ public: private: /* General */ - bool IsSolid(const Vector3i & a_Location); // Query our hosting world and ask it if there's a solid at a_location. bool StepOnce(); // The public version just calls this version * CALCULATIONS_PER_CALL times. void FinishCalculation(); // Clears the memory used for calculating the path. void FinishCalculation(ePathFinderStatus a_NewStatus); // Clears the memory used for calculating the path and changes the status. @@ -152,7 +162,7 @@ private: /* Openlist and closedlist management */ void OpenListAdd(cPathCell * a_Cell); cPathCell * OpenListPop(); - bool ProcessIfWalkable(const Vector3i &a_Location, cPathCell * a_Parent, int a_Cost); + bool ProcessIfWalkable(const Vector3i & a_Location, cPathCell * a_Source, int a_Cost); /* Map management */ void ProcessCell(cPathCell * a_Cell, cPathCell * a_Caller, int a_GDelta); @@ -179,12 +189,16 @@ private: std::vector<Vector3i> m_PathPoints; /* Interfacing with the world */ + void FillCellAttributes(cPathCell & a_Cell); // Query our hosting world and fill the cell with info cChunk * m_Chunk; // Only valid inside Step()! bool m_BadChunkFound; /* High level world queries */ - bool IsWalkable(const Vector3i & a_Location); - bool BodyFitsIn(const Vector3i & a_Location); + bool IsWalkable(const Vector3i & a_Location, const Vector3i & a_Source); + bool BodyFitsIn(const Vector3i & a_Location, const Vector3i & a_Source); + bool BlockTypeIsSpecial(BLOCKTYPE a_Type); + bool BlockTypeIsFence(BLOCKTYPE a_Type); // TODO Perhaps this should be moved to cBlockInfo + bool SpecialIsSolidFromThisDirection(BLOCKTYPE a_Type, NIBBLETYPE a_Meta, const Vector3i & a_Direction); bool HasSolidBelow(const Vector3i & a_Location); #ifdef COMPILING_PATHFIND_DEBUGGER #include "../path_irrlicht.cpp" |