|
|
@ -13,21 +13,27 @@ import engine.Enum; |
|
|
|
import engine.Enum.GameObjectType; |
|
|
|
import engine.Enum.GameObjectType; |
|
|
|
import engine.Enum.ModType; |
|
|
|
import engine.Enum.ModType; |
|
|
|
import engine.Enum.SourceType; |
|
|
|
import engine.Enum.SourceType; |
|
|
|
|
|
|
|
import engine.InterestManagement.WorldGrid; |
|
|
|
import engine.exception.MsgSendException; |
|
|
|
import engine.exception.MsgSendException; |
|
|
|
|
|
|
|
import engine.gameManager.BuildingManager; |
|
|
|
|
|
|
|
import engine.gameManager.ChatManager; |
|
|
|
import engine.gameManager.MovementManager; |
|
|
|
import engine.gameManager.MovementManager; |
|
|
|
|
|
|
|
import engine.math.Bounds; |
|
|
|
import engine.math.Vector3fImmutable; |
|
|
|
import engine.math.Vector3fImmutable; |
|
|
|
import engine.mobileAI.Threads.MobAIThread; |
|
|
|
import engine.mobileAI.Threads.MobAIThread; |
|
|
|
import engine.net.client.msg.MoveToPointMsg; |
|
|
|
import engine.net.client.msg.MoveToPointMsg; |
|
|
|
import engine.objects.*; |
|
|
|
import engine.objects.*; |
|
|
|
|
|
|
|
import engine.server.MBServerStatics; |
|
|
|
import org.pmw.tinylog.Logger; |
|
|
|
import org.pmw.tinylog.Logger; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.concurrent.ThreadLocalRandom; |
|
|
|
import java.util.concurrent.ThreadLocalRandom; |
|
|
|
|
|
|
|
|
|
|
|
import static engine.math.FastMath.sqr; |
|
|
|
import static engine.math.FastMath.sqr; |
|
|
|
import static engine.math.FastMath.sqrt; |
|
|
|
import static engine.math.FastMath.sqrt; |
|
|
|
|
|
|
|
|
|
|
|
public class MovementUtilities { |
|
|
|
public class MovementUtilities { |
|
|
|
|
|
|
|
private static final int cellGap = 4; |
|
|
|
|
|
|
|
|
|
|
|
public static boolean inRangeOfBindLocation(Mob agent) { |
|
|
|
public static boolean inRangeOfBindLocation(Mob agent) { |
|
|
|
|
|
|
|
|
|
|
@ -291,5 +297,129 @@ public class MovementUtilities { |
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public static void pathfind(AbstractCharacter character, Vector3fImmutable goal){ |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
ArrayList<Vector3fImmutable> path = getOptimizedPath(getPath(character.loc, goal), getPath(goal, character.loc)); |
|
|
|
|
|
|
|
if (path.isEmpty()) { |
|
|
|
|
|
|
|
((Mob) character).setDestination(character.loc); |
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
while (current.distanceSquared(goal) > 9) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
//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(-10000, 0, -10000); |
|
|
|
|
|
|
|
for (Vector3fImmutable point : surroundingCells) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (path.contains(point)) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Regions region = Regions.getRegionAtLocation(point); |
|
|
|
|
|
|
|
if(region != null) { |
|
|
|
|
|
|
|
//if (!region.stairs)
|
|
|
|
|
|
|
|
// point.setY(region.center.y);
|
|
|
|
|
|
|
|
//else
|
|
|
|
|
|
|
|
// point.setY(region.lerpY(point));
|
|
|
|
|
|
|
|
path.add(new Vector3fImmutable(region.center.x,region.center.y,region.center.z)); //only use center points when travelling through regions
|
|
|
|
|
|
|
|
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(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) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//TODO figure out best way to decide if a walking point intersects a mesh collider from a building
|
|
|
|
|
|
|
|
Building building = BuildingManager.getBuildingAtLocation(point); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(building == null) { |
|
|
|
|
|
|
|
printToPlayers(point, "No Building Found At: " + point); |
|
|
|
|
|
|
|
return false;//no building at this location means nothing obstructing the walking path
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!collidesWithBuilding(building,point)) { |
|
|
|
|
|
|
|
printToPlayers(point, "No Building Collision At: " + point); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(Regions.getRegionAtLocation(point) != null) { |
|
|
|
|
|
|
|
printToPlayers(point, "Region Found At: " + point); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
printToPlayers(point, "Path Blocked At: " + point); |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static boolean collidesWithBuilding(Building building, Vector3fImmutable end){ |
|
|
|
|
|
|
|
MeshBounds mb = Bounds.meshBoundsCache.get(building.meshUUID); |
|
|
|
|
|
|
|
return (end.x > mb.minX && end.x < mb.maxX && end.z > mb.minZ && end.z < mb.maxZ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static void printToPlayers(Vector3fImmutable loc, String message){ |
|
|
|
|
|
|
|
for(AbstractWorldObject awo : WorldGrid.getObjectsInRangePartial(loc, MBServerStatics.CHARACTER_LOAD_RANGE, MBServerStatics.MASK_PLAYER)){ |
|
|
|
|
|
|
|
PlayerCharacter pc = (PlayerCharacter)awo; |
|
|
|
|
|
|
|
ChatManager.chatSystemInfo(pc, message); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|