Minor command AI improvements

This commit is contained in:
Anuken
2022-02-18 16:35:29 -05:00
parent 9c1cb64c77
commit bc8842d0d7
3 changed files with 94 additions and 12 deletions

View File

@@ -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();
}

View File

@@ -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;