forked from MagicBane/Server
system enabled
This commit is contained in:
@@ -287,10 +287,10 @@ public class MobAI {
|
||||
|
||||
if (mob.agentType.equals(Enum.AIAgentType.GUARDMINION)) {
|
||||
Mob captain = (Mob) mob.guardCaptain;
|
||||
mob.destination = captain.destination.add(Formation.getOffset(2, mob.guardCaptain.minions.indexOf(mob.getObjectUUID()) + 3));
|
||||
mob.setDestination(captain.destination.add(Formation.getOffset(2, mob.guardCaptain.minions.indexOf(mob.getObjectUUID()) + 3)));
|
||||
mob.lastPatrolPointIndex = captain.lastPatrolPointIndex;
|
||||
} else {
|
||||
mob.destination = mob.patrolPoints.get(mob.lastPatrolPointIndex);
|
||||
mob.setDestination(mob.patrolPoints.get(mob.lastPatrolPointIndex));
|
||||
mob.lastPatrolPointIndex += 1;
|
||||
}
|
||||
|
||||
@@ -748,7 +748,7 @@ public class MobAI {
|
||||
if (CombatUtilities.inRange2D(mob, mob.guardCaptain, 6))
|
||||
return;
|
||||
|
||||
mob.destination = mob.guardCaptain.getLoc();
|
||||
mob.setDestination(mob.guardCaptain.getLoc());
|
||||
MovementUtilities.moveToLocation(mob, mob.destination, 5, false);
|
||||
} else
|
||||
chaseTarget(mob);
|
||||
@@ -904,7 +904,7 @@ public class MobAI {
|
||||
|
||||
if (CombatUtilities.inRange2D(mob, mob.getCombatTarget(), mob.getRange()) == false) {
|
||||
if (mob.getRange() > 15) {
|
||||
mob.destination = mob.getCombatTarget().getLoc();
|
||||
mob.setDestination(mob.getCombatTarget().getLoc());
|
||||
MovementUtilities.moveToLocation(mob, mob.destination, 0, false);
|
||||
} else {
|
||||
|
||||
@@ -913,11 +913,11 @@ public class MobAI {
|
||||
switch (mob.getCombatTarget().getObjectType()) {
|
||||
case PlayerCharacter:
|
||||
case Mob:
|
||||
mob.destination = MovementUtilities.GetDestinationToCharacter(mob, (AbstractCharacter) mob.getCombatTarget());
|
||||
mob.setDestination(MovementUtilities.GetDestinationToCharacter(mob, (AbstractCharacter) mob.getCombatTarget()));
|
||||
MovementUtilities.moveToLocation(mob, mob.destination, mob.getRange() + 1, false);
|
||||
break;
|
||||
case Building:
|
||||
mob.destination = mob.getCombatTarget().getLoc();
|
||||
mob.setDestination(mob.getCombatTarget().getLoc());
|
||||
MovementUtilities.moveToLocation(mob, mob.getCombatTarget().getLoc(), 0, false);
|
||||
break;
|
||||
}
|
||||
@@ -1240,7 +1240,7 @@ public class MobAI {
|
||||
float xPoint = ThreadLocalRandom.current().nextInt(400) - 200;
|
||||
float zPoint = ThreadLocalRandom.current().nextInt(400) - 200;
|
||||
Vector3fImmutable TreePos = mob.getGuild().getOwnedCity().getLoc();
|
||||
mob.destination = new Vector3fImmutable(TreePos.x + xPoint, TreePos.y, TreePos.z + zPoint);
|
||||
mob.setDestination(new Vector3fImmutable(TreePos.x + xPoint, TreePos.y, TreePos.z + zPoint));
|
||||
|
||||
MovementUtilities.aiMove(mob, mob.destination, true);
|
||||
|
||||
|
||||
@@ -13,21 +13,27 @@ import engine.Enum;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.Enum.ModType;
|
||||
import engine.Enum.SourceType;
|
||||
import engine.InterestManagement.WorldGrid;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.MovementManager;
|
||||
import engine.math.Bounds;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.mobileAI.Threads.MobAIThread;
|
||||
import engine.net.client.msg.MoveToPointMsg;
|
||||
import engine.objects.*;
|
||||
import engine.server.MBServerStatics;
|
||||
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 = 4;
|
||||
|
||||
public static boolean inRangeOfBindLocation(Mob agent) {
|
||||
|
||||
@@ -291,5 +297,129 @@ public class MovementUtilities {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -987,18 +987,7 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
|
||||
@Override
|
||||
public final void setLoc(final Vector3fImmutable value) {
|
||||
|
||||
Building building = BuildingManager.getBuildingAtLocation(this.loc);
|
||||
Regions region = null;
|
||||
if(building != null) {
|
||||
//look for region in the building we are in
|
||||
for (Regions regionCycle : building.getBounds().getRegions()) {
|
||||
float regionHeight = regionCycle.highLerp.y - regionCycle.lowLerp.y;
|
||||
if(regionHeight < 10)
|
||||
regionHeight = 10;
|
||||
if (regionCycle.isPointInPolygon(value) && Math.abs(regionCycle.highLerp.y - value.y) < regionHeight)
|
||||
region = regionCycle;
|
||||
}
|
||||
}
|
||||
Regions region = Regions.getRegionAtLocation(value);
|
||||
float regionHeightOffset = 0;
|
||||
if(region != null){
|
||||
this.region = region;
|
||||
|
||||
@@ -20,6 +20,7 @@ import engine.jobs.DeferredPowerJob;
|
||||
import engine.jobs.UpgradeNPCJob;
|
||||
import engine.math.Bounds;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.mobileAI.utilities.MovementUtilities;
|
||||
import engine.net.ByteBufferWriter;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
@@ -1899,4 +1900,6 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed {
|
||||
public int compareTo(@NotNull Delayed o) {
|
||||
return toIntExact(this.respawnTime - ((Mob) o).respawnTime);
|
||||
}
|
||||
|
||||
public void setDestination(Vector3fImmutable destination) {MovementUtilities.pathfind(this,destination);}
|
||||
}
|
||||
|
||||
@@ -270,32 +270,18 @@ public class Regions {
|
||||
return BuildingManager.getBuildingFromCache(region.parentBuildingID);
|
||||
}
|
||||
|
||||
public static Regions GetRegionForTeleport(Vector3fImmutable location) {
|
||||
public static Regions getRegionAtLocation(Vector3fImmutable location) {
|
||||
Regions region = null;
|
||||
|
||||
|
||||
//Find building
|
||||
for (AbstractWorldObject awo : WorldGrid.getObjectsInRangePartial(location, 128, MBServerStatics.MASK_BUILDING)) {
|
||||
Building building = (Building) awo;
|
||||
if (!Bounds.collide(location, building.getBounds()))
|
||||
continue;
|
||||
if(building != null) {
|
||||
region = BuildingManager.GetRegion(building, location.x, location.y, location.z);
|
||||
Building building = BuildingManager.getBuildingAtLocation(location);
|
||||
if(building != null) {
|
||||
//look for region in the building we are in
|
||||
for (Regions regionCycle : building.getBounds().getRegions()) {
|
||||
float regionHeight = regionCycle.highLerp.y - regionCycle.lowLerp.y;
|
||||
if(regionHeight < 10)
|
||||
regionHeight = 10;
|
||||
if (regionCycle.isPointInPolygon(location) && Math.abs(regionCycle.highLerp.y - location.y) < regionHeight)
|
||||
region = regionCycle;
|
||||
}
|
||||
//find regions that intersect x and z, check if object can enter.
|
||||
//for (Regions toEnter : building.getBounds().getRegions()) {
|
||||
// if (toEnter.isPointInPolygon(location)) {
|
||||
|
||||
// if (region == null)
|
||||
// region = toEnter;
|
||||
// else // we're using a low level to high level tree structure, database not always in order low to high.
|
||||
//check for highest level index.
|
||||
// if (region != null && toEnter.highLerp.y > region.highLerp.y)
|
||||
// region = toEnter;
|
||||
|
||||
|
||||
// }
|
||||
// }
|
||||
}
|
||||
return region;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ public class TeleportPowerAction extends AbstractPowerAction {
|
||||
|
||||
//TODO verify target loc is valid loc
|
||||
|
||||
Regions region = Regions.GetRegionForTeleport(targetLoc);
|
||||
Regions region = Regions.getRegionAtLocation(targetLoc);
|
||||
|
||||
if (region != null && !region.isOutside())
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user