diff --git a/core/src/io/anuke/mindustry/ai/Pathfinder.java b/core/src/io/anuke/mindustry/ai/Pathfinder.java index 9108e25641..4df7f28451 100644 --- a/core/src/io/anuke/mindustry/ai/Pathfinder.java +++ b/core/src/io/anuke/mindustry/ai/Pathfinder.java @@ -89,7 +89,12 @@ public class Pathfinder { } path.search ++; - path.frontier.clear(); + + if(path.lastSearchTime + 1000/60*3 > TimeUtils.millis()){ + path.frontier.clear(); + } + + path.lastSearchTime = TimeUtils.millis(); ObjectSet set = world.indexer().getEnemy(team, BlockFlag.target); for(Tile other : set){ @@ -171,6 +176,7 @@ public class Pathfinder { float[][] weights; int[][] searches; int search = 0; + long lastSearchTime; Queue frontier = new Queue<>(); PathData(){ diff --git a/core/src/io/anuke/mindustry/entities/units/FlyingUnitType.java b/core/src/io/anuke/mindustry/entities/units/FlyingUnitType.java index 3aa6ab8587..f31f7a2036 100644 --- a/core/src/io/anuke/mindustry/entities/units/FlyingUnitType.java +++ b/core/src/io/anuke/mindustry/entities/units/FlyingUnitType.java @@ -1,25 +1,23 @@ package io.anuke.mindustry.entities.units; -import com.badlogic.gdx.math.Vector2; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.resource.AmmoType; -import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.BlockFlag; +import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.Geometry; import io.anuke.ucore.util.Mathf; +import io.anuke.ucore.util.Translator; import static io.anuke.mindustry.Vars.world; public class FlyingUnitType extends UnitType { - protected static Vector2 vec = new Vector2(); + protected static Translator vec = new Translator(); - protected float boosterLength = 4.5f; - protected float retreatHealth = 10f; protected float maxAim = 30f; public FlyingUnitType(String name) { @@ -49,7 +47,10 @@ public class FlyingUnitType extends UnitType { @Override public void behavior(BaseUnit unit) { - + if(unit.health <= health * retreatPercent && + Geometry.findClosest(unit.x, unit.y, world.indexer().getAllied(unit.team, BlockFlag.repair)) != null){ + unit.setState(retreat); + } } protected void circle(BaseUnit unit, float circleLength){ @@ -128,7 +129,7 @@ public class FlyingUnitType extends UnitType { }else{ attack(unit, 150f); - if (unit.timer.get(timerReload, 7) && Mathf.angNear(unit.angleTo(unit.target), unit.rotation, 13f) + if (unit.timer.get(timerReload, reload) && Mathf.angNear(unit.angleTo(unit.target), unit.rotation, 13f) && unit.distanceTo(unit.target) < unit.inventory.getAmmo().getRange()) { AmmoType ammo = unit.inventory.getAmmo(); unit.inventory.useAmmo(); diff --git a/core/src/io/anuke/mindustry/entities/units/GroundUnitType.java b/core/src/io/anuke/mindustry/entities/units/GroundUnitType.java index 8768818ba8..05e92ace90 100644 --- a/core/src/io/anuke/mindustry/entities/units/GroundUnitType.java +++ b/core/src/io/anuke/mindustry/entities/units/GroundUnitType.java @@ -7,11 +7,15 @@ import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.game.TeamInfo.TeamData; +import io.anuke.mindustry.resource.AmmoType; +import io.anuke.mindustry.world.BlockFlag; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.types.Floor; import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Hue; +import io.anuke.ucore.util.Angles; +import io.anuke.ucore.util.Geometry; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Translator; @@ -19,12 +23,9 @@ import static io.anuke.mindustry.Vars.state; import static io.anuke.mindustry.Vars.world; public abstract class GroundUnitType extends UnitType{ - //only use for drawing! - protected Translator tr1 = new Translator(); - //only use for updating! - protected Translator tr2 = new Translator(); + protected static Translator vec = new Translator(); - protected float jumpDistance = 4f; + protected float maxAim = 30f; public GroundUnitType(String name) { super(name); @@ -34,6 +35,11 @@ public abstract class GroundUnitType extends UnitType{ range = 40f; } + @Override + public UnitState getStartState() { + return resupply; + } + @Override public void update(BaseUnit unit) { super.update(unit); @@ -56,8 +62,10 @@ public abstract class GroundUnitType extends UnitType{ } for (int i : Mathf.signs) { - tr1.trns(unit.baseRotation, ft * i); - Draw.rect(name + "-leg", unit.x + tr1.x, unit.y + tr1.y, 12f * i, 12f - Mathf.clamp(ft * i, 0, 2), unit.baseRotation - 90); + Draw.rect(name + "-leg", + unit.x + Angles.trnsx(unit.baseRotation, ft * i), + unit.y + Angles.trnsy(unit.baseRotation, ft * i), + 12f * i, 12f - Mathf.clamp(ft * i, 0, 2), unit.baseRotation - 90); } if(floor.liquid) { @@ -105,20 +113,100 @@ public abstract class GroundUnitType extends UnitType{ @Override public void behavior(BaseUnit unit) { + if(unit.health <= health * retreatPercent){ + unit.setState(retreat); + } + } - if(unit.target instanceof TileEntity && unit.distanceTo(unit.target) < range) { - if(unit.timer.get(timerReload, reload)){ - //shoot(unit, BulletType.shot, tr2.angle(), 4f); - } - }else{ - Tile targetTile = world.pathfinder().getTargetTile(unit.team, world.tileWorld(unit.x, unit.y)); + protected void moveToCore(BaseUnit unit){ + Tile tile = world.tileWorld(unit.x, unit.y); + Tile targetTile = world.pathfinder().getTargetTile(unit.team, tile); - tr2.trns(unit.baseRotation, speed); + if(tile == targetTile) return; - unit.baseRotation = Mathf.slerpDelta(unit.baseRotation, unit.angleTo(targetTile), 0.05f); - unit.walkTime += Timers.delta(); - unit.velocity.add(tr2); + vec.trns(unit.baseRotation, speed); + + unit.baseRotation = Mathf.slerpDelta(unit.baseRotation, unit.angleTo(targetTile), 0.05f); + unit.walkTime += Timers.delta(); + unit.velocity.add(vec); + } + + protected void moveAwayFromCore(BaseUnit unit){ + Tile tile = world.tileWorld(unit.x, unit.y); + Tile targetTile = world.pathfinder().getTargetTile(state.teams.enemiesOf(unit.team).first(), tile); + + if(tile == targetTile) return; + + vec.trns(unit.baseRotation, speed); + + unit.baseRotation = Mathf.slerpDelta(unit.baseRotation, unit.angleTo(targetTile), 0.05f); + unit.walkTime += Timers.delta(); + unit.velocity.add(vec); + } + + public final UnitState + + resupply = new UnitState(){ + public void entered(BaseUnit unit) { + unit.target = null; } - } + public void update(BaseUnit unit) { + //TODO move toward resupply point? + if(unit.inventory.totalAmmo() + 10 >= unit.inventory.ammoCapacity()){ + unit.state.set(unit, attack); + } + } + }, + attack = new UnitState(){ + public void entered(BaseUnit unit) { + unit.target = null; + } + + public void update(BaseUnit unit) { + if(unit.target != null && (unit.target instanceof TileEntity && + (((TileEntity)unit.target).tile.getTeam() == unit.team || !((TileEntity)unit.target).tile.breakable()))){ + unit.target = null; + } + + if(!unit.inventory.hasAmmo()) { + unit.state.set(unit, resupply); + }else if (unit.target == null){ + if(unit.timer.get(timerTarget, 20)) { + Unit closest = Units.getClosestEnemy(unit.team, unit.x, unit.y, + unit.inventory.getAmmo().getRange(), other -> other.distanceTo(unit) < 60f); + if(closest != null){ + unit.target = closest; + }else { + Tile target = Geometry.findClosest(unit.x, unit.y, world.indexer().getEnemy(unit.team, BlockFlag.resupplyPoint)); + if (target != null) unit.target = target.entity; + } + } + }else{ + moveToCore(unit); + + if (unit.timer.get(timerReload, reload) && Mathf.angNear(unit.angleTo(unit.target), unit.rotation, 13f) + && unit.distanceTo(unit.target) < unit.inventory.getAmmo().getRange()) { + AmmoType ammo = unit.inventory.getAmmo(); + unit.inventory.useAmmo(); + unit.rotate(unit.angleTo(unit.target)); + + shoot(unit, ammo, Angles.moveToward(unit.rotation, unit.angleTo(unit.target), maxAim), 4f); + } + } + } + }, + retreat = new UnitState() { + public void entered(BaseUnit unit) { + unit.target = null; + } + + public void update(BaseUnit unit) { + if(unit.health >= health){ + unit.state.set(unit, attack); + } + + moveAwayFromCore(unit); + } + }; } diff --git a/core/src/io/anuke/mindustry/entities/units/UnitType.java b/core/src/io/anuke/mindustry/entities/units/UnitType.java index 3b6f7899bb..e9a52a3066 100644 --- a/core/src/io/anuke/mindustry/entities/units/UnitType.java +++ b/core/src/io/anuke/mindustry/entities/units/UnitType.java @@ -42,6 +42,7 @@ public abstract class UnitType { protected float drag = 0.1f; protected float maxVelocity = 5f; protected float reload = 40f; + protected float retreatPercent = 20f; protected ObjectMap ammo = new ObjectMap<>(); public UnitType(String name){ diff --git a/core/src/io/anuke/mindustry/entities/units/types/Brute.java b/core/src/io/anuke/mindustry/entities/units/types/Brute.java index 1b6ca79c5a..c30b68fd9d 100644 --- a/core/src/io/anuke/mindustry/entities/units/types/Brute.java +++ b/core/src/io/anuke/mindustry/entities/units/types/Brute.java @@ -1,11 +1,13 @@ package io.anuke.mindustry.entities.units.types; +import io.anuke.mindustry.content.AmmoTypes; import io.anuke.mindustry.entities.units.GroundUnitType; public class Brute extends GroundUnitType { public Brute(String name) { super(name); + setAmmo(AmmoTypes.basicIron); } } diff --git a/core/src/io/anuke/mindustry/entities/units/types/Cruiser.java b/core/src/io/anuke/mindustry/entities/units/types/Cruiser.java index 6c7d32f126..a6818204c4 100644 --- a/core/src/io/anuke/mindustry/entities/units/types/Cruiser.java +++ b/core/src/io/anuke/mindustry/entities/units/types/Cruiser.java @@ -6,15 +6,11 @@ import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.entities.units.FlyingUnitType; import io.anuke.mindustry.entities.units.UnitState; import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.world.BlockFlag; import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Geometry; import io.anuke.ucore.util.Mathf; -import static io.anuke.mindustry.Vars.world; - public class Cruiser extends FlyingUnitType { @@ -66,14 +62,6 @@ public class Cruiser extends FlyingUnitType { } } - @Override - public void behavior(BaseUnit unit) { - if(unit.health <= retreatHealth && - Geometry.findClosest(unit.x, unit.y, world.indexer().getAllied(unit.team, BlockFlag.repair)) != null){ - unit.setState(retreat); - } - } - @Override public UnitState getStartState(){ return resupply; diff --git a/core/src/io/anuke/mindustry/entities/units/types/Scout.java b/core/src/io/anuke/mindustry/entities/units/types/Scout.java index c5a2714596..17a5e9cbb0 100644 --- a/core/src/io/anuke/mindustry/entities/units/types/Scout.java +++ b/core/src/io/anuke/mindustry/entities/units/types/Scout.java @@ -1,10 +1,12 @@ package io.anuke.mindustry.entities.units.types; +import io.anuke.mindustry.content.AmmoTypes; import io.anuke.mindustry.entities.units.GroundUnitType; public class Scout extends GroundUnitType { public Scout(){ super("scout"); + setAmmo(AmmoTypes.basicIron); } } diff --git a/core/src/io/anuke/mindustry/entities/units/types/Vtol.java b/core/src/io/anuke/mindustry/entities/units/types/Vtol.java index 47b3fbbdc3..7e057a8a39 100644 --- a/core/src/io/anuke/mindustry/entities/units/types/Vtol.java +++ b/core/src/io/anuke/mindustry/entities/units/types/Vtol.java @@ -7,15 +7,11 @@ import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.entities.units.FlyingUnitType; import io.anuke.mindustry.entities.units.UnitState; import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.world.BlockFlag; import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Geometry; import io.anuke.ucore.util.Mathf; -import static io.anuke.mindustry.Vars.world; - public class Vtol extends FlyingUnitType { public Vtol(){ @@ -23,6 +19,7 @@ public class Vtol extends FlyingUnitType { setAmmo(AmmoTypes.basicIron); speed = 0.3f; maxVelocity = 2f; + reload = 7; } @Override @@ -69,14 +66,6 @@ public class Vtol extends FlyingUnitType { } } - @Override - public void behavior(BaseUnit unit) { - if(unit.health <= retreatHealth && - Geometry.findClosest(unit.x, unit.y, world.indexer().getAllied(unit.team, BlockFlag.repair)) != null){ - unit.setState(retreat); - } - } - @Override public UnitState getStartState(){ return resupply;