From c8da2418256d9b15a36d7113847d0f4e6683e302 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 4 Feb 2022 17:34:13 -0500 Subject: [PATCH] Disrupt weapons complete --- .../units/weapons/disrupt-missile-fin.png | Bin 0 -> 305 bytes .../sprites/units/weapons/disrupt-missile.png | Bin 502 -> 639 bytes core/src/mindustry/content/Blocks.java | 6 +- core/src/mindustry/content/UnitTypes.java | 52 ++++++++++++-- core/src/mindustry/entities/Damage.java | 30 ++++++++ .../abilities/SuppressionFieldAbility.java | 58 ++-------------- .../mindustry/entities/bullet/BulletType.java | 8 +++ .../src/mindustry/entities/part/DrawPart.java | 9 ++- .../mindustry/entities/part/RegionPart.java | 3 - .../mindustry/entities/part/ShapePart.java | 64 ++++++++++++++++++ core/src/mindustry/graphics/Pal.java | 2 + core/src/mindustry/type/UnitType.java | 6 ++ .../mindustry/type/unit/MissileUnitType.java | 2 +- 13 files changed, 171 insertions(+), 69 deletions(-) create mode 100644 core/assets-raw/sprites/units/weapons/disrupt-missile-fin.png create mode 100644 core/src/mindustry/entities/part/ShapePart.java diff --git a/core/assets-raw/sprites/units/weapons/disrupt-missile-fin.png b/core/assets-raw/sprites/units/weapons/disrupt-missile-fin.png new file mode 100644 index 0000000000000000000000000000000000000000..9b5173fb28a090065fd2fdc6231d51f92192a984 GIT binary patch literal 305 zcmeAS@N?(olHy`uVBq!ia0y~yU{GaXU@+%kV_;zDZfKs&z`(#*9OUlAuae0M^?B0&Pb>|*UJaRMC#Zg}=#jyOMW>EI!I>q5QI zU3um{Ynxbrm*&zbL0+0muk@RJvigu$Ut#ur`|PciI^rSHQ#KuXu|h^8wJ|WzdBGKd zoHGw^I8M{hP~%WI7ZR@M(jw4Z|GX_L$tzKBg`Nv%Pv0x)J6www=`=^}Gfqs?qKtuJj_BLr9Qm+qbZ$CZQuvo|DxgZbm-g)OoW;rPp_ZASb6r z1gBj?Z-D~a`~&PA5gCfo$IhO4bLO2A$8YBcdHK)gzyD@dzMDHBB;<>I$m!IQi?8c< zK3?pn-JLHc%=2stv%$>t5DPTcuiMRwZ;D#|0H+JJM`A#o|3VQo{1FSk%$^wwhJuRGh@$*NbI+p zyfMUjs=g<$y5w&KnSv9?r*ruwzi3b~=$3C_I#;w@%Ak9F<{8;F@==E-f4*9<@8iwA z>n6yjGm1RCbKF*}r@Opv;Ynue=z`9F()YO9N;g%0ef=l(qZGrBNbZ}(cVs;i%D0=F zet(>_qh{T_sx!Rz{9FxQ#=L&)&6>{0y|w+%hNc3;gjuhp90bqJFT4_d?Mgz3%(>-% zt`@{Big(b~^Jh|dI8V<0sFU?>U*<52d8?0qyYr;BGbi8V72BEuxo~y`gJ-i&$8KvV z%j|eu<8c2zi?|U7qt|uk1cp=J=NK+|QeA!lK z*%;R?ahG6v{q^=Q{{2%JJ{UjdUAt$F+u=qF=V`Ax`b!^IB&rFDZ_?q_bT}2y`&>GJ z)xu$w?DO^m3_Q^Z(YLDuSC@I+dcP_2z7G2WF&>4a&jzd)nAik%ZkA-uU}f&Ole+0# sUGf12A@enb{7DS!_O5_{j;rR1XH9HA{a}z}U|?YIboFyt=akR{0Os@%TL1t6 literal 502 zcmeAS@N?(olHy`uVBq!ia0y~yU@&B0V9@7aV_;zLa!~rtz`(#*9OUlAunDE+NrR<=SXR`1g70+bhEnds(TGmcDX414Y zVYXh_=A5>>D~c5-DDK`|{e14-nRh!qmIkf-IiOc*)Gu5;q5g0NcYiAH*GAXHng}ZY>%Hc zoq3W+X+?3Rw$jU{!ygOgnT9uiE4#$PG>e1Dl}Wcl_0hBwqL{^io6Qy)%Q%E z^s%VGlc#NQ>ADF|pSy1^6yB6R6{=W35u6nNcb(eVSrz|>eIr2Kc#ojskRcVQOqu3z<0Y$#$mzpA& zl%8yz{CBZw`Tnrm2jWld;CQn3(1`+LiN0(1tWTX-5u!Eq)U_YXrzc)rxLtl1Hv builds = new Seq<>(); + + public static void applySuppression(Team team, float x, float y, float range, float reload, float maxDelay, float applyParticleChance, @Nullable Position source){ + builds.clear(); + indexer.eachBlock(null, x, y, range, build -> build.team != team, build -> { + float prev = build.healSuppressionTime; + build.applyHealSuppression(reload + 1f); + + //TODO maybe should be block field instead of instanceof check + if(build.wasRecentlyHealed(60f * 12f) || (build instanceof MendBuild || build instanceof RegenProjectorBuild)){ + + //add prev check so ability spam doesn't lead to particle spam (essentially, recently suppressed blocks don't get new particles) + if(!headless && prev - Time.time <= reload/2f){ + builds.add(build); + } + } + }); + + //to prevent particle spam, the amount of particles is to remain constant (scales with number of buildings) + float scaledChance = applyParticleChance / builds.size; + for(var build : builds){ + if(Mathf.chance(scaledChance)){ + Time.run(Mathf.random(maxDelay), () -> { + Fx.regenSuppressSeek.at(build.x + Mathf.range(build.block.size * tilesize / 2f), build.y + Mathf.range(build.block.size * tilesize / 2f), 0f, source); + }); + } + } + } /** Creates a dynamic explosion based on specified parameters. */ public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, boolean damage){ diff --git a/core/src/mindustry/entities/abilities/SuppressionFieldAbility.java b/core/src/mindustry/entities/abilities/SuppressionFieldAbility.java index ddbe055b66..5cb7c992c8 100644 --- a/core/src/mindustry/entities/abilities/SuppressionFieldAbility.java +++ b/core/src/mindustry/entities/abilities/SuppressionFieldAbility.java @@ -3,26 +3,19 @@ package mindustry.entities.abilities; import arc.graphics.*; import arc.graphics.g2d.*; import arc.math.*; -import arc.struct.*; import arc.util.*; -import mindustry.*; -import mindustry.content.*; +import mindustry.entities.*; import mindustry.gen.*; import mindustry.graphics.*; -import mindustry.world.blocks.defense.MendProjector.*; -import mindustry.world.blocks.defense.RegenProjector.*; - -import static mindustry.Vars.*; public class SuppressionFieldAbility extends Ability{ protected static Rand rand = new Rand(); - protected static Seq builds = new Seq<>(); public float reload = 60f * 1.5f; public float range = 200f; public float orbRadius = 4.1f, orbMidScl = 0.33f, orbSinScl = 8f, orbSinMag = 1f; - public Color color = Pal.sap.cpy().mul(1.6f); + public Color color = Pal.suppress; public float layer = Layer.effect; public float x = 0f, y = 0f; @@ -37,49 +30,17 @@ public class SuppressionFieldAbility extends Ability{ public float applyParticleChance = 13f; - protected boolean any; protected float timer; - protected float heat = 0f; @Override public void update(Unit unit){ if(!active) return; if((timer += Time.delta) >= reload){ - any = false; - builds.clear(); - Vars.indexer.eachBlock(null, unit.x,unit.y, range, build -> true, build -> { - if(build.team != unit.team){ - float prev = build.healSuppressionTime; - build.applyHealSuppression(reload + 1f); - - //TODO maybe should be block field instead of instanceof check - if(build.wasRecentlyHealed(60f * 12f) || (build instanceof MendBuild || build instanceof RegenProjectorBuild)){ - any = true; - - //add prev check so ability spam doesn't lead to particle spam (essentially, recently suppressed blocks don't get new particles) - if(!headless && prev - Time.time <= reload/2f){ - builds.add(build); - } - } - } - }); - - //to prevent particle spam, the amount of particles is to remain constant (scales with number of buildings) - float scaledChance = applyParticleChance / builds.size; - for(var build : builds){ - if(Mathf.chance(scaledChance)){ - Time.run(Mathf.random(reload), () -> { - Fx.regenSuppressSeek.at(build.x + Mathf.range(build.block.size * tilesize / 2f), build.y + Mathf.range(build.block.size * tilesize / 2f), 0f, unit); - }); - } - } - + Tmp.v1.set(x, y).rotate(unit.rotation - 90f).add(unit); + Damage.applySuppression(unit.team, Tmp.v1.x, Tmp.v1.y, range, reload, reload, applyParticleChance, unit); timer = 0f; } - - heat = Mathf.lerpDelta(heat, any ? 1f : 0f, 0.09f); - } @Override @@ -87,8 +48,8 @@ public class SuppressionFieldAbility extends Ability{ Draw.z(layer); float rad = orbRadius + Mathf.absin(orbSinScl, orbSinMag); - Tmp.v1.set(x, y).rotate(unit.rotation - 90f); - float rx = unit.x + Tmp.v1.x, ry = unit.y + Tmp.v1.y; + Tmp.v1.set(x, y).rotate(unit.rotation - 90f).add(unit); + float rx = Tmp.v1.x, ry = Tmp.v1.y; float base = (Time.time / particleLife); rand.setSeed(unit.id + hashCode()); @@ -112,13 +73,6 @@ public class SuppressionFieldAbility extends Ability{ Draw.color(color); Fill.circle(rx, ry, rad * orbMidScl); - //TODO improve - if(heat > 0.001f && false){ - Draw.color(Pal.sapBullet); - Lines.stroke(1.2f * heat * Mathf.absin(10f, 1f)); - Lines.circle(rx, ry, range); - } - Draw.reset(); } } diff --git a/core/src/mindustry/entities/bullet/BulletType.java b/core/src/mindustry/entities/bullet/BulletType.java index 81441e4ac8..60efac8679 100644 --- a/core/src/mindustry/entities/bullet/BulletType.java +++ b/core/src/mindustry/entities/bullet/BulletType.java @@ -5,6 +5,7 @@ import arc.audio.*; import arc.graphics.*; import arc.graphics.g2d.*; import arc.math.*; +import arc.math.geom.*; import arc.struct.*; import arc.util.*; import mindustry.*; @@ -171,6 +172,8 @@ public class BulletType extends Content implements Cloneable{ /** Use a negative value to disable homing delay. */ public float homingDelay = -1f; + public float suppressionRange = -1f, suppressionDuration = 60f * 8f, suppressionEffectChance = 50f; + public Color lightningColor = Pal.surge; public int lightning; public int lightningLength = 5, lightningLengthRand = 0; @@ -310,6 +313,11 @@ public class BulletType extends Content implements Cloneable{ Damage.createIncend(x, y, incendSpread, incendAmount); } + if(suppressionRange > 0){ + //bullets are pooled, require separate Vec2 instance + Damage.applySuppression(b.team, b.x, b.y, suppressionRange, suppressionDuration, 0f, suppressionEffectChance, new Vec2(b.x, b.y)); + } + if(splashDamageRadius > 0 && !b.absorbed){ Damage.damage(b.team, x, y, splashDamageRadius, splashDamage * b.damageMultiplier(), false, collidesAir, collidesGround, scaledSplashDamage); diff --git a/core/src/mindustry/entities/part/DrawPart.java b/core/src/mindustry/entities/part/DrawPart.java index 00e465e07e..06b6c168fc 100644 --- a/core/src/mindustry/entities/part/DrawPart.java +++ b/core/src/mindustry/entities/part/DrawPart.java @@ -19,7 +19,7 @@ public abstract class DrawPart{ /** Parameters for drawing a part in draw(). */ public static class PartParams{ //TODO document - public float warmup, reload, smoothReload, heat; + public float warmup, reload, smoothReload, heat, life; public float x, y, rotation; public int sideOverride = -1; @@ -32,6 +32,7 @@ public abstract class DrawPart{ this.y = y; this.rotation = rotation; this.sideOverride = -1; + this.life = 0f; return this; } } @@ -45,7 +46,9 @@ public abstract class DrawPart{ /** Weapon warmup, 0 when not firing, 1 when actively shooting. Not equivalent to heat. */ warmup = p -> p.warmup, /** Weapon heat, 1 when just fired, 0, when it has cooled down (duration depends on weapon) */ - heat = p -> p.heat; + heat = p -> p.heat, + /** Lifetime fraction, 0 to 1. Only for missiles. */ + life = p -> p.life; float get(PartParams p); @@ -78,7 +81,7 @@ public abstract class DrawPart{ } default PartProgress mul(float amount){ - return p -> get(p) * amount; + return p -> Mathf.clamp(get(p) * amount); } default PartProgress min(PartProgress other){ diff --git a/core/src/mindustry/entities/part/RegionPart.java b/core/src/mindustry/entities/part/RegionPart.java index 37d3a5d905..a1728ed75b 100644 --- a/core/src/mindustry/entities/part/RegionPart.java +++ b/core/src/mindustry/entities/part/RegionPart.java @@ -3,7 +3,6 @@ package mindustry.entities.part; import arc.*; import arc.graphics.*; import arc.graphics.g2d.*; -import arc.math.*; import arc.struct.*; import arc.util.*; import mindustry.graphics.*; @@ -30,7 +29,6 @@ public class RegionPart extends DrawPart{ /** Progress function for heat alpha. */ public PartProgress heatProgress = PartProgress.heat; public Blending blending = Blending.normal; - public Interp interp = Interp.linear; public float layer = -1, layerOffset = 0f; public float outlineLayerOffset = -0.001f; public float rotation, rotMove; @@ -64,7 +62,6 @@ public class RegionPart extends DrawPart{ float prevZ = Draw.z(); float prog = progress.get(params); - prog = interp.apply(prog); int len = mirror && params.sideOverride == -1 ? 2 : 1; for(int s = 0; s < len; s++){ diff --git a/core/src/mindustry/entities/part/ShapePart.java b/core/src/mindustry/entities/part/ShapePart.java new file mode 100644 index 0000000000..80407f66d7 --- /dev/null +++ b/core/src/mindustry/entities/part/ShapePart.java @@ -0,0 +1,64 @@ +package mindustry.entities.part; + +import arc.graphics.*; +import arc.graphics.g2d.*; +import arc.math.*; +import arc.util.*; + +public class ShapePart extends DrawPart{ + public boolean circle = false; + public int sides = 3; + public float radius = 3f, radiusTo = -1f; + public float x, y, rotation; + public float moveX, moveY, rotMove; + public Color color = Color.white; + public @Nullable Color colorTo; + public boolean mirror = false; + public PartProgress progress = PartProgress.warmup; + public float layer = -1f, layerOffset = 0f; + + @Override + public void draw(PartParams params){ + float z = Draw.z(); + if(layer > 0) Draw.z(layer); + if(under && turretShading) Draw.z(z - 0.0001f); + + Draw.z(Draw.z() + layerOffset); + + float prog = progress.get(params); + int len = mirror && params.sideOverride == -1 ? 2 : 1; + + for(int s = 0; s < len; s++){ + //use specific side if necessary + int i = params.sideOverride == -1 ? s : params.sideOverride; + + float sign = i == 1 ? -1 : 1; + Tmp.v1.set((x + moveX * prog) * sign, y + moveY * prog).rotate(params.rotation - 90); + + float + rx = params.x + Tmp.v1.x, + ry = params.y + Tmp.v1.y, + rad = radiusTo < 0 ? radius : Mathf.lerp(radius, radiusTo, prog); + + if(color != null && colorTo != null){ + Draw.color(color, colorTo, prog); + }else if(color != null){ + Draw.color(color); + } + + if(!circle){ + Fill.poly(rx, ry, sides, rad, rotMove * prog * sign + params.rotation - 90); + }else{ + Fill.circle(rx, ry, rad); + } + if(color != null) Draw.color(); + } + + Draw.z(z); + } + + @Override + public void load(String name){ + + } +} diff --git a/core/src/mindustry/graphics/Pal.java b/core/src/mindustry/graphics/Pal.java index 0915b08c4b..c1bca3c7f7 100644 --- a/core/src/mindustry/graphics/Pal.java +++ b/core/src/mindustry/graphics/Pal.java @@ -16,6 +16,8 @@ public class Pal{ sapBullet = Color.valueOf("bf92f9"), sapBulletBack = Color.valueOf("6d56bf"), + suppress = Pal.sap.cpy().mul(1.6f), + regen = Color.valueOf("d1efff"), reactorPurple = Color.valueOf("bf92f9"), diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index 370c810e46..b3bb0d5c8d 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -593,6 +593,9 @@ public class UnitType extends UnlockableContent{ part.getOutlines(out); } } + for(var part : parts){ + part.getOutlines(out); + } } @Override @@ -811,6 +814,9 @@ public class UnitType extends UnlockableContent{ }else{ DrawPart.params.set(0f, 0f, 0f, 0f, unit.x, unit.y, unit.rotation); } + if(unit instanceof Scaled s){ + DrawPart.params.life = s.fin(); + } for(int i = 0; i < parts.size; i++){ var part = parts.items[i]; part.draw(DrawPart.params); diff --git a/core/src/mindustry/type/unit/MissileUnitType.java b/core/src/mindustry/type/unit/MissileUnitType.java index 6610f36149..0839e72722 100644 --- a/core/src/mindustry/type/unit/MissileUnitType.java +++ b/core/src/mindustry/type/unit/MissileUnitType.java @@ -27,7 +27,7 @@ public class MissileUnitType extends UnitType{ trailLength = 7; hidden = true; speed = 4f; - lifetime = 60f * 1.6f; + lifetime = 60f * 1.7f; rotateSpeed = 2.5f; range = 30f; //TODO weapons, etc