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;
}
public float getWingFlapSoundPitch() {
return this == INSECTOID ? 0.66F : 1;
}
/**
* Predicate for abilities to control whether a player can fly.
*

View file

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

View file

@ -1,55 +1,57 @@
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.util.math.MathHelper;
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!
// 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 VOLUME_AT_MAX = 1;
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 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_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 float currentVal; // Cache last tick's curve value
public MotionBasedSoundInstance(SoundEvent sound, PlayerEntity player, Random random) {
super(sound, player.getSoundCategory(), 0.1F, random);
this.player = player;
private final float minVolume;
private final float maxVolume;
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
protected boolean shouldKeepPlaying() {
++tickCount;
if (player.isRemoved()) {
return false;
}
Pony pony = Pony.of(player);
if (!pony.getPhysics().isFlying() || !pony.getPhysics().getFlightType().isAvian()) {
if (entity.isRemoved() || !playingCondition.test(entity)) {
return false;
}
// Update effect position
x = (float)player.getX();
y = (float)player.getY();
z = (float)player.getZ();
x = (float)entity.getX();
y = (float)entity.getY();
z = (float)entity.getZ();
// Get velocity
float f = (float)player.getVelocity().horizontalLength();
float f = (float)entity.getVelocity().horizontalLength();
float lastVal = currentVal;
@ -62,7 +64,7 @@ public class MotionBasedSoundInstance extends FadeOutSoundInstance {
if (f >= 1.0E-7D) {
// Multiply output volume by reference volume for overall gain control.
volume = currentVal * VOLUME_AT_MAX;
volume = MathHelper.lerp(currentVal, minVolume, maxVolume);
} else {
volume = 0.0F;
}
@ -73,7 +75,7 @@ public class MotionBasedSoundInstance extends FadeOutSoundInstance {
}
// 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,
// 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;
ticksToGlide = MAX_TICKS_TO_GLIDE;
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());
}
} else {
@ -362,31 +364,35 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
entity.playSound(USounds.ENTITY_PLAYER_PEGASUS_MOLT, 0.3F, 1);
UCriteria.SHED_FEATHER.trigger(entity);
}
} else {
applyThrust(velocity);
}
moveFlying(velocity);
if (type.isAvian()) {
if (entity.getWorld().isClient && ticksInAir % IDLE_FLAP_INTERVAL == 0 && entity.getVelocity().length() < 0.29) {
flapping = true;
ticksToGlide = MAX_TICKS_TO_GLIDE;
}
if (entity.getWorld().isClient && ticksInAir % IDLE_FLAP_INTERVAL == 0 && entity.getVelocity().length() < 0.29) {
flapping = true;
ticksToGlide = MAX_TICKS_TO_GLIDE;
}
if (!SpellPredicate.IS_DISGUISE.isOn(pony)) {
if (ticksInAir % GLIDING_SOUND_INTERVAL == 1 && pony.isClient()) {
if (type.isAvian()) {
if (!SpellPredicate.IS_DISGUISE.isOn(pony) && pony.isClient()) {
if (ticksInAir % GLIDING_SOUND_INTERVAL == 5) {
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)) {
if (entity.getWorld().isClient && !soundPlaying) {
soundPlaying = true;
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) {
@ -517,12 +523,12 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
wallHitCooldown = MAX_WALL_HIT_CALLDOWN;
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));
velocity.fromImmutable(entity.getVelocity());
distance /= bouncyness;
} 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);
}
@ -572,7 +578,9 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
if (thrustScale <= 0.000001F & flapping) {
flapping = false;
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());
}
thrustScale = 1;
@ -601,7 +609,6 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
if (velocity.y < 0 && hovering) {
velocity.y *= 0.01;
}
}
private void applyTurbulance(MutableVector velocity) {