fixing #405 - Energy as its own component

This commit is contained in:
Gilbert Röhrbein 2020-01-12 17:43:25 +01:00
parent 9c65c43713
commit 28060e7b6e
9 changed files with 107 additions and 73 deletions

54
common/src/comp/energy.rs Normal file
View File

@ -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<Self, IDVStorage<Self>>;
}

View File

@ -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;

View File

@ -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 {

View File

@ -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<comp::Player>),
CanBuild(PhantomData<comp::CanBuild>),
Stats(PhantomData<comp::Stats>),
Energy(PhantomData<comp::Energy>),
LightEmitter(PhantomData<comp::LightEmitter>),
Item(PhantomData<comp::Item>),
Scale(PhantomData<comp::Scale>),
@ -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::<comp::Player>(entity, world),
EcsCompPhantom::CanBuild(_) => sync::handle_remove::<comp::CanBuild>(entity, world),
EcsCompPhantom::Stats(_) => sync::handle_remove::<comp::Stats>(entity, world),
EcsCompPhantom::Energy(_) => sync::handle_remove::<comp::Energy>(entity, world),
EcsCompPhantom::LightEmitter(_) => {
sync::handle_remove::<comp::LightEmitter>(entity, world)
}

View File

@ -110,6 +110,7 @@ impl State {
ecs.register::<comp::Body>();
ecs.register::<comp::Player>();
ecs.register::<comp::Stats>();
ecs.register::<comp::Energy>();
ecs.register::<comp::CanBuild>();
ecs.register::<comp::LightEmitter>();
ecs.register::<comp::Item>();

View File

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

View File

@ -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<Body>>,
pub player: ReadExpect<'a, UpdateTracker<Player>>,
pub stats: ReadExpect<'a, UpdateTracker<Stats>>,
pub energy: ReadExpect<'a, UpdateTracker<Energy>>,
pub can_build: ReadExpect<'a, UpdateTracker<CanBuild>>,
pub light_emitter: ReadExpect<'a, UpdateTracker<LightEmitter>>,
pub item: ReadExpect<'a, UpdateTracker<Item>>,
@ -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<Body>>,
player: WriteExpect<'a, UpdateTracker<Player>>,
stats: WriteExpect<'a, UpdateTracker<Stats>>,
energy: WriteExpect<'a, UpdateTracker<Energy>>,
can_build: WriteExpect<'a, UpdateTracker<CanBuild>>,
light_emitter: WriteExpect<'a, UpdateTracker<LightEmitter>>,
item: WriteExpect<'a, UpdateTracker<Item>>,
@ -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::<Body>();
world.register_tracker::<Player>();
world.register_tracker::<Stats>();
world.register_tracker::<Energy>();
world.register_tracker::<CanBuild>();
world.register_tracker::<LightEmitter>();
world.register_tracker::<Item>();

View File

@ -531,6 +531,7 @@ impl Hud {
let ecs = client.state().ecs();
let pos = ecs.read_storage::<comp::Pos>();
let stats = ecs.read_storage::<comp::Stats>();
let energy = ecs.read_storage::<comp::Energy>();
let hp_floater_lists = ecs.read_storage::<vcomp::HpFloaterList>();
let interpolated = ecs.read_storage::<vcomp::Interpolated>();
let players = ecs.read_storage::<comp::Player>();
@ -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::<comp::Stats>()
.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::<comp::Stats>();
let energy = ecs.read_storage::<comp::Energy>();
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

View File

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