Command setting UI for unit factories
This commit is contained in:
@@ -322,7 +322,7 @@ public class UnitTypes{
|
|||||||
speed = 0.55f;
|
speed = 0.55f;
|
||||||
hitSize = 8f;
|
hitSize = 8f;
|
||||||
health = 120f;
|
health = 120f;
|
||||||
buildSpeed = 0.35f;
|
buildSpeed = 0.3f;
|
||||||
armor = 1f;
|
armor = 1f;
|
||||||
|
|
||||||
abilities.add(new RepairFieldAbility(10f, 60f * 4, 60f));
|
abilities.add(new RepairFieldAbility(10f, 60f * 4, 60f));
|
||||||
@@ -1256,6 +1256,7 @@ public class UnitTypes{
|
|||||||
controller = u -> new MinerAI();
|
controller = u -> new MinerAI();
|
||||||
|
|
||||||
defaultCommand = UnitCommand.mineCommand;
|
defaultCommand = UnitCommand.mineCommand;
|
||||||
|
allowChangeCommands = false;
|
||||||
|
|
||||||
flying = true;
|
flying = true;
|
||||||
drag = 0.06f;
|
drag = 0.06f;
|
||||||
|
|||||||
@@ -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. */
|
/** 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};
|
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(). */
|
/** 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 = {};
|
public UnitCommand[] commands = {};
|
||||||
/** Command to assign to this unit upon creation. Null indicates the first command in the array. */
|
/** 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();
|
commands = cmds.toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(defaultCommand == null && commands.length > 0){
|
||||||
|
defaultCommand = commands[0];
|
||||||
|
}
|
||||||
|
|
||||||
if(stances.length == 0){
|
if(stances.length == 0){
|
||||||
if(canAttack){
|
if(canAttack){
|
||||||
Seq<UnitStance> seq = Seq.with(UnitStance.stop, UnitStance.shoot, UnitStance.holdFire, UnitStance.pursueTarget, UnitStance.patrol);
|
Seq<UnitStance> seq = Seq.with(UnitStance.stop, UnitStance.shoot, UnitStance.holdFire, UnitStance.pursueTarget, UnitStance.patrol);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package mindustry.world.blocks;
|
package mindustry.world.blocks;
|
||||||
|
|
||||||
|
import arc.*;
|
||||||
import arc.func.*;
|
import arc.func.*;
|
||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
import arc.scene.style.*;
|
import arc.scene.style.*;
|
||||||
@@ -93,6 +94,11 @@ public class ItemSelection{
|
|||||||
|
|
||||||
ScrollPane pane = new ScrollPane(cont, Styles.smallPane);
|
ScrollPane pane = new ScrollPane(cont, Styles.smallPane);
|
||||||
pane.setScrollingDisabled(true, false);
|
pane.setScrollingDisabled(true, false);
|
||||||
|
pane.exited(() -> {
|
||||||
|
if(pane.hasScroll()){
|
||||||
|
Core.scene.setScrollFocus(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if(block != null){
|
if(block != null){
|
||||||
pane.setScrollYForce(block.selectScroll);
|
pane.setScrollYForce(block.selectScroll);
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ public class Reconstructor extends UnitBlock{
|
|||||||
|
|
||||||
public boolean canSetCommand(){
|
public boolean canSetCommand(){
|
||||||
var output = unit();
|
var output = unit();
|
||||||
return output != null && output.commands.length > 1;
|
return output != null && output.commands.length > 1 && output.allowChangeCommands;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -6,11 +6,13 @@ import arc.graphics.g2d.*;
|
|||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
import arc.scene.style.*;
|
import arc.scene.style.*;
|
||||||
|
import arc.scene.ui.*;
|
||||||
import arc.scene.ui.layout.*;
|
import arc.scene.ui.layout.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import arc.util.io.*;
|
import arc.util.io.*;
|
||||||
import mindustry.*;
|
import mindustry.*;
|
||||||
|
import mindustry.ai.*;
|
||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
import mindustry.entities.units.*;
|
import mindustry.entities.units.*;
|
||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
@@ -46,23 +48,32 @@ public class UnitFactory extends UnitBlock{
|
|||||||
commandable = true;
|
commandable = true;
|
||||||
ambientSound = Sounds.respawning;
|
ambientSound = Sounds.respawning;
|
||||||
|
|
||||||
config(Integer.class, (UnitFactoryBuild tile, Integer i) -> {
|
config(Integer.class, (UnitFactoryBuild build, Integer i) -> {
|
||||||
if(!configurable) return;
|
if(!configurable) return;
|
||||||
|
|
||||||
if(tile.currentPlan == i) return;
|
if(build.currentPlan == i) return;
|
||||||
tile.currentPlan = i < 0 || i >= plans.size ? -1 : i;
|
build.currentPlan = i < 0 || i >= plans.size ? -1 : i;
|
||||||
tile.progress = 0;
|
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;
|
if(!configurable) return;
|
||||||
|
|
||||||
int next = plans.indexOf(p -> p.unit == val);
|
int next = plans.indexOf(p -> p.unit == val);
|
||||||
if(tile.currentPlan == next) return;
|
if(build.currentPlan == next) return;
|
||||||
tile.currentPlan = next;
|
build.currentPlan = next;
|
||||||
tile.progress = 0;
|
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));
|
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 class UnitFactoryBuild extends UnitBuild{
|
||||||
public @Nullable Vec2 commandPos;
|
public @Nullable Vec2 commandPos;
|
||||||
|
public @Nullable UnitCommand command;
|
||||||
public int currentPlan = -1;
|
public int currentPlan = -1;
|
||||||
|
|
||||||
public float fraction(){
|
public float fraction(){
|
||||||
return currentPlan == -1 ? 0 : progress / plans.get(currentPlan).time;
|
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
|
@Override
|
||||||
public void created(){
|
public void created(){
|
||||||
//auto-set to the first plan, it's better than nothing.
|
//auto-set to the first plan, it's better than nothing.
|
||||||
@@ -225,6 +242,59 @@ public class UnitFactory extends UnitBlock{
|
|||||||
|
|
||||||
if(units.any()){
|
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);
|
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<ImageButton>();
|
||||||
|
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{
|
}else{
|
||||||
table.table(Styles.black3, t -> t.add("@none").color(Color.lightGray));
|
table.table(Styles.black3, t -> t.add("@none").color(Color.lightGray));
|
||||||
}
|
}
|
||||||
@@ -311,9 +381,14 @@ public class UnitFactory extends UnitBlock{
|
|||||||
progress %= 1f;
|
progress %= 1f;
|
||||||
|
|
||||||
Unit unit = plan.unit.create(team);
|
Unit unit = plan.unit.create(team);
|
||||||
if(commandPos != null && unit.isCommandable()){
|
if(unit.isCommandable()){
|
||||||
unit.command().commandPosition(commandPos);
|
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);
|
payload = new UnitPayload(unit);
|
||||||
payVector.setZero();
|
payVector.setZero();
|
||||||
consume();
|
consume();
|
||||||
@@ -349,7 +424,7 @@ public class UnitFactory extends UnitBlock{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte version(){
|
public byte version(){
|
||||||
return 2;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -358,6 +433,7 @@ public class UnitFactory extends UnitBlock{
|
|||||||
write.f(progress);
|
write.f(progress);
|
||||||
write.s(currentPlan);
|
write.s(currentPlan);
|
||||||
TypeIO.writeVecNullable(write, commandPos);
|
TypeIO.writeVecNullable(write, commandPos);
|
||||||
|
TypeIO.writeCommand(write, command);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -368,6 +444,10 @@ public class UnitFactory extends UnitBlock{
|
|||||||
if(revision >= 2){
|
if(revision >= 2){
|
||||||
commandPos = TypeIO.readVecNullable(read);
|
commandPos = TypeIO.readVecNullable(read);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(revision >= 3){
|
||||||
|
command = TypeIO.readCommand(read);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user