diff --git a/core/assets-raw/sprites/blocks/payload/payload-mass-driver.png b/core/assets-raw/sprites/blocks/payload/payload-mass-driver.png index 5346bea41b..f8a1dee444 100644 Binary files a/core/assets-raw/sprites/blocks/payload/payload-mass-driver.png and b/core/assets-raw/sprites/blocks/payload/payload-mass-driver.png differ diff --git a/core/src/mindustry/input/DesktopInput.java b/core/src/mindustry/input/DesktopInput.java index 75d8a31f91..08f9d60dba 100644 --- a/core/src/mindustry/input/DesktopInput.java +++ b/core/src/mindustry/input/DesktopInput.java @@ -337,6 +337,9 @@ public class DesktopInput extends InputHandler{ if(player.dead() || locked){ cursorType = SystemCursor.arrow; + if(!Core.scene.hasMouse()){ + Core.graphics.cursor(cursorType); + } return; } diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index 58c4a7a2e8..281f4ef2d5 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -53,8 +53,13 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ public final OverlayFragment frag = new OverlayFragment(); + /** If true, there is a cutscene currently occurring in logic. */ + public boolean logicCutscene; + public Vec2 logicCamPan = new Vec2(); + public float logicCamSpeed = 0.1f; + /** If any of these functions return true, input is locked. */ - public Seq inputLocks = Seq.with(() -> renderer.isCutscene()); + public Seq inputLocks = Seq.with(() -> renderer.isCutscene(), () -> logicCutscene); public Interval controlInterval = new Interval(); public @Nullable Block block; public boolean overrideLineRotation; @@ -576,6 +581,10 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } public void update(){ + if(logicCutscene && !renderer.isCutscene()){ + Core.camera.position.lerpDelta(logicCamPan, logicCamSpeed); + } + playerPlanTree.clear(); player.unit().plans.each(playerPlanTree::insert); @@ -596,6 +605,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ //you don't want selected blocks while locked, looks weird if(locked()){ block = null; + } wasShooting = player.shooting; @@ -678,6 +688,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ public void updateState(){ if(state.isMenu()){ controlledType = null; + logicCutscene = false; } } diff --git a/core/src/mindustry/logic/CutsceneAction.java b/core/src/mindustry/logic/CutsceneAction.java new file mode 100644 index 0000000000..9026eea44f --- /dev/null +++ b/core/src/mindustry/logic/CutsceneAction.java @@ -0,0 +1,9 @@ +package mindustry.logic; + +public enum CutsceneAction{ + pan, + zoom, + stop; + + public static final CutsceneAction[] all = values(); +} diff --git a/core/src/mindustry/logic/LExecutor.java b/core/src/mindustry/logic/LExecutor.java index b93cc388ff..ee4afec401 100644 --- a/core/src/mindustry/logic/LExecutor.java +++ b/core/src/mindustry/logic/LExecutor.java @@ -1118,6 +1118,42 @@ public class LExecutor{ } } + public static class CutsceneI implements LInstruction{ + public CutsceneAction action = CutsceneAction.stop; + public int p1, p2, p3, p4; + + public CutsceneI(CutsceneAction action, int p1, int p2, int p3, int p4){ + this.action = action; + this.p1 = p1; + this.p2 = p2; + this.p3 = p3; + this.p4 = p4; + } + + public CutsceneI(){ + } + + @Override + public void run(LExecutor exec){ + if(headless) return; + + switch(action){ + case pan -> { + control.input.logicCutscene = true; + control.input.logicCamPan.set(World.unconv(exec.numf(p1)), World.unconv(exec.numf(p2))); + control.input.logicCamSpeed = exec.numf(p3); + } + case zoom -> { + control.input.logicCutscene = true; + renderer.setScale(Mathf.lerp(renderer.minZoom, renderer.maxZoom, Mathf.clamp(exec.numf(p1)))); + } + case stop -> { + control.input.logicCutscene = false; + } + } + } + } + //endregion //region privileged / world instructions diff --git a/core/src/mindustry/logic/LStatements.java b/core/src/mindustry/logic/LStatements.java index 8f5d5b894b..c7dac168c5 100644 --- a/core/src/mindustry/logic/LStatements.java +++ b/core/src/mindustry/logic/LStatements.java @@ -1294,4 +1294,60 @@ public class LStatements{ return new FlushNotificationI(); } } + + @RegisterStatement("cutscene") + public static class CutsceneStatement extends LStatement{ + public CutsceneAction action = CutsceneAction.pan; + public String p1 = "100", p2 = "100", p3 = " 0.06", p4 = "0"; + + @Override + public void build(Table table){ + rebuild(table); + } + + void rebuild(Table table){ + table.clearChildren(); + + table.button(b -> { + b.label(() -> action.name()).growX().wrap().labelAlign(Align.center); + b.clicked(() -> showSelect(b, CutsceneAction.all, action, o -> { + action = o; + rebuild(table); + })); + }, Styles.logict, () -> {}).size(90f, 40f).padLeft(2).color(table.color); + + switch(action){ + case pan -> { + table.add(" x "); + fields(table, p1, str -> p1 = str); + table.add(" y "); + fields(table, p2, str -> p2 = str); + + row(table); + + table.add(" speed "); + fields(table, p3, str -> p3 = str); + } + case zoom -> { + table.add(" level "); + fields(table, p1, str -> p1 = str); + } + } + } + + @Override + public boolean privileged(){ + return true; + } + + @Override + public Color color(){ + return Pal.logicWorld; + } + + @Override + public LInstruction build(LAssembler builder){ + return new CutsceneI(action, builder.var(p1), builder.var(p2), builder.var(p3), builder.var(p4)); + } + } }