From 06f3e0403495a3719c85183541d220ee7ff5adbf Mon Sep 17 00:00:00 2001
From: Sam <samuelkeiffer@gmail.com>
Date: Tue, 21 Sep 2021 22:25:14 -0400
Subject: [PATCH 01/14] Changed ItemDrop to use LootSpec

---
 assets/common/entity/village/dummy.ron   |  2 +-
 common/src/comp/inventory/item/mod.rs    | 14 ++++-
 common/src/event.rs                      |  4 +-
 common/src/generation.rs                 | 68 +++++-----------------
 common/src/lottery.rs                    | 72 +++++++++++++-----------
 common/state/src/state.rs                |  2 +-
 server/src/events/entity_creation.rs     |  5 +-
 server/src/events/entity_manipulation.rs | 16 +++---
 server/src/sys/terrain.rs                |  3 +-
 9 files changed, 82 insertions(+), 104 deletions(-)

diff --git a/assets/common/entity/village/dummy.ron b/assets/common/entity/village/dummy.ron
index 96e7b9d467..c62a515143 100644
--- a/assets/common/entity/village/dummy.ron
+++ b/assets/common/entity/village/dummy.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: Exact(Object(TrainingDummy)),
     alignment: Alignment(Passive),
 
-    loot: Uninit,
+    loot: None,
 
     hands: Uninit,
 
diff --git a/common/src/comp/inventory/item/mod.rs b/common/src/comp/inventory/item/mod.rs
index a432977fcd..b262a64420 100644
--- a/common/src/comp/inventory/item/mod.rs
+++ b/common/src/comp/inventory/item/mod.rs
@@ -13,6 +13,7 @@ use crate::{
         CharacterAbility,
     },
     effect::Effect,
+    lottery::LootSpec,
     recipe::RecipeInput,
     terrain::Block,
 };
@@ -862,10 +863,17 @@ impl Component for Item {
     type Storage = DerefFlaggedStorage<Self, IdvStorage<Self>>;
 }
 
-#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
-pub struct ItemDrop(pub Item);
+// #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+// pub struct ItemDrop<T: AsRef<str>>(pub LootSpec<T>);
 
-impl Component for ItemDrop {
+// impl<T: 'static + Send + Sync + AsRef<str>> Component for ItemDrop<T> {
+//     type Storage = IdvStorage<Self>;
+// }
+
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+pub struct ItemDrop<T: AsRef<str>>(pub LootSpec<T>);
+
+impl Component for ItemDrop<String> {
     type Storage = IdvStorage<Self>;
 }
 
diff --git a/common/src/event.rs b/common/src/event.rs
index d3a22423d8..e271d4000d 100644
--- a/common/src/event.rs
+++ b/common/src/event.rs
@@ -4,9 +4,9 @@ use crate::{
         self,
         agent::Sound,
         invite::{InviteKind, InviteResponse},
-        item::Item,
         DisconnectReason, Ori, Pos,
     },
+    lottery::LootSpec,
     outcome::Outcome,
     rtsim::RtSimEntity,
     terrain::SpriteKind,
@@ -134,7 +134,7 @@ pub enum ServerEvent {
         alignment: comp::Alignment,
         scale: comp::Scale,
         anchor: Option<comp::Anchor>,
-        drop_item: Option<Item>,
+        drop_item: Option<LootSpec<String>>,
         rtsim_entity: Option<RtSimEntity>,
         projectile: Option<comp::Projectile>,
     },
diff --git a/common/src/generation.rs b/common/src/generation.rs
index 837b8a2d83..b4686a510f 100644
--- a/common/src/generation.rs
+++ b/common/src/generation.rs
@@ -5,7 +5,7 @@ use crate::{
         inventory::loadout_builder::{ItemSpec, LoadoutBuilder},
         Alignment, Body, Item,
     },
-    lottery::{LootSpec, Lottery},
+    lottery::LootSpec,
     npc::{self, NPC_NAMES},
     trade,
     trade::SiteInformation,
@@ -37,17 +37,6 @@ impl Default for AlignmentMark {
     fn default() -> Self { Self::Alignment(Alignment::Wild) }
 }
 
-#[derive(Debug, Deserialize, Clone)]
-enum LootKind {
-    Item(String),
-    LootTable(String),
-    Uninit,
-}
-
-impl Default for LootKind {
-    fn default() -> Self { Self::Uninit }
-}
-
 #[derive(Debug, Deserialize, Clone)]
 enum Hands {
     TwoHanded(ItemSpec),
@@ -115,10 +104,8 @@ pub struct EntityConfig {
     alignment: AlignmentMark,
 
     /// Loot
-    /// Can be Item (with asset_specifier for item)
-    /// or LootTable (with asset_specifier for loot table)
-    /// or Uninit (means it should be specified something in the code)
-    loot: LootKind,
+    /// See LootSpec in lottery
+    loot: LootSpec<String>,
 
     /// Hands:
     /// - TwoHanded(ItemSpec) for one 2h or 1h weapon,
@@ -173,7 +160,7 @@ pub struct EntityInfo {
     pub scale: f32,
     // TODO: Properly give NPCs skills
     pub health_scaling: Option<u16>,
-    pub loot_drop: Option<Item>,
+    pub loot_drop: Option<LootSpec<String>>,
     pub loadout_asset: Option<String>,
     pub make_loadout: Option<fn(LoadoutBuilder, Option<&trade::SiteInformation>) -> LoadoutBuilder>,
     pub skillset_asset: Option<String>,
@@ -253,21 +240,7 @@ impl EntityInfo {
             self = self.with_alignment(alignment);
         }
 
-        match loot {
-            LootKind::Item(asset) => {
-                if let Ok(item) = Item::new_from_asset(&asset) {
-                    self = self.with_loot_drop(item);
-                }
-            },
-            LootKind::LootTable(asset) => {
-                if let Ok(table) = Lottery::<LootSpec<String>>::load(&asset) {
-                    if let Some(drop) = table.read().choose().to_item() {
-                        self = self.with_loot_drop(drop);
-                    }
-                }
-            },
-            LootKind::Uninit => {},
-        }
+        self = self.with_loot_drop(loot);
 
         let rng = &mut rand::thread_rng();
         match hands {
@@ -363,7 +336,7 @@ impl EntityInfo {
         self
     }
 
-    pub fn with_loot_drop(mut self, loot_drop: Item) -> Self {
+    pub fn with_loot_drop(mut self, loot_drop: LootSpec<String>) -> Self {
         self.loot_drop = Some(loot_drop);
         self
     }
@@ -469,6 +442,7 @@ mod tests {
         }
     }
 
+    #[cfg(test)]
     fn validate_hands(hands: Hands, _config_asset: &str) {
         match hands {
             Hands::TwoHanded(main_tool) => {
@@ -486,6 +460,7 @@ mod tests {
         }
     }
 
+    #[cfg(test)]
     fn validate_body_and_name(body: BodyBuilder, name: NameKind, config_asset: &str) {
         match body {
             BodyBuilder::RandomWith(string) => {
@@ -511,30 +486,13 @@ mod tests {
         }
     }
 
-    fn validate_loot(loot: LootKind, config_asset: &str) {
-        match loot {
-            LootKind::Item(asset) => {
-                if let Err(e) = Item::new_from_asset(&asset) {
-                    panic!(
-                        "Unable to parse loot item ({}) in {}. Err: {:?}",
-                        asset, config_asset, e
-                    );
-                }
-            },
-            LootKind::LootTable(asset) => {
-                // we need to just load it check if it exists,
-                // because all loot tables are tested in Lottery module
-                if let Err(e) = Lottery::<LootSpec<String>>::load(&asset) {
-                    panic!(
-                        "Unable to parse loot table ({}) in {}. Err: {:?}",
-                        asset, config_asset, e
-                    );
-                }
-            },
-            LootKind::Uninit => {},
-        }
+    #[cfg(test)]
+    fn validate_loot(loot: LootSpec<String>, _config_asset: &str) {
+        use crate::lottery;
+        lottery::tests::validate_loot_spec(&loot);
     }
 
+    #[cfg(test)]
     fn validate_meta(meta: Vec<Meta>, config_asset: &str) {
         let mut meta_counter = HashMap::new();
         for field in meta {
diff --git a/common/src/lottery.rs b/common/src/lottery.rs
index 6e5d103641..383d1c3b30 100644
--- a/common/src/lottery.rs
+++ b/common/src/lottery.rs
@@ -114,44 +114,52 @@ impl<T: AsRef<str>> LootSpec<T> {
     }
 }
 
+impl Default for LootSpec<String> {
+    fn default() -> Self { Self::None }
+}
+
 #[cfg(test)]
-mod tests {
+pub mod tests {
     use super::*;
     use crate::{assets, comp::Item};
 
+    #[cfg(test)]
+    pub fn validate_loot_spec(item: &LootSpec<String>) {
+        match item {
+            LootSpec::Item(item) => {
+                Item::new_from_asset_expect(item);
+            },
+            LootSpec::ItemQuantity(item, lower, upper) => {
+                assert!(
+                    *lower > 0,
+                    "Lower quantity must be more than 0. It is {}.",
+                    lower
+                );
+                assert!(
+                    upper >= lower,
+                    "Upper quantity must be at least the value of lower quantity. Upper value: \
+                     {}, low value: {}.",
+                    upper,
+                    lower
+                );
+                Item::new_from_asset_expect(item);
+            },
+            LootSpec::LootTable(loot_table) => {
+                let loot_table = Lottery::<LootSpec<String>>::load_expect_cloned(loot_table);
+                validate_table_contents(loot_table);
+            },
+            LootSpec::None => {},
+        }
+    }
+
+    fn validate_table_contents(table: Lottery<LootSpec<String>>) {
+        for (_, item) in table.iter() {
+            validate_loot_spec(item);
+        }
+    }
+
     #[test]
     fn test_loot_tables() {
-        fn validate_table_contents(table: Lottery<LootSpec<String>>) {
-            for (_, item) in table.iter() {
-                match item {
-                    LootSpec::Item(item) => {
-                        Item::new_from_asset_expect(item);
-                    },
-                    LootSpec::ItemQuantity(item, lower, upper) => {
-                        assert!(
-                            *lower > 0,
-                            "Lower quantity must be more than 0. It is {}.",
-                            lower
-                        );
-                        assert!(
-                            upper >= lower,
-                            "Upper quantity must be at least the value of lower quantity. Upper \
-                             value: {}, low value: {}.",
-                            upper,
-                            lower
-                        );
-                        Item::new_from_asset_expect(item);
-                    },
-                    LootSpec::LootTable(loot_table) => {
-                        let loot_table =
-                            Lottery::<LootSpec<String>>::load_expect_cloned(loot_table);
-                        validate_table_contents(loot_table);
-                    },
-                    LootSpec::None => {},
-                }
-            }
-        }
-
         let loot_tables =
             assets::read_expect_dir::<Lottery<LootSpec<String>>>("common.loot_tables", true);
         for loot_table in loot_tables {
diff --git a/common/state/src/state.rs b/common/state/src/state.rs
index 599d6013d4..141fc82d1b 100644
--- a/common/state/src/state.rs
+++ b/common/state/src/state.rs
@@ -189,7 +189,7 @@ impl State {
         ecs.register::<comp::Waypoint>();
         ecs.register::<comp::Projectile>();
         ecs.register::<comp::Melee>();
-        ecs.register::<comp::ItemDrop>();
+        ecs.register::<comp::ItemDrop<String>>();
         ecs.register::<comp::ChatMode>();
         ecs.register::<comp::Faction>();
         ecs.register::<comp::invite::Invite>();
diff --git a/server/src/events/entity_creation.rs b/server/src/events/entity_creation.rs
index 43294d0dff..16243b71c8 100644
--- a/server/src/events/entity_creation.rs
+++ b/server/src/events/entity_creation.rs
@@ -8,10 +8,11 @@ use common::{
         beam,
         buff::{BuffCategory, BuffData, BuffKind, BuffSource},
         inventory::loadout::Loadout,
-        shockwave, Agent, Alignment, Anchor, Body, Health, Inventory, Item, ItemDrop, LightEmitter,
+        shockwave, Agent, Alignment, Anchor, Body, Health, Inventory, ItemDrop, LightEmitter,
         Object, Ori, PidController, Poise, Pos, Projectile, Scale, SkillSet, Stats, Vel,
         WaypointArea,
     },
+    lottery::LootSpec,
     outcome::Outcome,
     rtsim::RtSimEntity,
     uid::Uid,
@@ -62,7 +63,7 @@ pub fn handle_create_npc(
     agent: impl Into<Option<Agent>>,
     alignment: Alignment,
     scale: Scale,
-    drop_item: Option<Item>,
+    drop_item: Option<LootSpec<String>>,
     home_chunk: Option<Anchor>,
     rtsim_entity: Option<RtSimEntity>,
     projectile: Option<Projectile>,
diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs
index c332c5558c..39f248b463 100644
--- a/server/src/events/entity_manipulation.rs
+++ b/server/src/events/entity_manipulation.rs
@@ -354,7 +354,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, last_change: Healt
 
         // Decide for a loot drop before turning into a lootbag
         let old_body = state.ecs().write_storage::<Body>().remove(entity);
-        let lottery = || {
+        let _ = || {
             Lottery::<LootSpec<String>>::load_expect(match old_body {
                 Some(common::comp::Body::Humanoid(_)) => "common.loot_tables.creature.humanoid",
                 Some(common::comp::Body::QuadrupedSmall(quadruped_small)) => {
@@ -503,13 +503,15 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, last_change: Healt
             })
         };
 
-        if let Some(item) = {
-            let mut item_drops = state.ecs().write_storage::<comp::ItemDrop>();
-            item_drops.remove(entity).map_or_else(
-                || lottery().read().choose().to_item(),
-                |item_drop| Some(item_drop.0),
+        let loot_spec = {
+            let mut item_drop = state.ecs().write_storage::<comp::ItemDrop<String>>();
+            item_drop.remove(entity).map_or_else(
+                || LootSpec::LootTable("common.loot_tables.fallback".to_string()),
+                |item| item.0,
             )
-        } {
+        };
+
+        if let Some(item) = loot_spec.to_item() {
             let pos = state.ecs().read_storage::<comp::Pos>().get(entity).cloned();
             let vel = state.ecs().read_storage::<comp::Vel>().get(entity).cloned();
             if let Some(pos) = pos {
diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs
index 850a48001a..90a2534eeb 100644
--- a/server/src/sys/terrain.rs
+++ b/server/src/sys/terrain.rs
@@ -13,6 +13,7 @@ use common::{
     comp::{self, agent, bird_medium, BehaviorCapability, ForceUpdate, Pos, Waypoint},
     event::{EventBus, ServerEvent},
     generation::EntityInfo,
+    lottery::LootSpec,
     resources::Time,
     terrain::TerrainGrid,
     LoadoutBuilder, SkillSetBuilder,
@@ -357,7 +358,7 @@ pub enum NpcData {
         body: comp::Body,
         alignment: comp::Alignment,
         scale: comp::Scale,
-        drop_item: Option<comp::Item>,
+        drop_item: Option<LootSpec<String>>,
     },
     Waypoint(Vec3<f32>),
 }

From b53643e12ab2fdd4bb9b74b6e011f4ac8a22c1b3 Mon Sep 17 00:00:00 2001
From: juliancoffee <lightdarkdaughter@gmail.com>
Date: Wed, 22 Sep 2021 20:16:10 +0300
Subject: [PATCH 02/14] Hardened loot table handling

- Rename LootSpec::None to LootSpec::Nothing to not confuse with Option
- Warn on invalid item paths in loot tables
---
 .../loot_tables/dungeon/tier-0/enemy.ron      |  2 +-
 .../loot_tables/dungeon/tier-1/enemy.ron      |  2 +-
 .../loot_tables/dungeon/tier-2/enemy.ron      |  2 +-
 .../loot_tables/dungeon/tier-3/enemy.ron      |  2 +-
 .../loot_tables/dungeon/tier-4/enemy.ron      |  2 +-
 .../loot_tables/dungeon/tier-5/minion.ron     |  2 +-
 assets/common/loot_tables/nothing.ron         |  2 +-
 common/src/comp/inventory/trade_pricing.rs    |  2 +-
 common/src/lottery.rs                         | 36 ++++++++++++-------
 9 files changed, 31 insertions(+), 21 deletions(-)

diff --git a/assets/common/loot_tables/dungeon/tier-0/enemy.ron b/assets/common/loot_tables/dungeon/tier-0/enemy.ron
index 9ca703569d..7bbde49d1c 100644
--- a/assets/common/loot_tables/dungeon/tier-0/enemy.ron
+++ b/assets/common/loot_tables/dungeon/tier-0/enemy.ron
@@ -4,5 +4,5 @@
     // Food
     (1.0, LootTable("common.loot_tables.food.wild_ingredients")),
     // Nothing
-    (2.0, None),
+    (2.0, Nothing),
 ]
diff --git a/assets/common/loot_tables/dungeon/tier-1/enemy.ron b/assets/common/loot_tables/dungeon/tier-1/enemy.ron
index ec12216fd1..3ea015efbf 100644
--- a/assets/common/loot_tables/dungeon/tier-1/enemy.ron
+++ b/assets/common/loot_tables/dungeon/tier-1/enemy.ron
@@ -4,7 +4,7 @@
     // Food
     (1.0, LootTable("common.loot_tables.food.wild_ingredients")),
     // Nothing
-    (2.0, None),
+    (2.0, Nothing),
     // Placeholder Drop Location
     (1.0, Item("common.items.crafting_ing.sticky_thread")),
 ]
diff --git a/assets/common/loot_tables/dungeon/tier-2/enemy.ron b/assets/common/loot_tables/dungeon/tier-2/enemy.ron
index c1368adc5d..9df44a3959 100644
--- a/assets/common/loot_tables/dungeon/tier-2/enemy.ron
+++ b/assets/common/loot_tables/dungeon/tier-2/enemy.ron
@@ -4,5 +4,5 @@
     // Food
     (1.0, LootTable("common.loot_tables.food.wild_ingredients")),
     // Nothing
-    (2.0, None),
+    (2.0, Nothing),
 ]
diff --git a/assets/common/loot_tables/dungeon/tier-3/enemy.ron b/assets/common/loot_tables/dungeon/tier-3/enemy.ron
index 6ef2e26870..fb51a5f9be 100644
--- a/assets/common/loot_tables/dungeon/tier-3/enemy.ron
+++ b/assets/common/loot_tables/dungeon/tier-3/enemy.ron
@@ -4,5 +4,5 @@
     // Food
     (1.0, LootTable("common.loot_tables.food.prepared")),
     // Nothing
-    (2.0, None),
+    (2.0, Nothing),
 ]
diff --git a/assets/common/loot_tables/dungeon/tier-4/enemy.ron b/assets/common/loot_tables/dungeon/tier-4/enemy.ron
index c0b5dff2df..19e8adf6aa 100644
--- a/assets/common/loot_tables/dungeon/tier-4/enemy.ron
+++ b/assets/common/loot_tables/dungeon/tier-4/enemy.ron
@@ -4,5 +4,5 @@
     // Food
     (1.0, LootTable("common.loot_tables.food.prepared")),
     // Nothing
-    (2.0, None),
+    (2.0, Nothing),
 ]
diff --git a/assets/common/loot_tables/dungeon/tier-5/minion.ron b/assets/common/loot_tables/dungeon/tier-5/minion.ron
index 5f4de1106a..eefc86528f 100644
--- a/assets/common/loot_tables/dungeon/tier-5/minion.ron
+++ b/assets/common/loot_tables/dungeon/tier-5/minion.ron
@@ -2,7 +2,7 @@
     // Currency
     (50.0, ItemQuantity("common.items.utility.coins", 50, 100)),
     // Nothing
-    (50.0, None),
+    (50.0, Nothing),
     // Special
     (1.0, Item("common.items.food.spore_corruption")),
 ]
diff --git a/assets/common/loot_tables/nothing.ron b/assets/common/loot_tables/nothing.ron
index 613a16e6e8..81cb0adf70 100644
--- a/assets/common/loot_tables/nothing.ron
+++ b/assets/common/loot_tables/nothing.ron
@@ -1,4 +1,4 @@
 [
     // No loot is dropped
-    (1.0, None),
+    (1.0, Nothing),
 ]
diff --git a/common/src/comp/inventory/trade_pricing.rs b/common/src/comp/inventory/trade_pricing.rs
index c7619149ed..45b2ab2631 100644
--- a/common/src/comp/inventory/trade_pricing.rs
+++ b/common/src/comp/inventory/trade_pricing.rs
@@ -113,7 +113,7 @@ impl From<Vec<(f32, LootSpec<String>)>> for ProbabilityFile {
                             .collect::<Vec<_>>()
                             .into_iter()
                     },
-                    LootSpec::None => Vec::new().into_iter(),
+                    LootSpec::Nothing => Vec::new().into_iter(),
                 })
                 .collect(),
         }
diff --git a/common/src/lottery.rs b/common/src/lottery.rs
index 383d1c3b30..46d5b5cc9a 100644
--- a/common/src/lottery.rs
+++ b/common/src/lottery.rs
@@ -85,37 +85,47 @@ pub enum LootSpec<T: AsRef<str>> {
     /// Loot table
     LootTable(T),
     /// No loot given
-    None,
+    Nothing,
 }
 
 impl<T: AsRef<str>> LootSpec<T> {
     pub fn to_item(&self) -> Option<Item> {
         match self {
-            Self::Item(item) => Item::new_from_asset(item.as_ref()).ok(),
+            Self::Item(item) => Item::new_from_asset(item.as_ref()).map_or_else(
+                |e| {
+                    warn!(?e, "Invalid item path");
+                    None
+                },
+                |i| Some(i),
+            ),
             Self::ItemQuantity(item, lower, upper) => {
                 let range = *lower..=*upper;
                 let quantity = thread_rng().gen_range(range);
-                if let Ok(mut item) = Item::new_from_asset(item.as_ref()) {
-                    // TODO: Handle multiple of an item that is unstackable
-                    if item.set_amount(quantity).is_err() {
-                        warn!("Tried to set quantity on non stackable item");
-                    }
-                    Some(item)
-                } else {
-                    None
+                match Item::new_from_asset(item.as_ref()) {
+                    Ok(mut item) => {
+                        // TODO: Handle multiple of an item that is unstackable
+                        if item.set_amount(quantity).is_err() {
+                            warn!("Tried to set quantity on non stackable item");
+                        }
+                        Some(item)
+                    },
+                    Err(e) => {
+                        warn!(?e, "Invalid item path");
+                        None
+                    },
                 }
             },
             Self::LootTable(table) => Lottery::<LootSpec<String>>::load_expect(table.as_ref())
                 .read()
                 .choose()
                 .to_item(),
-            Self::None => None,
+            Self::Nothing => None,
         }
     }
 }
 
 impl Default for LootSpec<String> {
-    fn default() -> Self { Self::None }
+    fn default() -> Self { Self::Nothing }
 }
 
 #[cfg(test)]
@@ -148,7 +158,7 @@ pub mod tests {
                 let loot_table = Lottery::<LootSpec<String>>::load_expect_cloned(loot_table);
                 validate_table_contents(loot_table);
             },
-            LootSpec::None => {},
+            LootSpec::Nothing => {},
         }
     }
 

From 38c004d4948f97c56130849c4bcbdb8bd00b67b4 Mon Sep 17 00:00:00 2001
From: juliancoffee <lightdarkdaughter@gmail.com>
Date: Wed, 22 Sep 2021 22:53:11 +0300
Subject: [PATCH 03/14] Move loot tables to entity configs

---
 assets/common/entity/village/guard.ron        |   2 +-
 assets/common/entity/village/merchant.ron     |   4 +-
 assets/common/entity/village/villager.ron     |   2 +-
 .../entity/wild/aggressive/alligator.ron      |   2 +-
 .../entity/wild/aggressive/archaeos.ron       |   2 +-
 assets/common/entity/wild/aggressive/asp.ron  |   2 +-
 .../common/entity/wild/aggressive/batfox.ron  |   2 +-
 assets/common/entity/wild/aggressive/bear.ron |   2 +-
 .../entity/wild/aggressive/bonerattler.ron    |   2 +-
 .../entity/wild/aggressive/cockatrice.ron     |   2 +-
 .../entity/wild/aggressive/crocodile.ron      |   2 +-
 .../common/entity/wild/aggressive/cyclope.ron |   2 +-
 .../entity/wild/aggressive/deadwood.ron       |   2 +-
 .../entity/wild/aggressive/dodarock.ron       |   2 +-
 .../entity/wild/aggressive/dreadhorn.ron      |   2 +-
 .../entity/wild/aggressive/frostfang.ron      |   2 +-
 .../common/entity/wild/aggressive/grolgar.ron |   2 +-
 .../common/entity/wild/aggressive/hakulaq.ron |   2 +-
 .../common/entity/wild/aggressive/hyena.ron   |   2 +-
 .../common/entity/wild/aggressive/icepike.ron |   2 +-
 .../entity/wild/aggressive/lavadrake.ron      |   2 +-
 assets/common/entity/wild/aggressive/lion.ron |   2 +-
 .../common/entity/wild/aggressive/mammoth.ron |   2 +-
 .../entity/wild/aggressive/maneater.ron       |   2 +-
 .../entity/wild/aggressive/mighty_saurok.ron  |   2 +-
 .../common/entity/wild/aggressive/monitor.ron |   2 +-
 .../entity/wild/aggressive/mountain_troll.ron |   2 +-
 .../common/entity/wild/aggressive/ngoubou.ron |   2 +-
 .../common/entity/wild/aggressive/ntouka.ron  |   2 +-
 .../entity/wild/aggressive/occult_saurok.ron  |   2 +-
 .../common/entity/wild/aggressive/odonto.ron  |   2 +-
 assets/common/entity/wild/aggressive/ogre.ron |   2 +-
 .../entity/wild/aggressive/rocksnapper.ron    |   2 +-
 .../entity/wild/aggressive/roshwalr.ron       |   2 +-
 .../entity/wild/aggressive/roshwalr_boss.ron  |   2 +-
 .../common/entity/wild/aggressive/saber.ron   |   2 +-
 .../entity/wild/aggressive/sand_raptor.ron    |   2 +-
 .../entity/wild/aggressive/sandshark.ron      |   2 +-
 .../entity/wild/aggressive/sly_saurok.ron     |   2 +-
 .../entity/wild/aggressive/snow_leopard.ron   |   2 +-
 .../entity/wild/aggressive/snow_raptor.ron    |   2 +-
 .../entity/wild/aggressive/sunlizard.ron      |   2 +-
 .../entity/wild/aggressive/swamp_troll.ron    |   2 +-
 .../entity/wild/aggressive/tarasque.ron       |   2 +-
 .../common/entity/wild/aggressive/tiger.ron   |   2 +-
 .../common/entity/wild/aggressive/wendigo.ron |   2 +-
 assets/common/entity/wild/aggressive/wolf.ron |   2 +-
 .../entity/wild/aggressive/wood_raptor.ron    |   2 +-
 assets/common/entity/wild/aggressive/yale.ron |   2 +-
 assets/common/entity/wild/peaceful/alpaca.ron |   2 +-
 .../common/entity/wild/peaceful/antelope.ron  |   2 +-
 .../entity/wild/peaceful/arctic_fox.ron       |   2 +-
 .../entity/wild/peaceful/arctic_hare.ron      |   2 +-
 .../common/entity/wild/peaceful/axolotl.ron   |   2 +-
 assets/common/entity/wild/peaceful/bear.ron   |   3 +-
 assets/common/entity/wild/peaceful/beaver.ron |   2 +-
 assets/common/entity/wild/peaceful/boar.ron   |   2 +-
 assets/common/entity/wild/peaceful/camel.ron  |   2 +-
 assets/common/entity/wild/peaceful/cat.ron    |   2 +-
 .../entity/wild/peaceful/catoblepas.ron       |   2 +-
 assets/common/entity/wild/peaceful/cattle.ron |   2 +-
 .../common/entity/wild/peaceful/chicken.ron   |   2 +-
 .../common/entity/wild/peaceful/clownfish.ron |   2 +-
 assets/common/entity/wild/peaceful/deer.ron   |   2 +-
 assets/common/entity/wild/peaceful/donkey.ron |   2 +-
 assets/common/entity/wild/peaceful/duck.ron   |   2 +-
 assets/common/entity/wild/peaceful/eagle.ron  |   2 +-
 .../entity/wild/peaceful/forest_fox.ron       |   2 +-
 assets/common/entity/wild/peaceful/frog.ron   |   2 +-
 .../common/entity/wild/peaceful/fungome.ron   |   2 +-
 assets/common/entity/wild/peaceful/gecko.ron  |   2 +-
 assets/common/entity/wild/peaceful/goat.ron   |   2 +-
 assets/common/entity/wild/peaceful/goose.ron  |   2 +-
 .../common/entity/wild/peaceful/highland.ron  |   2 +-
 .../common/entity/wild/peaceful/hirdrasil.ron |   2 +-
 .../common/entity/wild/peaceful/holladon.ron  |   2 +-
 assets/common/entity/wild/peaceful/horse.ron  |   2 +-
 .../common/entity/wild/peaceful/jackalope.ron |   2 +-
 assets/common/entity/wild/peaceful/kelpie.ron |   2 +-
 assets/common/entity/wild/peaceful/llama.ron  |   2 +-
 assets/common/entity/wild/peaceful/marlin.ron |   2 +-
 assets/common/entity/wild/peaceful/moose.ron  |   2 +-
 .../common/entity/wild/peaceful/mouflon.ron   |   2 +-
 assets/common/entity/wild/peaceful/owl.ron    |   2 +-
 .../common/entity/wild/peaceful/pangolin.ron  |   2 +-
 assets/common/entity/wild/peaceful/parrot.ron |   2 +-
 .../common/entity/wild/peaceful/peacock.ron   |   2 +-
 assets/common/entity/wild/peaceful/pig.ron    |   2 +-
 .../common/entity/wild/peaceful/piranha.ron   |   2 +-
 .../common/entity/wild/peaceful/porcupine.ron |   2 +-
 assets/common/entity/wild/peaceful/quokka.ron |   2 +-
 assets/common/entity/wild/peaceful/rabbit.ron |   2 +-
 .../common/entity/wild/peaceful/raccoon.ron   |   2 +-
 assets/common/entity/wild/peaceful/rat.ron    |   2 +-
 .../entity/wild/peaceful/river_salamander.ron |   2 +-
 .../common/entity/wild/peaceful/sand_hare.ron |   2 +-
 .../entity/wild/peaceful/sand_salamander.ron  |   2 +-
 assets/common/entity/wild/peaceful/sheep.ron  |   2 +-
 assets/common/entity/wild/peaceful/skunk.ron  |   2 +-
 .../common/entity/wild/peaceful/squirrel.ron  |   2 +-
 .../common/entity/wild/peaceful/tortoise.ron  |   2 +-
 .../common/entity/wild/peaceful/truffler.ron  |   2 +-
 assets/common/entity/wild/peaceful/turtle.ron |   2 +-
 .../common/entity/wild/peaceful/tuskram.ron   |   2 +-
 assets/common/entity/wild/peaceful/yak.ron    |   2 +-
 assets/common/entity/wild/peaceful/zebra.ron  |   2 +-
 server/src/events/entity_manipulation.rs      | 149 +-----------------
 server/src/rtsim/tick.rs                      |   2 +
 world/src/layer/mod.rs                        |   5 +-
 109 files changed, 115 insertions(+), 256 deletions(-)

diff --git a/assets/common/entity/village/guard.ron b/assets/common/entity/village/guard.ron
index 0b344ac502..1e4caa691e 100644
--- a/assets/common/entity/village/guard.ron
+++ b/assets/common/entity/village/guard.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("humanoid"),
     alignment: Alignment(Npc),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.humanoid"),
 
     hands: TwoHanded(Choice([
         (1.0, Some(Item("common.items.weapons.sword.cobalt-0"))),
diff --git a/assets/common/entity/village/merchant.ron b/assets/common/entity/village/merchant.ron
index d0632f737b..c20c0297bc 100644
--- a/assets/common/entity/village/merchant.ron
+++ b/assets/common/entity/village/merchant.ron
@@ -3,8 +3,8 @@ EntityConfig (
     body: RandomWith("humanoid"),
     alignment: Alignment(Npc),
 
-    // considering giving some gold/gems/materials?
-    loot: Uninit,
+    // TODO: consider giving some gold/gems/materials?
+    loot: LootTable("common.loot_tables.creature.humanoid"),
 
     hands: TwoHanded(Item("common.items.weapons.bow.eldwood-0")),
 
diff --git a/assets/common/entity/village/villager.ron b/assets/common/entity/village/villager.ron
index df46376d35..0320909a6d 100644
--- a/assets/common/entity/village/villager.ron
+++ b/assets/common/entity/village/villager.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("humanoid"),
     alignment: Alignment(Npc),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.humanoid"),
 
     hands: TwoHanded(Choice([
         (1.0, Some(Item("common.items.weapons.tool.broom"))),
diff --git a/assets/common/entity/wild/aggressive/alligator.ron b/assets/common/entity/wild/aggressive/alligator.ron
index 9e63eb22a2..878022cd3e 100644
--- a/assets/common/entity/wild/aggressive/alligator.ron
+++ b/assets/common/entity/wild/aggressive/alligator.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("alligator"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_low.generic"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/archaeos.ron b/assets/common/entity/wild/aggressive/archaeos.ron
index ef9fd560d9..43d7b1929c 100644
--- a/assets/common/entity/wild/aggressive/archaeos.ron
+++ b/assets/common/entity/wild/aggressive/archaeos.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("archaeos"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.theropod.horned"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/asp.ron b/assets/common/entity/wild/aggressive/asp.ron
index f40cbcb3ee..84cff4d550 100644
--- a/assets/common/entity/wild/aggressive/asp.ron
+++ b/assets/common/entity/wild/aggressive/asp.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("asp"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_low.venemous"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/batfox.ron b/assets/common/entity/wild/aggressive/batfox.ron
index dd0c68e9a3..fa77ed21b9 100644
--- a/assets/common/entity/wild/aggressive/batfox.ron
+++ b/assets/common/entity/wild/aggressive/batfox.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("batfox"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.generic"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/bear.ron b/assets/common/entity/wild/aggressive/bear.ron
index 66d3bd0042..15678ceaab 100644
--- a/assets/common/entity/wild/aggressive/bear.ron
+++ b/assets/common/entity/wild/aggressive/bear.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("bear"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.fanged"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/bonerattler.ron b/assets/common/entity/wild/aggressive/bonerattler.ron
index e5fa5910b1..7dc9b52038 100644
--- a/assets/common/entity/wild/aggressive/bonerattler.ron
+++ b/assets/common/entity/wild/aggressive/bonerattler.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("bonerattler"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.carapace"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/cockatrice.ron b/assets/common/entity/wild/aggressive/cockatrice.ron
index a367c30fcc..8de0517d5d 100644
--- a/assets/common/entity/wild/aggressive/cockatrice.ron
+++ b/assets/common/entity/wild/aggressive/cockatrice.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("cockatrice"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.bird_large.cockatrice"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/crocodile.ron b/assets/common/entity/wild/aggressive/crocodile.ron
index b839d4b4e5..469a497d8b 100644
--- a/assets/common/entity/wild/aggressive/crocodile.ron
+++ b/assets/common/entity/wild/aggressive/crocodile.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("crocodile"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_low.generic"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/cyclope.ron b/assets/common/entity/wild/aggressive/cyclope.ron
index 2e679b9458..6726ec0bca 100644
--- a/assets/common/entity/wild/aggressive/cyclope.ron
+++ b/assets/common/entity/wild/aggressive/cyclope.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("cyclops"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.biped_large.default"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/deadwood.ron b/assets/common/entity/wild/aggressive/deadwood.ron
index ebbcadf2e6..69d15721b6 100644
--- a/assets/common/entity/wild/aggressive/deadwood.ron
+++ b/assets/common/entity/wild/aggressive/deadwood.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("deadwood"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_low.deadwood"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/dodarock.ron b/assets/common/entity/wild/aggressive/dodarock.ron
index 444d4ae085..9d7693ff01 100644
--- a/assets/common/entity/wild/aggressive/dodarock.ron
+++ b/assets/common/entity/wild/aggressive/dodarock.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("dodarock"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.dodarock"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/dreadhorn.ron b/assets/common/entity/wild/aggressive/dreadhorn.ron
index e42bc14392..24cc0a5d07 100644
--- a/assets/common/entity/wild/aggressive/dreadhorn.ron
+++ b/assets/common/entity/wild/aggressive/dreadhorn.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("dreadhorn"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.dreadhorn"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/frostfang.ron b/assets/common/entity/wild/aggressive/frostfang.ron
index c315373e4c..6df71fb1d9 100644
--- a/assets/common/entity/wild/aggressive/frostfang.ron
+++ b/assets/common/entity/wild/aggressive/frostfang.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("frostfang"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.ice"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/grolgar.ron b/assets/common/entity/wild/aggressive/grolgar.ron
index 2b868ac934..0d8bed95ff 100644
--- a/assets/common/entity/wild/aggressive/grolgar.ron
+++ b/assets/common/entity/wild/aggressive/grolgar.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("grolgar"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.fanged"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/hakulaq.ron b/assets/common/entity/wild/aggressive/hakulaq.ron
index 68e4b77697..456b00db07 100644
--- a/assets/common/entity/wild/aggressive/hakulaq.ron
+++ b/assets/common/entity/wild/aggressive/hakulaq.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("hakulaq"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_low.fanged"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/hyena.ron b/assets/common/entity/wild/aggressive/hyena.ron
index dea8ade1f6..55807136aa 100644
--- a/assets/common/entity/wild/aggressive/hyena.ron
+++ b/assets/common/entity/wild/aggressive/hyena.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("hyena"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.generic"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/icepike.ron b/assets/common/entity/wild/aggressive/icepike.ron
index 2cb568b75d..8e3e119445 100644
--- a/assets/common/entity/wild/aggressive/icepike.ron
+++ b/assets/common/entity/wild/aggressive/icepike.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("icepike"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.fish"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/lavadrake.ron b/assets/common/entity/wild/aggressive/lavadrake.ron
index 43f9dfd981..2e73529654 100644
--- a/assets/common/entity/wild/aggressive/lavadrake.ron
+++ b/assets/common/entity/wild/aggressive/lavadrake.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("lavadrake"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_low.carapace"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/lion.ron b/assets/common/entity/wild/aggressive/lion.ron
index 703577cfa1..1f8bc3eafe 100644
--- a/assets/common/entity/wild/aggressive/lion.ron
+++ b/assets/common/entity/wild/aggressive/lion.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("lion"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.clawed"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/mammoth.ron b/assets/common/entity/wild/aggressive/mammoth.ron
index 6bf88c0e38..aa01c0f6b8 100644
--- a/assets/common/entity/wild/aggressive/mammoth.ron
+++ b/assets/common/entity/wild/aggressive/mammoth.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("mammoth"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.mammoth"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/maneater.ron b/assets/common/entity/wild/aggressive/maneater.ron
index 92ff16fa66..a546988da9 100644
--- a/assets/common/entity/wild/aggressive/maneater.ron
+++ b/assets/common/entity/wild/aggressive/maneater.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("maneater"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_low.maneater"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/mighty_saurok.ron b/assets/common/entity/wild/aggressive/mighty_saurok.ron
index 4fd00cc454..dba3286043 100644
--- a/assets/common/entity/wild/aggressive/mighty_saurok.ron
+++ b/assets/common/entity/wild/aggressive/mighty_saurok.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("saurok_mighty"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.biped_large.saurok"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/monitor.ron b/assets/common/entity/wild/aggressive/monitor.ron
index 2195fd63de..1b11c1407f 100644
--- a/assets/common/entity/wild/aggressive/monitor.ron
+++ b/assets/common/entity/wild/aggressive/monitor.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("monitor"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_low.generic"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/mountain_troll.ron b/assets/common/entity/wild/aggressive/mountain_troll.ron
index ef24ea5561..51c4cae461 100644
--- a/assets/common/entity/wild/aggressive/mountain_troll.ron
+++ b/assets/common/entity/wild/aggressive/mountain_troll.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("troll_mountain"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.biped_large.troll"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/ngoubou.ron b/assets/common/entity/wild/aggressive/ngoubou.ron
index 191d6642ac..f1441ed668 100644
--- a/assets/common/entity/wild/aggressive/ngoubou.ron
+++ b/assets/common/entity/wild/aggressive/ngoubou.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("ngoubou"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.horned"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/ntouka.ron b/assets/common/entity/wild/aggressive/ntouka.ron
index de2e848273..73cdc0465d 100644
--- a/assets/common/entity/wild/aggressive/ntouka.ron
+++ b/assets/common/entity/wild/aggressive/ntouka.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("ntouka"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.theropod.horned"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/occult_saurok.ron b/assets/common/entity/wild/aggressive/occult_saurok.ron
index 332ce79602..859799ac21 100644
--- a/assets/common/entity/wild/aggressive/occult_saurok.ron
+++ b/assets/common/entity/wild/aggressive/occult_saurok.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("saurok_occult"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.biped_large.saurok"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/odonto.ron b/assets/common/entity/wild/aggressive/odonto.ron
index a8cba7c234..5ac5b7ee1a 100644
--- a/assets/common/entity/wild/aggressive/odonto.ron
+++ b/assets/common/entity/wild/aggressive/odonto.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("odonto"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.theropod.generic"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/ogre.ron b/assets/common/entity/wild/aggressive/ogre.ron
index 7e3e655cfa..972ef756ef 100644
--- a/assets/common/entity/wild/aggressive/ogre.ron
+++ b/assets/common/entity/wild/aggressive/ogre.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("ogre"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.biped_large.default"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/rocksnapper.ron b/assets/common/entity/wild/aggressive/rocksnapper.ron
index b003b4f4d7..6e886a367e 100644
--- a/assets/common/entity/wild/aggressive/rocksnapper.ron
+++ b/assets/common/entity/wild/aggressive/rocksnapper.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("rocksnapper"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_low.carapace"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/roshwalr.ron b/assets/common/entity/wild/aggressive/roshwalr.ron
index cee362c67b..4d856d5d60 100644
--- a/assets/common/entity/wild/aggressive/roshwalr.ron
+++ b/assets/common/entity/wild/aggressive/roshwalr.ron
@@ -6,7 +6,7 @@ EntityConfig (
     ))),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.ice"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/roshwalr_boss.ron b/assets/common/entity/wild/aggressive/roshwalr_boss.ron
index 2f105614a1..95ce5d963a 100644
--- a/assets/common/entity/wild/aggressive/roshwalr_boss.ron
+++ b/assets/common/entity/wild/aggressive/roshwalr_boss.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: Exact(QuadrupedMedium(Body(species: Roshwalr, body_type: Female))),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.ice"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/saber.ron b/assets/common/entity/wild/aggressive/saber.ron
index 08e39d6245..c628224265 100644
--- a/assets/common/entity/wild/aggressive/saber.ron
+++ b/assets/common/entity/wild/aggressive/saber.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("sabertooth"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.fanged"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/sand_raptor.ron b/assets/common/entity/wild/aggressive/sand_raptor.ron
index 82f5a1abf3..e65e583856 100644
--- a/assets/common/entity/wild/aggressive/sand_raptor.ron
+++ b/assets/common/entity/wild/aggressive/sand_raptor.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("raptor_sand"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.theropod.raptor"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/sandshark.ron b/assets/common/entity/wild/aggressive/sandshark.ron
index 23df7e3f49..d06c09b294 100644
--- a/assets/common/entity/wild/aggressive/sandshark.ron
+++ b/assets/common/entity/wild/aggressive/sandshark.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("sandshark"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_low.carapace"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/sly_saurok.ron b/assets/common/entity/wild/aggressive/sly_saurok.ron
index d52795bda5..82c7b42ca2 100644
--- a/assets/common/entity/wild/aggressive/sly_saurok.ron
+++ b/assets/common/entity/wild/aggressive/sly_saurok.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("saurok_sly"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.biped_large.saurok"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/snow_leopard.ron b/assets/common/entity/wild/aggressive/snow_leopard.ron
index fbdeb737a3..83ac609422 100644
--- a/assets/common/entity/wild/aggressive/snow_leopard.ron
+++ b/assets/common/entity/wild/aggressive/snow_leopard.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("snowleopard"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.clawed"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/snow_raptor.ron b/assets/common/entity/wild/aggressive/snow_raptor.ron
index f892f197a3..48fb72a1f5 100644
--- a/assets/common/entity/wild/aggressive/snow_raptor.ron
+++ b/assets/common/entity/wild/aggressive/snow_raptor.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("raptor_snow"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.theropod.raptor"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/sunlizard.ron b/assets/common/entity/wild/aggressive/sunlizard.ron
index 0d5d11803b..594a17864e 100644
--- a/assets/common/entity/wild/aggressive/sunlizard.ron
+++ b/assets/common/entity/wild/aggressive/sunlizard.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("sunlizard"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.theropod.raptor"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/swamp_troll.ron b/assets/common/entity/wild/aggressive/swamp_troll.ron
index d8410db0e0..9cac895d83 100644
--- a/assets/common/entity/wild/aggressive/swamp_troll.ron
+++ b/assets/common/entity/wild/aggressive/swamp_troll.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("troll_swamp"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.biped_large.troll"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/tarasque.ron b/assets/common/entity/wild/aggressive/tarasque.ron
index 9240f05109..0ee11655bf 100644
--- a/assets/common/entity/wild/aggressive/tarasque.ron
+++ b/assets/common/entity/wild/aggressive/tarasque.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("tarasque"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.carapace"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/tiger.ron b/assets/common/entity/wild/aggressive/tiger.ron
index 309c9e7df7..ee8c890b65 100644
--- a/assets/common/entity/wild/aggressive/tiger.ron
+++ b/assets/common/entity/wild/aggressive/tiger.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("tiger"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.clawed"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/wendigo.ron b/assets/common/entity/wild/aggressive/wendigo.ron
index 8fef962284..2bf2f490a3 100644
--- a/assets/common/entity/wild/aggressive/wendigo.ron
+++ b/assets/common/entity/wild/aggressive/wendigo.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("wendigo"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.biped_large.wendigo"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/wolf.ron b/assets/common/entity/wild/aggressive/wolf.ron
index 57509f6382..54be102034 100644
--- a/assets/common/entity/wild/aggressive/wolf.ron
+++ b/assets/common/entity/wild/aggressive/wolf.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("wolf"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.fanged"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/wood_raptor.ron b/assets/common/entity/wild/aggressive/wood_raptor.ron
index fbc093e14a..bf9210ad56 100644
--- a/assets/common/entity/wild/aggressive/wood_raptor.ron
+++ b/assets/common/entity/wild/aggressive/wood_raptor.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("raptor_wood"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.theropod.raptor"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/aggressive/yale.ron b/assets/common/entity/wild/aggressive/yale.ron
index 0ea8d6dc09..fe7e4c9e77 100644
--- a/assets/common/entity/wild/aggressive/yale.ron
+++ b/assets/common/entity/wild/aggressive/yale.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("yale"),
     alignment: Alignment(Enemy),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.theropod.horned"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/alpaca.ron b/assets/common/entity/wild/peaceful/alpaca.ron
index b1b06b53a9..c74c42916b 100644
--- a/assets/common/entity/wild/peaceful/alpaca.ron
+++ b/assets/common/entity/wild/peaceful/alpaca.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("alpaca"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.wool"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/antelope.ron b/assets/common/entity/wild/peaceful/antelope.ron
index 573e457850..6712881c2f 100644
--- a/assets/common/entity/wild/peaceful/antelope.ron
+++ b/assets/common/entity/wild/peaceful/antelope.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("antelope"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.gentle"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/arctic_fox.ron b/assets/common/entity/wild/peaceful/arctic_fox.ron
index 4a289c0644..cc5ed43126 100644
--- a/assets/common/entity/wild/peaceful/arctic_fox.ron
+++ b/assets/common/entity/wild/peaceful/arctic_fox.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: Exact(QuadrupedSmall(Body(species: Fox, body_type: Female))),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.generic"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/arctic_hare.ron b/assets/common/entity/wild/peaceful/arctic_hare.ron
index 566b5c15e2..9104b17bbb 100644
--- a/assets/common/entity/wild/peaceful/arctic_hare.ron
+++ b/assets/common/entity/wild/peaceful/arctic_hare.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: Exact(QuadrupedSmall(Body(species: Hare, body_type: Female))),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.fur"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/axolotl.ron b/assets/common/entity/wild/peaceful/axolotl.ron
index f7b04e723e..02e3b21093 100644
--- a/assets/common/entity/wild/peaceful/axolotl.ron
+++ b/assets/common/entity/wild/peaceful/axolotl.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("axolotl"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.ooze"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/bear.ron b/assets/common/entity/wild/peaceful/bear.ron
index 3d132caf15..332e1ca541 100644
--- a/assets/common/entity/wild/peaceful/bear.ron
+++ b/assets/common/entity/wild/peaceful/bear.ron
@@ -1,9 +1,10 @@
 EntityConfig (
+    // FIXME: move this boi to spot directory
     name: Name("Well-fed Bear"),
     body: RandomWith("bear"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.clawed"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/beaver.ron b/assets/common/entity/wild/peaceful/beaver.ron
index fb7ed84625..647d55d6c4 100644
--- a/assets/common/entity/wild/peaceful/beaver.ron
+++ b/assets/common/entity/wild/peaceful/beaver.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("beaver"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.fur"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/boar.ron b/assets/common/entity/wild/peaceful/boar.ron
index bba9eac893..8fea407899 100644
--- a/assets/common/entity/wild/peaceful/boar.ron
+++ b/assets/common/entity/wild/peaceful/boar.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("boar"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.generic"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/camel.ron b/assets/common/entity/wild/peaceful/camel.ron
index fd574f17e1..a835a5a2cd 100644
--- a/assets/common/entity/wild/peaceful/camel.ron
+++ b/assets/common/entity/wild/peaceful/camel.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("camel"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.gentle"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/cat.ron b/assets/common/entity/wild/peaceful/cat.ron
index 1e7ad2372a..2ae273f45c 100644
--- a/assets/common/entity/wild/peaceful/cat.ron
+++ b/assets/common/entity/wild/peaceful/cat.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("cat"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.generic"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/catoblepas.ron b/assets/common/entity/wild/peaceful/catoblepas.ron
index d15457d45c..7e3217792d 100644
--- a/assets/common/entity/wild/peaceful/catoblepas.ron
+++ b/assets/common/entity/wild/peaceful/catoblepas.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("catoblepas"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.catoblepas"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/cattle.ron b/assets/common/entity/wild/peaceful/cattle.ron
index 72cc745057..94e74f5681 100644
--- a/assets/common/entity/wild/peaceful/cattle.ron
+++ b/assets/common/entity/wild/peaceful/cattle.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("cattle"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.gentle"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/chicken.ron b/assets/common/entity/wild/peaceful/chicken.ron
index 7d65a663ee..ca89bc50b3 100644
--- a/assets/common/entity/wild/peaceful/chicken.ron
+++ b/assets/common/entity/wild/peaceful/chicken.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("chicken"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.bird_medium"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/clownfish.ron b/assets/common/entity/wild/peaceful/clownfish.ron
index 76c8698071..57a01bdca5 100644
--- a/assets/common/entity/wild/peaceful/clownfish.ron
+++ b/assets/common/entity/wild/peaceful/clownfish.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("clownfish"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.fish"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/deer.ron b/assets/common/entity/wild/peaceful/deer.ron
index 0b12f635ca..6bb8316e2c 100644
--- a/assets/common/entity/wild/peaceful/deer.ron
+++ b/assets/common/entity/wild/peaceful/deer.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("deer"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.gentle"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/donkey.ron b/assets/common/entity/wild/peaceful/donkey.ron
index 5838cf2710..3725c02ae3 100644
--- a/assets/common/entity/wild/peaceful/donkey.ron
+++ b/assets/common/entity/wild/peaceful/donkey.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("donkey"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.gentle"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/duck.ron b/assets/common/entity/wild/peaceful/duck.ron
index c0f9283508..8fcba4874c 100644
--- a/assets/common/entity/wild/peaceful/duck.ron
+++ b/assets/common/entity/wild/peaceful/duck.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("duck"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.bird_medium"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/eagle.ron b/assets/common/entity/wild/peaceful/eagle.ron
index 093606f786..5cd69f2774 100644
--- a/assets/common/entity/wild/peaceful/eagle.ron
+++ b/assets/common/entity/wild/peaceful/eagle.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("eagle"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.bird_medium"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/forest_fox.ron b/assets/common/entity/wild/peaceful/forest_fox.ron
index f2a7e88651..14751ed70a 100644
--- a/assets/common/entity/wild/peaceful/forest_fox.ron
+++ b/assets/common/entity/wild/peaceful/forest_fox.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: Exact(QuadrupedSmall(Body(species: Fox, body_type: Male))),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.generic"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/frog.ron b/assets/common/entity/wild/peaceful/frog.ron
index 6bc65393f6..d2b0ca03e3 100644
--- a/assets/common/entity/wild/peaceful/frog.ron
+++ b/assets/common/entity/wild/peaceful/frog.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("frog"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.ooze"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/fungome.ron b/assets/common/entity/wild/peaceful/fungome.ron
index 96540f5d61..fa369e7a93 100644
--- a/assets/common/entity/wild/peaceful/fungome.ron
+++ b/assets/common/entity/wild/peaceful/fungome.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("fungome"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.mushroom"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/gecko.ron b/assets/common/entity/wild/peaceful/gecko.ron
index 830c51cb0d..e4569e9f9c 100644
--- a/assets/common/entity/wild/peaceful/gecko.ron
+++ b/assets/common/entity/wild/peaceful/gecko.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("gecko"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.ooze"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/goat.ron b/assets/common/entity/wild/peaceful/goat.ron
index 9f33ed002e..6f2e387932 100644
--- a/assets/common/entity/wild/peaceful/goat.ron
+++ b/assets/common/entity/wild/peaceful/goat.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("goat"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.wool")
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/goose.ron b/assets/common/entity/wild/peaceful/goose.ron
index 294f05754a..1e2a1ac7df 100644
--- a/assets/common/entity/wild/peaceful/goose.ron
+++ b/assets/common/entity/wild/peaceful/goose.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("goose"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.bird_medium"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/highland.ron b/assets/common/entity/wild/peaceful/highland.ron
index ef992cd8fb..d859373f86 100644
--- a/assets/common/entity/wild/peaceful/highland.ron
+++ b/assets/common/entity/wild/peaceful/highland.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("highland"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.gentle"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/hirdrasil.ron b/assets/common/entity/wild/peaceful/hirdrasil.ron
index c97924afd9..0be067552a 100644
--- a/assets/common/entity/wild/peaceful/hirdrasil.ron
+++ b/assets/common/entity/wild/peaceful/hirdrasil.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("hirdrasil"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.gentle"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/holladon.ron b/assets/common/entity/wild/peaceful/holladon.ron
index a57248dce9..eb4d9e8c79 100644
--- a/assets/common/entity/wild/peaceful/holladon.ron
+++ b/assets/common/entity/wild/peaceful/holladon.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("holladon"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.generic")
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/horse.ron b/assets/common/entity/wild/peaceful/horse.ron
index b42067c4c8..c07d313038 100644
--- a/assets/common/entity/wild/peaceful/horse.ron
+++ b/assets/common/entity/wild/peaceful/horse.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("horse"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.gentle"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/jackalope.ron b/assets/common/entity/wild/peaceful/jackalope.ron
index 130aad374a..3ce80fc5a0 100644
--- a/assets/common/entity/wild/peaceful/jackalope.ron
+++ b/assets/common/entity/wild/peaceful/jackalope.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("jackalope"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.fur"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/kelpie.ron b/assets/common/entity/wild/peaceful/kelpie.ron
index 1062c5bedb..8cad9576d0 100644
--- a/assets/common/entity/wild/peaceful/kelpie.ron
+++ b/assets/common/entity/wild/peaceful/kelpie.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("kelpie"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.gentle"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/llama.ron b/assets/common/entity/wild/peaceful/llama.ron
index 3b40a2149e..6b9ae9f5cc 100644
--- a/assets/common/entity/wild/peaceful/llama.ron
+++ b/assets/common/entity/wild/peaceful/llama.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("llama"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.wool")
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/marlin.ron b/assets/common/entity/wild/peaceful/marlin.ron
index e127c8aeba..ff0abdc85e 100644
--- a/assets/common/entity/wild/peaceful/marlin.ron
+++ b/assets/common/entity/wild/peaceful/marlin.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("marlin"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.fish"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/moose.ron b/assets/common/entity/wild/peaceful/moose.ron
index 47953674fc..51306769fa 100644
--- a/assets/common/entity/wild/peaceful/moose.ron
+++ b/assets/common/entity/wild/peaceful/moose.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("moose"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_low.fanged"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/mouflon.ron b/assets/common/entity/wild/peaceful/mouflon.ron
index c324dcbba5..ea037f9a5a 100644
--- a/assets/common/entity/wild/peaceful/mouflon.ron
+++ b/assets/common/entity/wild/peaceful/mouflon.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("mouflon"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.wool")
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/owl.ron b/assets/common/entity/wild/peaceful/owl.ron
index dd23ad327a..f7544c3743 100644
--- a/assets/common/entity/wild/peaceful/owl.ron
+++ b/assets/common/entity/wild/peaceful/owl.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("owl"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.bird_medium"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/pangolin.ron b/assets/common/entity/wild/peaceful/pangolin.ron
index ba207dd831..b4f2cd9e0e 100644
--- a/assets/common/entity/wild/peaceful/pangolin.ron
+++ b/assets/common/entity/wild/peaceful/pangolin.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("pangolin"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_low.generic"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/parrot.ron b/assets/common/entity/wild/peaceful/parrot.ron
index d680c71647..ec718c7cba 100644
--- a/assets/common/entity/wild/peaceful/parrot.ron
+++ b/assets/common/entity/wild/peaceful/parrot.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("parrot"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.bird_medium"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/peacock.ron b/assets/common/entity/wild/peaceful/peacock.ron
index b34c2e830d..4453aa8aac 100644
--- a/assets/common/entity/wild/peaceful/peacock.ron
+++ b/assets/common/entity/wild/peaceful/peacock.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("peacock"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.bird_medium"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/pig.ron b/assets/common/entity/wild/peaceful/pig.ron
index 3c20ae39cd..8e642bd80e 100644
--- a/assets/common/entity/wild/peaceful/pig.ron
+++ b/assets/common/entity/wild/peaceful/pig.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("pig"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.generic")
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/piranha.ron b/assets/common/entity/wild/peaceful/piranha.ron
index dc1f92651b..7ff3d4c683 100644
--- a/assets/common/entity/wild/peaceful/piranha.ron
+++ b/assets/common/entity/wild/peaceful/piranha.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("piranha"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.fish"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/porcupine.ron b/assets/common/entity/wild/peaceful/porcupine.ron
index 79fdade2b9..94278e6362 100644
--- a/assets/common/entity/wild/peaceful/porcupine.ron
+++ b/assets/common/entity/wild/peaceful/porcupine.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("porcupine"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.generic"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/quokka.ron b/assets/common/entity/wild/peaceful/quokka.ron
index e25c15cb3c..1d18487d75 100644
--- a/assets/common/entity/wild/peaceful/quokka.ron
+++ b/assets/common/entity/wild/peaceful/quokka.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("quokka"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.fur"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/rabbit.ron b/assets/common/entity/wild/peaceful/rabbit.ron
index 23ff937e6e..9266b03d08 100644
--- a/assets/common/entity/wild/peaceful/rabbit.ron
+++ b/assets/common/entity/wild/peaceful/rabbit.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("rabbit"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.generic"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/raccoon.ron b/assets/common/entity/wild/peaceful/raccoon.ron
index b941c98a24..d89dec27da 100644
--- a/assets/common/entity/wild/peaceful/raccoon.ron
+++ b/assets/common/entity/wild/peaceful/raccoon.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("raccoon"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.generic"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/rat.ron b/assets/common/entity/wild/peaceful/rat.ron
index d911990b8b..61c0fa8c3c 100644
--- a/assets/common/entity/wild/peaceful/rat.ron
+++ b/assets/common/entity/wild/peaceful/rat.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("rat"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.generic"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/river_salamander.ron b/assets/common/entity/wild/peaceful/river_salamander.ron
index 3f2914df60..fa0e59c5f0 100644
--- a/assets/common/entity/wild/peaceful/river_salamander.ron
+++ b/assets/common/entity/wild/peaceful/river_salamander.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: Exact(QuadrupedLow(Body(species: Salamander, body_type: Female))),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_low.salamander"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/sand_hare.ron b/assets/common/entity/wild/peaceful/sand_hare.ron
index 84a417974c..80964c719f 100644
--- a/assets/common/entity/wild/peaceful/sand_hare.ron
+++ b/assets/common/entity/wild/peaceful/sand_hare.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: Exact(QuadrupedSmall(Body(species: Hare, body_type: Male))),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.fur")
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/sand_salamander.ron b/assets/common/entity/wild/peaceful/sand_salamander.ron
index 2740438c2b..67117b2ba7 100644
--- a/assets/common/entity/wild/peaceful/sand_salamander.ron
+++ b/assets/common/entity/wild/peaceful/sand_salamander.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: Exact(QuadrupedLow(Body(species: Salamander, body_type: Male))),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_low.salamander"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/sheep.ron b/assets/common/entity/wild/peaceful/sheep.ron
index fff177dfd3..b1ae6645b5 100644
--- a/assets/common/entity/wild/peaceful/sheep.ron
+++ b/assets/common/entity/wild/peaceful/sheep.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("sheep"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.wool")
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/skunk.ron b/assets/common/entity/wild/peaceful/skunk.ron
index 6e782adcfb..3e96494083 100644
--- a/assets/common/entity/wild/peaceful/skunk.ron
+++ b/assets/common/entity/wild/peaceful/skunk.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("skunk"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.fur"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/squirrel.ron b/assets/common/entity/wild/peaceful/squirrel.ron
index 9daac3cd8e..3ae5257792 100644
--- a/assets/common/entity/wild/peaceful/squirrel.ron
+++ b/assets/common/entity/wild/peaceful/squirrel.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("squirrel"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.generic"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/tortoise.ron b/assets/common/entity/wild/peaceful/tortoise.ron
index 4104f1c43a..d7e0cca731 100644
--- a/assets/common/entity/wild/peaceful/tortoise.ron
+++ b/assets/common/entity/wild/peaceful/tortoise.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("tortoise"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_low.generic"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/truffler.ron b/assets/common/entity/wild/peaceful/truffler.ron
index c0c9adfc1f..f14273fae0 100644
--- a/assets/common/entity/wild/peaceful/truffler.ron
+++ b/assets/common/entity/wild/peaceful/truffler.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("truffler"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.mushroom"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/turtle.ron b/assets/common/entity/wild/peaceful/turtle.ron
index 4b55182fa6..7ae12f404f 100644
--- a/assets/common/entity/wild/peaceful/turtle.ron
+++ b/assets/common/entity/wild/peaceful/turtle.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("turtle"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_small.ooze"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/tuskram.ron b/assets/common/entity/wild/peaceful/tuskram.ron
index 32c091db3a..42b7769ae2 100644
--- a/assets/common/entity/wild/peaceful/tuskram.ron
+++ b/assets/common/entity/wild/peaceful/tuskram.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("tuskram"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.fanged"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/yak.ron b/assets/common/entity/wild/peaceful/yak.ron
index 95323b48d2..64abc7681e 100644
--- a/assets/common/entity/wild/peaceful/yak.ron
+++ b/assets/common/entity/wild/peaceful/yak.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("yak"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.gentle"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/zebra.ron b/assets/common/entity/wild/peaceful/zebra.ron
index fd7667965b..95627c2540 100644
--- a/assets/common/entity/wild/peaceful/zebra.ron
+++ b/assets/common/entity/wild/peaceful/zebra.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("zebra"),
     alignment: Alignment(Wild),
 
-    loot: Uninit,
+    loot: LootTable("common.loot_tables.creature.quad_medium.gentle"),
 
     hands: Uninit,
 
diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs
index 39f248b463..d6cfda56c6 100644
--- a/server/src/events/entity_manipulation.rs
+++ b/server/src/events/entity_manipulation.rs
@@ -354,154 +354,6 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, last_change: Healt
 
         // Decide for a loot drop before turning into a lootbag
         let old_body = state.ecs().write_storage::<Body>().remove(entity);
-        let _ = || {
-            Lottery::<LootSpec<String>>::load_expect(match old_body {
-                Some(common::comp::Body::Humanoid(_)) => "common.loot_tables.creature.humanoid",
-                Some(common::comp::Body::QuadrupedSmall(quadruped_small)) => {
-                    match quadruped_small.species {
-                        quadruped_small::Species::Dodarock => {
-                            "common.loot_tables.creature.quad_small.dodarock"
-                        },
-                        quadruped_small::Species::Truffler | quadruped_small::Species::Fungome => {
-                            "common.loot_tables.creature.quad_small.mushroom"
-                        },
-                        quadruped_small::Species::Sheep | quadruped_small::Species::Goat => {
-                            "common.loot_tables.creature.quad_small.wool"
-                        },
-                        quadruped_small::Species::Skunk
-                        | quadruped_small::Species::Quokka
-                        | quadruped_small::Species::Beaver
-                        | quadruped_small::Species::Jackalope
-                        | quadruped_small::Species::Hare => {
-                            "common.loot_tables.creature.quad_small.fur"
-                        },
-                        quadruped_small::Species::Frog
-                        | quadruped_small::Species::Axolotl
-                        | quadruped_small::Species::Gecko
-                        | quadruped_small::Species::Turtle => {
-                            "common.loot_tables.creature.quad_small.ooze"
-                        },
-                        _ => "common.loot_tables.creature.quad_small.generic",
-                    }
-                },
-                Some(Body::QuadrupedMedium(quadruped_medium)) => match quadruped_medium.species {
-                    quadruped_medium::Species::Frostfang | quadruped_medium::Species::Roshwalr => {
-                        "common.loot_tables.creature.quad_medium.ice"
-                    },
-                    quadruped_medium::Species::Catoblepas => {
-                        "common.loot_tables.creature.quad_medium.catoblepas"
-                    },
-                    quadruped_medium::Species::Bear
-                    | quadruped_medium::Species::Snowleopard
-                    | quadruped_medium::Species::Tiger
-                    | quadruped_medium::Species::Lion => {
-                        "common.loot_tables.creature.quad_medium.clawed"
-                    },
-                    quadruped_medium::Species::Tarasque
-                    | quadruped_medium::Species::Bonerattler => {
-                        "common.loot_tables.creature.quad_medium.carapace"
-                    },
-                    quadruped_medium::Species::Dreadhorn => {
-                        "common.loot_tables.creature.quad_medium.dreadhorn"
-                    },
-                    quadruped_medium::Species::Camel
-                    | quadruped_medium::Species::Deer
-                    | quadruped_medium::Species::Hirdrasil
-                    | quadruped_medium::Species::Horse
-                    | quadruped_medium::Species::Highland
-                    | quadruped_medium::Species::Zebra
-                    | quadruped_medium::Species::Donkey
-                    | quadruped_medium::Species::Antelope
-                    | quadruped_medium::Species::Kelpie
-                    | quadruped_medium::Species::Cattle
-                    | quadruped_medium::Species::Yak => {
-                        "common.loot_tables.creature.quad_medium.gentle"
-                    },
-                    quadruped_medium::Species::Mouflon
-                    | quadruped_medium::Species::Llama
-                    | quadruped_medium::Species::Alpaca => {
-                        "common.loot_tables.creature.quad_medium.wool"
-                    },
-                    quadruped_medium::Species::Ngoubou => {
-                        "common.loot_tables.creature.quad_medium.horned"
-                    },
-                    quadruped_medium::Species::Mammoth => {
-                        "common.loot_tables.creature.quad_medium.mammoth"
-                    },
-                    _ => "common.loot_tables.creature.quad_medium.fanged",
-                },
-                Some(common::comp::Body::BirdMedium(_)) => {
-                    "common.loot_tables.creature.bird_medium"
-                },
-                Some(common::comp::Body::BirdLarge(bird_large)) => match bird_large.species {
-                    bird_large::Species::Cockatrice => {
-                        "common.loot_tables.creature.bird_large.cockatrice"
-                    },
-                    bird_large::Species::Roc => "common.loot_tables.creature.bird_large.roc",
-                    _ => "common.loot_tables.creature.bird_large.phoenix",
-                },
-                Some(common::comp::Body::FishMedium(_)) => "common.loot_tables.creature.fish",
-                Some(common::comp::Body::FishSmall(_)) => "common.loot_tables.creature.fish",
-                Some(common::comp::Body::BipedLarge(biped_large)) => match biped_large.species {
-                    biped_large::Species::Wendigo => {
-                        "common.loot_tables.creature.biped_large.wendigo"
-                    },
-                    biped_large::Species::Cavetroll
-                    | biped_large::Species::Mountaintroll
-                    | biped_large::Species::Swamptroll => {
-                        "common.loot_tables.creature.biped_large.troll"
-                    },
-                    biped_large::Species::Occultsaurok
-                    | biped_large::Species::Mightysaurok
-                    | biped_large::Species::Slysaurok => {
-                        "common.loot_tables.creature.biped_large.saurok"
-                    },
-                    _ => "common.loot_tables.creature.biped_large.default",
-                },
-                Some(common::comp::Body::Golem(_)) => "common.loot_tables.creature.golem",
-                Some(common::comp::Body::Theropod(theropod)) => match theropod.species {
-                    theropod::Species::Sandraptor
-                    | theropod::Species::Snowraptor
-                    | theropod::Species::Woodraptor
-                    | theropod::Species::Sunlizard => "common.loot_tables.creature.theropod.raptor",
-                    theropod::Species::Archaeos
-                    | theropod::Species::Ntouka
-                    | theropod::Species::Yale => "common.loot_tables.creature.theropod.horned",
-                    _ => "common.loot_tables.creature.theropod.generic",
-                },
-                Some(common::comp::Body::Dragon(_)) => "common.loot_tables.creature.dragon",
-                Some(common::comp::Body::QuadrupedLow(quadruped_low)) => {
-                    match quadruped_low.species {
-                        quadruped_low::Species::Maneater => {
-                            "common.loot_tables.creature.quad_low.maneater"
-                        },
-                        quadruped_low::Species::Lavadrake
-                        | quadruped_low::Species::Rocksnapper
-                        | quadruped_low::Species::Sandshark => {
-                            "common.loot_tables.creature.quad_low.carapace"
-                        },
-                        quadruped_low::Species::Asp => {
-                            "common.loot_tables.creature.quad_low.venemous"
-                        },
-                        quadruped_low::Species::Hakulaq => {
-                            "common.loot_tables.creature.quad_low.fanged"
-                        },
-                        quadruped_low::Species::Deadwood => {
-                            "common.loot_tables.creature.quad_low.deadwood"
-                        },
-                        quadruped_low::Species::Basilisk => {
-                            "common.loot_tables.creature.quad_low.basilisk"
-                        },
-                        quadruped_low::Species::Salamander => {
-                            "common.loot_tables.creature.quad_low.salamander"
-                        },
-                        _ => "common.loot_tables.creature.quad_low.generic",
-                    }
-                },
-                Some(common::comp::Body::BipedSmall(_)) => "common.loot_tables.nothing",
-                _ => "common.loot_tables.fallback",
-            })
-        };
 
         let loot_spec = {
             let mut item_drop = state.ecs().write_storage::<comp::ItemDrop<String>>();
@@ -515,6 +367,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, last_change: Healt
             let pos = state.ecs().read_storage::<comp::Pos>().get(entity).cloned();
             let vel = state.ecs().read_storage::<comp::Vel>().get(entity).cloned();
             if let Some(pos) = pos {
+                // FIXME: Please, no BeastMeat from Possesed Turret
                 let _ = state
                     .create_object(comp::Pos(pos.0 + Vec3::unit_z() * 0.25), match old_body {
                         Some(common::comp::Body::Humanoid(_)) => object::Body::Pouch,
diff --git a/server/src/rtsim/tick.rs b/server/src/rtsim/tick.rs
index df17a84b1a..7728671edc 100644
--- a/server/src/rtsim/tick.rs
+++ b/server/src/rtsim/tick.rs
@@ -166,6 +166,8 @@ impl<'a> System<'a> for Sys {
                         comp::Body::Ship(_) => comp::Scale(comp::ship::AIRSHIP_SCALE),
                         _ => comp::Scale(1.0),
                     },
+                    // FIXME;
+                    // Drop loot
                     drop_item: None,
                     anchor: None,
                     rtsim_entity,
diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs
index bb5d07c67e..35a889737d 100644
--- a/world/src/layer/mod.rs
+++ b/world/src/layer/mod.rs
@@ -440,7 +440,8 @@ pub fn apply_caves_supplement<'a>(
                 // Abs units
                 let cave_base = (cave.alt + cave_floor) as i32;
 
-                let cave_depth = (col_sample.alt - cave.alt).max(0.0); //slightly different from earlier cave depth?
+                // slightly different from earlier cave depth?
+                let cave_depth = (col_sample.alt - cave.alt).max(0.0);
 
                 // Scatter things in caves
                 if let Some(z) = (-4..8).map(|z| cave_base + z).find(|z| {
@@ -505,6 +506,8 @@ pub fn apply_caves_supplement<'a>(
                                 })
                                 .with_automatic_name();
 
+                        // FIXME:
+                        // Drop something.
                         supplement.add_entity(entity);
                     }
                 }

From 8f84e00e7e13e9a81702b2a45dd031ccbf40072b Mon Sep 17 00:00:00 2001
From: juliancoffee <lightdarkdaughter@gmail.com>
Date: Thu, 23 Sep 2021 00:19:15 +0300
Subject: [PATCH 04/14] Hardened Loot handling part two

+ clippy advices
+ use LootSpec::Nothing for basic_summon explicitly
---
 common/src/lottery.rs             | 2 +-
 common/src/states/basic_summon.rs | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/common/src/lottery.rs b/common/src/lottery.rs
index 46d5b5cc9a..301b1facb4 100644
--- a/common/src/lottery.rs
+++ b/common/src/lottery.rs
@@ -96,7 +96,7 @@ impl<T: AsRef<str>> LootSpec<T> {
                     warn!(?e, "Invalid item path");
                     None
                 },
-                |i| Some(i),
+                Option::Some,
             ),
             Self::ItemQuantity(item, lower, upper) => {
                 let range = *lower..=*upper;
diff --git a/common/src/states/basic_summon.rs b/common/src/states/basic_summon.rs
index 338b488e75..eab53dd47b 100644
--- a/common/src/states/basic_summon.rs
+++ b/common/src/states/basic_summon.rs
@@ -187,7 +187,7 @@ impl CharacterBehavior for Data {
                                 .scale
                                 .unwrap_or(comp::Scale(1.0)),
                             anchor: None,
-                            drop_item: None,
+                            drop_item: Some(crate::lottery::LootSpec::Nothing),
                             rtsim_entity: None,
                             projectile,
                         });

From bc962f707d7f8245aae33914f86deccfff38bfd3 Mon Sep 17 00:00:00 2001
From: juliancoffee <lightdarkdaughter@gmail.com>
Date: Thu, 23 Sep 2021 00:23:25 +0300
Subject: [PATCH 05/14] Refactor cave supplement to more symmetric code

---
 world/src/layer/mod.rs | 118 ++++++++++++++++++++++-------------------
 1 file changed, 64 insertions(+), 54 deletions(-)

diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs
index 35a889737d..c5e3091916 100644
--- a/world/src/layer/mod.rs
+++ b/world/src/layer/mod.rs
@@ -453,61 +453,71 @@ pub fn apply_caves_supplement<'a>(
                     if RandomField::new(index.seed).chance(wpos2d.into(), 0.0014)
                         && cave_base < surface_z as i32 - 40
                     {
-                        let is_hostile: bool;
-                        let entity =
-                            EntityInfo::at(Vec3::new(wpos2d.x as f32, wpos2d.y as f32, z as f32))
-                                .with_body(if cave_depth < 70.0 {
-                                    is_hostile = false;
-                                    let species = match dynamic_rng.gen_range(0..4) {
-                                        0 => comp::quadruped_small::Species::Truffler,
-                                        1 => comp::quadruped_small::Species::Dodarock,
-                                        2 => comp::quadruped_small::Species::Holladon,
-                                        _ => comp::quadruped_small::Species::Batfox,
-                                    };
-                                    comp::quadruped_small::Body::random_with(dynamic_rng, &species)
-                                        .into()
-                                } else if cave_depth < 120.0 {
-                                    is_hostile = true;
-                                    let species = match dynamic_rng.gen_range(0..3) {
-                                        0 => comp::quadruped_low::Species::Rocksnapper,
-                                        1 => comp::quadruped_low::Species::Salamander,
-                                        _ => comp::quadruped_low::Species::Asp,
-                                    };
-                                    comp::quadruped_low::Body::random_with(dynamic_rng, &species)
-                                        .into()
-                                } else if cave_depth < 190.0 {
-                                    is_hostile = true;
-                                    let species = match dynamic_rng.gen_range(0..3) {
-                                        0 => comp::quadruped_low::Species::Rocksnapper,
-                                        1 => comp::quadruped_low::Species::Lavadrake,
-                                        _ => comp::quadruped_low::Species::Basilisk,
-                                    };
-                                    comp::quadruped_low::Body::random_with(dynamic_rng, &species)
-                                        .into()
-                                } else {
-                                    is_hostile = true;
-                                    let species = match dynamic_rng.gen_range(0..5) {
-                                        0 => comp::biped_large::Species::Ogre,
-                                        1 => comp::biped_large::Species::Cyclops,
-                                        2 => comp::biped_large::Species::Wendigo,
-                                        3 => match dynamic_rng.gen_range(0..2) {
-                                            0 => comp::biped_large::Species::Blueoni,
-                                            _ => comp::biped_large::Species::Redoni,
-                                        },
-                                        _ => comp::biped_large::Species::Cavetroll,
-                                    };
-                                    comp::biped_large::Body::random_with(dynamic_rng, &species)
-                                        .into()
-                                })
-                                .with_alignment(if is_hostile {
-                                    comp::Alignment::Enemy
-                                } else {
-                                    comp::Alignment::Wild
-                                })
-                                .with_automatic_name();
+                        let entity = EntityInfo::at(wpos2d.map(|e| e as f32).with_z(z as f32));
+                        let entity = if cave_depth < 70.0 {
+                            let species = match dynamic_rng.gen_range(0..4) {
+                                0 => comp::quadruped_small::Species::Truffler,
+                                1 => comp::quadruped_small::Species::Dodarock,
+                                2 => comp::quadruped_small::Species::Holladon,
+                                _ => comp::quadruped_small::Species::Batfox,
+                            };
+                            let body =
+                                comp::quadruped_small::Body::random_with(dynamic_rng, &species);
+                            // FIXME:
+                            // Drop something.
+                            entity
+                                .with_body(body.into())
+                                .with_alignment(comp::Alignment::Wild)
+                                .with_automatic_name()
+                        } else if cave_depth < 120.0 {
+                            let species = match dynamic_rng.gen_range(0..3) {
+                                0 => comp::quadruped_low::Species::Rocksnapper,
+                                1 => comp::quadruped_low::Species::Salamander,
+                                _ => comp::quadruped_low::Species::Asp,
+                            };
+                            let body =
+                                comp::quadruped_low::Body::random_with(dynamic_rng, &species);
+                            // FIXME:
+                            // Drop something.
+                            entity
+                                .with_body(body.into())
+                                .with_alignment(comp::Alignment::Enemy)
+                                .with_automatic_name()
+                        } else if cave_depth < 190.0 {
+                            let species = match dynamic_rng.gen_range(0..3) {
+                                0 => comp::quadruped_low::Species::Rocksnapper,
+                                1 => comp::quadruped_low::Species::Lavadrake,
+                                _ => comp::quadruped_low::Species::Basilisk,
+                            };
+                            let body =
+                                comp::quadruped_low::Body::random_with(dynamic_rng, &species);
+                            // FIXME:
+                            // Drop something.
+                            entity
+                                .with_body(body.into())
+                                .with_alignment(comp::Alignment::Enemy)
+                                .with_automatic_name()
+                        } else {
+                            let species = match dynamic_rng.gen_range(0..5) {
+                                0 => comp::biped_large::Species::Ogre,
+                                1 => comp::biped_large::Species::Cyclops,
+                                2 => comp::biped_large::Species::Wendigo,
+                                3 => match dynamic_rng.gen_range(0..2) {
+                                    0 => comp::biped_large::Species::Blueoni,
+                                    _ => comp::biped_large::Species::Redoni,
+                                },
+                                _ => comp::biped_large::Species::Cavetroll,
+                            };
+
+                            let body = comp::biped_large::Body::random_with(dynamic_rng, &species);
+                            // FIXME:
+                            // Drop something.
+                            entity
+                                .with_body(body.into())
+                                .with_alignment(comp::Alignment::Enemy)
+                                .with_automatic_name()
+                        };
 
-                        // FIXME:
-                        // Drop something.
                         supplement.add_entity(entity);
                     }
                 }

From 99e19dc5d0755b4649cb769e9d06fe2d4c48bfdc Mon Sep 17 00:00:00 2001
From: Sam <samuelkeiffer@gmail.com>
Date: Thu, 23 Sep 2021 14:43:31 -0400
Subject: [PATCH 06/14] Format fixes.

---
 assets/common/entity/spot/pirate.ron             | 6 +++---
 assets/common/entity/village/dummy.ron           | 2 +-
 assets/common/entity/wild/peaceful/goat.ron      | 2 +-
 assets/common/entity/wild/peaceful/holladon.ron  | 2 +-
 assets/common/entity/wild/peaceful/llama.ron     | 2 +-
 assets/common/entity/wild/peaceful/mouflon.ron   | 2 +-
 assets/common/entity/wild/peaceful/pig.ron       | 2 +-
 assets/common/entity/wild/peaceful/sand_hare.ron | 2 +-
 assets/common/entity/wild/peaceful/sheep.ron     | 2 +-
 server/src/events/entity_manipulation.rs         | 6 ++----
 10 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/assets/common/entity/spot/pirate.ron b/assets/common/entity/spot/pirate.ron
index a34722757c..1e5d89c5ff 100644
--- a/assets/common/entity/spot/pirate.ron
+++ b/assets/common/entity/spot/pirate.ron
@@ -1,9 +1,9 @@
 EntityConfig (
     name: Name("Pirate"),
     body: Exact(Humanoid(Body(
-        species: Human, 
-        body_type: Female, 
-        hair_style: 2, 
+        species: Human,
+        body_type: Female,
+        hair_style: 2,
         beard: 0,
         eyes: 0,
         accessory: 0,
diff --git a/assets/common/entity/village/dummy.ron b/assets/common/entity/village/dummy.ron
index c62a515143..45ad0082fa 100644
--- a/assets/common/entity/village/dummy.ron
+++ b/assets/common/entity/village/dummy.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: Exact(Object(TrainingDummy)),
     alignment: Alignment(Passive),
 
-    loot: None,
+    loot: Nothing,
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/goat.ron b/assets/common/entity/wild/peaceful/goat.ron
index 6f2e387932..676846a4fd 100644
--- a/assets/common/entity/wild/peaceful/goat.ron
+++ b/assets/common/entity/wild/peaceful/goat.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("goat"),
     alignment: Alignment(Wild),
 
-    loot: LootTable("common.loot_tables.creature.quad_small.wool")
+    loot: LootTable("common.loot_tables.creature.quad_small.wool"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/holladon.ron b/assets/common/entity/wild/peaceful/holladon.ron
index eb4d9e8c79..a86229ffc3 100644
--- a/assets/common/entity/wild/peaceful/holladon.ron
+++ b/assets/common/entity/wild/peaceful/holladon.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("holladon"),
     alignment: Alignment(Wild),
 
-    loot: LootTable("common.loot_tables.creature.quad_small.generic")
+    loot: LootTable("common.loot_tables.creature.quad_small.generic"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/llama.ron b/assets/common/entity/wild/peaceful/llama.ron
index 6b9ae9f5cc..146f3156b1 100644
--- a/assets/common/entity/wild/peaceful/llama.ron
+++ b/assets/common/entity/wild/peaceful/llama.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("llama"),
     alignment: Alignment(Wild),
 
-    loot: LootTable("common.loot_tables.creature.quad_medium.wool")
+    loot: LootTable("common.loot_tables.creature.quad_medium.wool"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/mouflon.ron b/assets/common/entity/wild/peaceful/mouflon.ron
index ea037f9a5a..4acf692f41 100644
--- a/assets/common/entity/wild/peaceful/mouflon.ron
+++ b/assets/common/entity/wild/peaceful/mouflon.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("mouflon"),
     alignment: Alignment(Wild),
 
-    loot: LootTable("common.loot_tables.creature.quad_medium.wool")
+    loot: LootTable("common.loot_tables.creature.quad_medium.wool"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/pig.ron b/assets/common/entity/wild/peaceful/pig.ron
index 8e642bd80e..67c6dea703 100644
--- a/assets/common/entity/wild/peaceful/pig.ron
+++ b/assets/common/entity/wild/peaceful/pig.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("pig"),
     alignment: Alignment(Wild),
 
-    loot: LootTable("common.loot_tables.creature.quad_small.generic")
+    loot: LootTable("common.loot_tables.creature.quad_small.generic"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/sand_hare.ron b/assets/common/entity/wild/peaceful/sand_hare.ron
index 80964c719f..6326bed01b 100644
--- a/assets/common/entity/wild/peaceful/sand_hare.ron
+++ b/assets/common/entity/wild/peaceful/sand_hare.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: Exact(QuadrupedSmall(Body(species: Hare, body_type: Male))),
     alignment: Alignment(Wild),
 
-    loot: LootTable("common.loot_tables.creature.quad_small.fur")
+    loot: LootTable("common.loot_tables.creature.quad_small.fur"),
 
     hands: Uninit,
 
diff --git a/assets/common/entity/wild/peaceful/sheep.ron b/assets/common/entity/wild/peaceful/sheep.ron
index b1ae6645b5..b1ff4216b7 100644
--- a/assets/common/entity/wild/peaceful/sheep.ron
+++ b/assets/common/entity/wild/peaceful/sheep.ron
@@ -3,7 +3,7 @@ EntityConfig (
     body: RandomWith("sheep"),
     alignment: Alignment(Wild),
 
-    loot: LootTable("common.loot_tables.creature.quad_small.wool")
+    loot: LootTable("common.loot_tables.creature.quad_small.wool"),
 
     hands: Uninit,
 
diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs
index d6cfda56c6..3d5652d14e 100644
--- a/server/src/events/entity_manipulation.rs
+++ b/server/src/events/entity_manipulation.rs
@@ -2,16 +2,14 @@ use crate::{
     client::Client,
     comp::{
         agent::{Agent, AgentEvent, Sound, SoundKind},
-        biped_large, bird_large, quadruped_low, quadruped_medium, quadruped_small,
         skills::SkillGroupKind,
-        theropod, BuffKind, BuffSource, PhysicsState,
+        BuffKind, BuffSource, PhysicsState,
     },
     rtsim::RtSim,
     sys::terrain::SAFE_ZONE_RADIUS,
     Server, SpawnPoint, StateExt,
 };
 use common::{
-    assets::AssetExt,
     combat,
     comp::{
         self, aura, buff,
@@ -21,7 +19,7 @@ use common::{
         Inventory, Player, Poise, Pos, SkillSet, Stats,
     },
     event::{EventBus, ServerEvent},
-    lottery::{LootSpec, Lottery},
+    lottery::LootSpec,
     outcome::Outcome,
     resources::Time,
     rtsim::RtSimEntity,

From 482194decb51d8ec8db173ee309135fdf2e00e98 Mon Sep 17 00:00:00 2001
From: Sam <samuelkeiffer@gmail.com>
Date: Thu, 23 Sep 2021 22:54:23 -0400
Subject: [PATCH 07/14] Cave now uses entity configs.

---
 .../entity/wild/aggressive/basilisk.ron       | 11 +++
 .../entity/wild/aggressive/blue_oni.ron       | 11 +++
 .../wild/aggressive/cave_salamander.ron       | 11 +++
 .../entity/wild/aggressive/cave_troll.ron     | 11 +++
 .../aggressive/{cyclope.ron => cyclops.ron}   |  0
 .../common/entity/wild/aggressive/red_oni.ron | 11 +++
 .../world/wildlife/spawn/temperate/rare.ron   |  2 +-
 world/src/layer/mod.rs                        | 94 +++++++------------
 8 files changed, 88 insertions(+), 63 deletions(-)
 create mode 100644 assets/common/entity/wild/aggressive/basilisk.ron
 create mode 100644 assets/common/entity/wild/aggressive/blue_oni.ron
 create mode 100644 assets/common/entity/wild/aggressive/cave_salamander.ron
 create mode 100644 assets/common/entity/wild/aggressive/cave_troll.ron
 rename assets/common/entity/wild/aggressive/{cyclope.ron => cyclops.ron} (100%)
 create mode 100644 assets/common/entity/wild/aggressive/red_oni.ron

diff --git a/assets/common/entity/wild/aggressive/basilisk.ron b/assets/common/entity/wild/aggressive/basilisk.ron
new file mode 100644
index 0000000000..ccd35c3234
--- /dev/null
+++ b/assets/common/entity/wild/aggressive/basilisk.ron
@@ -0,0 +1,11 @@
+EntityConfig (
+    name: Automatic,
+    body: RandomWith("basilisk"),
+    alignment: Alignment(Enemy),
+
+    loot: LootTable("common.loot_tables.creature.quad_low.basilisk"),
+
+    hands: Uninit,
+
+    meta: [],
+)
diff --git a/assets/common/entity/wild/aggressive/blue_oni.ron b/assets/common/entity/wild/aggressive/blue_oni.ron
new file mode 100644
index 0000000000..8f7ab3203f
--- /dev/null
+++ b/assets/common/entity/wild/aggressive/blue_oni.ron
@@ -0,0 +1,11 @@
+EntityConfig (
+    name: Automatic,
+    body: RandomWith("oni_blue"),
+    alignment: Alignment(Enemy),
+
+    loot: LootTable("common.loot_tables.creature.biped_large.default"),
+
+    hands: Uninit,
+
+    meta: [],
+)
diff --git a/assets/common/entity/wild/aggressive/cave_salamander.ron b/assets/common/entity/wild/aggressive/cave_salamander.ron
new file mode 100644
index 0000000000..9850bffb09
--- /dev/null
+++ b/assets/common/entity/wild/aggressive/cave_salamander.ron
@@ -0,0 +1,11 @@
+EntityConfig (
+    name: Automatic,
+    body: RandomWith("salamander"),
+    alignment: Alignment(Enemy),
+
+    loot: LootTable("common.loot_tables.creature.quad_low.salamander"),
+
+    hands: Uninit,
+
+    meta: [],
+)
diff --git a/assets/common/entity/wild/aggressive/cave_troll.ron b/assets/common/entity/wild/aggressive/cave_troll.ron
new file mode 100644
index 0000000000..a1d54dc12c
--- /dev/null
+++ b/assets/common/entity/wild/aggressive/cave_troll.ron
@@ -0,0 +1,11 @@
+EntityConfig (
+    name: Automatic,
+    body: RandomWith("troll_cave"),
+    alignment: Alignment(Enemy),
+
+    loot: LootTable("common.loot_tables.creature.biped_large.troll"),
+
+    hands: Uninit,
+
+    meta: [],
+)
diff --git a/assets/common/entity/wild/aggressive/cyclope.ron b/assets/common/entity/wild/aggressive/cyclops.ron
similarity index 100%
rename from assets/common/entity/wild/aggressive/cyclope.ron
rename to assets/common/entity/wild/aggressive/cyclops.ron
diff --git a/assets/common/entity/wild/aggressive/red_oni.ron b/assets/common/entity/wild/aggressive/red_oni.ron
new file mode 100644
index 0000000000..d553142e53
--- /dev/null
+++ b/assets/common/entity/wild/aggressive/red_oni.ron
@@ -0,0 +1,11 @@
+EntityConfig (
+    name: Automatic,
+    body: RandomWith("oni_red"),
+    alignment: Alignment(Enemy),
+
+    loot: LootTable("common.loot_tables.creature.biped_large.default"),
+
+    hands: Uninit,
+
+    meta: [],
+)
diff --git a/assets/world/wildlife/spawn/temperate/rare.ron b/assets/world/wildlife/spawn/temperate/rare.ron
index 790ff2b2db..00e53c1ac3 100644
--- a/assets/world/wildlife/spawn/temperate/rare.ron
+++ b/assets/world/wildlife/spawn/temperate/rare.ron
@@ -6,7 +6,7 @@ SpawnEntry (
             groups: [
                 (1, (1, 1, "common.entity.wild.aggressive.ogre")),
                 (1, (1, 1, "common.entity.wild.aggressive.swamp_troll")),
-                (1, (1, 1, "common.entity.wild.aggressive.cyclope")),
+                (1, (1, 1, "common.entity.wild.aggressive.cyclops")),
             ],
             is_underwater: false,
             day_period: [Night, Morning, Noon, Evening],
diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs
index c5e3091916..1ed4cc8410 100644
--- a/world/src/layer/mod.rs
+++ b/world/src/layer/mod.rs
@@ -12,7 +12,6 @@ use crate::{
 };
 use common::{
     assets::AssetExt,
-    comp,
     generation::{ChunkSupplement, EntityInfo},
     lottery::Lottery,
     terrain::{Block, BlockKind, SpriteKind},
@@ -454,68 +453,39 @@ pub fn apply_caves_supplement<'a>(
                         && cave_base < surface_z as i32 - 40
                     {
                         let entity = EntityInfo::at(wpos2d.map(|e| e as f32).with_z(z as f32));
-                        let entity = if cave_depth < 70.0 {
-                            let species = match dynamic_rng.gen_range(0..4) {
-                                0 => comp::quadruped_small::Species::Truffler,
-                                1 => comp::quadruped_small::Species::Dodarock,
-                                2 => comp::quadruped_small::Species::Holladon,
-                                _ => comp::quadruped_small::Species::Batfox,
+                        let entity = {
+                            let asset = if cave_depth < 70.0 {
+                                match dynamic_rng.gen_range(0..4) {
+                                    0 => "common.entity.wild.peaceful.truffler",
+                                    1 => "common.entity.wild.aggressive.dodarock",
+                                    2 => "common.entity.wild.peaceful.holladon",
+                                    _ => "common.entity.wild.aggressive.batfox",
+                                }
+                            } else if cave_depth < 120.0 {
+                                match dynamic_rng.gen_range(0..3) {
+                                    0 => "common.entity.wild.aggressive.rocksnapper",
+                                    1 => "common.entity.wild.aggressive.cave_salamander",
+                                    _ => "common.entity.wild.aggressive.asp",
+                                }
+                            } else if cave_depth < 190.0 {
+                                match dynamic_rng.gen_range(0..3) {
+                                    0 => "common.entity.wild.aggressive.rocksnapper",
+                                    1 => "common.entity.wild.aggressive.lavadrake",
+                                    _ => "common.entity.wild.aggressive.basilisk",
+                                }
+                            } else {
+                                match dynamic_rng.gen_range(0..5) {
+                                    0 => "common.entity.wild.aggressive.ogre",
+                                    1 => "common.entity.wild.aggressive.cyclops",
+                                    2 => "common.entity.wild.aggressive.wendigo",
+                                    3 => match dynamic_rng.gen_range(0..2) {
+                                        0 => "common.entity.wild.aggressive.blue_oni",
+                                        _ => "common.entity.wild.aggressive.red_oni",
+                                    },
+                                    _ => "common.entity.wild.aggressive.cave_troll",
+                                }
                             };
-                            let body =
-                                comp::quadruped_small::Body::random_with(dynamic_rng, &species);
-                            // FIXME:
-                            // Drop something.
-                            entity
-                                .with_body(body.into())
-                                .with_alignment(comp::Alignment::Wild)
-                                .with_automatic_name()
-                        } else if cave_depth < 120.0 {
-                            let species = match dynamic_rng.gen_range(0..3) {
-                                0 => comp::quadruped_low::Species::Rocksnapper,
-                                1 => comp::quadruped_low::Species::Salamander,
-                                _ => comp::quadruped_low::Species::Asp,
-                            };
-                            let body =
-                                comp::quadruped_low::Body::random_with(dynamic_rng, &species);
-                            // FIXME:
-                            // Drop something.
-                            entity
-                                .with_body(body.into())
-                                .with_alignment(comp::Alignment::Enemy)
-                                .with_automatic_name()
-                        } else if cave_depth < 190.0 {
-                            let species = match dynamic_rng.gen_range(0..3) {
-                                0 => comp::quadruped_low::Species::Rocksnapper,
-                                1 => comp::quadruped_low::Species::Lavadrake,
-                                _ => comp::quadruped_low::Species::Basilisk,
-                            };
-                            let body =
-                                comp::quadruped_low::Body::random_with(dynamic_rng, &species);
-                            // FIXME:
-                            // Drop something.
-                            entity
-                                .with_body(body.into())
-                                .with_alignment(comp::Alignment::Enemy)
-                                .with_automatic_name()
-                        } else {
-                            let species = match dynamic_rng.gen_range(0..5) {
-                                0 => comp::biped_large::Species::Ogre,
-                                1 => comp::biped_large::Species::Cyclops,
-                                2 => comp::biped_large::Species::Wendigo,
-                                3 => match dynamic_rng.gen_range(0..2) {
-                                    0 => comp::biped_large::Species::Blueoni,
-                                    _ => comp::biped_large::Species::Redoni,
-                                },
-                                _ => comp::biped_large::Species::Cavetroll,
-                            };
-
-                            let body = comp::biped_large::Body::random_with(dynamic_rng, &species);
-                            // FIXME:
-                            // Drop something.
-                            entity
-                                .with_body(body.into())
-                                .with_alignment(comp::Alignment::Enemy)
-                                .with_automatic_name()
+                            entity.with_asset_expect(asset)
                         };
 
                         supplement.add_entity(entity);

From 9a57b218ed033bf660798c71aff029f4ff09d9c0 Mon Sep 17 00:00:00 2001
From: Sam <samuelkeiffer@gmail.com>
Date: Fri, 24 Sep 2021 19:42:03 -0400
Subject: [PATCH 08/14] Rtsim now uses entity configs.

---
 server/src/rtsim/entity.rs |  64 ++++++++-------------
 server/src/rtsim/tick.rs   | 115 +++++++++++++++++--------------------
 server/src/sys/terrain.rs  |  12 +++-
 3 files changed, 86 insertions(+), 105 deletions(-)

diff --git a/server/src/rtsim/entity.rs b/server/src/rtsim/entity.rs
index b779b7fac1..09230a1c61 100644
--- a/server/src/rtsim/entity.rs
+++ b/server/src/rtsim/entity.rs
@@ -1,6 +1,5 @@
 use super::*;
 use common::{
-    comp::inventory::loadout_builder::LoadoutBuilder,
     resources::Time,
     rtsim::{Memory, MemoryItem},
     store::Id,
@@ -39,6 +38,8 @@ const PERM_GENUS: u32 = 4;
 impl Entity {
     pub fn rng(&self, perm: u32) -> impl Rng { RandomPerm::new(self.seed + perm) }
 
+    pub fn loadout_rng(&self) -> impl Rng { self.rng(PERM_LOADOUT) }
+
     pub fn get_body(&self) -> comp::Body {
         match self.kind {
             RtSimEntityKind::Random => {
@@ -81,47 +82,30 @@ impl Entity {
         }
     }
 
-    pub fn get_name(&self) -> String {
-        match self.kind {
-            RtSimEntityKind::Random => {
-                use common::{generation::get_npc_name, npc::NPC_NAMES};
-                let npc_names = NPC_NAMES.read();
-                match self.get_body() {
-                    comp::Body::BirdMedium(b) => {
-                        get_npc_name(&npc_names.bird_medium, b.species).to_string()
-                    },
-                    comp::Body::BirdLarge(b) => {
-                        get_npc_name(&npc_names.bird_large, b.species).to_string()
-                    },
-                    comp::Body::Dragon(b) => get_npc_name(&npc_names.dragon, b.species).to_string(),
-                    comp::Body::Humanoid(b) => {
-                        get_npc_name(&npc_names.humanoid, b.species).to_string()
-                    },
-                    comp::Body::Ship(_) => "Veloren Air".to_string(),
-                    //TODO: finish match as necessary
-                    _ => unimplemented!(),
-                }
+    pub fn get_entity_config(&self) -> &str {
+        match self.get_body() {
+            comp::Body::Humanoid(_) => match self.kind {
+                RtSimEntityKind::Cultist => "",
+                RtSimEntityKind::Random => "",
             },
-            RtSimEntityKind::Cultist => "Cultist Raider".to_string(),
-        }
-    }
-
-    pub fn get_loadout(&self) -> comp::inventory::loadout::Loadout {
-        let mut rng = self.rng(PERM_LOADOUT);
-        match self.kind {
-            RtSimEntityKind::Random => {
-                LoadoutBuilder::from_asset_expect("common.loadout.world.traveler", Some(&mut rng))
-                    .bag(
-                        comp::inventory::slot::ArmorSlot::Bag1,
-                        Some(comp::inventory::loadout_builder::make_potion_bag(100)),
-                    )
-                    .build()
+            comp::Body::BirdMedium(b) => match b.species {
+                comp::bird_medium::Species::Duck => "",
+                comp::bird_medium::Species::Chicken => "",
+                comp::bird_medium::Species::Goose => "",
+                comp::bird_medium::Species::Peacock => "",
+                comp::bird_medium::Species::Eagle => "",
+                comp::bird_medium::Species::Owl => "",
+                comp::bird_medium::Species::Parrot => "",
             },
-            RtSimEntityKind::Cultist => LoadoutBuilder::from_asset_expect(
-                "common.loadout.dungeon.tier-5.cultist",
-                Some(&mut rng),
-            )
-            .build(),
+            comp::Body::BirdLarge(b) => match b.species {
+                comp::bird_large::Species::Phoenix => "",
+                comp::bird_large::Species::Cockatrice => "",
+                comp::bird_large::Species::Roc => "",
+                // Wildcard match used here as there is an array above which limits what species are
+                // used
+                _ => unimplemented!(),
+            },
+            _ => unimplemented!(),
         }
     }
 
diff --git a/server/src/rtsim/tick.rs b/server/src/rtsim/tick.rs
index 7728671edc..aedbf66b77 100644
--- a/server/src/rtsim/tick.rs
+++ b/server/src/rtsim/tick.rs
@@ -1,9 +1,11 @@
 #![allow(dead_code)] // TODO: Remove this when rtsim is fleshed out
 
 use super::*;
+use crate::sys::terrain::NpcData;
 use common::{
-    comp::{self, inventory::loadout_builder::LoadoutBuilder, Behavior, BehaviorCapability},
+    comp,
     event::{EventBus, ServerEvent},
+    generation::EntityInfo,
     resources::{DeltaTime, Time},
     terrain::TerrainGrid,
 };
@@ -106,75 +108,62 @@ impl<'a> System<'a> for Sys {
         for id in to_reify {
             rtsim.reify_entity(id);
             let entity = &rtsim.entities[id];
+            let entity_config = entity.get_entity_config();
+            let rtsim_entity = Some(RtSimEntity(id));
             let body = entity.get_body();
-            let alignment = match body {
-                comp::Body::Humanoid(_) => match entity.kind {
-                    RtSimEntityKind::Random => comp::Alignment::Npc,
-                    RtSimEntityKind::Cultist => comp::Alignment::Enemy,
-                },
-                comp::Body::BirdLarge(bird_large) => match bird_large.species {
-                    comp::bird_large::Species::Roc => comp::Alignment::Enemy,
-                    comp::bird_large::Species::Cockatrice => comp::Alignment::Enemy,
-                    _ => comp::Alignment::Wild,
-                },
-                _ => comp::Alignment::Wild,
-            };
             let spawn_pos = terrain
                 .find_space(entity.pos.map(|e| e.floor() as i32))
                 .map(|e| e as f32)
                 + Vec3::new(0.5, 0.5, body.flying_height());
             let pos = comp::Pos(spawn_pos);
-            let mut agent = Some(comp::Agent::from_body(&body).with_behavior(
-                if matches!(body, comp::Body::Humanoid(_)) {
-                    Behavior::from(BehaviorCapability::SPEAK)
-                } else {
-                    Behavior::default()
-                },
-            ));
-
-            if matches!(alignment, comp::Alignment::Enemy) {
-                agent = agent.map(|a| a.with_aggro_no_warn());
-            }
-
-            let rtsim_entity = Some(RtSimEntity(id));
-
-            // TODO: this should be a bit more intelligent
-            let loadout = match body {
-                comp::Body::Humanoid(_) => entity.get_loadout(),
-                _ => LoadoutBuilder::empty().with_default_maintool(&body).build(),
-            };
-
-            let event = match body {
-                comp::Body::Ship(ship) => ServerEvent::CreateShip {
-                    pos,
-                    ship,
-                    mountable: false,
-                    agent,
-                    rtsim_entity,
-                },
-                _ => ServerEvent::CreateNpc {
-                    pos: comp::Pos(spawn_pos),
-                    stats: comp::Stats::new(entity.get_name()),
-                    skill_set: comp::SkillSet::default(),
-                    health: Some(comp::Health::new(body, 10)),
-                    loadout,
-                    poise: comp::Poise::new(body),
-                    body,
-                    agent,
-                    alignment,
-                    scale: match body {
-                        comp::Body::Ship(_) => comp::Scale(comp::ship::AIRSHIP_SCALE),
-                        _ => comp::Scale(1.0),
+            let mut loadout_rng = entity.loadout_rng();
+            let entity_info = NpcData::from_entity_info(
+                EntityInfo::at(pos.0).with_asset_expect(entity_config),
+                &mut loadout_rng,
+            );
+            if let NpcData::Data {
+                pos,
+                stats,
+                skill_set,
+                health,
+                poise,
+                loadout,
+                agent,
+                // Body discarded here so that species and body type are consistent between
+                // reifications
+                body: _,
+                alignment,
+                scale,
+                drop_item,
+            } = entity_info
+            {
+                let event = match body {
+                    comp::Body::Ship(ship) => ServerEvent::CreateShip {
+                        pos,
+                        ship,
+                        mountable: false,
+                        agent,
+                        rtsim_entity,
                     },
-                    // FIXME;
-                    // Drop loot
-                    drop_item: None,
-                    anchor: None,
-                    rtsim_entity,
-                    projectile: None,
-                },
-            };
-            server_emitter.emit(event);
+                    _ => ServerEvent::CreateNpc {
+                        pos,
+                        stats,
+                        skill_set,
+                        health,
+                        poise,
+                        loadout,
+                        agent,
+                        body,
+                        alignment,
+                        scale,
+                        anchor: None,
+                        drop_item,
+                        rtsim_entity,
+                        projectile: None,
+                    },
+                };
+                server_emitter.emit(event);
+            }
         }
 
         // Update rtsim with real entity data
diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs
index 90a2534eeb..3714f9137e 100644
--- a/server/src/sys/terrain.rs
+++ b/server/src/sys/terrain.rs
@@ -364,7 +364,7 @@ pub enum NpcData {
 }
 
 impl NpcData {
-    pub fn from_entity_info(entity: EntityInfo, rng: &mut impl Rng) -> Self {
+    pub fn from_entity_info(entity: EntityInfo, loadout_rng: &mut impl Rng) -> Self {
         let EntityInfo {
             // flags
             is_waypoint,
@@ -423,7 +423,7 @@ impl NpcData {
             // If there is config, apply it.
             // If not, use default equipement for this body.
             if let Some(asset) = loadout_asset {
-                loadout_builder = loadout_builder.with_asset_expect(&asset, rng);
+                loadout_builder = loadout_builder.with_asset_expect(&asset, loadout_rng);
             } else {
                 loadout_builder = loadout_builder.with_default_equipment(&body);
             }
@@ -465,6 +465,14 @@ impl NpcData {
                 .with_no_flee(!matches!(agent_mark, Some(agent::Mark::Guard)))
         });
 
+        let agent = if matches!(alignment, comp::Alignment::Enemy)
+            && matches!(body, comp::Body::Humanoid(_))
+        {
+            agent.map(|a| a.with_aggro_no_warn())
+        } else {
+            agent
+        };
+
         NpcData::Data {
             pos: Pos(pos),
             stats,

From 98382ea0120504376bb9c87af9dce5c2e8228f1a Mon Sep 17 00:00:00 2001
From: juliancoffee <lightdarkdaughter@gmail.com>
Date: Sat, 25 Sep 2021 22:30:17 +0300
Subject: [PATCH 09/14] Make Rtsim entity config work

---
 Cargo.lock                                    |   1 +
 assets/common/entity/wild/aggressive/roc.ron  |  11 ++
 .../common/entity/wild/peaceful/phoenix.ron   |  11 ++
 assets/common/entity/world/traveler.ron       |  18 +++
 assets/common/loadout/world/traveler.ron      |   6 -
 common/src/generation.rs                      |   4 +-
 server/Cargo.toml                             |   1 +
 server/src/rtsim/entity.rs                    | 137 ++++++++++++++----
 server/src/rtsim/mod.rs                       |   3 +-
 server/src/rtsim/tick.rs                      |  70 +++++----
 10 files changed, 194 insertions(+), 68 deletions(-)
 create mode 100644 assets/common/entity/wild/aggressive/roc.ron
 create mode 100644 assets/common/entity/wild/peaceful/phoenix.ron
 create mode 100644 assets/common/entity/world/traveler.ron

diff --git a/Cargo.lock b/Cargo.lock
index d592098e18..1faa8b3121 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6195,6 +6195,7 @@ dependencies = [
  "slab",
  "specs",
  "specs-idvs",
+ "strum",
  "tokio",
  "tracing",
  "vek",
diff --git a/assets/common/entity/wild/aggressive/roc.ron b/assets/common/entity/wild/aggressive/roc.ron
new file mode 100644
index 0000000000..89dc8d71b8
--- /dev/null
+++ b/assets/common/entity/wild/aggressive/roc.ron
@@ -0,0 +1,11 @@
+EntityConfig (
+    name: Automatic,
+    body: RandomWith("roc"),
+    alignment: Alignment(Enemy),
+
+    loot: LootTable("common.loot_tables.creature.bird_large.roc"),
+
+    hands: Uninit,
+
+    meta: [],
+)
diff --git a/assets/common/entity/wild/peaceful/phoenix.ron b/assets/common/entity/wild/peaceful/phoenix.ron
new file mode 100644
index 0000000000..a434f6c5f6
--- /dev/null
+++ b/assets/common/entity/wild/peaceful/phoenix.ron
@@ -0,0 +1,11 @@
+EntityConfig (
+    name: Automatic,
+    body: RandomWith("phoenix"),
+    alignment: Alignment(Wild),
+
+    loot: LootTable("common.loot_tables.creature.bird_large.phoenix"),
+
+    hands: Uninit,
+
+    meta: [],
+)
diff --git a/assets/common/entity/world/traveler.ron b/assets/common/entity/world/traveler.ron
new file mode 100644
index 0000000000..6d9e0fd1b4
--- /dev/null
+++ b/assets/common/entity/world/traveler.ron
@@ -0,0 +1,18 @@
+EntityConfig (
+    name: Automatic,
+    body: RandomWith("humanoid"),
+    alignment: Alignment(Npc),
+
+    loot: LootTable("common.loot_tables.creature.humanoid"),
+
+    hands: TwoHanded(Choice([
+        (1.0, Some(Item("common.items.weapons.sword.iron-0"))),
+        (1.0, Some(Item("common.items.weapons.bow.hardwood-2"))),
+        (1.0, Some(Item("common.items.weapons.axe.steel_axe-0"))),
+        (1.0, Some(Item("common.items.weapons.staff.frostwood_torch"))),
+    ])),
+
+    meta: [
+        LoadoutAsset("common.loadout.world.traveler"),
+    ],
+)
diff --git a/assets/common/loadout/world/traveler.ron b/assets/common/loadout/world/traveler.ron
index c4759de18a..1b54dc663c 100644
--- a/assets/common/loadout/world/traveler.ron
+++ b/assets/common/loadout/world/traveler.ron
@@ -1,10 +1,4 @@
 ({
-    ActiveMainhand: Choice([
-        (1.0, Some(Item("common.items.weapons.sword.iron-0"))),
-        (1.0, Some(Item("common.items.weapons.bow.hardwood-2"))),
-        (1.0, Some(Item("common.items.weapons.axe.steel_axe-0"))),
-        (1.0, Some(Item("common.items.weapons.staff.frostwood_torch"))),
-    ]),
 
     Armor(Chest): Item("common.items.npc_armor.chest.leather_blue"),
     Armor(Legs): Item("common.items.npc_armor.pants.leather_blue"),
diff --git a/common/src/generation.rs b/common/src/generation.rs
index b4686a510f..167fe8da67 100644
--- a/common/src/generation.rs
+++ b/common/src/generation.rs
@@ -110,8 +110,8 @@ pub struct EntityConfig {
     /// Hands:
     /// - TwoHanded(ItemSpec) for one 2h or 1h weapon,
     /// - Paired(ItemSpec) for two 1h weapons aka berserker mode,
-    /// - Mix { mainhand: ItemSpec, offhand: ItemSpec,
-    /// } for two different 1h weapons,
+    /// - Mix { mainhand: ItemSpec, offhand: ItemSpec, }
+    ///  for two different 1h weapons,
     /// - Uninit which means that tool should be specified somewhere in code,
     /// Where ItemSpec is taken from loadout_builder module
     // TODO: better name for this?
diff --git a/server/Cargo.toml b/server/Cargo.toml
index 2d1ae645b1..0d331fada3 100644
--- a/server/Cargo.toml
+++ b/server/Cargo.toml
@@ -28,6 +28,7 @@ network = { package = "veloren-network", path = "../network", features = ["metri
 specs = { git = "https://github.com/amethyst/specs.git", features = ["shred-derive"], rev = "f985bec5d456f7b0dd8aae99848f9473c2cd9d46" }
 specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git", rev = "8be2abcddf8f524cb5876e8dd20a7e47cfaf7573" }
 
+strum = { version = "0.21", features = ["derive"] }
 bincode = "1.3.2"
 num_cpus = "1.0"
 tracing = "0.1"
diff --git a/server/src/rtsim/entity.rs b/server/src/rtsim/entity.rs
index 09230a1c61..8ffff701f5 100644
--- a/server/src/rtsim/entity.rs
+++ b/server/src/rtsim/entity.rs
@@ -1,9 +1,11 @@
 use super::*;
 use common::{
+    comp::inventory::{loadout_builder::make_potion_bag, slot::ArmorSlot},
     resources::Time,
     rtsim::{Memory, MemoryItem},
     store::Id,
     terrain::TerrainGrid,
+    trade, LoadoutBuilder,
 };
 use rand_distr::{Distribution, Normal};
 use std::f32::consts::PI;
@@ -24,11 +26,19 @@ pub struct Entity {
     pub brain: Brain,
 }
 
+#[derive(Clone, Copy, strum::EnumIter)]
 pub enum RtSimEntityKind {
     Random,
     Cultist,
 }
 
+const BIRD_LARGE_ROSTER: &[comp::bird_large::Species] = &[
+    // Flame Wyvern not incuded until proper introduction
+    comp::bird_large::Species::Phoenix,
+    comp::bird_large::Species::Cockatrice,
+    comp::bird_large::Species::Roc,
+];
+
 const PERM_SPECIES: u32 = 0;
 const PERM_BODY: u32 = 1;
 const PERM_LOADOUT: u32 = 2;
@@ -54,12 +64,7 @@ impl Entity {
                             .into()
                     },
                     x if x < 0.50 => {
-                        let species = *(&[
-                            // Flame Wyvern not incuded until proper introduction
-                            comp::bird_large::Species::Phoenix,
-                            comp::bird_large::Species::Cockatrice,
-                            comp::bird_large::Species::Roc,
-                        ])
+                        let species = *BIRD_LARGE_ROSTER
                             .choose(&mut self.rng(PERM_SPECIES))
                             .unwrap();
                         comp::bird_large::Body::random_with(&mut self.rng(PERM_BODY), &species)
@@ -84,31 +89,26 @@ impl Entity {
 
     pub fn get_entity_config(&self) -> &str {
         match self.get_body() {
-            comp::Body::Humanoid(_) => match self.kind {
-                RtSimEntityKind::Cultist => "",
-                RtSimEntityKind::Random => "",
-            },
-            comp::Body::BirdMedium(b) => match b.species {
-                comp::bird_medium::Species::Duck => "",
-                comp::bird_medium::Species::Chicken => "",
-                comp::bird_medium::Species::Goose => "",
-                comp::bird_medium::Species::Peacock => "",
-                comp::bird_medium::Species::Eagle => "",
-                comp::bird_medium::Species::Owl => "",
-                comp::bird_medium::Species::Parrot => "",
-            },
-            comp::Body::BirdLarge(b) => match b.species {
-                comp::bird_large::Species::Phoenix => "",
-                comp::bird_large::Species::Cockatrice => "",
-                comp::bird_large::Species::Roc => "",
-                // Wildcard match used here as there is an array above which limits what species are
-                // used
-                _ => unimplemented!(),
-            },
+            comp::Body::Humanoid(_) => humanoid_config(self.kind),
+            comp::Body::BirdMedium(b) => bird_medium_config(b),
+            comp::Body::BirdLarge(b) => bird_large_config(b),
             _ => unimplemented!(),
         }
     }
 
+    pub fn get_adhoc_loadout(
+        &self,
+    ) -> fn(LoadoutBuilder, Option<&trade::SiteInformation>) -> LoadoutBuilder {
+        let body = self.get_body();
+        let kind = &self.kind;
+        // give potions to traveler humanoids or return loadout as is otherwise
+        if let (comp::Body::Humanoid(_), RtSimEntityKind::Random) = (body, kind) {
+            |l, _| l.bag(ArmorSlot::Bag1, Some(make_potion_bag(100)))
+        } else {
+            |l, _| l
+        }
+    }
+
     pub fn tick(&mut self, time: &Time, terrain: &TerrainGrid, world: &World, index: &IndexRef) {
         self.brain.route = match self.brain.route.clone() {
             Travel::Lost => {
@@ -706,3 +706,86 @@ impl Brain {
         })
     }
 }
+
+fn humanoid_config(kind: RtSimEntityKind) -> &'static str {
+    match kind {
+        RtSimEntityKind::Cultist => "common.entity.dungeon.tier-5.cultist",
+        RtSimEntityKind::Random => "common.entity.world.traveler",
+    }
+}
+
+fn bird_medium_config(body: comp::bird_medium::Body) -> &'static str {
+    match body.species {
+        comp::bird_medium::Species::Duck => "common.entity.wild.peaceful.duck",
+        comp::bird_medium::Species::Chicken => "common.entity.wild.peaceful.chicken",
+        comp::bird_medium::Species::Goose => "common.entity.wild.peaceful.goose",
+        comp::bird_medium::Species::Peacock => "common.entity.wild.peaceful.peacock",
+        comp::bird_medium::Species::Eagle => "common.entity.wild.peaceful.eagle",
+        comp::bird_medium::Species::Owl => "common.entity.wild.peaceful.owl",
+        comp::bird_medium::Species::Parrot => "common.entity.wild.peaceful.parrot",
+    }
+}
+
+fn bird_large_config(body: comp::bird_large::Body) -> &'static str {
+    match body.species {
+        comp::bird_large::Species::Phoenix => "common.entity.wild.peaceful.phoenix",
+        comp::bird_large::Species::Cockatrice => "common.entity.wild.aggressive.cockatrice",
+        comp::bird_large::Species::Roc => "common.entity.wild.aggressive.roc",
+        // Wildcard match used here as there is an array above
+        // which limits what species are used
+        _ => unimplemented!(),
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use common::generation::EntityInfo;
+    use strum::IntoEnumIterator;
+
+    // Brief, Incomplete and Mostly Wrong Test that all entity configs do exist.
+    //
+    // NOTE: Doesn't checks for ships, because we don't produce entity configs
+    // for them yet.
+    #[test]
+    fn test_entity_configs() {
+        let dummy_pos = Vec3::new(0.0, 0.0, 0.0);
+        // Bird Large test
+        for bird_large_species in BIRD_LARGE_ROSTER {
+            let female_body = comp::bird_large::Body {
+                species: *bird_large_species,
+                body_type: comp::bird_large::BodyType::Female,
+            };
+            let male_body = comp::bird_large::Body {
+                species: *bird_large_species,
+                body_type: comp::bird_large::BodyType::Male,
+            };
+
+            let female_config = bird_large_config(female_body);
+            std::mem::drop(EntityInfo::at(dummy_pos).with_asset_expect(female_config));
+            let male_config = bird_large_config(male_body);
+            std::mem::drop(EntityInfo::at(dummy_pos).with_asset_expect(male_config));
+        }
+        // Bird Medium test
+        for bird_med_species in comp::bird_medium::ALL_SPECIES {
+            let female_body = comp::bird_medium::Body {
+                species: bird_med_species,
+                body_type: comp::bird_medium::BodyType::Female,
+            };
+            let male_body = comp::bird_medium::Body {
+                species: bird_med_species,
+                body_type: comp::bird_medium::BodyType::Male,
+            };
+
+            let female_config = bird_medium_config(female_body);
+            std::mem::drop(EntityInfo::at(dummy_pos).with_asset_expect(female_config));
+            let male_config = bird_medium_config(male_body);
+            std::mem::drop(EntityInfo::at(dummy_pos).with_asset_expect(male_config));
+        }
+        // Humanoid test
+        for kind in RtSimEntityKind::iter() {
+            let config = humanoid_config(kind);
+            std::mem::drop(EntityInfo::at(dummy_pos).with_asset_expect(config));
+        }
+    }
+}
diff --git a/server/src/rtsim/mod.rs b/server/src/rtsim/mod.rs
index c48a40f514..e81598d810 100644
--- a/server/src/rtsim/mod.rs
+++ b/server/src/rtsim/mod.rs
@@ -166,7 +166,8 @@ pub fn init(
                             .iter()
                             .filter(|&(site_id, site)| {
                                 site.is_settlement()
-                                    // TODO: Remove this later, starting town should not be special-cased
+                                    // TODO: Remove this later, starting town should not be
+                                    // special-cased
                                     && spawn_town_id.map_or(false, |spawn_id| spawn_id != site_id)
                             })
                             .min_by_key(|(_, site)| {
diff --git a/server/src/rtsim/tick.rs b/server/src/rtsim/tick.rs
index aedbf66b77..abd0657f1b 100644
--- a/server/src/rtsim/tick.rs
+++ b/server/src/rtsim/tick.rs
@@ -108,44 +108,49 @@ impl<'a> System<'a> for Sys {
         for id in to_reify {
             rtsim.reify_entity(id);
             let entity = &rtsim.entities[id];
-            let entity_config = entity.get_entity_config();
             let rtsim_entity = Some(RtSimEntity(id));
+
             let body = entity.get_body();
             let spawn_pos = terrain
                 .find_space(entity.pos.map(|e| e.floor() as i32))
                 .map(|e| e as f32)
                 + Vec3::new(0.5, 0.5, body.flying_height());
+
             let pos = comp::Pos(spawn_pos);
-            let mut loadout_rng = entity.loadout_rng();
-            let entity_info = NpcData::from_entity_info(
-                EntityInfo::at(pos.0).with_asset_expect(entity_config),
-                &mut loadout_rng,
-            );
-            if let NpcData::Data {
-                pos,
-                stats,
-                skill_set,
-                health,
-                poise,
-                loadout,
-                agent,
-                // Body discarded here so that species and body type are consistent between
-                // reifications
-                body: _,
-                alignment,
-                scale,
-                drop_item,
-            } = entity_info
-            {
-                let event = match body {
-                    comp::Body::Ship(ship) => ServerEvent::CreateShip {
+
+            let event = if let comp::Body::Ship(ship) = body {
+                ServerEvent::CreateShip {
+                    pos,
+                    ship,
+                    mountable: false,
+                    agent: Some(comp::Agent::from_body(&body)),
+                    rtsim_entity,
+                }
+            } else {
+                let entity_config = entity.get_entity_config();
+                let mut loadout_rng = entity.loadout_rng();
+                let ad_hoc_loadout = entity.get_adhoc_loadout();
+                // Body is rewritten so that body parameters
+                // are consistent between reifications
+                let entity_info = EntityInfo::at(pos.0)
+                    .with_asset_expect(entity_config)
+                    .with_lazy_loadout(ad_hoc_loadout)
+                    .with_body(body)
+                    .with_health_scaling(10);
+                match NpcData::from_entity_info(entity_info, &mut loadout_rng) {
+                    NpcData::Data {
                         pos,
-                        ship,
-                        mountable: false,
+                        stats,
+                        skill_set,
+                        health,
+                        poise,
+                        loadout,
                         agent,
-                        rtsim_entity,
-                    },
-                    _ => ServerEvent::CreateNpc {
+                        body,
+                        alignment,
+                        scale,
+                        drop_item,
+                    } => ServerEvent::CreateNpc {
                         pos,
                         stats,
                         skill_set,
@@ -161,9 +166,10 @@ impl<'a> System<'a> for Sys {
                         rtsim_entity,
                         projectile: None,
                     },
-                };
-                server_emitter.emit(event);
-            }
+                    NpcData::Waypoint(_) => unimplemented!(),
+                }
+            };
+            server_emitter.emit(event);
         }
 
         // Update rtsim with real entity data

From e9e63997e8e971ff2e21736d3bd44970fdc88e98 Mon Sep 17 00:00:00 2001
From: juliancoffee <lightdarkdaughter@gmail.com>
Date: Sun, 26 Sep 2021 20:19:24 +0300
Subject: [PATCH 10/14] Adress review

- Mention failed loot specifier during getting item from lottery
---
 common/src/lottery.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/common/src/lottery.rs b/common/src/lottery.rs
index 301b1facb4..46c26399b5 100644
--- a/common/src/lottery.rs
+++ b/common/src/lottery.rs
@@ -93,7 +93,7 @@ impl<T: AsRef<str>> LootSpec<T> {
         match self {
             Self::Item(item) => Item::new_from_asset(item.as_ref()).map_or_else(
                 |e| {
-                    warn!(?e, "Invalid item path");
+                    warn!(?e, "error while loading item: {}", item.as_ref());
                     None
                 },
                 Option::Some,
@@ -110,7 +110,7 @@ impl<T: AsRef<str>> LootSpec<T> {
                         Some(item)
                     },
                     Err(e) => {
-                        warn!(?e, "Invalid item path");
+                        warn!(?e, "error while loading item: {}", item.as_ref());
                         None
                     },
                 }

From 3c0211bf0b03e14d0cf1157c386b3fc68c5d16bc Mon Sep 17 00:00:00 2001
From: juliancoffee <lightdarkdaughter@gmail.com>
Date: Sun, 26 Sep 2021 20:34:54 +0300
Subject: [PATCH 11/14] Adress review

- Added comments on why Waypoint branch of NpcData is unreachable.
- Added comments on signature of get_adhoc_loadout.
---
 server/src/rtsim/entity.rs | 3 +++
 server/src/rtsim/tick.rs   | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/server/src/rtsim/entity.rs b/server/src/rtsim/entity.rs
index 8ffff701f5..5c4afcb4b9 100644
--- a/server/src/rtsim/entity.rs
+++ b/server/src/rtsim/entity.rs
@@ -96,6 +96,9 @@ impl Entity {
         }
     }
 
+    /// Escape hatch for runtime creation of loadout not covered by entity config.
+    // NOTE: Signature is part of interface of EntityInfo, and site information
+    // is not used for RtSim as of now.
     pub fn get_adhoc_loadout(
         &self,
     ) -> fn(LoadoutBuilder, Option<&trade::SiteInformation>) -> LoadoutBuilder {
diff --git a/server/src/rtsim/tick.rs b/server/src/rtsim/tick.rs
index abd0657f1b..3769526538 100644
--- a/server/src/rtsim/tick.rs
+++ b/server/src/rtsim/tick.rs
@@ -166,6 +166,9 @@ impl<'a> System<'a> for Sys {
                         rtsim_entity,
                         projectile: None,
                     },
+                    // EntityConfig can't represent Waypoints at all
+                    // as of now, and if someone will try to spawn
+                    // rtsim waypoint it is definitely error.
                     NpcData::Waypoint(_) => unimplemented!(),
                 }
             };

From b423faa32cc85765635b7515a7c44c606687e582 Mon Sep 17 00:00:00 2001
From: juliancoffee <lightdarkdaughter@gmail.com>
Date: Mon, 27 Sep 2021 11:18:25 +0300
Subject: [PATCH 12/14] Fix csv tools for loot tables

---
 common/src/bin/csv_export/main.rs | 2 +-
 common/src/bin/csv_import/main.rs | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/common/src/bin/csv_export/main.rs b/common/src/bin/csv_export/main.rs
index d1b8776864..f2e16a8e75 100644
--- a/common/src/bin/csv_export/main.rs
+++ b/common/src/bin/csv_export/main.rs
@@ -267,7 +267,7 @@ fn loot_table(loot_table: &str) -> Result<(), Box<dyn Error>> {
             LootSpec::LootTable(table) => {
                 wtr.write_record(&[&chance, "LootTable", table, "", ""])?
             },
-            LootSpec::None => wtr.write_record(&[&chance, "None", "", ""])?,
+            LootSpec::Nothing => wtr.write_record(&[&chance, "Nothing", "", ""])?,
         }
     }
 
diff --git a/common/src/bin/csv_import/main.rs b/common/src/bin/csv_import/main.rs
index 671d8b766b..609c5059d4 100644
--- a/common/src/bin/csv_import/main.rs
+++ b/common/src/bin/csv_import/main.rs
@@ -468,9 +468,9 @@ fn loot_table(loot_table: &str) -> Result<(), Box<dyn Error>> {
                     .expect("No loot table")
                     .to_string(),
             ),
-            "None" => LootSpec::None,
+            "Nothing" => LootSpec::Nothing,
             a => panic!(
-                "Loot specifier kind must be either \"Item\", \"LootTable\", or \"None\"\n{}",
+                "Loot specifier kind must be either \"Item\", \"LootTable\", or \"Nothing\"\n{}",
                 a
             ),
         };

From 7df22ceaec75790a527cf3d09046bbcfe693f311 Mon Sep 17 00:00:00 2001
From: juliancoffee <lightdarkdaughter@gmail.com>
Date: Mon, 27 Sep 2021 20:36:18 +0300
Subject: [PATCH 13/14] Make ItemDrop component with Item again

---
 common/src/comp/inventory/item/mod.rs    |  5 ++---
 common/src/event.rs                      |  2 +-
 common/src/generation.rs                 |  6 +++---
 common/src/states/basic_summon.rs        |  2 +-
 common/state/src/state.rs                |  2 +-
 server/src/cmd.rs                        |  4 ++--
 server/src/events/entity_creation.rs     |  4 ++--
 server/src/events/entity_manipulation.rs | 10 +++-------
 server/src/events/mod.rs                 |  4 ++--
 server/src/rtsim/entity.rs               |  3 ++-
 server/src/rtsim/tick.rs                 |  4 ++--
 server/src/sys/terrain.rs                | 10 +++++-----
 12 files changed, 26 insertions(+), 30 deletions(-)

diff --git a/common/src/comp/inventory/item/mod.rs b/common/src/comp/inventory/item/mod.rs
index b262a64420..547fd2a8a0 100644
--- a/common/src/comp/inventory/item/mod.rs
+++ b/common/src/comp/inventory/item/mod.rs
@@ -13,7 +13,6 @@ use crate::{
         CharacterAbility,
     },
     effect::Effect,
-    lottery::LootSpec,
     recipe::RecipeInput,
     terrain::Block,
 };
@@ -871,9 +870,9 @@ impl Component for Item {
 // }
 
 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
-pub struct ItemDrop<T: AsRef<str>>(pub LootSpec<T>);
+pub struct ItemDrop(pub Item);
 
-impl Component for ItemDrop<String> {
+impl Component for ItemDrop {
     type Storage = IdvStorage<Self>;
 }
 
diff --git a/common/src/event.rs b/common/src/event.rs
index e271d4000d..c9eded34a1 100644
--- a/common/src/event.rs
+++ b/common/src/event.rs
@@ -134,7 +134,7 @@ pub enum ServerEvent {
         alignment: comp::Alignment,
         scale: comp::Scale,
         anchor: Option<comp::Anchor>,
-        drop_item: Option<LootSpec<String>>,
+        loot: LootSpec<String>,
         rtsim_entity: Option<RtSimEntity>,
         projectile: Option<comp::Projectile>,
     },
diff --git a/common/src/generation.rs b/common/src/generation.rs
index 167fe8da67..efb16b1b3f 100644
--- a/common/src/generation.rs
+++ b/common/src/generation.rs
@@ -160,7 +160,7 @@ pub struct EntityInfo {
     pub scale: f32,
     // TODO: Properly give NPCs skills
     pub health_scaling: Option<u16>,
-    pub loot_drop: Option<LootSpec<String>>,
+    pub loot: LootSpec<String>,
     pub loadout_asset: Option<String>,
     pub make_loadout: Option<fn(LoadoutBuilder, Option<&trade::SiteInformation>) -> LoadoutBuilder>,
     pub skillset_asset: Option<String>,
@@ -184,7 +184,7 @@ impl EntityInfo {
             second_tool: None,
             scale: 1.0,
             health_scaling: None,
-            loot_drop: None,
+            loot: LootSpec::Nothing,
             loadout_asset: None,
             make_loadout: None,
             skillset_asset: None,
@@ -337,7 +337,7 @@ impl EntityInfo {
     }
 
     pub fn with_loot_drop(mut self, loot_drop: LootSpec<String>) -> Self {
-        self.loot_drop = Some(loot_drop);
+        self.loot = loot_drop;
         self
     }
 
diff --git a/common/src/states/basic_summon.rs b/common/src/states/basic_summon.rs
index eab53dd47b..9ad22acf23 100644
--- a/common/src/states/basic_summon.rs
+++ b/common/src/states/basic_summon.rs
@@ -187,7 +187,7 @@ impl CharacterBehavior for Data {
                                 .scale
                                 .unwrap_or(comp::Scale(1.0)),
                             anchor: None,
-                            drop_item: Some(crate::lottery::LootSpec::Nothing),
+                            loot: crate::lottery::LootSpec::Nothing,
                             rtsim_entity: None,
                             projectile,
                         });
diff --git a/common/state/src/state.rs b/common/state/src/state.rs
index 141fc82d1b..599d6013d4 100644
--- a/common/state/src/state.rs
+++ b/common/state/src/state.rs
@@ -189,7 +189,7 @@ impl State {
         ecs.register::<comp::Waypoint>();
         ecs.register::<comp::Projectile>();
         ecs.register::<comp::Melee>();
-        ecs.register::<comp::ItemDrop<String>>();
+        ecs.register::<comp::ItemDrop>();
         ecs.register::<comp::ChatMode>();
         ecs.register::<comp::Faction>();
         ecs.register::<comp::invite::Invite>();
diff --git a/server/src/cmd.rs b/server/src/cmd.rs
index a214a4baf5..375e4ccc08 100644
--- a/server/src/cmd.rs
+++ b/server/src/cmd.rs
@@ -605,7 +605,7 @@ fn handle_make_npc(
                 agent,
                 alignment,
                 scale,
-                drop_item,
+                loot,
             } => {
                 let inventory = Inventory::new_with_loadout(loadout);
 
@@ -621,7 +621,7 @@ fn handle_make_npc(
                     entity_builder = entity_builder.with(agent);
                 }
 
-                if let Some(drop_item) = drop_item {
+                if let Some(drop_item) = loot.to_item() {
                     entity_builder = entity_builder.with(comp::ItemDrop(drop_item));
                 }
 
diff --git a/server/src/events/entity_creation.rs b/server/src/events/entity_creation.rs
index 16243b71c8..4d6cbc4cd2 100644
--- a/server/src/events/entity_creation.rs
+++ b/server/src/events/entity_creation.rs
@@ -63,7 +63,7 @@ pub fn handle_create_npc(
     agent: impl Into<Option<Agent>>,
     alignment: Alignment,
     scale: Scale,
-    drop_item: Option<LootSpec<String>>,
+    loot: LootSpec<String>,
     home_chunk: Option<Anchor>,
     rtsim_entity: Option<RtSimEntity>,
     projectile: Option<Projectile>,
@@ -82,7 +82,7 @@ pub fn handle_create_npc(
         entity
     };
 
-    let entity = if let Some(drop_item) = drop_item {
+    let entity = if let Some(drop_item) = loot.to_item() {
         entity.with(ItemDrop(drop_item))
     } else {
         entity
diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs
index 3d5652d14e..111facb639 100644
--- a/server/src/events/entity_manipulation.rs
+++ b/server/src/events/entity_manipulation.rs
@@ -19,7 +19,6 @@ use common::{
         Inventory, Player, Poise, Pos, SkillSet, Stats,
     },
     event::{EventBus, ServerEvent},
-    lottery::LootSpec,
     outcome::Outcome,
     resources::Time,
     rtsim::RtSimEntity,
@@ -354,14 +353,11 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, last_change: Healt
         let old_body = state.ecs().write_storage::<Body>().remove(entity);
 
         let loot_spec = {
-            let mut item_drop = state.ecs().write_storage::<comp::ItemDrop<String>>();
-            item_drop.remove(entity).map_or_else(
-                || LootSpec::LootTable("common.loot_tables.fallback".to_string()),
-                |item| item.0,
-            )
+            let mut item_drop = state.ecs().write_storage::<comp::ItemDrop>();
+            item_drop.remove(entity).map(|comp::ItemDrop(item)| item)
         };
 
-        if let Some(item) = loot_spec.to_item() {
+        if let Some(item) = loot_spec {
             let pos = state.ecs().read_storage::<comp::Pos>().get(entity).cloned();
             let vel = state.ecs().read_storage::<comp::Vel>().get(entity).cloned();
             if let Some(pos) = pos {
diff --git a/server/src/events/mod.rs b/server/src/events/mod.rs
index 6846333301..201d9a1258 100644
--- a/server/src/events/mod.rs
+++ b/server/src/events/mod.rs
@@ -152,7 +152,7 @@ impl Server {
                     alignment,
                     scale,
                     anchor: home_chunk,
-                    drop_item,
+                    loot,
                     rtsim_entity,
                     projectile,
                 } => handle_create_npc(
@@ -167,7 +167,7 @@ impl Server {
                     agent,
                     alignment,
                     scale,
-                    drop_item,
+                    loot,
                     home_chunk,
                     rtsim_entity,
                     projectile,
diff --git a/server/src/rtsim/entity.rs b/server/src/rtsim/entity.rs
index 5c4afcb4b9..d10a2faf2d 100644
--- a/server/src/rtsim/entity.rs
+++ b/server/src/rtsim/entity.rs
@@ -96,7 +96,8 @@ impl Entity {
         }
     }
 
-    /// Escape hatch for runtime creation of loadout not covered by entity config.
+    /// Escape hatch for runtime creation of loadout not covered by entity
+    /// config.
     // NOTE: Signature is part of interface of EntityInfo, and site information
     // is not used for RtSim as of now.
     pub fn get_adhoc_loadout(
diff --git a/server/src/rtsim/tick.rs b/server/src/rtsim/tick.rs
index 3769526538..c69ec4e5ed 100644
--- a/server/src/rtsim/tick.rs
+++ b/server/src/rtsim/tick.rs
@@ -149,7 +149,7 @@ impl<'a> System<'a> for Sys {
                         body,
                         alignment,
                         scale,
-                        drop_item,
+                        loot,
                     } => ServerEvent::CreateNpc {
                         pos,
                         stats,
@@ -162,7 +162,7 @@ impl<'a> System<'a> for Sys {
                         alignment,
                         scale,
                         anchor: None,
-                        drop_item,
+                        loot,
                         rtsim_entity,
                         projectile: None,
                     },
diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs
index 3714f9137e..6d9751e892 100644
--- a/server/src/sys/terrain.rs
+++ b/server/src/sys/terrain.rs
@@ -219,7 +219,7 @@ impl<'a> System<'a> for Sys {
                         body,
                         alignment,
                         scale,
-                        drop_item,
+                        loot,
                     } => {
                         server_emitter.emit(ServerEvent::CreateNpc {
                             pos,
@@ -233,7 +233,7 @@ impl<'a> System<'a> for Sys {
                             alignment,
                             scale,
                             anchor: Some(comp::Anchor::Chunk(key)),
-                            drop_item,
+                            loot,
                             rtsim_entity: None,
                             projectile: None,
                         });
@@ -358,7 +358,7 @@ pub enum NpcData {
         body: comp::Body,
         alignment: comp::Alignment,
         scale: comp::Scale,
-        drop_item: Option<LootSpec<String>>,
+        loot: LootSpec<String>,
     },
     Waypoint(Vec3<f32>),
 }
@@ -377,7 +377,7 @@ impl NpcData {
             scale,
             pos,
             health_scaling,
-            loot_drop,
+            loot,
             // tools and skills
             skillset_asset,
             main_tool,
@@ -484,7 +484,7 @@ impl NpcData {
             body,
             alignment,
             scale: comp::Scale(scale),
-            drop_item: loot_drop,
+            loot,
         }
     }
 }

From e5d6fd28873ed2df255987f6161b6715d929a19a Mon Sep 17 00:00:00 2001
From: juliancoffee <lightdarkdaughter@gmail.com>
Date: Mon, 27 Sep 2021 23:21:57 +0300
Subject: [PATCH 14/14] Cleaning

---
 common/src/comp/inventory/item/mod.rs    | 7 -------
 server/src/events/entity_manipulation.rs | 8 ++++----
 2 files changed, 4 insertions(+), 11 deletions(-)

diff --git a/common/src/comp/inventory/item/mod.rs b/common/src/comp/inventory/item/mod.rs
index 547fd2a8a0..a432977fcd 100644
--- a/common/src/comp/inventory/item/mod.rs
+++ b/common/src/comp/inventory/item/mod.rs
@@ -862,13 +862,6 @@ impl Component for Item {
     type Storage = DerefFlaggedStorage<Self, IdvStorage<Self>>;
 }
 
-// #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
-// pub struct ItemDrop<T: AsRef<str>>(pub LootSpec<T>);
-
-// impl<T: 'static + Send + Sync + AsRef<str>> Component for ItemDrop<T> {
-//     type Storage = IdvStorage<Self>;
-// }
-
 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
 pub struct ItemDrop(pub Item);
 
diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs
index 111facb639..75469bd038 100644
--- a/server/src/events/entity_manipulation.rs
+++ b/server/src/events/entity_manipulation.rs
@@ -346,18 +346,18 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, last_change: Healt
             Some(comp::Alignment::Owned(_))
         )
     {
-        // Only drop loot if entity has agency (not a player), and if it is not owned by
-        // another entity (not a pet)
+        // Only drop loot if entity has agency (not a player),
+        // and if it is not owned by another entity (not a pet)
 
         // Decide for a loot drop before turning into a lootbag
         let old_body = state.ecs().write_storage::<Body>().remove(entity);
 
-        let loot_spec = {
+        let item = {
             let mut item_drop = state.ecs().write_storage::<comp::ItemDrop>();
             item_drop.remove(entity).map(|comp::ItemDrop(item)| item)
         };
 
-        if let Some(item) = loot_spec {
+        if let Some(item) = item {
             let pos = state.ecs().read_storage::<comp::Pos>().get(entity).cloned();
             let vel = state.ecs().read_storage::<comp::Vel>().get(entity).cloned();
             if let Some(pos) = pos {