Instance numbers for HpChanges

This commit is contained in:
socksonme 2022-01-26 12:16:45 +02:00 committed by Socksonme
parent f8924d6c1a
commit ac5bf53c42
10 changed files with 71 additions and 15 deletions

View File

@ -212,6 +212,7 @@ impl Attack {
let is_crit = thread_rng().gen::<f32>() < self.crit_chance; let is_crit = thread_rng().gen::<f32>() < self.crit_chance;
let mut is_applied = false; let mut is_applied = false;
let mut accumulated_damage = 0.0; let mut accumulated_damage = 0.0;
let instance = rand::random();
for damage in self for damage in self
.damages .damages
.iter() .iter()
@ -235,6 +236,7 @@ impl Attack {
self.crit_multiplier, self.crit_multiplier,
strength_modifier, strength_modifier,
time, time,
instance,
); );
let applied_damage = -change.amount; let applied_damage = -change.amount;
accumulated_damage += applied_damage; accumulated_damage += applied_damage;
@ -259,6 +261,7 @@ impl Attack {
time, time,
crit: Some(is_crit), crit: Some(is_crit),
crit_mult: self.crit_multiplier, crit_mult: self.crit_multiplier,
instance,
}; };
emit(ServerEvent::HealthChange { emit(ServerEvent::HealthChange {
entity: target.entity, entity: target.entity,
@ -358,6 +361,7 @@ impl Attack {
time, time,
crit: None, crit: None,
crit_mult: self.crit_multiplier, crit_mult: self.crit_multiplier,
instance: rand::random(),
}; };
if change.amount.abs() > Health::HEALTH_EPSILON { if change.amount.abs() > Health::HEALTH_EPSILON {
emit(ServerEvent::HealthChange { emit(ServerEvent::HealthChange {
@ -392,6 +396,7 @@ impl Attack {
time, time,
crit: None, crit: None,
crit_mult: self.crit_multiplier, crit_mult: self.crit_multiplier,
instance: rand::random(),
}; };
if change.amount.abs() > Health::HEALTH_EPSILON { if change.amount.abs() > Health::HEALTH_EPSILON {
emit(ServerEvent::HealthChange { emit(ServerEvent::HealthChange {
@ -505,6 +510,7 @@ impl Attack {
time, time,
crit: None, crit: None,
crit_mult: self.crit_multiplier, crit_mult: self.crit_multiplier,
instance: rand::random(),
}; };
if change.amount.abs() > Health::HEALTH_EPSILON { if change.amount.abs() > Health::HEALTH_EPSILON {
emit(ServerEvent::HealthChange { emit(ServerEvent::HealthChange {
@ -539,6 +545,7 @@ impl Attack {
time, time,
crit: None, crit: None,
crit_mult: self.crit_multiplier, crit_mult: self.crit_multiplier,
instance: rand::random(),
}; };
if change.amount.abs() > Health::HEALTH_EPSILON { if change.amount.abs() > Health::HEALTH_EPSILON {
emit(ServerEvent::HealthChange { emit(ServerEvent::HealthChange {
@ -731,6 +738,7 @@ impl From<AttackerInfo<'_>> for DamageContributor {
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
pub enum DamageSource { pub enum DamageSource {
// Could be used to separate DOTs?
Buff(BuffKind), Buff(BuffKind),
Melee, Melee,
Projectile, Projectile,
@ -828,6 +836,7 @@ impl Damage {
crit_mult: f32, crit_mult: f32,
damage_modifier: f32, damage_modifier: f32,
time: Time, time: Time,
instance: u64,
) -> HealthChange { ) -> HealthChange {
let mut damage = self.value * damage_modifier; let mut damage = self.value * damage_modifier;
let critdamage = if is_crit { let critdamage = if is_crit {
@ -853,6 +862,7 @@ impl Damage {
time, time,
crit: Some(is_crit), crit: Some(is_crit),
crit_mult, crit_mult,
instance,
} }
}, },
DamageSource::Falling => { DamageSource::Falling => {
@ -867,6 +877,7 @@ impl Damage {
time, time,
crit: None, crit: None,
crit_mult, crit_mult,
instance,
} }
}, },
DamageSource::Buff(_) | DamageSource::Other => HealthChange { DamageSource::Buff(_) | DamageSource::Other => HealthChange {
@ -876,6 +887,7 @@ impl Damage {
time, time,
crit: None, crit: None,
crit_mult, crit_mult,
instance,
}, },
} }
} }

View File

@ -2,6 +2,7 @@ use crate::DamageSource;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use crate::{comp, consts::HP_PER_LEVEL}; use crate::{comp, consts::HP_PER_LEVEL};
use hashbrown::HashMap; use hashbrown::HashMap;
use rand;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::convert::TryFrom; use std::convert::TryFrom;
@ -28,6 +29,11 @@ pub struct HealthChange {
/// couldn't have been a crit) /// couldn't have been a crit)
pub crit: Option<bool>, pub crit: Option<bool>,
pub crit_mult: f32, pub crit_mult: f32,
/// A random instance ID given to every health change
/// Note: Two or more changes could have the same instance number, if they
/// came from the same attack (for example - the extra damage caused by
/// slashing weapons)
pub instance: u64,
} }
impl HealthChange { impl HealthChange {
@ -139,6 +145,7 @@ impl Health {
crit: None, crit: None,
crit_mult: 1.0, crit_mult: 1.0,
time: Time(0.0), time: Time(0.0),
instance: rand::random(),
}, },
is_dead: false, is_dead: false,
damage_contributors: HashMap::new(), damage_contributors: HashMap::new(),
@ -221,6 +228,7 @@ impl Health {
crit: None, crit: None,
crit_mult: 1.0, crit_mult: 1.0,
time: Time(0.0), time: Time(0.0),
instance: rand::random(),
}, },
is_dead: false, is_dead: false,
damage_contributors: HashMap::new(), damage_contributors: HashMap::new(),
@ -256,6 +264,7 @@ mod tests {
cause: None, cause: None,
crit: None, crit: None,
crit_mult: 1.0, crit_mult: 1.0,
instance: rand::random(),
}; };
health.change_by(health_change); health.change_by(health_change);
@ -283,6 +292,7 @@ mod tests {
cause: None, cause: None,
crit: None, crit: None,
crit_mult: 1.0, crit_mult: 1.0,
instance: rand::random(),
}; };
health.change_by(health_change); health.change_by(health_change);
@ -304,6 +314,7 @@ mod tests {
cause: None, cause: None,
crit: None, crit: None,
crit_mult: 1.0, crit_mult: 1.0,
instance: rand::random(),
}; };
health.change_by(health_change); health.change_by(health_change);
health.change_by(health_change); health.change_by(health_change);
@ -331,6 +342,7 @@ mod tests {
cause: None, cause: None,
crit: None, crit: None,
crit_mult: 1.0, crit_mult: 1.0,
instance: rand::random(),
}; };
health.change_by(health_change); health.change_by(health_change);
@ -342,6 +354,7 @@ mod tests {
cause: None, cause: None,
crit: None, crit: None,
crit_mult: 1.0, crit_mult: 1.0,
instance: rand::random(),
}; };
health.change_by(health_change); health.change_by(health_change);
@ -357,6 +370,7 @@ mod tests {
cause: None, cause: None,
crit: None, crit: None,
crit_mult: 1.0, crit_mult: 1.0,
instance: rand::random(),
}; };
health.change_by(health_change); health.change_by(health_change);

View File

@ -11,6 +11,7 @@ pub struct DamageInfo {
pub target: Uid, pub target: Uid,
pub by: Option<DamageContributor>, pub by: Option<DamageContributor>,
pub crit_mult: f32, pub crit_mult: f32,
pub instance: u64,
} }
/// An outcome represents the final result of an instantaneous event. It implies /// An outcome represents the final result of an instantaneous event. It implies

View File

@ -276,6 +276,7 @@ impl<'a> System<'a> for Sys {
time: *read_data.time, time: *read_data.time,
crit: None, crit: None,
crit_mult: 1.0, crit_mult: 1.0,
instance: rand::random(),
}, },
}); });
*accumulated = 0.0; *accumulated = 0.0;

View File

@ -128,6 +128,7 @@ impl<'a> System<'a> for Sys {
// Might make this more nuanced if shockwaves are used for non damage effects // Might make this more nuanced if shockwaves are used for non damage effects
let group = shockwave_owner.and_then(|e| read_data.groups.get(e)); let group = shockwave_owner.and_then(|e| read_data.groups.get(e));
// TODO: Join counter later?
// Go through all other effectable entities // Go through all other effectable entities
for (target, uid_b, pos_b, health_b, body_b, physics_state_b) in ( for (target, uid_b, pos_b, health_b, body_b, physics_state_b) in (
&read_data.entities, &read_data.entities,

View File

@ -1059,6 +1059,7 @@ fn handle_health(
crit: None, crit: None,
crit_mult: 1.0, crit_mult: 1.0,
time: *time, time: *time,
instance: rand::random(),
}; };
health.change_by(change); health.change_by(change);
Ok(()) Ok(())

View File

@ -91,6 +91,7 @@ pub fn handle_health_change(server: &Server, entity: EcsEntity, change: HealthCh
by: change.by, by: change.by,
target: *uid, target: *uid,
crit_mult: change.crit_mult, crit_mult: change.crit_mult,
instance: change.instance,
}, },
}); });
} }
@ -593,7 +594,7 @@ pub fn handle_land_on_ground(server: &Server, entity: EcsEntity, vel: Vec3<f32>)
&msm, &msm,
); );
let change = let change =
damage.calculate_health_change(damage_reduction, None, false, 0.0, 1.0, *time); damage.calculate_health_change(damage_reduction, None, false, 0.0, 1.0, *time, rand::random());
health.change_by(change); health.change_by(change);
let server_eventbus = ecs.read_resource::<EventBus<ServerEvent>>(); let server_eventbus = ecs.read_resource::<EventBus<ServerEvent>>();
server_eventbus.emit_now(ServerEvent::HealthChange { server_eventbus.emit_now(ServerEvent::HealthChange {
@ -601,6 +602,7 @@ pub fn handle_land_on_ground(server: &Server, entity: EcsEntity, vel: Vec3<f32>)
change, change,
}); });
} }
// Handle poise change // Handle poise change
if let Some(mut poise) = ecs.write_storage::<comp::Poise>().get_mut(entity) { if let Some(mut poise) = ecs.write_storage::<comp::Poise>().get_mut(entity) {
let poise_damage = -(mass.0 * vel.magnitude_squared() / 1500.0); let poise_damage = -(mass.0 * vel.magnitude_squared() / 1500.0);
@ -861,6 +863,7 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
} }
}, },
RadiusEffect::Attack(attack) => { RadiusEffect::Attack(attack) => {
// TODO: Join counter later?
let energies = &ecs.read_storage::<comp::Energy>(); let energies = &ecs.read_storage::<comp::Energy>();
let combos = &ecs.read_storage::<comp::Combo>(); let combos = &ecs.read_storage::<comp::Combo>();
let inventories = &ecs.read_storage::<comp::Inventory>(); let inventories = &ecs.read_storage::<comp::Inventory>();

View File

@ -159,6 +159,7 @@ impl StateExt for State {
0.0, 0.0,
1.0, 1.0,
*time, *time,
rand::random(),
); );
self.ecs() self.ecs()
.write_storage::<comp::Health>() .write_storage::<comp::Health>()

View File

@ -11,7 +11,6 @@ pub const HP_SHOWTIME: f32 = 3.0;
pub const CRIT_SHOWTIME: f32 = 0.7; pub const CRIT_SHOWTIME: f32 = 0.7;
pub const MY_HP_SHOWTIME: f32 = 2.5; pub const MY_HP_SHOWTIME: f32 = 2.5;
pub const HP_ACCUMULATETIME: f32 = 1.0; pub const HP_ACCUMULATETIME: f32 = 1.0;
pub const CRIT_ACCUMULATETIME: f32 = 0.25;
#[derive(Default)] #[derive(Default)]
pub struct Sys; pub struct Sys;

View File

@ -58,7 +58,6 @@ use crate::{
ecs::{ ecs::{
comp as vcomp, comp as vcomp,
comp::{HpFloater, HpFloaterList}, comp::{HpFloater, HpFloaterList},
sys::floater,
}, },
game_input::GameInput, game_input::GameInput,
hud::{img_ids::ImgsRot, prompt_dialog::DialogOutcomeEvent}, hud::{img_ids::ImgsRot, prompt_dialog::DialogOutcomeEvent},
@ -1581,14 +1580,15 @@ impl Hud {
((crate::ecs::sys::floater::MY_HP_SHOWTIME - floater.timer) * 0.25) ((crate::ecs::sys::floater::MY_HP_SHOWTIME - floater.timer) * 0.25)
+ 0.2 + 0.2
}; };
// TODO: Add options for these as well
if floater.info.amount.abs() > 1.0 { if floater.info.amount.abs() > 1.0 {
Text::new(&format!("{:.0}", floater.info.amount.abs())) Text::new(&format!("{:.1}", floater.info.amount.abs()))
.font_size(font_size) .font_size(font_size)
.font_id(self.fonts.cyri.conrod_id) .font_id(self.fonts.cyri.conrod_id)
.color(Color::Rgba(0.0, 0.0, 0.0, hp_fade)) .color(Color::Rgba(0.0, 0.0, 0.0, hp_fade))
.x_y(x, y - 3.0) .x_y(x, y - 3.0)
.set(player_sct_bg_id, ui_widgets); .set(player_sct_bg_id, ui_widgets);
Text::new(&format!("{:.0}", floater.info.amount.abs())) Text::new(&format!("{:.1}", floater.info.amount.abs()))
.font_size(font_size) .font_size(font_size)
.font_id(self.fonts.cyri.conrod_id) .font_id(self.fonts.cyri.conrod_id)
.color(if floater.info.amount < 0.0 { .color(if floater.info.amount < 0.0 {
@ -2485,7 +2485,7 @@ impl Hud {
// Damage and heal below 10/10 are shown as decimals // Damage and heal below 10/10 are shown as decimals
// TODO: this is not true right now, but we might want to add an // TODO: this is not true right now, but we might want to add an
// option for this // option for this
Text::new(&format!("{:.0}", floater.info.amount.abs())) Text::new(&format!("{:.1}", floater.info.amount.abs()))
.font_size(font_size) .font_size(font_size)
.font_id(self.fonts.cyri.conrod_id) .font_id(self.fonts.cyri.conrod_id)
.color(if floater.info.amount < 0.0 { .color(if floater.info.amount < 0.0 {
@ -2496,7 +2496,7 @@ impl Hud {
.x_y(x, y - 3.0) .x_y(x, y - 3.0)
.position_ingame(ingame_pos) .position_ingame(ingame_pos)
.set(sct_bg_id, ui_widgets); .set(sct_bg_id, ui_widgets);
Text::new(&format!("{:.0}", floater.info.amount.abs())) Text::new(&format!("{:.1}", floater.info.amount.abs()))
.font_size(font_size) .font_size(font_size)
.font_id(self.fonts.cyri.conrod_id) .font_id(self.fonts.cyri.conrod_id)
.x_y(x, y) .x_y(x, y)
@ -4676,6 +4676,30 @@ impl Hud {
}, },
None => hit_me, None => hit_me,
} { } {
let mut merged = false;
// Or maybe something like this
for floater in floater_list.floaters.iter_mut().rev() {
if floater.timer > 0.0 {
break;
}
if floater.info.instance == info.instance {
dbg!(floater.info.instance);
dbg!(floater.timer);
floater.info.amount += info.amount;
floater.info.crit_mult = info.crit_mult;
floater.info.crit = Some(
floater.info.crit.unwrap_or(false)
|| info.crit.unwrap_or(false)
);
merged = true;
}
}
if merged {
return;
}
// To separate healing and damage floaters
let last_floater = if info.amount < Health::HEALTH_EPSILON { let last_floater = if info.amount < Health::HEALTH_EPSILON {
floater_list floater_list
.floaters .floaters
@ -4691,22 +4715,21 @@ impl Hud {
}; };
match last_floater { match last_floater {
// TODO: This system is currently only in place because some damage
// sources create multiple HpChange events, which leads to multiple
// damage Outcomes. Will need to figure this out (perhaps storing an
// instance number for the hpchanges somehow?)
Some(f) Some(f)
if (info.crit.unwrap_or(false) // TODO: Change later so it's based on options
&& f.timer < floater::CRIT_ACCUMULATETIME if /*(info.crit.unwrap_or(false)
&& info.crit.unwrap_or(false))
|| (f.timer < floater::HP_ACCUMULATETIME || (f.timer < floater::HP_ACCUMULATETIME
&& !f.info.crit.unwrap_or(false) && !f.info.crit.unwrap_or(false)
&& !info.crit.unwrap_or(false)) => && !info.crit.unwrap_or(false)) */ false =>
{ {
dbg!(f.info.instance);
dbg!(f.timer);
//TODO: Add "jumping" animation on floater when it changes its //TODO: Add "jumping" animation on floater when it changes its
// value // value
f.info.amount += info.amount; f.info.amount += info.amount;
f.info.crit_mult = info.crit_mult; f.info.crit_mult = info.crit_mult;
// TODO: Temporary ofc.
f.info.crit = Some(f.info.crit.unwrap_or(false) || info.crit.unwrap_or(false));
}, },
_ => { _ => {
floater_list.floaters.push(HpFloater { floater_list.floaters.push(HpFloater {