diff --git a/core/src/mindustry/content/Fx.java b/core/src/mindustry/content/Fx.java index 690e6b4a85..6212d64e63 100644 --- a/core/src/mindustry/content/Fx.java +++ b/core/src/mindustry/content/Fx.java @@ -291,6 +291,18 @@ public class Fx{ Lines.circle(e.x, e.y, 2f + e.finpow() * 7f); }), + shieldWave = new Effect(22, e -> { + color(Pal.shield); + stroke(e.fout() * 2f); + Lines.circle(e.x, e.y, 4f + e.finpow() * 60f); + }), + + shieldApply = new Effect(11, e -> { + color(Pal.shield); + stroke(e.fout() * 2f); + Lines.circle(e.x, e.y, 2f + e.finpow() * 7f); + }), + hitBulletSmall = new Effect(14, e -> { color(Color.white, Pal.lightOrange, e.fin()); @@ -1275,9 +1287,9 @@ public class Fx{ }), shieldBreak = new Effect(40, e -> { - color(Pal.accent); + color(e.color); stroke(3f * e.fout()); - Lines.poly(e.x, e.y, 6, e.rotation + e.fin(), 90); + Lines.poly(e.x, e.y, 6, e.rotation + e.fin()); }), unitShieldBreak = new Effect(35, e -> { diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index 002c075f88..c88a068359 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -5,8 +5,8 @@ import arc.struct.*; import mindustry.ai.types.*; import mindustry.annotations.Annotations.*; import mindustry.ctype.*; +import mindustry.entities.abilities.*; import mindustry.entities.bullet.*; -import mindustry.entities.units.*; import mindustry.gen.*; import mindustry.graphics.*; import mindustry.type.*; @@ -129,6 +129,8 @@ public class UnitTypes implements ContentList{ buildSpeed = 0.8f; armor = 1f; + abilities.add(new HealFieldAbility(10f, 60f * 4, 60f)); + weapons.add(new Weapon("heal-weapon"){{ shootY = 2f; reload = 24f; @@ -155,7 +157,7 @@ public class UnitTypes implements ContentList{ mineSpeed = 5f; commandLimit = 8; - abilities.add(new HealFieldAbility(10f, 200f, 60f)); + abilities.add(new ShieldFieldAbility(15f, 30f, 60f * 5, 60f)); weapons.add(new Weapon("heal-shotgun-weapon"){{ x = 5f; @@ -199,8 +201,9 @@ public class UnitTypes implements ContentList{ mineTier = 2; mineSpeed = 7f; + drawShields = false; - abilities.add(new HealFieldAbility(15f, 170f, 60f)); + abilities.add(new ForceFieldAbility(60f, 0.12f, 200f, 60f * 8)); weapons.add(new Weapon("beam-weapon"){{ shake = 2f; diff --git a/core/src/mindustry/entities/units/Ability.java b/core/src/mindustry/entities/abilities/Ability.java similarity index 76% rename from core/src/mindustry/entities/units/Ability.java rename to core/src/mindustry/entities/abilities/Ability.java index cdd6d7fc6a..d8aed57239 100644 --- a/core/src/mindustry/entities/units/Ability.java +++ b/core/src/mindustry/entities/abilities/Ability.java @@ -1,4 +1,4 @@ -package mindustry.entities.units; +package mindustry.entities.abilities; import mindustry.gen.*; diff --git a/core/src/mindustry/entities/abilities/ForceFieldAbility.java b/core/src/mindustry/entities/abilities/ForceFieldAbility.java new file mode 100644 index 0000000000..57841d6886 --- /dev/null +++ b/core/src/mindustry/entities/abilities/ForceFieldAbility.java @@ -0,0 +1,82 @@ +package mindustry.entities.abilities; + +import arc.func.*; +import arc.graphics.*; +import arc.graphics.g2d.*; +import arc.math.*; +import arc.math.geom.*; +import arc.util.*; +import mindustry.content.*; +import mindustry.gen.*; +import mindustry.graphics.*; + +public class ForceFieldAbility implements Ability{ + /** Shield radius. */ + public float radius = 60f; + /** Shield regen speed in damage/tick. */ + public float regen = 0.1f; + /** Maximum shield. */ + public float max = 200f; + /** Cooldown after the shield is broken, in ticks. */ + public float cooldown = 60f * 5; + + private float realRad; + private Unit paramUnit; + private final Cons shieldConsumer = trait -> { + if(trait.team() != paramUnit.team && Intersector.isInsideHexagon(paramUnit.x, paramUnit.y, realRad * 2f, trait.x(), trait.y()) && paramUnit.shield > 0){ + trait.absorb(); + Fx.absorb.at(trait); + + //break shield + if(paramUnit.shield <= trait.damage()){ + paramUnit.shield -= cooldown * regen; + Fx.shieldBreak.at(paramUnit.x, paramUnit.y, radius, paramUnit.team.color); + } + + paramUnit.shield -= trait.damage(); + paramUnit.shieldAlpha = 1f; + } + }; + + public ForceFieldAbility(float radius, float regen, float max, float cooldown){ + this.radius = radius; + this.regen = regen; + this.max = max; + this.cooldown = cooldown; + } + + ForceFieldAbility(){} + + @Override + public void update(Unit unit){ + if(unit.shield < max){ + unit.shield += Time.delta() * regen; + } + + if(unit.shield > 0){ + unit.timer2 = Mathf.lerpDelta(unit.timer2, 1f, 0.06f); + paramUnit = unit; + checkRadius(unit); + + Groups.bullet.intersect(unit.x - realRad, unit.y - realRad, realRad * 2f, realRad * 2f, shieldConsumer); + }else{ + unit.timer2 = 0f; + } + } + + @Override + public void draw(Unit unit){ + checkRadius(unit); + + if(unit.shield > 0){ + Draw.z(Layer.shields); + Draw.color(unit.team.color, Color.white, Mathf.clamp(unit.shieldAlpha)); + Fill.poly(unit.x, unit.y, 6, realRad); + } + } + + private void checkRadius(Unit unit){ + //timer2 is used to store radius scale as an effect + realRad = unit.timer2 * radius; + } +} diff --git a/core/src/mindustry/entities/units/HealFieldAbility.java b/core/src/mindustry/entities/abilities/HealFieldAbility.java similarity index 96% rename from core/src/mindustry/entities/units/HealFieldAbility.java rename to core/src/mindustry/entities/abilities/HealFieldAbility.java index 7925410913..df3903ffa5 100644 --- a/core/src/mindustry/entities/units/HealFieldAbility.java +++ b/core/src/mindustry/entities/abilities/HealFieldAbility.java @@ -1,4 +1,4 @@ -package mindustry.entities.units; +package mindustry.entities.abilities; import arc.util.*; import mindustry.content.*; diff --git a/core/src/mindustry/entities/abilities/ShieldFieldAbility.java b/core/src/mindustry/entities/abilities/ShieldFieldAbility.java new file mode 100644 index 0000000000..15f9fc9147 --- /dev/null +++ b/core/src/mindustry/entities/abilities/ShieldFieldAbility.java @@ -0,0 +1,47 @@ +package mindustry.entities.abilities; + +import arc.util.*; +import mindustry.content.*; +import mindustry.entities.*; +import mindustry.gen.*; + +public class ShieldFieldAbility implements Ability{ + public float amount = 1, max = 100f, reload = 100, range = 60; + public Effect applyEffect = Fx.shieldApply; + public Effect activeEffect = Fx.shieldWave; + + private boolean applied = false; + + ShieldFieldAbility(){} + + public ShieldFieldAbility(float amount, float max, float reload, float range){ + this.amount = amount; + this.max = max; + this.reload = reload; + this.range = range; + } + + @Override + public void update(Unit unit){ + unit.timer1 += Time.delta(); + + if(unit.timer1 >= reload){ + applied = false; + + Units.nearby(unit.team, unit.x, unit.y, range, other -> { + if(other.shield < max){ + other.shield = Math.max(other.shield + amount, max); + other.shieldAlpha = 1f; //TODO may not be necessary + applyEffect.at(unit); + applied = true; + } + }); + + if(applied){ + activeEffect.at(unit); + } + + unit.timer1 = 0f; + } + } +} diff --git a/core/src/mindustry/entities/units/StatusFieldAbility.java b/core/src/mindustry/entities/abilities/StatusFieldAbility.java similarity index 96% rename from core/src/mindustry/entities/units/StatusFieldAbility.java rename to core/src/mindustry/entities/abilities/StatusFieldAbility.java index 2df5fda9fb..1993e29120 100644 --- a/core/src/mindustry/entities/units/StatusFieldAbility.java +++ b/core/src/mindustry/entities/abilities/StatusFieldAbility.java @@ -1,4 +1,4 @@ -package mindustry.entities.units; +package mindustry.entities.abilities; import arc.util.ArcAnnotate.*; import arc.util.*; diff --git a/core/src/mindustry/entities/comp/ShieldComp.java b/core/src/mindustry/entities/comp/ShieldComp.java index 204efff128..421bf1295f 100644 --- a/core/src/mindustry/entities/comp/ShieldComp.java +++ b/core/src/mindustry/entities/comp/ShieldComp.java @@ -34,7 +34,7 @@ abstract class ShieldComp implements Healthc, Posc{ shieldAlpha = 1f; } - float shieldDamage = Math.min(shield, amount); + float shieldDamage = Math.min(Math.max(shield, 0), amount); shield -= shieldDamage; amount -= shieldDamage; diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index 453f68369a..55c22cb37a 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -17,6 +17,7 @@ import mindustry.annotations.Annotations.*; import mindustry.content.*; import mindustry.ctype.*; import mindustry.entities.*; +import mindustry.entities.abilities.*; import mindustry.entities.units.*; import mindustry.game.*; import mindustry.gen.*; @@ -42,7 +43,6 @@ public class UnitType extends UnlockableContent{ public boolean faceTarget = true, rotateShooting = true, isCounted = true, lowAltitude = false; public boolean canBoost = false; public boolean destructibleWreck = true; - public float wreckHealth = 15f; public float sway = 1f; public int payloadCapacity = 1; public int commandLimit = 24; @@ -50,7 +50,7 @@ public class UnitType extends UnlockableContent{ public float deathShake = 2f; public Effect fallEffect = Fx.fallSmoke; public Effect fallThrusterEffect = Fx.fallSmoke; - public Seq abilities = new Seq<>(); + public Seq abilities = new Seq<>(); //TODO document public int legCount = 4, legGroupSize = 2; @@ -69,7 +69,7 @@ public class UnitType extends UnlockableContent{ public float itemOffsetY = 3f; public float lightRadius = 60f, lightOpacity = 0.6f; public Color lightColor = Pal.powerLight; - public boolean drawCell = true, drawItems = true; + public boolean drawCell = true, drawItems = true, drawShields = true; public int parts = 0; public int trailLength = 5; @@ -106,7 +106,7 @@ public class UnitType extends UnlockableContent{ public void update(Unit unit){ if(abilities.size > 0){ - for(Ability a : abilities){ + for(mindustry.entities.abilities.Ability a : abilities){ a.update(unit); } } @@ -255,19 +255,20 @@ public class UnitType extends UnlockableContent{ if(drawItems) drawItems(unit); drawLight(unit); - if(unit.shieldAlpha > 0){ + if(unit.shieldAlpha > 0 && drawShields){ drawShield(unit); } + if(legs != null){ + unit.trns(-legOffset.x, -legOffset.y); + } + if(abilities.size > 0){ for(Ability a : abilities){ a.draw(unit); + Draw.reset(); } } - - if(legs != null){ - unit.trns(-legOffset.x, -legOffset.y); - } } public void drawPayload(T unit){ diff --git a/core/src/mindustry/world/blocks/defense/ForceProjector.java b/core/src/mindustry/world/blocks/defense/ForceProjector.java index 669cb750f0..a2570b8385 100644 --- a/core/src/mindustry/world/blocks/defense/ForceProjector.java +++ b/core/src/mindustry/world/blocks/defense/ForceProjector.java @@ -122,7 +122,7 @@ public class ForceProjector extends Block{ if(buildup >= breakage && !broken){ broken = true; buildup = breakage; - Fx.shieldBreak.at(x, y, radius); + Fx.shieldBreak.at(x, y, radius, team.color); } if(hit > 0f){ @@ -162,8 +162,6 @@ public class ForceProjector extends Block{ if(Core.settings.getBool("animatedshields")){ Fill.poly(x, y, 6, radius); - - Draw.z(Layer.shields + 0.01f); }else{ Lines.stroke(1.5f); Draw.alpha(0.09f + Mathf.clamp(0.08f * hit));