diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index 05f5ebd5c9..0febc1e799 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -4,18 +4,13 @@ pub mod quadruped_medium; use specs::{Component, FlaggedStorage, VecStorage}; -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum Actor { - Character { name: String, body: Body }, -} - -impl Component for Actor { - type Storage = FlaggedStorage>; -} - #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Body { Humanoid(humanoid::Body), Quadruped(quadruped::Body), QuadrupedMedium(quadruped_medium::Body), } + +impl Component for Body { + type Storage = FlaggedStorage>; +} diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index fee0d63f16..8723cf8b0b 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -13,7 +13,7 @@ mod stats; pub use action_state::ActionState; pub use agent::Agent; pub use animation::{Animation, AnimationInfo}; -pub use body::{humanoid, quadruped, quadruped_medium, Actor, Body}; +pub use body::{humanoid, quadruped, quadruped_medium, Body}; pub use controller::Controller; pub use inputs::{Attacking, Gliding, Jumping, MoveDir, OnGround, Respawning, Rolling}; pub use inventory::{item, Inventory}; diff --git a/common/src/comp/stats.rs b/common/src/comp/stats.rs index 30e5bf3072..59dc2668b8 100644 --- a/common/src/comp/stats.rs +++ b/common/src/comp/stats.rs @@ -5,6 +5,7 @@ use specs::{Component, FlaggedStorage, VecStorage}; pub enum HealthSource { Attack { by: Uid }, // TODO: Implement weapon Suicide, + Revive, Unknown, } @@ -23,18 +24,20 @@ impl Health { self.maximum } pub fn set_to(&mut self, amount: u32, cause: HealthSource) { + let amount = amount.min(self.maximum); self.last_change = Some((amount as i32 - self.current as i32, 0.0, cause)); self.current = amount; } pub fn change_by(&mut self, amount: i32, cause: HealthSource) { - self.current = (self.current as i32 + amount).max(0) as u32; + self.current = ((self.current as i32 + amount).max(0) as u32).min(self.maximum); self.last_change = Some((amount, 0.0, cause)); } } -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct Stats { - pub hp: Health, + pub name: String, + pub health: Health, pub xp: u32, pub is_dead: bool, } @@ -42,14 +45,15 @@ pub struct Stats { impl Stats { pub fn should_die(&self) -> bool { // TODO: Remove - self.hp.current == 0 + self.health.current == 0 } } -impl Default for Stats { - fn default() -> Self { +impl Stats { + pub fn new(name: String) -> Self { Self { - hp: Health { + name, + health: Health { current: 100, maximum: 100, last_change: None, diff --git a/common/src/msg/ecs_packet.rs b/common/src/msg/ecs_packet.rs index 1c533cfd0e..76557b2e73 100644 --- a/common/src/msg/ecs_packet.rs +++ b/common/src/msg/ecs_packet.rs @@ -20,7 +20,7 @@ sphynx::sum_type! { Pos(comp::Pos), Vel(comp::Vel), Ori(comp::Ori), - Actor(comp::Actor), + Body(comp::Body), Player(comp::Player), Stats(comp::Stats), } @@ -33,7 +33,7 @@ sphynx::sum_type! { Pos(PhantomData), Vel(PhantomData), Ori(PhantomData), - Actor(PhantomData), + Body(PhantomData), Player(PhantomData), Stats(PhantomData), } diff --git a/common/src/state.rs b/common/src/state.rs index fa25027980..584426d79c 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -99,7 +99,7 @@ impl State { // Create a new Sphynx ECS world. fn setup_sphynx_world(ecs: &mut sphynx::World) { // Register server->client synced components. - ecs.register_synced::(); + ecs.register_synced::(); ecs.register_synced::(); ecs.register_synced::(); diff --git a/common/src/sys/combat.rs b/common/src/sys/combat.rs index 5aefa31c0d..162dee392d 100644 --- a/common/src/sys/combat.rs +++ b/common/src/sys/combat.rs @@ -52,7 +52,9 @@ impl<'a> System<'a> for Sys { && ori.0.angle_between(pos_b.0 - pos.0).to_degrees() < 70.0 { // Deal damage - stat_b.hp.change_by(-10, HealthSource::Attack { by: *uid }); // TODO: variable damage and weapon + stat_b + .health + .change_by(-10, HealthSource::Attack { by: *uid }); // TODO: variable damage and weapon vel_b.0 += (pos_b.0 - pos.0).normalized() * 10.0; vel_b.0.z = 15.0; let _ = force_updates.insert(b, ForceUpdate); diff --git a/common/src/sys/controller.rs b/common/src/sys/controller.rs index f78a912251..84cd440ef7 100644 --- a/common/src/sys/controller.rs +++ b/common/src/sys/controller.rs @@ -18,7 +18,7 @@ impl<'a> System<'a> for Sys { ReadStorage<'a, Pos>, ReadStorage<'a, Vel>, ReadStorage<'a, Ori>, - ReadStorage<'a, ActionState>, + WriteStorage<'a, ActionState>, WriteStorage<'a, MoveDir>, WriteStorage<'a, Jumping>, WriteStorage<'a, Attacking>, @@ -37,7 +37,7 @@ impl<'a> System<'a> for Sys { positions, velocities, orientations, - action_states, + mut action_states, mut move_dirs, mut jumpings, mut attackings, @@ -46,14 +46,16 @@ impl<'a> System<'a> for Sys { mut glidings, ): Self::SystemData, ) { - for (entity, controller, stats, pos, vel, ori, a) in ( + for (entity, controller, stats, pos, vel, ori, mut a) in ( &entities, &controllers, &stats, &positions, &velocities, &orientations, - &action_states, + // Although this is changed, it is only kept for this system + // as it will be replaced in the action state system + &mut action_states, ) .join() { @@ -80,18 +82,16 @@ impl<'a> System<'a> for Sys { // Glide if controller.glide && !a.on_ground && !a.attacking && !a.rolling { glidings.insert(entity, Gliding); + a.gliding = true; } else { glidings.remove(entity); + a.gliding = false; } // Attack if controller.attack && !a.attacking && !a.gliding && !a.rolling { attackings.insert(entity, Attacking::start()); - } - - // Jump - if controller.jump && a.on_ground && vel.0.z <= 0.0 { - jumpings.insert(entity, Jumping); + a.attacking = true; } // Roll @@ -103,6 +103,13 @@ impl<'a> System<'a> for Sys { && !a.gliding { rollings.insert(entity, Rolling::start()); + a.rolling = true; + } + + // Jump + if controller.jump && a.on_ground && vel.0.z <= 0.0 { + jumpings.insert(entity, Jumping); + a.on_ground = false; } } } diff --git a/common/src/sys/stats.rs b/common/src/sys/stats.rs index 22dc10d48b..8120bb82df 100644 --- a/common/src/sys/stats.rs +++ b/common/src/sys/stats.rs @@ -22,7 +22,7 @@ impl<'a> System<'a> for Sys { if let Err(err) = dyings.insert( entity, Dying { - cause: match stat.hp.last_change { + cause: match stat.health.last_change { Some(change) => change.2, None => { warn!("Nothing caused an entity to die!"); @@ -35,7 +35,7 @@ impl<'a> System<'a> for Sys { } stat.is_dead = true; } - if let Some(change) = &mut stat.hp.last_change { + if let Some(change) = &mut stat.health.last_change { change.1 += dt.0 as f64; } } diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 01c3bb0769..06d6642d0e 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -161,7 +161,7 @@ fn handle_kill(server: &mut Server, entity: EcsEntity, _args: String, _action: & .ecs_mut() .write_storage::() .get_mut(entity) - .map(|s| s.hp.set_to(0, comp::HealthSource::Suicide)); + .map(|s| s.health.set_to(0, comp::HealthSource::Suicide)); } fn handle_time(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { diff --git a/server/src/lib.rs b/server/src/lib.rs index 76c86cfc09..9912863eb4 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -146,8 +146,8 @@ impl Server { .with(comp::Vel(Vec3::zero())) .with(comp::Ori(Vec3::unit_y())) .with(comp::Controller::default()) - .with(comp::Actor::Character { name, body }) - .with(comp::Stats::default()) + .with(body) + .with(comp::Stats::new(name)) .with(comp::ActionState::default()) .with(comp::ForceUpdate) } @@ -161,8 +161,8 @@ impl Server { ) { let spawn_point = state.ecs().read_resource::().0; - state.write_component(entity, comp::Actor::Character { name, body }); - state.write_component(entity, comp::Stats::default()); + state.write_component(entity, body); + state.write_component(entity, comp::Stats::new(name)); state.write_component(entity, comp::Controller::default()); state.write_component(entity, comp::Pos(spawn_point)); state.write_component(entity, comp::Vel(Vec3::zero())); @@ -677,9 +677,7 @@ impl Server { self.state.write_component(entity, comp::ForceUpdate); client.force_state(ClientState::Dead); } else { - if let Err(err) = self.state.ecs_mut().delete_entity_synced(entity) { - warn!("Failed to delete client not found in kill list: {:?}", err); - } + let _ = self.state.ecs_mut().delete_entity_synced(entity); continue; } } @@ -696,14 +694,20 @@ impl Server { for entity in todo_respawn { if let Some(client) = self.clients.get_mut(&entity) { client.allow_state(ClientState::Character); - self.state.write_component(entity, comp::Stats::default()); + self.state + .ecs_mut() + .write_storage::() + .get_mut(entity) + .map(|stats| { + stats + .health + .set_to(stats.health.get_maximum(), comp::HealthSource::Revive) + }); self.state .ecs_mut() .write_storage::() .get_mut(entity) .map(|pos| pos.0.z += 100.0); - self.state.write_component(entity, comp::Vel(Vec3::zero())); - self.state.write_component(entity, comp::ForceUpdate); } } diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index e0d73fc2e1..32eb1fe321 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -314,7 +314,6 @@ impl Hud { // Nametags and healthbars if self.show.ingame { let ecs = client.state().ecs(); - let actor = ecs.read_storage::(); let pos = ecs.read_storage::(); let stats = ecs.read_storage::(); let player = ecs.read_storage::(); @@ -333,29 +332,25 @@ impl Hud { let mut health_back_id_walker = self.ids.health_bar_backs.walk(); // Render Name Tags - for (pos, name) in (&entities, &pos, &actor, &stats, player.maybe()) + for (pos, name) in (&entities, &pos, &stats, player.maybe()) .join() - .filter(|(entity, _, _, stats, _)| *entity != me && !stats.is_dead) + .filter(|(entity, _, stats, _)| *entity != me && !stats.is_dead) // Don't process nametags outside the vd (visibility further limited by ui backend) - .filter(|(_, pos, _, _, _)| { + .filter(|(_, pos, _, _)| { (pos.0 - player_pos) .map2(TerrainChunkSize::SIZE, |d, sz| d.abs() as f32 / sz as f32) .magnitude() < view_distance as f32 }) - .map(|(_, pos, actor, _, player)| match actor { - comp::Actor::Character { - name: char_name, .. - } => { - // Temporary - // If the player used the default character name display their name instead - let name = if char_name == "Character Name" { - player.map_or(char_name, |p| &p.alias) - } else { - char_name - }; - (pos.0, name) - } + .map(|(_, pos, stats, player)| { + // TODO: This is temporary + // If the player used the default character name display their name instead + let name = if stats.name == "Character Name" { + player.map_or(&stats.name, |p| &p.alias) + } else { + &stats.name + }; + (pos.0, name) }) { let id = name_id_walker.next( @@ -377,7 +372,7 @@ impl Hud { .filter(|(entity, _, stats)| { *entity != me && !stats.is_dead - && stats.hp.get_current() != stats.hp.get_maximum() + && stats.health.get_current() != stats.health.get_maximum() }) // Don't process health bars outside the vd (visibility further limited by ui backend) .filter(|(_, pos, _)| { @@ -405,7 +400,9 @@ impl Hud { // % HP Filling Rectangle::fill_with( [ - 120.0 * (stats.hp.get_current() as f64 / stats.hp.get_maximum() as f64), + 120.0 + * (stats.health.get_current() as f64 + / stats.health.get_maximum() as f64), 8.0, ], HP_COLOR, @@ -545,14 +542,14 @@ impl Hud { // Skillbar // Get player stats - let stats = client + if let Some(stats) = client .state() .ecs() .read_storage::() .get(client.entity()) - .map(|&s| s) - .unwrap_or_default(); - Skillbar::new(&self.imgs, &self.fonts, stats).set(self.ids.skillbar, ui_widgets); + { + Skillbar::new(&self.imgs, &self.fonts, stats).set(self.ids.skillbar, ui_widgets); + } // Chat box match Chat::new(&mut self.new_messages, &self.imgs, &self.fonts) diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index 91354370e6..add9658175 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -31,14 +31,14 @@ pub struct Skillbar<'a> { imgs: &'a Imgs, fonts: &'a Fonts, - stats: Stats, + stats: &'a Stats, #[conrod(common_builder)] common: widget::CommonBuilder, } impl<'a> Skillbar<'a> { - pub fn new(imgs: &'a Imgs, fonts: &'a Fonts, stats: Stats) -> Self { + pub fn new(imgs: &'a Imgs, fonts: &'a Fonts, stats: &'a Stats) -> Self { Self { imgs, fonts, @@ -78,7 +78,8 @@ impl<'a> Widget for Skillbar<'a> { let next_level_xp = (level as f64).powi(4) - start_level_xp; // TODO: We need a max xp value let xp_percentage = (self.stats.xp as f64 - start_level_xp) / next_level_xp; - let hp_percentage = self.stats.hp.get_current() as f64 / self.stats.hp.get_maximum() as f64; + let hp_percentage = + self.stats.health.get_current() as f64 / self.stats.health.get_maximum() as f64; let mana_percentage = 1.0; // TODO: Only show while aiming with a bow or when casting a spell. diff --git a/voxygen/src/scene/figure.rs b/voxygen/src/scene/figure.rs index 8b42334535..8bd8465597 100644 --- a/voxygen/src/scene/figure.rs +++ b/voxygen/src/scene/figure.rs @@ -551,12 +551,12 @@ impl FigureMgr { .get(client.entity()) .map_or(Vec3::zero(), |pos| pos.0); - for (entity, pos, vel, ori, actor, animation_info, stats) in ( + for (entity, pos, vel, ori, body, animation_info, stats) in ( &ecs.entities(), &ecs.read_storage::(), &ecs.read_storage::(), &ecs.read_storage::(), - &ecs.read_storage::(), + &ecs.read_storage::(), &ecs.read_storage::(), ecs.read_storage::().maybe(), ) @@ -569,18 +569,16 @@ impl FigureMgr { / view_distance as f32; // Keep from re-adding/removing entities on the border of the vd if vd_frac > 1.2 { - match actor { - comp::Actor::Character { body, .. } => match body { - Body::Humanoid(_) => { - self.character_states.remove(&entity); - } - Body::Quadruped(_) => { - self.quadruped_states.remove(&entity); - } - Body::QuadrupedMedium(_) => { - self.quadruped_medium_states.remove(&entity); - } - }, + match body { + Body::Humanoid(_) => { + self.character_states.remove(&entity); + } + Body::Quadruped(_) => { + self.quadruped_states.remove(&entity); + } + Body::QuadrupedMedium(_) => { + self.quadruped_medium_states.remove(&entity); + } } continue; } else if vd_frac > 1.0 { @@ -589,7 +587,7 @@ impl FigureMgr { // Change in health as color! let col = stats - .and_then(|stats| stats.hp.last_change) + .and_then(|stats| stats.health.last_change) .map(|(_, time, _)| { Rgba::broadcast(1.0) + Rgba::new(0.0, -1.0, -1.0, 0.0) @@ -597,170 +595,150 @@ impl FigureMgr { }) .unwrap_or(Rgba::broadcast(1.0)); - match actor { - comp::Actor::Character { body, .. } => { - let skeleton_attr = &self - .model_cache - .get_or_create_model(renderer, *body, tick) - .1; + let skeleton_attr = &self + .model_cache + .get_or_create_model(renderer, *body, tick) + .1; - match body { - Body::Humanoid(_) => { - let state = self.character_states.entry(entity).or_insert_with(|| { - FigureState::new(renderer, CharacterSkeleton::new()) - }); + match body { + Body::Humanoid(_) => { + let state = self + .character_states + .entry(entity) + .or_insert_with(|| FigureState::new(renderer, CharacterSkeleton::new())); - let target_skeleton = match animation_info.animation { - comp::Animation::Idle => { - anim::character::IdleAnimation::update_skeleton( - state.skeleton_mut(), - time, - animation_info.time, - skeleton_attr, - ) - } - comp::Animation::Run => { - anim::character::RunAnimation::update_skeleton( - state.skeleton_mut(), - (vel.0.magnitude(), time), - animation_info.time, - skeleton_attr, - ) - } - comp::Animation::Jump => { - anim::character::JumpAnimation::update_skeleton( - state.skeleton_mut(), - time, - animation_info.time, - skeleton_attr, - ) - } - comp::Animation::Attack => { - anim::character::AttackAnimation::update_skeleton( - state.skeleton_mut(), - time, - animation_info.time, - skeleton_attr, - ) - } - comp::Animation::Roll => { - anim::character::RollAnimation::update_skeleton( - state.skeleton_mut(), - time, - animation_info.time, - skeleton_attr, - ) - } - comp::Animation::Crun => { - anim::character::CrunAnimation::update_skeleton( - state.skeleton_mut(), - (vel.0.magnitude(), time), - animation_info.time, - skeleton_attr, - ) - } - comp::Animation::Cidle => { - anim::character::CidleAnimation::update_skeleton( - state.skeleton_mut(), - time, - animation_info.time, - skeleton_attr, - ) - } - comp::Animation::Gliding => { - anim::character::GlidingAnimation::update_skeleton( - state.skeleton_mut(), - (vel.0.magnitude(), time), - animation_info.time, - skeleton_attr, - ) - } - }; - - state.skeleton.interpolate(&target_skeleton, dt); - state.update(renderer, pos.0, ori.0, col, dt); + let target_skeleton = match animation_info.animation { + comp::Animation::Idle => anim::character::IdleAnimation::update_skeleton( + state.skeleton_mut(), + time, + animation_info.time, + skeleton_attr, + ), + comp::Animation::Run => anim::character::RunAnimation::update_skeleton( + state.skeleton_mut(), + (vel.0.magnitude(), time), + animation_info.time, + skeleton_attr, + ), + comp::Animation::Jump => anim::character::JumpAnimation::update_skeleton( + state.skeleton_mut(), + time, + animation_info.time, + skeleton_attr, + ), + comp::Animation::Attack => { + anim::character::AttackAnimation::update_skeleton( + state.skeleton_mut(), + time, + animation_info.time, + skeleton_attr, + ) } - Body::Quadruped(_) => { - let state = self.quadruped_states.entry(entity).or_insert_with(|| { - FigureState::new(renderer, QuadrupedSkeleton::new()) - }); - - let target_skeleton = match animation_info.animation { - comp::Animation::Run => { - anim::quadruped::RunAnimation::update_skeleton( - state.skeleton_mut(), - (vel.0.magnitude(), time), - animation_info.time, - skeleton_attr, - ) - } - comp::Animation::Idle => { - anim::quadruped::IdleAnimation::update_skeleton( - state.skeleton_mut(), - time, - animation_info.time, - skeleton_attr, - ) - } - comp::Animation::Jump => { - anim::quadruped::JumpAnimation::update_skeleton( - state.skeleton_mut(), - (vel.0.magnitude(), time), - animation_info.time, - skeleton_attr, - ) - } - - // TODO! - _ => state.skeleton_mut().clone(), - }; - - state.skeleton.interpolate(&target_skeleton, dt); - state.update(renderer, pos.0, ori.0, col, dt); + comp::Animation::Roll => anim::character::RollAnimation::update_skeleton( + state.skeleton_mut(), + time, + animation_info.time, + skeleton_attr, + ), + comp::Animation::Crun => anim::character::CrunAnimation::update_skeleton( + state.skeleton_mut(), + (vel.0.magnitude(), time), + animation_info.time, + skeleton_attr, + ), + comp::Animation::Cidle => anim::character::CidleAnimation::update_skeleton( + state.skeleton_mut(), + time, + animation_info.time, + skeleton_attr, + ), + comp::Animation::Gliding => { + anim::character::GlidingAnimation::update_skeleton( + state.skeleton_mut(), + (vel.0.magnitude(), time), + animation_info.time, + skeleton_attr, + ) } - Body::QuadrupedMedium(_) => { - let state = - self.quadruped_medium_states - .entry(entity) - .or_insert_with(|| { - FigureState::new(renderer, QuadrupedMediumSkeleton::new()) - }); + }; - let target_skeleton = match animation_info.animation { - comp::Animation::Run => { - anim::quadrupedmedium::RunAnimation::update_skeleton( - state.skeleton_mut(), - (vel.0.magnitude(), time), - animation_info.time, - skeleton_attr, - ) - } - comp::Animation::Idle => { - anim::quadrupedmedium::IdleAnimation::update_skeleton( - state.skeleton_mut(), - time, - animation_info.time, - skeleton_attr, - ) - } - comp::Animation::Jump => { - anim::quadrupedmedium::JumpAnimation::update_skeleton( - state.skeleton_mut(), - (vel.0.magnitude(), time), - animation_info.time, - skeleton_attr, - ) - } + state.skeleton.interpolate(&target_skeleton, dt); + state.update(renderer, pos.0, ori.0, col, dt); + } + Body::Quadruped(_) => { + let state = self + .quadruped_states + .entry(entity) + .or_insert_with(|| FigureState::new(renderer, QuadrupedSkeleton::new())); - // TODO! - _ => state.skeleton_mut().clone(), - }; + let target_skeleton = match animation_info.animation { + comp::Animation::Run => anim::quadruped::RunAnimation::update_skeleton( + state.skeleton_mut(), + (vel.0.magnitude(), time), + animation_info.time, + skeleton_attr, + ), + comp::Animation::Idle => anim::quadruped::IdleAnimation::update_skeleton( + state.skeleton_mut(), + time, + animation_info.time, + skeleton_attr, + ), + comp::Animation::Jump => anim::quadruped::JumpAnimation::update_skeleton( + state.skeleton_mut(), + (vel.0.magnitude(), time), + animation_info.time, + skeleton_attr, + ), - state.skeleton.interpolate(&target_skeleton, dt); - state.update(renderer, pos.0, ori.0, col, dt); + // TODO! + _ => state.skeleton_mut().clone(), + }; + + state.skeleton.interpolate(&target_skeleton, dt); + state.update(renderer, pos.0, ori.0, col, dt); + } + Body::QuadrupedMedium(_) => { + let state = self + .quadruped_medium_states + .entry(entity) + .or_insert_with(|| { + FigureState::new(renderer, QuadrupedMediumSkeleton::new()) + }); + + let target_skeleton = match animation_info.animation { + comp::Animation::Run => { + anim::quadrupedmedium::RunAnimation::update_skeleton( + state.skeleton_mut(), + (vel.0.magnitude(), time), + animation_info.time, + skeleton_attr, + ) } - } - } // TODO: Non-character actors + comp::Animation::Idle => { + anim::quadrupedmedium::IdleAnimation::update_skeleton( + state.skeleton_mut(), + time, + animation_info.time, + skeleton_attr, + ) + } + comp::Animation::Jump => { + anim::quadrupedmedium::JumpAnimation::update_skeleton( + state.skeleton_mut(), + (vel.0.magnitude(), time), + animation_info.time, + skeleton_attr, + ) + } + + // TODO! + _ => state.skeleton_mut().clone(), + }; + + state.skeleton.interpolate(&target_skeleton, dt); + state.update(renderer, pos.0, ori.0, col, dt); + } } } @@ -791,12 +769,12 @@ impl FigureMgr { .get(client.entity()) .map_or(Vec3::zero(), |pos| pos.0); - for (entity, _, _, _, actor, _, _) in ( + for (entity, _, _, _, body, _, _) in ( &ecs.entities(), &ecs.read_storage::(), &ecs.read_storage::(), &ecs.read_storage::(), - &ecs.read_storage::(), + &ecs.read_storage::(), &ecs.read_storage::(), ecs.read_storage::().maybe(), ) @@ -811,32 +789,28 @@ impl FigureMgr { // Don't render dead entities .filter(|(_, _, _, _, _, _, stats)| stats.map_or(true, |s| !s.is_dead)) { - match actor { - comp::Actor::Character { body, .. } => { - if let Some((locals, bone_consts)) = match body { - Body::Humanoid(_) => self - .character_states - .get(&entity) - .map(|state| (state.locals(), state.bone_consts())), - Body::Quadruped(_) => self - .quadruped_states - .get(&entity) - .map(|state| (state.locals(), state.bone_consts())), - Body::QuadrupedMedium(_) => self - .quadruped_medium_states - .get(&entity) - .map(|state| (state.locals(), state.bone_consts())), - } { - let model = &self - .model_cache - .get_or_create_model(renderer, *body, tick) - .0; + if let Some((locals, bone_consts)) = match body { + Body::Humanoid(_) => self + .character_states + .get(&entity) + .map(|state| (state.locals(), state.bone_consts())), + Body::Quadruped(_) => self + .quadruped_states + .get(&entity) + .map(|state| (state.locals(), state.bone_consts())), + Body::QuadrupedMedium(_) => self + .quadruped_medium_states + .get(&entity) + .map(|state| (state.locals(), state.bone_consts())), + } { + let model = &self + .model_cache + .get_or_create_model(renderer, *body, tick) + .0; - renderer.render_figure(model, globals, locals, bone_consts); - } else { - warn!("Body has no saved figure"); - } - } + renderer.render_figure(model, globals, locals, bone_consts); + } else { + warn!("Body has no saved figure"); } } }