Merge branch 'sam/buff-tweaks' into 'master'

Buffs can have variable tick times

See merge request veloren/veloren!3845
This commit is contained in:
Samuel Keiffer 2023-03-31 02:12:26 +00:00
commit ca91b75a24
2 changed files with 70 additions and 35 deletions

View File

@ -170,25 +170,33 @@ impl BuffKind {
rate: -data.strength,
kind: ModifierKind::Additive,
instance,
tick_dur: Secs(0.5),
}],
BuffKind::Regeneration => vec![BuffEffect::HealthChangeOverTime {
rate: data.strength,
kind: ModifierKind::Additive,
instance,
tick_dur: Secs(1.0),
}],
BuffKind::Saturation => vec![BuffEffect::HealthChangeOverTime {
rate: data.strength,
kind: ModifierKind::Additive,
instance,
tick_dur: Secs(3.0),
}],
BuffKind::Regeneration | BuffKind::Saturation => {
vec![BuffEffect::HealthChangeOverTime {
rate: data.strength,
kind: ModifierKind::Additive,
instance,
}]
},
BuffKind::Potion => {
vec![BuffEffect::HealthChangeOverTime {
rate: data.strength * stats.map_or(1.0, |s| s.heal_multiplier),
kind: ModifierKind::Additive,
instance,
tick_dur: Secs(0.1),
}]
},
BuffKind::CampfireHeal => vec![BuffEffect::HealthChangeOverTime {
rate: data.strength,
kind: ModifierKind::Fractional,
instance,
tick_dur: Secs(2.0),
}],
BuffKind::Cursed => vec![
BuffEffect::MaxHealthChangeOverTime {
@ -200,11 +208,13 @@ impl BuffKind {
rate: -1.0,
kind: ModifierKind::Additive,
instance,
tick_dur: Secs(0.5),
},
],
BuffKind::EnergyRegen => vec![BuffEffect::EnergyChangeOverTime {
rate: data.strength,
kind: ModifierKind::Additive,
tick_dur: Secs(1.0),
}],
BuffKind::IncreaseMaxEnergy => vec![BuffEffect::MaxEnergyModifier {
value: data.strength,
@ -225,10 +235,12 @@ impl BuffKind {
rate: -data.strength,
kind: ModifierKind::Additive,
instance,
tick_dur: Secs(0.25),
}],
BuffKind::Poisoned => vec![BuffEffect::EnergyChangeOverTime {
rate: -data.strength,
kind: ModifierKind::Additive,
tick_dur: Secs(0.5),
}],
BuffKind::Crippled => vec![
BuffEffect::MovementSpeed(1.0 - nn_scaling(data.strength)),
@ -236,6 +248,7 @@ impl BuffKind {
rate: -data.strength * 4.0,
kind: ModifierKind::Additive,
instance,
tick_dur: Secs(0.5),
},
],
BuffKind::Frenzied => vec![
@ -244,6 +257,7 @@ impl BuffKind {
rate: data.strength * 10.0,
kind: ModifierKind::Additive,
instance,
tick_dur: Secs(1.0),
},
],
BuffKind::Frozen => vec![
@ -321,9 +335,14 @@ pub enum BuffEffect {
rate: f32,
kind: ModifierKind,
instance: u64,
tick_dur: Secs,
},
/// Periodically consume entity energy
EnergyChangeOverTime { rate: f32, kind: ModifierKind },
EnergyChangeOverTime {
rate: f32,
kind: ModifierKind,
tick_dur: Secs,
},
/// Changes maximum health by a certain amount
MaxHealthModifier { value: f32, kind: ModifierKind },
/// Changes maximum energy by a certain amount

View File

@ -433,25 +433,48 @@ fn execute_effect(
time: Time,
buff_will_expire: bool,
) {
let num_ticks = |tick_dur: Secs| {
let time_passed = time.0 - buff_start_time.0;
let dt = dt as f64;
// Number of ticks has 3 parts
//
// First part checks if delta time was larger than the tick duration, if it was
// determines number of ticks in that time
//
// Second part checks if delta time has just passed the threshold for a tick
// ending/starting (and accounts for if that delta time was longer than the tick
// duration)
//
// Third part returns the fraction of the current time passed since the last
// time a tick duration would have happened, this is ignored (by flooring) when
// the buff is not ending, but is used if the buff is ending this tick
let num_ticks = (dt / tick_dur.0).floor()
+ if (dt % tick_dur.0) > (time_passed % tick_dur.0) {
1.0
} else {
0.0
}
+ (time_passed % tick_dur.0) / tick_dur.0;
if buff_will_expire {
Some(num_ticks as f32)
} else {
let floored = num_ticks.floor();
if floored >= 1.0 {
Some(floored as f32)
} else {
None
}
}
};
match effect {
BuffEffect::HealthChangeOverTime {
rate,
kind,
instance,
tick_dur,
} => {
// Apply health change if buff wasn't just added, only once per second or when
// buff is about to be removed
let time_passed = (time.0 - buff_start_time.0) as f32;
let one_second = (time_passed % 1.0) < dt;
if time_passed > dt && (one_second || buff_will_expire) {
let amount = if one_second {
// If buff not expiring this tick, then 1 second has passed
*rate
} else {
// If buff expiring this tick, only a fraction of the second has passed since
// last tick
((time.0 - buff_start_time.0) % 1.0) as f32 * rate
};
if let Some(num_ticks) = num_ticks(*tick_dur) {
let amount = *rate * num_ticks * tick_dur.0 as f32;
let (cause, by) = if amount != 0.0 {
(Some(DamageSource::Buff(buff_kind)), buff_owner)
@ -483,20 +506,13 @@ fn execute_effect(
});
};
},
BuffEffect::EnergyChangeOverTime { rate, kind } => {
// Apply energy change if buff wasn't just added, only once per second or when
// buff is about to be removed
let time_passed = (time.0 - buff_start_time.0) as f32;
let one_second = (time_passed % 1.0) < dt;
if time_passed > dt && (one_second || buff_will_expire) {
let amount = if one_second {
// If buff not expiring this tick, then 1 second has passed
*rate
} else {
// If buff expiring this tick, only a fraction of the second has passed since
// last tick
((time.0 - buff_start_time.0) % 1.0) as f32 * rate
};
BuffEffect::EnergyChangeOverTime {
rate,
kind,
tick_dur,
} => {
if let Some(num_ticks) = num_ticks(*tick_dur) {
let amount = *rate * num_ticks * tick_dur.0 as f32;
let amount = match *kind {
ModifierKind::Additive => amount,