From b0ca85069b418199a71d595ac1b43984e99419fc Mon Sep 17 00:00:00 2001 From: S Handley Date: Wed, 4 Mar 2020 10:09:48 +0000 Subject: [PATCH] Piggyback on the InventoryUpdate events and attach some additional event info so that we can detect why the inventory update was triggered, and emit an associated sfx event that matches it. --- CHANGELOG.md | 1 + assets/voxygen/audio/sfx.ron | 54 +++++++++++++++++++ .../voxygen/audio/sfx/inventory/add_item.wav | 3 ++ .../audio/sfx/inventory/consumable/apple.wav | 3 ++ .../audio/sfx/inventory/consumable/food.wav | 3 ++ .../audio/sfx/inventory/consumable/liquid.wav | 3 ++ client/src/lib.rs | 12 ++++- common/src/comp/inventory/item.rs | 2 +- common/src/comp/inventory/mod.rs | 36 +++++++++++-- common/src/comp/mod.rs | 2 +- common/src/event.rs | 3 +- common/src/msg/server.rs | 2 +- server/src/cmd.rs | 11 +++- server/src/events/interaction.rs | 5 +- server/src/events/inventory_manip.rs | 22 ++++++-- server/src/lib.rs | 10 +++- server/src/sys/entity_sync.rs | 7 ++- voxygen/src/audio/sfx/event_mapper/mod.rs | 4 +- .../audio/sfx/event_mapper/movement/mod.rs | 2 +- 19 files changed, 159 insertions(+), 26 deletions(-) create mode 100644 assets/voxygen/audio/sfx/inventory/add_item.wav create mode 100644 assets/voxygen/audio/sfx/inventory/consumable/apple.wav create mode 100644 assets/voxygen/audio/sfx/inventory/consumable/food.wav create mode 100644 assets/voxygen/audio/sfx/inventory/consumable/liquid.wav diff --git a/CHANGELOG.md b/CHANGELOG.md index 71ac390130..0e3ca83fa6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added new orc hairstyles - Added sfx for wielding/unwielding weapons - Fixed NPCs attacking the player forever after killing them +- Added sfx for collecting, dropping and using inventory items ### Changed diff --git a/assets/voxygen/audio/sfx.ron b/assets/voxygen/audio/sfx.ron index 38349f287e..2a8d79e5e2 100644 --- a/assets/voxygen/audio/sfx.ron +++ b/assets/voxygen/audio/sfx.ron @@ -35,5 +35,59 @@ ], threshold: 0.5, ), + Inventory(Collected): ( + files: [ + "voxygen.audio.sfx.inventory.add_item", + ], + threshold: 0.5, + ), + Inventory(Swapped): ( + files: [ + "voxygen.audio.sfx.inventory.add_item", + ], + threshold: 0.5, + ), + Inventory(Given): ( + files: [ + "voxygen.audio.sfx.inventory.add_item", + ], + threshold: 0.5, + ), + Inventory(Dropped): ( + files: [ + "voxygen.audio.sfx.footsteps.stepgrass_4", + ], + threshold: 0.5, + ), + Inventory(Consumed(Potion)): ( + files: [ + "voxygen.audio.sfx.inventory.consumable.liquid", + ], + threshold: 0.3, + ), + Inventory(Consumed(PotionMinor)): ( + files: [ + "voxygen.audio.sfx.inventory.consumable.liquid", + ], + threshold: 0.3, + ), + Inventory(Consumed(Apple)): ( + files: [ + "voxygen.audio.sfx.inventory.consumable.apple", + ], + threshold: 0.3, + ), + Inventory(Consumed(Mushroom)): ( + files: [ + "voxygen.audio.sfx.inventory.consumable.food", + ], + threshold: 0.3, + ), + Inventory(Consumed(Cheese)): ( + files: [ + "voxygen.audio.sfx.inventory.consumable.food", + ], + threshold: 0.3, + ) } ) \ No newline at end of file diff --git a/assets/voxygen/audio/sfx/inventory/add_item.wav b/assets/voxygen/audio/sfx/inventory/add_item.wav new file mode 100644 index 0000000000..b6fa2c3665 --- /dev/null +++ b/assets/voxygen/audio/sfx/inventory/add_item.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5320d020c82cab3f1ed294c06bdd50df007ed354bca2103b42e3fb4fc3f3ee7a +size 71196 diff --git a/assets/voxygen/audio/sfx/inventory/consumable/apple.wav b/assets/voxygen/audio/sfx/inventory/consumable/apple.wav new file mode 100644 index 0000000000..286d8aade0 --- /dev/null +++ b/assets/voxygen/audio/sfx/inventory/consumable/apple.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4c4d2931431c26b95a4d41b2e137b3db74456b8b9db54d7c48defb9d7bb67689 +size 70152 diff --git a/assets/voxygen/audio/sfx/inventory/consumable/food.wav b/assets/voxygen/audio/sfx/inventory/consumable/food.wav new file mode 100644 index 0000000000..ea39de567a --- /dev/null +++ b/assets/voxygen/audio/sfx/inventory/consumable/food.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0fd5074d0ec517b626e95bc34cb75e735d48dbb99473ffeadb79d90734f52f7d +size 31208 diff --git a/assets/voxygen/audio/sfx/inventory/consumable/liquid.wav b/assets/voxygen/audio/sfx/inventory/consumable/liquid.wav new file mode 100644 index 0000000000..fa0db211f4 --- /dev/null +++ b/assets/voxygen/audio/sfx/inventory/consumable/liquid.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8c3a38dede30bb4a8c13644bd43be5fe261f177f3c65f88e5d02da5b9ba68a97 +size 21548 diff --git a/client/src/lib.rs b/client/src/lib.rs index 90ecb651c6..57ee0fb4d7 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -14,6 +14,7 @@ pub use specs::{ use byteorder::{ByteOrder, LittleEndian}; use common::{ comp::{self, ControlEvent, Controller, ControllerInputs, InventoryManip}, + event::{EventBus, SfxEvent, SfxEventItem}, msg::{ validate_chat_msg, ChatMsgValidationError, ClientMsg, ClientState, PlayerListUpdate, RequestStateError, ServerError, ServerInfo, ServerMsg, MAX_BYTES_CHAT_MSG, @@ -377,6 +378,7 @@ impl Client { } } } + // Handle new messages from the server. frontend_events.append(&mut self.handle_new_messages()?); @@ -669,8 +671,14 @@ impl Client { self.state.write_component(entity, character_state); } }, - ServerMsg::InventoryUpdate(inventory) => { - self.state.write_component(self.entity, inventory) + ServerMsg::InventoryUpdate(inventory, event) => { + self.state.write_component(self.entity, inventory); + + self.state + .ecs() + .read_resource::>() + .emitter() + .emit(SfxEventItem::at_player_position(SfxEvent::Inventory(event))); }, ServerMsg::TerrainChunkUpdate { key, chunk } => { if let Ok(chunk) = chunk { diff --git a/common/src/comp/inventory/item.rs b/common/src/comp/inventory/item.rs index da958ee9b9..dd25ef9e4f 100644 --- a/common/src/comp/inventory/item.rs +++ b/common/src/comp/inventory/item.rs @@ -90,7 +90,7 @@ pub enum Armor { Necklace, } -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Consumable { Apple, Cheese, diff --git a/common/src/comp/inventory/mod.rs b/common/src/comp/inventory/mod.rs index f6833ff923..f192208b5c 100644 --- a/common/src/comp/inventory/mod.rs +++ b/common/src/comp/inventory/mod.rs @@ -1,10 +1,11 @@ pub mod item; // Reexports -pub use item::{Debug, Item, ItemKind, Tool}; +pub use item::{Consumable, Debug, Item, ItemKind, Tool}; use crate::assets; -use specs::{Component, HashMapStorage, NullStorage}; +use specs::{Component, FlaggedStorage, HashMapStorage}; +use specs_idvs::IDVStorage; use std::ops::Not; #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] @@ -136,12 +137,37 @@ impl Component for Inventory { type Storage = HashMapStorage; } -// ForceUpdate +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] +pub enum InventoryUpdateEvent { + Init, + Used, + Consumed(Consumable), + Gave, + Given, + Swapped, + Dropped, + Collected, + Possession, + Debug, +} + +impl Default for InventoryUpdateEvent { + fn default() -> Self { Self::Init } +} + #[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)] -pub struct InventoryUpdate; +pub struct InventoryUpdate { + event: InventoryUpdateEvent, +} + +impl InventoryUpdate { + pub fn new(event: InventoryUpdateEvent) -> Self { Self { event } } + + pub fn event(&self) -> InventoryUpdateEvent { self.event } +} impl Component for InventoryUpdate { - type Storage = NullStorage; + type Storage = FlaggedStorage>; } #[cfg(test)] mod test; diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index 24b1be9efb..2871761a7a 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -28,7 +28,7 @@ pub use controller::{ }; pub use energy::{Energy, EnergySource}; pub use inputs::CanBuild; -pub use inventory::{item, Inventory, InventoryUpdate, Item, ItemKind}; +pub use inventory::{item, Inventory, InventoryUpdate, InventoryUpdateEvent, Item, ItemKind}; pub use last::Last; pub use location::{Waypoint, WaypointArea}; pub use phys::{ForceUpdate, Gravity, Mass, Ori, PhysicsState, Pos, Scale, Sticky, Vel}; diff --git a/common/src/event.rs b/common/src/event.rs index 6ac5e49531..0ba59b7274 100644 --- a/common/src/event.rs +++ b/common/src/event.rs @@ -1,5 +1,5 @@ use crate::{comp, sync::Uid}; -use comp::item::Tool; +use comp::{item::Tool, InventoryUpdateEvent}; use parking_lot::Mutex; use serde::Deserialize; use specs::Entity as EcsEntity; @@ -42,6 +42,7 @@ pub enum SfxEvent { LevelUp, Wield(Tool), Unwield(Tool), + Inventory(InventoryUpdateEvent), } pub enum LocalEvent { diff --git a/common/src/msg/server.rs b/common/src/msg/server.rs index a9244b15f6..0a7b84ae33 100644 --- a/common/src/msg/server.rs +++ b/common/src/msg/server.rs @@ -71,7 +71,7 @@ pub enum ServerMsg { entity: u64, character_state: comp::CharacterState, }, - InventoryUpdate(comp::Inventory), + InventoryUpdate(comp::Inventory, comp::InventoryUpdateEvent), TerrainChunkUpdate { key: Vec2, chunk: Result, ()>, diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 1f46109481..b4a2e3e5dd 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -262,6 +262,7 @@ lazy_static! { ), ]; } + fn handle_give(server: &mut Server, entity: EcsEntity, args: String, _action: &ChatCommand) { if let Ok(item) = assets::load_cloned(&args) { server @@ -274,7 +275,10 @@ fn handle_give(server: &mut Server, entity: EcsEntity, args: String, _action: &C .state .ecs() .write_storage::() - .insert(entity, comp::InventoryUpdate); + .insert( + entity, + comp::InventoryUpdate::new(comp::InventoryUpdateEvent::Given), + ); } else { server.notify_client(entity, ServerMsg::private(String::from("Invalid item!"))); } @@ -1113,7 +1117,10 @@ fn handle_debug(server: &mut Server, entity: EcsEntity, _args: String, _action: .state .ecs() .write_storage::() - .insert(entity, comp::InventoryUpdate); + .insert( + entity, + comp::InventoryUpdate::new(comp::InventoryUpdateEvent::Debug), + ); } else { server.notify_client( entity, diff --git a/server/src/events/interaction.rs b/server/src/events/interaction.rs index 96be66e52b..7d7e3fd124 100644 --- a/server/src/events/interaction.rs +++ b/server/src/events/interaction.rs @@ -106,7 +106,10 @@ pub fn handle_possess(server: &Server, possessor_uid: Uid, possesse_uid: Uid) { } } ecs.write_storage::() - .insert(possesse, comp::InventoryUpdate) + .insert( + possesse, + comp::InventoryUpdate::new(comp::InventoryUpdateEvent::Possession), + ) .err() .map(|e| { error!( diff --git a/server/src/events/inventory_manip.rs b/server/src/events/inventory_manip.rs index 4485a62fb7..09998ca6aa 100644 --- a/server/src/events/inventory_manip.rs +++ b/server/src/events/inventory_manip.rs @@ -48,7 +48,10 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv } } - state.write_component(entity, comp::InventoryUpdate); + state.write_component( + entity, + comp::InventoryUpdate::new(comp::InventoryUpdateEvent::Collected), + ); }, comp::InventoryManip::Collect(pos) => { @@ -76,6 +79,8 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv .get_mut(entity) .and_then(|inv| inv.remove(slot)); + let mut event = comp::InventoryUpdateEvent::Used; + if let Some(item) = item_opt { match item.kind { comp::ItemKind::Tool { .. } => { @@ -94,7 +99,8 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv stats.equipment.main = Some(item); } }, - comp::ItemKind::Consumable { effect, .. } => { + comp::ItemKind::Consumable { kind, effect } => { + event = comp::InventoryUpdateEvent::Consumed(kind); state.apply_effect(entity, effect); }, comp::ItemKind::Utility { kind } => match kind { @@ -168,7 +174,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv } } - state.write_component(entity, comp::InventoryUpdate); + state.write_component(entity, comp::InventoryUpdate::new(event)); }, comp::InventoryManip::Swap(a, b) => { @@ -177,7 +183,10 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv .write_storage::() .get_mut(entity) .map(|inv| inv.swap_slots(a, b)); - state.write_component(entity, comp::InventoryUpdate); + state.write_component( + entity, + comp::InventoryUpdate::new(comp::InventoryUpdateEvent::Swapped), + ); }, comp::InventoryManip::Drop(slot) => { @@ -201,7 +210,10 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv item, )); } - state.write_component(entity, comp::InventoryUpdate); + state.write_component( + entity, + comp::InventoryUpdate::new(comp::InventoryUpdateEvent::Dropped), + ); }, } diff --git a/server/src/lib.rs b/server/src/lib.rs index b39fefea50..4d11efd110 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -282,7 +282,10 @@ impl Server { state.write_component(entity, comp::CharacterState::default()); state.write_component(entity, comp::Alignment::Owned(entity)); state.write_component(entity, comp::Inventory::default()); - state.write_component(entity, comp::InventoryUpdate); + state.write_component( + entity, + comp::InventoryUpdate::new(comp::InventoryUpdateEvent::default()), + ); // Make sure physics are accepted. state.write_component(entity, comp::ForceUpdate); @@ -606,7 +609,10 @@ impl StateExt for State { .map(|inv| inv.push(item).is_none()) .unwrap_or(false); if success { - self.write_component(entity, comp::InventoryUpdate); + self.write_component( + entity, + comp::InventoryUpdate::new(comp::InventoryUpdateEvent::Collected), + ); } success } diff --git a/server/src/sys/entity_sync.rs b/server/src/sys/entity_sync.rs index 1d28b77117..62bc7521a7 100644 --- a/server/src/sys/entity_sync.rs +++ b/server/src/sys/entity_sync.rs @@ -328,8 +328,11 @@ impl<'a> System<'a> for Sys { // TODO: Sync clients that don't have a position? // Sync inventories - for (client, inventory, _) in (&mut clients, &inventories, &inventory_updates).join() { - client.notify(ServerMsg::InventoryUpdate(inventory.clone())); + for (client, inventory, update) in (&mut clients, &inventories, &inventory_updates).join() { + client.notify(ServerMsg::InventoryUpdate( + inventory.clone(), + update.event(), + )); } // Remove all force flags. diff --git a/voxygen/src/audio/sfx/event_mapper/mod.rs b/voxygen/src/audio/sfx/event_mapper/mod.rs index e195d1cba2..94905cb802 100644 --- a/voxygen/src/audio/sfx/event_mapper/mod.rs +++ b/voxygen/src/audio/sfx/event_mapper/mod.rs @@ -1,5 +1,5 @@ -pub mod movement; -pub mod progression; +mod movement; +mod progression; use movement::MovementEventMapper; use progression::ProgressionEventMapper; diff --git a/voxygen/src/audio/sfx/event_mapper/movement/mod.rs b/voxygen/src/audio/sfx/event_mapper/movement/mod.rs index 77c2067177..617092e8d6 100644 --- a/voxygen/src/audio/sfx/event_mapper/movement/mod.rs +++ b/voxygen/src/audio/sfx/event_mapper/movement/mod.rs @@ -172,7 +172,7 @@ impl MovementEventMapper { match ( current_event.movement, current_event.action, - previous_event.event, + previous_event.event.clone(), ) { (_, ActionState::Roll { .. }, _) => SfxEvent::Roll, (MovementState::Climb, ..) => SfxEvent::Climb,