uox3/source/movement.h
Xoduz d355c4d946 Pathfinding update
- [UPD] UOX3 now supports Z as a third dimension for NPC pathfinding; automatically used in most places in code, it can also be triggered via .WalkTo() and .RunTo() JS Methods, which have been updated to support target Z coordinate. This means NPCs can now navigate up and down stairs, move between floors of buildings, etc.
- [UPD] NPCs will recalculate their path less often now in situations with little-to-no change since last they got a valid path, if they still have remaining steps in their previously calculated path. However, the more time passes from the original pathfind calculation, the more likely it is to retrigger.
- [UPD] Updated 'xwalk and 'xrun GM commands (js/commands/targeting/xwalk.js), hireling AI (js/npc/ai/hireling.js) and Herding skill (js/skill/herding.js) to make use of "3D pathfinding"
- [FIX] Fixed some issues with pathfinding code that could result in invalid results for what should be valid paths
2026-04-26 21:13:48 +08:00

98 lines
3.8 KiB
C++

#ifndef __MOVEMENT_H__
#define __MOVEMENT_H__
#include "mapclasses.h"
// Maximum Return Value: Number of steps to return (Replaces PATHNUM)
// NOTE: P_PF_MRV CANNOT EXCEED THE VALUE OF PATHNUM FOR THE TIME BEING
constexpr auto P_PF_MRV = 22;
// Minimum Flee Distance: MFD
constexpr auto P_PF_MFD = 15;
// Maximum Flee Distance: MAXFD
constexpr auto P_PF_MAXFD = 50;
struct PfNode_st
{
UI16 hCost;
UI16 gCost;
UI64 parent;
SI08 z;
PfNode_st() : hCost( 0 ), gCost( 0 ), parent( 0 ), z( 0 )
{
}
PfNode_st( UI16 nHC, UI16 nGC, UI64 nPS, SI08 nZ ) : hCost( nHC ), gCost( nGC ), parent( nPS ), z( nZ )
{
}
};
struct NodeFCost_st
{
UI64 xySer;
UI16 fCost;
NodeFCost_st() : xySer( 0 ), fCost( 0 )
{
}
NodeFCost_st( UI16 nFC, UI64 nS ) : xySer( nS ), fCost( nFC )
{
}
};
class CMovement
{
// Function declarations
public:
bool AdvancedPathfinding( CChar *mChar, UI16 targX, UI16 targY, SI08 targZ, bool willRun = false, bool allowPartial = false, UI16 maxSteps = 0, bool ignoreDoors = false );
auto IgnoreAndEvadeTarget( CChar *mChar ) -> void;
void Walking( CSocket *mSock, CChar *s, UI08 dir, SI16 sequence );
void CombatWalk( CChar *i );
void NpcMovement( CChar& mChar );
void PathFind( CChar *c, SI16 gx, SI16 gy, bool willRun = false, UI08 pathLen = P_PF_MRV );
UI08 Direction( CChar *c, SI16 x, SI16 y );
bool CheckForCharacterAtXYZ( CChar *c, SI16 cx, SI16 cy, SI08 cz );
SI08 CalcWalk( CChar *c, SI16 x, SI16 y, SI16 oldx, SI16 oldy, SI08 oldz, bool justask, bool waterWalk = false, bool ignoreDoors = false );
void DoJSInRange( CBaseObject *mObj, CBaseObject *objInRange );
void DoJSOutOfRange( CBaseObject *mObj, CBaseObject *objInRange );
bool SpeedHackDetection( CSocket *mSock, CChar *c, UI08 dir, SI16 sequence );
private:
bool PFGrabNodes( CChar *mChar, UI16 targX, UI16 targY, SI08 targZ, UI16 curX, UI16 curY, SI08 curZ, UI64 parentSer, UI16 parentGCost, std::map<UI64, PfNode_st>& openList, std::map<UI64, UI64>& closedList, std::deque<NodeFCost_st>& fCostList, bool ignoreDoors = false );
bool CalcMove( CChar *c, SI16 x, SI16 y, SI08 &z, UI08 dir );
bool HandleNPCWander( CChar& mChar );
bool IsValidDirection( UI08 dir );
bool IsFrozen( CChar *c, CSocket *mSock, SI16 sequence );
bool IsOverloaded( CChar *c, CSocket *mSock, SI16 sequence );
bool IsOk( std::vector<Tile_st> &xyblock, UI16 &xycount, UI08 world, SI08 ourZ, SI08 ourTop, SI16 x, SI16 y, UI16 instanceId, bool ignoreDoor, bool waterWalk );
void GetAverageZ( UI08 nm, SI16 x, SI16 y, SI08& z, SI08& avg, SI08& top );
void GetStartZ( UI08 world, CChar *c, SI16 x, SI16 y, SI08 z, SI08& zlow, SI08& ztop, UI16 instanceId, bool waterWalk );
void GetBlockingStatics( SI16 x, SI16 y, std::vector<Tile_st> &xyblock, UI16 &xycount, UI08 worldNumber );
void GetBlockingDynamics( SI16 x, SI16 y, std::vector<Tile_st> &xyblock, UI16 &xycount, UI08 worldNumber, UI16 instanceId, bool ignoreDoors = false );
UI08 Direction( SI16 sx, SI16 sy, SI16 dx, SI16 dy );
void NpcWalk( CChar *i, UI08 j, SI08 getWander );
SI16 GetXfromDir( UI08 dir, SI16 x );
SI16 GetYfromDir( UI08 dir, SI16 y );
void BoundingBoxTeleport( CChar *c, UI16 fx2Actual, UI16 fy2Actual, SI16 newz, SI16 newy );
bool VerifySequence( CChar *c, CSocket *mSock, SI16 sequence);
bool CheckForRunning( CChar *c, UI08 dir );
bool CheckForStealth( CChar *c );
bool CheckForHouseBan( CChar *c, CSocket *mSock );
void MoveCharForDirection( CChar *c, SI16 newX, SI16 newY, SI08 newZ );
void SendWalkToPlayer( CChar *c, CSocket *mSock, SI16 sequence );
void SendWalkToOtherPlayers( CChar *c, UI08 dir, SI16 oldx, SI16 oldy );
void OutputShoveMessage( CChar *c, CSocket *mSock );
void HandleItemCollision( CChar *c, CSocket *mSock, SI16 oldx, SI16 oldy );
bool IsGMBody( CChar *c );
void DenyMovement( CSocket *mSock, CChar *s, SI16 sequence );
};
extern CMovement *Movement;
#endif