diff --git a/core/src/mindustry/ai/ControlPathfinder.java b/core/src/mindustry/ai/ControlPathfinder.java index a43e38f68c..e56bfe86e3 100644 --- a/core/src/mindustry/ai/ControlPathfinder.java +++ b/core/src/mindustry/ai/ControlPathfinder.java @@ -70,7 +70,7 @@ public class ControlPathfinder implements Runnable{ //} for(var entry : requests){ - + entry.value.update(maxUpdate / requests.size); } } diff --git a/core/src/mindustry/ai/types/CommandAI.java b/core/src/mindustry/ai/types/CommandAI.java index 43f881a41f..e56afe5181 100644 --- a/core/src/mindustry/ai/types/CommandAI.java +++ b/core/src/mindustry/ai/types/CommandAI.java @@ -7,29 +7,45 @@ import mindustry.gen.*; public class CommandAI extends AIController{ public @Nullable Vec2 targetPos; + public @Nullable Teamc attackTarget; @Override public void updateUnit(){ + updateVisuals(); + updateTargeting(); + //TODO + if(attackTarget != null){ + if(targetPos == null) targetPos = new Vec2(); + targetPos.set(attackTarget); + } + if(targetPos != null){ - //if(unit.isFlying()){ - moveTo(targetPos, 5f); - //} + moveTo(targetPos, attackTarget != null ? unit.type.range - 10f : 5f); if(unit.isFlying()){ unit.lookAt(targetPos); }else{ faceTarget(); } + }else if(target != null){ + faceTarget(); } } + @Override + public Teamc findMainTarget(float x, float y, float range, boolean air, boolean ground){ + return attackTarget == null ? super.findMainTarget(x, y, range, air, ground) : attackTarget; + } + public void commandPosition(Vec2 pos){ targetPos = pos; + attackTarget = null; } public void commandTarget(Teamc moveTo){ //TODO + attackTarget = moveTo; } } diff --git a/core/src/mindustry/content/Fx.java b/core/src/mindustry/content/Fx.java index 6f69c71448..058b46659f 100644 --- a/core/src/mindustry/content/Fx.java +++ b/core/src/mindustry/content/Fx.java @@ -183,11 +183,17 @@ public class Fx{ } }), - moveCommand = new Effect(15, e -> { + moveCommand = new Effect(20, e -> { color(Pal.command); stroke(e.fout() * 5f); Lines.circle(e.x, e.y, 6f + e.fin() * 2f); - }).layer(Layer.effect - 20f), + }).layer(Layer.overlayUI), + + attackCommand = new Effect(20, e -> { + color(Pal.remove); + stroke(e.fout() * 5f); + poly(e.x, e.y, 4, 7f + e.fin() * 2f); + }).layer(Layer.overlayUI), commandSend = new Effect(28, e -> { color(Pal.command); diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index ad1aa9ce61..7f103a59ba 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -3269,6 +3269,7 @@ public class UnitTypes{ health = 700f; armor = 3f; hitSize = 12f; + buildBeamOffset = 8f; engineOffset = 7.5f; engineSize = 3.4f; diff --git a/core/src/mindustry/input/DesktopInput.java b/core/src/mindustry/input/DesktopInput.java index db98c3d2db..20aba0e19d 100644 --- a/core/src/mindustry/input/DesktopInput.java +++ b/core/src/mindustry/input/DesktopInput.java @@ -675,15 +675,30 @@ public class DesktopInput extends InputHandler{ } }else if(selectedUnits.size > 0){ //move to location - TODO right click instead? - //TODO all this needs to be synced, done with packets, etc Vec2 target = input.mouseWorld().cpy(); - for(var sel : selectedUnits){ - ((CommandAI)sel.controller()).commandPosition(target); + Teamc build = world.buildWorld(target.x, target.y); + + if(build == null || build.team() == player.team()){ + build = selectedEnemyUnit(target.x, target.y); } - Fx.moveCommand.at(target); + if(build != null && build.team() != player.team()){ + for(var sel : selectedUnits){ + ((CommandAI)sel.controller()).commandTarget(build); + } + + Fx.attackCommand.at(build); + }else{ + for(var sel : selectedUnits){ + ((CommandAI)sel.controller()).commandPosition(target); + } + + Fx.moveCommand.at(target); + } + + } return super.tap(x, y, count, button); diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index c8600a4482..447823b0b9 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -1199,6 +1199,20 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ return tmpUnits.min(u -> u.isCommandable(), u -> u.dst(x, y) - u.hitSize/2f); } + public @Nullable Unit selectedEnemyUnit(float x, float y){ + tmpUnits.clear(); + float rad = 4f; + + Seq data = state.teams.present; + for(int i = 0; i < data.size; i++){ + if(data.items[i].team != player.team()){ + data.items[i].tree().intersect(x - rad / 2f, y - rad / 2f, rad, rad, tmpUnits); + } + } + + return tmpUnits.min(u -> u.dst(x, y) - u.hitSize/2f); + } + public Seq selectedCommandUnits(float x, float y, float w, float h){ var tree = player.team().data().tree(); tmpUnits.clear();