diff --git a/core/src/mindustry/ai/types/DefenderAI.java b/core/src/mindustry/ai/types/DefenderAI.java index 93040727e0..3f7915e68e 100644 --- a/core/src/mindustry/ai/types/DefenderAI.java +++ b/core/src/mindustry/ai/types/DefenderAI.java @@ -6,10 +6,14 @@ import mindustry.entities.units.*; import mindustry.gen.*; import mindustry.world.meta.*; +import static mindustry.Vars.*; + public class DefenderAI extends AIController{ @Override public void updateMovement(){ + unloadPayloads(); + if(target != null){ moveTo(target, (target instanceof Sized s ? s.hitSize()/2f * 1.1f : 0f) + unit.hitSize/2f + 15f, 50f); unit.lookAt(target); @@ -23,6 +27,7 @@ public class DefenderAI extends AIController{ @Override protected Teamc findTarget(float x, float y, float range, boolean air, boolean ground){ + //find unit to follow if not in rally mode if(command() != UnitCommand.rally){ //Sort by max health and closer target. @@ -34,6 +39,14 @@ public class DefenderAI extends AIController{ var block = targetFlag(unit.x, unit.y, BlockFlag.rally, false); if(block != null) return block; //return core if found - return unit.closestCore(); + var core = unit.closestCore(); + if(core != null) return core; + + //for enemies, target the enemy core. + if(state.rules.waves && unit.team == state.rules.waveTeam){ + return unit.closestEnemyCore(); + } + + return null; } } diff --git a/core/src/mindustry/ai/types/FlyingAI.java b/core/src/mindustry/ai/types/FlyingAI.java index 72d7eda4ff..b3e35a21d1 100644 --- a/core/src/mindustry/ai/types/FlyingAI.java +++ b/core/src/mindustry/ai/types/FlyingAI.java @@ -11,6 +11,8 @@ public class FlyingAI extends AIController{ @Override public void updateMovement(){ + unloadPayloads(); + if(target != null && unit.hasWeapons() && command() == UnitCommand.attack){ if(!unit.type.circleTarget){ moveTo(target, unit.type.range * 0.8f); diff --git a/core/src/mindustry/entities/units/AIController.java b/core/src/mindustry/entities/units/AIController.java index e0c3231309..e4d2bfaf2b 100644 --- a/core/src/mindustry/entities/units/AIController.java +++ b/core/src/mindustry/entities/units/AIController.java @@ -9,6 +9,7 @@ import mindustry.entities.*; import mindustry.gen.*; import mindustry.type.*; import mindustry.world.*; +import mindustry.world.blocks.payloads.*; import mindustry.world.meta.*; import static mindustry.Vars.*; @@ -178,6 +179,14 @@ public class AIController implements UnitController{ return Geometry.findClosest(unit.x, unit.y, Vars.spawner.getSpawns()); } + protected void unloadPayloads(){ + if(unit instanceof Payloadc pay && pay.hasPayload() && target instanceof Building && pay.payloads().peek() instanceof UnitPayload){ + if(target.within(unit, Math.max(unit.type().range + 1f, 75f))){ + pay.dropLastPayload(); + } + } + } + protected void circle(Position target, float circleLength){ circle(target, circleLength, unit.speed()); } diff --git a/core/src/mindustry/game/SpawnGroup.java b/core/src/mindustry/game/SpawnGroup.java index 2b7e8625c9..115c78a7e6 100644 --- a/core/src/mindustry/game/SpawnGroup.java +++ b/core/src/mindustry/game/SpawnGroup.java @@ -1,5 +1,6 @@ package mindustry.game; +import arc.struct.*; import arc.util.*; import arc.util.serialization.*; import arc.util.serialization.Json.*; @@ -39,12 +40,12 @@ public class SpawnGroup implements JsonSerializable{ public float shieldScaling = 0f; /** Amount of enemies spawned initially, with no scaling */ public int unitAmount = 1; + /** Seq of payloads that this unit will spawn with. */ + public @Nullable Seq payloads; /** Status effect applied to the spawned unit. Null to disable. */ - @Nullable - public StatusEffect effect; + public @Nullable StatusEffect effect; /** Items this unit spawns with. Null to disable. */ - @Nullable - public ItemStack items; + public @Nullable ItemStack items; public SpawnGroup(UnitType type){ this.type = type; @@ -85,6 +86,15 @@ public class SpawnGroup implements JsonSerializable{ unit.shield = getShield(wave); + //load up spawn payloads + if(payloads != null && unit instanceof Payloadc pay){ + for(var type : payloads){ + if(type == null) continue; + Unit payload = type.create(unit.team); + pay.pickup(payload); + } + } + return unit; } @@ -101,6 +111,9 @@ public class SpawnGroup implements JsonSerializable{ if(shieldScaling != 0) json.writeValue("shieldScaling", shieldScaling); if(unitAmount != 1) json.writeValue("amount", unitAmount); if(effect != null) json.writeValue("effect", effect.name); + if(payloads != null && payloads.size > 0){ + json.writeValue("payloads", payloads.map(u -> u.name).toArray(String.class)); + } } @Override @@ -117,6 +130,9 @@ public class SpawnGroup implements JsonSerializable{ shields = data.getFloat("shields", 0); shieldScaling = data.getFloat("shieldScaling", 0); unitAmount = data.getInt("amount", 1); + if(data.has("payloads")){ + payloads = Seq.with(json.readValue(String[].class, data.get("payloads"))).map(s -> content.getByName(ContentType.unit, s)); + } //old boss effect ID if(data.has("effect") && data.get("effect").isNumber() && data.getInt("effect", -1) == 8){