Improved pathfinding to handle cases when both player and target are moving

This commit is contained in:
dam 2025-11-25 15:14:39 +02:00 committed by Ryan
parent dfb53cfa03
commit 6241ff9ce5

View file

@ -11,6 +11,7 @@ import core.game.world.GameWorld;
import core.game.world.map.Direction;
import core.game.world.map.Location;
import core.game.world.map.Point;
import core.game.world.map.RegionManager;
import core.game.world.map.path.Path;
import core.game.world.map.path.Pathfinder;
import core.net.packet.PacketRepository;
@ -384,34 +385,39 @@ public abstract class MovementPulse extends Pulse {
Location ml = mover.getLocation();
Location dl = destination.getLocation();
// Lead the target if they're walking/running, unless they're already within interaction range
if(loc != null && destination instanceof Entity) {
WalkingQueue wq = ((Entity)destination).getWalkingQueue();
if(wq.hasPath()) {
if (loc != null && destination instanceof Entity) {
WalkingQueue wq = ((Entity) destination).getWalkingQueue();
if (wq.hasPath()) {
Point[] points = wq.getQueue().toArray(new Point[0]);
if(points.length > 0) {
if (points.length > 0) {
Point p = points[0];
Point predictiveIntersection = null;
for(int i=0; i<points.length; i++) {
Location closestBorder = getClosestBorderToPoint (points[i], loc.getZ());
for (int i = 0; i < points.length; i++) {
Location closestBorder = getClosestBorderToPoint(points[i], loc.getZ());
if (!RegionManager.isTeleportPermitted(closestBorder)) { // A nasty hack to discard invalid intersection points
continue;
}
int moverDist = Math.max(Math.abs(ml.getX() - closestBorder.getX()), Math.abs(ml.getY() - closestBorder.getY()));
float movementRatio = moverDist / (float) ((i + 1) / (mover.getWalkingQueue().isRunning() ? 2 : 1));
if (predictiveIntersection == null && movementRatio <= 1.0) { //try to predict an intersection point on the path if possible
predictiveIntersection = points[i];
break;
}
// Otherwise, we target the farthest point along target's planned movement that's within 1 tick's running,
// this ensures the player will run to catch up to the target if able.
if(moverDist <= 2) {
if (moverDist <= 2) {
p = points[i];
}
}
if (predictiveIntersection != null)
p = predictiveIntersection;
Location endLoc = getClosestBorderToPoint(p, loc.getZ());
if (!RegionManager.isTeleportPermitted(endLoc)) { // Basically a prayer
return loc;
}
return endLoc;
}
}