Improved the changeling flying sounds

This commit is contained in:
Sollace 2023-08-06 19:53:06 +01:00
parent db69d649a5
commit ada4afd645
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
4 changed files with 71 additions and 52 deletions

View file

@ -38,6 +38,10 @@ public enum FlightType {
return this == INSECTOID ? USounds.ENTITY_PLAYER_CHANGELING_BUZZ : USounds.ENTITY_PLAYER_PEGASUS_WINGSFLAP; return this == INSECTOID ? USounds.ENTITY_PLAYER_CHANGELING_BUZZ : USounds.ENTITY_PLAYER_PEGASUS_WINGSFLAP;
} }
public float getWingFlapSoundPitch() {
return this == INSECTOID ? 0.66F : 1;
}
/** /**
* Predicate for abilities to control whether a player can fly. * Predicate for abilities to control whether a player can fly.
* *

View file

@ -64,28 +64,34 @@ public class ClientInteractionManager extends InteractionManager {
client.execute(() -> { client.execute(() -> {
SoundManager soundManager = client.getSoundManager(); SoundManager soundManager = client.getSoundManager();
if (type == SOUND_EARS_RINGING && source instanceof LivingEntity) { if (type == SOUND_EARS_RINGING && source instanceof LivingEntity living) {
soundManager.play(new LoopingSoundInstance<>((LivingEntity)source, soundManager.play(new LoopingSoundInstance<>(living,
createTicker(100).and(e -> !e.isRemoved()), createTicker(100).and(e -> !e.isRemoved()),
USounds.ENTITY_PLAYER_EARS_RINGING, 0.01F, 2, Random.create(seed)).setFadeIn() USounds.ENTITY_PLAYER_EARS_RINGING, 0.01F, 2, Random.create(seed)).setFadeIn()
); );
} else if (type == SOUND_BEE && source instanceof BeeEntity) { } else if (type == SOUND_BEE && source instanceof BeeEntity bee) {
soundManager.playNextTick( soundManager.playNextTick(
((BeeEntity)source).hasAngerTime() bee.hasAngerTime()
? new AggressiveBeeSoundInstance(((BeeEntity)source)) ? new AggressiveBeeSoundInstance(bee)
: new PassiveBeeSoundInstance(((BeeEntity)source)) : new PassiveBeeSoundInstance(bee)
); );
} else if (type == SOUND_MINECART && source instanceof AbstractMinecartEntity) { } else if (type == SOUND_MINECART && source instanceof AbstractMinecartEntity minecart) {
soundManager.play(new MovingMinecartSoundInstance((AbstractMinecartEntity)source)); soundManager.play(new MovingMinecartSoundInstance(minecart));
} else if (type == SOUND_CHANGELING_BUZZ && source instanceof PlayerEntity) { } else if (type == SOUND_CHANGELING_BUZZ && source instanceof PlayerEntity player) {
soundManager.play(new LoopingSoundInstance<>((PlayerEntity)source, e -> { soundManager.play(new MotionBasedSoundInstance<>(USounds.ENTITY_PLAYER_CHANGELING_BUZZ, player, e -> {
PlayerPhysics physics = Pony.of(e).getPhysics(); PlayerPhysics physics = Pony.of(e).getPhysics();
return physics.isFlying() && physics.getFlightType() == FlightType.INSECTOID; return physics.isFlying() && physics.getFlightType() == FlightType.INSECTOID;
}, USounds.ENTITY_PLAYER_CHANGELING_BUZZ, 1F, 1F, Random.create(seed))); }, 0.25F, 0.5F, 0.66F, Random.create(seed)));
} else if (type == SOUND_GLIDING && source instanceof PlayerEntity && isClientPlayer((PlayerEntity) source)) { } else if (type == SOUND_GLIDING && source instanceof PlayerEntity player && isClientPlayer(player)) {
soundManager.play(new MotionBasedSoundInstance(SoundEvents.ITEM_ELYTRA_FLYING, (PlayerEntity)source, Random.create(seed))); soundManager.play(new MotionBasedSoundInstance<>(SoundEvents.ITEM_ELYTRA_FLYING, player, e -> {
} else if (type == SOUND_GLIDING && source instanceof PlayerEntity) { Pony pony = Pony.of(e);
soundManager.play(new MotionBasedSoundInstance(USounds.ENTITY_PLAYER_PEGASUS_FLYING, (PlayerEntity)source, Random.create(seed))); return pony.getPhysics().isFlying() && pony.getPhysics().getFlightType().isAvian();
}, 0, 1, 1, Random.create(seed)));
} else if (type == SOUND_GLIDING && source instanceof PlayerEntity player) {
soundManager.play(new MotionBasedSoundInstance<>(USounds.ENTITY_PLAYER_PEGASUS_FLYING, player, e -> {
Pony pony = Pony.of(e);
return pony.getPhysics().isFlying() && pony.getPhysics().getFlightType().isAvian();
}, 0, 1, 1, Random.create(seed)));
} else if (type == SOUND_MAGIC_BEAM) { } else if (type == SOUND_MAGIC_BEAM) {
soundManager.play(new LoopedEntityTrackingSoundInstance(USounds.SPELL_CAST_SHOOT, 0.3F, 1F, source, seed)); soundManager.play(new LoopedEntityTrackingSoundInstance(USounds.SPELL_CAST_SHOOT, 0.3F, 1F, source, seed));
} else if (type == SOUND_HEART_BEAT) { } else if (type == SOUND_HEART_BEAT) {

View file

@ -1,55 +1,57 @@
package com.minelittlepony.unicopia.client.sound; package com.minelittlepony.unicopia.client.sound;
import com.minelittlepony.unicopia.entity.player.Pony; import java.util.function.Predicate;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.Entity;
import net.minecraft.sound.SoundEvent; import net.minecraft.sound.SoundEvent;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.random.Random; import net.minecraft.util.math.random.Random;
public class MotionBasedSoundInstance extends FadeOutSoundInstance { public class MotionBasedSoundInstance<E extends Entity> extends FadeOutSoundInstance {
// Tune these if you want to change the way this sounds! // Tune these if you want to change the way this sounds!
// Currently just hardcoded for flying because nothing else uses this class // Currently just hardcoded for flying because nothing else uses this class
private static final float MAX_VELOCITY = 1.5F; // Max velocity before we clamp volume (units/tick?) private static final float MAX_VELOCITY = 1.5F; // Max velocity before we clamp volume (units/tick?)
private static final float VOLUME_AT_MAX = 1;
private static final float ATTEN_EXPO = 2; // Exponent for velocity based attenuation private static final float ATTEN_EXPO = 2; // Exponent for velocity based attenuation
private static final int FADEIN_TICKS = 20; // Ticks for fade-in private static final int FADEIN_TICKS = 20; // Ticks for fade-in
private static final float MIN_PITCH = 0.7F; // Pitch at 0-speed private static final float MIN_PITCH = 0.7F; // Pitch at 0-speed
private static final float MAX_PITCH = 2.6F; // Pitch at reference speed MAX_VELOCITY private static final float MAX_PITCH = 2.6F; // Pitch at reference speed MAX_VELOCITY
private static final float MAX_RATE_TICKS = 20; // How many ticks it takes to go from 0 to max volume (filter!) private static final float MAX_RATE_TICKS = 20; // How many ticks it takes to go from 0 to max volume (filter!)
private final PlayerEntity player; private final E entity;
private int tickCount; private int tickCount;
private float currentVal; // Cache last tick's curve value private float currentVal; // Cache last tick's curve value
public MotionBasedSoundInstance(SoundEvent sound, PlayerEntity player, Random random) { private final float minVolume;
super(sound, player.getSoundCategory(), 0.1F, random); private final float maxVolume;
this.player = player; private final float referencePitch;
private final Predicate<E> playingCondition;
public MotionBasedSoundInstance(SoundEvent sound, E entity, Predicate<E> playingCondition, float minVolume, float maxVolume, float pitch, Random random) {
super(sound, entity.getSoundCategory(), 0.1F, random);
this.entity = entity;
this.pitch = pitch;
this.referencePitch = pitch;
this.minVolume = minVolume;
this.maxVolume = maxVolume;
this.playingCondition = playingCondition;
} }
@Override @Override
protected boolean shouldKeepPlaying() { protected boolean shouldKeepPlaying() {
++tickCount; ++tickCount;
if (player.isRemoved()) { if (entity.isRemoved() || !playingCondition.test(entity)) {
return false;
}
Pony pony = Pony.of(player);
if (!pony.getPhysics().isFlying() || !pony.getPhysics().getFlightType().isAvian()) {
return false; return false;
} }
// Update effect position // Update effect position
x = (float)player.getX(); x = (float)entity.getX();
y = (float)player.getY(); y = (float)entity.getY();
z = (float)player.getZ(); z = (float)entity.getZ();
// Get velocity // Get velocity
float f = (float)player.getVelocity().horizontalLength(); float f = (float)entity.getVelocity().horizontalLength();
float lastVal = currentVal; float lastVal = currentVal;
@ -62,7 +64,7 @@ public class MotionBasedSoundInstance extends FadeOutSoundInstance {
if (f >= 1.0E-7D) { if (f >= 1.0E-7D) {
// Multiply output volume by reference volume for overall gain control. // Multiply output volume by reference volume for overall gain control.
volume = currentVal * VOLUME_AT_MAX; volume = MathHelper.lerp(currentVal, minVolume, maxVolume);
} else { } else {
volume = 0.0F; volume = 0.0F;
} }
@ -73,7 +75,7 @@ public class MotionBasedSoundInstance extends FadeOutSoundInstance {
} }
// Control pitch with velocity // Control pitch with velocity
pitch = MathHelper.lerp(currentVal,MIN_PITCH,MAX_PITCH); pitch = MathHelper.lerp(currentVal, MIN_PITCH, MAX_PITCH) * referencePitch;
// Setting target volume every frame breaks interpolation. We set volume directly, // Setting target volume every frame breaks interpolation. We set volume directly,
// so that FadeOutSoundInstance only handles stopping the sound with an actual fade out! // so that FadeOutSoundInstance only handles stopping the sound with an actual fade out!

View file

@ -293,7 +293,9 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
strafe = 1; strafe = 1;
ticksToGlide = MAX_TICKS_TO_GLIDE; ticksToGlide = MAX_TICKS_TO_GLIDE;
if (!SpellPredicate.IS_DISGUISE.isOn(pony)) { if (!SpellPredicate.IS_DISGUISE.isOn(pony)) {
entity.playSound(type.getWingFlapSound(), 0.25F, 1); if (type != FlightType.INSECTOID) {
entity.playSound(type.getWingFlapSound(), 0.25F, entity.getSoundPitch() * type.getWingFlapSoundPitch());
}
entity.getWorld().emitGameEvent(entity, GameEvent.ELYTRA_GLIDE, entity.getPos()); entity.getWorld().emitGameEvent(entity, GameEvent.ELYTRA_GLIDE, entity.getPos());
} }
} else { } else {
@ -362,31 +364,35 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
entity.playSound(USounds.ENTITY_PLAYER_PEGASUS_MOLT, 0.3F, 1); entity.playSound(USounds.ENTITY_PLAYER_PEGASUS_MOLT, 0.3F, 1);
UCriteria.SHED_FEATHER.trigger(entity); UCriteria.SHED_FEATHER.trigger(entity);
} }
} else {
applyThrust(velocity);
} }
moveFlying(velocity); moveFlying(velocity);
if (type.isAvian()) { if (entity.getWorld().isClient && ticksInAir % IDLE_FLAP_INTERVAL == 0 && entity.getVelocity().length() < 0.29) {
if (entity.getWorld().isClient && ticksInAir % IDLE_FLAP_INTERVAL == 0 && entity.getVelocity().length() < 0.29) { flapping = true;
flapping = true; ticksToGlide = MAX_TICKS_TO_GLIDE;
ticksToGlide = MAX_TICKS_TO_GLIDE; }
}
if (!SpellPredicate.IS_DISGUISE.isOn(pony)) { if (type.isAvian()) {
if (ticksInAir % GLIDING_SOUND_INTERVAL == 1 && pony.isClient()) { if (!SpellPredicate.IS_DISGUISE.isOn(pony) && pony.isClient()) {
if (ticksInAir % GLIDING_SOUND_INTERVAL == 5) {
InteractionManager.instance().playLoopingSound(entity, InteractionManager.SOUND_GLIDING, entity.getId()); InteractionManager.instance().playLoopingSound(entity, InteractionManager.SOUND_GLIDING, entity.getId());
} }
} }
velocity.y -= 0.02 * getGravitySignum();
velocity.x *= 0.9896;
velocity.z *= 0.9896;
} else if (type == FlightType.INSECTOID && !SpellPredicate.IS_DISGUISE.isOn(pony)) { } else if (type == FlightType.INSECTOID && !SpellPredicate.IS_DISGUISE.isOn(pony)) {
if (entity.getWorld().isClient && !soundPlaying) { if (entity.getWorld().isClient && !soundPlaying) {
soundPlaying = true; soundPlaying = true;
InteractionManager.instance().playLoopingSound(entity, InteractionManager.SOUND_CHANGELING_BUZZ, entity.getId()); InteractionManager.instance().playLoopingSound(entity, InteractionManager.SOUND_CHANGELING_BUZZ, entity.getId());
} }
} }
velocity.y -= 0.02 * getGravitySignum();
velocity.x *= 0.9896;
velocity.z *= 0.9896;
} }
private void tickArtificialFlight(MutableVector velocity) { private void tickArtificialFlight(MutableVector velocity) {
@ -517,12 +523,12 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
wallHitCooldown = MAX_WALL_HIT_CALLDOWN; wallHitCooldown = MAX_WALL_HIT_CALLDOWN;
if (bouncyness > 0) { if (bouncyness > 0) {
entity.playSound(USounds.ENTITY_PLAYER_REBOUND, 1, 1); entity.playSound(USounds.ENTITY_PLAYER_REBOUND, 1, entity.getSoundPitch());
ProjectileUtil.ricochet(entity, Vec3d.of(pos), 0.4F + Math.min(2, bouncyness / 18F)); ProjectileUtil.ricochet(entity, Vec3d.of(pos), 0.4F + Math.min(2, bouncyness / 18F));
velocity.fromImmutable(entity.getVelocity()); velocity.fromImmutable(entity.getVelocity());
distance /= bouncyness; distance /= bouncyness;
} else { } else {
entity.playSound(distance > 4 ? SoundEvents.ENTITY_PLAYER_BIG_FALL : SoundEvents.ENTITY_PLAYER_SMALL_FALL, 1, 1); entity.playSound(distance > 4 ? SoundEvents.ENTITY_PLAYER_BIG_FALL : SoundEvents.ENTITY_PLAYER_SMALL_FALL, 1, entity.getSoundPitch());
} }
entity.damage(entity.getDamageSources().flyIntoWall(), distance); entity.damage(entity.getDamageSources().flyIntoWall(), distance);
} }
@ -572,7 +578,9 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
if (thrustScale <= 0.000001F & flapping) { if (thrustScale <= 0.000001F & flapping) {
flapping = false; flapping = false;
if (!SpellPredicate.IS_DISGUISE.isOn(pony)) { if (!SpellPredicate.IS_DISGUISE.isOn(pony)) {
entity.playSound(getFlightType().getWingFlapSound(), 0.5F, 1); if (getFlightType() != FlightType.INSECTOID) {
entity.playSound(getFlightType().getWingFlapSound(), 0.25F, entity.getSoundPitch() * getFlightType().getWingFlapSoundPitch());
}
entity.getWorld().emitGameEvent(entity, GameEvent.ELYTRA_GLIDE, entity.getPos()); entity.getWorld().emitGameEvent(entity, GameEvent.ELYTRA_GLIDE, entity.getPos());
} }
thrustScale = 1; thrustScale = 1;
@ -601,7 +609,6 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
if (velocity.y < 0 && hovering) { if (velocity.y < 0 && hovering) {
velocity.y *= 0.01; velocity.y *= 0.01;
} }
} }
private void applyTurbulance(MutableVector velocity) { private void applyTurbulance(MutableVector velocity) {