RTS Control groups

This commit is contained in:
Anuken
2023-09-19 23:48:40 -04:00
parent e6b2e27d2a
commit aecd220574
8 changed files with 119 additions and 18 deletions

View File

@@ -14,6 +14,7 @@ public enum Binding implements KeyBind{
boost(KeyCode.shiftLeft),
command_mode(KeyCode.shiftLeft),
command_queue(KeyCode.mouseMiddle),
create_control_group(KeyCode.controlLeft),
control(KeyCode.controlLeft),
respawn(KeyCode.v),
select(KeyCode.mouseLeft),

View File

@@ -11,6 +11,7 @@ import arc.math.*;
import arc.math.geom.*;
import arc.scene.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
import mindustry.*;
import mindustry.core.*;
@@ -22,6 +23,7 @@ import mindustry.graphics.*;
import mindustry.ui.*;
import mindustry.world.*;
import static arc.Core.camera;
import static arc.Core.*;
import static mindustry.Vars.*;
import static mindustry.input.PlaceMode.*;
@@ -49,6 +51,11 @@ public class DesktopInput extends InputHandler{
/** Previously selected tile. */
public Tile prevSelected;
/** Most recently selected control group by index */
public int lastCtrlGroup;
/** Time of most recent control group selection */
public long lastCtrlGroupSelectMillis;
boolean showHint(){
return ui.hudfrag.shown && Core.settings.getBool("hints") && selectPlans.isEmpty() &&
(!isBuilding && !Core.settings.getBool("buildautopause") || player.unit().isBuilding() || !player.dead() && !player.unit().spawnedByCore());
@@ -262,22 +269,86 @@ public class DesktopInput extends InputHandler{
//validate commanding units
selectedUnits.removeAll(u -> !u.isCommandable() || !u.isValid());
if(commandMode && input.keyTap(Binding.select_all_units) && !scene.hasField() && !scene.hasDialog()){
selectedUnits.clear();
commandBuildings.clear();
for(var unit : player.team().data().units){
if(unit.isCommandable()){
selectedUnits.add(unit);
if(commandMode && !scene.hasField() && !scene.hasDialog()){
if(input.keyTap(Binding.select_all_units)){
selectedUnits.clear();
commandBuildings.clear();
for(var unit : player.team().data().units){
if(unit.isCommandable()){
selectedUnits.add(unit);
}
}
}
}
if(commandMode && input.keyTap(Binding.select_all_unit_factories) && !scene.hasField() && !scene.hasDialog()){
selectedUnits.clear();
commandBuildings.clear();
for(var build : player.team().data().buildings){
if(build.block.commandable){
commandBuildings.add(build);
if(input.keyTap(Binding.select_all_unit_factories)){
selectedUnits.clear();
commandBuildings.clear();
for(var build : player.team().data().buildings){
if(build.block.commandable){
commandBuildings.add(build);
}
}
}
for(int i = 0; i < controlGroupBindings.length; i++){
if(input.keyTap(controlGroupBindings[i])){
//create control group if it doesn't exist yet
if(controlGroups[i] == null) controlGroups[i] = new IntSeq();
IntSeq group = controlGroups[i];
boolean creating = input.keyDown(Binding.create_control_group);
//clear existing if making a new control group
//if any of the control group edit buttons are pressed take the current selection
if(creating){
group.clear();
IntSeq selectedUnitIds = selectedUnits.mapInt(u -> u.id);
if(Core.settings.getBool("distinctcontrolgroups", true)){
for(IntSeq cg : controlGroups){
if(cg != null){
cg.removeAll(selectedUnitIds);
}
}
}
group.addAll(selectedUnitIds);
}
//remove invalid units
for(int j = 0; j < group.size; j++){
Unit u = Groups.unit.getByID(group.get(j));
if(u == null || !u.isCommandable() || !u.isValid()){
group.removeIndex(j);
j --;
}
}
//replace the selected units with the current control group
if(!group.isEmpty() && !creating){
selectedUnits.clear();
commandBuildings.clear();
group.each(id -> {
var unit = Groups.unit.getByID(id);
if(unit != null){
selectedUnits.addAll(unit);
}
});
//double tap to center camera
if(lastCtrlGroup == i && Time.timeSinceMillis(lastCtrlGroupSelectMillis) < 400){
float totalX = 0, totalY = 0;
for(Unit unit : selectedUnits){
totalX += unit.x;
totalY += unit.y;
}
panning = true;
Core.camera.position.set(totalX / selectedUnits.size, totalY / selectedUnits.size);
}
lastCtrlGroup = i;
lastCtrlGroupSelectMillis = Time.millis();
}
}
}
}

View File

@@ -53,6 +53,18 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
final static int maxLength = 100;
final static Rect r1 = new Rect(), r2 = new Rect();
final static Seq<Unit> tmpUnits = new Seq<>(false);
final static Binding[] controlGroupBindings = {
Binding.block_select_01,
Binding.block_select_02,
Binding.block_select_03,
Binding.block_select_04,
Binding.block_select_05,
Binding.block_select_06,
Binding.block_select_07,
Binding.block_select_08,
Binding.block_select_09,
Binding.block_select_10
};
/** If true, there is a cutscene currently occurring in logic. */
public boolean logicCutscene;
@@ -87,6 +99,8 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
public boolean commandRect = false;
public boolean tappedOne = false;
public float commandRectX, commandRectY;
/** Groups of units saved to different hotkeys */
public IntSeq[] controlGroups = new IntSeq[controlGroupBindings.length];
private Seq<BuildPlan> plansOut = new Seq<>(BuildPlan.class);
private QuadTree<BuildPlan> playerPlanTree = new QuadTree<>(new Rect());
@@ -124,6 +138,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
Events.on(ResetEvent.class, e -> {
logicCutscene = false;
Arrays.fill(controlGroups, null);
});
}