Cleanup & control fixes

This commit is contained in:
Anuken
2022-02-09 19:58:08 -05:00
parent e0b3003c95
commit 4278c057b4
10 changed files with 30 additions and 39 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

-1
View File
@@ -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
View File
@@ -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;
} }
+8 -5
View File
@@ -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;
-6
View File
@@ -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);