Exp floaters.

You load in with correct energy and health values now.
This commit is contained in:
Sam 2021-01-04 12:16:42 -05:00
parent 30df603115
commit b6d2d48ead
8 changed files with 113 additions and 60 deletions

View File

@ -1,3 +1,4 @@
use crate::comp::Body;
use serde::{Deserialize, Serialize};
use specs::{Component, DerefFlaggedStorage};
use specs_idvs::IdvStorage;
@ -29,10 +30,19 @@ pub enum StatChangeError {
}
impl Energy {
pub fn new(amount: u32) -> Energy {
pub fn new(body: Body, level: u16) -> Energy {
let mut energy = Energy::empty();
energy.update_max_energy(Some(body), level);
energy.set_to(energy.maximum(), EnergySource::Revive);
energy
}
pub fn empty() -> Self {
Energy {
current: amount,
maximum: amount,
current: 0,
maximum: 0,
regen_rate: 0.0,
last_change: None,
}
@ -75,6 +85,12 @@ impl Energy {
self.maximum = amount;
self.current = self.current.min(self.maximum);
}
pub fn update_max_energy(&mut self, body: Option<Body>, level: u16) {
if let Some(body) = body {
self.set_maximum(body.base_energy() + 50 * level as u32);
}
}
}
pub struct EnergyChange {

View File

@ -39,7 +39,7 @@ pub struct Health {
}
impl Health {
pub fn new(body: Body, level: u32) -> Self {
pub fn new(body: Body, level: u16) -> Self {
let mut health = Health::empty();
health.update_max_hp(Some(body), level);
@ -103,10 +103,10 @@ impl Health {
}
// TODO: Delete this once stat points will be a thing
pub fn update_max_hp(&mut self, body: Option<Body>, level: u32) {
pub fn update_max_hp(&mut self, body: Option<Body>, level: u16) {
if let Some(body) = body {
self.set_base_max(body.base_health() + body.base_health_increase() * level);
self.set_maximum(body.base_health() + body.base_health_increase() * level);
self.set_base_max(body.base_health() + body.base_health_increase() * level as u32);
self.set_maximum(body.base_health() + body.base_health_increase() * level as u32);
}
}

View File

@ -113,7 +113,7 @@ impl<'a> System<'a> for Sys {
.copied()
.flatten()
.unwrap_or(0);
health.update_max_hp(Some(stat.body_type), health_level.into());
health.update_max_hp(Some(stat.body_type), health_level);
let mut stat = stats.get_mut_unchecked();
stat.skill_set.modify_health = false;
}
@ -126,9 +126,8 @@ impl<'a> System<'a> for Sys {
.get(&Skill::General(GeneralSkill::EnergyIncrease))
.copied()
.flatten()
.unwrap_or(0) as u32;
let energy_max = stat.body_type.base_energy() + 50 * energy_level;
energy.set_maximum(energy_max);
.unwrap_or(0);
energy.update_max_energy(Some(stat.body_type), energy_level);
let mut stat = stats.get_mut_unchecked();
stat.skill_set.modify_energy = false;
}

View File

@ -251,14 +251,18 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
}
}
let num_pools = xp_pools.len() as f32;
let exp = (exp / num_pools).ceil() as i32;
for pool in xp_pools.drain() {
stats.skill_set.change_experience(pool, exp);
stats
.skill_set
.change_experience(pool, (exp / num_pools).ceil() as i32);
}
state
.ecs()
.write_resource::<Vec<Outcome>>()
.push(Outcome::ExpChange { uid: *uid, exp });
.push(Outcome::ExpChange {
uid: *uid,
exp: exp as i32,
});
}
});
}
@ -294,16 +298,17 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
}
}
let num_pools = xp_pools.len() as f32;
let exp = (exp_reward / num_pools).ceil() as i32;
for pool in xp_pools.drain() {
attacker_stats.skill_set.change_experience(pool, exp);
attacker_stats
.skill_set
.change_experience(pool, (exp_reward / num_pools).ceil() as i32);
}
state
.ecs()
.write_resource::<Vec<Outcome>>()
.push(Outcome::ExpChange {
uid: *attacker_uid,
exp,
exp: exp_reward as i32,
});
}
})();

View File

@ -4,8 +4,11 @@ use crate::{
};
use common::{
character::CharacterId,
comp,
comp::Inventory,
comp::{
self,
skills::{GeneralSkill, Skill},
Inventory,
},
effect::Effect,
uid::{Uid, UidAllocator},
util::Dir,
@ -139,7 +142,7 @@ impl StateExt for State {
.with(stats)
.with(health)
.with(comp::Alignment::Npc)
.with(comp::Energy::new(body.base_energy()))
.with(comp::Energy::new(body, 0))
.with(comp::Gravity(1.0))
.with(comp::CharacterState::default())
.with(inventory)
@ -219,7 +222,6 @@ impl StateExt for State {
fn initialize_character_data(&mut self, entity: EcsEntity, character_id: CharacterId) {
let spawn_point = self.ecs().read_resource::<SpawnPoint>().0;
self.write_component(entity, comp::Energy::new(1000));
self.write_component(entity, comp::Controller::default());
self.write_component(entity, comp::Pos(spawn_point));
self.write_component(entity, comp::Vel(Vec3::zero()));
@ -269,10 +271,24 @@ impl StateExt for State {
z_max: body.height(),
});
self.write_component(entity, body);
self.write_component(
entity,
comp::Health::new(stats.body_type, 0), //Placeholder 0
let (health_level, energy_level) = (
stats
.skill_set
.skills
.get(&Skill::General(GeneralSkill::HealthIncrease))
.copied()
.flatten()
.unwrap_or(0),
stats
.skill_set
.skills
.get(&Skill::General(GeneralSkill::EnergyIncrease))
.copied()
.flatten()
.unwrap_or(0),
);
self.write_component(entity, comp::Health::new(stats.body_type, health_level));
self.write_component(entity, comp::Energy::new(stats.body_type, energy_level));
self.write_component(entity, stats);
self.write_component(entity, inventory);
self.write_component(

View File

@ -1,7 +1,7 @@
use super::{
img_ids::{Imgs, ImgsRot},
item_imgs::{ItemImgs, ItemKey::Tool},
Show, TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN, XP_COLOR, HP_COLOR, CRITICAL_HP_COLOR,
Show, CRITICAL_HP_COLOR, HP_COLOR, TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN, XP_COLOR,
};
use crate::{
i18n::Localization,
@ -1148,20 +1148,29 @@ impl<'a> Widget for Diary<'a> {
let skill = Skill::Sword(DCost);
let prereqs_met = tweak!(true);
let suff_pts = tweak!(false);
let label_txt = &format!( "{}/{}",
let label_txt = &format!(
"{}/{}",
skills.get(&skill).copied().map_or(0, |l| l.unwrap_or(1)),
skill.get_max_level().unwrap_or(1));
skill.get_max_level().unwrap_or(1)
);
if Button::image(self.imgs.sword_whirlwind)
.w_h(tweak!(74.0), tweak!(74.0))
.middle_of(state.skills_top_r[2])
.label(if prereqs_met {&label_txt} else {""}
)
.label(if prereqs_met { &label_txt } else { "" })
.label_y(conrod_core::position::Relative::Scalar(tweak!(-28.0)))
.label_x(conrod_core::position::Relative::Scalar(tweak!(32.0)))
.label_color(if suff_pts {HP_COLOR} else {CRITICAL_HP_COLOR})
.label_color(if suff_pts {
HP_COLOR
} else {
CRITICAL_HP_COLOR
})
.label_font_size(self.fonts.cyri.scale(tweak!(16)))
.label_font_id(self.fonts.cyri.conrod_id)
.image_color(if prereqs_met {TEXT_COLOR} else {Color::Rgba(0.41, 0.41, 0.41, tweak!(0.7))})
.image_color(if prereqs_met {
TEXT_COLOR
} else {
Color::Rgba(0.41, 0.41, 0.41, tweak!(0.7))
})
.with_tooltip(
self.tooltip_manager,
"Dash Cost",

View File

@ -77,6 +77,7 @@ use conrod_core::{
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget,
};
use hashbrown::HashMap;
use rand::Rng;
use specs::{Join, WorldExt};
use std::{
collections::VecDeque,
@ -285,6 +286,13 @@ pub struct BuffInfo {
dur: Option<Duration>,
}
pub struct ExpFloater {
pub owner: Uid,
pub exp_change: i32,
pub timer: f32,
pub rand_offset: (f32, f32),
}
pub struct DebugInfo {
pub tps: f64,
pub frame_time: Duration,
@ -681,6 +689,7 @@ pub struct Hud {
hotbar: hotbar::State,
events: Vec<Event>,
crosshair_opacity: f32,
exp_floaters: Vec<ExpFloater>,
}
impl Hud {
@ -779,6 +788,7 @@ impl Hud {
hotbar: hotbar_state,
events: Vec::new(),
crosshair_opacity: 0.0,
exp_floaters: Vec::new(),
}
}
@ -1060,26 +1070,10 @@ impl Hud {
}
}
// EXP Numbers
self.exp_floaters.retain(|f| f.timer > 0_f32);
if let Some(uid) = uids.get(me) {
for exp in ecs
.read_resource::<Vec<Outcome>>()
.iter()
.filter(
|o| matches!(o, Outcome::ExpChange { uid: uid_, .. } if uid == uid_ ),
)
.filter_map(|o| {
if let Outcome::ExpChange { exp, .. } = o {
Some(exp)
} else {
None
}
})
{
println!("{}", exp);
for floater in self.exp_floaters.iter_mut().filter(|f| f.owner == *uid) {
let number_speed = 50.0; // Number Speed for Single EXP
let timer = 100.0; // Fake number
let rand1 = 0.5; // Fake number
let rand2 = -0.1; // Fake number
let player_sct_bg_id = player_sct_bg_id_walker.next(
&mut self.ids.player_sct_bgs,
&mut ui_widgets.widget_id_generator(),
@ -1091,34 +1085,35 @@ impl Hud {
// Increase font size based on fraction of maximum health
// "flashes" by having a larger size in the first 100ms
let font_size_xp = 30
+ ((*exp as f32 / 300.0).min(1.0) * 50.0) as u32
+ if timer < 0.1 {
FLASH_MAX * (((1.0 - timer / 0.1) * 10.0) as u32)
+ ((floater.exp_change as f32 / 300.0).min(1.0) * 50.0) as u32
+ if floater.timer < 0.1 {
FLASH_MAX * (((1.0 - floater.timer / 0.1) * 10.0) as u32)
} else {
0
};
let y = timer as f64 * number_speed; // Timer sets the widget offset
let fade = ((4.0 - timer as f32) * 0.25) + 0.2; // Timer sets text transparency
let y = floater.timer as f64 * number_speed; // Timer sets the widget offset
let fade = ((4.0 - floater.timer as f32) * 0.25) + 0.2; // Timer sets text transparency
Text::new(&format!("{} Exp", exp))
Text::new(&format!("{} Exp", floater.exp_change))
.font_size(font_size_xp)
.font_id(self.fonts.cyri.conrod_id)
.color(Color::Rgba(0.0, 0.0, 0.0, fade))
.x_y(
ui_widgets.win_w * (0.5 * rand1 as f64 - 0.25),
ui_widgets.win_h * (0.15 * rand2 as f64) + y - 3.0,
ui_widgets.win_w * (0.5 * floater.rand_offset.0 as f64 - 0.25),
ui_widgets.win_h * (0.15 * floater.rand_offset.1 as f64) + y - 3.0,
)
.set(player_sct_bg_id, ui_widgets);
Text::new(&format!("{} Exp", exp))
Text::new(&format!("{} Exp", floater.exp_change))
.font_size(font_size_xp)
.font_id(self.fonts.cyri.conrod_id)
.color(Color::Rgba(0.59, 0.41, 0.67, fade))
.x_y(
ui_widgets.win_w * (0.5 * rand1 as f64 - 0.25),
ui_widgets.win_h * (0.15 * rand2 as f64) + y,
ui_widgets.win_w * (0.5 * floater.rand_offset.0 as f64 - 0.25),
ui_widgets.win_h * (0.15 * floater.rand_offset.1 as f64) + y,
)
.set(player_sct_id, ui_widgets);
floater.timer -= dt.as_secs_f32();
}
}
}
@ -2778,6 +2773,18 @@ impl Hud {
pub fn free_look(&mut self, free_look: bool) { self.show.free_look = free_look; }
pub fn auto_walk(&mut self, auto_walk: bool) { self.show.auto_walk = auto_walk; }
pub fn handle_outcome(&mut self, outcome: &Outcome) {
match outcome {
Outcome::ExpChange { uid, exp } => self.exp_floaters.push(ExpFloater {
owner: *uid,
exp_change: *exp,
timer: 4.0,
rand_offset: rand::thread_rng().gen::<(f32, f32)>(),
}),
_ => {},
}
}
}
// Get item qualities of equipped items and assign a tooltip title/frame color
pub fn get_quality_col<I: ItemDesc>(item: &I) -> Color {

View File

@ -1250,6 +1250,7 @@ impl PlayState for SessionState {
for outcome in outcomes {
self.scene
.handle_outcome(&outcome, &scene_data, &mut global_state.audio);
self.hud.handle_outcome(&outcome);
}
}
}