No Erekir default AI / Core unit tweaks

This commit is contained in:
Anuken
2022-02-06 20:54:57 -05:00
parent cb110e5e6f
commit ce82b3943e
13 changed files with 147 additions and 73 deletions

View File

@@ -19,6 +19,7 @@ public class SuicideAI extends GroundAI{
@Override @Override
public void updateUnit(){ public void updateUnit(){
if(disabled()) 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;

View File

@@ -2546,7 +2546,7 @@ public class Blocks{
thrusterLength = 34/4f; thrusterLength = 34/4f;
armor = 5f; armor = 5f;
unitCapModifier = 6; unitCapModifier = 4;
researchCostMultiplier = 0.07f; researchCostMultiplier = 0.07f;
}}; }};
@@ -2561,7 +2561,7 @@ public class Blocks{
thrusterLength = 40/4f; thrusterLength = 40/4f;
armor = 10f; armor = 10f;
unitCapModifier = 10; unitCapModifier = 8;
researchCostMultiplier = 0.11f; researchCostMultiplier = 0.11f;
}}; }};
@@ -2576,7 +2576,7 @@ public class Blocks{
thrusterLength = 48/4f; thrusterLength = 48/4f;
armor = 15f; armor = 15f;
unitCapModifier = 14; unitCapModifier = 12;
researchCostMultiplier = 0.11f; researchCostMultiplier = 0.11f;
}}; }};

View File

@@ -2674,14 +2674,12 @@ public class UnitTypes{
//endregion //endregion
//region erekir - mech //region erekir - mech
bulwark = new UnitType("bulwark"){{ bulwark = new ErekirUnitType("bulwark"){{
drag = 0.1f; drag = 0.1f;
speed = 0.6f; speed = 0.6f;
hitSize = 23f; hitSize = 23f;
health = 7000; health = 7000;
armor = 5f; armor = 5f;
outlineColor = Pal.darkOutline;
envDisabled = Env.space;
abilities.add(new ShieldArcAbility(){{ abilities.add(new ShieldArcAbility(){{
region = "bulwark-shield"; region = "bulwark-shield";
@@ -2771,14 +2769,12 @@ public class UnitTypes{
}}); }});
}}; }};
krepost = new UnitType("krepost"){{ krepost = new ErekirUnitType("krepost"){{
drag = 0.1f; drag = 0.1f;
speed = 1.1f; speed = 1.1f;
hitSize = 44f; hitSize = 44f;
health = 18000; health = 18000;
armor = 8f; armor = 8f;
outlineColor = Pal.darkOutline;
envDisabled = Env.space;
rotateSpeed = 1.6f; rotateSpeed = 1.6f;
lockLegBase = true; lockLegBase = true;
legContinuousMove = true; legContinuousMove = true;
@@ -2887,11 +2883,10 @@ public class UnitTypes{
//endregion //endregion
//region erekir - flying //region erekir - flying
quell = new UnitType("quell"){{ quell = new ErekirUnitType("quell"){{
defaultController = FlyingFollowAI::new; defaultController = FlyingFollowAI::new;
envDisabled = 0; envDisabled = 0;
outlineColor = Pal.darkOutline;
lowAltitude = false; lowAltitude = false;
flying = true; flying = true;
drag = 0.06f; drag = 0.06f;
@@ -2953,11 +2948,10 @@ public class UnitTypes{
); );
}}; }};
disrupt = new UnitType("disrupt"){{ disrupt = new ErekirUnitType("disrupt"){{
defaultController = FlyingFollowAI::new; defaultController = FlyingFollowAI::new;
envDisabled = 0; envDisabled = 0;
outlineColor = Pal.darkOutline;
lowAltitude = false; lowAltitude = false;
flying = true; flying = true;
drag = 0.07f; drag = 0.07f;
@@ -3122,12 +3116,11 @@ public class UnitTypes{
//region erekir - core //region erekir - core
//TODO bad name //TODO bad name
evoke = new UnitType("evoke"){{ evoke = new ErekirUnitType("evoke"){{
defaultController = BuilderAI::new; defaultController = BuilderAI::new;
isCounted = false; isCounted = false;
envDisabled = 0; envDisabled = 0;
outlineColor = Pal.darkOutline;
lowAltitude = false; lowAltitude = false;
mineWalls = true; mineWalls = true;
mineFloor = false; mineFloor = false;
@@ -3136,15 +3129,14 @@ public class UnitTypes{
mineSpeed = 4f; mineSpeed = 4f;
mineTier = 4; mineTier = 4;
buildSpeed = 0.8f; buildSpeed = 0.8f;
drag = 0.06f; drag = 0.08f;
speed = 2.9f; speed = 5.3f;
rotateSpeed = 9f; rotateSpeed = 7f;
accel = 0.1f; accel = 0.09f;
itemCapacity = 60; itemCapacity = 60;
health = 300f; health = 300f;
armor = 1f; armor = 1f;
hitSize = 9f; hitSize = 9f;
commandLimit = 5;
engineSize = 0; engineSize = 0;
setEnginesMirror( setEnginesMirror(
@@ -3152,43 +3144,37 @@ public class UnitTypes{
new UnitEngine(23 / 4f, -22 / 4f, 2.2f, 315f) new UnitEngine(23 / 4f, -22 / 4f, 2.2f, 315f)
); );
weapons.add(new Weapon(){{ weapons.add(new RepairBeamWeapon(){{
reload = 17f; reload = 25f;
x = 0f; x = 0f;
y = 1f; y = 6.5f;
top = false; rotate = false;
shootY = 0f;
beamWidth = 0.7f;
repairSpeed = 0.25f;
aimDst = 0f;
shootCone = 15f;
fractionRepair = true;
mirror = false; mirror = false;
bullet = new LaserBoltBulletType(){{ targetUnits = false;
speed = 4.2f; targetBuildings = true;
frontColor = Color.white; autoTarget = false;
backColor = hitColor = trailColor = Pal.accent; controllable = true;
laserColor = Pal.accent;
healColor = Pal.accent;
height = 6f; bullet = new BulletType(){{
trailLength = 5; maxRange = 70f;
trailWidth = 2f;
healColor = Pal.accent;
healPercent = 1f;
healAmount = 25f;
collidesTeam = true;
lifetime = 31f;
shootEffect = Fx.colorSpark;
hitEffect = smokeEffect = despawnEffect = Fx.hitLaserColor;
//TODO 0, or 1?
damage = 0;
}}; }};
}}); }});
}}; }};
incite = new UnitType("incite"){{ incite = new ErekirUnitType("incite"){{
defaultController = BuilderAI::new; defaultController = BuilderAI::new;
isCounted = false; isCounted = false;
envDisabled = 0; envDisabled = 0;
outlineColor = Pal.darkOutline;
lowAltitude = false; lowAltitude = false;
flying = true; flying = true;
mineWalls = true; mineWalls = true;
@@ -3206,7 +3192,6 @@ public class UnitTypes{
health = 600f; health = 600f;
armor = 2f; armor = 2f;
hitSize = 18f; hitSize = 18f;
commandLimit = 7;
buildBeamOffset = 10f; buildBeamOffset = 10f;
engineSize = 0; engineSize = 0;
payloadCapacity = Mathf.sqr(2f) * tilePayload; payloadCapacity = Mathf.sqr(2f) * tilePayload;
@@ -3243,12 +3228,11 @@ public class UnitTypes{
}}); }});
}}; }};
emanate = new UnitType("emanate"){{ emanate = new ErekirUnitType("emanate"){{
defaultController = BuilderAI::new; defaultController = BuilderAI::new;
isCounted = false; isCounted = false;
envDisabled = 0; envDisabled = 0;
outlineColor = Pal.darkOutline;
lowAltitude = false; lowAltitude = false;
flying = true; flying = true;
targetAir = false; targetAir = false;
@@ -3266,7 +3250,6 @@ public class UnitTypes{
health = 1300f; health = 1300f;
armor = 3f; armor = 3f;
hitSize = 36f; hitSize = 36f;
commandLimit = 9;
buildBeamOffset = 72f / 4f; buildBeamOffset = 72f / 4f;
engineSize = 0; engineSize = 0;
payloadCapacity = Mathf.sqr(3f) * tilePayload; payloadCapacity = Mathf.sqr(3f) * tilePayload;
@@ -3328,14 +3311,14 @@ public class UnitTypes{
internal = true; internal = true;
}}; }};
manifold = new UnitType("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;
envDisabled = 0; envDisabled = 0;
outlineColor = Pal.darkOutline;
lowAltitude = false; lowAltitude = false;
flying = true; flying = true;
drag = 0.06f; drag = 0.06f;
@@ -3345,7 +3328,6 @@ public class UnitTypes{
itemCapacity = 60; itemCapacity = 60;
health = 200f; health = 200f;
hitSize = 11f; hitSize = 11f;
commandLimit = 0;
engineSize = 2.3f; engineSize = 2.3f;
engineOffset = 6.5f; engineOffset = 6.5f;
hidden = true; hidden = true;
@@ -3355,9 +3337,10 @@ public class UnitTypes{
); );
}}; }};
assemblyDrone = new UnitType("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;

View File

@@ -231,7 +231,7 @@ public class BulletType extends Content implements Cloneable{
/** Returns maximum distance the bullet this bullet type has can travel. */ /** Returns maximum distance the bullet this bullet type has can travel. */
public float range(){ public float range(){
if(rangeOverride > 0) return rangeOverride; if(rangeOverride > 0) return rangeOverride;
return Mathf.zero(drag) ? speed * lifetime : Math.max(speed * (1f - Mathf.pow(1f - drag, lifetime)) / drag, maxRange); return Math.max(Mathf.zero(drag) ? speed * lifetime : speed * (1f - Mathf.pow(1f - drag, lifetime)) / drag, maxRange);
} }
/** @return continuous damage in damage/sec, or -1 if not continuous. */ /** @return continuous damage in damage/sec, or -1 if not continuous. */

View File

@@ -33,6 +33,10 @@ public class AIController implements UnitController{
@Override @Override
public void updateUnit(){ public void updateUnit(){
if(disabled()){
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);
@@ -45,6 +49,10 @@ public class AIController implements UnitController{
updateMovement(); updateMovement();
} }
public boolean disabled(){
return !unit.team.isAI() && !unit.type.defaultAI;
}
@Nullable @Nullable
public AIController fallback(){ public AIController fallback(){
return null; return null;

View File

@@ -67,6 +67,10 @@ 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. */
public boolean coreUnitDock = false;
public boolean createWreck = true; public boolean createWreck = true;
public boolean createScorch = true; public boolean createScorch = true;
public boolean useUnitCap = true; public boolean useUnitCap = true;
@@ -503,6 +507,8 @@ public class UnitType extends UnlockableContent{
} }
this.weapons = mapped; this.weapons = mapped;
weapons.each(Weapon::init);
//dynamically create ammo capacity based on firing rate //dynamically create ammo capacity based on firing rate
if(ammoCapacity < 0){ if(ammoCapacity < 0){
float shotsPerSecond = weapons.sumf(w -> w.useAmmo ? 60f / w.reload : 0f); float shotsPerSecond = weapons.sumf(w -> w.useAmmo ? 60f / w.reload : 0f);

View File

@@ -465,6 +465,10 @@ public class Weapon implements Cloneable{
} }
} }
public void init(){
}
public void load(){ public void load(){
region = Core.atlas.find(name); region = Core.atlas.find(name);
heatRegion = Core.atlas.find(name + "-heat"); heatRegion = Core.atlas.find(name + "-heat");

View File

@@ -0,0 +1,18 @@
package mindustry.type.unit;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.world.meta.*;
/** Config class for special Erekir unit properties. */
public class ErekirUnitType extends UnitType{
public ErekirUnitType(String name){
super(name);
commandLimit = 0;
outlineColor = Pal.darkOutline;
envDisabled = Env.space;
defaultAI = false;
coreUnitDock = true;
}
}

View File

@@ -2,6 +2,7 @@ package mindustry.type.unit;
import mindustry.ai.types.*; import mindustry.ai.types.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*; import mindustry.type.*;
import mindustry.world.meta.*; import mindustry.world.meta.*;
@@ -31,6 +32,7 @@ public class MissileUnitType extends UnitType{
rotateSpeed = 2.5f; rotateSpeed = 2.5f;
range = 30f; range = 30f;
targetPriority = -1f; targetPriority = -1f;
//TODO weapons, etc outlineColor = Pal.darkOutline;
//TODO weapon configs, etc?
} }
} }

View File

@@ -1,10 +1,8 @@
package mindustry.type.unit; package mindustry.type.unit;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.world.meta.*; import mindustry.world.meta.*;
public class TankUnitType extends UnitType{ public class TankUnitType extends ErekirUnitType{
public TankUnitType(String name){ public TankUnitType(String name){
super(name); super(name);
@@ -14,7 +12,6 @@ public class TankUnitType extends UnitType{
rotateSpeed = 1.3f; rotateSpeed = 1.3f;
envDisabled = Env.none; envDisabled = Env.none;
speed = 0.8f; speed = 0.8f;
outlineColor = Pal.darkOutline;
} }
} }

View File

@@ -7,9 +7,12 @@ import arc.math.*;
import arc.math.geom.*; import arc.math.geom.*;
import arc.scene.ui.layout.*; import arc.scene.ui.layout.*;
import arc.util.*; import arc.util.*;
import mindustry.*;
import mindustry.content.*;
import mindustry.entities.*; import mindustry.entities.*;
import mindustry.entities.units.*; import mindustry.entities.units.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*; import mindustry.type.*;
import mindustry.world.blocks.units.*; import mindustry.world.blocks.units.*;
import mindustry.world.meta.*; import mindustry.world.meta.*;
@@ -19,7 +22,9 @@ import mindustry.world.meta.*;
* Rotation must be set to true. Fixed repair points are not supported. * Rotation must be set to true. Fixed repair points are not supported.
* */ * */
public class RepairBeamWeapon extends Weapon{ public class RepairBeamWeapon extends Weapon{
public boolean targetBuildings = false; public boolean targetBuildings = false, targetUnits = true;
//TODO leads to wrong stats
public boolean fractionRepair = false;
public float repairSpeed = 0.3f; public float repairSpeed = 0.3f;
public float beamWidth = 1f; public float beamWidth = 1f;
@@ -29,6 +34,9 @@ public class RepairBeamWeapon extends Weapon{
public TextureRegion laser, laserEnd, laserTop, laserTopEnd; public TextureRegion laser, laserEnd, laserTop, laserTopEnd;
public Color laserColor = Color.valueOf("98ffa9"), laserTopColor = Color.white.cpy(); public Color laserColor = Color.valueOf("98ffa9"), laserTopColor = Color.white.cpy();
//only for blocks
public Color healColor = Pal.heal;
public Effect healEffect = Fx.healBlockFull;
public RepairBeamWeapon(String name){ public RepairBeamWeapon(String name){
super(name); super(name);
@@ -72,9 +80,8 @@ public class RepairBeamWeapon extends Weapon{
@Override @Override
protected Teamc findTarget(Unit unit, float x, float y, float range, boolean air, boolean ground){ protected Teamc findTarget(Unit unit, float x, float y, float range, boolean air, boolean ground){
var out = Units.closest(unit.team, x, y, range, u -> u != unit && u.damaged()); var out = targetUnits ? Units.closest(unit.team, x, y, range, u -> u != unit && u.damaged()) : null;
if(out != null || !targetBuildings) return out; if(out != null || !targetBuildings) return out;
//TODO maybe buildings shouldn't be allowed at all
return Units.findAllyTile(unit.team, x, y, range, Building::damaged); return Units.findAllyTile(unit.team, x, y, range, Building::damaged);
} }
@@ -92,11 +99,48 @@ public class RepairBeamWeapon extends Weapon{
public void update(Unit unit, WeaponMount mount){ public void update(Unit unit, WeaponMount mount){
super.update(unit, mount); super.update(unit, mount);
HealBeamMount heal = (HealBeamMount)mount; float
heal.strength = Mathf.lerpDelta(heal.strength, Mathf.num(mount.target != null), 0.2f); weaponRotation = unit.rotation - 90,
wx = unit.x + Angles.trnsx(weaponRotation, x, y),
wy = unit.y + Angles.trnsy(weaponRotation, x, y);
if(mount.target instanceof Healthc u){ HealBeamMount heal = (HealBeamMount)mount;
u.heal(repairSpeed * heal.strength * Time.delta); heal.target = null;
boolean canShoot = mount.shoot;
if(!autoTarget){
if(canShoot){
heal.lastEnd.set(heal.aimX, heal.aimY);
if(!rotate && !Angles.within(Angles.angle(wx, wy, heal.aimX, heal.aimY), unit.rotation, shootCone)){
canShoot = false;
}
}
//limit range
heal.lastEnd.sub(wx, wy).limit(range()).add(wx, wy);
if(targetBuildings){
var build = Vars.world.buildWorld(mount.aimX, mount.aimY);
if(build != null && build.team == unit.team){
heal.target = build;
}
}
if(targetUnits){
//TODO does not support healing units manually yet
}
}
heal.strength = Mathf.lerpDelta(heal.strength, Mathf.num(autoTarget ? mount.target != null : canShoot), 0.2f);
//create heal effect periodically
if(canShoot && mount.target instanceof Building b && b.damaged() && (heal.effectTimer += Time.delta) >= reload){
healEffect.at(b.x, b.y, b.block.size, healColor);
heal.effectTimer = 0f;
}
if(canShoot && mount.target instanceof Healthc u){
u.heal(repairSpeed * heal.strength * Time.delta * (fractionRepair ? u.maxHealth() / 100f : 1f));
} }
} }
@@ -112,15 +156,22 @@ public class RepairBeamWeapon extends Weapon{
wy = unit.y + Angles.trnsy(weaponRotation, x, y); wy = unit.y + Angles.trnsy(weaponRotation, x, y);
float z = Draw.z(); float z = Draw.z();
RepairPoint.drawBeam(wx, wy, unit.rotation + mount.rotation, shootY, unit.id, mount.target == null ? null : (Sized)mount.target, unit.team, heal.strength, RepairPoint.drawBeam(wx, wy, unit.rotation + mount.rotation, shootY, unit.id, mount.target == null || controllable ? null : (Sized)mount.target, unit.team, heal.strength,
pulseStroke, pulseRadius, beamWidth, heal.lastEnd, heal.offset, laserColor, laserTopColor, pulseStroke, pulseRadius, beamWidth, heal.lastEnd, heal.offset, laserColor, laserTopColor,
laser, laserEnd, laserTop, laserTopEnd); laser, laserEnd, laserTop, laserTopEnd);
Draw.z(z); Draw.z(z);
} }
@Override
public void init(){
if(fractionRepair){
bullet.healPercent = repairSpeed;
}
}
public static class HealBeamMount extends WeaponMount{ public static class HealBeamMount extends WeaponMount{
public Vec2 offset = new Vec2(), lastEnd = new Vec2(); public Vec2 offset = new Vec2(), lastEnd = new Vec2();
public float strength; public float strength, effectTimer;
public HealBeamMount(Weapon weapon){ public HealBeamMount(Weapon weapon){
super(weapon); super(weapon);

View File

@@ -98,18 +98,18 @@ public class RepairPoint extends Block{
return new TextureRegion[]{baseRegion, region}; return new TextureRegion[]{baseRegion, region};
} }
public static void drawBeam(float x, float y, float rotation, float length, int id, Sized target, Team team, public static void drawBeam(float x, float y, float rotation, float length, int id, @Nullable Sized target, Team team,
float strength, float pulseStroke, float pulseRadius, float beamWidth, float strength, float pulseStroke, float pulseRadius, float beamWidth,
Vec2 lastEnd, Vec2 offset, Vec2 lastEnd, Vec2 offset,
Color laserColor, Color laserTopColor, Color laserColor, Color laserTopColor,
TextureRegion laser, TextureRegion laserEnd, TextureRegion laserTop, TextureRegion laserTopEnd){ TextureRegion laser, TextureRegion laserEnd, TextureRegion laserTop, TextureRegion laserTopEnd){
rand.setSeed(id + (target instanceof Entityc e ? e.id() : 0));
if(target != null){ if(target != null){
float float
originX = x + Angles.trnsx(rotation, length), originX = x + Angles.trnsx(rotation, length),
originY = y + Angles.trnsy(rotation, length); originY = y + Angles.trnsy(rotation, length);
rand.setSeed(id + (target instanceof Entityc e ? e.id() : 0));
lastEnd.set(target).sub(originX, originY); lastEnd.set(target).sub(originX, originY);
lastEnd.setLength(Math.max(2f, lastEnd.len())); lastEnd.setLength(Math.max(2f, lastEnd.len()));

View File

@@ -172,7 +172,7 @@ public class UnitAssembler extends PayloadBlock{
public Seq<Unit> units = new Seq<>(); public Seq<Unit> units = new Seq<>();
public Seq<UnitAssemblerModuleBuild> modules = new Seq<>(); public Seq<UnitAssemblerModuleBuild> modules = new Seq<>();
public BlockSeq blocks = new BlockSeq(); public BlockSeq blocks = new BlockSeq();
public float progress, warmup, droneWarmup; public float progress, warmup, droneWarmup, powerWarmup;
public float invalidWarmup = 0f; public float invalidWarmup = 0f;
public int currentTier = 0; public int currentTier = 0;
public boolean wasOccupied = false; public boolean wasOccupied = false;
@@ -284,6 +284,7 @@ public class UnitAssembler extends PayloadBlock{
units.removeAll(u -> !u.isAdded() || u.dead || !(u.controller() instanceof AssemblerAI)); units.removeAll(u -> !u.isAdded() || u.dead || !(u.controller() instanceof AssemblerAI));
powerWarmup = Mathf.lerpDelta(powerWarmup, efficiency(), 0.1f);
droneWarmup = Mathf.lerpDelta(droneWarmup, units.size < dronesCreated ? efficiency() : 0f, 0.1f); droneWarmup = Mathf.lerpDelta(droneWarmup, units.size < dronesCreated ? efficiency() : 0f, 0.1f);
totalDroneProgress += droneWarmup * Time.delta; totalDroneProgress += droneWarmup * Time.delta;
@@ -380,6 +381,7 @@ public class UnitAssembler extends PayloadBlock{
var plan = plan(); var plan = plan();
//draw the unit construction as outline
Draw.draw(Layer.blockBuilding, () -> { Draw.draw(Layer.blockBuilding, () -> {
Draw.color(Pal.accent, warmup); Draw.color(Pal.accent, warmup);
@@ -397,8 +399,9 @@ public class UnitAssembler extends PayloadBlock{
Draw.z(Layer.buildBeam); Draw.z(Layer.buildBeam);
//draw unit outline //draw unit silhouette
Draw.mixcol(Tmp.c1.set(Pal.accent).lerp(Pal.remove, invalidWarmup), 1f); Draw.mixcol(Tmp.c1.set(Pal.accent).lerp(Pal.remove, invalidWarmup), 1f);
Draw.alpha(powerWarmup);
Draw.rect(plan.unit.fullIcon, spawn.x, spawn.y); Draw.rect(plan.unit.fullIcon, spawn.x, spawn.y);
//build beams do not draw when invalid //build beams do not draw when invalid
@@ -423,6 +426,7 @@ public class UnitAssembler extends PayloadBlock{
//draw full area //draw full area
Lines.stroke(2f, Pal.accent); Lines.stroke(2f, Pal.accent);
Draw.alpha(powerWarmup);
Drawf.dashRectBasic(spawn.x - fulls, spawn.y - fulls, fulls*2f, fulls*2f); Drawf.dashRectBasic(spawn.x - fulls, spawn.y - fulls, fulls*2f, fulls*2f);
Draw.reset(); Draw.reset();