mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Handling crits (very bad color choice+naming)
This commit is contained in:
parent
93d3ce18b4
commit
634a3095d6
@ -11,7 +11,7 @@ use crate::{
|
||||
Player, Poise, PoiseChange, SkillSet, Stats,
|
||||
},
|
||||
event::ServerEvent,
|
||||
outcome::Outcome,
|
||||
outcome::{DamageInfo, Outcome},
|
||||
states::utils::StageSection,
|
||||
uid::{Uid, UidAllocator},
|
||||
util::Dir,
|
||||
@ -239,14 +239,17 @@ impl Attack {
|
||||
let applied_damage = -change.amount;
|
||||
accumulated_damage += applied_damage;
|
||||
|
||||
// Could also check this when handling outcomes and display 0.0 damage differently?
|
||||
// Could also check this when handling outcomes and display 0.0 damage
|
||||
// differently?
|
||||
if applied_damage != 0.0 {
|
||||
emit_outcome(Outcome::Damage {
|
||||
pos: target.pos,
|
||||
target: target.uid,
|
||||
by: attacker.map(|a| a.uid),
|
||||
amount: applied_damage,
|
||||
crit: is_crit,
|
||||
info: DamageInfo {
|
||||
target: target.uid,
|
||||
by: attacker.map(|a| a.uid),
|
||||
amount: change.amount,
|
||||
crit: is_crit,
|
||||
},
|
||||
});
|
||||
}
|
||||
if change.amount.abs() > Health::HEALTH_EPSILON {
|
||||
|
@ -4,6 +4,14 @@ use hashbrown::HashSet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use vek::*;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
pub struct DamageInfo {
|
||||
pub amount: f32,
|
||||
pub crit: bool,
|
||||
pub target: Uid,
|
||||
pub by: Option<Uid>,
|
||||
}
|
||||
|
||||
/// An outcome represents the final result of an instantaneous event. It implies
|
||||
/// that said event has already occurred. It is not a request for that event to
|
||||
/// occur, nor is it something that may be cancelled or otherwise altered. Its
|
||||
@ -60,11 +68,7 @@ pub enum Outcome {
|
||||
},
|
||||
Damage {
|
||||
pos: Vec3<f32>,
|
||||
amount: f32,
|
||||
target: Uid,
|
||||
by: Option<Uid>,
|
||||
// TODO: Maybe seperate attack data/info into seperate struct?
|
||||
crit: bool,
|
||||
info: DamageInfo,
|
||||
},
|
||||
Death {
|
||||
pos: Vec3<f32>,
|
||||
|
@ -1,4 +1,4 @@
|
||||
use common::comp::Ori;
|
||||
use common::{comp::Ori, outcome::DamageInfo};
|
||||
use specs::Component;
|
||||
use specs_idvs::IdvStorage;
|
||||
use vek::*;
|
||||
@ -8,8 +8,7 @@ use vek::*;
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct HpFloater {
|
||||
pub timer: f32,
|
||||
// Numbers of times significant damage has been dealt
|
||||
pub hp_change: f32,
|
||||
pub info: DamageInfo,
|
||||
// Used for randomly offsetting
|
||||
pub rand: f32,
|
||||
}
|
||||
|
@ -1399,7 +1399,7 @@ impl Hud {
|
||||
.read_storage::<comp::Pos>()
|
||||
.get(client.entity())
|
||||
.map_or(Vec3::zero(), |pos| pos.0);
|
||||
// SCT Output values are called hp_damage and floater.hp_change
|
||||
// SCT Output values are called hp_damage and floater.info.amount
|
||||
// Numbers are currently divided by 10 and rounded
|
||||
if global_state.settings.interface.sct {
|
||||
// Render Player SCT numbers
|
||||
@ -1424,19 +1424,24 @@ impl Hud {
|
||||
|
||||
// Calculate total change
|
||||
// Ignores healing
|
||||
let hp_damage: f32 = floaters.iter().map(|f| f.hp_change.min(0.0)).sum();
|
||||
let hp_damage: f32 = floaters.iter().map(|f| f.info.amount.min(0.0)).sum();
|
||||
|
||||
// .fold(0.0, |acc, f| f.hp_change.min(0.0) + acc);
|
||||
// .fold(0.0, |acc, f| f.info.amount.min(0.0) + acc);
|
||||
let hp_dmg_rounded_abs = hp_damage.round().abs() as u32;
|
||||
let max_hp_frac = hp_damage.abs() as f32 / health.maximum() as f32;
|
||||
let timer = floaters
|
||||
.last()
|
||||
.expect("There must be at least one floater")
|
||||
.timer;
|
||||
let crit = floaters
|
||||
.last()
|
||||
.expect("There must be at least one floater")
|
||||
.info
|
||||
.crit;
|
||||
// Increase font size based on fraction of maximum health
|
||||
// "flashes" by having a larger size in the first 100ms
|
||||
let font_size = 30
|
||||
+ ((max_hp_frac * 10.0) as u32) * 3
|
||||
+ ((max_hp_frac * 10.0) as u32) * 3 * if crit { 2 } else { 1 }
|
||||
+ if timer < 0.1 {
|
||||
FLASH_MAX * (((1.0 - timer / 0.1) * 10.0) as u32)
|
||||
} else {
|
||||
@ -1461,7 +1466,11 @@ impl Hud {
|
||||
.font_size(font_size)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(if hp_damage < 0.0 {
|
||||
Color::Rgba(1.0, 0.1, 0.0, hp_fade)
|
||||
if crit {
|
||||
Color::Rgba(1.0, 0.9, 0.1, hp_fade)
|
||||
} else {
|
||||
Color::Rgba(1.0, 0.1, 0.0, hp_fade)
|
||||
}
|
||||
} else {
|
||||
Color::Rgba(0.0, 0.0, 0.0, 0.0)
|
||||
})
|
||||
@ -1472,7 +1481,7 @@ impl Hud {
|
||||
// Healing always single numbers so just skip damage when in batch mode
|
||||
|
||||
if global_state.settings.interface.sct_player_batch
|
||||
&& floater.hp_change < 0.0
|
||||
&& floater.info.amount < 0.0
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -1485,34 +1494,39 @@ impl Hud {
|
||||
&mut self.ids.player_scts,
|
||||
&mut ui_widgets.widget_id_generator(),
|
||||
);
|
||||
let max_hp_frac = floater.hp_change.abs() as f32 / health.maximum() as f32;
|
||||
let max_hp_frac =
|
||||
floater.info.amount.abs() as f32 / health.maximum() as f32;
|
||||
// Increase font size based on fraction of maximum health
|
||||
// "flashes" by having a larger size in the first 100ms
|
||||
// TODO: example
|
||||
let font_size = 30
|
||||
+ ((max_hp_frac * 10.0) as u32) * 3
|
||||
+ ((max_hp_frac * 10.0) as u32)
|
||||
* 3
|
||||
* if floater.info.crit { 2 } else { 1 }
|
||||
+ if floater.timer < 0.1 {
|
||||
// TODO: Maybe change font size wrt crits here?
|
||||
FLASH_MAX * (((1.0 - floater.timer / 0.1) * 10.0) as u32)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
// Timer sets the widget offset
|
||||
let y = if floater.hp_change < 0.0 {
|
||||
let y = if floater.info.amount < 0.0 {
|
||||
floater.timer as f64
|
||||
* number_speed
|
||||
* floater.hp_change.signum() as f64
|
||||
* floater.info.amount.signum() as f64
|
||||
//* -1.0
|
||||
+ 300.0
|
||||
- ui_widgets.win_h * 0.5
|
||||
} else {
|
||||
floater.timer as f64
|
||||
* number_speed
|
||||
* floater.hp_change.signum() as f64
|
||||
* floater.info.amount.signum() as f64
|
||||
* -1.0
|
||||
+ 300.0
|
||||
- ui_widgets.win_h * 0.5
|
||||
};
|
||||
// Healing is offset randomly
|
||||
let x = if floater.hp_change < 0.0 {
|
||||
let x = if floater.info.amount < 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
(floater.rand as f64 - 0.5) * 0.2 * ui_widgets.win_w
|
||||
@ -1521,35 +1535,45 @@ impl Hud {
|
||||
let hp_fade = ((crate::ecs::sys::floater::MY_HP_SHOWTIME - floater.timer)
|
||||
* 0.25)
|
||||
+ 0.2;
|
||||
if floater.hp_change.abs() > 1.0 {
|
||||
Text::new(&format!("{:.0}", floater.hp_change.abs()))
|
||||
if floater.info.amount.abs() > 1.0 {
|
||||
Text::new(&format!("{:.0}", floater.info.amount.abs()))
|
||||
.font_size(font_size)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(Color::Rgba(0.0, 0.0, 0.0, hp_fade))
|
||||
.x_y(x, y - 3.0)
|
||||
.set(player_sct_bg_id, ui_widgets);
|
||||
Text::new(&format!("{:.0}", floater.hp_change.abs()))
|
||||
Text::new(&format!("{:.0}", floater.info.amount.abs()))
|
||||
.font_size(font_size)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(if floater.hp_change < 0.0 {
|
||||
Color::Rgba(1.0, 0.1, 0.0, hp_fade)
|
||||
.color(if floater.info.amount < 0.0 {
|
||||
// TODO: example
|
||||
if floater.info.crit {
|
||||
Color::Rgba(1.0, 0.9, 0.1, hp_fade)
|
||||
} else {
|
||||
Color::Rgba(1.0, 0.1, 0.0, hp_fade)
|
||||
}
|
||||
} else {
|
||||
Color::Rgba(0.1, 1.0, 0.1, hp_fade)
|
||||
})
|
||||
.x_y(x, y)
|
||||
.set(player_sct_id, ui_widgets);
|
||||
} else {
|
||||
Text::new(&format!("{:.1}", floater.hp_change.abs()))
|
||||
Text::new(&format!("{:.1}", floater.info.amount.abs()))
|
||||
.font_size(font_size)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(Color::Rgba(0.0, 0.0, 0.0, hp_fade))
|
||||
.x_y(x, y - 3.0)
|
||||
.set(player_sct_bg_id, ui_widgets);
|
||||
Text::new(&format!("{:.1}", floater.hp_change.abs()))
|
||||
Text::new(&format!("{:.1}", floater.info.amount.abs()))
|
||||
.font_size(font_size)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(if floater.hp_change < 0.0 {
|
||||
Color::Rgba(1.0, 0.1, 0.0, hp_fade)
|
||||
.color(if floater.info.amount < 0.0 {
|
||||
// TODO: example
|
||||
if floater.info.crit {
|
||||
Color::Rgba(1.0, 0.9, 0.1, hp_fade)
|
||||
} else {
|
||||
Color::Rgba(1.0, 0.1, 0.0, hp_fade)
|
||||
}
|
||||
} else {
|
||||
Color::Rgba(0.1, 1.0, 0.1, hp_fade)
|
||||
})
|
||||
@ -2179,12 +2203,20 @@ impl Hud {
|
||||
let floaters = &hpfl.floaters;
|
||||
|
||||
// Colors
|
||||
// TODO: Add for crits as well?
|
||||
// Maybe decrease increase blue for lighter colour?
|
||||
const WHITE: Rgb<f32> = Rgb::new(1.0, 0.9, 0.8);
|
||||
const LIGHT_OR: Rgb<f32> = Rgb::new(1.0, 0.925, 0.749);
|
||||
const LIGHT_MED_OR: Rgb<f32> = Rgb::new(1.0, 0.85, 0.498);
|
||||
const MED_OR: Rgb<f32> = Rgb::new(1.0, 0.776, 0.247);
|
||||
const DARK_ORANGE: Rgb<f32> = Rgb::new(1.0, 0.7, 0.0);
|
||||
const RED_ORANGE: Rgb<f32> = Rgb::new(1.0, 0.349, 0.0);
|
||||
const CWHITE: Rgb<f32> = Rgb::new(1.0, 0.9, 0.413);
|
||||
const CLIGHT_YEL: Rgb<f32> = Rgb::new(1.0, 0.9, 0.353);
|
||||
const CLIGHT_MED_YEL: Rgb<f32> = Rgb::new(1.0, 0.9, 0.256);
|
||||
const CMED_YEL: Rgb<f32> = Rgb::new(1.0, 0.9, 0.184);
|
||||
const CDARK_ORANGE: Rgb<f32> = Rgb::new(1.0, 0.9, 0.098);
|
||||
const CRED_ORANGE: Rgb<f32> = Rgb::new(1.0, 0.9, 0.0);
|
||||
const DAMAGE_COLORS: [Rgb<f32>; 6] = [
|
||||
WHITE,
|
||||
LIGHT_OR,
|
||||
@ -2193,10 +2225,22 @@ impl Hud {
|
||||
DARK_ORANGE,
|
||||
RED_ORANGE,
|
||||
];
|
||||
const CDAMAGE_COLORS: [Rgb<f32>; 6] = [
|
||||
CWHITE,
|
||||
CLIGHT_YEL,
|
||||
CLIGHT_MED_YEL,
|
||||
CMED_YEL,
|
||||
CDARK_ORANGE,
|
||||
CRED_ORANGE,
|
||||
];
|
||||
// Largest value that select the first color is 40, then it shifts colors
|
||||
// every 5
|
||||
let font_col = |font_size: u32| {
|
||||
DAMAGE_COLORS[(font_size.saturating_sub(36) / 5).min(5) as usize]
|
||||
let font_col = |font_size: u32, crit: bool| {
|
||||
if crit {
|
||||
CDAMAGE_COLORS[(font_size.saturating_sub(72) / 5).min(5) as usize]
|
||||
} else {
|
||||
DAMAGE_COLORS[(font_size.saturating_sub(36) / 5).min(5) as usize]
|
||||
}
|
||||
};
|
||||
|
||||
if global_state.settings.interface.sct_damage_batch {
|
||||
@ -2208,8 +2252,8 @@ impl Hud {
|
||||
// Calculate total change
|
||||
// Ignores healing
|
||||
let hp_damage = floaters.iter().fold(0.0, |acc, f| {
|
||||
if f.hp_change < 0.0 {
|
||||
acc + f.hp_change
|
||||
if f.info.amount < 0.0 {
|
||||
acc + f.info.amount
|
||||
} else {
|
||||
acc
|
||||
}
|
||||
@ -2220,16 +2264,21 @@ impl Hud {
|
||||
.last()
|
||||
.expect("There must be at least one floater")
|
||||
.timer;
|
||||
let crit = floaters
|
||||
.last()
|
||||
.expect("There must be at least one floater")
|
||||
.info
|
||||
.crit;
|
||||
// Increase font size based on fraction of maximum health
|
||||
// "flashes" by having a larger size in the first 100ms
|
||||
let font_size = 30
|
||||
+ ((max_hp_frac * 10.0) as u32) * 3
|
||||
+ ((max_hp_frac * 10.0) as u32) * 3 * if crit { 2 } else { 1 }
|
||||
+ if timer < 0.1 {
|
||||
FLASH_MAX * (((1.0 - timer / 0.1) * 10.0) as u32)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let font_col = font_col(font_size);
|
||||
let font_col = font_col(font_size, crit);
|
||||
// Timer sets the widget offset
|
||||
let y = (timer as f64 / crate::ecs::sys::floater::HP_SHOWTIME as f64
|
||||
* number_speed)
|
||||
@ -2286,18 +2335,20 @@ impl Hud {
|
||||
let sct_bg_id = sct_bg_walker
|
||||
.next(&mut self.ids.sct_bgs, &mut ui_widgets.widget_id_generator());
|
||||
// Calculate total change
|
||||
let max_hp_frac = floater.hp_change.abs() as f32
|
||||
let max_hp_frac = floater.info.amount.abs() as f32
|
||||
/ health.map_or(1.0, |h| h.maximum() as f32);
|
||||
// Increase font size based on fraction of maximum health
|
||||
// "flashes" by having a larger size in the first 100ms
|
||||
let font_size = 30
|
||||
+ ((max_hp_frac * 10.0) as u32) * 3
|
||||
+ ((max_hp_frac * 10.0) as u32)
|
||||
* 3
|
||||
* if floater.info.crit { 2 } else { 1 }
|
||||
+ if floater.timer < 0.1 {
|
||||
FLASH_MAX * (((1.0 - floater.timer / 0.1) * 10.0) as u32)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let font_col = font_col(font_size);
|
||||
let font_col = font_col(font_size, floater.info.crit);
|
||||
// Timer sets the widget offset
|
||||
let y = (floater.timer as f64
|
||||
/ crate::ecs::sys::floater::HP_SHOWTIME as f64
|
||||
@ -2307,12 +2358,12 @@ impl Hud {
|
||||
let fade = ((crate::ecs::sys::floater::HP_SHOWTIME - floater.timer)
|
||||
* 0.25)
|
||||
+ 0.2;
|
||||
if floater.hp_change.abs() < 1.0 {
|
||||
if floater.info.amount.abs() < 1.0 {
|
||||
// Damage and heal below 10/10 are shown as decimals
|
||||
Text::new(&format!("{:.0}", floater.hp_change.abs()))
|
||||
Text::new(&format!("{:.0}", floater.info.amount.abs()))
|
||||
.font_size(font_size)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(if floater.hp_change < 0.0 {
|
||||
.color(if floater.info.amount < 0.0 {
|
||||
Color::Rgba(0.0, 0.0, 0.0, fade)
|
||||
} else {
|
||||
Color::Rgba(0.0, 0.0, 0.0, 1.0)
|
||||
@ -2320,11 +2371,11 @@ impl Hud {
|
||||
.x_y(0.0, y - 3.0)
|
||||
.position_ingame(ingame_pos)
|
||||
.set(sct_bg_id, ui_widgets);
|
||||
Text::new(&format!("{:.0}", floater.hp_change.abs()))
|
||||
Text::new(&format!("{:.0}", floater.info.amount.abs()))
|
||||
.font_size(font_size)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.x_y(0.0, y)
|
||||
.color(if floater.hp_change < 0.0 {
|
||||
.color(if floater.info.amount < 0.0 {
|
||||
Color::Rgba(font_col.r, font_col.g, font_col.b, fade)
|
||||
} else {
|
||||
Color::Rgba(0.1, 1.0, 0.1, 1.0)
|
||||
@ -2333,10 +2384,10 @@ impl Hud {
|
||||
.set(sct_id, ui_widgets);
|
||||
} else {
|
||||
// Damage and heal above 10/10 are shown rounded
|
||||
Text::new(&format!("{:.1}", floater.hp_change.abs()))
|
||||
Text::new(&format!("{:.1}", floater.info.amount.abs()))
|
||||
.font_size(font_size)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(if floater.hp_change < 0.0 {
|
||||
.color(if floater.info.amount < 0.0 {
|
||||
Color::Rgba(0.0, 0.0, 0.0, fade)
|
||||
} else {
|
||||
Color::Rgba(0.0, 0.0, 0.0, 1.0)
|
||||
@ -2344,11 +2395,11 @@ impl Hud {
|
||||
.x_y(0.0, y - 3.0)
|
||||
.position_ingame(ingame_pos)
|
||||
.set(sct_bg_id, ui_widgets);
|
||||
Text::new(&format!("{:.1}", floater.hp_change.abs()))
|
||||
Text::new(&format!("{:.1}", floater.info.amount.abs()))
|
||||
.font_size(font_size)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.x_y(0.0, y)
|
||||
.color(if floater.hp_change < 0.0 {
|
||||
.color(if floater.info.amount < 0.0 {
|
||||
Color::Rgba(font_col.r, font_col.g, font_col.b, fade)
|
||||
} else {
|
||||
Color::Rgba(0.1, 1.0, 0.1, 1.0)
|
||||
@ -4477,29 +4528,23 @@ impl Hud {
|
||||
timer: 1.0,
|
||||
})
|
||||
},
|
||||
Outcome::Damage {
|
||||
by,
|
||||
target,
|
||||
crit,
|
||||
amount,
|
||||
..
|
||||
} => {
|
||||
Outcome::Damage { info, .. } => {
|
||||
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(entity) = ecs.entity_from_uid(info.target.0) {
|
||||
if let Some(floater_list) = hp_floater_lists.get_mut(entity) {
|
||||
if match by {
|
||||
if match info.by {
|
||||
Some(by) => {
|
||||
let by_me = my_uid.map_or(false, |&uid| *by == uid);
|
||||
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
|
||||
my_uid.map_or(false, |&uid| info.target == uid) || by_me
|
||||
},
|
||||
None => false,
|
||||
} {
|
||||
@ -4508,12 +4553,13 @@ impl Hud {
|
||||
Some(f) if f.timer < floater::HP_ACCUMULATETIME => {
|
||||
//TODO: Add "jumping" animation on floater when it changes its
|
||||
// value
|
||||
f.hp_change += -*amount;
|
||||
f.info.amount += info.amount;
|
||||
f.info.crit = info.crit;
|
||||
},
|
||||
_ => {
|
||||
floater_list.floaters.push(HpFloater {
|
||||
timer: 0.0,
|
||||
hp_change: -*amount,
|
||||
info: *info,
|
||||
rand: rand::random(),
|
||||
});
|
||||
},
|
||||
@ -4521,7 +4567,6 @@ impl Hud {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
_ => {},
|
||||
|
@ -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, &scene_data.client);
|
||||
self.hud.handle_outcome(&outcome, scene_data.client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user