diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index 8e83af02f4..1f752a375a 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -322,7 +322,7 @@ public class UnitTypes{ speed = 0.55f; hitSize = 8f; health = 120f; - buildSpeed = 0.35f; + buildSpeed = 0.3f; armor = 1f; abilities.add(new RepairFieldAbility(10f, 60f * 4, 60f)); @@ -1256,6 +1256,7 @@ public class UnitTypes{ controller = u -> new MinerAI(); defaultCommand = UnitCommand.mineCommand; + allowChangeCommands = false; flying = true; drag = 0.06f; diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index 3819a23e3c..9e498b65be 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -300,6 +300,8 @@ public class UnitType extends UnlockableContent implements Senseable{ /** Flags to target based on priority. Null indicates that the closest target should be found. The closest enemy core is used as a fallback. */ public BlockFlag[] targetFlags = {null}; + /** A value of false is used to hide command changing UI in unit factories. */ + public boolean allowChangeCommands = true; /** Commands available to this unit through RTS controls. An empty array means commands will be assigned based on unit capabilities in init(). */ public UnitCommand[] commands = {}; /** Command to assign to this unit upon creation. Null indicates the first command in the array. */ @@ -860,6 +862,10 @@ public class UnitType extends UnlockableContent implements Senseable{ commands = cmds.toArray(); } + if(defaultCommand == null && commands.length > 0){ + defaultCommand = commands[0]; + } + if(stances.length == 0){ if(canAttack){ Seq seq = Seq.with(UnitStance.stop, UnitStance.shoot, UnitStance.holdFire, UnitStance.pursueTarget, UnitStance.patrol); diff --git a/core/src/mindustry/world/blocks/ItemSelection.java b/core/src/mindustry/world/blocks/ItemSelection.java index 24e49706de..6bbe2ba127 100644 --- a/core/src/mindustry/world/blocks/ItemSelection.java +++ b/core/src/mindustry/world/blocks/ItemSelection.java @@ -1,5 +1,6 @@ package mindustry.world.blocks; +import arc.*; import arc.func.*; import arc.math.*; import arc.scene.style.*; @@ -93,6 +94,11 @@ public class ItemSelection{ ScrollPane pane = new ScrollPane(cont, Styles.smallPane); pane.setScrollingDisabled(true, false); + pane.exited(() -> { + if(pane.hasScroll()){ + Core.scene.setScrollFocus(null); + } + }); if(block != null){ pane.setScrollYForce(block.selectScroll); diff --git a/core/src/mindustry/world/blocks/units/Reconstructor.java b/core/src/mindustry/world/blocks/units/Reconstructor.java index f0448063a4..023270260b 100644 --- a/core/src/mindustry/world/blocks/units/Reconstructor.java +++ b/core/src/mindustry/world/blocks/units/Reconstructor.java @@ -168,7 +168,7 @@ public class Reconstructor extends UnitBlock{ public boolean canSetCommand(){ var output = unit(); - return output != null && output.commands.length > 1; + return output != null && output.commands.length > 1 && output.allowChangeCommands; } @Override diff --git a/core/src/mindustry/world/blocks/units/UnitFactory.java b/core/src/mindustry/world/blocks/units/UnitFactory.java index 6747310d2d..c6369a0bfe 100644 --- a/core/src/mindustry/world/blocks/units/UnitFactory.java +++ b/core/src/mindustry/world/blocks/units/UnitFactory.java @@ -6,11 +6,13 @@ import arc.graphics.g2d.*; import arc.math.*; import arc.math.geom.*; import arc.scene.style.*; +import arc.scene.ui.*; import arc.scene.ui.layout.*; import arc.struct.*; import arc.util.*; import arc.util.io.*; import mindustry.*; +import mindustry.ai.*; import mindustry.entities.*; import mindustry.entities.units.*; import mindustry.game.EventType.*; @@ -46,23 +48,32 @@ public class UnitFactory extends UnitBlock{ commandable = true; ambientSound = Sounds.respawning; - config(Integer.class, (UnitFactoryBuild tile, Integer i) -> { + config(Integer.class, (UnitFactoryBuild build, Integer i) -> { if(!configurable) return; - if(tile.currentPlan == i) return; - tile.currentPlan = i < 0 || i >= plans.size ? -1 : i; - tile.progress = 0; + if(build.currentPlan == i) return; + build.currentPlan = i < 0 || i >= plans.size ? -1 : i; + build.progress = 0; + if(build.command != null && !Structs.contains(build.unit().commands, build.command)){ + build.command = null; + } }); - config(UnitType.class, (UnitFactoryBuild tile, UnitType val) -> { + config(UnitType.class, (UnitFactoryBuild build, UnitType val) -> { if(!configurable) return; int next = plans.indexOf(p -> p.unit == val); - if(tile.currentPlan == next) return; - tile.currentPlan = next; - tile.progress = 0; + if(build.currentPlan == next) return; + build.currentPlan = next; + build.progress = 0; + if(build.command != null && !Structs.contains(val.commands, build.command)){ + build.command = null; + } }); + config(UnitCommand.class, (UnitFactoryBuild build, UnitCommand command) -> build.command = command); + configClear((UnitFactoryBuild build) -> build.command = null); + consume(new ConsumeItemDynamic((UnitFactoryBuild e) -> e.currentPlan != -1 ? plans.get(Math.min(e.currentPlan, plans.size - 1)).requirements : ItemStack.empty)); } @@ -177,12 +188,18 @@ public class UnitFactory extends UnitBlock{ public class UnitFactoryBuild extends UnitBuild{ public @Nullable Vec2 commandPos; + public @Nullable UnitCommand command; public int currentPlan = -1; public float fraction(){ return currentPlan == -1 ? 0 : progress / plans.get(currentPlan).time; } + public boolean canSetCommand(){ + var output = unit(); + return output != null && output.commands.length > 1 && output.allowChangeCommands; + } + @Override public void created(){ //auto-set to the first plan, it's better than nothing. @@ -225,6 +242,59 @@ public class UnitFactory extends UnitBlock{ if(units.any()){ ItemSelection.buildTable(UnitFactory.this, table, units, () -> currentPlan == -1 ? null : plans.get(currentPlan).unit, unit -> configure(plans.indexOf(u -> u.unit == unit)), selectionRows, selectionColumns); + + table.row(); + + Table commands = new Table(); + commands.top().left(); + commands.background(Styles.black6); + + Runnable rebuildCommands = () -> { + commands.clear(); + var unit = unit(); + if(unit != null && canSetCommand()){ + var group = new ButtonGroup(); + group.setMinCheckCount(0); + int i = 0, columns = Mathf.clamp(units.size, 2, selectionColumns); + var list = unit.commands; + + commands.image(Tex.whiteui, Pal.gray).height(4f).growX().colspan(columns).row(); + + for(var item : list){ + ImageButton button = commands.button(item.getIcon(), Styles.clearNoneTogglei, 40f, () -> { + configure(item); + }).tooltip(item.localized()).group(group).get(); + + button.update(() -> button.setChecked(command == item || (command == null && unit.defaultCommand == item))); + + if(++i % columns == 0){ + commands.row(); + } + } + + if(list.length < columns){ + for(int j = 0; j < (columns - list.length); j++){ + commands.add().size(40f); + } + } + } + }; + + rebuildCommands.run(); + + UnitType[] lastUnit = {unit()}; + + commands.update(() -> { + if(lastUnit[0] != unit()){ + lastUnit[0] = unit(); + rebuildCommands.run(); + } + }); + + table.row(); + + table.add(commands).fillX().left(); + }else{ table.table(Styles.black3, t -> t.add("@none").color(Color.lightGray)); } @@ -311,9 +381,14 @@ public class UnitFactory extends UnitBlock{ progress %= 1f; Unit unit = plan.unit.create(team); - if(commandPos != null && unit.isCommandable()){ - unit.command().commandPosition(commandPos); + if(unit.isCommandable()){ + if(commandPos != null){ + unit.command().commandPosition(commandPos); + } + + unit.command().command(command == null && payload.unit.type.defaultCommand != null ? payload.unit.type.defaultCommand : command); } + payload = new UnitPayload(unit); payVector.setZero(); consume(); @@ -349,7 +424,7 @@ public class UnitFactory extends UnitBlock{ @Override public byte version(){ - return 2; + return 3; } @Override @@ -358,6 +433,7 @@ public class UnitFactory extends UnitBlock{ write.f(progress); write.s(currentPlan); TypeIO.writeVecNullable(write, commandPos); + TypeIO.writeCommand(write, command); } @Override @@ -368,6 +444,10 @@ public class UnitFactory extends UnitBlock{ if(revision >= 2){ commandPos = TypeIO.readVecNullable(read); } + + if(revision >= 3){ + command = TypeIO.readCommand(read); + } } } }