mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'sam/fix-health-buffs' into 'master'
Fix interaction of max health and max health over time buffs causing infinite health scaling. See merge request veloren/veloren!2557
This commit is contained in:
commit
1020fbe86a
@ -152,9 +152,9 @@ pub enum BuffEffect {
|
|||||||
/// Gradually changes an entities max health over time
|
/// Gradually changes an entities max health over time
|
||||||
MaxHealthChangeOverTime {
|
MaxHealthChangeOverTime {
|
||||||
rate: f32,
|
rate: f32,
|
||||||
accumulated: f32,
|
|
||||||
kind: ModifierKind,
|
kind: ModifierKind,
|
||||||
target_fraction: f32,
|
target_fraction: f32,
|
||||||
|
achieved_fraction: Option<f32>,
|
||||||
},
|
},
|
||||||
/// Modifies move speed of target
|
/// Modifies move speed of target
|
||||||
MovementSpeed(f32),
|
MovementSpeed(f32),
|
||||||
@ -247,9 +247,9 @@ impl Buff {
|
|||||||
vec![
|
vec![
|
||||||
BuffEffect::MaxHealthChangeOverTime {
|
BuffEffect::MaxHealthChangeOverTime {
|
||||||
rate: -10.0,
|
rate: -10.0,
|
||||||
accumulated: 0.0,
|
|
||||||
kind: ModifierKind::Additive,
|
kind: ModifierKind::Additive,
|
||||||
target_fraction: 1.0 - data.strength,
|
target_fraction: 1.0 - data.strength,
|
||||||
|
achieved_fraction: None,
|
||||||
},
|
},
|
||||||
BuffEffect::HealthChangeOverTime {
|
BuffEffect::HealthChangeOverTime {
|
||||||
rate: -10.0,
|
rate: -10.0,
|
||||||
|
@ -226,7 +226,8 @@ impl<'a> System<'a> for Sys {
|
|||||||
},
|
},
|
||||||
BuffEffect::MaxHealthModifier { value, kind } => match kind {
|
BuffEffect::MaxHealthModifier { value, kind } => match kind {
|
||||||
ModifierKind::Additive => {
|
ModifierKind::Additive => {
|
||||||
stat.max_health_modifier += *value / (health.base_max() as f32);
|
stat.max_health_modifier *=
|
||||||
|
1.0 + *value / (health.base_max() as f32);
|
||||||
},
|
},
|
||||||
ModifierKind::Fractional => {
|
ModifierKind::Fractional => {
|
||||||
stat.max_health_modifier *= *value;
|
stat.max_health_modifier *= *value;
|
||||||
@ -245,31 +246,63 @@ impl<'a> System<'a> for Sys {
|
|||||||
},
|
},
|
||||||
BuffEffect::MaxHealthChangeOverTime {
|
BuffEffect::MaxHealthChangeOverTime {
|
||||||
rate,
|
rate,
|
||||||
accumulated,
|
|
||||||
kind,
|
kind,
|
||||||
target_fraction,
|
target_fraction,
|
||||||
|
achieved_fraction,
|
||||||
} => {
|
} => {
|
||||||
*accumulated += *rate * dt;
|
// Current fraction uses information from last tick, which is
|
||||||
let current_fraction = health.maximum() as f32
|
// necessary as buffs from this tick are not guaranteed to have
|
||||||
/ (health.base_max() as f32 * stat.max_health_modifier);
|
// finished applying
|
||||||
let progress = (1.0 - current_fraction) / (1.0 - *target_fraction);
|
let current_fraction =
|
||||||
if progress > 1.0 {
|
health.maximum() as f32 / health.base_max() as f32;
|
||||||
stat.max_health_modifier *= *target_fraction;
|
|
||||||
} else if accumulated.abs() > rate.abs() {
|
// If achieved_fraction not initialized, initialize it to health
|
||||||
match kind {
|
// fraction
|
||||||
|
if achieved_fraction.is_none() {
|
||||||
|
*achieved_fraction = Some(current_fraction)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(achieved_fraction) = achieved_fraction {
|
||||||
|
// Percentage change that should be applied to max_health
|
||||||
|
let health_tick = match kind {
|
||||||
ModifierKind::Additive => {
|
ModifierKind::Additive => {
|
||||||
stat.max_health_modifier = stat.max_health_modifier
|
// `rate * dt` is amount of health, dividing by base max
|
||||||
* current_fraction
|
// creates fraction
|
||||||
+ *accumulated / health.maximum() as f32;
|
*rate * dt / health.base_max() as f32
|
||||||
},
|
},
|
||||||
ModifierKind::Fractional => {
|
ModifierKind::Fractional => {
|
||||||
stat.max_health_modifier *=
|
// `rate * dt` is the fraction
|
||||||
current_fraction * (1.0 - *accumulated);
|
*rate * dt
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
*accumulated = 0.0;
|
|
||||||
|
let potential_fraction = *achieved_fraction + health_tick;
|
||||||
|
|
||||||
|
// Potential progress towards target fraction, if
|
||||||
|
// target_fraction ~ 1.0 then set progress to 1.0 to avoid
|
||||||
|
// divide by zero
|
||||||
|
let progress = if (1.0 - *target_fraction).abs() > f32::EPSILON
|
||||||
|
{
|
||||||
|
(1.0 - potential_fraction) / (1.0 - *target_fraction)
|
||||||
} else {
|
} else {
|
||||||
stat.max_health_modifier *= current_fraction;
|
1.0
|
||||||
|
};
|
||||||
|
|
||||||
|
// Change achieved_fraction depending on what other buffs have
|
||||||
|
// occurred
|
||||||
|
if progress > 1.0 {
|
||||||
|
// If potential fraction already beyond target fraction,
|
||||||
|
// simply multiply max_health_modifier by the target
|
||||||
|
// fraction, and set achieved fraction to target_fraction
|
||||||
|
*achieved_fraction = *target_fraction;
|
||||||
|
} else {
|
||||||
|
// Else have not achieved target yet, update
|
||||||
|
// achieved_fraction
|
||||||
|
*achieved_fraction = potential_fraction;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply achieved_fraction to max_health_modifier
|
||||||
|
stat.max_health_modifier *= *achieved_fraction;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
BuffEffect::MovementSpeed(speed) => {
|
BuffEffect::MovementSpeed(speed) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user