diff --git a/core/assets/sounds/shieldBreak.ogg b/core/assets/sounds/shieldBreak.ogg new file mode 100644 index 0000000000..34e46fadda Binary files /dev/null and b/core/assets/sounds/shieldBreak.ogg differ diff --git a/core/assets/sounds/shieldBreakSmall.ogg b/core/assets/sounds/shieldBreakSmall.ogg new file mode 100644 index 0000000000..5b48066129 Binary files /dev/null and b/core/assets/sounds/shieldBreakSmall.ogg differ diff --git a/core/assets/sounds/shieldHit.ogg b/core/assets/sounds/shieldHit.ogg new file mode 100644 index 0000000000..e2dc8f4a2e Binary files /dev/null and b/core/assets/sounds/shieldHit.ogg differ diff --git a/core/assets/sounds/shockwaveTower.ogg b/core/assets/sounds/shockwaveTower.ogg new file mode 100644 index 0000000000..c043ea65b6 Binary files /dev/null and b/core/assets/sounds/shockwaveTower.ogg differ diff --git a/core/src/mindustry/audio/SoundPriority.java b/core/src/mindustry/audio/SoundPriority.java index 7a1fa1dcfb..1f865f0b00 100644 --- a/core/src/mindustry/audio/SoundPriority.java +++ b/core/src/mindustry/audio/SoundPriority.java @@ -59,6 +59,8 @@ public class SoundPriority{ walkerStep.setMinConcurrentInterrupt(0.6f); mechStepHeavy.setMinConcurrentInterrupt(0.6f); + shieldHit.setMaxConcurrent(4); + max(4, mechStep, mechStepHeavy, walkerStep); } diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index e6ba7d46e9..d61fb5f036 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -1514,7 +1514,9 @@ public class UnitTypes{ buildBeamOffset = 43; ammoCapacity = 1; - abilities.add(new ForceFieldAbility(140f, 4f, 7000f, 60f * 8, 8, 0f), new RepairFieldAbility(130f, 60f * 2, 140f)); + abilities.add(new ForceFieldAbility(140f, 4f, 7000f, 60f * 8, 8, 0f){{ + breakSound = Sounds.shieldBreak; + }}, new RepairFieldAbility(130f, 60f * 2, 140f)); }}; //endregion diff --git a/core/src/mindustry/entities/abilities/ForceFieldAbility.java b/core/src/mindustry/entities/abilities/ForceFieldAbility.java index 2ef8e8e804..f9906d8660 100644 --- a/core/src/mindustry/entities/abilities/ForceFieldAbility.java +++ b/core/src/mindustry/entities/abilities/ForceFieldAbility.java @@ -1,6 +1,7 @@ package mindustry.entities.abilities; import arc.*; +import arc.audio.*; import arc.func.*; import arc.graphics.*; import arc.graphics.g2d.*; @@ -30,6 +31,10 @@ public class ForceFieldAbility extends Ability{ /** Rotation of shield. */ public float rotation = 0f; + public Sound breakSound = Sounds.shieldBreakSmall; + public Sound hitSound = Sounds.shieldHit; + public float hitSoundVolume = 0.12f; + /** State. */ protected float radiusScale, alpha; protected boolean wasBroken = true; @@ -37,11 +42,12 @@ public class ForceFieldAbility extends Ability{ private static float realRad; private static Unit paramUnit; private static ForceFieldAbility paramField; - private static final Cons shieldConsumer = trait -> { - if(trait.team != paramUnit.team && trait.type.absorbable && Intersector.isInRegularPolygon(paramField.sides, paramUnit.x, paramUnit.y, realRad, paramField.rotation, trait.x(), trait.y()) && paramUnit.shield > 0){ - trait.absorb(); - Fx.absorb.at(trait); - paramUnit.shield -= trait.type().shieldDamage(trait); + private static final Cons shieldConsumer = b -> { + if(b.team != paramUnit.team && b.type.absorbable && Intersector.isInRegularPolygon(paramField.sides, paramUnit.x, paramUnit.y, realRad, paramField.rotation, b.x(), b.y()) && paramUnit.shield > 0){ + b.absorb(); + Fx.absorb.at(b); + paramField.hitSound.at(b.x, b.y, 1f + Mathf.range(0.1f), paramField.hitSoundVolume); + paramUnit.shield -= b.type().shieldDamage(b); paramField.alpha = 1f; } }; @@ -82,6 +88,7 @@ public class ForceFieldAbility extends Ability{ unit.shield -= cooldown * regen; Fx.shieldBreak.at(unit.x, unit.y, radius, unit.type.shieldColor(unit), this); + breakSound.at(unit.x, unit.y); } wasBroken = unit.shield <= 0f; @@ -110,6 +117,7 @@ public class ForceFieldAbility extends Ability{ //self-destructing units can have a shield on death if(unit.shield > 0f && !wasBroken){ Fx.shieldBreak.at(unit.x, unit.y, radius, unit.type.shieldColor(unit), this); + breakSound.at(unit.x, unit.y); } } diff --git a/core/src/mindustry/entities/abilities/ShieldArcAbility.java b/core/src/mindustry/entities/abilities/ShieldArcAbility.java index a044466d27..3dffd2c93e 100644 --- a/core/src/mindustry/entities/abilities/ShieldArcAbility.java +++ b/core/src/mindustry/entities/abilities/ShieldArcAbility.java @@ -16,6 +16,7 @@ import mindustry.graphics.*; import mindustry.ui.*; public class ShieldArcAbility extends Ability{ + private static Unit paramUnit; private static ShieldArcAbility paramField; private static Vec2 paramPos = new Vec2(); @@ -48,6 +49,8 @@ public class ShieldArcAbility extends Ability{ }else{ b.absorb(); Fx.absorb.at(b); + + paramField.hitSound.at(b.x, b.y, 1f + Mathf.range(0.1f), paramField.hitSoundVolume); } // break shield @@ -55,6 +58,8 @@ public class ShieldArcAbility extends Ability{ paramField.data -= paramField.cooldown * paramField.regen; Fx.arcShieldBreak.at(paramPos.x, paramPos.y, 0, paramField.color == null ? paramUnit.type.shieldColor(paramUnit) : paramField.color, paramUnit); + + paramField.breakSound.at(paramPos.x, paramPos.y); } // shieldDamage for consistency @@ -121,6 +126,9 @@ public class ShieldArcAbility extends Ability{ public float chanceDeflect = -1f; /** Deflection sound. */ public Sound deflectSound = Sounds.none; + public Sound breakSound = Sounds.shieldBreakSmall; + public Sound hitSound = Sounds.shieldHit; + public float hitSoundVolume = 0.12f; /** Multiplier for shield damage taken from missile units. */ public float missileUnitMultiplier = 2f; diff --git a/core/src/mindustry/entities/bullet/BulletType.java b/core/src/mindustry/entities/bullet/BulletType.java index d32d407937..22746e9c40 100644 --- a/core/src/mindustry/entities/bullet/BulletType.java +++ b/core/src/mindustry/entities/bullet/BulletType.java @@ -376,6 +376,13 @@ public class BulletType extends Content implements Cloneable{ } } + @Override + public void afterPatch(){ + super.afterPatch(); + + range = calculateRange(); + } + @Override public void load(){ for(var part : parts){ diff --git a/core/src/mindustry/mod/DataPatcher.java b/core/src/mindustry/mod/DataPatcher.java index 8690c50717..9b1a0ee398 100644 --- a/core/src/mindustry/mod/DataPatcher.java +++ b/core/src/mindustry/mod/DataPatcher.java @@ -137,6 +137,8 @@ public class DataPatcher{ weapon.load(); weapon.init(); }else if(object instanceof Content cont){ + cont.init(); + cont.postInit(); cont.load(); } }else{ diff --git a/core/src/mindustry/world/blocks/defense/ForceProjector.java b/core/src/mindustry/world/blocks/defense/ForceProjector.java index 37111fd26e..b73e8e07a7 100644 --- a/core/src/mindustry/world/blocks/defense/ForceProjector.java +++ b/core/src/mindustry/world/blocks/defense/ForceProjector.java @@ -1,6 +1,7 @@ package mindustry.world.blocks.defense; import arc.*; +import arc.audio.*; import arc.func.*; import arc.graphics.*; import arc.graphics.g2d.*; @@ -42,6 +43,9 @@ public class ForceProjector extends Block{ public float coolantConsumption = 0.1f; public boolean consumeCoolant = true; public float crashDamageMultiplier = 2f; + public Sound breakSound = Sounds.shieldBreak; + public Sound hitSound = Sounds.shieldHit; + public float hitSoundVolume = 0.12f; public Effect absorbEffect = Fx.absorb; public Effect shieldBreakEffect = Fx.shieldBreak; public @Load("@-top") TextureRegion topRegion; @@ -49,12 +53,16 @@ public class ForceProjector extends Block{ //TODO json support public @Nullable Consume itemConsumer, coolantConsumer; + //lambdas need to be static to prevent GC + protected static ForceProjector paramBlock; protected static ForceBuild paramEntity; - protected static Effect paramEffect; protected static final Cons shieldConsumer = bullet -> { - if(bullet.team != paramEntity.team && bullet.type.absorbable && !bullet.absorbed && Intersector.isInRegularPolygon(((ForceProjector)(paramEntity.block)).sides, paramEntity.x, paramEntity.y, paramEntity.realRadius(), ((ForceProjector)(paramEntity.block)).shieldRotation, bullet.x, bullet.y)){ + if(bullet.team != paramEntity.team && bullet.type.absorbable && !bullet.absorbed && + Intersector.isInRegularPolygon(paramBlock.sides, paramEntity.x, paramEntity.y, paramEntity.realRadius(), paramBlock.shieldRotation, bullet.x, bullet.y)){ + bullet.absorb(); - paramEffect.at(bullet); + paramBlock.hitSound.at(bullet.x, bullet.y, 1f + Mathf.range(0.1f), paramBlock.hitSoundVolume); + paramBlock.absorbEffect.at(bullet); paramEntity.hit = 1f; paramEntity.buildup += bullet.type.shieldDamage(bullet); } @@ -233,6 +241,7 @@ public class ForceProjector extends Block{ broken = true; buildup = shieldHealth; shieldBreakEffect.at(x, y, realRadius(), team.color); + breakSound.at(x, y); if(team != state.rules.defaultTeam){ Events.fire(Trigger.forceProjectorBreak); } @@ -249,8 +258,8 @@ public class ForceProjector extends Block{ float realRadius = realRadius(); if(realRadius > 0 && !broken){ + paramBlock = ForceProjector.this; paramEntity = this; - paramEffect = absorbEffect; Groups.bullet.intersect(x - realRadius, y - realRadius, realRadius * 2f, realRadius * 2f, shieldConsumer); } } diff --git a/core/src/mindustry/world/blocks/defense/ShockwaveTower.java b/core/src/mindustry/world/blocks/defense/ShockwaveTower.java index 2181bf7d7d..d7b30eaca5 100644 --- a/core/src/mindustry/world/blocks/defense/ShockwaveTower.java +++ b/core/src/mindustry/world/blocks/defense/ShockwaveTower.java @@ -29,7 +29,7 @@ public class ShockwaveTower extends Block{ public float shake = 2f; //checking for bullets every frame is costly, so only do it at intervals even when ready. public float checkInterval = 8f; - public Sound shootSound = Sounds.bang; + public Sound shootSound = Sounds.shockwaveTower; public Color waveColor = Pal.accent, heatColor = Pal.turretHeat, shapeColor = Color.valueOf("f29c83"); public float cooldownMultiplier = 1f; public Effect hitEffect = Fx.hitSquaresColor; @@ -62,7 +62,7 @@ public class ShockwaveTower extends Block{ Drawf.dashCircle(x * tilesize + offset, y * tilesize + offset, range, waveColor); } - + public class ShockwaveTowerBuild extends Building{ public float reloadCounter = Mathf.random(reload); public float heat = 0f; @@ -82,7 +82,7 @@ public class ShockwaveTower extends Block{ heat = 1f; reloadCounter = 0f; waveEffect.at(x, y, range, waveColor); - shootSound.at(this); + shootSound.at(x, y, 1f + Mathf.range(0.15f), 1f); Effect.shake(shake, shake, this); float waveDamage = Math.min(bulletDamage, bulletDamage * falloffCount / targets.size);