Don't stack buffs of the same kind with equal attributes

This commit is contained in:
Maxicarlos08 2024-01-13 18:45:54 +01:00
parent 3922d28c8b
commit da08376e9a
No known key found for this signature in database
3 changed files with 39 additions and 28 deletions

View File

@ -791,7 +791,7 @@ impl AttackDamage {
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct AttackEffect {
target: Option<GroupTarget>,
effect: CombatEffect,
@ -890,7 +890,7 @@ impl CombatEffect {
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum CombatRequirement {
AnyDamage,
Energy(f32),
@ -898,7 +898,7 @@ pub enum CombatRequirement {
TargetHasBuff(BuffKind),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum DamagedEffect {
Combo(i32),
}

View File

@ -460,9 +460,6 @@ pub struct BuffData {
pub strength: f32,
pub duration: Option<Secs>,
pub delay: Option<Secs>,
/// Force the buff effects to be applied each tick, ignoring num_ticks
#[serde(default)]
pub force_immediate: bool,
/// Used for buffs that have rider buffs (e.g. Flame, Frigid)
pub secondary_duration: Option<Secs>,
/// Used to add random data to buffs if needed (e.g. polymorphed)
@ -479,7 +476,6 @@ impl BuffData {
Self {
strength,
duration,
force_immediate: false,
delay: None,
secondary_duration: None,
misc_data: None,
@ -496,12 +492,6 @@ impl BuffData {
self
}
/// Force the buff effects to be applied each tick, ignoring num_ticks
pub fn with_force_immediate(mut self, force_immediate: bool) -> Self {
self.force_immediate = force_immediate;
self
}
pub fn with_misc_data(mut self, misc_data: MiscBuffData) -> Self {
self.misc_data = Some(misc_data);
self
@ -524,14 +514,14 @@ pub enum BuffCategory {
SelfBuff,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum ModifierKind {
Additive,
Multiplicative,
}
/// Data indicating and configuring behaviour of a de/buff.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum BuffEffect {
/// Periodically damages or heals entity
HealthChangeOverTime {
@ -782,11 +772,36 @@ impl Buffs {
pub fn insert(&mut self, buff: Buff, current_time: Time) -> BuffKey {
let kind = buff.kind;
let key = self.buffs.insert(buff);
self.kinds[kind]
.get_or_insert_with(|| (Vec::new(), current_time))
.0
.push(key);
// Try to find another buff with same data, cat_ids and source
let other_key = self.kinds[kind].as_ref().and_then(|(keys, _)| {
keys.iter()
.find(|key| {
self.buffs.get(**key).map_or(false, |other_buff| {
other_buff.data == buff.data
&& other_buff.cat_ids == buff.cat_ids
&& other_buff.source == buff.source
})
})
.copied()
});
// If another buff with the same fields is found, update end_time and effects
let key = if let Some((other_buff, key)) =
other_key.and_then(|key| Some((self.buffs.get_mut(key)?, key)))
{
other_buff.end_time = buff.end_time;
other_buff.effects = buff.effects;
key
// Otherwise, insert a new buff
} else {
let key = self.buffs.insert(buff);
self.kinds[kind]
.get_or_insert_with(|| (Vec::new(), current_time))
.0
.push(key);
key
};
self.sort_kind(kind);
if kind.queues() {
self.delay_queueable_buffs(kind, current_time);

View File

@ -161,7 +161,7 @@ impl<'a> System<'a> for Sys {
entity,
buff_change: BuffChange::Add(Buff::new(
BuffKind::Bleeding,
BuffData::new(1.0, Some(Secs(6.0))).with_force_immediate(true),
BuffData::new(1.0, Some(Secs(6.0))),
Vec::new(),
BuffSource::World,
*read_data.time,
@ -179,7 +179,7 @@ impl<'a> System<'a> for Sys {
entity,
buff_change: BuffChange::Add(Buff::new(
BuffKind::Bleeding,
BuffData::new(5.0, Some(Secs(3.0))).with_force_immediate(true),
BuffData::new(5.0, Some(Secs(3.0))),
Vec::new(),
BuffSource::World,
*read_data.time,
@ -215,7 +215,7 @@ impl<'a> System<'a> for Sys {
entity,
buff_change: BuffChange::Add(Buff::new(
BuffKind::Bleeding,
BuffData::new(15.0, Some(Secs(0.1))).with_force_immediate(true),
BuffData::new(15.0, Some(Secs(0.1))),
Vec::new(),
BuffSource::World,
*read_data.time,
@ -420,7 +420,6 @@ impl<'a> System<'a> for Sys {
execute_effect(
effect,
buff.kind,
&buff.data,
buff.start_time,
kind_start_time,
&read_data,
@ -478,7 +477,6 @@ impl<'a> System<'a> for Sys {
fn execute_effect(
effect: &BuffEffect,
buff_kind: BuffKind,
buff_data: &BuffData,
buff_start_time: Time,
buff_kind_start_time: Time,
read_data: &ReadData,
@ -516,9 +514,7 @@ fn execute_effect(
let prev_tick = ((time_passed - dt).max(0.0) / tick_dur.0).floor();
let whole_ticks = curr_tick - prev_tick;
if buff_data.force_immediate {
Some((1.0 / tick_dur.0 * dt) as f32)
} else if buff_will_expire {
if buff_will_expire {
// If the buff is ending, include the fraction of progress towards the next
// tick.
let fractional_tick = (time_passed % tick_dur.0) / tick_dur.0;