diff --git a/assets/voxygen/item_image_manifest.ron b/assets/voxygen/item_image_manifest.ron
index 23b1bc4f33..89bf8ae82b 100644
--- a/assets/voxygen/item_image_manifest.ron
+++ b/assets/voxygen/item_image_manifest.ron
@@ -2480,7 +2480,7 @@
         (0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 0.9,
     ),
     Consumable("common.items.food.cheese"): VoxTrans(
-        "voxel.object.cheese-0",
+        "voxel.object.cheese",
         (0.0, 0.0, 0.0), (-60.0, -10.0, 0.0), 0.8,
     ),
     Consumable("common.items.food.blue_cheese"): VoxTrans(
@@ -2661,8 +2661,9 @@
         "voxel.object.ice_shard",
         (0.0, 0.0, 0.0), (10.0, -20.0, 30.0), 1.0,
     ),
-    Ingredient("FlayerBagDamaged"): Png(
-        "element.items.item_flayer_soul",
+    Ingredient("FlayerBagDamaged"): VoxTrans(
+        "voxel.object.glowing_remains",
+        (0.0, 0.0, 0.0), (10.0, -20.0, 30.0), 1.0,
     ),
     Ingredient("RaptorFeather"): VoxTrans(
         "voxel.object.raptor_feather",
@@ -2880,8 +2881,9 @@
         "voxel.object.honey",
         (1.0, 0.0, 0.0), (-20.0, 20.0, -30.0), 0.9,
     ),
-    Ingredient("MortarPestle"): Png(
-        "element.items.item_mortarpestlecoco",
+    Ingredient("MortarPestle"): VoxTrans(
+        "voxel.object.mortar_pestle",
+        (0.0, 0.0, 0.0), (10.0, -20.0, 30.0), 1.0,
     ),
     Ingredient("EmptyVial"): VoxTrans(
         "voxel.object.potion_empty",
diff --git a/assets/voxygen/voxel/object/cheese.vox b/assets/voxygen/voxel/object/cheese.vox
new file mode 100644
index 0000000000..e7a7b7c670
--- /dev/null
+++ b/assets/voxygen/voxel/object/cheese.vox
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:25455fa8d01e603280e842bbe7b3ce7361ca202dad31c9ca2a291c4b69250dc0
+size 3460
diff --git a/assets/voxygen/voxel/object/collar.vox b/assets/voxygen/voxel/object/collar.vox
index 256c04220b..d32817159e 100644
--- a/assets/voxygen/voxel/object/collar.vox
+++ b/assets/voxygen/voxel/object/collar.vox
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:fad24f6450d61d5949aa64a12d35a2a2d5d7adcb1e3097b4dc5e514efc246e1b
-size 55936
+oid sha256:35eb993c094e43b81e36a17a37cabec38ebace3068956d82c96c200134eb9250
+size 1424
diff --git a/assets/voxygen/voxel/object/glowing_remains.vox b/assets/voxygen/voxel/object/glowing_remains.vox
new file mode 100644
index 0000000000..f9e78792de
--- /dev/null
+++ b/assets/voxygen/voxel/object/glowing_remains.vox
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:740322b4c3136aecd6e9c5bbacd29f33d12bd1059d0b08a0c991be7bfa94db51
+size 1736
diff --git a/assets/voxygen/voxel/object/mortar_pestle.vox b/assets/voxygen/voxel/object/mortar_pestle.vox
new file mode 100644
index 0000000000..6341a0dc6f
--- /dev/null
+++ b/assets/voxygen/voxel/object/mortar_pestle.vox
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:979790e5b2311014ec1129d0b6f8ffdbbfd1663b577647c8bbf669520f333c6b
+size 1612
diff --git a/assets/voxygen/voxel/object/mushroom_curry.vox b/assets/voxygen/voxel/object/mushroom_curry.vox
index bf3f039bde..6c86f24907 100644
--- a/assets/voxygen/voxel/object/mushroom_curry.vox
+++ b/assets/voxygen/voxel/object/mushroom_curry.vox
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:cb91306dec47543cea8e5b78dfa0eabe3a5fbcf170953e71552f1c4aa46d9dbb
-size 56956
+oid sha256:0a98f71348317c17ba90164f85d8e609f997b70f9de44498ff437a9d382fd7de
+size 2616
diff --git a/voxygen/src/audio/sfx/event_mapper/block/mod.rs b/voxygen/src/audio/sfx/event_mapper/block/mod.rs
deleted file mode 100644
index 33dce469c6..0000000000
--- a/voxygen/src/audio/sfx/event_mapper/block/mod.rs
+++ /dev/null
@@ -1,297 +0,0 @@
-/// EventMapper::Block watches the sound emitting blocks within
-/// chunk range of the player and emits ambient sfx
-use crate::{
-    audio::sfx::{SfxEvent, SfxTriggerItem, SfxTriggers, SFX_DIST_LIMIT_SQR},
-    scene::{terrain::BlocksOfInterest, Camera, Terrain},
-    AudioFrontend,
-};
-
-use super::EventMapper;
-use client::Client;
-use common::{
-    comp::Pos,
-    spiral::Spiral2d,
-    terrain::TerrainChunk,
-    vol::{ReadVol, RectRasterableVol},
-};
-use common_state::State;
-use hashbrown::HashMap;
-use rand::{thread_rng, Rng};
-use std::time::{Duration, Instant};
-use vek::*;
-
-#[derive(Clone, PartialEq)]
-struct PreviousBlockState {
-    event: SfxEvent,
-    time: Instant,
-}
-
-impl Default for PreviousBlockState {
-    fn default() -> Self {
-        Self {
-            event: SfxEvent::Idle,
-            time: Instant::now()
-                .checked_add(Duration::from_millis(thread_rng().gen_range(0..500)))
-                .unwrap_or_else(Instant::now),
-        }
-    }
-}
-
-pub struct BlockEventMapper {
-    history: HashMap<Vec3<i32>, PreviousBlockState>,
-}
-
-impl EventMapper for BlockEventMapper {
-    fn maintain(
-        &mut self,
-        audio: &mut AudioFrontend,
-        state: &State,
-        player_entity: specs::Entity,
-        camera: &Camera,
-        triggers: &SfxTriggers,
-        terrain: &Terrain<TerrainChunk>,
-        client: &Client,
-    ) {
-        let focus_off = camera.get_focus_pos().map(f32::trunc);
-        let cam_pos = camera.dependents().cam_pos + focus_off;
-
-        // Get the player position and chunk
-        let player_pos = state
-            .read_component_copied::<Pos>(player_entity)
-            .unwrap_or_default();
-        let player_chunk = player_pos.0.xy().map2(TerrainChunk::RECT_SIZE, |e, sz| {
-            (e.floor() as i32).div_euclid(sz as i32)
-        });
-
-        // For determining if underground/crickets should chirp
-        let (terrain_alt, temp) = match client.current_chunk() {
-            Some(chunk) => (chunk.meta().alt(), chunk.meta().temp()),
-            None => (0.0, 0.0),
-        };
-
-        struct BlockSounds<'a> {
-            // The function to select the blocks of interest that we should emit from
-            blocks: fn(&'a BlocksOfInterest) -> &'a [Vec3<i32>],
-            // The range, in chunks, that the particles should be generated in from the player
-            range: usize,
-            // The sound of the generated particle
-            sfx: SfxEvent,
-            // The volume of the sfx
-            volume: f32,
-            // Condition that must be true to play
-            cond: fn(&State) -> bool,
-        }
-
-        let sounds: &[BlockSounds] = &[
-            BlockSounds {
-                blocks: |boi| &boi.leaves,
-                range: 1,
-                sfx: SfxEvent::Birdcall,
-                volume: 1.0,
-                cond: |st| st.get_day_period().is_light(),
-            },
-            BlockSounds {
-                blocks: |boi| &boi.leaves,
-                range: 1,
-                sfx: SfxEvent::Owl,
-                volume: 1.0,
-                cond: |st| st.get_day_period().is_dark(),
-            },
-            // BlockSounds {
-            //     blocks: |boi| &boi.river,
-            //     range: 1,
-            //     sfx: SfxEvent::RunningWater,
-            //     volume: 1.0,
-            //     cond: |_| true,
-            // },
-            //BlockSounds {
-            //    blocks: |boi| &boi.embers,
-            //    range: 1,
-            //    sfx: SfxEvent::Embers,
-            //    volume: 0.15,
-            //    //volume: 0.05,
-            //    cond: |_| true,
-            //    //cond: |st| st.get_day_period().is_dark(),
-            //},
-            BlockSounds {
-                blocks: |boi| &boi.frogs,
-                range: 1,
-                sfx: SfxEvent::Frog,
-                volume: 0.8,
-                cond: |st| st.get_day_period().is_dark(),
-            },
-            //BlockSounds {
-            //    blocks: |boi| &boi.flowers,
-            //    range: 4,
-            //    sfx: SfxEvent::LevelUp,
-            //    volume: 1.0,
-            //    cond: |st| st.get_day_period().is_dark(),
-            //},
-            BlockSounds {
-                blocks: |boi| &boi.cricket1,
-                range: 1,
-                sfx: SfxEvent::Cricket1,
-                volume: 0.33,
-                cond: |st| st.get_day_period().is_dark(),
-            },
-            BlockSounds {
-                blocks: |boi| &boi.cricket2,
-                range: 1,
-                sfx: SfxEvent::Cricket2,
-                volume: 0.33,
-                cond: |st| st.get_day_period().is_dark(),
-            },
-            BlockSounds {
-                blocks: |boi| &boi.cricket3,
-                range: 1,
-                sfx: SfxEvent::Cricket3,
-                volume: 0.33,
-                cond: |st| st.get_day_period().is_dark(),
-            },
-            BlockSounds {
-                blocks: |boi| &boi.beehives,
-                range: 1,
-                sfx: SfxEvent::Bees,
-                volume: 0.5,
-                cond: |st| st.get_day_period().is_light(),
-            },
-        ];
-
-        // Iterate through each kind of block of interest
-        for sounds in sounds.iter() {
-            // If the timing condition is false, continue
-            // or if the player is far enough underground, continue
-            // TODO Address bird hack properly. See TODO on line 190
-            if !(sounds.cond)(state)
-                || player_pos.0.z < (terrain_alt - 30.0)
-                || (sounds.sfx == SfxEvent::Birdcall && thread_rng().gen_bool(0.995))
-                || (sounds.sfx == SfxEvent::Owl && thread_rng().gen_bool(0.998))
-                || (sounds.sfx == SfxEvent::Frog && thread_rng().gen_bool(0.95))
-                //Crickets will not chirp below 5 Celsius
-                || (sounds.sfx == SfxEvent::Cricket1 && (temp < -0.33))
-                || (sounds.sfx == SfxEvent::Cricket2 && (temp < -0.33))
-                || (sounds.sfx == SfxEvent::Cricket3 && (temp < -0.33))
-            {
-                continue;
-            }
-
-            // For chunks surrounding the player position
-            for offset in Spiral2d::new().take((sounds.range * 2 + 1).pow(2)) {
-                let chunk_pos = player_chunk + offset;
-
-                // Get all the blocks of interest in this chunk
-                terrain.get(chunk_pos).map(|chunk_data| {
-                    // Get the positions of the blocks of type sounds
-                    let blocks = (sounds.blocks)(&chunk_data.blocks_of_interest);
-
-                    let absolute_pos: Vec3<i32> =
-                        Vec3::from(chunk_pos * TerrainChunk::RECT_SIZE.map(|e| e as i32));
-
-                    // Iterate through each individual block
-                    for block in blocks {
-                        // TODO Address this hack properly, potentially by making a new
-                        // block of interest type which picks fewer leaf blocks
-                        // Hack to reduce the number of bird sounds (too many leaf blocks)
-                        if ((sounds.sfx == SfxEvent::Birdcall || sounds.sfx == SfxEvent::Owl)
-                            && thread_rng().gen_bool(0.999))
-                            || (sounds.sfx == SfxEvent::Frog && thread_rng().gen_bool(0.75))
-                        {
-                            continue;
-                        }
-                        let block_pos: Vec3<i32> = absolute_pos + block;
-                        let internal_state = self.history.entry(block_pos).or_default();
-
-                        let block_pos = block_pos.map(|x| x as f32);
-
-                        if Self::should_emit(
-                            internal_state,
-                            triggers.get_key_value(&sounds.sfx),
-                            temp,
-                        ) {
-                            // If the camera is within SFX distance
-                            if (block_pos.distance_squared(cam_pos)) < SFX_DIST_LIMIT_SQR {
-                                let underwater = state
-                                    .terrain()
-                                    .get(cam_pos.map(|e| e.floor() as i32))
-                                    .map(|b| b.is_liquid())
-                                    .unwrap_or(false);
-
-                                let sfx_trigger_item = triggers.get_key_value(&sounds.sfx);
-                                audio.emit_sfx(
-                                    sfx_trigger_item,
-                                    block_pos,
-                                    Some(sounds.volume),
-                                    underwater,
-                                );
-                            }
-                            internal_state.time = Instant::now();
-                            internal_state.event = sounds.sfx.clone();
-                        }
-                    }
-                });
-            }
-        }
-    }
-}
-
-impl BlockEventMapper {
-    pub fn new() -> Self {
-        Self {
-            history: HashMap::new(),
-        }
-    }
-
-    /// Ensures that:
-    /// 1. An sfx.ron entry exists for an SFX event
-    /// 2. The sfx has not been played since it's timeout threshold has elapsed,
-    /// which prevents firing every tick
-    /// Note that with so many blocks to choose from and different blocks being
-    /// selected each time, this is not perfect, but does reduce the number of
-    /// plays from blocks that have already emitted sfx and are stored in the
-    /// BlockEventMapper history.
-    fn should_emit(
-        previous_state: &PreviousBlockState,
-        sfx_trigger_item: Option<(&SfxEvent, &SfxTriggerItem)>,
-        temp: f32,
-    ) -> bool {
-        if let Some((event, item)) = sfx_trigger_item {
-            //The interval between cricket chirps calculated by converting chunk
-            // temperature to centigrade (we should create a function for this) and applying
-            // the "cricket formula" to it
-            let cricket_interval = (25.0 / (3.0 * ((temp * 30.0) + 15.0))).max(0.5);
-            if &previous_state.event == event {
-                //In case certain sounds need modification to their threshold,
-                //use match event
-                match event {
-                    SfxEvent::Cricket1 => {
-                        previous_state.time.elapsed().as_secs_f32()
-                            >= cricket_interval + thread_rng().gen_range(-0.1..0.1)
-                    },
-                    SfxEvent::Cricket2 => {
-                        //the length and manner of this sound is quite different
-                        if cricket_interval < 0.75 {
-                            previous_state.time.elapsed().as_secs_f32() >= 0.75
-                        } else {
-                            previous_state.time.elapsed().as_secs_f32()
-                                >= cricket_interval + thread_rng().gen_range(-0.1..0.1)
-                        }
-                    },
-                    SfxEvent::Cricket3 => {
-                        previous_state.time.elapsed().as_secs_f32()
-                            >= cricket_interval + thread_rng().gen_range(-0.1..0.1)
-                    },
-                    //Adds random factor to frogs (probably doesn't do anything most of the time)
-                    SfxEvent::Frog => {
-                        previous_state.time.elapsed().as_secs_f32()
-                            >= thread_rng().gen_range(-2.0..2.0)
-                    },
-                    _ => previous_state.time.elapsed().as_secs_f32() >= item.threshold,
-                }
-            } else {
-                true
-            }
-        } else {
-            false
-        }
-    }
-}
diff --git a/voxygen/src/audio/sfx/event_mapper/campfire/mod.rs b/voxygen/src/audio/sfx/event_mapper/campfire/mod.rs
deleted file mode 100644
index cdd6f9ea68..0000000000
--- a/voxygen/src/audio/sfx/event_mapper/campfire/mod.rs
+++ /dev/null
@@ -1,129 +0,0 @@
-/// EventMapper::Campfire maps sfx to campfires
-use crate::{
-    audio::sfx::{SfxEvent, SfxTriggerItem, SfxTriggers, SFX_DIST_LIMIT_SQR},
-    scene::{Camera, Terrain},
-    AudioFrontend,
-};
-
-use super::EventMapper;
-
-use client::Client;
-use common::{
-    comp::{object, Body, Pos},
-    terrain::TerrainChunk,
-    vol::ReadVol,
-};
-use common_state::State;
-use hashbrown::HashMap;
-use specs::{Entity as EcsEntity, Join, WorldExt};
-use std::time::{Duration, Instant};
-
-#[derive(Clone)]
-struct PreviousEntityState {
-    event: SfxEvent,
-    time: Instant,
-}
-
-impl Default for PreviousEntityState {
-    fn default() -> Self {
-        Self {
-            event: SfxEvent::Idle,
-            time: Instant::now(),
-        }
-    }
-}
-
-pub struct CampfireEventMapper {
-    event_history: HashMap<EcsEntity, PreviousEntityState>,
-}
-
-impl EventMapper for CampfireEventMapper {
-    fn maintain(
-        &mut self,
-        audio: &mut AudioFrontend,
-        state: &State,
-        player_entity: specs::Entity,
-        camera: &Camera,
-        triggers: &SfxTriggers,
-        _terrain: &Terrain<TerrainChunk>,
-        _client: &Client,
-    ) {
-        let ecs = state.ecs();
-        let focus_off = camera.get_focus_pos().map(f32::trunc);
-        let cam_pos = camera.dependents().cam_pos + focus_off;
-        for (entity, body, pos) in (
-            &ecs.entities(),
-            &ecs.read_storage::<Body>(),
-            &ecs.read_storage::<Pos>(),
-        )
-            .join()
-            .filter(|(_, _, e_pos)| (e_pos.0.distance_squared(cam_pos)) < SFX_DIST_LIMIT_SQR)
-        {
-            if let Body::Object(object::Body::CampfireLit) = body {
-                let internal_state = self.event_history.entry(entity).or_default();
-
-                let mapped_event = SfxEvent::Campfire;
-
-                // Check for SFX config entry for this movement
-                if Self::should_emit(internal_state, triggers.get_key_value(&mapped_event)) {
-                    let underwater = state
-                        .terrain()
-                        .get(cam_pos.map(|e| e.floor() as i32))
-                        .map(|b| b.is_liquid())
-                        .unwrap_or(false);
-                    let sfx_trigger_item = triggers.get_key_value(&mapped_event);
-                    const CAMPFIRE_VOLUME: f32 = 0.8;
-                    audio.emit_sfx(sfx_trigger_item, pos.0, Some(CAMPFIRE_VOLUME), underwater);
-                    internal_state.time = Instant::now();
-                }
-
-                // update state to determine the next event. We only record the time (above) if
-                // it was dispatched
-                internal_state.event = mapped_event;
-            }
-        }
-        self.cleanup(player_entity);
-    }
-}
-
-impl CampfireEventMapper {
-    pub fn new() -> Self {
-        Self {
-            event_history: HashMap::new(),
-        }
-    }
-
-    /// As the player explores the world, we track the last event of the nearby
-    /// entities to determine the correct SFX item to play next based on
-    /// their activity. `cleanup` will remove entities from event tracking if
-    /// they have not triggered an event for > n seconds. This prevents
-    /// stale records from bloating the Map size.
-    fn cleanup(&mut self, player: EcsEntity) {
-        const TRACKING_TIMEOUT: u64 = 10;
-
-        let now = Instant::now();
-        self.event_history.retain(|entity, event| {
-            now.duration_since(event.time) < Duration::from_secs(TRACKING_TIMEOUT)
-                || entity.id() == player.id()
-        });
-    }
-
-    /// Ensures that:
-    /// 1. An sfx.ron entry exists for an SFX event
-    /// 2. The sfx has not been played since it's timeout threshold has elapsed,
-    /// which prevents firing every tick
-    fn should_emit(
-        previous_state: &PreviousEntityState,
-        sfx_trigger_item: Option<(&SfxEvent, &SfxTriggerItem)>,
-    ) -> bool {
-        if let Some((event, item)) = sfx_trigger_item {
-            if &previous_state.event == event {
-                previous_state.time.elapsed().as_secs_f32() >= item.threshold
-            } else {
-                true
-            }
-        } else {
-            false
-        }
-    }
-}
diff --git a/voxygen/src/audio/sfx/event_mapper/combat/mod.rs b/voxygen/src/audio/sfx/event_mapper/combat/mod.rs
deleted file mode 100644
index 9014010c56..0000000000
--- a/voxygen/src/audio/sfx/event_mapper/combat/mod.rs
+++ /dev/null
@@ -1,182 +0,0 @@
-/// EventMapper::Combat watches the combat states of surrounding entities' and
-/// emits sfx related to weapons and attacks/abilities
-use crate::{
-    audio::sfx::{SfxEvent, SfxTriggerItem, SfxTriggers, SFX_DIST_LIMIT_SQR},
-    scene::{Camera, Terrain},
-    AudioFrontend,
-};
-
-use super::EventMapper;
-
-use client::Client;
-use common::{
-    comp::{
-        inventory::slot::EquipSlot, item::ItemKind, CharacterAbilityType, CharacterState,
-        Inventory, Pos,
-    },
-    terrain::TerrainChunk,
-    vol::ReadVol,
-};
-use common_state::State;
-use hashbrown::HashMap;
-use specs::{Entity as EcsEntity, Join, WorldExt};
-use std::time::{Duration, Instant};
-
-#[derive(Clone)]
-struct PreviousEntityState {
-    event: SfxEvent,
-    time: Instant,
-    weapon_drawn: bool,
-}
-
-impl Default for PreviousEntityState {
-    fn default() -> Self {
-        Self {
-            event: SfxEvent::Idle,
-            time: Instant::now(),
-            weapon_drawn: false,
-        }
-    }
-}
-
-pub struct CombatEventMapper {
-    event_history: HashMap<EcsEntity, PreviousEntityState>,
-}
-
-impl EventMapper for CombatEventMapper {
-    fn maintain(
-        &mut self,
-        audio: &mut AudioFrontend,
-        state: &State,
-        player_entity: specs::Entity,
-        camera: &Camera,
-        triggers: &SfxTriggers,
-        _terrain: &Terrain<TerrainChunk>,
-        _client: &Client,
-    ) {
-        let ecs = state.ecs();
-
-        let focus_off = camera.get_focus_pos().map(f32::trunc);
-        let cam_pos = camera.dependents().cam_pos + focus_off;
-
-        for (entity, pos, inventory, character) in (
-            &ecs.entities(),
-            &ecs.read_storage::<Pos>(),
-            ecs.read_storage::<Inventory>().maybe(),
-            ecs.read_storage::<CharacterState>().maybe(),
-        )
-            .join()
-            .filter(|(_, e_pos, ..)| (e_pos.0.distance_squared(cam_pos)) < SFX_DIST_LIMIT_SQR)
-        {
-            if let Some(character) = character {
-                let sfx_state = self.event_history.entry(entity).or_default();
-
-                let mapped_event = inventory.map_or(SfxEvent::Idle, |inv| {
-                    Self::map_event(character, sfx_state, inv)
-                });
-
-                // Check for SFX config entry for this movement
-                if Self::should_emit(sfx_state, triggers.get_key_value(&mapped_event)) {
-                    let underwater = state
-                        .terrain()
-                        .get(cam_pos.map(|e| e.floor() as i32))
-                        .map(|b| b.is_liquid())
-                        .unwrap_or(false);
-
-                    let sfx_trigger_item = triggers.get_key_value(&mapped_event);
-                    audio.emit_sfx(sfx_trigger_item, pos.0, None, underwater);
-                    sfx_state.time = Instant::now();
-                }
-
-                // update state to determine the next event. We only record the time (above) if
-                // it was dispatched
-                sfx_state.event = mapped_event;
-                sfx_state.weapon_drawn = Self::weapon_drawn(character);
-            }
-        }
-
-        self.cleanup(player_entity);
-    }
-}
-
-impl CombatEventMapper {
-    pub fn new() -> Self {
-        Self {
-            event_history: HashMap::new(),
-        }
-    }
-
-    /// As the player explores the world, we track the last event of the nearby
-    /// entities to determine the correct SFX item to play next based on
-    /// their activity. `cleanup` will remove entities from event tracking if
-    /// they have not triggered an event for > n seconds. This prevents
-    /// stale records from bloating the Map size.
-    fn cleanup(&mut self, player: EcsEntity) {
-        const TRACKING_TIMEOUT: u64 = 10;
-
-        let now = Instant::now();
-        self.event_history.retain(|entity, event| {
-            now.duration_since(event.time) < Duration::from_secs(TRACKING_TIMEOUT)
-                || entity.id() == player.id()
-        });
-    }
-
-    /// Ensures that:
-    /// 1. An sfx.ron entry exists for an SFX event
-    /// 2. The sfx has not been played since it's timeout threshold has elapsed,
-    /// which prevents firing every tick
-    fn should_emit(
-        previous_state: &PreviousEntityState,
-        sfx_trigger_item: Option<(&SfxEvent, &SfxTriggerItem)>,
-    ) -> bool {
-        if let Some((event, item)) = sfx_trigger_item {
-            if &previous_state.event == event {
-                previous_state.time.elapsed().as_secs_f32() >= item.threshold
-            } else {
-                true
-            }
-        } else {
-            false
-        }
-    }
-
-    fn map_event(
-        character_state: &CharacterState,
-        previous_state: &PreviousEntityState,
-        inventory: &Inventory,
-    ) -> SfxEvent {
-        if let Some(item) = inventory.equipped(EquipSlot::ActiveMainhand) {
-            if let ItemKind::Tool(data) = item.kind() {
-                if character_state.is_attack() {
-                    return SfxEvent::Attack(
-                        CharacterAbilityType::from(character_state),
-                        data.kind,
-                    );
-                } else if let Some(wield_event) = match (
-                    previous_state.weapon_drawn,
-                    character_state.is_dodge(),
-                    Self::weapon_drawn(character_state),
-                ) {
-                    (false, false, true) => Some(SfxEvent::Wield(data.kind)),
-                    (true, false, false) => Some(SfxEvent::Unwield(data.kind)),
-                    _ => None,
-                } {
-                    return wield_event;
-                }
-            }
-            // Check for attacking states
-        }
-
-        SfxEvent::Idle
-    }
-
-    /// This helps us determine whether we should be emitting the Wield/Unwield
-    /// events. For now, consider either CharacterState::Wielding or
-    /// ::Equipping to mean the weapon is drawn. This will need updating if the
-    /// animations change to match the wield_duration associated with the weapon
-    fn weapon_drawn(character: &CharacterState) -> bool {
-        character.is_wield() || matches!(character, CharacterState::Equipping { .. })
-    }
-}
-
-#[cfg(test)] mod tests;
diff --git a/voxygen/src/audio/sfx/event_mapper/combat/tests.rs b/voxygen/src/audio/sfx/event_mapper/combat/tests.rs
deleted file mode 100644
index 14fb308459..0000000000
--- a/voxygen/src/audio/sfx/event_mapper/combat/tests.rs
+++ /dev/null
@@ -1,239 +0,0 @@
-use super::*;
-use crate::audio::sfx::SfxEvent;
-use common::{
-    combat::{self, DamageKind},
-    comp::{
-        inventory::loadout_builder::LoadoutBuilder, item::tool::ToolKind, CharacterAbilityType,
-        CharacterState, InputKind, Item,
-    },
-    states,
-};
-use std::time::{Duration, Instant};
-
-#[test]
-fn maps_wield_while_equipping() {
-    let loadout = LoadoutBuilder::empty()
-        .active_mainhand(Some(Item::new_from_asset_expect(
-            "common.items.weapons.axe.starter_axe",
-        )))
-        .build();
-    let inventory = Inventory::new_with_loadout(loadout);
-
-    let result = CombatEventMapper::map_event(
-        &CharacterState::Equipping(states::equipping::Data {
-            static_data: states::equipping::StaticData {
-                buildup_duration: Duration::from_millis(10),
-            },
-            timer: Duration::default(),
-            is_sneaking: false,
-        }),
-        &PreviousEntityState {
-            event: SfxEvent::Idle,
-            time: Instant::now(),
-            weapon_drawn: false,
-        },
-        &inventory,
-    );
-
-    assert_eq!(result, SfxEvent::Wield(ToolKind::Axe));
-}
-
-#[test]
-fn maps_unwield() {
-    let loadout = LoadoutBuilder::empty()
-        .active_mainhand(Some(Item::new_from_asset_expect(
-            "common.items.weapons.bow.starter",
-        )))
-        .build();
-    let inventory = Inventory::new_with_loadout(loadout);
-
-    let result = CombatEventMapper::map_event(
-        &CharacterState::default(),
-        &PreviousEntityState {
-            event: SfxEvent::Idle,
-            time: Instant::now(),
-            weapon_drawn: true,
-        },
-        &inventory,
-    );
-
-    assert_eq!(result, SfxEvent::Unwield(ToolKind::Bow));
-}
-
-#[test]
-fn maps_basic_melee() {
-    let loadout = LoadoutBuilder::empty()
-        .active_mainhand(Some(Item::new_from_asset_expect(
-            "common.items.weapons.axe.starter_axe",
-        )))
-        .build();
-    let inventory = Inventory::new_with_loadout(loadout);
-
-    let result = CombatEventMapper::map_event(
-        &CharacterState::BasicMelee(states::basic_melee::Data {
-            static_data: states::basic_melee::StaticData {
-                buildup_duration: Duration::default(),
-                swing_duration: Duration::default(),
-                recover_duration: Duration::default(),
-                base_damage: 10.0,
-                base_poise_damage: 10.0,
-                knockback: combat::Knockback {
-                    strength: 0.0,
-                    direction: combat::KnockbackDir::Away,
-                },
-                range: 1.0,
-                max_angle: 1.0,
-                ability_info: empty_ability_info(),
-                damage_effect: None,
-                damage_kind: DamageKind::Slashing,
-            },
-            timer: Duration::default(),
-            stage_section: states::utils::StageSection::Buildup,
-            exhausted: false,
-        }),
-        &PreviousEntityState {
-            event: SfxEvent::Idle,
-            time: Instant::now(),
-            weapon_drawn: true,
-        },
-        &inventory,
-    );
-
-    assert_eq!(
-        result,
-        SfxEvent::Attack(CharacterAbilityType::BasicMelee, ToolKind::Axe)
-    );
-}
-
-#[test]
-fn matches_ability_stage() {
-    let loadout = LoadoutBuilder::empty()
-        .active_mainhand(Some(Item::new_from_asset_expect(
-            "common.items.weapons.sword.starter",
-        )))
-        .build();
-    let inventory = Inventory::new_with_loadout(loadout);
-
-    let result = CombatEventMapper::map_event(
-        &CharacterState::ComboMelee(states::combo_melee::Data {
-            static_data: states::combo_melee::StaticData {
-                num_stages: 1,
-                stage_data: vec![states::combo_melee::Stage {
-                    stage: 1,
-                    base_damage: 100.0,
-                    base_poise_damage: 100.0,
-                    damage_increase: 10.0,
-                    poise_damage_increase: 10.0,
-                    knockback: 10.0,
-                    range: 4.0,
-                    angle: 30.0,
-                    base_buildup_duration: Duration::from_millis(500),
-                    base_swing_duration: Duration::from_millis(200),
-                    hit_timing: 0.5,
-                    base_recover_duration: Duration::from_millis(400),
-                    forward_movement: 0.5,
-                    damage_kind: DamageKind::Slashing,
-                    damage_effect: None,
-                }],
-                initial_energy_gain: 0.0,
-                max_energy_gain: 100.0,
-                energy_increase: 20.0,
-                speed_increase: 0.05,
-                max_speed_increase: 0.8,
-                scales_from_combo: 2,
-                is_interruptible: true,
-                ori_modifier: 1.0,
-                ability_info: empty_ability_info(),
-            },
-            exhausted: false,
-            stage: 1,
-            timer: Duration::default(),
-            stage_section: states::utils::StageSection::Action,
-        }),
-        &PreviousEntityState {
-            event: SfxEvent::Idle,
-            time: Instant::now(),
-            weapon_drawn: true,
-        },
-        &inventory,
-    );
-
-    assert_eq!(
-        result,
-        SfxEvent::Attack(
-            CharacterAbilityType::ComboMelee(states::utils::StageSection::Action, 1),
-            ToolKind::Sword
-        )
-    );
-}
-
-#[test]
-fn ignores_different_ability_stage() {
-    let loadout = LoadoutBuilder::empty()
-        .active_mainhand(Some(Item::new_from_asset_expect(
-            "common.items.weapons.axe.starter_axe",
-        )))
-        .build();
-    let inventory = Inventory::new_with_loadout(loadout);
-
-    let result = CombatEventMapper::map_event(
-        &CharacterState::ComboMelee(states::combo_melee::Data {
-            static_data: states::combo_melee::StaticData {
-                num_stages: 1,
-                stage_data: vec![states::combo_melee::Stage {
-                    stage: 1,
-                    base_damage: 100.0,
-                    base_poise_damage: 100.0,
-                    damage_increase: 100.0,
-                    poise_damage_increase: 10.0,
-                    knockback: 10.0,
-                    range: 4.0,
-                    angle: 30.0,
-                    base_buildup_duration: Duration::from_millis(500),
-                    base_swing_duration: Duration::from_millis(200),
-                    hit_timing: 0.5,
-                    base_recover_duration: Duration::from_millis(400),
-                    forward_movement: 0.5,
-                    damage_kind: DamageKind::Slashing,
-                    damage_effect: None,
-                }],
-                initial_energy_gain: 0.0,
-                max_energy_gain: 100.0,
-                energy_increase: 20.0,
-                speed_increase: 0.05,
-                max_speed_increase: 0.8,
-                scales_from_combo: 2,
-                is_interruptible: true,
-                ori_modifier: 1.0,
-                ability_info: empty_ability_info(),
-            },
-            exhausted: false,
-            stage: 1,
-            timer: Duration::default(),
-            stage_section: states::utils::StageSection::Action,
-        }),
-        &PreviousEntityState {
-            event: SfxEvent::Idle,
-            time: Instant::now(),
-            weapon_drawn: true,
-        },
-        &inventory,
-    );
-
-    assert_ne!(
-        result,
-        SfxEvent::Attack(
-            CharacterAbilityType::ComboMelee(states::utils::StageSection::Action, 2),
-            ToolKind::Sword
-        )
-    );
-}
-
-fn empty_ability_info() -> states::utils::AbilityInfo {
-    states::utils::AbilityInfo {
-        tool: None,
-        hand: None,
-        input: InputKind::Primary,
-        input_attr: None,
-    }
-}
diff --git a/voxygen/src/audio/sfx/event_mapper/mod.rs b/voxygen/src/audio/sfx/event_mapper/mod.rs
deleted file mode 100644
index 844c472ad9..0000000000
--- a/voxygen/src/audio/sfx/event_mapper/mod.rs
+++ /dev/null
@@ -1,72 +0,0 @@
-mod block;
-mod campfire;
-mod combat;
-mod movement;
-
-use client::Client;
-use common::terrain::TerrainChunk;
-use common_state::State;
-
-use block::BlockEventMapper;
-use campfire::CampfireEventMapper;
-use combat::CombatEventMapper;
-use movement::MovementEventMapper;
-
-use super::SfxTriggers;
-use crate::{
-    scene::{Camera, Terrain},
-    AudioFrontend,
-};
-
-trait EventMapper {
-    fn maintain(
-        &mut self,
-        audio: &mut AudioFrontend,
-        state: &State,
-        player_entity: specs::Entity,
-        camera: &Camera,
-        triggers: &SfxTriggers,
-        terrain: &Terrain<TerrainChunk>,
-        client: &Client,
-    );
-}
-
-pub struct SfxEventMapper {
-    mappers: Vec<Box<dyn EventMapper>>,
-}
-
-impl SfxEventMapper {
-    pub fn new() -> Self {
-        Self {
-            mappers: vec![
-                Box::new(CombatEventMapper::new()),
-                Box::new(MovementEventMapper::new()),
-                Box::new(BlockEventMapper::new()),
-                Box::new(CampfireEventMapper::new()),
-            ],
-        }
-    }
-
-    pub fn maintain(
-        &mut self,
-        audio: &mut AudioFrontend,
-        state: &State,
-        player_entity: specs::Entity,
-        camera: &Camera,
-        triggers: &SfxTriggers,
-        terrain: &Terrain<TerrainChunk>,
-        client: &Client,
-    ) {
-        for mapper in &mut self.mappers {
-            mapper.maintain(
-                audio,
-                state,
-                player_entity,
-                camera,
-                triggers,
-                terrain,
-                client,
-            );
-        }
-    }
-}
diff --git a/voxygen/src/audio/sfx/event_mapper/movement/tests.rs b/voxygen/src/audio/sfx/event_mapper/movement/tests.rs
deleted file mode 100644
index 8a31168fc9..0000000000
--- a/voxygen/src/audio/sfx/event_mapper/movement/tests.rs
+++ /dev/null
@@ -1,358 +0,0 @@
-use super::*;
-use crate::audio::sfx::SfxEvent;
-use common::{
-    comp::{
-        bird_large, humanoid, quadruped_medium, quadruped_small, Body, CharacterState, InputKind,
-        Ori, PhysicsState,
-    },
-    states,
-    terrain::{Block, BlockKind},
-};
-use std::time::{Duration, Instant};
-
-#[test]
-fn no_item_config_no_emit() {
-    let previous_state = PreviousEntityState::default();
-    let result = MovementEventMapper::should_emit(&previous_state, None);
-
-    assert!(!result);
-}
-
-#[test]
-fn config_but_played_since_threshold_no_emit() {
-    let trigger_item = SfxTriggerItem {
-        files: vec![String::from("some.path.to.sfx.file")],
-        threshold: 1.0,
-    };
-
-    // Triggered a 'Run' 0 seconds ago
-    let previous_state = PreviousEntityState {
-        event: SfxEvent::Run(BlockKind::Grass),
-        time: Instant::now(),
-        on_ground: true,
-        in_water: false,
-        distance_travelled: 0.0,
-    };
-
-    let result = MovementEventMapper::should_emit(
-        &previous_state,
-        Some((&SfxEvent::Run(BlockKind::Grass), &trigger_item)),
-    );
-
-    assert!(!result);
-}
-
-#[test]
-fn config_and_not_played_since_threshold_emits() {
-    let trigger_item = SfxTriggerItem {
-        files: vec![String::from("some.path.to.sfx.file")],
-        threshold: 0.5,
-    };
-
-    let previous_state = PreviousEntityState {
-        event: SfxEvent::Idle,
-        time: Instant::now().checked_add(Duration::from_secs(1)).unwrap(),
-        on_ground: true,
-        in_water: false,
-        distance_travelled: 0.0,
-    };
-
-    let result = MovementEventMapper::should_emit(
-        &previous_state,
-        Some((&SfxEvent::Run(BlockKind::Grass), &trigger_item)),
-    );
-
-    assert!(result);
-}
-
-#[test]
-fn same_previous_event_elapsed_emits() {
-    let trigger_item = SfxTriggerItem {
-        files: vec![String::from("some.path.to.sfx.file")],
-        threshold: 0.5,
-    };
-
-    let previous_state = PreviousEntityState {
-        event: SfxEvent::Run(BlockKind::Grass),
-        time: Instant::now()
-            .checked_sub(Duration::from_millis(1800))
-            .unwrap(),
-        on_ground: true,
-        in_water: false,
-        distance_travelled: 2.0,
-    };
-
-    let result = MovementEventMapper::should_emit(
-        &previous_state,
-        Some((&SfxEvent::Run(BlockKind::Grass), &trigger_item)),
-    );
-
-    assert!(result);
-}
-
-#[test]
-fn maps_idle() {
-    let result = MovementEventMapper::map_movement_event(
-        &CharacterState::Idle(common::states::idle::Data { is_sneaking: false }),
-        &PhysicsState {
-            on_ground: Some(Block::empty()),
-            ..Default::default()
-        },
-        &PreviousEntityState {
-            event: SfxEvent::Idle,
-            time: Instant::now(),
-            on_ground: true,
-            in_water: false,
-            distance_travelled: 0.0,
-        },
-        Vec3::zero(),
-        BlockKind::Grass,
-    );
-
-    assert_eq!(result, SfxEvent::Idle);
-}
-
-#[test]
-fn maps_run_with_sufficient_velocity() {
-    let result = MovementEventMapper::map_movement_event(
-        &CharacterState::Idle(common::states::idle::Data { is_sneaking: false }),
-        &PhysicsState {
-            on_ground: Some(Block::empty()),
-            ..Default::default()
-        },
-        &PreviousEntityState {
-            event: SfxEvent::Idle,
-            time: Instant::now(),
-            on_ground: true,
-            in_water: false,
-            distance_travelled: 0.0,
-        },
-        Vec3::new(0.5, 0.8, 0.0),
-        BlockKind::Grass,
-    );
-
-    assert_eq!(result, SfxEvent::Run(BlockKind::Grass));
-}
-
-#[test]
-fn does_not_map_run_with_insufficient_velocity() {
-    let result = MovementEventMapper::map_movement_event(
-        &CharacterState::Idle(common::states::idle::Data { is_sneaking: false }),
-        &PhysicsState {
-            on_ground: Some(Block::empty()),
-            ..Default::default()
-        },
-        &PreviousEntityState {
-            event: SfxEvent::Idle,
-            time: Instant::now(),
-            on_ground: true,
-            in_water: false,
-            distance_travelled: 0.0,
-        },
-        Vec3::new(0.02, 0.0001, 0.0),
-        BlockKind::Grass,
-    );
-
-    assert_eq!(result, SfxEvent::Idle);
-}
-
-#[test]
-fn does_not_map_run_with_sufficient_velocity_but_not_on_ground() {
-    let result = MovementEventMapper::map_movement_event(
-        &CharacterState::Idle(common::states::idle::Data { is_sneaking: false }),
-        &Default::default(),
-        &PreviousEntityState {
-            event: SfxEvent::Idle,
-            time: Instant::now(),
-            on_ground: false,
-            in_water: false,
-            distance_travelled: 0.0,
-        },
-        Vec3::new(0.5, 0.8, 0.0),
-        BlockKind::Grass,
-    );
-
-    assert_eq!(result, SfxEvent::Idle);
-}
-
-#[test]
-fn maps_roll() {
-    let result = MovementEventMapper::map_movement_event(
-        &CharacterState::Roll(states::roll::Data {
-            static_data: states::roll::StaticData {
-                buildup_duration: Duration::default(),
-                movement_duration: Duration::default(),
-                recover_duration: Duration::default(),
-                roll_strength: 0.0,
-                immune_melee: false,
-                ability_info: empty_ability_info(),
-            },
-            timer: Duration::default(),
-            stage_section: states::utils::StageSection::Buildup,
-            was_wielded: true,
-            is_sneaking: false,
-            was_combo: None,
-        }),
-        &PhysicsState {
-            on_ground: Some(Block::empty()),
-            ..Default::default()
-        },
-        &PreviousEntityState {
-            event: SfxEvent::Run(BlockKind::Grass),
-            time: Instant::now(),
-            on_ground: true,
-            in_water: false,
-            distance_travelled: 0.0,
-        },
-        Vec3::new(0.5, 0.5, 0.0),
-        BlockKind::Grass,
-    );
-
-    assert_eq!(result, SfxEvent::Roll);
-}
-
-#[test]
-fn maps_land_on_ground_to_run() {
-    let result = MovementEventMapper::map_movement_event(
-        &CharacterState::Idle(common::states::idle::Data { is_sneaking: false }),
-        &PhysicsState {
-            on_ground: Some(Block::empty()),
-            ..Default::default()
-        },
-        &PreviousEntityState {
-            event: SfxEvent::Idle,
-            time: Instant::now(),
-            on_ground: false,
-            in_water: false,
-            distance_travelled: 0.0,
-        },
-        Vec3::zero(),
-        BlockKind::Grass,
-    );
-
-    assert_eq!(result, SfxEvent::Run(BlockKind::Grass));
-}
-
-#[test]
-fn maps_glider_open() {
-    let result = MovementEventMapper::map_movement_event(
-        &CharacterState::Glide(states::glide::Data::new(10.0, 1.0, Ori::default())),
-        &Default::default(),
-        &PreviousEntityState {
-            event: SfxEvent::Jump,
-            time: Instant::now(),
-            on_ground: false,
-            in_water: false,
-            distance_travelled: 0.0,
-        },
-        Vec3::zero(),
-        BlockKind::Grass,
-    );
-
-    assert_eq!(result, SfxEvent::GliderOpen);
-}
-
-#[test]
-fn maps_glide() {
-    let result = MovementEventMapper::map_movement_event(
-        &CharacterState::Glide(states::glide::Data::new(10.0, 1.0, Ori::default())),
-        &Default::default(),
-        &PreviousEntityState {
-            event: SfxEvent::Glide,
-            time: Instant::now(),
-            on_ground: false,
-            in_water: false,
-            distance_travelled: 0.0,
-        },
-        Vec3::zero(),
-        BlockKind::Grass,
-    );
-
-    assert_eq!(result, SfxEvent::Glide);
-}
-
-#[test]
-fn maps_glider_close_when_closing_mid_flight() {
-    let result = MovementEventMapper::map_movement_event(
-        &CharacterState::Idle(common::states::idle::Data { is_sneaking: false }),
-        &Default::default(),
-        &PreviousEntityState {
-            event: SfxEvent::Glide,
-            time: Instant::now(),
-            on_ground: false,
-            in_water: false,
-            distance_travelled: 0.0,
-        },
-        Vec3::zero(),
-        BlockKind::Grass,
-    );
-
-    assert_eq!(result, SfxEvent::GliderClose);
-}
-
-#[test]
-#[ignore]
-fn maps_glider_close_when_landing() {
-    let result = MovementEventMapper::map_movement_event(
-        &CharacterState::Idle(common::states::idle::Data { is_sneaking: false }),
-        &PhysicsState {
-            on_ground: Some(Block::empty()),
-            ..Default::default()
-        },
-        &PreviousEntityState {
-            event: SfxEvent::Glide,
-            time: Instant::now(),
-            on_ground: false,
-            in_water: false,
-            distance_travelled: 0.0,
-        },
-        Vec3::zero(),
-        BlockKind::Grass,
-    );
-
-    assert_eq!(result, SfxEvent::GliderClose);
-}
-
-#[test]
-fn maps_quadrupeds_running() {
-    let result = MovementEventMapper::map_non_humanoid_movement_event(
-        &PhysicsState {
-            on_ground: Some(Block::empty()),
-            ..Default::default()
-        },
-        Vec3::new(0.5, 0.8, 0.0),
-        BlockKind::Grass,
-    );
-
-    assert_eq!(result, SfxEvent::Run(BlockKind::Grass));
-}
-
-#[test]
-fn determines_relative_volumes() {
-    let human =
-        MovementEventMapper::get_volume_for_body_type(&Body::Humanoid(humanoid::Body::random()));
-
-    let quadruped_medium = MovementEventMapper::get_volume_for_body_type(&Body::QuadrupedMedium(
-        quadruped_medium::Body::random(),
-    ));
-
-    let quadruped_small = MovementEventMapper::get_volume_for_body_type(&Body::QuadrupedSmall(
-        quadruped_small::Body::random(),
-    ));
-
-    let bird_large =
-        MovementEventMapper::get_volume_for_body_type(&Body::BirdLarge(bird_large::Body::random()));
-
-    assert!(quadruped_medium < human);
-    assert!(quadruped_small < quadruped_medium);
-    assert!(bird_large < quadruped_small);
-}
-
-fn empty_ability_info() -> states::utils::AbilityInfo {
-    states::utils::AbilityInfo {
-        tool: None,
-        hand: None,
-        input: InputKind::Primary,
-        input_attr: None,
-    }
-}