diff --git a/core/src/mindustry/content/Fx.java b/core/src/mindustry/content/Fx.java index ae0577907f..a84d9fdb9c 100644 --- a/core/src/mindustry/content/Fx.java +++ b/core/src/mindustry/content/Fx.java @@ -36,6 +36,39 @@ public class Fx{ }), + unitControl = new Effect(30f, e -> { + if(!(e.data instanceof Unitc)) return; + + Unitc select = (Unitc)e.data; + + mixcol(Pal.accent, 1f); + alpha(e.fout()); + rect(select.type().icon(Cicon.full), select.x(), select.y(), select.rotation() - 90f); + Lines.square(select.x(), select.y(), e.fout() * select.hitSize() * 2f, 45f); + Lines.stroke(e.fin() * 2f); + Lines.square(select.x(), select.y(), e.fout() * select.hitSize() * 3f, 45f); + reset(); + }), + + unitSpirit = new Effect(20f, e -> { + if(!(e.data instanceof Position)) return; + Position to = e.data(); + + color(Pal.accent); + + Tmp.v1.set(e.x, e.y).interpolate(Tmp.v2.set(to), e.fin(), Interpolation.pow2In); + float x = Tmp.v1.x, y = Tmp.v1.y; + float size = 2.5f * e.fin(); + + Fill.square(x, y, 1.5f * size, 45f); + + Tmp.v1.set(e.x, e.y).interpolate(Tmp.v2.set(to), e.fin(), Interpolation.pow5In); + x = Tmp.v1.x; + y = Tmp.v1.y; + + Fill.square(x, y, 1f * size, 45f); + }), + itemTransfer = new Effect(30f, e -> { if(!(e.data instanceof Position)) return; Position to = e.data(); diff --git a/core/src/mindustry/graphics/OverlayRenderer.java b/core/src/mindustry/graphics/OverlayRenderer.java index 5c36db0091..ac1b29e0a5 100644 --- a/core/src/mindustry/graphics/OverlayRenderer.java +++ b/core/src/mindustry/graphics/OverlayRenderer.java @@ -18,7 +18,8 @@ public class OverlayRenderer{ private static final float indicatorLength = 14f; private static final float spawnerMargin = tilesize*11f; private static final Rect rect = new Rect(); - private float buildFadeTime; + private float buildFade, unitFade; + private Unitc lastSelect; public void drawBottom(){ InputHandler input = control.input; @@ -64,6 +65,23 @@ public class OverlayRenderer{ InputHandler input = control.input; + Unitc select = input.selectedUnit(); + if(!Core.input.keyDown(Binding.control)) select = null; + unitFade = Mathf.lerpDelta(unitFade, Mathf.num(select != null), 0.1f); + + if(select != null) lastSelect = select; + if(select == null) select = lastSelect; + if(select != null && select.isAI()){ + Draw.mixcol(Pal.accent, 1f); + Draw.alpha(unitFade); + Draw.rect(select.type().icon(Cicon.full), select.x(), select.y(), select.rotation() - 90); + Lines.stroke(unitFade); + Lines.square(select.x(), select.y(), select.hitSize() * 1.5f, Time.time() * 2f); + Draw.reset(); + } + + + //draw config selected block if(input.frag.config.isShown()){ Tilec tile = input.frag.config.getSelectedTile(); @@ -72,12 +90,12 @@ public class OverlayRenderer{ input.drawTop(); - buildFadeTime = Mathf.lerpDelta(buildFadeTime, input.isPlacing() ? 1f : 0f, 0.06f); + buildFade = Mathf.lerpDelta(buildFade, input.isPlacing() ? 1f : 0f, 0.06f); Draw.reset(); - Lines.stroke(buildFadeTime * 2f); + Lines.stroke(buildFade * 2f); - if(buildFadeTime > 0.005f){ + if(buildFade > 0.005f){ state.teams.eachEnemyCore(player.team(), core -> { float dst = core.dst(player); if(dst < state.rules.enemyCoreBuildRadius * 2.2f){ diff --git a/core/src/mindustry/input/Binding.java b/core/src/mindustry/input/Binding.java index 0648fc0a7a..70e7165a48 100644 --- a/core/src/mindustry/input/Binding.java +++ b/core/src/mindustry/input/Binding.java @@ -11,6 +11,7 @@ public enum Binding implements KeyBind{ move_y(new Axis(KeyCode.S, KeyCode.W)), mouse_move(KeyCode.MOUSE_BACK), dash(KeyCode.SHIFT_LEFT), + control(KeyCode.ALT_LEFT), select(KeyCode.MOUSE_LEFT), deselect(KeyCode.MOUSE_RIGHT), break_block(KeyCode.MOUSE_RIGHT), diff --git a/core/src/mindustry/input/DesktopInput.java b/core/src/mindustry/input/DesktopInput.java index c0aae9dd9a..88cffdeb4f 100644 --- a/core/src/mindustry/input/DesktopInput.java +++ b/core/src/mindustry/input/DesktopInput.java @@ -174,13 +174,10 @@ public class DesktopInput extends InputHandler{ } if(!scene.hasMouse()){ - if(Core.input.keyTap(Binding.select)){ - Unitc unit = Units.closest(player.team(), Core.input.mouseWorld().x, Core.input.mouseWorld().y, 40f, u -> true); - if(unit != null){ - unit.hitbox(Tmp.r1); - if(Tmp.r1.contains(Core.input.mouseWorld())){ - Call.onUnitControl(player, unit); - } + if(Core.input.keyDown(Binding.control) && Core.input.keyTap(Binding.select)){ + Unitc on = selectedUnit(); + if(on != null){ + Call.onUnitControl(player, on); } } diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index cd6dbc6a10..c1e9d2b4cd 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -175,6 +175,10 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ //make sure it's AI controlled, so players can't overwrite each other }else if(unit.isAI() && unit.team() == player.team()){ player.unit(unit); + Time.run(Fx.unitSpirit.lifetime, () -> Fx.unitControl.at(unit.x(), unit.y(), 0f, unit)); + if(!player.dead()){ + Fx.unitSpirit.at(player.x(), player.y(), 0f, unit); + } } } @@ -706,6 +710,18 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ return Core.input.mouseWorld(getMouseX(), getMouseY()).sub(x, y).angle(); } + public @Nullable Unitc selectedUnit(){ + Unitc unit = Units.closest(player.team(), Core.input.mouseWorld().x, Core.input.mouseWorld().y, 40f, Unitc::isAI); + if(unit != null){ + unit.hitbox(Tmp.r1); + Tmp.r1.grow(6f); + if(Tmp.r1.contains(Core.input.mouseWorld())){ + return unit; + } + } + return null; + } + public void remove(){ Core.input.removeProcessor(this); frag.remove(); diff --git a/core/src/mindustry/ui/fragments/PlayerListFragment.java b/core/src/mindustry/ui/fragments/PlayerListFragment.java index 8d8066cb0e..76926cf89b 100644 --- a/core/src/mindustry/ui/fragments/PlayerListFragment.java +++ b/core/src/mindustry/ui/fragments/PlayerListFragment.java @@ -20,6 +20,7 @@ public class PlayerListFragment extends Fragment{ private Table content = new Table().marginRight(13f).marginLeft(13f); private Interval timer = new Interval(); private TextField sField; + private boolean found = false; @Override public void build(Group parent){ @@ -71,13 +72,15 @@ public class PlayerListFragment extends Fragment{ content.clear(); float h = 74f; + found = false; Groups.player.sort(Structs.comparing(Playerc::team)); Groups.player.each(user -> { + found = true; NetConnection connection = user.con(); if(connection == null && net.server() && !user.isLocal()) return; - if(sField.getText().length() > 0 && !user.name().toLowerCase().contains(sField.getText().toLowerCase()) && !Strings.stripColors(user.name.toLowerCase()).contains(sField.getText().toLowerCase())) return; + if(sField.getText().length() > 0 && !user.name().toLowerCase().contains(sField.getText().toLowerCase()) && !Strings.stripColors(user.name().toLowerCase()).contains(sField.getText().toLowerCase())) return; Table button = new Table(); button.left(); @@ -150,7 +153,7 @@ public class PlayerListFragment extends Fragment{ content.row(); }); - if(sField.getText().length() > 0 && !Groups.player.contains(user -> user.name.toLowerCase().contains(sField.getText().toLowerCase()))) { + if(!found){ content.add(Core.bundle.format("players.notfound")).padBottom(6).width(350f).maxHeight(h + 14); }