From e47806b9b80fa1c1e7bac74be269020608979f86 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 15 Apr 2023 15:54:33 -0400 Subject: [PATCH] Minimap attack indicators --- core/src/mindustry/core/Control.java | 12 ++++ core/src/mindustry/game/AttackIndicators.java | 66 +++++++++++++++++++ .../mindustry/graphics/MinimapRenderer.java | 28 ++++++++ .../ui/fragments/MinimapFragment.java | 13 +++- 4 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 core/src/mindustry/game/AttackIndicators.java diff --git a/core/src/mindustry/core/Control.java b/core/src/mindustry/core/Control.java index af3d649437..9d6a699bde 100644 --- a/core/src/mindustry/core/Control.java +++ b/core/src/mindustry/core/Control.java @@ -49,6 +49,7 @@ public class Control implements ApplicationListener, Loadable{ public Saves saves; public SoundControl sound; public InputHandler input; + public AttackIndicators indicators; private Interval timer = new Interval(2); private boolean hiscore = false; @@ -58,6 +59,13 @@ public class Control implements ApplicationListener, Loadable{ public Control(){ saves = new Saves(); sound = new SoundControl(); + indicators = new AttackIndicators(); + + Events.on(BuildDamageEvent.class, e -> { + if(e.build.team == Vars.player.team()){ + indicators.add(e.build.tileX(), e.build.tileY()); + } + }); //show dialog saying that mod loading was skipped. Events.on(ClientLoadEvent.class, e -> { @@ -100,6 +108,7 @@ public class Control implements ApplicationListener, Loadable{ Events.on(ResetEvent.class, event -> { player.reset(); toBePlaced.clear(); + indicators.clear(); hiscore = false; saves.resetSave(); @@ -628,6 +637,9 @@ public class Control implements ApplicationListener, Loadable{ if(state.isGame()){ input.update(); + if(!state.isPaused()){ + indicators.update(); + } //auto-update rpc every 5 seconds if(timer.get(0, 60 * 5)){ diff --git a/core/src/mindustry/game/AttackIndicators.java b/core/src/mindustry/game/AttackIndicators.java new file mode 100644 index 0000000000..dded3808ff --- /dev/null +++ b/core/src/mindustry/game/AttackIndicators.java @@ -0,0 +1,66 @@ +package mindustry.game; + +import arc.math.geom.*; +import arc.struct.*; +import arc.util.*; +import mindustry.annotations.Annotations.*; +import mindustry.gen.*; + +/** Updates and stores attack indicators for the minimap. */ +public class AttackIndicators{ + private static final float duration = 15f * 60f; + + private LongSeq indicators = new LongSeq(false, 16); + private IntIntMap posToIndex = new IntIntMap(); + + public LongSeq list(){ + return indicators; + } + + public void clear(){ + indicators.clear(); + posToIndex.clear(); + } + + public void add(int x, int y){ + int pos = Point2.pack(x, y); + int index = posToIndex.get(pos, -1); + + //there is an existing indicator... + if(index != -1){ + //reset its time (new attack) + indicators.items[index] = Indicator.time(indicators.items[index], 0f); + }else{ + //new indicator created + indicators.add(Indicator.get(pos, 0f)); + posToIndex.put(pos, indicators.size - 1); + } + } + + public void update(){ + long[] items = indicators.items; + for(int i = 0; i < indicators.size; i ++){ + long l = items[i]; + items[i] = l = Indicator.time(l, Indicator.time(l) + Time.delta); + + if(Indicator.time(l) >= duration){ + //remove the indicator as it has timed out, make sure to not skip the next one + indicators.removeIndex(i); + posToIndex.remove(Indicator.pos(l)); + + if(indicators.size > 0){ + //relocation of head to this new index + posToIndex.put(Indicator.pos(items[i]), i); + } + + i --; + } + } + } + + @Struct + class IndicatorStruct{ + int pos; + float time; + } +} diff --git a/core/src/mindustry/graphics/MinimapRenderer.java b/core/src/mindustry/graphics/MinimapRenderer.java index 59e88f2be3..083e03b951 100644 --- a/core/src/mindustry/graphics/MinimapRenderer.java +++ b/core/src/mindustry/graphics/MinimapRenderer.java @@ -201,6 +201,34 @@ public class MinimapRenderer{ } } + LongSeq indicators = control.indicators.list(); + float fin = ((Time.globalTime / 30f) % 1f); + float rad = scale(fin * 5f + tilesize - 2f); + Lines.stroke(Scl.scl((1f - fin) * 4f + 0.5f)); + + for(int i = 0; i < indicators.size; i++){ + long ind = indicators.items[i]; + int + pos = Indicator.pos(ind), + ix = Point2.x(pos), + iy = Point2.y(pos); + float time = Indicator.time(ind), offset = 0f; + + //fix multiblock offset - this is suboptimal + Building build = world.build(pos); + if(build != null){ + offset = build.block.offset / tilesize; + } + + Vec2 v = transform(Tmp.v1.set((ix + 0.5f + offset) * tilesize, (iy + 0.5f + offset) * tilesize)); + + Draw.color(Color.orange, Color.scarlet, Mathf.clamp(time / 50f)); + + Lines.square(v.x, v.y, rad); + } + + Draw.reset(); + state.rules.objectives.eachRunning(obj -> { for(var marker : obj.markers){ marker.drawMinimap(this); diff --git a/core/src/mindustry/ui/fragments/MinimapFragment.java b/core/src/mindustry/ui/fragments/MinimapFragment.java index 76f7aa202a..583c80d63e 100644 --- a/core/src/mindustry/ui/fragments/MinimapFragment.java +++ b/core/src/mindustry/ui/fragments/MinimapFragment.java @@ -86,15 +86,16 @@ public class MinimapFragment{ panx += deltaX / zoom; pany += deltaY / zoom; }else{ - Rect r = getRectBounds(); - Tmp.v1.set(x, y).sub(r.x, r.y).scl(1f / r.width, 1f / r.height).scl(world.unitWidth(), world.unitHeight()); - control.input.panCamera(Tmp.v1); + panTo(x, y); } } @Override public void touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){ super.touchDown(event, x, y, pointer, button); + if(button == KeyCode.mouseRight){ + panTo(x, y); + } } @Override @@ -125,6 +126,12 @@ public class MinimapFragment{ }); } + public void panTo(float relativeX, float relativeY){ + Rect r = getRectBounds(); + Tmp.v1.set(relativeX, relativeY).sub(r.x, r.y).scl(1f / r.width, 1f / r.height).scl(world.unitWidth(), world.unitHeight()); + control.input.panCamera(Tmp.v1); + } + public boolean shown(){ return shown; }