From f5351589d6a439a97844e307c5716c19fc67326e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Korg=C3=B3l?= Date: Fri, 26 Jul 2019 16:23:33 +0200 Subject: [PATCH 1/3] Add Level and Exp component --- common/src/comp/mod.rs | 2 +- common/src/comp/stats.rs | 64 +++++++++++++++++++++++++++++++++++-- voxygen/src/hud/skillbar.rs | 17 ++++------ 3 files changed, 70 insertions(+), 13 deletions(-) diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index 25321f555d..91d0b380a7 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -22,5 +22,5 @@ pub use inputs::{ pub use inventory::{item, Inventory}; pub use phys::{ForceUpdate, Ori, Pos, Vel}; pub use player::Player; -pub use stats::{Dying, HealthSource, Stats}; +pub use stats::{Dying, Exp, HealthSource, Level, Stats}; pub use visual::LightEmitter; diff --git a/common/src/comp/stats.rs b/common/src/comp/stats.rs index 96230ca453..142396fe65 100644 --- a/common/src/comp/stats.rs +++ b/common/src/comp/stats.rs @@ -17,6 +17,17 @@ pub struct Health { pub last_change: Option<(i32, f64, HealthSource)>, } +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub struct Exp { + current: f64, + maximum: f64, +} + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub struct Level { + amount: u32, +} + impl Health { pub fn get_current(&self) -> u32 { self.current @@ -35,11 +46,56 @@ impl Health { } } +impl Exp { + pub fn get_current(&self) -> f64 { + self.current + } + + pub fn get_maximum(&self) -> f64 { + self.maximum + } + + pub fn set_current(&mut self, current: f64) { + if self.current < self.maximum { + self.current = current; + } + } + + pub fn set_maximum(&mut self, maximum: f64) { + self.maximum = maximum; + } + + pub fn change_current_by(&mut self, current: f64) { + if self.current < self.maximum { + self.current + current; + } + } + + pub fn change_maximum_by(&mut self, maximum: f64) { + self.maximum + maximum; + } +} + +impl Level { + pub fn set_level(&mut self, level: u32) { + self.amount = level; + } + + pub fn get_level(&self) -> u32 { + self.amount + } + + pub fn change_by(&mut self, level: u32) { + self.amount + level; + } +} + #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Stats { pub name: String, pub health: Health, - pub xp: u32, + pub level: Level, + pub exp: Exp, pub is_dead: bool, } @@ -64,7 +120,11 @@ impl Stats { maximum: 100, last_change: None, }, - xp: 0, + level: Level { amount: 1 }, + exp: Exp { + current: 0.0, + maximum: 50.0, + }, is_dead: false, } } diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index a385fd71b7..e38617b075 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -71,12 +71,12 @@ impl<'a> Widget for Skillbar<'a> { fn update(self, args: widget::UpdateArgs) -> Self::Event { let widget::UpdateArgs { state, ui, .. } = args; - // TODO: remove this - let level = (self.stats.xp as f64).log(4.0).trunc() as u32 + 1; - let start_level_xp = ((level - 1) as f64).powi(4); - let next_level_xp = (level as f64).powi(4) - start_level_xp; + let level = (self.stats.level.get_level()).to_string(); + let next_level = self.stats.level.get_level() + 1; // TODO: We need a max xp value - let xp_percentage = (self.stats.xp as f64 - start_level_xp) / next_level_xp; + let xp_percentage = self.stats.exp.get_current(); + let max_xp = self.stats.exp.get_maximum(); + let hp_percentage = self.stats.health.get_current() as f64 / self.stats.health.get_maximum() as f64; let mana_percentage = 1.0; @@ -167,16 +167,13 @@ impl<'a> Widget for Skillbar<'a> { // Level Display - // TODO: don't construct a new string here - // TODO: Insert actual Level here. - Text::new(&level.to_string()) + Text::new(&level) .left_from(state.ids.xp_bar, -15.0) .font_size(10) .color(TEXT_COLOR) .set(state.ids.level_text, ui); - // TODO: Insert next Level here. - Text::new(&(level + 1).to_string()) + Text::new(&next_level.to_string()) .right_from(state.ids.xp_bar, -15.0) .font_size(10) .color(TEXT_COLOR) From 69dcd3ddef2518fbde06b4bf6c0349d21a0628a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Korg=C3=B3l?= Date: Fri, 26 Jul 2019 20:40:29 +0200 Subject: [PATCH 2/3] Get EXP for killing NPCs and Players, properly show EXP bar --- Cargo.lock | 1 + common/src/comp/stats.rs | 26 ++++++++++++-------------- server/src/lib.rs | 26 +++++++++++++++++++++++++- voxygen/src/hud/skillbar.rs | 11 +++++------ 4 files changed, 43 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d538c5eb2b..38426e2e79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2769,6 +2769,7 @@ dependencies = [ name = "veloren-server" version = "0.2.0" dependencies = [ + "chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/common/src/comp/stats.rs b/common/src/comp/stats.rs index 142396fe65..89bdcf1298 100644 --- a/common/src/comp/stats.rs +++ b/common/src/comp/stats.rs @@ -56,37 +56,35 @@ impl Exp { } pub fn set_current(&mut self, current: f64) { - if self.current < self.maximum { - self.current = current; - } + self.current = current; } - pub fn set_maximum(&mut self, maximum: f64) { - self.maximum = maximum; - } + // TODO: Uncomment when needed + // pub fn set_maximum(&mut self, maximum: f64) { + // self.maximum = maximum; + // } pub fn change_current_by(&mut self, current: f64) { - if self.current < self.maximum { - self.current + current; - } + self.current = self.current + current; } pub fn change_maximum_by(&mut self, maximum: f64) { - self.maximum + maximum; + self.maximum = self.maximum + maximum; } } impl Level { - pub fn set_level(&mut self, level: u32) { - self.amount = level; - } + // TODO: Uncomment when needed + // pub fn set_level(&mut self, level: u32) { + // self.amount = level; + // } pub fn get_level(&self) -> u32 { self.amount } pub fn change_by(&mut self, level: u32) { - self.amount + level; + self.amount = self.amount + level; } } diff --git a/server/src/lib.rs b/server/src/lib.rs index 79c6736f82..8cb4763bc4 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -710,7 +710,7 @@ impl Server { self.clients .notify_registered(ServerMsg::EcsSync(self.state.ecs_mut().next_sync_package())); - // Sync deaths. + // Handle deaths. let ecs = &self.state.ecs(); let clients = &mut self.clients; let todo_kill = (&ecs.entities(), &ecs.read_storage::()) @@ -737,6 +737,30 @@ impl Server { clients.notify_registered(ServerMsg::chat(msg)); } + // Give EXP to the client + if let Some(_enemy) = ecs.read_storage::().get(entity) { + if let comp::HealthSource::Attack { by } = dying.cause { + ecs.entity_from_uid(by.into()).and_then(|attacker| { + let mut stats = ecs.write_storage::(); + let attacker_stats = stats.get_mut(attacker).unwrap(); + + // TODO: Discuss whether we should give EXP by Player Killing or not. + if attacker_stats.exp.get_current() >= attacker_stats.exp.get_maximum() + { + attacker_stats.exp.change_maximum_by(25.0); + attacker_stats.exp.set_current(0.0); + attacker_stats.level.change_by(1); + } else { + // TODO: Don't make this a single value and make it depend on + // slayed entity's level + attacker_stats.exp.change_current_by(1.0); + }; + + ecs.read_storage::().get(attacker).cloned() + }); + } + } + entity }) .collect::>(); diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index e38617b075..dc3018f829 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -72,10 +72,9 @@ impl<'a> Widget for Skillbar<'a> { let widget::UpdateArgs { state, ui, .. } = args; let level = (self.stats.level.get_level()).to_string(); - let next_level = self.stats.level.get_level() + 1; - // TODO: We need a max xp value - let xp_percentage = self.stats.exp.get_current(); - let max_xp = self.stats.exp.get_maximum(); + let next_level = (self.stats.level.get_level() + 1).to_string(); + + let exp_percentage = self.stats.exp.get_current() / self.stats.exp.get_maximum(); let hp_percentage = self.stats.health.get_current() as f64 / self.stats.health.get_maximum() as f64; @@ -94,7 +93,7 @@ impl<'a> Widget for Skillbar<'a> { .mid_bottom_of(ui.window) .set(state.ids.xp_bar, ui); - Rectangle::fill_with([406.0 * (xp_percentage), 5.0], XP_COLOR) // "W=406*[Exp. %]" + Rectangle::fill_with([406.0 * (exp_percentage), 5.0], XP_COLOR) // "W=406*[Exp. %]" .top_left_with_margins_on(state.ids.xp_bar, 5.0, 21.0) .set(state.ids.xp_bar_progress, ui); @@ -173,7 +172,7 @@ impl<'a> Widget for Skillbar<'a> { .color(TEXT_COLOR) .set(state.ids.level_text, ui); - Text::new(&next_level.to_string()) + Text::new(&next_level) .right_from(state.ids.xp_bar, -15.0) .font_size(10) .color(TEXT_COLOR) From 948dc2ee7e10ac77a55513f9ddd9a98200da5709 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Korg=C3=B3l?= Date: Sat, 27 Jul 2019 15:04:34 +0200 Subject: [PATCH 3/3] Show level and xp on character menu --- voxygen/src/hud/character_window.rs | 21 ++++++++++++++------- voxygen/src/hud/mod.rs | 5 ++++- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/voxygen/src/hud/character_window.rs b/voxygen/src/hud/character_window.rs index 243f3e23ef..9ce1bb2afd 100644 --- a/voxygen/src/hud/character_window.rs +++ b/voxygen/src/hud/character_window.rs @@ -1,4 +1,5 @@ use super::{img_ids::Imgs, Fonts, TEXT_COLOR, XP_COLOR}; +use common::comp::Stats; use conrod_core::{ color, widget::{self, Button, Image, Rectangle, Text}, @@ -69,16 +70,18 @@ widget_ids! { pub struct CharacterWindow<'a> { imgs: &'a Imgs, fonts: &'a Fonts, + stats: &'a Stats, #[conrod(common_builder)] common: widget::CommonBuilder, } impl<'a> CharacterWindow<'a> { - pub fn new(imgs: &'a Imgs, fonts: &'a Fonts) -> Self { + pub fn new(imgs: &'a Imgs, fonts: &'a Fonts, stats: &'a Stats) -> Self { Self { imgs, fonts, + stats, common: widget::CommonBuilder::default(), } } @@ -104,8 +107,13 @@ impl<'a> Widget for CharacterWindow<'a> { fn update(self, args: widget::UpdateArgs) -> Self::Event { let widget::UpdateArgs { id, state, ui, .. } = args; - // TODO: Read from parameter/character struct. - let xp_percentage = 0.4; + let xp_percentage = self.stats.exp.get_current() / self.stats.exp.get_maximum(); + let xp_treshold = format!( + "{}/{}", + self.stats.exp.get_current(), + self.stats.exp.get_maximum() + ); + let level = (self.stats.level.get_level()).to_string(); // Frame Image::new(self.imgs.window_3) @@ -330,8 +338,8 @@ impl<'a> Widget for CharacterWindow<'a> { //.label_font_size(14) //.set(state.charwindow_tab1, ui); - // TODO: Use an actual character level. - Text::new("1") + // Level + Text::new(&level) .mid_top_with_margin_on(state.charwindow_rectangle, 10.0) .font_id(self.fonts.opensans) .font_size(30) @@ -355,8 +363,7 @@ impl<'a> Widget for CharacterWindow<'a> { .set(state.charwindow_tab1_expbar, ui); // Exp-Text - // TODO: Shows current Exp over the next threshold Exp. - Text::new("120/170") + Text::new(&xp_treshold) .mid_top_with_margin_on(state.charwindow_tab1_expbar, 10.0) .font_id(self.fonts.opensans) .font_size(15) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index eb03cf8aae..3318a45762 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -690,7 +690,10 @@ impl Hud { // Character Window if let Windows::CharacterAnd(small) = self.show.open_windows { - match CharacterWindow::new(&self.imgs, &self.fonts) + let ecs = client.state().ecs(); + let stats = ecs.read_storage::(); + let player_stats = stats.get(client.entity()).unwrap(); + match CharacterWindow::new(&self.imgs, &self.fonts, &player_stats) .set(self.ids.character_window, ui_widgets) { Some(character_window::Event::Close) => {