From 4741e4123088617807f3881b6ba4439f25238aef Mon Sep 17 00:00:00 2001
From: timokoesters <timo@koesters.xyz>
Date: Tue, 17 Mar 2020 18:27:52 +0100
Subject: [PATCH] Add support for different models per weapon type

---
 assets/common/items/weapons/hammer_1.ron      |  2 +-
 assets/common/items/weapons/shield_1.ron      |  2 +-
 assets/common/items/weapons/staff_1.ron       |  2 +-
 assets/common/items/weapons/starter_axe.ron   |  2 +-
 assets/common/items/weapons/starter_bow.ron   |  2 +-
 .../common/items/weapons/starter_dagger.ron   |  2 +-
 .../common/items/weapons/starter_hammer.ron   |  2 +-
 assets/common/items/weapons/starter_staff.ron |  6 +--
 assets/voxygen/item_image_manifest.ron        | 12 ++---
 .../voxel/humanoid_main_weapon_manifest.ron   | 42 ++++++++++++++++
 common/src/comp/inventory/item.rs             | 49 ++++++++++++++-----
 common/src/sys/agent.rs                       |  3 +-
 voxygen/src/anim/character/attack.rs          | 12 ++---
 voxygen/src/anim/character/block.rs           | 12 ++---
 voxygen/src/anim/character/blockidle.rs       | 12 ++---
 voxygen/src/anim/character/cidle.rs           | 12 ++---
 voxygen/src/anim/character/mod.rs             | 28 +++++------
 voxygen/src/anim/character/wield.rs           | 12 ++---
 voxygen/src/anim/mod.rs                       | 28 +++++------
 voxygen/src/hud/bag.rs                        |  4 +-
 voxygen/src/hud/skillbar.rs                   | 40 +++++++--------
 voxygen/src/scene/figure/cache.rs             |  4 +-
 voxygen/src/scene/figure/load.rs              | 49 ++++++++++++-------
 23 files changed, 208 insertions(+), 131 deletions(-)
 create mode 100644 assets/voxygen/voxel/humanoid_main_weapon_manifest.ron

diff --git a/assets/common/items/weapons/hammer_1.ron b/assets/common/items/weapons/hammer_1.ron
index 268cf1f7da..9f31453a57 100644
--- a/assets/common/items/weapons/hammer_1.ron
+++ b/assets/common/items/weapons/hammer_1.ron
@@ -5,7 +5,7 @@ Item(
     Power: 20",
     kind: Tool(
         ToolData (
-            kind: Hammer,    
+            kind: Hammer(BasicHammer),    
             equip_time_millis: 1000,
         )
     )
diff --git a/assets/common/items/weapons/shield_1.ron b/assets/common/items/weapons/shield_1.ron
index 23dd6b0ddb..8ad6d4f71b 100644
--- a/assets/common/items/weapons/shield_1.ron
+++ b/assets/common/items/weapons/shield_1.ron
@@ -3,7 +3,7 @@ Item(
     description: "Legends tell this item is useless.",
     kind: Tool (
         ToolData (
-            kind: Shield,
+            kind: Shield(BasicShield),
             equip_time_millis: 400,
         )
     ),
diff --git a/assets/common/items/weapons/staff_1.ron b/assets/common/items/weapons/staff_1.ron
index 4a66a40399..6ad09d6635 100644
--- a/assets/common/items/weapons/staff_1.ron
+++ b/assets/common/items/weapons/staff_1.ron
@@ -5,7 +5,7 @@ Item(
     Power: 6",
     kind: Tool(
         ToolData (
-            kind: Staff,    
+            kind: Staff(BasicStaff),    
             equip_time_millis: 800,
         )
     ),
diff --git a/assets/common/items/weapons/starter_axe.ron b/assets/common/items/weapons/starter_axe.ron
index 89a71e297c..a534e2eaa4 100644
--- a/assets/common/items/weapons/starter_axe.ron
+++ b/assets/common/items/weapons/starter_axe.ron
@@ -5,7 +5,7 @@ Item(
     Power: 15",
     kind: Tool(
         ToolData (
-            kind: Axe,    
+            kind: Axe(BasicAxe),    
             equip_time_millis: 1000,
         )
     ),
diff --git a/assets/common/items/weapons/starter_bow.ron b/assets/common/items/weapons/starter_bow.ron
index 14b11333a5..33064b766b 100644
--- a/assets/common/items/weapons/starter_bow.ron
+++ b/assets/common/items/weapons/starter_bow.ron
@@ -5,7 +5,7 @@ Item(
     Power: 15",
     kind: Tool(
         ToolData (
-            kind: Bow,    
+            kind: Bow(BasicBow),    
             equip_time_millis: 800,
         )
     ),
diff --git a/assets/common/items/weapons/starter_dagger.ron b/assets/common/items/weapons/starter_dagger.ron
index 8817c6865f..bed9c3890b 100644
--- a/assets/common/items/weapons/starter_dagger.ron
+++ b/assets/common/items/weapons/starter_dagger.ron
@@ -4,7 +4,7 @@ Item(
     Power: 15",
     kind: Tool(
         ToolData (
-            kind: Dagger,    
+            kind: Dagger(BasicDagger),    
             equip_time_millis: 300,
         )
     ),
diff --git a/assets/common/items/weapons/starter_hammer.ron b/assets/common/items/weapons/starter_hammer.ron
index 6242cfc7c1..3e3a55f6e3 100644
--- a/assets/common/items/weapons/starter_hammer.ron
+++ b/assets/common/items/weapons/starter_hammer.ron
@@ -5,7 +5,7 @@ Item(
     Power: 15",
     kind: Tool(
         ToolData (
-            kind: Hammer,    
+            kind: Hammer(BasicHammer),    
             equip_time_millis: 1000,
         )
     ),
diff --git a/assets/common/items/weapons/starter_staff.ron b/assets/common/items/weapons/starter_staff.ron
index 2cf741181c..bc5d808ae3 100644
--- a/assets/common/items/weapons/starter_staff.ron
+++ b/assets/common/items/weapons/starter_staff.ron
@@ -5,12 +5,8 @@ Item(
     Power: 20",
     kind: Tool(
         ToolData (
-            kind: Staff,    
+            kind: Staff(BasicHammer),    
             equip_time_millis: 800,
-            attack_buildup_millis: 400,
-            attack_recover_millis: 300,
-            range: 3,
-            base_damage: 10, 
         )
     ),
 )
diff --git a/assets/voxygen/item_image_manifest.ron b/assets/voxygen/item_image_manifest.ron
index 1705c5119c..7ff7586d71 100644
--- a/assets/voxygen/item_image_manifest.ron
+++ b/assets/voxygen/item_image_manifest.ron
@@ -3,11 +3,11 @@
 //  VoxTrans(specifier, offset, (x_rot, y_rot, z_rot), zoom)
 ({
     // Weapons
-    Tool(Bow): VoxTrans(
+    Tool(Bow(BasicBow)): VoxTrans(
         "voxel.weapon.bow.simple-bow",
         (0.0, 0.0, 0.0), (90.0, 90.0, 0.0), 1.0,
     ),
-    Tool(Dagger): VoxTrans(
+    Tool(Dagger(BasicDagger)): VoxTrans(
         "voxel.weapon.dagger.dagger_rusty",
         (0.0, 0.0, -4.0), (-120.0, 90.0, 0.0), 1.1,
     ),
@@ -15,19 +15,19 @@
         "voxel.weapon.sword.rusty_2h",
         (0.0, 9.0, 0.0), (-90.0, 90.0, 0.0), 2.4,
     ),
-    Tool(Axe): VoxTrans(
+    Tool(Axe(BasicAxe)): VoxTrans(
         "voxel.weapon.axe.rusty_2h",
         (0.0, -8.0, 0.0), (-90.0, 90.0, 0.0), 2.0,
     ),
-    Tool(Hammer): VoxTrans(
+    Tool(Hammer(BasicHammer)): VoxTrans(
         "voxel.weapon.hammer.rusty_2h",
         (0.0, -8.0, 0.0), (-90.0, 90.0, 0.0), 2.0,
     ),
-    Tool(Staff): VoxTrans(
+    Tool(Staff(BasicStaff)): VoxTrans(
         "voxel.weapon.staff.wood-fire",
         (0.0, -9.0, 0.0), (90.0, 90.0, 0.0), 2.5,
     ),
-    Tool(Shield): VoxTrans(
+    Tool(Shield(BasicShield)): VoxTrans(
         "voxel.weapon.shield.wood-0",
         (0.0, 0.0, 0.0), (-90.0, 90.0, 0.0), 2.4,
     ),
diff --git a/assets/voxygen/voxel/humanoid_main_weapon_manifest.ron b/assets/voxygen/voxel/humanoid_main_weapon_manifest.ron
new file mode 100644
index 0000000000..60871bc99f
--- /dev/null
+++ b/assets/voxygen/voxel/humanoid_main_weapon_manifest.ron
@@ -0,0 +1,42 @@
+({
+    Sword(Scimitar): (
+        vox_spec: ("weapon.sword.rusty_2h", (-1.5, -6.5, -4.0)),
+        color: None
+    ),
+    Sword(Rapier): (
+        vox_spec: ("weapon.sword.rusty_2h", (-1.5, -6.5, -4.0)),
+        color: None
+    ),
+    Axe(BasicAxe): (
+        vox_spec: ("weapon.axe.rusty_2h", (-1.5, -5.0, -4.0)),
+        color: None
+    ),
+    Hammer(BasicHammer): (
+        vox_spec: ("weapon.hammer.rusty_2h", (-2.5, -5.5, -4.0)),
+        color: None
+    ),
+    Dagger(BasicDagger): (
+        vox_spec: ("weapon.hammer.rusty_2h", (-2.5, -5.5, -4.0)), // TODO
+        color: None
+    ),
+    Shield(BasicShield): (
+        vox_spec: ("weapon.shield.wood-0", (-2.5, -6.5, -2.0)),
+        color: None
+    ),
+    Bow(BasicBow): (
+        vox_spec: ("weapon.bow.simple-bow", (-1.0, -6.0, -2.0)),
+        color: None
+    ),
+    Staff(BasicStaff): (
+        vox_spec: ("weapon.staff.wood-fire", (-1.0, -6.0, -3.0)),
+        color: None
+    ),
+    Debug(Boost): (
+        vox_spec: ("weapon.debug_wand", (-1.5, -9.5, -4.0)),
+        color: None
+    ),
+    Debug(Possess): (
+        vox_spec: ("weapon.debug_wand", (-1.5, -9.5, -4.0)),
+        color: None
+    ),
+})
diff --git a/common/src/comp/inventory/item.rs b/common/src/comp/inventory/item.rs
index 16961c3005..0b5d4c59e9 100644
--- a/common/src/comp/inventory/item.rs
+++ b/common/src/comp/inventory/item.rs
@@ -7,7 +7,6 @@ use crate::{
     effect::Effect,
     terrain::{Block, BlockKind},
 };
-//use rand::prelude::*;
 use rand::seq::SliceRandom;
 use specs::{Component, FlaggedStorage};
 use specs_idvs::IDVStorage;
@@ -18,16 +17,40 @@ pub enum SwordKind {
     Scimitar,
     Rapier,
 }
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
+pub enum AxeKind {
+    BasicAxe,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
+pub enum HammerKind {
+    BasicHammer,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
+pub enum BowKind {
+    BasicBow,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
+pub enum DaggerKind {
+    BasicDagger,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
+pub enum StaffKind {
+    BasicStaff,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
+pub enum ShieldKind {
+    BasicShield,
+}
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
 pub enum ToolKind {
     Sword(SwordKind),
-    Axe,
-    Hammer,
-    Bow,
-    Dagger,
-    Staff,
-    Shield,
+    Axe(AxeKind),
+    Hammer(HammerKind),
+    Bow(BowKind),
+    Dagger(DaggerKind),
+    Staff(StaffKind),
+    Shield(ShieldKind),
     Debug(DebugKind),
     /// This is an placeholder item, it is used by non-humanoid npcs to attack
     Empty,
@@ -54,17 +77,17 @@ impl ToolData {
                     base_damage: 20,
                 },
             ],
-            Axe => vec![BasicMelee {
+            Axe(_) => vec![BasicMelee {
                 buildup_duration: Duration::from_millis(700),
                 recover_duration: Duration::from_millis(100),
                 base_damage: 8,
             }],
-            Hammer => vec![BasicMelee {
+            Hammer(_) => vec![BasicMelee {
                 buildup_duration: Duration::from_millis(700),
                 recover_duration: Duration::from_millis(300),
                 base_damage: 10,
             }],
-            Bow => vec![BasicRanged {
+            Bow(_) => vec![BasicRanged {
                 projectile: Projectile {
                     hit_ground: vec![projectile::Effect::Stick],
                     hit_wall: vec![projectile::Effect::Stick],
@@ -82,17 +105,17 @@ impl ToolData {
                 projectile_body: Body::Object(object::Body::Arrow),
                 recover_duration: Duration::from_millis(300),
             }],
-            Dagger => vec![BasicMelee {
+            Dagger(_) => vec![BasicMelee {
                 buildup_duration: Duration::from_millis(100),
                 recover_duration: Duration::from_millis(400),
                 base_damage: 5,
             }],
-            Staff => vec![BasicMelee {
+            Staff(_) => vec![BasicMelee {
                 buildup_duration: Duration::from_millis(400),
                 recover_duration: Duration::from_millis(300),
                 base_damage: 7,
             }],
-            Shield => vec![BasicBlock],
+            Shield(_) => vec![BasicBlock],
             Debug(kind) => match kind {
                 DebugKind::Boost => vec![
                     CharacterAbility::Boost {
diff --git a/common/src/sys/agent.rs b/common/src/sys/agent.rs
index 9d8415ea28..fd7313af78 100644
--- a/common/src/sys/agent.rs
+++ b/common/src/sys/agent.rs
@@ -161,6 +161,8 @@ impl<'a> System<'a> for Sys {
                                 .copied()
                                 .unwrap_or(Alignment::Owned(*target)),
                         ) {
+                            inputs.look_dir = tgt_pos.0 - pos.0;
+
                             // Don't attack entities we are passive towards
                             // TODO: This is here, it's a bit of a hack
                             if let Some(alignment) = alignment {
@@ -174,7 +176,6 @@ impl<'a> System<'a> for Sys {
                             let dist_sqrd = pos.0.distance_squared(tgt_pos.0);
                             if dist_sqrd < MIN_ATTACK_DIST.powf(2.0) {
                                 // Close-range attack
-                                inputs.look_dir = tgt_pos.0 - pos.0;
                                 inputs.move_dir = Vec2::from(tgt_pos.0 - pos.0)
                                     .try_normalized()
                                     .unwrap_or(Vec2::unit_y())
diff --git a/voxygen/src/anim/character/attack.rs b/voxygen/src/anim/character/attack.rs
index bdb84ef253..dea9736ebe 100644
--- a/voxygen/src/anim/character/attack.rs
+++ b/voxygen/src/anim/character/attack.rs
@@ -82,7 +82,7 @@ impl Animation for AttackAnimation {
                     * Quaternion::rotation_z(1.4 + slow * 0.5);
                 next.control.scale = Vec3::one();
             },
-            Some(ToolKind::Axe) => {
+            Some(ToolKind::Axe(_)) => {
                 next.l_hand.offset =
                     Vec3::new(-8.0 + accel_slow * 10.0, 8.0 + accel_fast * 3.0, 0.0);
                 next.l_hand.ori = Quaternion::rotation_z(-0.8)
@@ -107,7 +107,7 @@ impl Animation for AttackAnimation {
                     * Quaternion::rotation_y(0.0 + accel_med * -0.4);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Hammer) => {
+            Some(ToolKind::Hammer(_)) => {
                 next.l_hand.offset =
                     Vec3::new(-8.0 + accel_slow * 10.0, 8.0 + accel_fast * 3.0, 0.0);
                 next.l_hand.ori = Quaternion::rotation_z(-0.8)
@@ -132,7 +132,7 @@ impl Animation for AttackAnimation {
                     * Quaternion::rotation_y(0.0 + accel_med * -0.4);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Staff) => {
+            Some(ToolKind::Staff(_)) => {
                 next.l_hand.offset =
                     Vec3::new(-8.0 + accel_slow * 10.0, 8.0 + accel_fast * 3.0, 0.0);
                 next.l_hand.ori = Quaternion::rotation_z(-0.8)
@@ -157,7 +157,7 @@ impl Animation for AttackAnimation {
                     * Quaternion::rotation_y(0.0 + accel_med * -0.4);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Shield) => {
+            Some(ToolKind::Shield(_)) => {
                 next.l_hand.offset =
                     Vec3::new(-8.0 + accel_slow * 10.0, 8.0 + accel_fast * 3.0, 0.0);
                 next.l_hand.ori = Quaternion::rotation_z(-0.8)
@@ -182,7 +182,7 @@ impl Animation for AttackAnimation {
                     * Quaternion::rotation_y(0.0 + accel_med * -0.4);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Bow) => {
+            Some(ToolKind::Bow(_)) => {
                 next.l_hand.offset = Vec3::new(-7.0, -2.0 + slow * 5.0, -1.0);
                 next.l_hand.ori = Quaternion::rotation_x(PI / 2.0)
                     * Quaternion::rotation_y(-0.3)
@@ -203,7 +203,7 @@ impl Animation for AttackAnimation {
                     * Quaternion::rotation_z(0.0);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Dagger) => {
+            Some(ToolKind::Dagger(_)) => {
                 next.l_hand.offset =
                     Vec3::new(-8.0 + accel_slow * 10.0, 8.0 + accel_fast * 3.0, 0.0);
                 next.l_hand.ori = Quaternion::rotation_z(-0.8)
diff --git a/voxygen/src/anim/character/block.rs b/voxygen/src/anim/character/block.rs
index 4ed5e7d542..a9e58b8756 100644
--- a/voxygen/src/anim/character/block.rs
+++ b/voxygen/src/anim/character/block.rs
@@ -81,7 +81,7 @@ impl Animation for BlockAnimation {
                     * Quaternion::rotation_z(-1.57);
                 next.control.scale = Vec3::one();
             },
-            Some(ToolKind::Axe) => {
+            Some(ToolKind::Axe(_)) => {
                 next.l_hand.offset = Vec3::new(
                     -6.0 + wave_ultra_slow_cos * 1.0,
                     3.5 + wave_ultra_slow_cos * 0.5,
@@ -106,7 +106,7 @@ impl Animation for BlockAnimation {
                     * Quaternion::rotation_z(0.0);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Hammer) => {
+            Some(ToolKind::Hammer(_)) => {
                 next.l_hand.offset = Vec3::new(-7.0, 3.5, 6.5);
                 next.l_hand.ori = Quaternion::rotation_x(2.07)
                     * Quaternion::rotation_y(0.0)
@@ -127,7 +127,7 @@ impl Animation for BlockAnimation {
                     * Quaternion::rotation_z(-0.85);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Staff) => {
+            Some(ToolKind::Staff(_)) => {
                 next.l_hand.offset = Vec3::new(
                     -6.0 + wave_ultra_slow_cos * 1.0,
                     3.5 + wave_ultra_slow_cos * 0.5,
@@ -152,7 +152,7 @@ impl Animation for BlockAnimation {
                     * Quaternion::rotation_z(0.0);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Shield) => {
+            Some(ToolKind::Shield(_)) => {
                 next.l_hand.offset = Vec3::new(
                     -6.0 + wave_ultra_slow_cos * 1.0,
                     3.5 + wave_ultra_slow_cos * 0.5,
@@ -177,7 +177,7 @@ impl Animation for BlockAnimation {
                     * Quaternion::rotation_z(0.0);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Bow) => {
+            Some(ToolKind::Bow(_)) => {
                 next.l_hand.offset = Vec3::new(
                     -6.0 + wave_ultra_slow_cos * 1.0,
                     3.5 + wave_ultra_slow_cos * 0.5,
@@ -202,7 +202,7 @@ impl Animation for BlockAnimation {
                     * Quaternion::rotation_z(0.0);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Dagger) => {
+            Some(ToolKind::Dagger(_)) => {
                 next.l_hand.offset = Vec3::new(
                     -6.0 + wave_ultra_slow_cos * 1.0,
                     3.5 + wave_ultra_slow_cos * 0.5,
diff --git a/voxygen/src/anim/character/blockidle.rs b/voxygen/src/anim/character/blockidle.rs
index aa035383ac..0c7551b71b 100644
--- a/voxygen/src/anim/character/blockidle.rs
+++ b/voxygen/src/anim/character/blockidle.rs
@@ -80,7 +80,7 @@ impl Animation for BlockIdleAnimation {
                     * Quaternion::rotation_z(-1.57);
                 next.control.scale = Vec3::one();
             },
-            Some(ToolKind::Axe) => {
+            Some(ToolKind::Axe(_)) => {
                 next.l_hand.offset = Vec3::new(
                     -6.0 + wave_ultra_slow_cos * 1.0,
                     3.5 + wave_ultra_slow_cos * 0.5,
@@ -105,7 +105,7 @@ impl Animation for BlockIdleAnimation {
                     * Quaternion::rotation_z(0.0);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Hammer) => {
+            Some(ToolKind::Hammer(_)) => {
                 next.l_hand.offset = Vec3::new(-7.0, 3.5 + wave_ultra_slow * 2.0, 6.5);
                 next.l_hand.ori = Quaternion::rotation_x(2.07)
                     * Quaternion::rotation_y(0.0)
@@ -126,7 +126,7 @@ impl Animation for BlockIdleAnimation {
                     * Quaternion::rotation_z(-0.85);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Staff) => {
+            Some(ToolKind::Staff(_)) => {
                 next.l_hand.offset = Vec3::new(
                     -6.0 + wave_ultra_slow_cos * 1.0,
                     3.5 + wave_ultra_slow_cos * 0.5,
@@ -151,7 +151,7 @@ impl Animation for BlockIdleAnimation {
                     * Quaternion::rotation_z(0.0);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Shield) => {
+            Some(ToolKind::Shield(_)) => {
                 next.l_hand.offset = Vec3::new(
                     -6.0 + wave_ultra_slow_cos * 1.0,
                     3.5 + wave_ultra_slow_cos * 0.5,
@@ -176,7 +176,7 @@ impl Animation for BlockIdleAnimation {
                     * Quaternion::rotation_z(0.0);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Bow) => {
+            Some(ToolKind::Bow(_)) => {
                 next.l_hand.offset = Vec3::new(
                     -6.0 + wave_ultra_slow_cos * 1.0,
                     3.5 + wave_ultra_slow_cos * 0.5,
@@ -201,7 +201,7 @@ impl Animation for BlockIdleAnimation {
                     * Quaternion::rotation_z(0.0);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Dagger) => {
+            Some(ToolKind::Dagger(_)) => {
                 next.l_hand.offset = Vec3::new(
                     -6.0 + wave_ultra_slow_cos * 1.0,
                     3.5 + wave_ultra_slow_cos * 0.5,
diff --git a/voxygen/src/anim/character/cidle.rs b/voxygen/src/anim/character/cidle.rs
index d72262fb69..80613193cb 100644
--- a/voxygen/src/anim/character/cidle.rs
+++ b/voxygen/src/anim/character/cidle.rs
@@ -81,7 +81,7 @@ impl Animation for CidleAnimation {
                     * Quaternion::rotation_z(0.0);
                 next.control.scale = Vec3::one();
             },
-            Some(ToolKind::Axe) => {
+            Some(ToolKind::Axe(_)) => {
                 next.l_hand.offset = Vec3::new(
                     -6.5 + wave_ultra_slow_cos * 1.0,
                     -0.5 + wave_ultra_slow_cos * 0.5,
@@ -108,7 +108,7 @@ impl Animation for CidleAnimation {
                     * Quaternion::rotation_z(0.0);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Hammer) => {
+            Some(ToolKind::Hammer(_)) => {
                 next.l_hand.offset = Vec3::new(-7.0, 4.0, 3.0);
                 next.l_hand.ori = Quaternion::rotation_x(1.27 + wave_ultra_slow * -0.1)
                     * Quaternion::rotation_y(0.0)
@@ -129,7 +129,7 @@ impl Animation for CidleAnimation {
                     * Quaternion::rotation_z(wave_ultra_slow * 0.2);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Staff) => {
+            Some(ToolKind::Staff(_)) => {
                 next.l_hand.offset = Vec3::new(
                     -6.0 + wave_ultra_slow_cos * 1.0,
                     1.0 + wave_ultra_slow_cos * 0.5,
@@ -154,7 +154,7 @@ impl Animation for CidleAnimation {
                     * Quaternion::rotation_z(0.0);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Shield) => {
+            Some(ToolKind::Shield(_)) => {
                 next.l_hand.offset = Vec3::new(
                     -6.0 + wave_ultra_slow_cos * 1.0,
                     3.5 + wave_ultra_slow_cos * 0.5,
@@ -179,7 +179,7 @@ impl Animation for CidleAnimation {
                     * Quaternion::rotation_z(0.0);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Bow) => {
+            Some(ToolKind::Bow(_)) => {
                 next.l_hand.offset = Vec3::new(
                     -1.0 + wave_ultra_slow_cos * 1.0,
                     3.0 + wave_ultra_slow_cos * 0.5,
@@ -208,7 +208,7 @@ impl Animation for CidleAnimation {
                     * Quaternion::rotation_z(0.0);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Dagger) => {
+            Some(ToolKind::Dagger(_)) => {
                 next.l_hand.offset = Vec3::new(
                     -6.0 + wave_ultra_slow_cos * 1.0,
                     3.5 + wave_ultra_slow_cos * 0.5,
diff --git a/voxygen/src/anim/character/mod.rs b/voxygen/src/anim/character/mod.rs
index 952d8f149f..0fe9e9ac1a 100644
--- a/voxygen/src/anim/character/mod.rs
+++ b/voxygen/src/anim/character/mod.rs
@@ -227,25 +227,25 @@ impl<'a> From<&'a comp::humanoid::Body> for SkeletonAttr {
                 (Danari, Male) => 0.0,
                 (Danari, Female) => 0.0,
             },
-            weapon_x: match ToolKind::Hammer {
+            weapon_x: match ToolKind::Empty {
                 ToolKind::Sword(_) => 0.0,
-                ToolKind::Axe => 3.0,
-                ToolKind::Hammer => 0.0,
-                ToolKind::Shield => 3.0,
-                ToolKind::Staff => 3.0,
-                ToolKind::Bow => 0.0,
-                ToolKind::Dagger => 0.0,
+                ToolKind::Axe(_) => 3.0,
+                ToolKind::Hammer(_) => 0.0,
+                ToolKind::Shield(_) => 3.0,
+                ToolKind::Staff(_) => 3.0,
+                ToolKind::Bow(_) => 0.0,
+                ToolKind::Dagger(_) => 0.0,
                 ToolKind::Debug(_) => 0.0,
                 ToolKind::Empty => 0.0,
             },
-            weapon_y: match ToolKind::Hammer {
+            weapon_y: match ToolKind::Empty {
                 ToolKind::Sword(_) => -1.25,
-                ToolKind::Axe => 0.0,
-                ToolKind::Hammer => -2.0,
-                ToolKind::Shield => 0.0,
-                ToolKind::Staff => 0.0,
-                ToolKind::Bow => -2.0,
-                ToolKind::Dagger => -2.0,
+                ToolKind::Axe(_) => 0.0,
+                ToolKind::Hammer(_) => -2.0,
+                ToolKind::Shield(_) => 0.0,
+                ToolKind::Staff(_) => 0.0,
+                ToolKind::Bow(_) => -2.0,
+                ToolKind::Dagger(_) => -2.0,
                 ToolKind::Debug(_) => 0.0,
                 ToolKind::Empty => 0.0,
             },
diff --git a/voxygen/src/anim/character/wield.rs b/voxygen/src/anim/character/wield.rs
index c050e7e03a..05cfaafdc6 100644
--- a/voxygen/src/anim/character/wield.rs
+++ b/voxygen/src/anim/character/wield.rs
@@ -44,7 +44,7 @@ impl Animation for WieldAnimation {
                     * Quaternion::rotation_z(0.0);
                 next.control.scale = Vec3::one();
             },
-            Some(ToolKind::Axe) => {
+            Some(ToolKind::Axe(_)) => {
                 next.l_hand.offset = Vec3::new(-6.5, -0.5, 6.0);
                 next.l_hand.ori = Quaternion::rotation_x(0.13) * Quaternion::rotation_z(-0.25);
                 next.l_hand.scale = Vec3::one() * 1.01;
@@ -63,7 +63,7 @@ impl Animation for WieldAnimation {
                     * Quaternion::rotation_z(0.0);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Hammer) => {
+            Some(ToolKind::Hammer(_)) => {
                 next.l_hand.offset = Vec3::new(-7.0, 4.0, 3.0);
                 next.l_hand.ori = Quaternion::rotation_x(1.27 + wave * 0.25)
                     * Quaternion::rotation_y(0.0)
@@ -84,7 +84,7 @@ impl Animation for WieldAnimation {
                     * Quaternion::rotation_z(wave * -0.25);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Staff) => {
+            Some(ToolKind::Staff(_)) => {
                 next.l_hand.offset = Vec3::new(
                     -6.0 + wave_ultra_slow_cos * 1.0,
                     1.0 + wave_ultra_slow_cos * 0.5,
@@ -109,7 +109,7 @@ impl Animation for WieldAnimation {
                     * Quaternion::rotation_z(0.0);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Shield) => {
+            Some(ToolKind::Shield(_)) => {
                 next.l_hand.offset = Vec3::new(-6.0, 3.5, 0.0);
                 next.l_hand.ori = Quaternion::rotation_x(-0.3);
                 next.l_hand.scale = Vec3::one() * 1.01;
@@ -126,7 +126,7 @@ impl Animation for WieldAnimation {
                     * Quaternion::rotation_z(0.0);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Bow) => {
+            Some(ToolKind::Bow(_)) => {
                 next.l_hand.offset = Vec3::new(
                     -1.0 - wave_ultra_slow_cos * 1.0,
                     3.0 + wave_ultra_slow_cos * 0.5,
@@ -155,7 +155,7 @@ impl Animation for WieldAnimation {
                     * Quaternion::rotation_z(0.0);
                 next.main.scale = Vec3::one();
             },
-            Some(ToolKind::Dagger) => {
+            Some(ToolKind::Dagger(_)) => {
                 next.l_hand.offset = Vec3::new(-6.0, 3.5, 0.0);
                 next.l_hand.ori = Quaternion::rotation_x(-0.3);
                 next.l_hand.scale = Vec3::one() * 1.01;
diff --git a/voxygen/src/anim/mod.rs b/voxygen/src/anim/mod.rs
index c09fbc3e97..5860306ecf 100644
--- a/voxygen/src/anim/mod.rs
+++ b/voxygen/src/anim/mod.rs
@@ -166,27 +166,27 @@ impl<'a> From<&'a comp::humanoid::Body> for SkeletonAttr {
                 (Danari, Male) => 0.0,
                 (Danari, Female) => 0.0,
             },
-            weapon_x: match ToolKind::Hammer {
+            weapon_x: match ToolKind::Empty {
                 // TODO: Inventory
                 ToolKind::Sword(_) => 0.0,
-                ToolKind::Axe => 3.0,
-                ToolKind::Hammer => 0.0,
-                ToolKind::Shield => 3.0,
-                ToolKind::Staff => 3.0,
-                ToolKind::Bow => 0.0,
-                ToolKind::Dagger => 0.0,
+                ToolKind::Axe(_) => 3.0,
+                ToolKind::Hammer(_) => 0.0,
+                ToolKind::Shield(_) => 3.0,
+                ToolKind::Staff(_) => 3.0,
+                ToolKind::Bow(_) => 0.0,
+                ToolKind::Dagger(_) => 0.0,
                 ToolKind::Debug(_) => 0.0,
                 ToolKind::Empty => 0.0,
             },
-            weapon_y: match ToolKind::Hammer {
+            weapon_y: match ToolKind::Empty {
                 // TODO: Inventory
                 ToolKind::Sword(_) => -1.25,
-                ToolKind::Axe => 0.0,
-                ToolKind::Hammer => -2.0,
-                ToolKind::Shield => 0.0,
-                ToolKind::Staff => 0.0,
-                ToolKind::Bow => -2.0,
-                ToolKind::Dagger => -2.0,
+                ToolKind::Axe(_) => 0.0,
+                ToolKind::Hammer(_) => -2.0,
+                ToolKind::Shield(_) => 0.0,
+                ToolKind::Staff(_) => 0.0,
+                ToolKind::Bow(_) => -2.0,
+                ToolKind::Dagger(_) => -2.0,
                 ToolKind::Debug(_) => 0.0,
                 ToolKind::Empty => 0.0,
             },
diff --git a/voxygen/src/hud/bag.rs b/voxygen/src/hud/bag.rs
index c8348e4dd6..77af78dd3a 100644
--- a/voxygen/src/hud/bag.rs
+++ b/voxygen/src/hud/bag.rs
@@ -58,8 +58,8 @@ widget_ids! {
         hands_bg,
         pants_bg,
         belt_bg,
-        ring-r_bg,
-        ring-l_bg,
+        ring_r_bg,
+        ring_l_bg,
         foot_bg,
         back_bg,
         tabard_bg,
diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs
index 877132222d..70c5bdb576 100644
--- a/voxygen/src/hud/skillbar.rs
+++ b/voxygen/src/hud/skillbar.rs
@@ -586,8 +586,8 @@ impl<'a> Widget for Skillbar<'a> {
             .color(
                 match self.loadout.active_item.as_ref().map(|i| &i.item.kind) {
                     Some(ItemKind::Tool(ToolData { kind, .. })) => match kind {
-                        ToolKind::Bow => Some(BG_COLOR_2),
-                        ToolKind::Staff => Some(BG_COLOR_2),
+                        ToolKind::Bow(_) => Some(BG_COLOR_2),
+                        ToolKind::Staff(_) => Some(BG_COLOR_2),
                         _ => Some(BG_COLOR_2),
                     },
                     _ => Some(BG_COLOR_2),
@@ -599,10 +599,10 @@ impl<'a> Widget for Skillbar<'a> {
             match self.loadout.active_item.as_ref().map(|i| &i.item.kind) {
                 Some(ItemKind::Tool(ToolData { kind, .. })) => match kind {
                     ToolKind::Sword(_) => self.imgs.twohsword_m1,
-                    ToolKind::Hammer => self.imgs.twohhammer_m1,
-                    ToolKind::Axe => self.imgs.twohaxe_m1,
-                    ToolKind::Bow => self.imgs.bow_m1,
-                    ToolKind::Staff => self.imgs.staff_m1,
+                    ToolKind::Hammer(_) => self.imgs.twohhammer_m1,
+                    ToolKind::Axe(_) => self.imgs.twohaxe_m1,
+                    ToolKind::Bow(_) => self.imgs.bow_m1,
+                    ToolKind::Staff(_) => self.imgs.staff_m1,
                     ToolKind::Debug(DebugKind::Boost) => self.imgs.flyingrod_m1,
                     _ => self.imgs.twohaxe_m1,
                 },
@@ -612,8 +612,8 @@ impl<'a> Widget for Skillbar<'a> {
         .w(
             match self.loadout.active_item.as_ref().map(|i| &i.item.kind) {
                 Some(ItemKind::Tool(ToolData { kind, .. })) => match kind {
-                    ToolKind::Bow => 30.0 * scale,
-                    ToolKind::Staff => 32.0 * scale,
+                    ToolKind::Bow(_) => 30.0 * scale,
+                    ToolKind::Staff(_) => 32.0 * scale,
                     _ => 38.0 * scale,
                 },
                 _ => 38.0 * scale,
@@ -622,8 +622,8 @@ impl<'a> Widget for Skillbar<'a> {
         .h(
             match self.loadout.active_item.as_ref().map(|i| &i.item.kind) {
                 Some(ItemKind::Tool(ToolData { kind, .. })) => match kind {
-                    ToolKind::Bow => 30.0 * scale,
-                    ToolKind::Staff => 32.0 * scale,
+                    ToolKind::Bow(_) => 30.0 * scale,
+                    ToolKind::Staff(_) => 32.0 * scale,
                     _ => 38.0 * scale,
                 },
                 _ => 38.0 * scale,
@@ -687,8 +687,8 @@ impl<'a> Widget for Skillbar<'a> {
             .color(
                 match self.loadout.active_item.as_ref().map(|i| &i.item.kind) {
                     Some(ItemKind::Tool(ToolData { kind, .. })) => match kind {
-                        ToolKind::Bow => Some(BG_COLOR_2),
-                        ToolKind::Staff => Some(BG_COLOR_2),
+                        ToolKind::Bow(_) => Some(BG_COLOR_2),
+                        ToolKind::Staff(_) => Some(BG_COLOR_2),
                         _ => Some(BG_COLOR_2),
                     },
                     _ => Some(BG_COLOR_2),
@@ -700,10 +700,10 @@ impl<'a> Widget for Skillbar<'a> {
             match self.loadout.active_item.as_ref().map(|i| &i.item.kind) {
                 Some(ItemKind::Tool(ToolData { kind, .. })) => match kind {
                     ToolKind::Sword(_) => self.imgs.twohsword_m2,
-                    ToolKind::Hammer => self.imgs.twohhammer_m2,
-                    ToolKind::Axe => self.imgs.twohaxe_m2,
-                    ToolKind::Bow => self.imgs.bow_m2,
-                    ToolKind::Staff => self.imgs.staff_m2,
+                    ToolKind::Hammer(_) => self.imgs.twohhammer_m2,
+                    ToolKind::Axe(_) => self.imgs.twohaxe_m2,
+                    ToolKind::Bow(_) => self.imgs.bow_m2,
+                    ToolKind::Staff(_) => self.imgs.staff_m2,
                     ToolKind::Debug(DebugKind::Boost) => self.imgs.flyingrod_m2,
                     _ => self.imgs.twohaxe_m2,
                 },
@@ -713,8 +713,8 @@ impl<'a> Widget for Skillbar<'a> {
         .w(
             match self.loadout.active_item.as_ref().map(|i| &i.item.kind) {
                 Some(ItemKind::Tool(ToolData { kind, .. })) => match kind {
-                    ToolKind::Bow => 30.0 * scale,
-                    ToolKind::Staff => 30.0 * scale,
+                    ToolKind::Bow(_) => 30.0 * scale,
+                    ToolKind::Staff(_) => 30.0 * scale,
                     _ => 38.0 * scale,
                 },
                 _ => 38.0 * scale,
@@ -723,8 +723,8 @@ impl<'a> Widget for Skillbar<'a> {
         .h(
             match self.loadout.active_item.as_ref().map(|i| &i.item.kind) {
                 Some(ItemKind::Tool(ToolData { kind, .. })) => match kind {
-                    ToolKind::Bow => 30.0 * scale,
-                    ToolKind::Staff => 30.0 * scale,
+                    ToolKind::Bow(_) => 30.0 * scale,
+                    ToolKind::Staff(_) => 30.0 * scale,
                     _ => 38.0 * scale,
                 },
                 _ => 38.0 * scale,
diff --git a/voxygen/src/scene/figure/cache.rs b/voxygen/src/scene/figure/cache.rs
index a96d5825c3..90af923e3e 100644
--- a/voxygen/src/scene/figure/cache.rs
+++ b/voxygen/src/scene/figure/cache.rs
@@ -119,6 +119,8 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
                                     HumArmorPantsSpec::load_watched(&mut self.manifest_indicator);
                                 let humanoid_armor_foot_spec =
                                     HumArmorFootSpec::load_watched(&mut self.manifest_indicator);
+                                let humanoid_main_weapon_spec =
+                                    HumMainWeaponSpec::load_watched(&mut self.manifest_indicator);
 
                                 // TODO: This is bad code, maybe this method should return Option<_>
                                 let default_loadout = Loadout::default();
@@ -213,7 +215,7 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
                                             })
                                             .unwrap_or_default()
                                     {
-                                        Some(mesh_main(
+                                        Some(humanoid_main_weapon_spec.mesh_main_weapon(
                                             loadout.active_item.as_ref().map(|i| &i.item.kind),
                                         ))
                                     } else {
diff --git a/voxygen/src/scene/figure/load.rs b/voxygen/src/scene/figure/load.rs
index fd3602df48..75758fdbe1 100644
--- a/voxygen/src/scene/figure/load.rs
+++ b/voxygen/src/scene/figure/load.rs
@@ -243,6 +243,8 @@ pub struct HumArmorBeltSpec(HashMap<Belt, ArmorVoxSpec>);
 pub struct HumArmorPantsSpec(HashMap<Pants, ArmorVoxSpec>);
 #[derive(Serialize, Deserialize)]
 pub struct HumArmorFootSpec(HashMap<Foot, ArmorVoxSpec>);
+#[derive(Serialize, Deserialize)]
+pub struct HumMainWeaponSpec(HashMap<ToolKind, ArmorVoxSpec>);
 
 impl Asset for HumArmorShoulderSpec {
     const ENDINGS: &'static [&'static str] = &["ron"];
@@ -286,6 +288,13 @@ impl Asset for HumArmorFootSpec {
         Ok(ron::de::from_reader(buf_reader).expect("Error parsing humanoid armor foot spec"))
     }
 }
+impl Asset for HumMainWeaponSpec {
+    const ENDINGS: &'static [&'static str] = &["ron"];
+
+    fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
+        Ok(ron::de::from_reader(buf_reader).expect("Error parsing humanoid main weapon spec"))
+    }
+}
 
 impl HumArmorShoulderSpec {
     pub fn load_watched(indicator: &mut ReloadIndicator) -> Arc<Self> {
@@ -624,25 +633,29 @@ impl HumArmorFootSpec {
     }
 }
 
-pub fn mesh_main(item_kind: Option<&ItemKind>) -> Mesh<FigurePipeline> {
-    if let Some(item_kind) = item_kind {
-        let (name, offset) = match item_kind {
-            ItemKind::Tool(ToolData { kind, .. }) => match kind {
-                ToolKind::Sword(_) => ("weapon.sword.rusty_2h", Vec3::new(-1.5, -6.5, -4.0)),
-                ToolKind::Axe => ("weapon.axe.rusty_2h", Vec3::new(-1.5, -5.0, -4.0)),
-                ToolKind::Hammer => ("weapon.hammer.rusty_2h", Vec3::new(-2.5, -5.5, -4.0)),
-                ToolKind::Dagger => ("weapon.hammer.rusty_2h", Vec3::new(-2.5, -5.5, -4.0)),
-                ToolKind::Shield => ("weapon.shield.wood-0", Vec3::new(-2.5, -6.5, -2.0)),
-                ToolKind::Bow => ("weapon.bow.simple-bow", Vec3::new(-1.0, -6.0, -2.0)),
-                ToolKind::Staff => ("weapon.staff.wood-fire", Vec3::new(-1.0, -6.0, -3.0)),
-                ToolKind::Debug(_) => ("weapon.debug_wand", Vec3::new(-1.5, -9.5, -4.0)),
-                ToolKind::Empty => return Mesh::new(),
-            },
-            _ => return Mesh::new(),
+impl HumMainWeaponSpec {
+    pub fn load_watched(indicator: &mut ReloadIndicator) -> Arc<Self> {
+        assets::load_watched::<Self>("voxygen.voxel.humanoid_main_weapon_manifest", indicator)
+            .unwrap()
+    }
+
+    pub fn mesh_main_weapon(&self, item_kind: Option<&ItemKind>) -> Mesh<FigurePipeline> {
+        let tool_kind = if let Some(ItemKind::Tool(ToolData { kind, .. })) = item_kind {
+            kind
+        } else {
+            return Mesh::new();
         };
-        load_mesh(name, offset)
-    } else {
-        Mesh::new()
+
+        let spec = match self.0.get(tool_kind) {
+            Some(spec) => spec,
+            None => {
+                error!("No hand specification exists for {:?}", tool_kind);
+                return load_mesh("not_found", Vec3::new(-1.5, -1.5, -7.0));
+            },
+        };
+
+        let tool_kind_segment = graceful_load_segment(&spec.vox_spec.0);
+        generate_mesh(&tool_kind_segment, Vec3::from(spec.vox_spec.1))
     }
 }