diff --git a/CHANGELOG.md b/CHANGELOG.md
index f037571a06..d21aeda126 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -33,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Overhauled world colours
- Improved projectile physics
- Improved overhead aiming
+- Improved first person aiming
- Figure meshing no longer blocks the main thread.
- Overhauled persistence layer including no longer storing serialized JSON items in the database
diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs
index 986bc6647d..ec9ba06157 100644
--- a/common/src/comp/body.rs
+++ b/common/src/comp/body.rs
@@ -140,7 +140,7 @@ impl Body {
pub fn radius(&self) -> f32 {
// TODO: Improve these values (some might be reliant on more info in inner type)
match self {
- Body::Humanoid(_) => 0.35,
+ Body::Humanoid(body) => 0.35 * body.scale(),
Body::QuadrupedSmall(_) => 0.4,
Body::QuadrupedMedium(body) => match body.species {
quadruped_medium::Species::Grolgar => 1.9,
@@ -173,10 +173,10 @@ impl Body {
pub fn height(&self) -> f32 {
match self {
Body::Humanoid(humanoid) => match humanoid.species {
- humanoid::Species::Danari => 1.5,
- humanoid::Species::Dwarf => 1.55,
- humanoid::Species::Orc => 1.95,
- _ => 1.8,
+ humanoid::Species::Danari => 1.5 * humanoid.scale(),
+ humanoid::Species::Dwarf => 1.55 * humanoid.scale(),
+ humanoid::Species::Orc => 1.95 * humanoid.scale(),
+ _ => 1.8 * humanoid.scale(),
},
Body::QuadrupedSmall(body) => match body.species {
quadruped_small::Species::Dodarock => 1.5,
diff --git a/common/src/comp/body/humanoid.rs b/common/src/comp/body/humanoid.rs
index 43a3d0dc1f..f4dfda99ec 100644
--- a/common/src/comp/body/humanoid.rs
+++ b/common/src/comp/body/humanoid.rs
@@ -63,8 +63,33 @@ impl Body {
.accessory
.min(self.species.num_accessories(self.body_type) - 1);
}
+
+ /// Returns a scale value relative to the average humanoid
+ pub fn scale(&self) -> f32 {
+ use BodyType::*;
+ use Species::*;
+ match (self.species, self.body_type) {
+ (Orc, Male) => 1.14,
+ (Orc, Female) => 1.02,
+ (Human, Male) => 1.02,
+ (Human, Female) => 0.96,
+ (Elf, Male) => 1.02,
+ (Elf, Female) => 0.96,
+ (Dwarf, Male) => 0.84,
+ (Dwarf, Female) => 0.78,
+ (Undead, Male) => 0.96,
+ (Undead, Female) => 0.9,
+ (Danari, Male) => 0.696,
+ (Danari, Female) => 0.696,
+ }
+ }
+
+ /// Returns the eye height for this humanoid.
+ pub fn eye_height(&self) -> f32 { DEFAULT_HUMANOID_EYE_HEIGHT * self.scale() }
}
+pub const DEFAULT_HUMANOID_EYE_HEIGHT: f32 = 1.65;
+
impl From
for super::Body {
fn from(body: Body) -> Self { super::Body::Humanoid(body) }
}
diff --git a/server/src/events/entity_creation.rs b/server/src/events/entity_creation.rs
index 0ac5100999..28034143a8 100644
--- a/server/src/events/entity_creation.rs
+++ b/server/src/events/entity_creation.rs
@@ -2,8 +2,8 @@ use crate::{sys, Server, StateExt};
use common::{
character::CharacterId,
comp::{
- self, Agent, Alignment, Body, Gravity, Item, ItemDrop, LightEmitter, Loadout, Pos,
- Projectile, Scale, Stats, Vel, WaypointArea,
+ self, humanoid::DEFAULT_HUMANOID_EYE_HEIGHT, Agent, Alignment, Body, Gravity, Item,
+ ItemDrop, LightEmitter, Loadout, Pos, Projectile, Scale, Stats, Vel, WaypointArea,
},
outcome::Outcome,
util::Dir,
@@ -105,8 +105,12 @@ pub fn handle_shoot(
.write_resource::>()
.push(Outcome::ProjectileShot { pos, body, vel });
- // TODO: Player height
- pos.z += 1.2;
+ let eye_height = match state.ecs().read_storage::().get(entity) {
+ Some(comp::Body::Humanoid(body)) => body.eye_height(),
+ _ => DEFAULT_HUMANOID_EYE_HEIGHT,
+ };
+
+ pos.z += eye_height;
let mut builder = state.create_projectile(Pos(pos), Vel(vel), body, projectile);
if let Some(light) = light {
diff --git a/voxygen/src/anim/src/character/mod.rs b/voxygen/src/anim/src/character/mod.rs
index 37738b7f8c..b6ef304af9 100644
--- a/voxygen/src/anim/src/character/mod.rs
+++ b/voxygen/src/anim/src/character/mod.rs
@@ -158,32 +158,12 @@ impl<'a> std::convert::TryFrom<&'a comp::Body> for SkeletonAttr {
}
}
-impl SkeletonAttr {
- pub fn calculate_scale(body: &Body) -> f32 {
- use comp::humanoid::{BodyType::*, Species::*};
- match (body.species, body.body_type) {
- (Orc, Male) => 1.14,
- (Orc, Female) => 1.02,
- (Human, Male) => 1.02,
- (Human, Female) => 0.96,
- (Elf, Male) => 1.02,
- (Elf, Female) => 0.96,
- (Dwarf, Male) => 0.84,
- (Dwarf, Female) => 0.78,
- (Undead, Male) => 0.96,
- (Undead, Female) => 0.9,
- (Danari, Male) => 0.696,
- (Danari, Female) => 0.696,
- }
- }
-}
-
impl<'a> From<&'a Body> for SkeletonAttr {
#[allow(clippy::match_single_binding)] // TODO: Pending review in #587
fn from(body: &'a Body) -> Self {
use comp::humanoid::{BodyType::*, Species::*};
Self {
- scaler: SkeletonAttr::calculate_scale(body),
+ scaler: body.scale(),
head_scale: match (body.species, body.body_type) {
(Orc, Male) => 0.9,
(Orc, Female) => 0.9,
diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs
index a4970a1ed8..35dd68c32f 100644
--- a/voxygen/src/scene/mod.rs
+++ b/voxygen/src/scene/mod.rs
@@ -23,10 +23,10 @@ use crate::{
settings::Settings,
window::{AnalogGameInput, Event},
};
-use anim::character::SkeletonAttr;
use client::Client;
use common::{
comp,
+ comp::humanoid::DEFAULT_HUMANOID_EYE_HEIGHT,
outcome::Outcome,
span,
state::{DeltaTime, State},
@@ -456,10 +456,20 @@ impl Scene {
.read_storage::()
.get(scene_data.player_entity)
{
- Some(comp::Body::Humanoid(body)) => SkeletonAttr::calculate_scale(body),
+ Some(comp::Body::Humanoid(body)) => body.scale(),
_ => 1_f32,
};
+ let eye_height = match scene_data
+ .state
+ .ecs()
+ .read_storage::()
+ .get(scene_data.player_entity)
+ {
+ Some(comp::Body::Humanoid(body)) => body.eye_height(),
+ _ => DEFAULT_HUMANOID_EYE_HEIGHT,
+ };
+
// Add the analog input to camera
self.camera
.rotate_by(Vec3::from([self.camera_input_state.x, 0.0, 0.0]));
@@ -475,13 +485,13 @@ impl Scene {
if player_rolling {
player_scale * 0.8
} else if is_running && on_ground.unwrap_or(false) {
- player_scale * 1.65 + (scene_data.state.get_time() as f32 * 17.0).sin() * 0.05
+ eye_height + (scene_data.state.get_time() as f32 * 17.0).sin() * 0.05
} else {
- player_scale * 1.65
+ eye_height
}
},
CameraMode::ThirdPerson if scene_data.is_aiming => player_scale * 2.2,
- CameraMode::ThirdPerson => player_scale * 1.65,
+ CameraMode::ThirdPerson => eye_height,
CameraMode::Freefly => 0.0,
};
diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs
index 1ed9105336..729d7b4a54 100644
--- a/voxygen/src/session.rs
+++ b/voxygen/src/session.rs
@@ -6,7 +6,7 @@ use crate::{
key_state::KeyState,
menu::char_selection::CharSelectionState,
render::Renderer,
- scene::{camera, Scene, SceneData},
+ scene::{camera, CameraMode, Scene, SceneData},
settings::{AudioOutput, ControlSettings, Settings},
window::{AnalogGameInput, Event, GameInput},
Direction, Error, GlobalState, PlayState, PlayStateResult,
@@ -248,7 +248,7 @@ impl PlayState for SessionState {
(
is_aiming,
- if is_aiming {
+ if is_aiming && self.scene.camera().get_mode() == CameraMode::ThirdPerson {
Vec3::unit_z() * 0.05
} else {
Vec3::zero()