diff --git a/common/src/comp/energy.rs b/common/src/comp/energy.rs new file mode 100644 index 0000000000..88164813e0 --- /dev/null +++ b/common/src/comp/energy.rs @@ -0,0 +1,54 @@ +use specs::{Component, FlaggedStorage}; +use specs_idvs::IDVStorage; + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub struct Energy { + current: u32, + maximum: u32, + pub last_change: Option<(i32, f64, EnergySource)>, +} + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub enum EnergySource { + CastSpell, + LevelUp, + Unknown, +} + +impl Energy { + pub fn new(amount: u32) -> Energy { + Energy { + current: amount, + maximum: amount, + last_change: None, + } + } + + pub fn current(&self) -> u32 { + self.current + } + + pub fn maximum(&self) -> u32 { + self.maximum + } + + pub fn set_to(&mut self, amount: u32, cause: EnergySource) { + 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: EnergySource) { + self.current = ((self.current as i32 + amount).max(0) as u32).min(self.maximum); + self.last_change = Some((amount, 0.0, cause)); + } + + pub fn set_maximum(&mut self, amount: u32) { + self.maximum = amount; + self.current = self.current.min(self.maximum); + } +} + +impl Component for Energy { + type Storage = FlaggedStorage>; +} diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index 42f8e6e161..5f2a631c89 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -3,6 +3,7 @@ mod agent; mod body; mod character_state; mod controller; +mod energy; mod inputs; mod inventory; mod last; @@ -25,6 +26,7 @@ pub use controller::{ ControlEvent, Controller, ControllerInputs, Input, InputState, InventoryManip, MountState, Mounting, }; +pub use energy::Energy; pub use inputs::CanBuild; pub use inventory::{item, Inventory, InventoryUpdate, Item, ItemKind}; pub use last::Last; diff --git a/common/src/comp/stats.rs b/common/src/comp/stats.rs index e4eceeaaa1..532f6cb8be 100644 --- a/common/src/comp/stats.rs +++ b/common/src/comp/stats.rs @@ -19,12 +19,6 @@ pub enum HealthSource { Item, Unknown, } -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] -pub enum EnergySource { - CastSpell, - LevelUp, - Unknown, -} #[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub struct Health { @@ -33,13 +27,6 @@ pub struct Health { pub last_change: (f64, HealthChange), } -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] -pub struct Energy { - current: u32, - maximum: u32, - pub last_change: Option<(i32, f64, EnergySource)>, -} - #[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub struct Exp { current: u32, @@ -90,32 +77,6 @@ impl Health { } } -impl Energy { - pub fn current(&self) -> u32 { - self.current - } - - pub fn maximum(&self) -> u32 { - self.maximum - } - - pub fn set_to(&mut self, amount: u32, cause: EnergySource) { - 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: EnergySource) { - self.current = ((self.current as i32 + amount).max(0) as u32).min(self.maximum); - self.last_change = Some((amount, 0.0, cause)); - } - - pub fn set_maximum(&mut self, amount: u32) { - self.maximum = amount; - self.current = self.current.min(self.maximum); - } -} - impl Exp { pub fn current(&self) -> u32 { self.current @@ -161,7 +122,6 @@ impl Level { pub struct Stats { pub name: String, pub health: Health, - pub energy: Energy, pub level: Level, pub exp: Exp, pub equipment: Equipment, @@ -204,11 +164,6 @@ impl Stats { current: 0, maximum: 50, }, - energy: Energy { - current: 200, - maximum: 200, - last_change: None, - }, equipment: Equipment { main: main, alt: None, @@ -229,12 +184,6 @@ impl Stats { self.health.current = amount; self } - - pub fn with_max_energy(mut self, amount: u32) -> Self { - self.energy.maximum = amount; - self.energy.current = amount; - self - } } impl Component for Stats { diff --git a/common/src/msg/ecs_packet.rs b/common/src/msg/ecs_packet.rs index e714416ff9..6e1a2a65a7 100644 --- a/common/src/msg/ecs_packet.rs +++ b/common/src/msg/ecs_packet.rs @@ -12,6 +12,7 @@ sum_type! { Player(comp::Player), CanBuild(comp::CanBuild), Stats(comp::Stats), + Energy(comp::Energy), LightEmitter(comp::LightEmitter), Item(comp::Item), Scale(comp::Scale), @@ -31,6 +32,7 @@ sum_type! { Player(PhantomData), CanBuild(PhantomData), Stats(PhantomData), + Energy(PhantomData), LightEmitter(PhantomData), Item(PhantomData), Scale(PhantomData), @@ -49,6 +51,7 @@ impl sync::CompPacket for EcsCompPacket { EcsCompPacket::Player(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::CanBuild(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Stats(comp) => sync::handle_insert(comp, entity, world), + EcsCompPacket::Energy(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::LightEmitter(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Item(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Scale(comp) => sync::handle_insert(comp, entity, world), @@ -65,6 +68,7 @@ impl sync::CompPacket for EcsCompPacket { EcsCompPacket::Player(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::CanBuild(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Stats(comp) => sync::handle_modify(comp, entity, world), + EcsCompPacket::Energy(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::LightEmitter(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Item(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Scale(comp) => sync::handle_modify(comp, entity, world), @@ -81,6 +85,7 @@ impl sync::CompPacket for EcsCompPacket { EcsCompPhantom::Player(_) => sync::handle_remove::(entity, world), EcsCompPhantom::CanBuild(_) => sync::handle_remove::(entity, world), EcsCompPhantom::Stats(_) => sync::handle_remove::(entity, world), + EcsCompPhantom::Energy(_) => sync::handle_remove::(entity, world), EcsCompPhantom::LightEmitter(_) => { sync::handle_remove::(entity, world) } diff --git a/common/src/state.rs b/common/src/state.rs index 6966d3b1cc..a111a5f1fa 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -110,6 +110,7 @@ impl State { ecs.register::(); ecs.register::(); ecs.register::(); + ecs.register::(); ecs.register::(); ecs.register::(); ecs.register::(); diff --git a/server/src/lib.rs b/server/src/lib.rs index 6a1575c772..6bf0557244 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -258,6 +258,7 @@ impl Server { state.write_component(entity, body); state.write_component(entity, comp::Stats::new(name, main)); + state.write_component(entity, comp::Energy::new(200)); state.write_component(entity, comp::Controller::default()); state.write_component(entity, comp::Pos(spawn_point)); state.write_component(entity, comp::Vel(Vec3::zero())); @@ -1184,6 +1185,7 @@ impl StateExt for State { .with(comp::Controller::default()) .with(body) .with(stats) + .with(comp::Energy::new(100)) .with(comp::Gravity(1.0)) .with(comp::CharacterState::default()) } diff --git a/server/src/sys/sentinel.rs b/server/src/sys/sentinel.rs index 8fc04ea445..320a07a4dd 100644 --- a/server/src/sys/sentinel.rs +++ b/server/src/sys/sentinel.rs @@ -1,8 +1,8 @@ use super::SysTimer; use common::{ comp::{ - Body, CanBuild, Gravity, Item, LightEmitter, Mass, MountState, Mounting, Player, Scale, - Stats, Sticky, + Body, CanBuild, Energy, Gravity, Item, LightEmitter, Mass, MountState, Mounting, Player, + Scale, Stats, Sticky, }, msg::EcsCompPacket, sync::{EntityPackage, SyncPackage, Uid, UpdateTracker, WorldSyncExt}, @@ -40,6 +40,7 @@ pub struct TrackedComps<'a> { pub body: ReadStorage<'a, Body>, pub player: ReadStorage<'a, Player>, pub stats: ReadStorage<'a, Stats>, + pub energy: ReadStorage<'a, Energy>, pub can_build: ReadStorage<'a, CanBuild>, pub light_emitter: ReadStorage<'a, LightEmitter>, pub item: ReadStorage<'a, Item>, @@ -68,6 +69,10 @@ impl<'a> TrackedComps<'a> { .get(entity) .cloned() .map(|c| comps.push(c.into())); + self.energy + .get(entity) + .cloned() + .map(|c| comps.push(c.into())); self.can_build .get(entity) .cloned() @@ -108,6 +113,7 @@ pub struct ReadTrackers<'a> { pub body: ReadExpect<'a, UpdateTracker>, pub player: ReadExpect<'a, UpdateTracker>, pub stats: ReadExpect<'a, UpdateTracker>, + pub energy: ReadExpect<'a, UpdateTracker>, pub can_build: ReadExpect<'a, UpdateTracker>, pub light_emitter: ReadExpect<'a, UpdateTracker>, pub item: ReadExpect<'a, UpdateTracker>, @@ -129,6 +135,7 @@ impl<'a> ReadTrackers<'a> { .with_component(&comps.uid, &*self.body, &comps.body, filter) .with_component(&comps.uid, &*self.player, &comps.player, filter) .with_component(&comps.uid, &*self.stats, &comps.stats, filter) + .with_component(&comps.uid, &*self.energy, &comps.energy, filter) .with_component(&comps.uid, &*self.can_build, &comps.can_build, filter) .with_component( &comps.uid, @@ -152,6 +159,7 @@ pub struct WriteTrackers<'a> { body: WriteExpect<'a, UpdateTracker>, player: WriteExpect<'a, UpdateTracker>, stats: WriteExpect<'a, UpdateTracker>, + energy: WriteExpect<'a, UpdateTracker>, can_build: WriteExpect<'a, UpdateTracker>, light_emitter: WriteExpect<'a, UpdateTracker>, item: WriteExpect<'a, UpdateTracker>, @@ -169,6 +177,7 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) { trackers.body.record_changes(&comps.body); trackers.player.record_changes(&comps.player); trackers.stats.record_changes(&comps.stats); + trackers.energy.record_changes(&comps.energy); trackers.can_build.record_changes(&comps.can_build); trackers.light_emitter.record_changes(&comps.light_emitter); trackers.item.record_changes(&comps.item); @@ -185,6 +194,7 @@ pub fn register_trackers(world: &mut World) { world.register_tracker::(); world.register_tracker::(); world.register_tracker::(); + world.register_tracker::(); world.register_tracker::(); world.register_tracker::(); world.register_tracker::(); diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index e316298721..a318424935 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -531,6 +531,7 @@ impl Hud { let ecs = client.state().ecs(); let pos = ecs.read_storage::(); let stats = ecs.read_storage::(); + let energy = ecs.read_storage::(); let hp_floater_lists = ecs.read_storage::(); let interpolated = ecs.read_storage::(); let players = ecs.read_storage::(); @@ -615,22 +616,24 @@ impl Hud { let mut health_front_id_walker = self.ids.health_bar_fronts.walk(); let mut sct_bg_id_walker = self.ids.sct_bgs.walk(); let mut sct_id_walker = self.ids.scts.walk(); + // Render Health Bars - for (pos, stats, scale, hp_floater_list) in ( + for (pos, stats, energy, scale, hp_floater_list) in ( &entities, &pos, interpolated.maybe(), &stats, + &energy, scales.maybe(), hp_floater_lists.maybe(), // Potentially move this to its own loop ) .join() - .filter(|(entity, _, _, stats, _, _)| { + .filter(|(entity, _, _, stats, _, _, _)| { *entity != me && !stats.is_dead //&& stats.health.current() != stats.health.maximum() }) // Don't process health bars outside the vd (visibility further limited by ui backend) - .filter(|(_, pos, _, _, _, _)| { + .filter(|(_, pos, _, _, _, _, _)| { Vec2::from(pos.0 - player_pos) .map2(TerrainChunk::RECT_SIZE, |d: f32, sz| { d.abs() as f32 / sz as f32 @@ -638,10 +641,11 @@ impl Hud { .magnitude() < view_distance as f32 }) - .map(|(_, pos, interpolated, stats, scale, f)| { + .map(|(_, pos, interpolated, stats, energy, scale, f)| { ( interpolated.map_or(pos.0, |i| i.pos), stats, + energy, scale.map_or(1.0, |s| s.0), f, ) @@ -665,8 +669,7 @@ impl Hud { ); let hp_percentage = stats.health.current() as f64 / stats.health.maximum() as f64 * 100.0; - let energy_percentage = - stats.energy.current() as f64 / stats.energy.maximum() as f64 * 100.0; + let energy_percentage = energy.current() as f64 / energy.maximum() as f64 * 100.0; let hp_ani = (self.pulse * 4.0/*speed factor*/).cos() * 0.5 + 1.0; //Animation timer let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani); @@ -694,7 +697,7 @@ impl Hud { // % Mana Filling Rectangle::fill_with( [ - 73.0 * (stats.energy.current() as f64 / stats.energy.maximum() as f64), + 73.0 * (energy.current() as f64 / energy.maximum() as f64), 1.5, ], MANA_COLOR, @@ -1643,14 +1646,20 @@ impl Hud { // Skillbar // Get player stats - if let Some(stats) = client - .state() - .ecs() - .read_storage::() - .get(client.entity()) - { - Skillbar::new(global_state, &self.imgs, &self.fonts, &stats, self.pulse) - .set(self.ids.skillbar, ui_widgets); + let ecs = client.state().ecs(); + let stats = ecs.read_storage::(); + let energy = ecs.read_storage::(); + let entity = client.entity(); + if let (Some(stats), Some(energy)) = (stats.get(entity), energy.get(entity)) { + Skillbar::new( + global_state, + &self.imgs, + &self.fonts, + &stats, + &energy, + self.pulse, + ) + .set(self.ids.skillbar, ui_widgets); } // Chat box diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index 6b72c9ccee..cd935021c1 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -3,7 +3,7 @@ use super::{ /*FOCUS_COLOR, RAGE_COLOR,*/ HP_COLOR, LOW_HP_COLOR, MANA_COLOR, TEXT_COLOR, XP_COLOR, }; use crate::GlobalState; -use common::comp::{item::Debug, item::Tool, ItemKind, Stats}; +use common::comp::{item::Debug, item::Tool, Energy, ItemKind, Stats}; use conrod_core::{ color, widget::{self, Button, Image, Rectangle, Text}, @@ -97,6 +97,7 @@ pub struct Skillbar<'a> { imgs: &'a Imgs, fonts: &'a Fonts, stats: &'a Stats, + energy: &'a Energy, pulse: f32, #[conrod(common_builder)] common: widget::CommonBuilder, @@ -109,12 +110,14 @@ impl<'a> Skillbar<'a> { imgs: &'a Imgs, fonts: &'a Fonts, stats: &'a Stats, + energy: &'a Energy, pulse: f32, ) -> Self { Self { imgs, fonts: fonts, stats, + energy, global_state, current_resource: ResourceType::Mana, common: widget::CommonBuilder::default(), @@ -162,8 +165,7 @@ impl<'a> Widget for Skillbar<'a> { let hp_percentage = self.stats.health.current() as f64 / self.stats.health.maximum() as f64 * 100.0; - let energy_percentage = - self.stats.energy.current() as f64 / self.stats.energy.maximum() as f64 * 100.0; + let energy_percentage = self.energy.current() as f64 / self.energy.maximum() as f64 * 100.0; let scale = 2.0; @@ -839,8 +841,8 @@ impl<'a> Widget for Skillbar<'a> { .set(state.ids.health_text, ui); let energy_text = format!( "{}/{}", - self.stats.energy.current() as u32, - self.stats.energy.maximum() as u32 + self.energy.current() as u32, + self.energy.maximum() as u32 ); Text::new(&energy_text) .mid_top_with_margin_on(state.ids.energybar_bg, 6.0 * scale)