Minor command AI improvements
This commit is contained in:
@@ -11,14 +11,16 @@ import mindustry.gen.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
public class CommandAI extends AIController{
|
||||
private static final float localInterval = 30f;
|
||||
private static final Vec2 vecOut = new Vec2();
|
||||
private static final float localInterval = 40f;
|
||||
private static final Vec2 vecOut = new Vec2(), flockVec = new Vec2(), separation = new Vec2(), cohesion = new Vec2(), massCenter = new Vec2();
|
||||
|
||||
public @Nullable Vec2 targetPos;
|
||||
public @Nullable Teamc attackTarget;
|
||||
|
||||
private Vec2 lastTargetPos;
|
||||
private int pathId = -1;
|
||||
private Seq<Unit> local = new Seq<>(false);
|
||||
private boolean flocked;
|
||||
|
||||
@Override
|
||||
public void updateUnit(){
|
||||
@@ -31,18 +33,28 @@ public class CommandAI extends AIController{
|
||||
}
|
||||
|
||||
if(targetPos != null){
|
||||
if(timer.get(timerTarget3, localInterval)){
|
||||
if(timer.get(timerTarget3, localInterval) || !flocked){
|
||||
if(!flocked){
|
||||
//make sure updates are staggered randomly
|
||||
timer.reset(timerTarget3, Mathf.random(localInterval));
|
||||
}
|
||||
|
||||
local.clear();
|
||||
//TODO experiment with 2/3/4
|
||||
float size = unit.hitSize * 3f;
|
||||
unit.team.data().tree().intersect(unit.x - size / 2f, unit.y - size/2f, size, size, local);
|
||||
local.remove(unit);
|
||||
flocked = true;
|
||||
}
|
||||
}else{
|
||||
//make sure updates are staggered randomly
|
||||
timer.reset(timerTarget3, Mathf.random(localInterval));
|
||||
flocked = false;
|
||||
}
|
||||
|
||||
if(attackTarget != null){
|
||||
if(targetPos == null) targetPos = new Vec2();
|
||||
if(targetPos == null){
|
||||
targetPos = new Vec2();
|
||||
lastTargetPos = targetPos;
|
||||
}
|
||||
targetPos.set(attackTarget);
|
||||
|
||||
if(unit.isGrounded() && attackTarget instanceof Building build && build.tile.solid() && unit.pathType() != Pathfinder.costLegs){
|
||||
@@ -68,7 +80,9 @@ public class CommandAI extends AIController{
|
||||
attackTarget != null && unit.within(attackTarget, engageRange) ? engageRange :
|
||||
unit.isGrounded() ? 0f :
|
||||
attackTarget != null ? engageRange :
|
||||
0f, 100f, false);
|
||||
0f, 100f, false, null);
|
||||
|
||||
//calculateFlock().limit(unit.speed() * flockMult)
|
||||
}
|
||||
|
||||
if(unit.isFlying()){
|
||||
@@ -77,14 +91,75 @@ public class CommandAI extends AIController{
|
||||
faceTarget();
|
||||
}
|
||||
|
||||
if(attackTarget == null && unit.within(targetPos, Math.max(5f, unit.hitSize / 2.5f))){
|
||||
targetPos = null;
|
||||
if(attackTarget == null){
|
||||
if(unit.within(targetPos, Math.max(5f, unit.hitSize / 2f))){
|
||||
targetPos = null;
|
||||
}else if(local.size > 1){
|
||||
int count = 0;
|
||||
for(var near : local){
|
||||
//has arrived
|
||||
if(near.isCommandable() && !near.command().hasCommand() && targetPos.equals(near.command().lastTargetPos)){
|
||||
count ++;
|
||||
}
|
||||
}
|
||||
|
||||
//others have arrived at destination, so this one will too
|
||||
if(count >= Math.max(2, local.size / 3)){
|
||||
targetPos = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}else if(target != null){
|
||||
faceTarget();
|
||||
}
|
||||
}
|
||||
|
||||
public static float cohesionScl = 0.3f;
|
||||
public static float cohesionRad = 3f, separationRad = 1.1f, separationScl = 1f, flockMult = 0.5f;
|
||||
|
||||
//TODO ひどい
|
||||
Vec2 calculateFlock(){
|
||||
if(local.isEmpty()) return flockVec.setZero();
|
||||
|
||||
flockVec.setZero();
|
||||
separation.setZero();
|
||||
cohesion.setZero();
|
||||
massCenter.set(unit);
|
||||
|
||||
float rad = unit.hitSize;
|
||||
float sepDst = rad * separationRad, cohDst = rad * cohesionRad;
|
||||
|
||||
//"cohesed" isn't even a word smh
|
||||
int separated = 0, cohesed = 1;
|
||||
|
||||
for(var other : local){
|
||||
float dst = other.dst(unit);
|
||||
if(dst < sepDst){
|
||||
separation.add(Tmp.v1.set(unit).sub(other).scl(1f / sepDst));
|
||||
separated ++;
|
||||
}
|
||||
|
||||
if(dst < cohDst){
|
||||
massCenter.add(other);
|
||||
cohesed ++;
|
||||
}
|
||||
}
|
||||
|
||||
if(separated > 0){
|
||||
separation.scl(1f / separated);
|
||||
flockVec.add(separation.scl(separationScl));
|
||||
}
|
||||
|
||||
if(cohesed > 1){
|
||||
massCenter.scl(1f / cohesed);
|
||||
flockVec.add(Tmp.v1.set(massCenter).sub(unit).limit(cohesionScl * unit.type.speed));
|
||||
//seek mass center?
|
||||
}
|
||||
|
||||
return flockVec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keepState(){
|
||||
return true;
|
||||
@@ -107,6 +182,7 @@ public class CommandAI extends AIController{
|
||||
|
||||
public void commandPosition(Vec2 pos){
|
||||
targetPos = pos;
|
||||
lastTargetPos = pos;
|
||||
attackTarget = null;
|
||||
pathId = Vars.controlPath.nextTargetId();
|
||||
}
|
||||
|
||||
@@ -256,10 +256,10 @@ public class AIController implements UnitController{
|
||||
}
|
||||
|
||||
public void moveTo(Position target, float circleLength, float smooth){
|
||||
moveTo(target, circleLength, smooth, unit.isFlying());
|
||||
moveTo(target, circleLength, smooth, unit.isFlying(), null);
|
||||
}
|
||||
|
||||
public void moveTo(Position target, float circleLength, float smooth, boolean keepDistance){
|
||||
public void moveTo(Position target, float circleLength, float smooth, boolean keepDistance, @Nullable Vec2 offset){
|
||||
if(target == null) return;
|
||||
|
||||
vec.set(target).sub(unit);
|
||||
@@ -267,6 +267,7 @@ public class AIController implements UnitController{
|
||||
float length = circleLength <= 0.001f ? 1f : Mathf.clamp((unit.dst(target) - circleLength) / smooth, -1f, 1f);
|
||||
|
||||
vec.setLength(unit.speed() * length);
|
||||
|
||||
if(length < -0.5f){
|
||||
if(keepDistance){
|
||||
vec.rotate(180f);
|
||||
@@ -277,6 +278,11 @@ public class AIController implements UnitController{
|
||||
vec.setZero();
|
||||
}
|
||||
|
||||
if(offset != null){
|
||||
vec.add(offset);
|
||||
vec.setLength(unit.speed() * length);
|
||||
}
|
||||
|
||||
//do not move when infinite vectors are used.
|
||||
if(vec.isNaN() || vec.isInfinite()) return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user