mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
fix: Prevent dispatching Run SFX if an entity is not moving
This adds the entity's velocity as an argument when mapping the movement state to an SFX event, and prevents the run SFX from being returned if the velocity is below a threshold. This will prevent hearing the run sfx when stuck in a corner, or running into a surface where the character is not actually moving their feet.
This commit is contained in:
parent
0c4434f015
commit
309834df1b
@ -4,7 +4,7 @@ use crate::audio::sfx::{SfxTriggerItem, SfxTriggers};
|
||||
|
||||
use client::Client;
|
||||
use common::{
|
||||
comp::{ActionState, Body, CharacterState, MovementState, Pos},
|
||||
comp::{ActionState, Body, CharacterState, MovementState, Pos, Vel},
|
||||
event::{EventBus, SfxEvent, SfxEventItem},
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
@ -38,9 +38,10 @@ impl MovementEventMapper {
|
||||
.get(client.entity())
|
||||
.map_or(Vec3::zero(), |pos| pos.0);
|
||||
|
||||
for (entity, pos, body, character) in (
|
||||
for (entity, pos, vel, body, character) in (
|
||||
&ecs.entities(),
|
||||
&ecs.read_storage::<Pos>(),
|
||||
&ecs.read_storage::<Vel>(),
|
||||
&ecs.read_storage::<Body>(),
|
||||
ecs.read_storage::<CharacterState>().maybe(),
|
||||
)
|
||||
@ -59,7 +60,9 @@ impl MovementEventMapper {
|
||||
});
|
||||
|
||||
let mapped_event = match body {
|
||||
Body::Humanoid(_) => Self::map_movement_event(character, state.event.clone()),
|
||||
Body::Humanoid(_) => {
|
||||
Self::map_movement_event(character, state.event.clone(), vel.0)
|
||||
}
|
||||
Body::QuadrupedMedium(_) => {
|
||||
// TODO: Quadriped running sfx
|
||||
SfxEvent::Idle
|
||||
@ -122,12 +125,25 @@ impl MovementEventMapper {
|
||||
/// however that list does not provide enough resolution to target specific entity events, such
|
||||
/// as opening or closing the glider. These methods translate those entity states with some additional
|
||||
/// data into more specific `SfxEvent`'s which we attach sounds to
|
||||
fn map_movement_event(current_event: &CharacterState, previous_event: SfxEvent) -> SfxEvent {
|
||||
fn map_movement_event(
|
||||
current_event: &CharacterState,
|
||||
previous_event: SfxEvent,
|
||||
vel: Vec3<f32>,
|
||||
) -> SfxEvent {
|
||||
match (current_event.movement, current_event.action, previous_event) {
|
||||
(_, ActionState::Roll { .. }, _) => SfxEvent::Roll,
|
||||
(MovementState::Climb, ..) => SfxEvent::Climb,
|
||||
(MovementState::Swim, ..) => SfxEvent::Swim,
|
||||
(MovementState::Run, ..) => SfxEvent::Run,
|
||||
(MovementState::Run, ..) => {
|
||||
// If the entitys's velocity is very low, they may be stuck, or walking into a solid object.
|
||||
// We should not trigger the run SFX in this case, even if their move state indicates running.
|
||||
// The 0.1 value is an approximation from playtesting scenarios where this can occur.
|
||||
if vel.magnitude() > 0.1 {
|
||||
SfxEvent::Run
|
||||
} else {
|
||||
SfxEvent::Idle
|
||||
}
|
||||
}
|
||||
(MovementState::Jump, ..) => SfxEvent::Jump,
|
||||
(MovementState::Fall, _, SfxEvent::Glide) => SfxEvent::GliderClose,
|
||||
(MovementState::Stand, _, SfxEvent::Fall) => SfxEvent::Run,
|
||||
@ -238,24 +254,40 @@ mod tests {
|
||||
action: ActionState::Idle,
|
||||
},
|
||||
SfxEvent::Idle,
|
||||
Vec3::zero(),
|
||||
);
|
||||
|
||||
assert_eq!(result, SfxEvent::Idle);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn maps_run() {
|
||||
fn maps_run_with_sufficient_velocity() {
|
||||
let result = MovementEventMapper::map_movement_event(
|
||||
&CharacterState {
|
||||
movement: MovementState::Run,
|
||||
action: ActionState::Idle,
|
||||
},
|
||||
SfxEvent::Idle,
|
||||
Vec3::new(0.5, 0.8, 0.0),
|
||||
);
|
||||
|
||||
assert_eq!(result, SfxEvent::Run);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn does_not_map_run_with_insufficient_velocity() {
|
||||
let result = MovementEventMapper::map_movement_event(
|
||||
&CharacterState {
|
||||
movement: MovementState::Run,
|
||||
action: ActionState::Idle,
|
||||
},
|
||||
SfxEvent::Idle,
|
||||
Vec3::new(0.02, 0.0001, 0.0),
|
||||
);
|
||||
|
||||
assert_eq!(result, SfxEvent::Idle);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn maps_roll() {
|
||||
let result = MovementEventMapper::map_movement_event(
|
||||
@ -267,6 +299,7 @@ mod tests {
|
||||
movement: MovementState::Run,
|
||||
},
|
||||
SfxEvent::Run,
|
||||
Vec3::zero(),
|
||||
);
|
||||
|
||||
assert_eq!(result, SfxEvent::Roll);
|
||||
@ -280,6 +313,7 @@ mod tests {
|
||||
action: ActionState::Idle,
|
||||
},
|
||||
SfxEvent::Fall,
|
||||
Vec3::zero(),
|
||||
);
|
||||
|
||||
assert_eq!(result, SfxEvent::Fall);
|
||||
@ -293,6 +327,7 @@ mod tests {
|
||||
action: ActionState::Idle,
|
||||
},
|
||||
SfxEvent::Fall,
|
||||
Vec3::zero(),
|
||||
);
|
||||
|
||||
assert_eq!(result, SfxEvent::Run);
|
||||
@ -306,6 +341,7 @@ mod tests {
|
||||
action: ActionState::Idle,
|
||||
},
|
||||
SfxEvent::Jump,
|
||||
Vec3::zero(),
|
||||
);
|
||||
|
||||
assert_eq!(result, SfxEvent::GliderOpen);
|
||||
@ -319,6 +355,7 @@ mod tests {
|
||||
action: ActionState::Idle,
|
||||
},
|
||||
SfxEvent::Glide,
|
||||
Vec3::zero(),
|
||||
);
|
||||
|
||||
assert_eq!(result, SfxEvent::Glide);
|
||||
@ -332,6 +369,7 @@ mod tests {
|
||||
action: ActionState::Idle,
|
||||
},
|
||||
SfxEvent::Glide,
|
||||
Vec3::zero(),
|
||||
);
|
||||
|
||||
assert_eq!(result, SfxEvent::GliderClose);
|
||||
@ -345,6 +383,7 @@ mod tests {
|
||||
action: ActionState::Idle,
|
||||
},
|
||||
SfxEvent::Glide,
|
||||
Vec3::zero(),
|
||||
);
|
||||
|
||||
assert_eq!(result, SfxEvent::GliderClose);
|
||||
|
Loading…
Reference in New Issue
Block a user