forked from MagicBane/Server
				
			
				 7 changed files with 323 additions and 393 deletions
			
			
		@ -0,0 +1,116 @@
				@@ -0,0 +1,116 @@
					 | 
				
			||||
package engine.gameManager; | 
				
			||||
 | 
				
			||||
import engine.math.Vector3fImmutable; | 
				
			||||
import engine.objects.*; | 
				
			||||
 | 
				
			||||
import java.util.ArrayList; | 
				
			||||
 | 
				
			||||
 | 
				
			||||
public class NavigationManager { | 
				
			||||
 | 
				
			||||
    private static final int cellGap = 1; | 
				
			||||
    private static final int stepHeight = 2; | 
				
			||||
 | 
				
			||||
    public static void pathfind(AbstractCharacter character, Vector3fImmutable goal){ | 
				
			||||
        try { | 
				
			||||
            ArrayList<Vector3fImmutable> path = getOptimizedPath(getPath(character.loc, goal), getPath(goal, character.loc)); | 
				
			||||
            if (path.isEmpty()) { | 
				
			||||
                character.destination = goal; | 
				
			||||
                return; //no points to walk to
 | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            character.destination = path.get(0); | 
				
			||||
 | 
				
			||||
        } catch(Exception e){ | 
				
			||||
            //something failed
 | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static ArrayList<Vector3fImmutable> getOptimizedPath(ArrayList<Vector3fImmutable> startToGoal, ArrayList<Vector3fImmutable> goalToStart) { | 
				
			||||
        ArrayList<Vector3fImmutable> optimalPath = new ArrayList<>(); | 
				
			||||
        optimalPath.add(startToGoal.get(0)); | 
				
			||||
        for(Vector3fImmutable point : startToGoal) | 
				
			||||
        { | 
				
			||||
            if(!goalToStart.contains(point)) | 
				
			||||
            { | 
				
			||||
                continue; | 
				
			||||
            } | 
				
			||||
            optimalPath.add(point); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        //optimize the path to its smallest possible amount of points
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
        return optimalPath; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    private static ArrayList<Vector3fImmutable> getPath(Vector3fImmutable start, Vector3fImmutable goal) { | 
				
			||||
        ArrayList<Vector3fImmutable> path = new ArrayList<>(); | 
				
			||||
        path.add(start); | 
				
			||||
        Vector3fImmutable current = start; | 
				
			||||
        boolean obstructed = false; | 
				
			||||
        int count = 0; | 
				
			||||
        while (current.distanceSquared(goal) > 9 && count < 250) | 
				
			||||
        { | 
				
			||||
            //gather the 8 cells around the player
 | 
				
			||||
            ArrayList<Vector3fImmutable> surroundingCells = new ArrayList<>(); | 
				
			||||
            surroundingCells.add(current.add(new Vector3fImmutable(cellGap, 0, 0))); | 
				
			||||
            surroundingCells.add(current.add(new Vector3fImmutable(cellGap, 0, cellGap))); | 
				
			||||
            surroundingCells.add(current.add(new Vector3fImmutable(0, 0, cellGap))); | 
				
			||||
            surroundingCells.add(current.add(new Vector3fImmutable(-cellGap, 0, 0))); | 
				
			||||
            surroundingCells.add(current.add(new Vector3fImmutable(-cellGap, 0, -cellGap))); | 
				
			||||
            surroundingCells.add(current.add(new Vector3fImmutable(0, 0, -cellGap))); | 
				
			||||
            surroundingCells.add(current.add(new Vector3fImmutable(-cellGap, 0, cellGap))); | 
				
			||||
            surroundingCells.add(current.add(new Vector3fImmutable(cellGap, 0, -cellGap))); | 
				
			||||
            Vector3fImmutable cheapest = new Vector3fImmutable(Vector3fImmutable.ZERO); | 
				
			||||
            for (Vector3fImmutable point : surroundingCells) | 
				
			||||
            { | 
				
			||||
                count++; | 
				
			||||
 | 
				
			||||
                if (path.contains(point)) | 
				
			||||
                    continue; | 
				
			||||
 | 
				
			||||
                if (pointIsBlocked(point)) { | 
				
			||||
                    obstructed = true; | 
				
			||||
                    continue; | 
				
			||||
                } | 
				
			||||
 | 
				
			||||
                if (getCost(cheapest, current, goal) > getCost(point, current, goal)) | 
				
			||||
                    cheapest = point; | 
				
			||||
            } | 
				
			||||
            current = cheapest; | 
				
			||||
            path.add(cheapest); | 
				
			||||
        } | 
				
			||||
        if(obstructed) { | 
				
			||||
            return path; | 
				
			||||
        }else { | 
				
			||||
            ArrayList<Vector3fImmutable> goalPath = new ArrayList<>(); | 
				
			||||
            goalPath.add(start); | 
				
			||||
            goalPath.add(goal); | 
				
			||||
            return goalPath; //if the path isn't obstructed we can walk directly from start to the goal
 | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static float getCost(Vector3fImmutable point, Vector3fImmutable start, Vector3fImmutable goal) { | 
				
			||||
        float gCost = start.distanceSquared(point); | 
				
			||||
        float hCost = goal.distanceSquared(point); | 
				
			||||
        return gCost + hCost; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static boolean pointIsBlocked(Vector3fImmutable point) { | 
				
			||||
 | 
				
			||||
        Building building = BuildingManager.getBuildingAtLocation(point); | 
				
			||||
        if(building != null) | 
				
			||||
            for(Regions region : building.getBounds().getRegions()) | 
				
			||||
                if(region.isPointInPolygon(point)) | 
				
			||||
                    if(Math.abs(region.lerpY(point) - point.y) > stepHeight) // get the height distance between current height and target location height
 | 
				
			||||
                        return true; | 
				
			||||
 | 
				
			||||
        Zone currentZone = ZoneManager.findSmallestZone(point); | 
				
			||||
        if(currentZone == null) | 
				
			||||
            return false; | 
				
			||||
        else | 
				
			||||
            return currentZone.navMesh.contains(point.x,point.z); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,364 +0,0 @@
				@@ -1,364 +0,0 @@
					 | 
				
			||||
// • ▌ ▄ ·.  ▄▄▄·  ▄▄ • ▪   ▄▄· ▄▄▄▄·  ▄▄▄·  ▐▄▄▄  ▄▄▄ .
 | 
				
			||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
 | 
				
			||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
 | 
				
			||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
 | 
				
			||||
// ▀▀  █▪▀▀▀ ▀  ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀  ▀  ▀ ▀▀  █▪ ▀▀▀
 | 
				
			||||
//      Magicbane Emulator Project © 2013 - 2022
 | 
				
			||||
//                www.magicbane.com
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
package engine.mobileAI.utilities; | 
				
			||||
 | 
				
			||||
import engine.Enum; | 
				
			||||
import engine.Enum.GameObjectType; | 
				
			||||
import engine.Enum.ModType; | 
				
			||||
import engine.Enum.SourceType; | 
				
			||||
import engine.InterestManagement.Terrain; | 
				
			||||
import engine.exception.MsgSendException; | 
				
			||||
import engine.gameManager.BuildingManager; | 
				
			||||
import engine.gameManager.MovementManager; | 
				
			||||
import engine.gameManager.ZoneManager; | 
				
			||||
import engine.math.Bounds; | 
				
			||||
import engine.math.Vector3fImmutable; | 
				
			||||
import engine.mobileAI.Threads.MobAIThread; | 
				
			||||
import engine.net.client.msg.MoveToPointMsg; | 
				
			||||
import engine.objects.*; | 
				
			||||
import org.pmw.tinylog.Logger; | 
				
			||||
 | 
				
			||||
import java.util.ArrayList; | 
				
			||||
import java.util.concurrent.ThreadLocalRandom; | 
				
			||||
 | 
				
			||||
import static engine.math.FastMath.sqr; | 
				
			||||
import static engine.math.FastMath.sqrt; | 
				
			||||
 | 
				
			||||
public class MovementUtilities { | 
				
			||||
    private static final int cellGap = 1; | 
				
			||||
    private static final int stepHeight = 3; | 
				
			||||
 | 
				
			||||
    public static boolean inRangeOfBindLocation(Mob agent) { | 
				
			||||
 | 
				
			||||
 | 
				
			||||
        if (agent.isPlayerGuard()) { | 
				
			||||
 | 
				
			||||
            Mob guardCaptain = null; | 
				
			||||
            if (agent.getContract() != null) | 
				
			||||
                guardCaptain = agent; | 
				
			||||
            else | 
				
			||||
                guardCaptain = (Mob) agent.guardCaptain; | 
				
			||||
 | 
				
			||||
            if (guardCaptain != null) { | 
				
			||||
                Building barracks = guardCaptain.building; | 
				
			||||
 | 
				
			||||
                if (barracks != null) { | 
				
			||||
                    City city = barracks.getCity(); | 
				
			||||
 | 
				
			||||
                    if (city != null) { | 
				
			||||
                        Building tol = city.getTOL(); | 
				
			||||
 | 
				
			||||
                        //Guards recall distance = 814.
 | 
				
			||||
                        if (tol != null) { | 
				
			||||
                            return !(agent.getLoc().distanceSquared2D(tol.getLoc()) > sqr(Enum.CityBoundsType.ZONE.halfExtents)); | 
				
			||||
                        } | 
				
			||||
 | 
				
			||||
                    } | 
				
			||||
                } | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            return true; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        Vector3fImmutable sl = new Vector3fImmutable(agent.getLoc().getX(), 0, agent.getLoc().getZ()); | 
				
			||||
        Vector3fImmutable tl = new Vector3fImmutable(agent.getTrueBindLoc().x, 0, agent.getTrueBindLoc().z); | 
				
			||||
 | 
				
			||||
        float distanceSquaredToTarget = sl.distanceSquared2D(tl); //distance to center of target
 | 
				
			||||
        float zoneRange = 250; | 
				
			||||
 | 
				
			||||
        if (agent.getParentZone() != null) { | 
				
			||||
            if (agent.getParentZone().bounds != null) | 
				
			||||
                zoneRange = agent.getParentZone().bounds.getHalfExtents().x * 2; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (zoneRange > 300) | 
				
			||||
            zoneRange = 300; | 
				
			||||
 | 
				
			||||
        if (agent.getSpawnRadius() > zoneRange) | 
				
			||||
            zoneRange = agent.getSpawnRadius(); | 
				
			||||
 | 
				
			||||
 | 
				
			||||
        return distanceSquaredToTarget < sqr(MobAIThread.AI_DROP_AGGRO_RANGE + zoneRange); | 
				
			||||
 | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static boolean inRangeToAggro(Mob agent, PlayerCharacter target) { | 
				
			||||
 | 
				
			||||
        Vector3fImmutable sl = agent.getLoc(); | 
				
			||||
        Vector3fImmutable tl = target.getLoc(); | 
				
			||||
 | 
				
			||||
        float distanceSquaredToTarget = sl.distanceSquared2D(tl) - sqr(agent.calcHitBox() + target.calcHitBox()); //distance to center of target
 | 
				
			||||
        float range = MobAIThread.AI_BASE_AGGRO_RANGE; | 
				
			||||
 | 
				
			||||
        if (agent.isPlayerGuard()) | 
				
			||||
            range = 150; | 
				
			||||
 | 
				
			||||
        return distanceSquaredToTarget < sqr(range); | 
				
			||||
 | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static boolean inRangeDropAggro(Mob agent, AbstractCharacter target) { | 
				
			||||
        float range = MobAIThread.AI_BASE_AGGRO_RANGE * MobAIThread.AI_BASE_AGGRO_RANGE; | 
				
			||||
        if(agent.isPlayerGuard()) | 
				
			||||
            range = 62500; | 
				
			||||
        if(agent.isSiege()) | 
				
			||||
            range = agent.getRange() * agent.getRange(); | 
				
			||||
 | 
				
			||||
        return agent.loc.distanceSquared(target.loc) > range; | 
				
			||||
 | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static void moveToLocation(Mob agent, Vector3fImmutable newLocation, float offset, boolean isWalking) { | 
				
			||||
        try { | 
				
			||||
 | 
				
			||||
            //don't move farther than 30 units from player.
 | 
				
			||||
            if (offset > 30) | 
				
			||||
                offset = 30; | 
				
			||||
            Vector3fImmutable newLoc = Vector3fImmutable.getRandomPointInCircle(newLocation, offset); | 
				
			||||
 | 
				
			||||
 | 
				
			||||
            agent.setFaceDir(newLoc.subtract2D(agent.getLoc()).normalize()); | 
				
			||||
 | 
				
			||||
            aiMove(agent, newLoc, isWalking); | 
				
			||||
        } catch (Exception e) { | 
				
			||||
            Logger.error(e.toString()); | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static boolean canMove(Mob agent) { | 
				
			||||
        if (agent.getMobBase() != null && Enum.MobFlagType.SENTINEL.elementOf(agent.getMobBase().getFlags())) | 
				
			||||
            return false; | 
				
			||||
 | 
				
			||||
        return (agent.isAlive() && !agent.getBonuses().getBool(ModType.Stunned, SourceType.None) && !agent.getBonuses().getBool(ModType.CannotMove, SourceType.None)); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static void aiMove(Mob agent, Vector3fImmutable vect, boolean isWalking) { | 
				
			||||
 | 
				
			||||
        //update our walk/run state.
 | 
				
			||||
        if (isWalking && !agent.isWalk()) { | 
				
			||||
            agent.setWalkMode(true); | 
				
			||||
            MovementManager.sendRWSSMsg(agent); | 
				
			||||
        } else if (!isWalking && agent.isWalk()) { | 
				
			||||
            agent.setWalkMode(false); | 
				
			||||
            MovementManager.sendRWSSMsg(agent); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        MoveToPointMsg msg = new MoveToPointMsg(); | 
				
			||||
 | 
				
			||||
 | 
				
			||||
//		Regions currentRegion = Mob.InsideBuildingRegion(agent);
 | 
				
			||||
//
 | 
				
			||||
//		if (currentRegion != null){
 | 
				
			||||
//
 | 
				
			||||
//
 | 
				
			||||
//			if (currentRegion.isGroundLevel()){
 | 
				
			||||
//				agent.setInBuilding(0);
 | 
				
			||||
//				agent.setInFloorID(-1);
 | 
				
			||||
//			}else{
 | 
				
			||||
//				agent.setInBuilding(currentRegion.getLevel());
 | 
				
			||||
//				agent.setInFloorID(currentRegion.getRoom());
 | 
				
			||||
//			}
 | 
				
			||||
//		}else{
 | 
				
			||||
//			agent.setInBuilding(-1);
 | 
				
			||||
//			agent.setInFloorID(-1);
 | 
				
			||||
//			agent.setInBuildingID(0);
 | 
				
			||||
//		}
 | 
				
			||||
//		agent.setLastRegion(currentRegion);
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
        Vector3fImmutable startLoc = null; | 
				
			||||
        Vector3fImmutable endLoc = null; | 
				
			||||
 | 
				
			||||
//		if (agent.getLastRegion() != null){
 | 
				
			||||
//			Building inBuilding = Building.getBuildingFromCache(agent.getInBuildingID());
 | 
				
			||||
//			if (inBuilding != null){
 | 
				
			||||
//				startLoc = ZoneManager.convertWorldToLocal(inBuilding, agent.getLoc());
 | 
				
			||||
//				endLoc = ZoneManager.convertWorldToLocal(inBuilding, vect);
 | 
				
			||||
//			}
 | 
				
			||||
//		}else{
 | 
				
			||||
//			agent.setBuildingID(0);
 | 
				
			||||
//			agent.setInBuildingID(0);
 | 
				
			||||
//			startLoc = agent.getLoc();
 | 
				
			||||
//			endLoc = vect;
 | 
				
			||||
//		}
 | 
				
			||||
 | 
				
			||||
        startLoc = agent.getLoc(); | 
				
			||||
        endLoc = vect; | 
				
			||||
 | 
				
			||||
        msg.setSourceType(GameObjectType.Mob.ordinal()); | 
				
			||||
        msg.setSourceID(agent.getObjectUUID()); | 
				
			||||
        msg.setStartCoord(startLoc); | 
				
			||||
        msg.setEndCoord(endLoc); | 
				
			||||
        msg.setInBuildingFloor(-1); | 
				
			||||
        msg.setInBuilding(-1); | 
				
			||||
        msg.setStartLocType(0); | 
				
			||||
        msg.setInBuildingUUID(0); | 
				
			||||
 | 
				
			||||
 | 
				
			||||
        try { | 
				
			||||
            MovementManager.movement(msg, agent); | 
				
			||||
        } catch (MsgSendException e) { | 
				
			||||
            // TODO Figure out how we want to handle the msg send exception
 | 
				
			||||
            e.printStackTrace(); | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static Vector3fImmutable GetDestinationToCharacter(Mob aiAgent, AbstractCharacter character) { | 
				
			||||
 | 
				
			||||
        if (!character.isMoving()) | 
				
			||||
            return character.getLoc(); | 
				
			||||
 | 
				
			||||
 | 
				
			||||
        float agentDistanceEndLoc = aiAgent.getLoc().distanceSquared2D(character.getEndLoc()); | 
				
			||||
        float characterDistanceEndLoc = character.getLoc().distanceSquared2D(character.getEndLoc()); | 
				
			||||
 | 
				
			||||
        if (agentDistanceEndLoc > characterDistanceEndLoc) | 
				
			||||
            return character.getEndLoc(); | 
				
			||||
 | 
				
			||||
        return character.getLoc(); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static void pathfind(AbstractCharacter character, Vector3fImmutable goal){ | 
				
			||||
        try { | 
				
			||||
 | 
				
			||||
            //if(character.region == null && Regions.getRegionAtLocation(goal) != null) {//mover not inside a building
 | 
				
			||||
             //   Building building = BuildingManager.getBuildingAtLocation(goal);
 | 
				
			||||
               // ArrayList<Regions> entrances = new ArrayList<>();
 | 
				
			||||
                //for (Regions region : building.getBounds().getRegions()) {
 | 
				
			||||
                //    if (region.exit && region.level == 0)
 | 
				
			||||
                //        entrances.add(region);
 | 
				
			||||
                //}
 | 
				
			||||
 //                   Regions cheapest = null;
 | 
				
			||||
 //                   for(Regions entrance : entrances){
 | 
				
			||||
 //                       if(cheapest == null) {
 | 
				
			||||
 //                           cheapest = entrance;
 | 
				
			||||
 //                           continue;
 | 
				
			||||
 //                       }
 | 
				
			||||
//                        if(getCost(new Vector3fImmutable(entrance.center),character.loc,goal) < getCost(new Vector3fImmutable(cheapest.center),character.loc,goal))
 | 
				
			||||
//                            cheapest = entrance;
 | 
				
			||||
//                    }
 | 
				
			||||
//
 | 
				
			||||
//                    goal = new Vector3fImmutable(cheapest.center.x, cheapest.center.y, cheapest.center.z);
 | 
				
			||||
 | 
				
			||||
            //}
 | 
				
			||||
 | 
				
			||||
            ArrayList<Vector3fImmutable> path = getOptimizedPath(getPath(character.loc, goal), getPath(goal, character.loc)); | 
				
			||||
            if (path.isEmpty()) { | 
				
			||||
                ((Mob) character).destination = goal; | 
				
			||||
                return; //no points to walk to
 | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            ((Mob) character).destination = path.get(0); | 
				
			||||
 | 
				
			||||
        } catch(Exception e){ | 
				
			||||
            //something failed
 | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static ArrayList<Vector3fImmutable> getOptimizedPath(ArrayList<Vector3fImmutable> startToGoal, ArrayList<Vector3fImmutable> goalToStart) { | 
				
			||||
        ArrayList<Vector3fImmutable> optimalPath = new ArrayList<>(); | 
				
			||||
        optimalPath.add(startToGoal.get(0)); | 
				
			||||
        for(Vector3fImmutable point : startToGoal) | 
				
			||||
        { | 
				
			||||
            if(!goalToStart.contains(point)) | 
				
			||||
            { | 
				
			||||
                continue; | 
				
			||||
            } | 
				
			||||
            optimalPath.add(point); | 
				
			||||
        } | 
				
			||||
        return optimalPath; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    private static ArrayList<Vector3fImmutable> getPath(Vector3fImmutable start, Vector3fImmutable goal) { | 
				
			||||
        ArrayList<Vector3fImmutable> path = new ArrayList<>(); | 
				
			||||
        path.add(start); | 
				
			||||
        Vector3fImmutable current = start; | 
				
			||||
        boolean obstructed = false; | 
				
			||||
        int count = 0; | 
				
			||||
        while (current.distanceSquared(goal) > 9 && count < 250) | 
				
			||||
        { | 
				
			||||
            //gather the 8 cells around the player
 | 
				
			||||
            ArrayList<Vector3fImmutable> surroundingCells = new ArrayList<>(); | 
				
			||||
            surroundingCells.add(current.add(new Vector3fImmutable(cellGap, 0, 0))); | 
				
			||||
            surroundingCells.add(current.add(new Vector3fImmutable(cellGap, 0, cellGap))); | 
				
			||||
            surroundingCells.add(current.add(new Vector3fImmutable(0, 0, cellGap))); | 
				
			||||
            surroundingCells.add(current.add(new Vector3fImmutable(-cellGap, 0, 0))); | 
				
			||||
            surroundingCells.add(current.add(new Vector3fImmutable(-cellGap, 0, -cellGap))); | 
				
			||||
            surroundingCells.add(current.add(new Vector3fImmutable(0, 0, -cellGap))); | 
				
			||||
            surroundingCells.add(current.add(new Vector3fImmutable(-cellGap, 0, cellGap))); | 
				
			||||
            surroundingCells.add(current.add(new Vector3fImmutable(cellGap, 0, -cellGap))); | 
				
			||||
            Vector3fImmutable cheapest = new Vector3fImmutable(Vector3fImmutable.ZERO); | 
				
			||||
            for (Vector3fImmutable point : surroundingCells) | 
				
			||||
            { | 
				
			||||
                count++; | 
				
			||||
 | 
				
			||||
                if (path.contains(point)) | 
				
			||||
                    continue; | 
				
			||||
 | 
				
			||||
                if (pointIsBlocked(point)) { | 
				
			||||
                    obstructed = true; | 
				
			||||
                    continue; | 
				
			||||
                } | 
				
			||||
                Building building = BuildingManager.getBuildingAtLocation(point); | 
				
			||||
                Regions region = null; | 
				
			||||
                if(building != null) | 
				
			||||
                    for(Regions reg : building.getBounds().getRegions()) | 
				
			||||
                        if(reg.isPointInPolygon(point)) | 
				
			||||
                            region = reg; | 
				
			||||
 | 
				
			||||
                if(region != null) | 
				
			||||
                    point = new Vector3fImmutable(point.x,region.lerpY(point),point.z); // adjust the Y value of the point to the region height it is in
 | 
				
			||||
                else | 
				
			||||
                    point = new Vector3fImmutable(point.x, Terrain.getWorldHeight(point),point.z); | 
				
			||||
 | 
				
			||||
                if (getCost(cheapest, current, goal) > getCost(point, current, goal)) | 
				
			||||
                    cheapest = point; | 
				
			||||
 | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            current = cheapest; | 
				
			||||
            path.add(cheapest); | 
				
			||||
        } | 
				
			||||
        if(obstructed) { | 
				
			||||
            return path; | 
				
			||||
        }else { | 
				
			||||
            ArrayList<Vector3fImmutable> goalPath = new ArrayList<>(); | 
				
			||||
            goalPath.add(goal); | 
				
			||||
            goalPath.add(start); | 
				
			||||
            return goalPath; //if the path isn't obstructed we can walk directly from start to the goal
 | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static float getCost(Vector3fImmutable point, Vector3fImmutable start, Vector3fImmutable goal) { | 
				
			||||
        float gCost = start.distanceSquared(point); | 
				
			||||
        float hCost = goal.distanceSquared(point); | 
				
			||||
        return gCost + hCost; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static boolean pointIsBlocked(Vector3fImmutable point) { | 
				
			||||
 | 
				
			||||
        Building building = BuildingManager.getBuildingAtLocation(point); | 
				
			||||
        if(building == null) | 
				
			||||
            return false;//no building at this location means nothing obstructing the walking path
 | 
				
			||||
 | 
				
			||||
        Regions region = Regions.getRegionAtLocation(point); | 
				
			||||
        if(region != null && Math.abs(region.lerpY(point) - point.y) < stepHeight) { | 
				
			||||
            return false; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        Zone currentZone = ZoneManager.findSmallestZone(point); | 
				
			||||
        if(currentZone == null) | 
				
			||||
            return false; | 
				
			||||
        else | 
				
			||||
            return currentZone.navMesh.contains(point.x,point.z); | 
				
			||||
        //return false;
 | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
} | 
				
			||||
@ -0,0 +1,80 @@
				@@ -0,0 +1,80 @@
					 | 
				
			||||
package engine.mobileAI.utilities; | 
				
			||||
import engine.objects.Regions; | 
				
			||||
import java.awt.geom.Area; | 
				
			||||
import java.util.ArrayList; | 
				
			||||
 | 
				
			||||
public class PathingUtilities { | 
				
			||||
    public static class Point { | 
				
			||||
        public int x; | 
				
			||||
        public int y; | 
				
			||||
        public Point previous; | 
				
			||||
 | 
				
			||||
        public Point(int x, int y, Point previous) { | 
				
			||||
            this.x = x; | 
				
			||||
            this.y = y; | 
				
			||||
            this.previous = previous; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        public Point offset(int ox, int oy) { return new Point(x + ox, y + oy, this);  } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static boolean IsWalkable(Area navMesh, Point point) { | 
				
			||||
        if (navMesh.contains(point.x, point.y)) | 
				
			||||
            return true; | 
				
			||||
 | 
				
			||||
        Regions region = Regions.getRegionAtPoint(point); | 
				
			||||
        if (region != null) { | 
				
			||||
            return !(region.getHeightAtPoint(point) - point.y > 2); | 
				
			||||
        } | 
				
			||||
        return false; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static ArrayList<Point> FindNeighbors(Area navMesh, Point point) { | 
				
			||||
        ArrayList<Point> neighbors = new ArrayList<>(); | 
				
			||||
        Point up = point.offset(0,  1); | 
				
			||||
        Point down = point.offset(0,  -1); | 
				
			||||
        Point left = point.offset(-1, 0); | 
				
			||||
        Point right = point.offset(1, 0); | 
				
			||||
        if (IsWalkable(navMesh, up)) neighbors.add(up); | 
				
			||||
        if (IsWalkable(navMesh, down)) neighbors.add(down); | 
				
			||||
        if (IsWalkable(navMesh, left)) neighbors.add(left); | 
				
			||||
        if (IsWalkable(navMesh, right)) neighbors.add(right); | 
				
			||||
        return neighbors; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static ArrayList<Point> FindPath(Area navMesh, Point start, Point end) { | 
				
			||||
        boolean finished = false; | 
				
			||||
        ArrayList<Point> used = new ArrayList<>(); | 
				
			||||
        used.add(start); | 
				
			||||
        while (!finished) { | 
				
			||||
            ArrayList<Point> newOpen = new ArrayList<>(); | 
				
			||||
            for(int i = 0; i < used.size(); ++i){ | 
				
			||||
                Point point = used.get(i); | 
				
			||||
                for (Point neighbor : FindNeighbors(navMesh, point)) { | 
				
			||||
                    if (!used.contains(neighbor) && !newOpen.contains(neighbor)) { | 
				
			||||
                        newOpen.add(neighbor); | 
				
			||||
                    } | 
				
			||||
                } | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            for(Point point : newOpen) { | 
				
			||||
                used.add(point); | 
				
			||||
                if (end.equals(point)) { | 
				
			||||
                    finished = true; | 
				
			||||
                    break; | 
				
			||||
                } | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if (!finished && newOpen.isEmpty()) | 
				
			||||
                return null; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        ArrayList<Point> path = new ArrayList<>(); | 
				
			||||
        Point point = used.get(used.size() - 1); | 
				
			||||
        while(point.previous != null) { | 
				
			||||
            path.add(0, point); | 
				
			||||
            point = point.previous; | 
				
			||||
        } | 
				
			||||
        return path; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
					Loading…
					
					
				
		Reference in new issue