Cleanup & control fixes
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
@@ -844,7 +844,6 @@ bar.output = Output
|
|||||||
bar.strength = [stat]{0}[lightgray]x strength
|
bar.strength = [stat]{0}[lightgray]x strength
|
||||||
|
|
||||||
units.processorcontrol = [lightgray]Processor Controlled
|
units.processorcontrol = [lightgray]Processor Controlled
|
||||||
units.nocontroller = [lightgray]\ue815 No Controller
|
|
||||||
|
|
||||||
bullet.damage = [stat]{0}[lightgray] damage
|
bullet.damage = [stat]{0}[lightgray] damage
|
||||||
bullet.splashdamage = [stat]{0}[lightgray] area dmg ~[stat] {1}[lightgray] tiles
|
bullet.splashdamage = [stat]{0}[lightgray] area dmg ~[stat] {1}[lightgray] tiles
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import static mindustry.ai.Pathfinder.*;
|
|||||||
//TODO I'm sure this class has countless problems
|
//TODO I'm sure this class has countless problems
|
||||||
public class ControlPathfinder implements Runnable{
|
public class ControlPathfinder implements Runnable{
|
||||||
private static final long maxUpdate = Time.millisToNanos(20);
|
private static final long maxUpdate = Time.millisToNanos(20);
|
||||||
private static final int updateFPS = 40;
|
private static final int updateFPS = 60;
|
||||||
private static final int updateInterval = 1000 / updateFPS;
|
private static final int updateInterval = 1000 / updateFPS;
|
||||||
|
|
||||||
public static boolean showDebug = false;
|
public static boolean showDebug = false;
|
||||||
@@ -151,6 +151,7 @@ public class ControlPathfinder implements Runnable{
|
|||||||
req.destination.set(destination);
|
req.destination.set(destination);
|
||||||
req.curId = pathId;
|
req.curId = pathId;
|
||||||
req.lastUpdateId = state.updateId;
|
req.lastUpdateId = state.updateId;
|
||||||
|
req.lastPos.set(unit);
|
||||||
req.lastWorldUpdate = worldUpdateId;
|
req.lastWorldUpdate = worldUpdateId;
|
||||||
|
|
||||||
requests.put(unit, req);
|
requests.put(unit, req);
|
||||||
@@ -170,6 +171,16 @@ public class ControlPathfinder implements Runnable{
|
|||||||
req.destination.set(destination);
|
req.destination.set(destination);
|
||||||
req.curId = pathId;
|
req.curId = pathId;
|
||||||
|
|
||||||
|
//check for the unit getting stuck every N seconds
|
||||||
|
if((req.stuckTimer += Time.delta) >= 60f * 5f){
|
||||||
|
req.stuckTimer = 0f;
|
||||||
|
//force recalculate
|
||||||
|
if(req.lastPos.within(unit, 1f)){
|
||||||
|
req.lastWorldUpdate = -1;
|
||||||
|
}
|
||||||
|
req.lastPos.set(unit);
|
||||||
|
}
|
||||||
|
|
||||||
if(req.done){
|
if(req.done){
|
||||||
int[] items = req.result.items;
|
int[] items = req.result.items;
|
||||||
int len = req.result.size;
|
int len = req.result.size;
|
||||||
@@ -193,11 +204,9 @@ public class ControlPathfinder implements Runnable{
|
|||||||
req.rayPathIndex = req.pathIndex;
|
req.rayPathIndex = req.pathIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO indecision dance: moving forward blocks the raycasted node from view, so it moves back.
|
|
||||||
if((req.raycastTimer += Time.delta) >= 50f){
|
if((req.raycastTimer += Time.delta) >= 50f){
|
||||||
for(int i = len - 1; i > req.pathIndex; i--){
|
for(int i = len - 1; i > req.pathIndex; i--){
|
||||||
int val = items[i];
|
int val = items[i];
|
||||||
//TODO this raycasting is flawed, it assumes units can move through corners even when they can't.
|
|
||||||
if(!raycast(pathType, tileX, tileY, val % wwidth, val / wwidth)){
|
if(!raycast(pathType, tileX, tileY, val % wwidth, val / wwidth)){
|
||||||
req.rayPathIndex = i;
|
req.rayPathIndex = i;
|
||||||
break;
|
break;
|
||||||
@@ -343,6 +352,7 @@ public class ControlPathfinder implements Runnable{
|
|||||||
|
|
||||||
//total update time no longer than maxUpdate
|
//total update time no longer than maxUpdate
|
||||||
for(var req : threadRequests){
|
for(var req : threadRequests){
|
||||||
|
//TODO this is flawed with many paths
|
||||||
req.update(maxUpdate / requests.size);
|
req.update(maxUpdate / requests.size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -365,6 +375,9 @@ public class ControlPathfinder implements Runnable{
|
|||||||
volatile boolean done = false;
|
volatile boolean done = false;
|
||||||
volatile boolean foundEnd = false;
|
volatile boolean foundEnd = false;
|
||||||
|
|
||||||
|
final Vec2 lastPos = new Vec2();
|
||||||
|
float stuckTimer = 0f;
|
||||||
|
|
||||||
final Vec2 destination = new Vec2();
|
final Vec2 destination = new Vec2();
|
||||||
final Vec2 lastDestination = new Vec2();
|
final Vec2 lastDestination = new Vec2();
|
||||||
|
|
||||||
@@ -373,7 +386,8 @@ public class ControlPathfinder implements Runnable{
|
|||||||
volatile int lastWorldUpdate;
|
volatile int lastWorldUpdate;
|
||||||
|
|
||||||
//TODO only access on main thread??
|
//TODO only access on main thread??
|
||||||
int pathIndex;
|
volatile int pathIndex;
|
||||||
|
|
||||||
int rayPathIndex = -1;
|
int rayPathIndex = -1;
|
||||||
IntSeq result = new IntSeq();
|
IntSeq result = new IntSeq();
|
||||||
float raycastTimer;
|
float raycastTimer;
|
||||||
@@ -386,13 +400,11 @@ public class ControlPathfinder implements Runnable{
|
|||||||
|
|
||||||
int start, goal;
|
int start, goal;
|
||||||
|
|
||||||
|
long lastUpdateId;
|
||||||
long lastTime;
|
long lastTime;
|
||||||
|
|
||||||
volatile int lastId, curId;
|
volatile int lastId, curId;
|
||||||
|
|
||||||
//TODO invalidate when not request for a while
|
|
||||||
long lastUpdateId;
|
|
||||||
|
|
||||||
void update(long maxUpdateNs){
|
void update(long maxUpdateNs){
|
||||||
if(curId != lastId){
|
if(curId != lastId){
|
||||||
clear();
|
clear();
|
||||||
|
|||||||
@@ -19,11 +19,6 @@ public class SuicideAI extends GroundAI{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateUnit(){
|
public void updateUnit(){
|
||||||
if(disabled()){
|
|
||||||
stopShooting();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Units.invalidateTarget(target, unit.team, unit.x, unit.y, Float.MAX_VALUE)){
|
if(Units.invalidateTarget(target, unit.team, unit.x, unit.y, Float.MAX_VALUE)){
|
||||||
target = null;
|
target = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3144,6 +3144,7 @@ public class Blocks{
|
|||||||
coolantOverride = Liquids.water;
|
coolantOverride = Liquids.water;
|
||||||
coolantMultiplier = 6f;
|
coolantMultiplier = 6f;
|
||||||
|
|
||||||
|
unitFilter = u -> !u.spawnedByCore;
|
||||||
shootShake = 1f;
|
shootShake = 1f;
|
||||||
ammoPerShot = 5;
|
ammoPerShot = 5;
|
||||||
draw = new DrawTurret("reinforced-");
|
draw = new DrawTurret("reinforced-");
|
||||||
@@ -3497,7 +3498,7 @@ public class Blocks{
|
|||||||
requirements(Category.units, with(Items.graphite, 600, Items.beryllium, 600, Items.oxide, 200, Items.tungsten, 500));
|
requirements(Category.units, with(Items.graphite, 600, Items.beryllium, 600, Items.oxide, 200, Items.tungsten, 500));
|
||||||
size = 5;
|
size = 5;
|
||||||
//TODO requirements?
|
//TODO requirements?
|
||||||
plans.add(new AssemblerUnitPlan(UnitTypes.vanquish, 60f * 35f, BlockStack.list(Blocks.tungstenWallLarge, 6, Blocks.duct, 14, Blocks.cliffCrusher, 10)));
|
plans.add(new AssemblerUnitPlan(UnitTypes.vanquish, 60f * 50f, BlockStack.list(Blocks.tungstenWallLarge, 6, Blocks.duct, 14, Blocks.cliffCrusher, 12)));
|
||||||
consumes.power(3f);
|
consumes.power(3f);
|
||||||
areaSize = 13;
|
areaSize = 13;
|
||||||
|
|
||||||
@@ -3508,8 +3509,8 @@ public class Blocks{
|
|||||||
shipAssembler = new UnitAssembler("ship-assembler"){{
|
shipAssembler = new UnitAssembler("ship-assembler"){{
|
||||||
requirements(Category.units, with(Items.beryllium, 700, Items.oxide, 150, Items.tungsten, 500, Items.silicon, 800));
|
requirements(Category.units, with(Items.beryllium, 700, Items.oxide, 150, Items.tungsten, 500, Items.silicon, 800));
|
||||||
size = 5;
|
size = 5;
|
||||||
plans.add(new AssemblerUnitPlan(UnitTypes.quell, 60f * 25f, BlockStack.list(Blocks.berylliumWallLarge, 4, Blocks.duct, 10, Blocks.plasmaBore, 4)));
|
plans.add(new AssemblerUnitPlan(UnitTypes.quell, 60f * 40f, BlockStack.list(Blocks.berylliumWallLarge, 4, Blocks.duct, 10, Blocks.plasmaBore, 4)));
|
||||||
consumes.power(2f);
|
consumes.power(3f);
|
||||||
areaSize = 13;
|
areaSize = 13;
|
||||||
|
|
||||||
//consumes.liquid(Liquids.gallium, 2f / 60f);
|
//consumes.liquid(Liquids.gallium, 2f / 60f);
|
||||||
@@ -3520,8 +3521,8 @@ public class Blocks{
|
|||||||
mechAssembler = new UnitAssembler("mech-assembler"){{
|
mechAssembler = new UnitAssembler("mech-assembler"){{
|
||||||
requirements(Category.units, with(Items.graphite, 600, Items.carbide, 600, Items.oxide, 200, Items.tungsten, 500));
|
requirements(Category.units, with(Items.graphite, 600, Items.carbide, 600, Items.oxide, 200, Items.tungsten, 500));
|
||||||
size = 5;
|
size = 5;
|
||||||
plans.add(new AssemblerUnitPlan(UnitTypes.bulwark, 60f * 40f, BlockStack.list(Blocks.tungstenWallLarge, 5, Blocks.duct, 2)));
|
plans.add(new AssemblerUnitPlan(UnitTypes.bulwark, 60f * 60f, BlockStack.list(Blocks.tungstenWallLarge, 5, Blocks.duct, 2)));
|
||||||
consumes.power(2f);
|
consumes.power(3f);
|
||||||
areaSize = 13;
|
areaSize = 13;
|
||||||
|
|
||||||
//consumes.liquid(Liquids.gallium, 2f / 60f);
|
//consumes.liquid(Liquids.gallium, 2f / 60f);
|
||||||
@@ -3605,6 +3606,7 @@ public class Blocks{
|
|||||||
constructor = new Constructor("constructor"){{
|
constructor = new Constructor("constructor"){{
|
||||||
requirements(Category.units, with(Items.silicon, 100, Items.beryllium, 150, Items.tungsten, 80));
|
requirements(Category.units, with(Items.silicon, 100, Items.beryllium, 150, Items.tungsten, 80));
|
||||||
hasPower = true;
|
hasPower = true;
|
||||||
|
buildSpeed = 0.3f;
|
||||||
consumes.power(2f);
|
consumes.power(2f);
|
||||||
size = 3;
|
size = 3;
|
||||||
}};
|
}};
|
||||||
@@ -3614,6 +3616,7 @@ public class Blocks{
|
|||||||
requirements(Category.units, with(Items.silicon, 150, Items.oxide, 150, Items.tungsten, 200, Items.phaseFabric, 40));
|
requirements(Category.units, with(Items.silicon, 150, Items.oxide, 150, Items.tungsten, 200, Items.phaseFabric, 40));
|
||||||
hasPower = true;
|
hasPower = true;
|
||||||
consumes.power(2f);
|
consumes.power(2f);
|
||||||
|
buildSpeed = 0.3f;
|
||||||
maxBlockSize = 4;
|
maxBlockSize = 4;
|
||||||
minBlockSize = 3;
|
minBlockSize = 3;
|
||||||
size = 5;
|
size = 5;
|
||||||
|
|||||||
@@ -3323,7 +3323,6 @@ public class UnitTypes{
|
|||||||
|
|
||||||
manifold = new ErekirUnitType("manifold"){{
|
manifold = new ErekirUnitType("manifold"){{
|
||||||
defaultController = CargoAI::new;
|
defaultController = CargoAI::new;
|
||||||
defaultAI = true;
|
|
||||||
isCounted = false;
|
isCounted = false;
|
||||||
allowedInPayloads = false;
|
allowedInPayloads = false;
|
||||||
logicControllable = false;
|
logicControllable = false;
|
||||||
@@ -3350,7 +3349,6 @@ public class UnitTypes{
|
|||||||
assemblyDrone = new ErekirUnitType("assembly-drone"){{
|
assemblyDrone = new ErekirUnitType("assembly-drone"){{
|
||||||
defaultController = AssemblerAI::new;
|
defaultController = AssemblerAI::new;
|
||||||
|
|
||||||
defaultAI = true;
|
|
||||||
flying = true;
|
flying = true;
|
||||||
drag = 0.06f;
|
drag = 0.06f;
|
||||||
accel = 0.11f;
|
accel = 0.11f;
|
||||||
|
|||||||
@@ -33,11 +33,6 @@ public class AIController implements UnitController{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateUnit(){
|
public void updateUnit(){
|
||||||
if(disabled()){
|
|
||||||
stopShooting();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//use fallback AI when possible
|
//use fallback AI when possible
|
||||||
if(useFallback() && (fallback != null || (fallback = fallback()) != null)){
|
if(useFallback() && (fallback != null || (fallback = fallback()) != null)){
|
||||||
if(fallback.unit != unit) fallback.unit(unit);
|
if(fallback.unit != unit) fallback.unit(unit);
|
||||||
@@ -57,10 +52,6 @@ public class AIController implements UnitController{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean disabled(){
|
|
||||||
return !unit.team.isAI() && !unit.type.defaultAI;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public AIController fallback(){
|
public AIController fallback(){
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -69,8 +69,6 @@ public class UnitType extends UnlockableContent{
|
|||||||
public boolean logicControllable = true;
|
public boolean logicControllable = true;
|
||||||
public boolean playerControllable = true;
|
public boolean playerControllable = true;
|
||||||
public boolean allowedInPayloads = true;
|
public boolean allowedInPayloads = true;
|
||||||
/** If false, this unit has no AI when not controlled by a player, regardless of AI controller. */
|
|
||||||
public boolean defaultAI = true;
|
|
||||||
/** TODO If true, core units need to "dock" to this unit to work, and can un-dock at the unit instead of respawning at core. */
|
/** TODO If true, core units need to "dock" to this unit to work, and can un-dock at the unit instead of respawning at core. */
|
||||||
public boolean coreUnitDock = false;
|
public boolean coreUnitDock = false;
|
||||||
public boolean createWreck = true;
|
public boolean createWreck = true;
|
||||||
@@ -302,10 +300,6 @@ public class UnitType extends UnlockableContent{
|
|||||||
}
|
}
|
||||||
}).growX();
|
}).growX();
|
||||||
|
|
||||||
if(coreUnitDock && !defaultAI){
|
|
||||||
table.row().add("@units.nocontroller").growX().left().row();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(unit.controller() instanceof LogicAI){
|
if(unit.controller() instanceof LogicAI){
|
||||||
table.row();
|
table.row();
|
||||||
table.add(Blocks.microProcessor.emoji() + " " + Core.bundle.get("units.processorcontrol")).growX().wrap().left();
|
table.add(Blocks.microProcessor.emoji() + " " + Core.bundle.get("units.processorcontrol")).growX().wrap().left();
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ public class ErekirUnitType extends UnitType{
|
|||||||
commandLimit = 0;
|
commandLimit = 0;
|
||||||
outlineColor = Pal.darkOutline;
|
outlineColor = Pal.darkOutline;
|
||||||
envDisabled = Env.space;
|
envDisabled = Env.space;
|
||||||
//TODO necessary, or not?
|
|
||||||
defaultAI = false;
|
|
||||||
coreUnitDock = true;
|
coreUnitDock = true;
|
||||||
unitBasedDefaultController = u -> !playerControllable || u.team.isAI() ? defaultController.get() : new CommandAI();
|
unitBasedDefaultController = u -> !playerControllable || u.team.isAI() ? defaultController.get() : new CommandAI();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ public class Turret extends ReloadTurret{
|
|||||||
public boolean playerControllable = true;
|
public boolean playerControllable = true;
|
||||||
public boolean displayAmmoMultiplier = true;
|
public boolean displayAmmoMultiplier = true;
|
||||||
public Sortf unitSort = UnitSorts.closest;
|
public Sortf unitSort = UnitSorts.closest;
|
||||||
|
public Boolf<Unit> unitFilter = u -> true;
|
||||||
|
|
||||||
public DrawBlock draw = new DrawTurret();
|
public DrawBlock draw = new DrawTurret();
|
||||||
|
|
||||||
@@ -419,9 +420,9 @@ public class Turret extends ReloadTurret{
|
|||||||
float range = range();
|
float range = range();
|
||||||
|
|
||||||
if(targetAir && !targetGround){
|
if(targetAir && !targetGround){
|
||||||
target = Units.bestEnemy(team, x, y, range, e -> !e.dead() && !e.isGrounded(), unitSort);
|
target = Units.bestEnemy(team, x, y, range, e -> !e.dead() && !e.isGrounded() && unitFilter.get(e), unitSort);
|
||||||
}else{
|
}else{
|
||||||
target = Units.bestTarget(team, x, y, range, e -> !e.dead() && (e.isGrounded() || targetAir) && (!e.isGrounded() || targetGround), b -> targetGround, unitSort);
|
target = Units.bestTarget(team, x, y, range, e -> !e.dead() && unitFilter.get(e) && (e.isGrounded() || targetAir) && (!e.isGrounded() || targetGround), b -> targetGround, unitSort);
|
||||||
|
|
||||||
if(target == null && canHeal()){
|
if(target == null && canHeal()){
|
||||||
target = Units.findAllyTile(team, x, y, range, b -> b.damaged() && b != this);
|
target = Units.findAllyTile(team, x, y, range, b -> b.damaged() && b != this);
|
||||||
|
|||||||
Reference in New Issue
Block a user