Crits now only glob with eachother, now show up like healing

Still a WIP, need to change crits to being non-floating and try implementing crits popping, need to remove some debugging stuff later
This commit is contained in:
socksonme 2022-01-24 19:01:06 +02:00 committed by Socksonme
parent ce95680df9
commit 7a1e19d42c
8 changed files with 138 additions and 33 deletions

View File

@ -258,6 +258,7 @@ impl Attack {
cause: Some(damage.damage.source),
time,
crit: Some(is_crit),
crit_mult: self.crit_multiplier,
};
emit(ServerEvent::HealthChange {
entity: target.entity,
@ -356,6 +357,7 @@ impl Attack {
cause: None,
time,
crit: None,
crit_mult: self.crit_multiplier,
};
if change.amount.abs() > Health::HEALTH_EPSILON {
emit(ServerEvent::HealthChange {
@ -389,6 +391,7 @@ impl Attack {
cause: None,
time,
crit: None,
crit_mult: self.crit_multiplier,
};
if change.amount.abs() > Health::HEALTH_EPSILON {
emit(ServerEvent::HealthChange {
@ -501,6 +504,7 @@ impl Attack {
cause: None,
time,
crit: None,
crit_mult: self.crit_multiplier,
};
if change.amount.abs() > Health::HEALTH_EPSILON {
emit(ServerEvent::HealthChange {
@ -534,6 +538,7 @@ impl Attack {
cause: None,
time,
crit: None,
crit_mult: self.crit_multiplier,
};
if change.amount.abs() > Health::HEALTH_EPSILON {
emit(ServerEvent::HealthChange {
@ -847,6 +852,7 @@ impl Damage {
cause: Some(self.source),
time,
crit: Some(is_crit),
crit_mult,
}
},
DamageSource::Falling => {
@ -860,6 +866,7 @@ impl Damage {
cause: Some(self.source),
time,
crit: None,
crit_mult,
}
},
DamageSource::Buff(_) | DamageSource::Other => HealthChange {
@ -868,6 +875,7 @@ impl Damage {
cause: Some(self.source),
time,
crit: None,
crit_mult,
},
}
}

View File

@ -27,6 +27,7 @@ pub struct HealthChange {
/// Whether or not the health change was caused by a crit (None if it
/// couldn't have been a crit)
pub crit: Option<bool>,
pub crit_mult: f32,
}
impl HealthChange {
@ -136,6 +137,7 @@ impl Health {
by: None,
cause: None,
crit: None,
crit_mult: 1.0,
time: Time(0.0),
},
is_dead: false,
@ -215,6 +217,7 @@ impl Health {
by: None,
cause: None,
crit: None,
crit_mult: 1.0,
time: Time(0.0),
},
is_dead: false,
@ -250,6 +253,7 @@ mod tests {
by: Some(damage_contrib),
cause: None,
crit: None,
crit_mult: 1.0,
};
health.change_by(health_change);
@ -276,6 +280,7 @@ mod tests {
by: Some(damage_contrib),
cause: None,
crit: None,
crit_mult: 1.0,
};
health.change_by(health_change);
@ -296,6 +301,7 @@ mod tests {
by: Some(damage_contrib),
cause: None,
crit: None,
crit_mult: 1.0,
};
health.change_by(health_change);
health.change_by(health_change);
@ -322,6 +328,7 @@ mod tests {
by: Some(damage_contrib1),
cause: None,
crit: None,
crit_mult: 1.0,
};
health.change_by(health_change);
@ -332,6 +339,7 @@ mod tests {
by: Some(damage_contrib2),
cause: None,
crit: None,
crit_mult: 1.0,
};
health.change_by(health_change);
@ -346,6 +354,7 @@ mod tests {
by: Some(damage_contrib2),
cause: None,
crit: None,
crit_mult: 1.0,
};
health.change_by(health_change);

View File

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

View File

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

View File

@ -1057,6 +1057,7 @@ fn handle_health(
by: None,
cause: None,
crit: None,
crit_mult: 1.0,
time: *time,
};
health.change_by(change);

View File

@ -89,6 +89,7 @@ pub fn handle_health_change(server: &Server, entity: EcsEntity, change: HealthCh
crit: change.crit,
by: change.by,
target: *uid,
crit_mult: change.crit_mult,
},
});
}

View File

@ -8,8 +8,10 @@ use specs::{Entities, Join, Read, ReadStorage, WriteStorage};
// How long floaters last (in seconds)
pub const HP_SHOWTIME: f32 = 3.0;
pub const CRIT_SHOWTIME: f32 = 0.7;
pub const MY_HP_SHOWTIME: f32 = 2.5;
pub const HP_ACCUMULATETIME: f32 = 1.0;
pub const CRIT_ACCUMULATETIME: f32 = 0.25;
#[derive(Default)]
pub struct Sys;
@ -82,6 +84,10 @@ impl<'a> System<'a> for Sys {
// Increment timer
floater.timer += dt.0;
}
// // TODO: For popping effect
// floaters.retain(|f| !f.info.crit || (f.info.crit && f.timer <
// CRIT_SHOWTIME));
// Clear floaters if newest floater is past show time or health runs out
if floaters.last().map_or(false, |f| {
f.timer

View File

@ -1411,6 +1411,7 @@ impl Hud {
.filter(|fl| !fl.floaters.is_empty()),
healths.get(me),
) {
// TODO: Change these for crits
if global_state.settings.interface.sct_player_batch {
let number_speed = 100.0; // Player Batched Numbers Speed
let player_sct_bg_id = player_sct_bg_id_walker.next(
@ -1445,13 +1446,21 @@ impl Hud {
.last()
.and_then(|f| f.info.crit)
.unwrap_or(false);
let crit_mult =
damage_floaters.last().map_or(1.0, |f| f.info.crit_mult);
// 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 * if crit { 2 } else { 1 }
+ ((max_hp_frac * 10.0 * if crit { 1.5 * crit_mult } else { 1.0 })
as u32)
* 3
+ if timer < 0.1 {
FLASH_MAX * (((1.0 - timer / 0.1) * 10.0) as u32)
FLASH_MAX
* (((1.0 - timer / 0.1)
* 10.0
* if crit { 1.5 * crit_mult } else { 1.0 })
as u32)
} else {
0
};
@ -1486,6 +1495,7 @@ impl Hud {
.set(player_sct_id, ui_widgets);
}
};
// TODO: Change these for crits
for floater in floaters {
// Healing always single numbers so just skip damage when in batch mode
@ -1509,20 +1519,33 @@ impl Hud {
// "flashes" by having a larger size in the first 100ms
// TODO: example
let font_size = 30
+ ((max_hp_frac * 10.0) as u32) * 3 * if crit { 2 } else { 1 }
+ (max_hp_frac
* 10.0
* if crit {
1.5 * floater.info.crit_mult
} else {
1.0
}) as u32
* 3
+ 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)
FLASH_MAX
* (((1.0 - floater.timer / 0.1)
* 10.0
* if crit {
1.5 * floater.info.crit_mult
} else {
1.0
}) as u32)
} else {
0
};
// Timer sets the widget offset
let y = if floater.info.amount < 0.0 {
floater.timer as f64
* number_speed
* floater.info.amount.signum() as f64
//* -1.0
+ 300.0
* number_speed
* floater.info.amount.signum() as f64
//* -1.0
+ 300.0
- ui_widgets.win_h * 0.5
} else {
floater.timer as f64
@ -1533,10 +1556,10 @@ impl Hud {
- ui_widgets.win_h * 0.5
};
// Healing is offset randomly
let x = if floater.info.amount < 0.0 {
let x = if floater.info.amount < 0.0 && !crit {
0.0
} else {
(floater.rand as f64 - 0.5) * 0.2 * ui_widgets.win_w
(floater.rand as f64 - 0.5).abs().max(0.2) * (floater.rand as f64 - 0.5).signum() * 0.25 * ui_widgets.win_w
};
// Timer sets text transparency
let hp_fade = ((crate::ecs::sys::floater::MY_HP_SHOWTIME - floater.timer)
@ -2211,6 +2234,8 @@ impl Hud {
// Colors
// TODO: The crit colors and their names are pretty bad as it stands
//TODO: They don't stand out enough as they should, and they fade weirdly, such
// that they look transparent from the get-go
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);
@ -2243,13 +2268,18 @@ impl Hud {
// every 5
let font_col = |font_size: u32, crit: bool| {
if crit {
CDAMAGE_COLORS[(font_size.saturating_sub(72) / 5).min(5) as usize]
// TODO: This will probably be the way crit colours are handled (with a
// different algo for choosing the color)
// CDAMAGE_COLORS[(font_size.saturating_sub(72) / 5).min(5) as usize]
// TODO: Temporary
Rgb::new(1.0, 0.9, 0.0)
} else {
DAMAGE_COLORS[(font_size.saturating_sub(36) / 5).min(5) as usize]
}
};
// TODO: Might have to change something here as well
// TODO: Change these for crits
if global_state.settings.interface.sct_damage_batch {
let number_speed = 50.0; // Damage number speed
let sct_id = sct_walker
@ -2275,13 +2305,21 @@ impl Hud {
.last()
.and_then(|f| f.info.crit)
.unwrap_or(false);
let crit_mult =
damage_floaters.last().map_or(1.0, |f| f.info.crit_mult);
// 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 * if crit { 2 } else { 1 }
+ ((max_hp_frac * 10.0 * if crit { 1.5 * crit_mult } else { 1.0 })
as u32)
* 3
+ if timer < 0.1 {
FLASH_MAX * (((1.0 - timer / 0.1) * 10.0) as u32)
FLASH_MAX
* (((1.0 - timer / 0.1)
* 10.0
* if crit { 1.5 * crit_mult } else { 1.0 })
as u32)
} else {
0
};
@ -2351,22 +2389,55 @@ impl Hud {
// 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 * if crit { 2 } else { 1 }
+ (max_hp_frac
* 10.0
* if crit {
2.5 * floater.info.crit_mult
} else {
1.0
}) as u32
* 3
+ if floater.timer < 0.1 {
FLASH_MAX * (((1.0 - floater.timer / 0.1) * 10.0) as u32)
FLASH_MAX
* (((1.0 - floater.timer / 0.1)
* 10.0
* if crit {
1.5 * floater.info.crit_mult
} else {
1.0
}) as u32)
} else {
0
};
let font_col = font_col(font_size, crit);
// Timer sets the widget offset
let y = (floater.timer as f64
/ crate::ecs::sys::floater::HP_SHOWTIME as f64
* number_speed)
+ 100.0;
// TODO: Keep working on this
let y = if crit {
ui_widgets.win_h * (floater.rand as f64 % 0.175)
} else {
(floater.timer as f64
/ crate::ecs::sys::floater::HP_SHOWTIME as f64
* number_speed)
+ 100.0
};
let x = if !crit {
0.0
} else {
(floater.rand as f64 - 0.5).abs().max(0.2) * (floater.rand as f64 - 0.5).signum() * 0.25 * ui_widgets.win_w
};
dbg!(x);
dbg!(y);
// Timer sets text transparency
let fade = ((crate::ecs::sys::floater::HP_SHOWTIME - floater.timer)
* 0.25)
+ 0.2;
let fade = if crit {
((crate::ecs::sys::floater::CRIT_SHOWTIME - floater.timer) * 0.25)
+ 0.2
} else {
((crate::ecs::sys::floater::HP_SHOWTIME - floater.timer) * 0.25)
+ 0.2
};
if floater.info.amount.abs() < 1.0 {
// Damage and heal below 10/10 are shown as decimals
Text::new(&format!("{:.0}", floater.info.amount.abs()))
@ -2377,13 +2448,13 @@ impl Hud {
} else {
Color::Rgba(0.0, 0.0, 0.0, 1.0)
})
.x_y(0.0, y - 3.0)
.x_y(x, y - 3.0)
.position_ingame(ingame_pos)
.set(sct_bg_id, ui_widgets);
Text::new(&format!("{:.0}", floater.info.amount.abs()))
.font_size(font_size)
.font_id(self.fonts.cyri.conrod_id)
.x_y(0.0, y)
.x_y(x, y)
.color(if floater.info.amount < 0.0 {
Color::Rgba(font_col.r, font_col.g, font_col.b, fade)
} else {
@ -2401,13 +2472,13 @@ impl Hud {
} else {
Color::Rgba(0.0, 0.0, 0.0, 1.0)
})
.x_y(0.0, y - 3.0)
.x_y(x, y - 3.0)
.position_ingame(ingame_pos)
.set(sct_bg_id, ui_widgets);
Text::new(&format!("{:.1}", floater.info.amount.abs()))
.font_size(font_size)
.font_id(self.fonts.cyri.conrod_id)
.x_y(0.0, y)
.x_y(x, y)
.color(if floater.info.amount < 0.0 {
Color::Rgba(font_col.r, font_col.g, font_col.b, fade)
} else {
@ -4571,15 +4642,22 @@ impl Hud {
.rev()
.find(|f| f.info.amount > Health::HEALTH_EPSILON)
};
match last_floater {
Some(f) if f.timer < floater::HP_ACCUMULATETIME => {
// TODO: Only seperate crits for anything that didn't hit the enemy?
Some(f)
if (info.crit.unwrap_or(false)
&& f.timer < floater::CRIT_ACCUMULATETIME
&& info.crit.unwrap_or(false))
|| (f.timer < floater::HP_ACCUMULATETIME
&& !f.info.crit.unwrap_or(false)
&& !info.crit.unwrap_or(false)) =>
{
//TODO: Add "jumping" animation on floater when it changes its
// value
dbg!("add to floater");
f.info.amount += info.amount;
// Only change the crit value if it's not None
if info.crit.is_some() {
f.info.crit = info.crit;
}
f.info.crit_mult = info.crit_mult;
},
_ => {
floater_list.floaters.push(HpFloater {