Merge branch 'shandley/inventory-sfx' into 'master'

Add inventory SFX

Closes #485

See merge request veloren/veloren!810
This commit is contained in:
Acrimon 2020-03-04 10:09:48 +00:00
commit 7478d1a063
19 changed files with 159 additions and 26 deletions

View File

@ -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

View File

@ -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,
)
}
)

BIN
assets/voxygen/audio/sfx/inventory/add_item.wav (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/audio/sfx/inventory/consumable/apple.wav (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/audio/sfx/inventory/consumable/food.wav (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/audio/sfx/inventory/consumable/liquid.wav (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -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::<EventBus<SfxEventItem>>()
.emitter()
.emit(SfxEventItem::at_player_position(SfxEvent::Inventory(event)));
},
ServerMsg::TerrainChunkUpdate { key, chunk } => {
if let Ok(chunk) = chunk {

View File

@ -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,

View File

@ -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<Self>;
}
// 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<Self>;
type Storage = FlaggedStorage<Self, IDVStorage<Self>>;
}
#[cfg(test)] mod test;

View File

@ -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};

View File

@ -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 {

View File

@ -71,7 +71,7 @@ pub enum ServerMsg {
entity: u64,
character_state: comp::CharacterState,
},
InventoryUpdate(comp::Inventory),
InventoryUpdate(comp::Inventory, comp::InventoryUpdateEvent),
TerrainChunkUpdate {
key: Vec2<i32>,
chunk: Result<Box<TerrainChunk>, ()>,

View File

@ -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::<comp::InventoryUpdate>()
.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::<comp::InventoryUpdate>()
.insert(entity, comp::InventoryUpdate);
.insert(
entity,
comp::InventoryUpdate::new(comp::InventoryUpdateEvent::Debug),
);
} else {
server.notify_client(
entity,

View File

@ -106,7 +106,10 @@ pub fn handle_possess(server: &Server, possessor_uid: Uid, possesse_uid: Uid) {
}
}
ecs.write_storage::<comp::InventoryUpdate>()
.insert(possesse, comp::InventoryUpdate)
.insert(
possesse,
comp::InventoryUpdate::new(comp::InventoryUpdateEvent::Possession),
)
.err()
.map(|e| {
error!(

View File

@ -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::<comp::Inventory>()
.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),
);
},
}

View File

@ -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
}

View File

@ -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.

View File

@ -1,5 +1,5 @@
pub mod movement;
pub mod progression;
mod movement;
mod progression;
use movement::MovementEventMapper;
use progression::ProgressionEventMapper;

View File

@ -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,