Unit command prototype

This commit is contained in:
Anuken
2022-02-08 18:30:35 -05:00
parent 2fabd39ea1
commit f9efbb6686
15 changed files with 146 additions and 20 deletions

View File

@@ -12,6 +12,7 @@ public enum Binding implements KeyBind{
pan(KeyCode.mouseForward),
boost(KeyCode.shiftLeft),
commandMode(KeyCode.shiftLeft),
control(KeyCode.controlLeft),
respawn(KeyCode.v),
select(KeyCode.mouseLeft),

View File

@@ -12,6 +12,8 @@ import arc.scene.ui.*;
import arc.scene.ui.layout.*;
import arc.util.*;
import mindustry.*;
import mindustry.ai.types.*;
import mindustry.content.*;
import mindustry.core.*;
import mindustry.entities.units.*;
import mindustry.game.EventType.*;
@@ -114,6 +116,27 @@ public class DesktopInput extends InputHandler{
drawSelection(schemX, schemY, cursorX, cursorY, Vars.maxSchematicSize);
}
for(Unit unit : selectedUnits){
CommandAI ai = (CommandAI)unit.controller();
//draw target line
if(ai.targetPos != null){
Tmp.v1.set(ai.targetPos).sub(unit).setLength(unit.hitSize / 2f);
Drawf.dashLine(Pal.accent, unit.x + Tmp.v1.x, unit.y + Tmp.v1.y, ai.targetPos.x, ai.targetPos.y);
}
Drawf.square(unit.x, unit.y, unit.hitSize / 1.4f + 1f);
}
//draw command overlay UI
if(commandMode){
Unit sel = selectedCommandUnit(input.mouseWorldX(), input.mouseWorldY());
if(sel != null){
Drawf.square(sel.x, sel.y, sel.hitSize / 1.4f + Mathf.absin(4f, 1f), selectedUnits.contains(sel) ? Pal.remove : Pal.accent);
}
}
Draw.reset();
}
@@ -220,11 +243,19 @@ public class DesktopInput extends InputHandler{
Core.camera.position.x += Mathf.clamp((Core.input.mouseX() - Core.graphics.getWidth() / 2f) * panScale, -1, 1) * camSpeed;
Core.camera.position.y += Mathf.clamp((Core.input.mouseY() - Core.graphics.getHeight() / 2f) * panScale, -1, 1) * camSpeed;
}
}
commandMode = input.keyDown(Binding.commandMode) && !locked && state.rules.unitCommand && block == null;
shouldShoot = !scene.hasMouse() && !locked;
//TODO should selected units be cleared out of command mode?
if(!commandMode){
selectedUnits.clear();
}
//validate commanding units
selectedUnits.removeAll(u -> !u.isCommandable());
if(!scene.hasMouse() && !locked){
if(Core.input.keyDown(Binding.control) && Core.input.keyTap(Binding.select)){
Unit on = selectedUnit();
@@ -503,6 +534,26 @@ public class DesktopInput extends InputHandler{
sreq = req;
}else if(req != null && req.breaking){
deleting = true;
}else if(commandMode){
Unit unit = selectedCommandUnit(input.mouseWorldX(), input.mouseWorldY());
if(unit != null){
if(selectedUnits.contains(unit)){
selectedUnits.remove(unit);
}else{
selectedUnits.add(unit);
}
}else if(selectedUnits.size > 0){
//move to location - TODO right click instead?
//TODO all this needs to be synced, done with packets, etc
Vec2 target = input.mouseWorld().cpy();
for(var sel : selectedUnits){
((CommandAI)sel.controller()).commandPosition(target);
}
Fx.moveCommand.at(target);
}
}else if(selected != null){
//only begin shooting if there's no cursor event
if(!tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && !tileTapped(selected.build) && !player.unit().activelyBuilding() && !droppingItem
@@ -520,7 +571,7 @@ public class DesktopInput extends InputHandler{
}else if(Core.input.keyTap(Binding.deselect) && !selectRequests.isEmpty()){
selectRequests.clear();
lastSchematic = null;
}else if(Core.input.keyTap(Binding.break_block) && !Core.scene.hasMouse() && player.isBuilder()){
}else if(Core.input.keyTap(Binding.break_block) && !Core.scene.hasMouse() && player.isBuilder() && !commandMode){
//is recalculated because setting the mode to breaking removes potential multiblock cursor offset
deleting = false;
mode = breaking;

View File

@@ -48,6 +48,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
/** Maximum line length. */
final static int maxLength = 100;
final static Rect r1 = new Rect(), r2 = new Rect();
final static Seq<Unit> tmpUnits = new Seq<>();
public final OverlayFragment frag = new OverlayFragment();
@@ -71,6 +72,10 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
public Seq<BuildPlan> lineRequests = new Seq<>();
public Seq<BuildPlan> selectRequests = new Seq<>();
//for RTS controls
public Seq<Unit> selectedUnits = new Seq<>();
public boolean commandMode = false;
private Seq<BuildPlan> plansOut = new Seq<>(BuildPlan.class);
private QuadTree<BuildPlan> playerPlanTree = new QuadTree<>(new Rect());
@@ -1183,6 +1188,14 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
return null;
}
public @Nullable Unit selectedCommandUnit(float x, float y){
var tree = player.team().data().tree();
tmpUnits.clear();
float rad = 4f;
tree.intersect(x - rad/2f, y - rad/2f, rad, rad, tmpUnits);
return tmpUnits.min(u -> u.isCommandable(), u -> u.dst(x, y) - u.hitSize/2f);
}
public void remove(){
Core.input.removeProcessor(this);
frag.remove();
@@ -1225,7 +1238,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
public boolean canShoot(){
return block == null && !onConfigurable() && !isDroppingItem() && !player.unit().activelyBuilding() &&
!(player.unit() instanceof Mechc && player.unit().isFlying()) && !player.unit().mining();
!(player.unit() instanceof Mechc && player.unit().isFlying()) && !player.unit().mining() && !commandMode;
}
public boolean onConfigurable(){