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()