diff --git a/assets/voxygen/shaders/include/light.glsl b/assets/voxygen/shaders/include/light.glsl
index e30c1fc052..8c64bd037d 100644
--- a/assets/voxygen/shaders/include/light.glsl
+++ b/assets/voxygen/shaders/include/light.glsl
@@ -184,7 +184,8 @@ float lights_at(vec3 wpos, vec3 wnorm, vec3 /*cam_to_frag*/view_dir, vec3 mu, ve
 #if (LIGHTING_TYPE & LIGHTING_TYPE_TRANSMISSION) != 0
         is_direct = true;
 #endif
-        vec3 direct_light = PI * color * strength * square_factor * light_reflection_factor(/*direct_norm_dir*/wnorm, /*cam_to_frag*/view_dir, direct_light_dir, k_d, k_s, alpha, voxel_norm, voxel_lighting);
+        vec3 lrf = light_reflection_factor(/*direct_norm_dir*/wnorm, /*cam_to_frag*/view_dir, direct_light_dir, k_d, k_s, alpha, voxel_norm, voxel_lighting);
+        vec3 direct_light = PI * color * strength * square_factor * pow(lrf, vec3(0.5)); // TODO: Don't use ^0.5, it's non-physical but helps with hill climbing
         float computed_shadow = ShadowCalculationPoint(i, -difference, wnorm, wpos/*, light_distance*/);
         // directed_light += is_direct ? max(computed_shadow, /*LIGHT_AMBIANCE*/0.0) * direct_light * square_factor : vec3(0.0);
         #ifdef FIGURE_SHADER
diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs
index 587b3f5b1f..553384db9f 100644
--- a/common/src/comp/character_state.rs
+++ b/common/src/comp/character_state.rs
@@ -167,6 +167,18 @@ impl CharacterState {
         )
     }
 
+    pub fn is_using_hands(&self) -> bool {
+        matches!(
+            self,
+            CharacterState::Climb(_)
+                | CharacterState::Equipping(_)
+                | CharacterState::Dance
+                | CharacterState::Glide
+                | CharacterState::GlideWield
+                | CharacterState::Roll(_),
+        )
+    }
+
     pub fn is_block(&self) -> bool { matches!(self, CharacterState::BasicBlock) }
 
     pub fn is_dodge(&self) -> bool { matches!(self, CharacterState::Roll(_)) }
diff --git a/voxygen/anim/src/character/jump.rs b/voxygen/anim/src/character/jump.rs
index 8d1742aaf4..7bf3948940 100644
--- a/voxygen/anim/src/character/jump.rs
+++ b/voxygen/anim/src/character/jump.rs
@@ -192,6 +192,16 @@ impl Animation for JumpAnimation {
         next.lantern.scale = Vec3::one() * 0.65;
         next.hold.scale = Vec3::one() * 0.0;
 
+        if skeleton.holding_lantern {
+            next.hand_r.position = Vec3::new(s_a.hand.0, s_a.hand.1 + 5.0, s_a.hand.2 + 9.0);
+            next.hand_r.orientation = Quaternion::rotation_x(2.25) * Quaternion::rotation_z(0.9);
+
+            next.lantern.position = Vec3::new(0.0, 0.0, -3.5);
+            next.lantern.orientation = next.hand_r.orientation.inverse()
+                * Quaternion::rotation_x(slow * 0.5)
+                * Quaternion::rotation_y(tilt * 4.0 * slow + tilt * 3.0);
+        }
+
         next.torso.position = Vec3::new(0.0, 0.0, 0.0) * s_a.scaler;
         next.torso.orientation = Quaternion::rotation_x(0.0);
         next.torso.scale = Vec3::one() / 11.0 * s_a.scaler;
diff --git a/voxygen/anim/src/character/mod.rs b/voxygen/anim/src/character/mod.rs
index 96fb1b01dc..a060291196 100644
--- a/voxygen/anim/src/character/mod.rs
+++ b/voxygen/anim/src/character/mod.rs
@@ -69,8 +69,19 @@ skeleton_impls!(struct CharacterSkeleton {
     control,
     control_l,
     control_r,
+    :: // Begin non-bone fields
+    holding_lantern: bool,
 });
 
+impl CharacterSkeleton {
+    pub fn new(holding_lantern: bool) -> Self {
+        Self {
+            holding_lantern,
+            ..Self::default()
+        }
+    }
+}
+
 impl Skeleton for CharacterSkeleton {
     type Attr = SkeletonAttr;
     type Body = Body;
@@ -93,9 +104,14 @@ impl Skeleton for CharacterSkeleton {
         let control_mat = chest_mat * Mat4::<f32>::from(self.control);
         let control_l_mat = control_mat * Mat4::<f32>::from(self.control_l);
         let control_r_mat = control_mat * Mat4::<f32>::from(self.control_r);
+        let hand_r_mat = control_r_mat * Mat4::<f32>::from(self.hand_r);
 
         let hand_l_mat = Mat4::<f32>::from(self.hand_l);
-        let lantern_mat = Mat4::<f32>::from(self.lantern);
+        let lantern_mat = if self.holding_lantern {
+            hand_r_mat
+        } else {
+            shorts_mat
+        } * Mat4::<f32>::from(self.lantern);
 
         *(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [
             make_bone(head_mat),
@@ -104,7 +120,7 @@ impl Skeleton for CharacterSkeleton {
             make_bone(chest_mat * Mat4::<f32>::from(self.back)),
             make_bone(shorts_mat),
             make_bone(control_l_mat * hand_l_mat),
-            make_bone(control_r_mat * Mat4::<f32>::from(self.hand_r)),
+            make_bone(hand_r_mat),
             make_bone(torso_mat * Mat4::<f32>::from(self.foot_l)),
             make_bone(torso_mat * Mat4::<f32>::from(self.foot_r)),
             make_bone(chest_mat * Mat4::<f32>::from(self.shoulder_l)),
@@ -112,12 +128,11 @@ impl Skeleton for CharacterSkeleton {
             make_bone(chest_mat * Mat4::<f32>::from(self.glider)),
             make_bone(control_l_mat * Mat4::<f32>::from(self.main)),
             make_bone(control_r_mat * Mat4::<f32>::from(self.second)),
-            make_bone(shorts_mat * lantern_mat),
+            make_bone(lantern_mat),
             // FIXME: Should this be control_l_mat?
             make_bone(control_mat * hand_l_mat * Mat4::<f32>::from(self.hold)),
         ];
-        // NOTE: lantern_mat.cols.w = lantern_mat * Vec4::unit_w()
-        Vec3::new(-0.3, 0.1, 0.8) + (lantern_mat.cols.w / 13.0).xyz()
+        (lantern_mat * Vec4::new(-0.0, -0.0, -1.5, 1.0)).xyz()
     }
 }
 
diff --git a/voxygen/anim/src/character/run.rs b/voxygen/anim/src/character/run.rs
index 5d5100f8d7..25d9139715 100644
--- a/voxygen/anim/src/character/run.rs
+++ b/voxygen/anim/src/character/run.rs
@@ -256,6 +256,20 @@ impl Animation for RunAnimation {
         next.lantern.scale = Vec3::one() * 0.65;
         next.hold.scale = Vec3::one() * 0.0;
 
+        if skeleton.holding_lantern {
+            next.hand_r.position = Vec3::new(
+                s_a.hand.0,
+                s_a.hand.1 + 5.0 - impact * 0.2,
+                s_a.hand.2 + 11.0 + impact * -0.1,
+            );
+            next.hand_r.orientation = Quaternion::rotation_x(2.25) * Quaternion::rotation_z(0.9);
+
+            next.lantern.position = Vec3::new(0.0, 0.0, -2.5);
+            next.lantern.orientation = next.hand_r.orientation.inverse()
+                * Quaternion::rotation_x((foothorir + 0.5) * 1.0 * speednorm)
+                * Quaternion::rotation_y(tilt * 4.0 * foothorir + tilt * 3.0);
+        }
+
         next.torso.position = Vec3::new(0.0, 0.0, 0.0) * s_a.scaler;
         next.torso.scale = Vec3::one() / 11.0 * s_a.scaler;
 
diff --git a/voxygen/anim/src/character/sit.rs b/voxygen/anim/src/character/sit.rs
index 74cd609d60..558e184ba6 100644
--- a/voxygen/anim/src/character/sit.rs
+++ b/voxygen/anim/src/character/sit.rs
@@ -29,8 +29,16 @@ impl Animation for SitAnimation {
         let stop = (anim_time * 3.0).min(PI / 2.0).sin();
 
         let head_look = Vec2::new(
-            (global_time + anim_time / 18.0).floor().mul(7331.0).sin() * 0.25,
-            (global_time + anim_time / 18.0).floor().mul(1337.0).sin() * 0.125,
+            (global_time * 0.05 + anim_time / 15.0)
+                .floor()
+                .mul(7331.0)
+                .sin()
+                * 0.25,
+            (global_time * 0.05 + anim_time / 15.0)
+                .floor()
+                .mul(1337.0)
+                .sin()
+                * 0.125,
         );
         next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1 + slow * 0.1 + stop * -0.8);
         next.head.orientation = Quaternion::rotation_z(head_look.x + slow * 0.2 - slow * 0.1)
@@ -79,6 +87,21 @@ impl Animation for SitAnimation {
 
         next.torso.position = Vec3::new(0.0, -0.2, stop * -0.16) * s_a.scaler;
 
+        if skeleton.holding_lantern {
+            next.hand_r.position = Vec3::new(
+                s_a.hand.0 - head_look.x * 10.0,
+                s_a.hand.1 + 5.0 + head_look.y * 12.0,
+                s_a.hand.2 + 9.0 - head_look.y * 12.0,
+            );
+            next.hand_r.orientation = Quaternion::rotation_x(2.25)
+                * Quaternion::rotation_z(0.9)
+                * Quaternion::rotation_y(head_look.x * 3.0)
+                * Quaternion::rotation_x(head_look.y * 3.0);
+
+            next.lantern.position = Vec3::new(0.0, 0.0, -3.5);
+            next.lantern.orientation = next.hand_r.orientation.inverse();
+        }
+
         next
     }
 }
diff --git a/voxygen/anim/src/character/sneak.rs b/voxygen/anim/src/character/sneak.rs
index ca0a41d99e..13897e5a0a 100644
--- a/voxygen/anim/src/character/sneak.rs
+++ b/voxygen/anim/src/character/sneak.rs
@@ -158,6 +158,15 @@ impl Animation for SneakAnimation {
 
             next.foot_r.position = Vec3::new(s_a.foot.0, 4.0 + s_a.foot.1, s_a.foot.2);
         }
+
+        if skeleton.holding_lantern {
+            next.hand_r.position = Vec3::new(s_a.hand.0, s_a.hand.1 + 5.0, s_a.hand.2 + 9.0);
+            next.hand_r.orientation = Quaternion::rotation_x(2.5);
+
+            next.lantern.position = Vec3::new(0.0, 1.5, -5.5);
+            next.lantern.orientation = next.hand_r.orientation.inverse();
+        }
+
         next
     }
 }
diff --git a/voxygen/anim/src/character/stand.rs b/voxygen/anim/src/character/stand.rs
index 34f8cbcb38..242f365de4 100644
--- a/voxygen/anim/src/character/stand.rs
+++ b/voxygen/anim/src/character/stand.rs
@@ -32,6 +32,7 @@ impl Animation for StandAnimation {
         let mut next = (*skeleton).clone();
 
         let slow = (anim_time * 1.0).sin();
+        let fast = (anim_time * 5.0).sin();
         let impact = (avg_vel.z).max(-15.0);
         let head_look = Vec2::new(
             ((global_time + anim_time) / 10.0).floor().mul(7331.0).sin() * 0.15,
@@ -142,6 +143,22 @@ impl Animation for StandAnimation {
         next.lantern.position = Vec3::new(s_a.lantern.0, s_a.lantern.1, s_a.lantern.2);
         next.lantern.orientation = Quaternion::rotation_x(0.1) * Quaternion::rotation_y(0.1);
 
+        if skeleton.holding_lantern {
+            next.hand_r.position = Vec3::new(
+                s_a.hand.0 - head_look.x * 10.0,
+                s_a.hand.1 + 5.0 - head_look.y * 8.0 + slow * 0.15 - impact * 0.2,
+                s_a.hand.2 + 11.0 + slow * 0.5 + impact * -0.1,
+            );
+            next.hand_r.orientation = Quaternion::rotation_x(2.5 + slow * -0.06 + impact * -0.1)
+                * Quaternion::rotation_z(0.9)
+                * Quaternion::rotation_y(head_look.x * 3.0)
+                * Quaternion::rotation_x(head_look.y * 3.0);
+
+            next.lantern.position = Vec3::new(0.0, 0.0, -3.5);
+            next.lantern.orientation =
+                next.hand_r.orientation.inverse() * Quaternion::rotation_x(fast * 0.1);
+        }
+
         next.torso.position = Vec3::new(0.0, 0.0, 0.0) * s_a.scaler;
         next.second.scale = Vec3::one();
         next.second.scale = match hands {
diff --git a/voxygen/anim/src/character/wield.rs b/voxygen/anim/src/character/wield.rs
index 1dc4244f63..aaa4f035d2 100644
--- a/voxygen/anim/src/character/wield.rs
+++ b/voxygen/anim/src/character/wield.rs
@@ -320,15 +320,17 @@ impl Animation for WieldAnimation {
         };
         match hands {
             (None, None) | (None, Some(Hands::One)) => {
-                next.hand_l.position = Vec3::new(-4.5, 8.0, 5.0);
-                next.hand_l.orientation = Quaternion::rotation_x(1.9) * Quaternion::rotation_y(-0.5)
+                next.hand_l.position = Vec3::new(-8.0, 2.0, 1.0);
+                next.hand_l.orientation =
+                    Quaternion::rotation_x(0.5) * Quaternion::rotation_y(0.25);
             },
             (_, _) => {},
         };
         match hands {
             (None, None) | (Some(Hands::One), None) => {
-                next.hand_r.position = Vec3::new(4.5, 8.0, 5.0);
-                next.hand_r.orientation = Quaternion::rotation_x(1.9) * Quaternion::rotation_y(0.5)
+                next.hand_r.position = Vec3::new(8.0, 2.0, 1.0);
+                next.hand_r.orientation =
+                    Quaternion::rotation_x(0.5) * Quaternion::rotation_y(-0.25);
             },
             (_, _) => {},
         };
@@ -337,6 +339,21 @@ impl Animation for WieldAnimation {
             next.second = next.main;
         }
 
+        if skeleton.holding_lantern {
+            next.hand_r.position = Vec3::new(
+                s_a.hand.0 - head_look.x * 10.0,
+                s_a.hand.1 + 5.0 + slow * 0.15,
+                s_a.hand.2 + 9.0 + head_look.y * 18.0 + slow * 0.5,
+            );
+            next.hand_r.orientation = Quaternion::rotation_x(2.25 + slow * -0.06)
+                * Quaternion::rotation_z(0.9)
+                * Quaternion::rotation_y(head_look.x * 3.0)
+                * Quaternion::rotation_x(head_look.y * 3.0);
+
+            next.lantern.position = Vec3::new(0.0, 0.0, -3.5);
+            next.lantern.orientation = next.hand_r.orientation.inverse();
+        }
+
         next
     }
 }
diff --git a/voxygen/anim/src/lib.rs b/voxygen/anim/src/lib.rs
index c424b4d869..8895e92841 100644
--- a/voxygen/anim/src/lib.rs
+++ b/voxygen/anim/src/lib.rs
@@ -5,12 +5,15 @@
 compile_error!("Can't use both \"be-dyn-lib\" and \"use-dyn-lib\" features at once");
 
 macro_rules! skeleton_impls {
-    { struct $Skeleton:ident { $( $(+)? $bone:ident ),* $(,)? } } => {
+    { struct $Skeleton:ident { $( $(+)? $bone:ident ),* $(,)? $(:: $($field:ident : $field_ty:ty),* $(,)? )? } } => {
         #[derive(Clone, Default)]
         pub struct $Skeleton {
             $(
                 $bone: $crate::Bone,
             )*
+            $($(
+                $field : $field_ty,
+            )*)?
         }
 
         impl<'a, Factor> $crate::vek::Lerp<Factor> for &'a $Skeleton
@@ -25,6 +28,9 @@ macro_rules! skeleton_impls {
                     $(
                         $bone: Lerp::lerp_unclamped_precise(from.$bone, to.$bone, factor),
                     )*
+                    $($(
+                        $field : to.$field.clone(),
+                    )*)?
                 }
             }
 
@@ -33,6 +39,9 @@ macro_rules! skeleton_impls {
                     $(
                         $bone: Lerp::lerp_unclamped(from.$bone, to.$bone, factor),
                     )*
+                    $($(
+                        $field : to.$field.clone(),
+                    )*)?
                 }
             }
         }
diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs
index 5e931d8374..c048dc16c1 100644
--- a/voxygen/src/scene/figure/mod.rs
+++ b/voxygen/src/scene/figure/mod.rs
@@ -584,6 +584,7 @@ impl FigureMgr {
                 health,
                 inventory,
                 item,
+                light_emitter,
             ),
         ) in (
             &ecs.entities(),
@@ -599,6 +600,7 @@ impl FigureMgr {
             ecs.read_storage::<Health>().maybe(),
             ecs.read_storage::<Inventory>().maybe(),
             ecs.read_storage::<Item>().maybe(),
+            ecs.read_storage::<LightEmitter>().maybe(),
         )
             .join()
             .enumerate()
@@ -760,12 +762,20 @@ impl FigureMgr {
                         &slow_jobs,
                     );
 
+                    let holding_lantern = inventory
+                        .map_or(false, |i| i.equipped(EquipSlot::Lantern).is_some())
+                        && light_emitter.is_some()
+                        && !(matches!(second_tool_hand, Some(_))
+                            && character.map_or(false, |c| c.is_wield()))
+                        && !character.map_or(false, |c| c.is_using_hands())
+                        && physics.in_liquid().is_none();
+
                     let state = self
                         .states
                         .character_states
                         .entry(entity)
                         .or_insert_with(|| {
-                            FigureState::new(renderer, CharacterSkeleton::default())
+                            FigureState::new(renderer, CharacterSkeleton::new(holding_lantern))
                         });
 
                     // Average velocity relative to the current ground
@@ -787,7 +797,7 @@ impl FigureMgr {
                     ) {
                         // Standing
                         (true, false, false) => anim::character::StandAnimation::update_skeleton(
-                            &CharacterSkeleton::default(),
+                            &CharacterSkeleton::new(holding_lantern),
                             (active_tool_kind, second_tool_kind, hands, time, rel_avg_vel),
                             state.state_time,
                             &mut state_animation_rate,
@@ -795,7 +805,7 @@ impl FigureMgr {
                         ),
                         // Running
                         (true, true, false) => anim::character::RunAnimation::update_skeleton(
-                            &CharacterSkeleton::default(),
+                            &CharacterSkeleton::new(holding_lantern),
                             (
                                 active_tool_kind,
                                 second_tool_kind,
@@ -814,7 +824,7 @@ impl FigureMgr {
                         ),
                         // In air
                         (false, _, false) => anim::character::JumpAnimation::update_skeleton(
-                            &CharacterSkeleton::default(),
+                            &CharacterSkeleton::new(holding_lantern),
                             (
                                 active_tool_kind,
                                 second_tool_kind,
@@ -831,7 +841,7 @@ impl FigureMgr {
                         ),
                         // Swim
                         (_, _, true) => anim::character::SwimAnimation::update_skeleton(
-                            &CharacterSkeleton::default(),
+                            &CharacterSkeleton::new(holding_lantern),
                             (
                                 active_tool_kind,
                                 second_tool_kind,
@@ -1376,7 +1386,7 @@ impl FigureMgr {
                         },
                         CharacterState::BasicBlock { .. } => {
                             anim::character::BlockAnimation::update_skeleton(
-                                &CharacterSkeleton::default(),
+                                &CharacterSkeleton::new(holding_lantern),
                                 (active_tool_kind, second_tool_kind, time),
                                 state.state_time,
                                 &mut state_animation_rate,
diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs
index eccdbf5f90..daff82a064 100644
--- a/voxygen/src/scene/mod.rs
+++ b/voxygen/src/scene/mod.rs
@@ -560,7 +560,6 @@ impl Scene {
         lights.extend(
             (
                 &scene_data.state.ecs().read_storage::<comp::Pos>(),
-                scene_data.state.ecs().read_storage::<comp::Ori>().maybe(),
                 scene_data
                     .state
                     .ecs()
@@ -572,23 +571,16 @@ impl Scene {
                     .read_storage::<comp::LightAnimation>(),
             )
                 .join()
-                .filter(|(pos, _, _, light_anim)| {
+                .filter(|(pos, _, light_anim)| {
                     light_anim.col != Rgb::zero()
                         && light_anim.strength > 0.0
                         && (pos.0.distance_squared(player_pos) as f32)
                             < loaded_distance.powi(2) + LIGHT_DIST_RADIUS
                 })
-                .map(|(pos, ori, interpolated, light_anim)| {
+                .map(|(pos, interpolated, light_anim)| {
                     // Use interpolated values if they are available
-                    let (pos, rot) = interpolated
-                        .map_or((pos.0, ori.copied().unwrap_or_default()), |i| {
-                            (i.pos, i.ori)
-                        });
-                    Light::new(
-                        pos + (rot.to_quat() * light_anim.offset),
-                        light_anim.col,
-                        light_anim.strength,
-                    )
+                    let pos = interpolated.map_or(pos.0, |i| i.pos);
+                    Light::new(pos + light_anim.offset, light_anim.col, light_anim.strength)
                 })
                 .chain(
                     self.event_lights