diff --git a/common/src/combat.rs b/common/src/combat.rs
index 709a050c5c..1ba9de057d 100644
--- a/common/src/combat.rs
+++ b/common/src/combat.rs
@@ -9,7 +9,7 @@ use crate::{
             slot::EquipSlot,
         },
         skills::{SkillGroupKind, SkillSet},
-        BuffKind, Health, HealthChange, HealthSource, Inventory, Stats,
+        Body, BuffKind, Health, HealthChange, HealthSource, Inventory, Stats,
     },
     uid::Uid,
     util::Dir,
@@ -245,7 +245,7 @@ fn offensive_rating(inv: &Inventory, skillset: &SkillSet) -> f32 {
     active_damage.max(second_damage)
 }
 
-pub fn combat_rating(inventory: &Inventory, health: &Health, stats: &Stats) -> f32 {
+pub fn combat_rating(inventory: &Inventory, health: &Health, stats: &Stats, body: Body) -> f32 {
     let defensive_weighting = 1.0;
     let offensive_weighting = 1.0;
     let defensive_rating = health.maximum() as f32
@@ -256,5 +256,5 @@ pub fn combat_rating(inventory: &Inventory, health: &Health, stats: &Stats) -> f
     let combined_rating = (offensive_rating * offensive_weighting
         + defensive_rating * defensive_weighting)
         / (offensive_weighting + defensive_weighting);
-    combined_rating * stats.body_type.combat_multiplier()
+    combined_rating * body.combat_multiplier()
 }
diff --git a/common/src/comp/stats.rs b/common/src/comp/stats.rs
index 4fc5dd7dbc..e333420e5e 100644
--- a/common/src/comp/stats.rs
+++ b/common/src/comp/stats.rs
@@ -1,7 +1,4 @@
-use crate::{
-    comp,
-    comp::{skills::SkillSet, Body},
-};
+use crate::comp::skills::SkillSet;
 use serde::{Deserialize, Serialize};
 use specs::{Component, DerefFlaggedStorage};
 use specs_idvs::IdvStorage;
@@ -27,15 +24,13 @@ impl Error for StatChangeError {}
 pub struct Stats {
     pub name: String,
     pub skill_set: SkillSet,
-    pub body_type: Body,
 }
 
 impl Stats {
-    pub fn new(name: String, body: Body) -> Self {
+    pub fn new(name: String) -> Self {
         Self {
             name,
             skill_set: SkillSet::default(),
-            body_type: body,
         }
     }
 
@@ -45,7 +40,6 @@ impl Stats {
         Self {
             name: "".to_owned(),
             skill_set: SkillSet::default(),
-            body_type: comp::Body::Humanoid(comp::body::humanoid::Body::random()),
         }
     }
 }
diff --git a/common/sys/src/stats.rs b/common/sys/src/stats.rs
index 2f6bfe3aeb..26137611b5 100644
--- a/common/sys/src/stats.rs
+++ b/common/sys/src/stats.rs
@@ -1,7 +1,7 @@
 use common::{
     comp::{
         skills::{GeneralSkill, Skill},
-        CharacterState, Energy, EnergyChange, EnergySource, Health, Pos, Stats,
+        Body, CharacterState, Energy, EnergyChange, EnergySource, Health, Pos, Stats,
     },
     event::{EventBus, ServerEvent},
     metrics::SysMetrics,
@@ -31,6 +31,7 @@ impl<'a> System<'a> for Sys {
         ReadStorage<'a, Uid>,
         ReadStorage<'a, Pos>,
         Write<'a, Vec<Outcome>>,
+        ReadStorage<'a, Body>,
     );
 
     fn run(
@@ -47,6 +48,7 @@ impl<'a> System<'a> for Sys {
             uids,
             positions,
             mut outcomes,
+            bodies,
         ): Self::SystemData,
     ) {
         let start_time = std::time::Instant::now();
@@ -111,10 +113,11 @@ impl<'a> System<'a> for Sys {
         }
 
         // Apply effects from leveling skills
-        for (mut stats, mut health, mut energy) in (
+        for (mut stats, mut health, mut energy, body) in (
             &mut stats.restrict_mut(),
             &mut healths.restrict_mut(),
             &mut energies.restrict_mut(),
+            &bodies,
         )
             .join()
         {
@@ -126,7 +129,7 @@ impl<'a> System<'a> for Sys {
                     .skill_level(Skill::General(GeneralSkill::HealthIncrease))
                     .unwrap_or(None)
                     .unwrap_or(0);
-                health.update_max_hp(Some(stat.body_type), health_level);
+                health.update_max_hp(Some(*body), health_level);
                 let mut stat = stats.get_mut_unchecked();
                 stat.skill_set.modify_health = false;
             }
@@ -138,7 +141,7 @@ impl<'a> System<'a> for Sys {
                     .skill_level(Skill::General(GeneralSkill::EnergyIncrease))
                     .unwrap_or(None)
                     .unwrap_or(0);
-                energy.update_max_energy(Some(stat.body_type), energy_level);
+                energy.update_max_energy(Some(*body), energy_level);
                 let mut stat = stats.get_mut_unchecked();
                 stat.skill_set.modify_energy = false;
             }
diff --git a/server/src/character_creator.rs b/server/src/character_creator.rs
index 32199d2c6a..0d8fd31e51 100644
--- a/server/src/character_creator.rs
+++ b/server/src/character_creator.rs
@@ -10,7 +10,7 @@ pub fn create_character(
     body: Body,
     character_loader: &ReadExpect<'_, CharacterLoader>,
 ) {
-    let stats = Stats::new(character_alias.to_string(), body);
+    let stats = Stats::new(character_alias.to_string());
 
     let loadout = LoadoutBuilder::new()
         .defaults()
diff --git a/server/src/cmd.rs b/server/src/cmd.rs
index c4c32b96ed..1acc34e994 100644
--- a/server/src/cmd.rs
+++ b/server/src/cmd.rs
@@ -820,10 +820,10 @@ fn handle_spawn(
                                 .state
                                 .create_npc(
                                     pos,
-                                    comp::Stats::new(
-                                        get_npc_name(id, npc::BodyType::from_body(body)),
-                                        body,
-                                    ),
+                                    comp::Stats::new(get_npc_name(
+                                        id,
+                                        npc::BodyType::from_body(body),
+                                    )),
                                     comp::Health::new(body, 1),
                                     inventory,
                                     body,
@@ -929,7 +929,7 @@ fn handle_spawn_training_dummy(
 
             let body = comp::Body::Object(comp::object::Body::TrainingDummy);
 
-            let stats = comp::Stats::new("Training Dummy".to_string(), body);
+            let stats = comp::Stats::new("Training Dummy".to_string());
 
             let health = comp::Health::new(body, 0);
 
diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs
index c4eb0d0244..503c026c03 100644
--- a/server/src/events/entity_manipulation.rs
+++ b/server/src/events/entity_manipulation.rs
@@ -164,6 +164,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
         let healths = state.ecs().read_storage::<Health>();
         let inventories = state.ecs().read_storage::<Inventory>();
         let players = state.ecs().read_storage::<Player>();
+        let bodies = state.ecs().read_storage::<Body>();
         let by = if let HealthSource::Damage { by: Some(by), .. } = cause {
             by
         } else {
@@ -174,16 +175,21 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
         } else {
             return;
         };
-        let (entity_stats, entity_health, entity_inventory) =
-            if let (Some(entity_stats), Some(entity_health), Some(entity_inventory)) = (
-                stats.get(entity),
-                healths.get(entity),
-                inventories.get(entity),
-            ) {
-                (entity_stats, entity_health, entity_inventory)
-            } else {
-                return;
-            };
+        let (entity_stats, entity_health, entity_inventory, entity_body) = if let (
+            Some(entity_stats),
+            Some(entity_health),
+            Some(entity_inventory),
+            Some(entity_body),
+        ) = (
+            stats.get(entity),
+            healths.get(entity),
+            inventories.get(entity),
+            bodies.get(entity),
+        ) {
+            (entity_stats, entity_health, entity_inventory, entity_body)
+        } else {
+            return;
+        };
 
         let groups = state.ecs().read_storage::<Group>();
         let attacker_group = groups.get(attacker);
@@ -201,7 +207,8 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
         // TODO: Scale xp from skillset rather than health, when NPCs have their own
         // skillsets
         let mut exp_reward =
-            combat::combat_rating(entity_inventory, entity_health, entity_stats) * 2.5;
+            combat::combat_rating(entity_inventory, entity_health, entity_stats, *entity_body)
+                * 2.5;
 
         // Distribute EXP to group
         let positions = state.ecs().read_storage::<Pos>();
diff --git a/server/src/events/inventory_manip.rs b/server/src/events/inventory_manip.rs
index 5e63197e58..22439d623f 100644
--- a/server/src/events/inventory_manip.rs
+++ b/server/src/events/inventory_manip.rs
@@ -562,10 +562,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
                     });
             },
             item::Throwable::TrainingDummy => {
-                new_entity = new_entity.with(comp::Stats::new(
-                    "Training Dummy".to_string(),
-                    comp::object::Body::TrainingDummy.into(),
-                ));
+                new_entity = new_entity.with(comp::Stats::new("Training Dummy".to_string()));
             },
         };
 
diff --git a/server/src/rtsim/tick.rs b/server/src/rtsim/tick.rs
index 48e260a3c2..bc8631ca16 100644
--- a/server/src/rtsim/tick.rs
+++ b/server/src/rtsim/tick.rs
@@ -97,7 +97,7 @@ impl<'a> System<'a> for Sys {
             let body = entity.get_body();
             server_emitter.emit(ServerEvent::CreateNpc {
                 pos: comp::Pos(spawn_pos),
-                stats: comp::Stats::new(entity.get_name(), body),
+                stats: comp::Stats::new(entity.get_name()),
                 health: comp::Health::new(body, 10),
                 loadout: match body {
                     comp::Body::Humanoid(_) => entity.get_loadout(),
diff --git a/server/src/state_ext.rs b/server/src/state_ext.rs
index 6031bb07d6..f7df8128ab 100644
--- a/server/src/state_ext.rs
+++ b/server/src/state_ext.rs
@@ -290,8 +290,8 @@ impl StateExt for State {
                     .unwrap_or(None)
                     .unwrap_or(0),
             );
-            self.write_component(entity, comp::Health::new(stats.body_type, health_level));
-            self.write_component(entity, comp::Energy::new(stats.body_type, energy_level));
+            self.write_component(entity, comp::Health::new(body, health_level));
+            self.write_component(entity, comp::Energy::new(body, energy_level));
             self.write_component(entity, stats);
             self.write_component(entity, inventory);
             self.write_component(
diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs
index 1f33c7f64a..1b6c2000f1 100644
--- a/server/src/sys/terrain.rs
+++ b/server/src/sys/terrain.rs
@@ -124,7 +124,7 @@ impl<'a> System<'a> for Sys {
                 let name = entity.name.unwrap_or_else(|| "Unnamed".to_string());
                 let alignment = entity.alignment;
                 let main_tool = entity.main_tool;
-                let mut stats = comp::Stats::new(name, body);
+                let mut stats = comp::Stats::new(name);
 
                 let mut scale = entity.scale;
 
@@ -135,13 +135,10 @@ impl<'a> System<'a> for Sys {
                         let npc_names = NPC_NAMES.read();
 
                         body = comp::Body::Humanoid(body_new);
-                        stats = comp::Stats::new(
-                            format!(
-                                "Gentle Giant {}",
-                                get_npc_name(&npc_names.humanoid, body_new.species)
-                            ),
-                            body,
-                        );
+                        stats = comp::Stats::new(format!(
+                            "Gentle Giant {}",
+                            get_npc_name(&npc_names.humanoid, body_new.species)
+                        ));
                     }
                     scale = 2.0 + rand::random::<f32>();
                 }
@@ -154,7 +151,7 @@ impl<'a> System<'a> for Sys {
                 let loadout =
                     LoadoutBuilder::build_loadout(body, main_tool, loadout_config).build();
 
-                let health = comp::Health::new(stats.body_type, entity.level.unwrap_or(0));
+                let health = comp::Health::new(body, entity.level.unwrap_or(0));
 
                 let can_speak = match body {
                     comp::Body::Humanoid(_) => alignment == comp::Alignment::Npc,
diff --git a/voxygen/src/hud/bag.rs b/voxygen/src/hud/bag.rs
index 28601fee5e..8194443e8f 100644
--- a/voxygen/src/hud/bag.rs
+++ b/voxygen/src/hud/bag.rs
@@ -18,7 +18,7 @@ use crate::{
 use client::Client;
 use common::{
     combat::{combat_rating, Damage},
-    comp::{item::Quality, Energy, Health, Stats},
+    comp::{item::Quality, Body, Energy, Health, Stats},
 };
 use conrod_core::{
     color,
@@ -100,6 +100,7 @@ pub struct Bag<'a> {
     health: &'a Health,
     energy: &'a Energy,
     show: &'a Show,
+    body: &'a Body,
 }
 
 impl<'a> Bag<'a> {
@@ -118,6 +119,7 @@ impl<'a> Bag<'a> {
         health: &'a Health,
         energy: &'a Energy,
         show: &'a Show,
+        body: &'a Body,
     ) -> Self {
         Self {
             client,
@@ -134,6 +136,7 @@ impl<'a> Bag<'a> {
             energy,
             health,
             show,
+            body,
         }
     }
 }
@@ -428,7 +431,8 @@ impl<'a> Widget for Bag<'a> {
                     .resize(STATS.len(), &mut ui.widget_id_generator())
             });
             // Stats
-            let combat_rating = combat_rating(inventory, self.health, self.stats).min(999.9);
+            let combat_rating =
+                combat_rating(inventory, self.health, self.stats, *self.body).min(999.9);
             let indicator_col = cr_color(combat_rating);
             for i in STATS.iter().copied().enumerate() {
                 let btn = Button::image(match i.1 {
diff --git a/voxygen/src/hud/group.rs b/voxygen/src/hud/group.rs
index 64777a1f41..b6d568bcd6 100644
--- a/voxygen/src/hud/group.rs
+++ b/voxygen/src/hud/group.rs
@@ -340,6 +340,7 @@ impl<'a> Widget for Group<'a> {
             let buffs = client_state.ecs().read_storage::<common::comp::Buffs>();
             let inventory = client_state.ecs().read_storage::<common::comp::Inventory>();
             let uid_allocator = client_state.ecs().read_resource::<UidAllocator>();
+            let bodies = client_state.ecs().read_storage::<common::comp::Body>();
 
             // Keep track of the total number of widget ids we are using for buffs
             let mut total_buff_count = 0;
@@ -352,80 +353,80 @@ impl<'a> Widget for Group<'a> {
                 let buffs = entity.and_then(|entity| buffs.get(entity));
                 let inventory = entity.and_then(|entity| inventory.get(entity));
                 let is_leader = uid == leader;
+                let body = entity.and_then(|entity| bodies.get(entity));
 
-                if let Some(stats) = stats {
-                    let combat_rating =
-                        combat::combat_rating(inventory.unwrap(), &health.unwrap(), stats); // We can unwrap here because we check for stats first
+                if let (Some(stats), Some(inventory), Some(health), Some(body)) =
+                    (stats, inventory, health, body)
+                {
+                    let combat_rating = combat::combat_rating(inventory, health, stats, *body);
                     let char_name = stats.name.to_string();
-                    if let Some(health) = health {
-                        let health_perc = health.current() as f64 / health.maximum() as f64;
-                        // change panel positions when debug info is shown
-                        let x = if debug_on { i / 8 } else { i / 12 };
-                        let y = if debug_on { i % 8 } else { i % 12 };
-                        let back = Image::new(self.imgs.member_bg).top_left_with_margins_on(
-                            ui.window,
-                            50.0 + offset + y as f64 * 77.0,
-                            10.0 + x as f64 * 180.0,
-                        );
-                        let hp_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8; //Animation timer
-                        let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani);
-                        let health_col = match (health_perc * 100.0) as u8 {
-                            0..=20 => crit_hp_color,
-                            21..=40 => LOW_HP_COLOR,
-                            _ => HP_COLOR,
-                        };
-                        // Don't show panel for the player!
-                        // Panel BG
-                        back.w_h(152.0, 36.0)
-                            .color(if is_leader {
-                                Some(ERROR_COLOR)
-                            } else {
-                                Some(TEXT_COLOR)
-                            })
-                            .set(state.ids.member_panels_bg[i], ui);
-                        // Health
-                        Image::new(self.imgs.bar_content)
-                            .w_h(148.0 * health_perc, 22.0)
-                            .color(Some(health_col))
-                            .top_left_with_margins_on(state.ids.member_panels_bg[i], 2.0, 2.0)
-                            .set(state.ids.member_health[i], ui);
-                        if health.is_dead {
-                            // Death Text
-                            Text::new(&self.localized_strings.get("hud.group.dead"))
-                                .mid_top_with_margin_on(state.ids.member_panels_bg[i], 1.0)
-                                .font_size(20)
-                                .font_id(self.fonts.cyri.conrod_id)
-                                .color(KILL_COLOR)
-                                .set(state.ids.dead_txt[i], ui);
+                    let health_perc = health.current() as f64 / health.maximum() as f64;
+                    // change panel positions when debug info is shown
+                    let x = if debug_on { i / 8 } else { i / 12 };
+                    let y = if debug_on { i % 8 } else { i % 12 };
+                    let back = Image::new(self.imgs.member_bg).top_left_with_margins_on(
+                        ui.window,
+                        50.0 + offset + y as f64 * 77.0,
+                        10.0 + x as f64 * 180.0,
+                    );
+                    let hp_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8; //Animation timer
+                    let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani);
+                    let health_col = match (health_perc * 100.0) as u8 {
+                        0..=20 => crit_hp_color,
+                        21..=40 => LOW_HP_COLOR,
+                        _ => HP_COLOR,
+                    };
+                    // Don't show panel for the player!
+                    // Panel BG
+                    back.w_h(152.0, 36.0)
+                        .color(if is_leader {
+                            Some(ERROR_COLOR)
                         } else {
-                            // Health Text
-                            let txt = format!(
-                                "{}/{}",
-                                health.current() / 10_u32,
-                                health.maximum() / 10_u32,
-                            );
-                            // Change font size depending on health amount
-                            let font_size = match health.maximum() {
-                                0..=999 => 14,
-                                1000..=9999 => 13,
-                                10000..=99999 => 12,
-                                _ => 11,
-                            };
-                            // Change text offset depending on health amount
-                            let txt_offset = match health.maximum() {
-                                0..=999 => 4.0,
-                                1000..=9999 => 4.5,
-                                10000..=99999 => 5.0,
-                                _ => 5.5,
-                            };
-                            Text::new(&txt)
-                                .mid_top_with_margin_on(state.ids.member_panels_bg[i], txt_offset)
-                                .font_size(font_size)
-                                .font_id(self.fonts.cyri.conrod_id)
-                                .color(Color::Rgba(1.0, 1.0, 1.0, 0.5))
-                                .set(state.ids.health_txt[i], ui);
+                            Some(TEXT_COLOR)
+                        })
+                        .set(state.ids.member_panels_bg[i], ui);
+                    // Health
+                    Image::new(self.imgs.bar_content)
+                        .w_h(148.0 * health_perc, 22.0)
+                        .color(Some(health_col))
+                        .top_left_with_margins_on(state.ids.member_panels_bg[i], 2.0, 2.0)
+                        .set(state.ids.member_health[i], ui);
+                    if health.is_dead {
+                        // Death Text
+                        Text::new(&self.localized_strings.get("hud.group.dead"))
+                            .mid_top_with_margin_on(state.ids.member_panels_bg[i], 1.0)
+                            .font_size(20)
+                            .font_id(self.fonts.cyri.conrod_id)
+                            .color(KILL_COLOR)
+                            .set(state.ids.dead_txt[i], ui);
+                    } else {
+                        // Health Text
+                        let txt = format!(
+                            "{}/{}",
+                            health.current() / 10_u32,
+                            health.maximum() / 10_u32,
+                        );
+                        // Change font size depending on health amount
+                        let font_size = match health.maximum() {
+                            0..=999 => 14,
+                            1000..=9999 => 13,
+                            10000..=99999 => 12,
+                            _ => 11,
                         };
-                    }
+                        // Change text offset depending on health amount
+                        let txt_offset = match health.maximum() {
+                            0..=999 => 4.0,
+                            1000..=9999 => 4.5,
+                            10000..=99999 => 5.0,
+                            _ => 5.5,
+                        };
+                        Text::new(&txt)
+                            .mid_top_with_margin_on(state.ids.member_panels_bg[i], txt_offset)
+                            .font_size(font_size)
+                            .font_id(self.fonts.cyri.conrod_id)
+                            .color(Color::Rgba(1.0, 1.0, 1.0, 0.5))
+                            .set(state.ids.health_txt[i], ui);
+                    };
 
                     // Panel Frame
                     Image::new(self.imgs.member_frame)
diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs
index 75be629adb..f011bbc420 100644
--- a/voxygen/src/hud/mod.rs
+++ b/voxygen/src/hud/mod.rs
@@ -1341,7 +1341,7 @@ impl Hud {
                             health,
                             buffs,
                             energy,
-                            combat_rating: combat::combat_rating(inventory, health, stats),
+                            combat_rating: combat::combat_rating(inventory, health, stats, *body),
                         });
                         let bubble = if dist_sqr < SPEECH_BUBBLE_RANGE.powi(2) {
                             speech_bubbles.get(uid)
@@ -2011,6 +2011,7 @@ impl Hud {
         let character_states = ecs.read_storage::<comp::CharacterState>();
         let controllers = ecs.read_storage::<comp::Controller>();
         let ability_map = ecs.fetch::<comp::item::tool::AbilityMap>();
+        let bodies = ecs.read_storage::<comp::Body>();
 
         if let (
             Some(health),
@@ -2047,10 +2048,11 @@ impl Hud {
         }
         // Bag contents
         if self.show.bag {
-            if let (Some(player_stats), Some(health), Some(energy)) = (
+            if let (Some(player_stats), Some(health), Some(energy), Some(body)) = (
                 stats.get(client.entity()),
                 healths.get(entity),
                 energies.get(entity),
+                bodies.get(entity),
             ) {
                 match Bag::new(
                     client,
@@ -2066,6 +2068,7 @@ impl Hud {
                     &health,
                     &energy,
                     &self.show,
+                    &body,
                 )
                 .set(self.ids.bag, ui_widgets)
                 {