diff --git a/core/src/mindustry/ai/types/DefenderAI.java b/core/src/mindustry/ai/types/DefenderAI.java new file mode 100644 index 0000000000..04cc59435d --- /dev/null +++ b/core/src/mindustry/ai/types/DefenderAI.java @@ -0,0 +1,34 @@ +package mindustry.ai.types; + +import arc.math.*; +import mindustry.entities.*; +import mindustry.entities.Units.*; +import mindustry.entities.units.*; +import mindustry.gen.*; +import mindustry.world.meta.*; + +public class DefenderAI extends AIController{ + + @Override + public void updateMovement(){ + if(target != null){ + moveTo(target, unit.range(), 5f); + unit.lookAt(target); + }else{ + Teamc block = targetFlag(unit.x, unit.y, BlockFlag.rally, false); + if(block == null) block = unit.closestCore(); + moveTo(block, 60f); + } + } + + @Override + protected void updateTargeting(){ + if(retarget()) target = findTarget(unit.x, unit.y, 0f, true, true); + } + + @Override + protected Teamc findTarget(float x, float y, float range, boolean air, boolean ground){ + //Sort by max health and closer target. + return Units.closest(unit.team, x, y, u -> !u.dead() && u.type != unit.type, (u, tx, ty) -> -u.maxHealth + Mathf.dst2(u.x, u.y, tx, ty) / 800f); + } +} diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index c53770e0fc..7f4ae97766 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -1370,6 +1370,8 @@ public class UnitTypes implements ContentList{ }}; oct = new UnitType("oct"){{ + defaultController = DefenderAI::new; + armor = 16f; health = 24000; speed = 0.8f; diff --git a/core/src/mindustry/entities/Units.java b/core/src/mindustry/entities/Units.java index 970374811b..0b0538adb6 100644 --- a/core/src/mindustry/entities/Units.java +++ b/core/src/mindustry/entities/Units.java @@ -248,7 +248,7 @@ public class Units{ return result; } - /** Returns the closest ally of this team. Filter by predicate. */ + /** Returns the closest ally of this team in a range. Filter by predicate. */ public static Unit closest(Team team, float x, float y, float range, Boolf predicate){ result = null; cdist = 0f; @@ -266,6 +266,24 @@ public class Units{ return result; } + /** Returns the closest ally of this team using a custom comparison function. Filter by predicate. */ + public static Unit closest(Team team, float x, float y, Boolf predicate, Sortf sort){ + result = null; + cdist = 0f; + + for(Unit e : Groups.unit){ + if(!predicate.get(e) || e.team() != team) continue; + + float cost = sort.cost(e, x, y); + if(result == null || cost < cdist){ + result = e; + cdist = cost; + } + } + + return result; + } + /** Returns the closest ally of this team. Filter by predicate. * Unlike the closest() function, this only guarantees that unit hitboxes overlap the range. */ public static Unit closestOverlap(Team team, float x, float y, float range, Boolf predicate){