diff --git a/core/assets-raw/sprites/blocks/drills/eruption-drill.png b/core/assets-raw/sprites/blocks/drills/eruption-drill.png index da7f046576..f4b809a51e 100644 Binary files a/core/assets-raw/sprites/blocks/drills/eruption-drill.png and b/core/assets-raw/sprites/blocks/drills/eruption-drill.png differ diff --git a/core/assets-raw/sprites/blocks/units/ship-assembler-in.png b/core/assets-raw/sprites/blocks/units/ship-assembler-in.png new file mode 100644 index 0000000000..d411cbd4cd Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/ship-assembler-in.png differ diff --git a/core/assets-raw/sprites/blocks/units/ship-assembler-side1.png b/core/assets-raw/sprites/blocks/units/ship-assembler-side1.png new file mode 100644 index 0000000000..ec57520298 Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/ship-assembler-side1.png differ diff --git a/core/assets-raw/sprites/blocks/units/ship-assembler-side2.png b/core/assets-raw/sprites/blocks/units/ship-assembler-side2.png new file mode 100644 index 0000000000..5bac81cd38 Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/ship-assembler-side2.png differ diff --git a/core/assets-raw/sprites/blocks/units/ship-assembler-top.png b/core/assets-raw/sprites/blocks/units/ship-assembler-top.png new file mode 100644 index 0000000000..a80bf2b8f7 Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/ship-assembler-top.png differ diff --git a/core/assets-raw/sprites/blocks/units/ship-assembler.png b/core/assets-raw/sprites/blocks/units/ship-assembler.png new file mode 100644 index 0000000000..bf54cf6950 Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/ship-assembler.png differ diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 72490d09d8..3f5118cf97 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -837,7 +837,8 @@ bullet.buildingdamage = [stat]{0}%[lightgray] building damage bullet.knockback = [stat]{0}[lightgray] knockback bullet.pierce = [stat]{0}[lightgray]x pierce bullet.infinitepierce = [stat]pierce -bullet.healpercent = [stat]{0}[lightgray]% healing +bullet.healpercent = [stat]{0}[lightgray]% repair +bullet.healamount = [stat]{0}[lightgray] direct repair bullet.multiplier = [stat]{0}[lightgray]x ammo multiplier bullet.reload = [stat]{0}[lightgray]x fire rate bullet.range = [stat]{0}[lightgray] tiles range diff --git a/core/assets/icons/icons.properties b/core/assets/icons/icons.properties index c144be8365..f73bb43dda 100755 --- a/core/assets/icons/icons.properties +++ b/core/assets/icons/icons.properties @@ -492,3 +492,4 @@ 63212=quell|unit-quell-ui 63211=breach|block-breach-ui 63210=eruption-drill|block-eruption-drill-ui +63209=ship-assembler|block-ship-assembler-ui diff --git a/core/assets/logicids.dat b/core/assets/logicids.dat index 2f9b492308..825c410021 100644 Binary files a/core/assets/logicids.dat and b/core/assets/logicids.dat differ diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index d9fab5facd..fdbfb5e26d 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -131,6 +131,7 @@ public class Blocks{ //unit - erekir tankAssembler, + shipAssembler, basicAssemblerModule, //payloads @@ -3264,15 +3265,25 @@ public class Blocks{ tankAssembler = new UnitAssembler("tank-assembler"){{ requirements(Category.units, with(Items.graphite, 10)); size = 5; - droneType = UnitTypes.manifold; - plans.add(new AssemblerUnitPlan(UnitTypes.vanquish, 60f * 5f, BlockStack.list(Blocks.thoriumWallLarge, 4, Blocks.duct, 2))); + plans.add(new AssemblerUnitPlan(UnitTypes.vanquish, 60f * 10f, BlockStack.list(Blocks.thoriumWallLarge, 4, Blocks.duct, 2))); + consumes.power(2f); + areaSize = 13; + + //TODO unit production is rarely continuous, can be double + consumes.liquid(Liquids.gallium, 1f / 60f); + }}; + + //TODO requirements + shipAssembler = new UnitAssembler("ship-assembler"){{ + requirements(Category.units, with(Items.graphite, 10)); + size = 5; + plans.add(new AssemblerUnitPlan(UnitTypes.quell, 60f * 4f, BlockStack.list(Blocks.thoriumWallLarge, 4, Blocks.duct, 2))); consumes.power(2f); areaSize = 13; //TODO unit production is rarely continuous, can be double consumes.liquid(Liquids.gallium, 1f / 60f); - droneType = UnitTypes.assemblyDrone; }}; basicAssemblerModule = new UnitAssemblerModule("basic-assembler-module"){{ diff --git a/core/src/mindustry/content/Fx.java b/core/src/mindustry/content/Fx.java index 36b054e87e..492e48260d 100644 --- a/core/src/mindustry/content/Fx.java +++ b/core/src/mindustry/content/Fx.java @@ -752,6 +752,14 @@ public class Fx{ Drawf.light(e.x, e.y, 23f, Pal.heal, e.fout() * 0.7f); }), + hitLaserColor = new Effect(8, e -> { + color(Color.white, e.color, e.fin()); + stroke(0.5f + e.fout()); + Lines.circle(e.x, e.y, e.fin() * 5f); + + Drawf.light(e.x, e.y, 23f, e.color, e.fout() * 0.7f); + }), + hitYellowLaser = new Effect(8, e -> { color(Color.white, Pal.lightTrail, e.fin()); stroke(0.5f + e.fout()); diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index 28515f02de..f5898ef20f 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -2563,7 +2563,6 @@ public class UnitTypes{ outlineColor = Pal.darkOutline; lowAltitude = false; flying = true; - targetAir = false; mineSpeed = 6.5f; mineTier = 1; buildSpeed = 0.8f; @@ -2584,32 +2583,31 @@ public class UnitTypes{ ); weapons.add(new Weapon(){{ - reload = 55f; + reload = 17f; x = 0f; y = 1f; top = false; mirror = false; - bullet = new ArtilleryBulletType(3f, 11){{ - trailLength = 8; - trailWidth = 2.4f; - collidesTiles = true; - collides = true; - trailEffect = Fx.none; - trailColor = Pal.bulletYellowBack; - homingPower = 0.01f; - splashDamage = 10; - splashDamageRadius = 20f; - weaveMag = 2f; - weaveScale = 4f; - width = 10f; - height = 13f; + bullet = new LaserBoltBulletType(){{ + speed = 4.2f; + frontColor = Color.white; + backColor = hitColor = trailColor = Pal.accent; - lifetime = 50f; - hitEffect = Fx.blastExplosion; - shootEffect = Fx.shootBig; - smokeEffect = Fx.shootBigSmoke; - buildingDamageMultiplier = 0.4f; + height = 6f; + trailLength = 5; + trailWidth = 2f; + + healColor = Pal.accent; + healPercent = 1f; + healAmount = 25f; + collidesTeam = true; + + lifetime = 35f; + shootEffect = Fx.colorSpark; + hitEffect = smokeEffect = despawnEffect = Fx.hitLaserColor; + + damage = 10; }}; }}); }}; diff --git a/core/src/mindustry/entities/bullet/BulletType.java b/core/src/mindustry/entities/bullet/BulletType.java index d13910641f..97334567f1 100644 --- a/core/src/mindustry/entities/bullet/BulletType.java +++ b/core/src/mindustry/entities/bullet/BulletType.java @@ -118,6 +118,8 @@ public class BulletType extends Content implements Cloneable{ public float rangeChange = 0f; /** % of block health healed **/ public float healPercent = 0f; + /** flat amount of block health healed */ + public float healAmount = 0f; /** Whether to make fire on impact */ public boolean makeFire = false; /** Whether to create hit effects on despawn. Forced to true if this bullet has any special effects like splash damage. */ @@ -131,6 +133,7 @@ public class BulletType extends Content implements Cloneable{ public float fragVelocityMin = 0.2f, fragVelocityMax = 1f, fragLifeMin = 1f, fragLifeMax = 1f; public @Nullable BulletType fragBullet = null; public Color hitColor = Color.white; + public Color healColor = Pal.heal; public Color trailColor = Pal.missileYellowBack; public float trailChance = -0.0001f; @@ -218,8 +221,12 @@ public class BulletType extends Content implements Cloneable{ return -1f; } + public boolean heals(){ + return healPercent > 0 || healAmount > 0; + } + public boolean testCollision(Bullet bullet, Building tile){ - return healPercent <= 0.001f || tile.team != bullet.team || tile.healthf() < 1f; + return !heals() || tile.team != bullet.team || tile.healthf() < 1f; } /** If direct is false, this is an indirect hit and the tile was already damaged. @@ -229,9 +236,9 @@ public class BulletType extends Content implements Cloneable{ Fires.create(build.tile); } - if(healPercent > 0f && build.team == b.team && !(build.block instanceof ConstructBlock)){ - Fx.healBlockFull.at(build.x, build.y, build.block.size, Pal.heal); - build.heal(healPercent / 100f * build.maxHealth); + if(heals()&& build.team == b.team && !(build.block instanceof ConstructBlock)){ + Fx.healBlockFull.at(build.x, build.y, build.block.size, healColor); + build.heal(healPercent / 100f * build.maxHealth + healAmount); }else if(build.team != b.team && direct){ hit(b); } @@ -291,10 +298,10 @@ public class BulletType extends Content implements Cloneable{ Damage.status(b.team, x, y, splashDamageRadius, status, statusDuration, collidesAir, collidesGround); } - if(healPercent > 0f){ + if(heals()){ indexer.eachBlock(b.team, x, y, splashDamageRadius, Building::damaged, other -> { - Fx.healBlockFull.at(other.x, other.y, other.block.size, Pal.heal); - other.heal(healPercent / 100f * other.maxHealth()); + Fx.healBlockFull.at(other.x, other.y, other.block.size, healColor); + other.heal(healPercent / 100f * other.maxHealth() + healAmount); }); } @@ -362,7 +369,7 @@ public class BulletType extends Content implements Cloneable{ if(homingPower > 0.0001f && b.time >= homingDelay){ Teamc target; //home in on allies if possible - if(healPercent > 0){ + if(heals()){ target = Units.closestTarget(null, b.x, b.y, homingRange, e -> e.checkTarget(collidesAir, collidesGround) && e.team != b.team && !b.hasCollided(e.id), t -> collidesGround && (t.team != b.team || t.damaged()) && !b.hasCollided(t.id) diff --git a/core/src/mindustry/entities/bullet/EmpBulletType.java b/core/src/mindustry/entities/bullet/EmpBulletType.java index 539d27d46a..e7c702b5ad 100644 --- a/core/src/mindustry/entities/bullet/EmpBulletType.java +++ b/core/src/mindustry/entities/bullet/EmpBulletType.java @@ -28,7 +28,7 @@ public class EmpBulletType extends BasicBulletType{ } if(other.block.hasPower && other.damaged()){ - other.heal(healPercent / 100f * other.maxHealth()); + other.heal(healPercent / 100f * other.maxHealth() + healAmount); Fx.healBlockFull.at(other.x, other.y, other.block.size, hitColor); applyEffect.at(other, other.block.size * 7f); } diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index 1629be8746..087791291c 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -454,7 +454,7 @@ public class UnitType extends UnlockableContent{ }).layer(Layer.debris); } - canHeal = weapons.contains(w -> w.bullet.healPercent > 0f); + canHeal = weapons.contains(w -> w.bullet.heals()); //add mirrored weapon variants Seq mapped = new Seq<>(); diff --git a/core/src/mindustry/world/blocks/defense/turrets/Turret.java b/core/src/mindustry/world/blocks/defense/turrets/Turret.java index ab466fb31c..8fd202f1d8 100644 --- a/core/src/mindustry/world/blocks/defense/turrets/Turret.java +++ b/core/src/mindustry/world/blocks/defense/turrets/Turret.java @@ -412,7 +412,7 @@ public class Turret extends ReloadTurret{ } protected boolean canHeal(){ - return targetHealing && hasAmmo() && peekAmmo().collidesTeam && peekAmmo().healPercent > 0; + return targetHealing && hasAmmo() && peekAmmo().collidesTeam && peekAmmo().heals(); } protected void findTarget(){ diff --git a/core/src/mindustry/world/meta/StatValues.java b/core/src/mindustry/world/meta/StatValues.java index cbfcbac5e7..1e6cb788be 100644 --- a/core/src/mindustry/world/meta/StatValues.java +++ b/core/src/mindustry/world/meta/StatValues.java @@ -329,6 +329,10 @@ public class StatValues{ sep(bt, Core.bundle.format("bullet.healpercent", Strings.autoFixed(type.healPercent, 2))); } + if(type.healAmount > 0f){ + sep(bt, Core.bundle.format("bullet.healamount", Strings.autoFixed(type.healAmount, 2))); + } + if(type.pierce || type.pierceCap != -1){ sep(bt, type.pierceCap == -1 ? "@bullet.infinitepierce" : Core.bundle.format("bullet.pierce", type.pierceCap)); }