From 4278c057b4d29e8e8bf11096972deb9a253c3c0f Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 9 Feb 2022 19:58:08 -0500 Subject: [PATCH] Cleanup & control fixes --- .../blocks/turrets/afflict/afflict.png | Bin 0 -> 1879 bytes core/assets/bundles/bundle.properties | 1 - core/src/mindustry/ai/ControlPathfinder.java | 26 +++++++++++++----- core/src/mindustry/ai/types/SuicideAI.java | 5 ---- core/src/mindustry/content/Blocks.java | 13 +++++---- core/src/mindustry/content/UnitTypes.java | 2 -- .../entities/units/AIController.java | 9 ------ core/src/mindustry/type/UnitType.java | 6 ---- .../mindustry/type/unit/ErekirUnitType.java | 2 -- .../world/blocks/defense/turrets/Turret.java | 5 ++-- 10 files changed, 30 insertions(+), 39 deletions(-) create mode 100644 core/assets-raw/sprites/blocks/turrets/afflict/afflict.png diff --git a/core/assets-raw/sprites/blocks/turrets/afflict/afflict.png b/core/assets-raw/sprites/blocks/turrets/afflict/afflict.png new file mode 100644 index 0000000000000000000000000000000000000000..d62f5abc791b22716658b6a1b2d5b67a6a732f0d GIT binary patch literal 1879 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg4mJh`hQoG=rx_R+7>k44ofy`glX=O&z%JqB|A>uKUeDIW7rszmZ`aJyZX|g^8!#10FE%kg>eOo%8H&jRUUd2&h4&yW!Sm&p|hZ@3NilFUr?)3WG3fNpmTb~wOpq|sX1UDx;bp(!?Y>JP z3>6Y4(kz!59%P>J5%6JjXi?nk;K2UiZ+pA^8P3@r$}?&=zYcR@O_wdQJJmm z?zTmY8^kN7t-QVH`SRl>)64IbE@qf;_JwV3?|HU^^CC=5*%M4YXa7H~=9cTrC~>vs zWOZapY_c)KrdjpH)#96UgQsmZV@z=Stb04*#Hwd^8P4R`E!Oppyt0qGA=_a7&1J1s zwi#>+m;QvWzyGJ=>#wtU|K0Nu__Q6X>s?Y47b7v**GrjxPvn4h) zC|s&hI9S!NnJHpc{1*0uf)YL)i_WqOF)$Qx6{g*}_F=QP%`uTew$F_!3=!U0H_pDD z`{P$#%WoFlS$qv!wIY_UWQbVZ^mP_ngIID@ILldt?#!PUeK#;HB69 z-1;w3dtIdPu;vqvgsCg0{+#q(C;3M3mAl6_1Up>2y;`tqjq3}E1V@4R<`0euC5%c_ z6~7lSFytw2(&IXtV3)w-aK52q;~|aLi!RKIS-almOg}@U!iilPCX;_Myc7}Ob-d=f z@a7rzj^qXnj&s*IGQ?UkZm-i^{F9+l;015v6@{}+6Rz29JC$X(fMr3dptC>ItbbdM zWr($W`Eqshhs8_FZv8vLP@%qP=CoW}lWdUiOWUJsK6yepHs;R^ zXS~(0_RREo*3n`uS8k;_C6s2}75-`zAXTyC=PijniV3s$E$;AGc`G#kycMxWAz?PZ z1oMZlck4chb#6F&z2?~(|L%_`1JCwl-O>82+)&!kF#qSR^P3cRh%DYVCAcAV!M$hM z+dnonB-%O1FmGVeJGDh;wk-GNX;&N-v_JSf6W^GW^xoskYKGS=Mzi8mWTkJ{9LV%t z5UMoutp291i-&6zPA&@QbTinWu_Pjt!DVfV?8*hMfri<(Ld+Y^T+e3VaAA-!J>mD^ z{Qdl$vKAe44^Lzd;_zdXIQyp~pUXBljbjyq&gZwkPH;8;(t0rK?EAOcTurk=7<4}W z{(Xk6QKDhu+5DYN6LXB2S&|rLRL@-cbMN9ux6;4gI>*tdrgl}cfw8gur>hXhIlIZS zOu0I*922fBy>aPq-1*IoTla0c_SDDsJJTlHo`tgWzt~7eyf%)GRms{XIVJVUT`P;d zJNF*GUjF~@R=?u(#s$mIuiM>t@%la6aJAdHYj0_Gt?PDkzQdO`>wK2};TaB#zA)UW z|M~xM^tCj@TeWpnC6U+fufD>t=kK>KuS**roLO>fp1R?VZ!H;TXH_A)y8oZ0c*cc#Ao!BVro z@ooD#X>G|c6FE#I`a&>&^hJ`r-J`S z%QvYhKX}Q&P{Xy=^d56l&ogFDh6{i8t)KdhC*A47uiZ!FxY!v!=(?QEIDgrZ?Q^3r zgI#@9#Y52!cSjYrYKI4z|7Nx?cW;PPxFB)5MPc&Kh7TeSI2oOF+xiN$x2vs8e`I)I zg}@gHODz_u^&!m%E-Gv=C@|sJBDZu0SHg))J1#0*$nav2Xgka0Xu%L!|1kTC*;X!g zh7<93-hBM3!OGxpPbt0kv{xR3hnmACQEM%^^Cy+AD?42IWB&R#qr|6m6EzubzPNYl z(Qn2ZT^3%m;H9pvYF-o&)@40ODx$ReIr}$_Mdq&GoLZbGBErVxWW~Dq-{Z{*fVk2rzgzhU$8J_ zv^xaNSd=3WF)O}g=Hm9B4U7y8a!kI7U7H*Z80=s1gTe~DWM4fK$m)} literal 0 HcmV?d00001 diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 6406ab4f88..cf6be1cb93 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -844,7 +844,6 @@ bar.output = Output bar.strength = [stat]{0}[lightgray]x strength units.processorcontrol = [lightgray]Processor Controlled -units.nocontroller = [lightgray]\ue815 No Controller bullet.damage = [stat]{0}[lightgray] damage bullet.splashdamage = [stat]{0}[lightgray] area dmg ~[stat] {1}[lightgray] tiles diff --git a/core/src/mindustry/ai/ControlPathfinder.java b/core/src/mindustry/ai/ControlPathfinder.java index c344d4d746..9c9a4e812b 100644 --- a/core/src/mindustry/ai/ControlPathfinder.java +++ b/core/src/mindustry/ai/ControlPathfinder.java @@ -19,7 +19,7 @@ import static mindustry.ai.Pathfinder.*; //TODO I'm sure this class has countless problems public class ControlPathfinder implements Runnable{ 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; public static boolean showDebug = false; @@ -151,6 +151,7 @@ public class ControlPathfinder implements Runnable{ req.destination.set(destination); req.curId = pathId; req.lastUpdateId = state.updateId; + req.lastPos.set(unit); req.lastWorldUpdate = worldUpdateId; requests.put(unit, req); @@ -170,6 +171,16 @@ public class ControlPathfinder implements Runnable{ req.destination.set(destination); 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){ int[] items = req.result.items; int len = req.result.size; @@ -193,11 +204,9 @@ public class ControlPathfinder implements Runnable{ 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){ for(int i = len - 1; i > req.pathIndex; 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)){ req.rayPathIndex = i; break; @@ -343,6 +352,7 @@ public class ControlPathfinder implements Runnable{ //total update time no longer than maxUpdate for(var req : threadRequests){ + //TODO this is flawed with many paths req.update(maxUpdate / requests.size); } } @@ -365,6 +375,9 @@ public class ControlPathfinder implements Runnable{ volatile boolean done = false; volatile boolean foundEnd = false; + final Vec2 lastPos = new Vec2(); + float stuckTimer = 0f; + final Vec2 destination = new Vec2(); final Vec2 lastDestination = new Vec2(); @@ -373,7 +386,8 @@ public class ControlPathfinder implements Runnable{ volatile int lastWorldUpdate; //TODO only access on main thread?? - int pathIndex; + volatile int pathIndex; + int rayPathIndex = -1; IntSeq result = new IntSeq(); float raycastTimer; @@ -386,13 +400,11 @@ public class ControlPathfinder implements Runnable{ int start, goal; + long lastUpdateId; long lastTime; volatile int lastId, curId; - //TODO invalidate when not request for a while - long lastUpdateId; - void update(long maxUpdateNs){ if(curId != lastId){ clear(); diff --git a/core/src/mindustry/ai/types/SuicideAI.java b/core/src/mindustry/ai/types/SuicideAI.java index e17cd5d121..dc45290932 100644 --- a/core/src/mindustry/ai/types/SuicideAI.java +++ b/core/src/mindustry/ai/types/SuicideAI.java @@ -19,11 +19,6 @@ public class SuicideAI extends GroundAI{ @Override public void updateUnit(){ - if(disabled()){ - stopShooting(); - return; - } - if(Units.invalidateTarget(target, unit.team, unit.x, unit.y, Float.MAX_VALUE)){ target = null; } diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 38b21406bd..d97cb16b4f 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -3144,6 +3144,7 @@ public class Blocks{ coolantOverride = Liquids.water; coolantMultiplier = 6f; + unitFilter = u -> !u.spawnedByCore; shootShake = 1f; ammoPerShot = 5; 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)); size = 5; //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); areaSize = 13; @@ -3508,8 +3509,8 @@ public class Blocks{ shipAssembler = new UnitAssembler("ship-assembler"){{ requirements(Category.units, with(Items.beryllium, 700, Items.oxide, 150, Items.tungsten, 500, Items.silicon, 800)); size = 5; - plans.add(new AssemblerUnitPlan(UnitTypes.quell, 60f * 25f, BlockStack.list(Blocks.berylliumWallLarge, 4, Blocks.duct, 10, Blocks.plasmaBore, 4))); - consumes.power(2f); + plans.add(new AssemblerUnitPlan(UnitTypes.quell, 60f * 40f, BlockStack.list(Blocks.berylliumWallLarge, 4, Blocks.duct, 10, Blocks.plasmaBore, 4))); + consumes.power(3f); areaSize = 13; //consumes.liquid(Liquids.gallium, 2f / 60f); @@ -3520,8 +3521,8 @@ public class Blocks{ mechAssembler = new UnitAssembler("mech-assembler"){{ requirements(Category.units, with(Items.graphite, 600, Items.carbide, 600, Items.oxide, 200, Items.tungsten, 500)); size = 5; - plans.add(new AssemblerUnitPlan(UnitTypes.bulwark, 60f * 40f, BlockStack.list(Blocks.tungstenWallLarge, 5, Blocks.duct, 2))); - consumes.power(2f); + plans.add(new AssemblerUnitPlan(UnitTypes.bulwark, 60f * 60f, BlockStack.list(Blocks.tungstenWallLarge, 5, Blocks.duct, 2))); + consumes.power(3f); areaSize = 13; //consumes.liquid(Liquids.gallium, 2f / 60f); @@ -3605,6 +3606,7 @@ public class Blocks{ constructor = new Constructor("constructor"){{ requirements(Category.units, with(Items.silicon, 100, Items.beryllium, 150, Items.tungsten, 80)); hasPower = true; + buildSpeed = 0.3f; consumes.power(2f); 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)); hasPower = true; consumes.power(2f); + buildSpeed = 0.3f; maxBlockSize = 4; minBlockSize = 3; size = 5; diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index c115b814b5..2086bf09bb 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -3323,7 +3323,6 @@ public class UnitTypes{ manifold = new ErekirUnitType("manifold"){{ defaultController = CargoAI::new; - defaultAI = true; isCounted = false; allowedInPayloads = false; logicControllable = false; @@ -3350,7 +3349,6 @@ public class UnitTypes{ assemblyDrone = new ErekirUnitType("assembly-drone"){{ defaultController = AssemblerAI::new; - defaultAI = true; flying = true; drag = 0.06f; accel = 0.11f; diff --git a/core/src/mindustry/entities/units/AIController.java b/core/src/mindustry/entities/units/AIController.java index 1bd6163465..7c97aba9d9 100644 --- a/core/src/mindustry/entities/units/AIController.java +++ b/core/src/mindustry/entities/units/AIController.java @@ -33,11 +33,6 @@ public class AIController implements UnitController{ @Override public void updateUnit(){ - if(disabled()){ - stopShooting(); - return; - } - //use fallback AI when possible if(useFallback() && (fallback != null || (fallback = fallback()) != null)){ 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 public AIController fallback(){ return null; diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index 55e3485739..b4895d9601 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -69,8 +69,6 @@ public class UnitType extends UnlockableContent{ public boolean logicControllable = true; public boolean playerControllable = 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. */ public boolean coreUnitDock = false; public boolean createWreck = true; @@ -302,10 +300,6 @@ public class UnitType extends UnlockableContent{ } }).growX(); - if(coreUnitDock && !defaultAI){ - table.row().add("@units.nocontroller").growX().left().row(); - } - if(unit.controller() instanceof LogicAI){ table.row(); table.add(Blocks.microProcessor.emoji() + " " + Core.bundle.get("units.processorcontrol")).growX().wrap().left(); diff --git a/core/src/mindustry/type/unit/ErekirUnitType.java b/core/src/mindustry/type/unit/ErekirUnitType.java index 3cfb917d12..099ab679b8 100644 --- a/core/src/mindustry/type/unit/ErekirUnitType.java +++ b/core/src/mindustry/type/unit/ErekirUnitType.java @@ -13,8 +13,6 @@ public class ErekirUnitType extends UnitType{ commandLimit = 0; outlineColor = Pal.darkOutline; envDisabled = Env.space; - //TODO necessary, or not? - defaultAI = false; coreUnitDock = true; unitBasedDefaultController = u -> !playerControllable || u.team.isAI() ? defaultController.get() : new CommandAI(); } diff --git a/core/src/mindustry/world/blocks/defense/turrets/Turret.java b/core/src/mindustry/world/blocks/defense/turrets/Turret.java index 0b1b2d54d7..1c3aaeae30 100644 --- a/core/src/mindustry/world/blocks/defense/turrets/Turret.java +++ b/core/src/mindustry/world/blocks/defense/turrets/Turret.java @@ -103,6 +103,7 @@ public class Turret extends ReloadTurret{ public boolean playerControllable = true; public boolean displayAmmoMultiplier = true; public Sortf unitSort = UnitSorts.closest; + public Boolf unitFilter = u -> true; public DrawBlock draw = new DrawTurret(); @@ -419,9 +420,9 @@ public class Turret extends ReloadTurret{ float range = range(); 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{ - 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()){ target = Units.findAllyTile(team, x, y, range, b -> b.damaged() && b != this);