diff --git a/core/assets-raw/sprites/units/weapons/scathe-missile-surge-cell.png b/core/assets-raw/sprites/units/weapons/scathe-missile-surge-cell.png new file mode 100644 index 0000000000..7854083dfd Binary files /dev/null and b/core/assets-raw/sprites/units/weapons/scathe-missile-surge-cell.png differ diff --git a/core/assets-raw/sprites/units/weapons/scathe-missile-surge-split-cell.png b/core/assets-raw/sprites/units/weapons/scathe-missile-surge-split-cell.png new file mode 100644 index 0000000000..7854083dfd Binary files /dev/null and b/core/assets-raw/sprites/units/weapons/scathe-missile-surge-split-cell.png differ diff --git a/core/assets-raw/sprites/units/weapons/scathe-missile-surge-split.png b/core/assets-raw/sprites/units/weapons/scathe-missile-surge-split.png new file mode 100644 index 0000000000..22d7b4a9a6 Binary files /dev/null and b/core/assets-raw/sprites/units/weapons/scathe-missile-surge-split.png differ diff --git a/core/assets-raw/sprites/units/weapons/scathe-missile-surge.png b/core/assets-raw/sprites/units/weapons/scathe-missile-surge.png new file mode 100644 index 0000000000..fd05b27d08 Binary files /dev/null and b/core/assets-raw/sprites/units/weapons/scathe-missile-surge.png differ diff --git a/core/assets/icons/icons.properties b/core/assets/icons/icons.properties index 7c59cb0a5d..c2f98f347f 100755 --- a/core/assets/icons/icons.properties +++ b/core/assets/icons/icons.properties @@ -593,3 +593,5 @@ 63089=small-heat-redirector|block-small-heat-redirector-ui 63088=large-cliff-crusher|block-large-cliff-crusher-ui 63087=scathe-missile-phase|unit-scathe-missile-phase-ui +63086=scathe-missile-surge|unit-scathe-missile-surge-ui +63085=scathe-missile-surge-split|unit-scathe-missile-surge-split-ui diff --git a/core/src/mindustry/ai/types/MissileAI.java b/core/src/mindustry/ai/types/MissileAI.java index 4dafbd6156..50b450afe5 100644 --- a/core/src/mindustry/ai/types/MissileAI.java +++ b/core/src/mindustry/ai/types/MissileAI.java @@ -33,7 +33,7 @@ public class MissileAI extends AIController{ @Override public Teamc target(float x, float y, float range, boolean air, boolean ground){ - return Units.closestTarget(unit.team, x, y, range, u -> u.checkTarget(air, ground), t -> ground && (!t.block.underBullets || (shooter != null && t == Vars.world.buildWorld(shooter.aimX, shooter.aimY)))); + return Units.closestTarget(unit.team, x, y, range, u -> u.checkTarget(air, ground) && !u.isMissile(), t -> ground && (!t.block.underBullets || (shooter != null && t == Vars.world.buildWorld(shooter.aimX, shooter.aimY)))); } @Override diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 1bf9c9783c..013497374f 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -4752,7 +4752,8 @@ public class Blocks{ ammo( Items.carbide, new BulletType(){{ shootEffect = Fx.shootBig; - smokeEffect = Fx.shootSmokeMissile; + smokeEffect = Fx.shootSmokeMissileColor; + hitColor = Pal.redLight; ammoMultiplier = 1f; spawnUnit = new MissileUnitType("scathe-missile"){{ @@ -4838,7 +4839,8 @@ public class Blocks{ //TODO - needs balancing Items.phaseFabric, new BulletType(){{ shootEffect = Fx.shootBig; - smokeEffect = Fx.shootSmokeMissile; + smokeEffect = Fx.shootSmokeMissileColor; + hitColor = Color.valueOf("ffd37f"); ammoMultiplier = 1f; reloadMultiplier = 0.8f; @@ -4925,24 +4927,27 @@ public class Blocks{ }}; }}, - //TODO finish this Items.surgeAlloy, new BulletType(){{ shootEffect = Fx.shootBig; - smokeEffect = Fx.shootSmokeMissile; + smokeEffect = Fx.shootSmokeMissileColor; + hitColor = Color.valueOf("f7e97e"); + ammoMultiplier = 1f; + rangeChange = -8f*9f; + reloadMultiplier = 0.9f; spawnUnit = new MissileUnitType("scathe-missile-surge"){{ - speed = 4.6f; + speed = 4.4f; maxRange = 6f; - lifetime = 60f * 5.5f; + lifetime = 60f * 1.4f; outlineColor = Pal.darkOutline; - engineColor = trailColor = Pal.redLight; + engineColor = trailColor = Color.valueOf("f7e97e"); engineLayer = Layer.effect; engineSize = 3.1f; engineOffset = 10f; rotateSpeed = 0.25f; trailLength = 18; - missileAccelTime = 50f; + missileAccelTime = 30f; lowAltitude = true; loopSound = Sounds.missileTrail; loopSoundVolume = 0.6f; @@ -4952,7 +4957,7 @@ public class Blocks{ fogRadius = 6f; - health = 210; + health = 400; weapons.add(new Weapon(){{ shootCone = 360f; @@ -4961,42 +4966,78 @@ public class Blocks{ deathExplosionEffect = Fx.massiveExplosion; shootOnDeath = true; shake = 10f; - bullet = new ExplosionBulletType(1500f, 65f){{ - hitColor = Pal.redLight; - shootEffect = new MultiEffect(Fx.massiveExplosion, Fx.scatheExplosion, Fx.scatheLight, new WaveEffect(){{ - lifetime = 10f; - strokeFrom = 4f; - sizeTo = 130f; - }}); + bullet = new ExplosionBulletType(400f, 40f){{ + hitColor = engineColor; + shootEffect = new MultiEffect(Fx.massiveExplosion, Fx.scatheExplosionSmall); collidesAir = false; buildingDamageMultiplier = 0.25f; ammoMultiplier = 1f; fragLifeMin = 0.1f; - fragBullets = 7; - fragBullet = new ArtilleryBulletType(3.4f, 32){{ - buildingDamageMultiplier = 0.3f; - drag = 0.02f; - hitEffect = Fx.massiveExplosion; - despawnEffect = Fx.scatheSlash; - knockback = 0.8f; - lifetime = 23f; - width = height = 18f; - collidesTiles = false; - splashDamageRadius = 40f; - splashDamage = 160f; - backColor = trailColor = hitColor = Pal.redLight; - frontColor = Color.white; - smokeEffect = Fx.shootBigSmoke2; - despawnShake = 7f; - lightRadius = 30f; - lightColor = Pal.redLight; - lightOpacity = 0.5f; + fragBullets = 5; + fragRandomSpread = 0f; + fragSpread = 37f; + fragBullet = new BulletType(){{ + shootEffect = Fx.shootBig; + smokeEffect = Fx.shootSmokeMissile; + ammoMultiplier = 1f; - trailLength = 20; - trailWidth = 3.5f; - trailEffect = Fx.none; + spawnUnit = new MissileUnitType("scathe-missile-surge-split"){{ + speed = 4.8f; + maxRange = 6f; + lifetime = 60f * 3.5f; + outlineColor = Pal.darkOutline; + engineColor = trailColor = Color.valueOf("f7e97e"); + engineLayer = Layer.effect; + engineSize = 2.2f; + engineOffset = 8f; + rotateSpeed = 1.35f; + trailLength = 12; + //missileAccelTime = 20f; + lowAltitude = true; + loopSound = Sounds.missileTrail; + loopSoundVolume = 0.6f; + deathSound = Sounds.largeExplosion; + targetAir = false; + targetUnderBlocks = false; + + fogRadius = 6f; + + health = 100; + + weapons.add(new Weapon(){{ + shootCone = 360f; + mirror = false; + reload = 1f; + deathExplosionEffect = Fx.massiveExplosion; + shootOnDeath = true; + shake = 10f; + bullet = new ExplosionBulletType(340f, 35f){{ + lightning = 5; + lightningDamage = 35f; + lightningLength = 8; + + hitColor = engineColor; + shootEffect = new MultiEffect(Fx.massiveExplosion, Fx.scatheExplosionSmall, Fx.scatheLightSmall, new WaveEffect(){{ + lifetime = 10f; + strokeFrom = 4f; + sizeTo = 100f; + }}); + + collidesAir = false; + buildingDamageMultiplier = 0.2f; + }}; + }}); + + abilities.add(new MoveEffectAbility(){{ + effect = Fx.missileTrailSmokeSmall; + rotation = 180f; + y = -9f; + color = Color.grays(0.6f).lerp(Color.valueOf("f7e97e"), 0.5f).a(0.4f); + interval = 5f; + }}); + }}; }}; }}; }}); @@ -5005,7 +5046,7 @@ public class Blocks{ effect = Fx.missileTrailSmoke; rotation = 180f; y = -9f; - color = Color.grays(0.6f).lerp(Pal.redLight, 0.5f).a(0.4f); + color = Color.grays(0.6f).lerp(Color.valueOf("f7e97e"), 0.5f).a(0.4f); interval = 7f; }}); }}; diff --git a/core/src/mindustry/content/Fx.java b/core/src/mindustry/content/Fx.java index 9fdbe7ac4d..3709d935f9 100644 --- a/core/src/mindustry/content/Fx.java +++ b/core/src/mindustry/content/Fx.java @@ -519,6 +519,26 @@ public class Fx{ } }).layer(Layer.bullet - 1f), + missileTrailSmokeSmall = new Effect(120f, 200f, b -> { + float intensity = 1.3f; + + color(b.color, 0.7f); + for(int i = 0; i < 3; i++){ + rand.setSeed(b.id*2 + i); + float lenScl = rand.random(0.5f, 1f); + int fi = i; + b.scaled(b.lifetime * lenScl, e -> { + randLenVectors(e.id + fi - 1, e.fin(Interp.pow10Out), (int)(2.9f * intensity), 13f * intensity, (x, y, in, out) -> { + float fout = e.fout(Interp.pow5Out) * rand.random(0.5f, 1f); + float rad = fout * ((2f + intensity) * 2.35f); + + Fill.circle(e.x + x, e.y + y, rad); + Drawf.light(e.x + x, e.y + y, rad * 2.5f, b.color, 0.5f); + }); + }); + } + }).layer(Layer.bullet - 1f), + neoplasmSplat = new Effect(400f, 300f, b -> { float intensity = 3f; @@ -557,6 +577,24 @@ public class Fx{ } }), + scatheExplosionSmall = new Effect(40f, 160f, e -> { + color(e.color); + stroke(e.fout() * 4f); + float circleRad = 6f + e.finpow() * 40f; + Lines.circle(e.x, e.y, circleRad); + + rand.setSeed(e.id); + for(int i = 0; i < 16; i++){ + float angle = rand.random(360f); + float lenRand = rand.random(0.5f, 1f); + Tmp.v1.trns(angle, circleRad); + + for(int s : Mathf.signs){ + Drawf.tri(e.x + Tmp.v1.x, e.y + Tmp.v1.y, e.foutpow() * 30f, e.fout() * 25f * lenRand + 6f, angle + 90f + s * 90f); + } + } + }), + scatheLight = new Effect(60f, 160f, e -> { float circleRad = 6f + e.finpow() * 60f; @@ -564,6 +602,13 @@ public class Fx{ Fill.circle(e.x, e.y, circleRad); }).layer(Layer.bullet + 2f), + scatheLightSmall = new Effect(60f, 160f, e -> { + float circleRad = 6f + e.finpow() * 40f; + + color(e.color, e.foutpow()); + Fill.circle(e.x, e.y, circleRad); + }).layer(Layer.bullet + 2f), + scatheSlash = new Effect(40f, 160f, e -> { Draw.color(e.color); for(int s : Mathf.signs){ @@ -1737,6 +1782,18 @@ public class Fx{ } }), + shootSmokeMissileColor = new Effect(130f, 300f, e -> { + color(e.color); + alpha(0.5f); + rand.setSeed(e.id); + for(int i = 0; i < 35; i++){ + v.trns(e.rotation + 180f + rand.range(21f), rand.random(e.finpow() * 90f)).add(rand.range(3f), rand.range(3f)); + e.scaled(e.lifetime * rand.random(0.2f, 1f), b -> { + Fill.circle(e.x + v.x, e.y + v.y, b.fout() * 9f + 0.3f); + }); + } + }), + regenParticle = new Effect(100f, e -> { color(Pal.regen); diff --git a/core/src/mindustry/entities/bullet/BulletType.java b/core/src/mindustry/entities/bullet/BulletType.java index 2c18fa158a..a4ad4fff13 100644 --- a/core/src/mindustry/entities/bullet/BulletType.java +++ b/core/src/mindustry/entities/bullet/BulletType.java @@ -527,7 +527,7 @@ public class BulletType extends Content implements Cloneable{ if(fragBullet != null && (fragOnAbsorb || !b.absorbed) && !(b.frags >= pierceFragCap && pierceFragCap > 0)){ for(int i = 0; i < fragBullets; i++){ float len = Mathf.random(fragOffsetMin, fragOffsetMax); - float a = b.rotation() + Mathf.range(fragRandomSpread / 2) + fragAngle + ((i - fragBullets/2) * fragSpread); + float a = b.rotation() + Mathf.range(fragRandomSpread / 2) + fragAngle + fragSpread * i - (fragBullets - 1) * fragSpread / 2f; fragBullet.create(b, x + Angles.trnsx(a, len), y + Angles.trnsy(a, len), a, Mathf.random(fragVelocityMin, fragVelocityMax), Mathf.random(fragLifeMin, fragLifeMax)); } b.frags++; @@ -819,7 +819,7 @@ public class BulletType extends Content implements Cloneable{ Bullet bullet = Bullet.create(); bullet.type = this; - bullet.owner = owner; + bullet.owner = shooter == null ? owner : shooter; bullet.team = team; bullet.time = 0f; bullet.originX = x; diff --git a/core/src/mindustry/entities/comp/UnitComp.java b/core/src/mindustry/entities/comp/UnitComp.java index 548e34965e..ef479e2956 100644 --- a/core/src/mindustry/entities/comp/UnitComp.java +++ b/core/src/mindustry/entities/comp/UnitComp.java @@ -445,6 +445,10 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I } } + public boolean isMissile(){ + return this instanceof TimedKillc; + } + public int count(){ return team.data().countType(type); }