Merge branch 'DaforLynx/initial-hurt-sfx' into 'master'

Added npc hurt sfx

See merge request veloren/veloren!2467
This commit is contained in:
Imbris
2021-06-17 05:49:09 +00:00
27 changed files with 164 additions and 44 deletions

View File

@ -831,56 +831,126 @@
], ],
threshold: 0.2, threshold: 0.2,
), ),
Utterance(Angry, Wendigo): (
files: [
"voxygen.audio.sfx.utterance.wendigo_angry",
],
threshold: 0.2,
),
Utterance(Angry, BipedLarge): ( Utterance(Angry, BipedLarge): (
files: [ files: [
"voxygen.audio.sfx.utterance.ogre_angry", "voxygen.audio.sfx.utterance.ogre_angry1",
"voxygen.audio.sfx.utterance.ogre_angry2", "voxygen.audio.sfx.utterance.ogre_angry2",
], ],
threshold: 0.2, threshold: 1.0,
),
Utterance(Angry, Reptile): (
files: [
"voxygen.audio.sfx.utterance.saurok_angry",
],
threshold: 0.2,
), ),
Utterance(Angry, Bird): ( Utterance(Angry, Bird): (
files: [ files: [
"voxygen.audio.sfx.utterance.bird_angry", "voxygen.audio.sfx.utterance.bird_angry1",
], ],
threshold: 0.2, threshold: 1.0,
), ),
Utterance(Calm, Pig): ( Utterance(Calm, Pig): (
files: [ files: [
"voxygen.audio.sfx.utterance.pig_calm", "voxygen.audio.sfx.utterance.pig_calm1",
], ],
threshold: 0.2, threshold: 1.0,
),
Utterance(Angry, Adlet): (
files: [
"voxygen.audio.sfx.utterance.adlet_angry1",
"voxygen.audio.sfx.utterance.adlet_angry2",
],
threshold: 1.0,
),
Utterance(Angry, Alligator): (
files: [
"voxygen.audio.sfx.utterance.alligator_angry1",
"voxygen.audio.sfx.utterance.alligator_angry2",
],
threshold: 1.0,
),
Utterance(Angry, Antelope): (
files: [
"voxygen.audio.sfx.utterance.antelope_angry1",
],
threshold: 1.0,
),
Utterance(Angry, Reptile): (
files: [
"voxygen.audio.sfx.utterance.alligator_angry1",
"voxygen.audio.sfx.utterance.alligator_angry2",
],
threshold: 1.0,
),
Utterance(Angry, Saurok): (
files: [
"voxygen.audio.sfx.utterance.saurok_angry1",
],
threshold: 1.0,
),
Utterance(Angry, Wendigo): (
files: [
"voxygen.audio.sfx.utterance.wendigo_angry1",
],
threshold: 1.0,
), ),
Utterance(Calm, Cow): ( Utterance(Calm, Cow): (
files: [ files: [
"voxygen.audio.sfx.utterance.cow_calm", "voxygen.audio.sfx.utterance.cow_calm1",
"voxygen.audio.sfx.utterance.cow_calm2", "voxygen.audio.sfx.utterance.cow_calm2",
"voxygen.audio.sfx.utterance.cow_calm3", "voxygen.audio.sfx.utterance.cow_calm3",
], ],
threshold: 0.2, threshold: 1.0,
), ),
Utterance(Calm, Sheep): ( Utterance(Calm, Sheep): (
files: [ files: [
"voxygen.audio.sfx.utterance.sheep_calm", "voxygen.audio.sfx.utterance.sheep_calm1",
], ],
threshold: 0.2, threshold: 1.0,
), ),
Utterance(Greeting, HumanMale): ( Utterance(Greeting, HumanMale): (
files: [ files: [
"voxygen.audio.sfx.utterance.humanmale_greeting", "voxygen.audio.sfx.utterance.humanmale_greeting1",
], ],
threshold: 0.2, threshold: 1.0,
),
Utterance(Hurt, Adlet): (
files: [
"voxygen.audio.sfx.utterance.adlet_hurt1",
"voxygen.audio.sfx.utterance.adlet_hurt2",
],
threshold: 1.0,
),
Utterance(Hurt, Antelope): (
files: [
"voxygen.audio.sfx.utterance.antelope",
],
threshold: 1.0,
),
Utterance(Hurt, HumanMale): (
files: [
"voxygen.audio.sfx.utterance.humanmale_hurt1",
],
threshold: 1.0,
),
Utterance(Hurt, Lion): (
files: [
"voxygen.audio.sfx.utterance.lion_hurt1",
],
threshold: 1.0,
),
Utterance(Hurt, Marlin): (
files: [
"voxygen.audio.sfx.utterance.marlin_hurt1",
],
threshold: 1.0,
),
Utterance(Hurt, Maneater): (
files: [
"voxygen.audio.sfx.utterance.maneater_hurt1",
],
threshold: 1.0,
),
Utterance(Hurt, Mindflayer): (
files: [
"voxygen.audio.sfx.utterance.mindflayer_hurt1",
],
threshold: 1.0,
), ),
} }
) )

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -261,6 +261,7 @@ pub enum AgentEvent {
)>, )>,
), ),
ServerSound(Sound), ServerSound(Sound),
Hurt,
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]

View File

@ -1,7 +1,7 @@
use crate::{ use crate::{
client::Client, client::Client,
comp::{ comp::{
agent::{Sound, SoundKind}, agent::{Agent, AgentEvent, Sound, SoundKind},
biped_large, bird_large, quadruped_low, quadruped_medium, quadruped_small, biped_large, bird_large, quadruped_low, quadruped_medium, quadruped_small,
skills::SkillGroupKind, skills::SkillGroupKind,
theropod, PhysicsState, theropod, PhysicsState,
@ -60,6 +60,13 @@ pub fn handle_damage(server: &Server, entity: EcsEntity, change: HealthChange) {
if let Some(mut health) = ecs.write_storage::<Health>().get_mut(entity) { if let Some(mut health) = ecs.write_storage::<Health>().get_mut(entity) {
health.change_by(change); health.change_by(change);
} }
// This if statement filters out anything under 5 damage, for DOT ticks
// TODO: Find a better way to separate direct damage from DOT here
if change.amount < -50 {
if let Some(agent) = ecs.write_storage::<Agent>().get_mut(entity) {
agent.inbox.push_front(AgentEvent::Hurt);
}
}
} }
pub fn handle_knockback(server: &Server, entity: EcsEntity, impulse: Vec3<f32>) { pub fn handle_knockback(server: &Server, entity: EcsEntity, impulse: Vec3<f32>) {

View File

@ -633,11 +633,27 @@ impl<'a> AgentData<'a> {
} }
// Interact if incoming messages // Interact if incoming messages
if !agent.inbox.is_empty() { if !agent.inbox.is_empty() {
if !matches!(agent.inbox.front(), Some(AgentEvent::ServerSound(_))) { if matches!(
agent.action_state.timer = 0.1; agent.inbox.front(),
} else if let Some(AgentEvent::ServerSound(sound)) = agent.inbox.pop_front() { Some(AgentEvent::ServerSound(_)) | Some(AgentEvent::Hurt)
) {
let sound = agent.inbox.pop_front();
match sound {
Some(AgentEvent::ServerSound(sound)) => {
agent.sounds_heard.push(sound); agent.sounds_heard.push(sound);
agent.awareness += sound.vol; agent.awareness += sound.vol;
},
Some(AgentEvent::Hurt) => {
// Hurt utterances at random upon receiving damage
if thread_rng().gen::<f32>() < 0.4 {
controller.push_event(ControlEvent::Utterance(UtteranceKind::Hurt));
}
},
//Note: this should be unreachable
Some(_) | None => return,
}
} else {
agent.action_state.timer = 0.1;
} }
} }
if agent.action_state.timer > 0.0 { if agent.action_state.timer > 0.0 {
@ -676,6 +692,13 @@ impl<'a> AgentData<'a> {
return; return;
} }
if let Some(AgentEvent::Hurt) = agent.inbox.pop_front() {
// Hurt utterances at random upon receiving damage
if thread_rng().gen::<f32>() < 0.4 {
controller.push_event(ControlEvent::Utterance(UtteranceKind::Hurt));
}
}
if let Some(Target { if let Some(Target {
target, target,
selected_at, selected_at,

View File

@ -316,7 +316,7 @@ impl MusicMgr {
// Adds a bit of randomness between plays // Adds a bit of randomness between plays
let silence_between_tracks_seconds: f32 = let silence_between_tracks_seconds: f32 =
if matches!(music_state, MusicState::Activity(MusicActivity::Explore)) { if matches!(music_state, MusicState::Activity(MusicActivity::Explore)) {
rng.gen_range(60.0..120.0) rng.gen_range(90.0..180.0)
} else { } else {
0.0 0.0
}; };

View File

@ -91,12 +91,12 @@ use client::Client;
use common::{ use common::{
assets::{self, AssetExt, AssetHandle}, assets::{self, AssetExt, AssetHandle},
comp::{ comp::{
beam, biped_large, humanoid, beam, biped_large, biped_small, humanoid,
item::{ItemKind, ToolKind}, item::{ItemKind, ToolKind},
object, object,
poise::PoiseState, poise::PoiseState,
quadruped_medium, quadruped_small, Body, CharacterAbilityType, InventoryUpdateEvent, quadruped_low, quadruped_medium, quadruped_small, Body, CharacterAbilityType,
UtteranceKind, InventoryUpdateEvent, UtteranceKind,
}, },
outcome::Outcome, outcome::Outcome,
terrain::{BlockKind, TerrainChunk}, terrain::{BlockKind, TerrainChunk},
@ -199,7 +199,14 @@ pub enum VoiceKind {
Pig, Pig,
Cow, Cow,
Canine, Canine,
BigCat, Lion,
Mindflayer,
Marlin,
Maneater,
Adlet,
Antelope,
Alligator,
Saurok,
} }
fn body_to_voice(body: &Body) -> Option<VoiceKind> { fn body_to_voice(body: &Body) -> Option<VoiceKind> {
@ -208,6 +215,11 @@ fn body_to_voice(body: &Body) -> Option<VoiceKind> {
humanoid::BodyType::Female => VoiceKind::HumanFemale, humanoid::BodyType::Female => VoiceKind::HumanFemale,
humanoid::BodyType::Male => VoiceKind::HumanMale, humanoid::BodyType::Male => VoiceKind::HumanMale,
}, },
Body::QuadrupedLow(body) => match body.species {
quadruped_low::Species::Maneater => VoiceKind::Maneater,
quadruped_low::Species::Alligator => VoiceKind::Alligator,
_ => return None,
},
Body::QuadrupedSmall(body) => match body.species { Body::QuadrupedSmall(body) => match body.species {
quadruped_small::Species::Sheep => VoiceKind::Sheep, quadruped_small::Species::Sheep => VoiceKind::Sheep,
quadruped_small::Species::Pig | quadruped_small::Species::Boar => VoiceKind::Pig, quadruped_small::Species::Pig | quadruped_small::Species::Boar => VoiceKind::Pig,
@ -218,7 +230,7 @@ fn body_to_voice(body: &Body) -> Option<VoiceKind> {
| quadruped_medium::Species::Tiger | quadruped_medium::Species::Tiger
| quadruped_medium::Species::Lion | quadruped_medium::Species::Lion
| quadruped_medium::Species::Frostfang | quadruped_medium::Species::Frostfang
| quadruped_medium::Species::Snowleopard => VoiceKind::BigCat, | quadruped_medium::Species::Snowleopard => VoiceKind::Lion,
quadruped_medium::Species::Wolf quadruped_medium::Species::Wolf
| quadruped_medium::Species::Roshwalr | quadruped_medium::Species::Roshwalr
| quadruped_medium::Species::Tarasque | quadruped_medium::Species::Tarasque
@ -231,17 +243,24 @@ fn body_to_voice(body: &Body) -> Option<VoiceKind> {
| quadruped_medium::Species::Yak | quadruped_medium::Species::Yak
| quadruped_medium::Species::Moose | quadruped_medium::Species::Moose
| quadruped_medium::Species::Dreadhorn => VoiceKind::Cow, | quadruped_medium::Species::Dreadhorn => VoiceKind::Cow,
quadruped_medium::Species::Antelope => VoiceKind::Antelope,
_ => return None, _ => return None,
}, },
Body::BirdMedium(_) | Body::BirdLarge(_) => VoiceKind::Bird, Body::BirdMedium(_) | Body::BirdLarge(_) => VoiceKind::Bird,
Body::BipedSmall(body) => match body.species {
biped_small::Species::Adlet => VoiceKind::Adlet,
_ => return None,
},
Body::BipedLarge(body) => match body.species { Body::BipedLarge(body) => match body.species {
biped_large::Species::Wendigo => VoiceKind::Wendigo, biped_large::Species::Wendigo => VoiceKind::Wendigo,
biped_large::Species::Occultsaurok biped_large::Species::Occultsaurok
| biped_large::Species::Mightysaurok | biped_large::Species::Mightysaurok
| biped_large::Species::Slysaurok => VoiceKind::Reptile, | biped_large::Species::Slysaurok => VoiceKind::Saurok,
biped_large::Species::Mindflayer => VoiceKind::Mindflayer,
_ => VoiceKind::BipedLarge, _ => VoiceKind::BipedLarge,
}, },
Body::Theropod(_) | Body::Dragon(_) => VoiceKind::Reptile, Body::Theropod(_) | Body::Dragon(_) => VoiceKind::Reptile,
Body::FishSmall(_) | Body::FishMedium(_) => VoiceKind::Marlin,
_ => return None, _ => return None,
}) })
} }
@ -480,15 +499,15 @@ impl SfxMgr {
}, },
Outcome::Damage { pos, .. } => { Outcome::Damage { pos, .. } => {
let sfx_trigger_item = triggers.get_key_value(&SfxEvent::Damage); let sfx_trigger_item = triggers.get_key_value(&SfxEvent::Damage);
audio.emit_sfx(sfx_trigger_item, *pos, None, false); audio.emit_sfx(sfx_trigger_item, *pos, Some(1.5), false);
}, },
Outcome::Block { pos, parry, .. } => { Outcome::Block { pos, parry, .. } => {
if *parry { if *parry {
let sfx_trigger_item = triggers.get_key_value(&SfxEvent::Parry); let sfx_trigger_item = triggers.get_key_value(&SfxEvent::Parry);
audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), false); audio.emit_sfx(sfx_trigger_item, *pos, Some(1.5), false);
} else { } else {
let sfx_trigger_item = triggers.get_key_value(&SfxEvent::Block); let sfx_trigger_item = triggers.get_key_value(&SfxEvent::Block);
audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), false); audio.emit_sfx(sfx_trigger_item, *pos, Some(1.5), false);
} }
}, },
Outcome::PoiseChange { pos, state, .. } => match state { Outcome::PoiseChange { pos, state, .. } => match state {
@ -496,22 +515,22 @@ impl SfxMgr {
PoiseState::Interrupted => { PoiseState::Interrupted => {
let sfx_trigger_item = let sfx_trigger_item =
triggers.get_key_value(&SfxEvent::PoiseChange(PoiseState::Interrupted)); triggers.get_key_value(&SfxEvent::PoiseChange(PoiseState::Interrupted));
audio.emit_sfx(sfx_trigger_item, *pos, None, false); audio.emit_sfx(sfx_trigger_item, *pos, Some(1.5), false);
}, },
PoiseState::Stunned => { PoiseState::Stunned => {
let sfx_trigger_item = let sfx_trigger_item =
triggers.get_key_value(&SfxEvent::PoiseChange(PoiseState::Stunned)); triggers.get_key_value(&SfxEvent::PoiseChange(PoiseState::Stunned));
audio.emit_sfx(sfx_trigger_item, *pos, None, false); audio.emit_sfx(sfx_trigger_item, *pos, Some(1.5), false);
}, },
PoiseState::Dazed => { PoiseState::Dazed => {
let sfx_trigger_item = let sfx_trigger_item =
triggers.get_key_value(&SfxEvent::PoiseChange(PoiseState::Dazed)); triggers.get_key_value(&SfxEvent::PoiseChange(PoiseState::Dazed));
audio.emit_sfx(sfx_trigger_item, *pos, None, false); audio.emit_sfx(sfx_trigger_item, *pos, Some(1.5), false);
}, },
PoiseState::KnockedDown => { PoiseState::KnockedDown => {
let sfx_trigger_item = let sfx_trigger_item =
triggers.get_key_value(&SfxEvent::PoiseChange(PoiseState::KnockedDown)); triggers.get_key_value(&SfxEvent::PoiseChange(PoiseState::KnockedDown));
audio.emit_sfx(sfx_trigger_item, *pos, None, false); audio.emit_sfx(sfx_trigger_item, *pos, Some(1.5), false);
}, },
}, },
Outcome::Utterance { pos, kind, body } => { Outcome::Utterance { pos, kind, body } => {
@ -519,7 +538,7 @@ impl SfxMgr {
let sfx_trigger_item = let sfx_trigger_item =
triggers.get_key_value(&SfxEvent::Utterance(*kind, voice)); triggers.get_key_value(&SfxEvent::Utterance(*kind, voice));
if let Some(sfx_trigger_item) = sfx_trigger_item { if let Some(sfx_trigger_item) = sfx_trigger_item {
audio.emit_sfx(Some(sfx_trigger_item), *pos, Some(2.5), false); audio.emit_sfx(Some(sfx_trigger_item), *pos, Some(1.5), false);
} else { } else {
debug!( debug!(
"No utterance sound effect exists for ({:?}, {:?})", "No utterance sound effect exists for ({:?}, {:?})",