package net.scapeemulator.game.model.mob.action; import java.util.Deque; import net.scapeemulator.game.model.Position; import net.scapeemulator.game.model.area.Area; import net.scapeemulator.game.model.area.QuadArea; import net.scapeemulator.game.model.mob.Direction; import net.scapeemulator.game.model.mob.Mob; import net.scapeemulator.game.model.pathfinding.DumbPathFinder; import net.scapeemulator.game.model.pathfinding.Path; import net.scapeemulator.game.model.player.Player; import net.scapeemulator.game.task.Action; public class FollowAction extends Action<Mob> { protected final Mob target; private Path path = new Path(); protected int distance; private boolean behind; public FollowAction(Mob mob, Mob target, boolean behind) { this(mob, target, behind, 0); if (!behind) throw new IllegalArgumentException("Must state a max distance if not following behind."); } public FollowAction(Mob mob, Mob target, boolean behind, int distance) { super(mob, 1, true); this.behind = behind; this.distance = distance; this.target = target; mob.turnToTarget(target); mob.getWalkingQueue().reset(); } @Override public void execute() { if (target.isTeleporting() || !target.getPosition().isWithinDistance(mob.getPosition())) { stop(); return; } Area targetBounds = target.getBounds(); if (behind) { Deque<Position> recentPoints = target.getWalkingQueue().getRecentPoints(); if (!recentPoints.isEmpty()) { Position last = recentPoints.peekLast(); int lastX = last.getX(); int lastY = last.getY(); targetBounds = new QuadArea(lastX, lastY, lastX + target.getSize() - 1, lastY + target.getSize() - 1); } } // Check if we are inside the mob (and not supposed to be) if (distance > 0 && mob.getBounds().anyWithinArea(target.getPosition(), target.getSize(), 0, true)) { Position p = Direction.getNearbyTraversableTiles(mob.getPosition(), mob.getSize()).get(0); mob.getWalkingQueue().addPoint(p); return; } // Check if we are inside the target area (don't move) if (targetBounds.anyWithinArea(mob.getPosition(), mob.getSize(), distance, false)) { return; } path = DumbPathFinder.find(mob.getPosition(), targetBounds.center(), mob.getSize(), 2, false); if (path == null || path.isEmpty()) { return; } mob.getWalkingQueue().addPoint(path.poll()); if (path.isEmpty()) { return; } if (mob instanceof Player) { if (!((Player) mob).getSettings().isRunning()) { return; } if ((targetBounds.anyWithinArea(path.peek(), mob.getSize(), distance == 0 ? 0 : distance - 1, false) && !behind)) { return; } mob.getWalkingQueue().addPoint(path.poll()); } } @Override public void stop() { mob.resetTurnToTarget(); super.stop(); } }