mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
HpFloaters are now created by Outcomes, touched up Damage Outcome
This commit is contained in:
parent
bf6c6fb33d
commit
aee7888a92
@ -238,9 +238,14 @@ impl Attack {
|
||||
);
|
||||
let applied_damage = -change.amount;
|
||||
accumulated_damage += applied_damage;
|
||||
// TODO: Check this out later
|
||||
// if applied_damage > 0.0 {
|
||||
//
|
||||
// }
|
||||
emit_outcome(Outcome::Damage {
|
||||
pos: target.pos,
|
||||
uid: target.uid,
|
||||
target: target.uid,
|
||||
by: attacker.map(|a| a.uid),
|
||||
amount: applied_damage,
|
||||
crit: is_crit,
|
||||
});
|
||||
|
@ -60,10 +60,10 @@ pub enum Outcome {
|
||||
},
|
||||
Damage {
|
||||
pos: Vec3<f32>,
|
||||
/// The exact amount of damage delt,
|
||||
/// excluding any sources of healing
|
||||
amount: f32,
|
||||
uid: Uid,
|
||||
target: Uid,
|
||||
by: Option<Uid>,
|
||||
// TODO: Maybe seperate attack data/info into seperate struct?
|
||||
crit: bool,
|
||||
},
|
||||
Death {
|
||||
|
@ -1,8 +1,7 @@
|
||||
use crate::ecs::comp::{HpFloater, HpFloaterList};
|
||||
use crate::ecs::comp::HpFloaterList;
|
||||
use common::{
|
||||
comp::{Health, Pos},
|
||||
resources::{DeltaTime, PlayerEntity},
|
||||
uid::Uid,
|
||||
};
|
||||
use common_ecs::{Job, Origin, Phase, System};
|
||||
use specs::{Entities, Join, Read, ReadStorage, WriteStorage};
|
||||
@ -19,7 +18,6 @@ impl<'a> System<'a> for Sys {
|
||||
Entities<'a>,
|
||||
Read<'a, PlayerEntity>,
|
||||
Read<'a, DeltaTime>,
|
||||
ReadStorage<'a, Uid>,
|
||||
ReadStorage<'a, Pos>,
|
||||
ReadStorage<'a, Health>,
|
||||
WriteStorage<'a, HpFloaterList>,
|
||||
@ -32,7 +30,7 @@ impl<'a> System<'a> for Sys {
|
||||
#[allow(clippy::blocks_in_if_conditions)] // TODO: Pending review in #587
|
||||
fn run(
|
||||
_job: &mut Job<Self>,
|
||||
(entities, my_entity, dt, uids, pos, healths, mut hp_floater_lists): Self::SystemData,
|
||||
(entities, my_entity, dt, pos, healths, mut hp_floater_lists): Self::SystemData,
|
||||
) {
|
||||
// Add hp floater lists to all entities with health and a position
|
||||
// Note: necessary in order to know last_hp
|
||||
@ -48,70 +46,12 @@ impl<'a> System<'a> for Sys {
|
||||
});
|
||||
}
|
||||
|
||||
// Add hp floaters to all entities that have been damaged
|
||||
let my_uid = my_entity.0.and_then(|entity| uids.get(entity));
|
||||
for (entity, health, hp_floater_list) in (&entities, &healths, &mut hp_floater_lists).join()
|
||||
{
|
||||
for hp_floater_list in (&mut hp_floater_lists).join() {
|
||||
// Increment timer for time since last damaged by me
|
||||
hp_floater_list
|
||||
.time_since_last_dmg_by_me
|
||||
.as_mut()
|
||||
.map(|t| *t += dt.0);
|
||||
|
||||
// Check if health has changed (won't work if damaged and then healed with
|
||||
// equivalently in the same frame)
|
||||
if (hp_floater_list.last_hp - health.current()).abs() > Health::HEALTH_EPSILON {
|
||||
hp_floater_list.last_hp = health.current();
|
||||
// TODO: What if multiple health changes occurred since last check here
|
||||
// Also, If we make health store a vec of the last_changes (from say the last
|
||||
// frame), what if the client receives the health component from
|
||||
// two different server ticks at once, then one will be lost
|
||||
// (tbf this is probably a rare occurance and the results
|
||||
// would just be a transient glitch in the display of these damage numbers)
|
||||
// (maybe health changes could be sent to the client as a list
|
||||
// of events)
|
||||
if match health.last_change.by.map(|x| x.uid()) {
|
||||
// HealthSource::Damage { by: Some(by), .. }
|
||||
// | HealthSource::Heal { by: Some(by) } => {
|
||||
// let by_me = my_uid.map_or(false, |&uid| by == uid);
|
||||
// // If the attack was by me also reset this timer
|
||||
// if by_me {
|
||||
// hp_floater_list.time_since_last_dmg_by_me = Some(0.0);
|
||||
// }
|
||||
// my_entity.0 == Some(entity) || by_me
|
||||
// },
|
||||
// HealthSource::Suicide => my_entity.0 == Some(entity),
|
||||
// HealthSource::World => my_entity.0 == Some(entity),
|
||||
// HealthSource::LevelUp => my_entity.0 == Some(entity),
|
||||
// HealthSource::Command => true,
|
||||
// HealthSource::Item => true,
|
||||
// _ => false,
|
||||
Some(by) => {
|
||||
let by_me = my_uid.map_or(false, |&uid| by == uid);
|
||||
// If the attack was by me also reset this timer
|
||||
if by_me {
|
||||
hp_floater_list.time_since_last_dmg_by_me = Some(0.0);
|
||||
}
|
||||
my_entity.0 == Some(entity) || by_me
|
||||
},
|
||||
None => false,
|
||||
} {
|
||||
let last_floater = hp_floater_list.floaters.last_mut();
|
||||
match last_floater {
|
||||
Some(f) if f.timer < HP_ACCUMULATETIME => {
|
||||
//TODO: Add "jumping" animation on floater when it changes its value
|
||||
f.hp_change += health.last_change.amount;
|
||||
},
|
||||
_ => {
|
||||
hp_floater_list.floaters.push(HpFloater {
|
||||
timer: 0.0,
|
||||
hp_change: health.last_change.amount,
|
||||
rand: rand::random(),
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove floater lists on entities without health or without position
|
||||
|
@ -54,7 +54,12 @@ use trade::Trade;
|
||||
|
||||
use crate::{
|
||||
cmd::get_player_uuid,
|
||||
ecs::{comp as vcomp, comp::HpFloaterList},
|
||||
ecs::{comp as vcomp, comp::{HpFloater, HpFloaterList}, sys::floater},
|
||||
ecs::{
|
||||
comp as vcomp,
|
||||
comp::{HpFloater, HpFloaterList},
|
||||
sys::floater,
|
||||
},
|
||||
game_input::GameInput,
|
||||
hud::{img_ids::ImgsRot, prompt_dialog::DialogOutcomeEvent},
|
||||
render::UiDrawer,
|
||||
@ -1416,14 +1421,17 @@ impl Hud {
|
||||
&mut self.ids.player_scts,
|
||||
&mut ui_widgets.widget_id_generator(),
|
||||
);
|
||||
// TODO: Change to use Outcome
|
||||
|
||||
// Calculate total change
|
||||
// Ignores healing
|
||||
let hp_damage: f32 = floaters.iter().map(|f| f.hp_change.min(0.0)).sum();
|
||||
dbg!(hp_damage);
|
||||
|
||||
// .fold(0.0, |acc, f| f.hp_change.min(0.0) + acc);
|
||||
let hp_dmg_rounded_abs = hp_damage.round().abs() as u32;
|
||||
dbg!(hp_dmg_rounded_abs);
|
||||
let max_hp_frac = hp_damage.abs() as f32 / health.maximum() as f32;
|
||||
dbg!(max_hp_frac);
|
||||
let timer = floaters
|
||||
.last()
|
||||
.expect("There must be at least one floater")
|
||||
@ -1481,6 +1489,7 @@ impl Hud {
|
||||
&mut ui_widgets.widget_id_generator(),
|
||||
);
|
||||
let max_hp_frac = floater.hp_change.abs() as f32 / health.maximum() as f32;
|
||||
dbg!(max_hp_frac);
|
||||
// Increase font size based on fraction of maximum health
|
||||
// "flashes" by having a larger size in the first 100ms
|
||||
let font_size = 30
|
||||
@ -4437,7 +4446,7 @@ impl Hud {
|
||||
|
||||
pub fn camera_clamp(&mut self, camera_clamp: bool) { self.show.camera_clamp = camera_clamp; }
|
||||
|
||||
pub fn handle_outcome(&mut self, outcome: &Outcome) {
|
||||
pub fn handle_outcome(&mut self, outcome: &Outcome, client: &Client) {
|
||||
match outcome {
|
||||
Outcome::ExpChange { uid, exp, xp_pools } => {
|
||||
self.floaters.exp_floaters.push(ExpFloater {
|
||||
@ -4473,9 +4482,57 @@ impl Hud {
|
||||
})
|
||||
},
|
||||
Outcome::Damage {
|
||||
uid, crit, amount, ..
|
||||
by,
|
||||
target,
|
||||
crit,
|
||||
amount,
|
||||
..
|
||||
} => {
|
||||
dbg!(uid);
|
||||
let ecs = client.state().ecs();
|
||||
let mut hp_floater_lists = ecs.write_storage::<vcomp::HpFloaterList>();
|
||||
let uids = ecs.read_storage::<Uid>();
|
||||
let me = client.entity();
|
||||
let my_uid = uids.get(me);
|
||||
|
||||
if let Some(entity) = ecs.entity_from_uid(target.0) {
|
||||
if let Some(floater_list) = hp_floater_lists.get_mut(entity) {
|
||||
if match by {
|
||||
Some(by) => {
|
||||
let by_me = my_uid.map_or(false, |&uid| *by == uid);
|
||||
// If the attack was by me also reset this timer
|
||||
if by_me {
|
||||
floater_list.time_since_last_dmg_by_me = Some(0.0);
|
||||
}
|
||||
my_uid.map_or(false, |&uid| *target == uid) || by_me
|
||||
},
|
||||
None => false,
|
||||
} {
|
||||
let last_floater = floater_list.floaters.last_mut();
|
||||
match last_floater {
|
||||
Some(f) if f.timer < floater::HP_ACCUMULATETIME => {
|
||||
//TODO: Add "jumping" animation on floater when it changes its
|
||||
// value
|
||||
f.hp_change += -*amount;
|
||||
},
|
||||
_ => {
|
||||
floater_list.floaters.push(HpFloater {
|
||||
timer: 0.0,
|
||||
hp_change: -*amount,
|
||||
rand: rand::random(),
|
||||
});
|
||||
},
|
||||
}
|
||||
} else {
|
||||
dbg!("not by player/hit player");
|
||||
}
|
||||
} else {
|
||||
dbg!("no floater list");
|
||||
}
|
||||
} else {
|
||||
dbg!("no entity from target uid");
|
||||
}
|
||||
|
||||
dbg!(target);
|
||||
dbg!(crit);
|
||||
dbg!(amount);
|
||||
},
|
||||
|
@ -1579,7 +1579,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);
|
||||
self.hud.handle_outcome(&outcome, &scene_data.client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user