More sound effects + core destruction sound

This commit is contained in:
Anuken
2025-12-06 23:14:08 -05:00
parent 65c63c292e
commit e255912156
19 changed files with 130 additions and 8 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -63,8 +63,14 @@ public class SoundPriority{
shieldHit.setMaxConcurrent(4);
max(4, mechStep, mechStepHeavy, walkerStep, walkerStepSmall, walkerStepTiny, mechStepSmall);
//repair sounds are lower priority and generally not important
set(-1f, blockHeal, healAbility);
//step sounds are low priority
set(-1f, mechStep, mechStepHeavy, walkerStep, walkerStepSmall, walkerStepTiny, mechStepSmall);
set(-2f, mechStep, mechStepHeavy, walkerStep, walkerStepSmall, walkerStepTiny, mechStepSmall);
coreExplode.setFalloffOffset(100f);
}
static void max(int max, Sound... sounds){

View File

@@ -2622,7 +2622,7 @@ public class Blocks{
powerProduction = 130f;
itemDuration = 140f;
ambientSound = Sounds.pulse;
ambientSoundVolume = 0.07f;
ambientSoundVolume = 0.08f;
liquidCapacity = 80f;
consumePower(25f);
@@ -6298,6 +6298,7 @@ public class Blocks{
beamWidth = 0.73f;
powerUse = 1f;
pulseRadius = 5f;
ambientSoundVolume = 0.9f;
}};
repairTurret = new RepairTurret("repair-turret"){{
@@ -6312,6 +6313,7 @@ public class Blocks{
coolantUse = 0.16f;
coolantMultiplier = 1.6f;
acceptCoolant = true;
ambientSoundVolume = 1.25f;
}};
//endregion

View File

@@ -550,6 +550,36 @@ public class Fx{
}
}),
coreExplosion = new Effect(55f, 240f, e -> {
color(e.color);
stroke(e.fout() * 4f);
float circleRad = 6f + e.finpow() * 120f;
Lines.circle(e.x, e.y, circleRad);
stroke(e.fout() * 2.5f);
rand.setSeed(e.id);
for(int i = 0; i < 30; i++){
float angle = rand.random(360f);
float lenRand = rand.random(0.5f, 1f);
Lines.lineAngle(e.x, e.y, angle, e.foutpow() * 50f * rand.random(1f, 0.6f) + 2f, e.finpow() * 100f * lenRand + 6f);
}
stroke(e.fout() * 2f);
for(int i = 0; i < 30; i++){
float angle = rand.random(360f);
float lenRand = rand.random(0.5f, 1f);
float speed = rand.random(1f, 0.6f);
float fin = e.finpow() / rand.random(0.3f, 1f);
float fout = 1f - fin;
if(fin < 1f){
stroke(fout * 2f);
Lines.lineAngle(e.x, e.y, angle, Interp.pow3Out.apply(fin) * 80f * speed + 2f, fin * 100f * lenRand + 6f);
}
}
}),
smokeAoeCloud = new Effect(60f * 3f, 250f, e -> {
color(e.color, 0.65f);

View File

@@ -3307,7 +3307,7 @@ public class UnitTypes{
weapons.add(new Weapon("anthicus-weapon"){{
shootSound = Sounds.missileLarge;
shootSoundVolume = 0.65f;
shootSoundVolume = 0.5f;
x = 29f / 4f;
y = -11f / 4f;
shootY = 1.5f;

View File

@@ -262,6 +262,32 @@ public class Effect{
decal(region, x, y, Mathf.random(4) * 90, 3600, Pal.rubble);
}
public static void shockwaveDust(float x, float y, float rad){
shockwaveDust(x, y, rad, 1f);
}
public static void shockwaveDust(float x, float y, float rad, float density){
float spacing = 12f;
int waves = Math.max(1, Mathf.ceil(rad / spacing));
for(int i = 0; i < waves; i++){
int fi = i;
Time.run(i * 3.5f, () -> {
float radius = 1 + spacing * fi;
int rays = Mathf.ceil(radius * Mathf.PI * 2f / 6f * density);
for(int r = 0; r < rays; r++){
if(Mathf.chance(0.7f - fi * 0.02f)){
float angle = r * 360f / (float)rays;
float ox = Angles.trnsx(angle, radius), oy = Angles.trnsy(angle, radius);
Tile t = world.tileWorld(x + ox, y + oy);
if(t != null){
Fx.podLandDust.at(t.worldx(), t.worldy(), angle + Mathf.range(30f), Tmp.c1.set(t.floor().mapColor).mul(1.7f + Mathf.range(0.15f)));
}
}
}
});
}
}
public static class EffectContainer implements Scaled{
public float x, y, time, lifetime, rotation;
public Color color;

View File

@@ -1,6 +1,8 @@
package mindustry.entities.abilities;
import arc.*;
import arc.audio.*;
import arc.math.*;
import arc.scene.ui.layout.*;
import arc.util.*;
import mindustry.content.*;
@@ -13,6 +15,8 @@ public class RepairFieldAbility extends Ability{
public float amount = 1, reload = 100, range = 60, healPercent = 0f;
public Effect healEffect = Fx.heal;
public Effect activeEffect = Fx.healWaveDynamic;
public Sound sound = Sounds.healAbility;
public float soundVolume = 0.5f;
public boolean parentizeEffects = false;
/** Multiplies healing to units of the same type by this amount. */
public float sameTypeHealMult = 1f;
@@ -69,6 +73,7 @@ public class RepairFieldAbility extends Ability{
if(wasHealed){
activeEffect.at(unit, range);
sound.at(unit, 1f + Mathf.range(0.1f), soundVolume);
}
timer = 0f;

View File

@@ -161,6 +161,10 @@ public class BulletType extends Content implements Cloneable{
public float healPercent = 0f;
/** flat amount of block health healed */
public float healAmount = 0f;
/** sound played when a block is healed */
public Sound healSound = Sounds.blockHeal;
/** volume of heal sound */
public float healSoundVolume = 0.9f;
/** Fraction of bullet damage that heals that shooter. */
public float lifesteal = 0f;
/** Whether to make fire on impact */
@@ -442,6 +446,7 @@ public class BulletType extends Content implements Cloneable{
if(heals() && build.team == b.team && !(build.block instanceof ConstructBlock)){
healEffect.at(build.x, build.y, 0f, healColor, build.block);
build.heal(healPercent / 100f * build.maxHealth + healAmount);
healSound.at(build, 1f + Mathf.range(0.1f), healSoundVolume);
hit(b);
}else if(build.team != b.team && direct){

View File

@@ -2178,7 +2178,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
public void killed(){
dead = true;
Events.fire(new BlockDestroyEvent(tile));
block.destroySound.at(tile, Mathf.random(block.destroyPitchMin, block.destroyPitchMax));
if(!headless) playDestroySound();
onDestroyed();
if(tile != emptyTile){
tile.remove();
@@ -2187,6 +2187,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
afterDestroyed();
}
public void playDestroySound(){
block.destroySound.at(tile, Mathf.random(block.destroyPitchMin, block.destroyPitchMax), block.destroySoundVolume);
}
public void checkAllowUpdate(){
if(!allowUpdate()){
enabled = false;

View File

@@ -10,6 +10,7 @@ import arc.math.geom.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
import mindustry.*;
import mindustry.ai.types.*;
import mindustry.annotations.Annotations.*;
import mindustry.audio.*;
@@ -126,6 +127,10 @@ public class Weapon implements Cloneable{
public int otherSide = -1;
/** draw Z offset relative to the default value */
public float layerOffset = 0f;
/** sound looped when shooting */
public Sound activeSound = Sounds.none;
/** volume of active sound */
public float activeSoundVolume = 1f;
/** sound used for shooting */
public Sound shootSound = Sounds.pew;
/** volume of the shoot sound */
@@ -419,6 +424,10 @@ public class Weapon implements Cloneable{
mount.side = !mount.side;
}
if(!headless && activeSound != Sounds.none && mount.shoot && can && mount.warmup >= minWarmup){
Vars.control.sound.loop(activeSound, unit, activeSoundVolume);
}
//shoot if applicable
if(mount.shoot && //must be shooting
can && //must be able to shoot

View File

@@ -61,6 +61,7 @@ public class RepairBeamWeapon extends Weapon{
recoil = 0f;
noAttack = true;
useAttackRange = false;
activeSound = Sounds.healBeam;
}
@Override

View File

@@ -314,6 +314,8 @@ public class Block extends UnlockableContent implements Senseable{
public Sound breakSound = Sounds.breaks;
/** Sounds made when this block is destroyed.*/
public Sound destroySound = Sounds.boom;
/** Volume of destruction sound. */
public float destroySoundVolume = 1f;
/** Range of destroy sound. */
public float destroyPitchMin = 1f, destroyPitchMax = 1f;
/** How reflective this block is. */

View File

@@ -354,7 +354,7 @@ public class Accelerator extends Block{
float spacing = 12f;
for(int i = 0; i < 13; i++){
int fi = i;
Time.run(i * 1.1f, () -> {
Time.run(i * 2f, () -> {
float radius = block.size/2f + 1 + spacing * fi;
int rays = Mathf.ceil(radius * Mathf.PI * 2f / 6f);
for(int r = 0; r < rays; r++){
@@ -369,8 +369,6 @@ public class Accelerator extends Block{
}
});
}
});
}

View File

@@ -1,5 +1,6 @@
package mindustry.world.blocks.defense;
import arc.audio.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
@@ -28,6 +29,10 @@ public class MendProjector extends Block{
public float phaseBoost = 12f;
public float phaseRangeBoost = 50f;
public float useTime = 400f;
public Sound mendSound = Sounds.healAbility;
public float mendSoundVolume = 0.5f;
private boolean any = false;
public MendProjector(String name){
super(name);
@@ -69,7 +74,7 @@ public class MendProjector extends Block{
@Override
public void drawPlace(int x, int y, int rotation, boolean valid){
super.drawPlace(x, y, rotation, valid);
Drawf.dashCircle(x * tilesize + offset, y * tilesize + offset, range, baseColor);
indexer.eachBlock(player.team(), x * tilesize + offset, y * tilesize + offset, range, other -> true, other -> Drawf.selected(other, Tmp.c1.set(baseColor).a(Mathf.absin(4f, 1f))));
@@ -101,11 +106,18 @@ public class MendProjector extends Block{
float realRange = range + phaseHeat * phaseRangeBoost;
charge = 0f;
any = false;
indexer.eachBlock(this, realRange, b -> b.damaged() && !b.isHealSuppressed(), other -> {
other.heal(other.maxHealth() * (healPercent + phaseHeat * phaseBoost) / 100f * efficiency);
other.recentlyHealed();
Fx.healBlockFull.at(other.x, other.y, other.block.size, baseColor, other.block);
any = true;
});
if(any){
mendSound.at(this, 1f + Mathf.range(0.1f), mendSoundVolume);
}
}
}

View File

@@ -82,6 +82,8 @@ public class CoreBlock extends StorageBlock{
//support everything
replaceable = false;
destroySound = Sounds.coreExplode;
destroySoundVolume = 1.6f;
}
@Remote(called = Loc.server)
@@ -621,6 +623,9 @@ public class CoreBlock extends StorageBlock{
super.onDestroyed();
}
Effect.shockwaveDust(x, y, 40f + block.size * tilesize, 0.5f);
Fx.coreExplosion.at(x, y, team.color);
//add a spawn to the map for future reference - waves should be disabled, so it shouldn't matter
if(state.isCampaign() && team == state.rules.waveTeam && team.cores().size <= 1 && spawner.getSpawns().size == 0 && state.rules.sector.planet.enemyCoreSpawnReplace){
//do not recache
@@ -634,6 +639,16 @@ public class CoreBlock extends StorageBlock{
Events.fire(new CoreChangeEvent(this));
}
@Override
public void playDestroySound(){
if(team.data().cores.size <= 1 && player != null && player.team() == team && state.rules.canGameOver){
//play at full volume when doing a game over
block.destroySound.play(block.destroySoundVolume, Mathf.random(block.destroyPitchMin, block.destroyPitchMax), 0f);
}else{
super.playDestroySound();
}
}
@Override
public void afterDestroyed(){
super.afterDestroyed();

View File

@@ -63,6 +63,8 @@ public class RepairTurret extends Block{
group = BlockGroup.projectors;
envEnabled |= Env.space;
ambientSound = Sounds.healBeam;
ambientSoundVolume = 1f;
}
@Override
@@ -176,6 +178,11 @@ public class RepairTurret extends Block{
Drawf.dashCircle(x, y, repairRadius, Pal.accent);
}
@Override
public boolean shouldAmbientSound(){
return target != null && efficiency > 0f;
}
@Override
public void updateTile(){
float multiplier = 1f;