Extract buff executor into own function

This commit is contained in:
juliancoffee 2022-09-05 15:48:23 +03:00
parent 7ea720b2ef
commit 54c48c7112

View File

@ -11,10 +11,10 @@ use common::{
Energy, Group, Health, HealthChange, Inventory, LightEmitter, ModifierKind, PhysicsState, Energy, Group, Health, HealthChange, Inventory, LightEmitter, ModifierKind, PhysicsState,
Stats, Stats,
}, },
event::{EventBus, ServerEvent}, event::{Emitter, EventBus, ServerEvent},
resources::{DeltaTime, Time}, resources::{DeltaTime, Time},
terrain::SpriteKind, terrain::SpriteKind,
uid::UidAllocator, uid::{Uid, UidAllocator},
Damage, DamageSource, Damage, DamageSource,
}; };
use common_base::prof_span; use common_base::prof_span;
@ -22,8 +22,8 @@ use common_ecs::{Job, Origin, ParMode, Phase, System};
use hashbrown::HashMap; use hashbrown::HashMap;
use rayon::iter::ParallelIterator; use rayon::iter::ParallelIterator;
use specs::{ use specs::{
saveload::MarkerAllocator, shred::ResourceId, Entities, Join, ParJoin, Read, ReadExpect, saveload::MarkerAllocator, shred::ResourceId, Entities, Entity, Join, ParJoin, Read,
ReadStorage, SystemData, World, WriteStorage, ReadExpect, ReadStorage, SystemData, World, WriteStorage,
}; };
use std::time::Duration; use std::time::Duration;
@ -257,6 +257,62 @@ impl<'a> System<'a> for Sys {
// Now, execute the buff, based on it's delta // Now, execute the buff, based on it's delta
for effect in &mut buff.effects { for effect in &mut buff.effects {
execute_effect(
effect,
buff.kind,
buff.time,
&read_data,
&mut *stat,
health,
energy,
entity,
buff_owner,
&mut server_emitter,
dt,
);
}
}
}
// Remove buffs that expire
if !expired_buffs.is_empty() {
server_emitter.emit(ServerEvent::Buff {
entity,
buff_change: BuffChange::RemoveById(expired_buffs),
});
}
// Remove buffs that don't persist on death
if health.is_dead {
server_emitter.emit(ServerEvent::Buff {
entity,
buff_change: BuffChange::RemoveByCategory {
all_required: vec![],
any_required: vec![],
none_required: vec![BuffCategory::PersistOnDeath],
},
});
}
}
// Turned back to true
buffs.set_event_emission(true);
stats.set_event_emission(true);
}
}
fn execute_effect(
effect: &mut BuffEffect,
buff_kind: BuffKind,
buff_time: Option<std::time::Duration>,
read_data: &ReadData,
stat: &mut Stats,
health: &Health,
energy: &Energy,
entity: Entity,
buff_owner: Option<Uid>,
server_emitter: &mut Emitter<ServerEvent>,
dt: f32,
) {
match effect { match effect {
BuffEffect::HealthChangeOverTime { BuffEffect::HealthChangeOverTime {
rate, rate,
@ -268,10 +324,10 @@ impl<'a> System<'a> for Sys {
// Apply health change only once per second, per health, or // Apply health change only once per second, per health, or
// when a buff is removed // when a buff is removed
if accumulated.abs() > rate.abs().min(1.0) if accumulated.abs() > rate.abs().min(1.0)
|| buff.time.map_or(false, |dur| dur == Duration::default()) || buff_time.map_or(false, |dur| dur == Duration::default())
{ {
let (cause, by) = if *accumulated != 0.0 { let (cause, by) = if *accumulated != 0.0 {
(Some(DamageSource::Buff(buff.kind)), buff_owner) (Some(DamageSource::Buff(buff_kind)), buff_owner)
} else { } else {
(None, None) (None, None)
}; };
@ -280,14 +336,12 @@ impl<'a> System<'a> for Sys {
ModifierKind::Fractional => health.maximum() * *accumulated, ModifierKind::Fractional => health.maximum() * *accumulated,
}; };
let damage_contributor = by.and_then(|uid| { let damage_contributor = by.and_then(|uid| {
read_data.uid_allocator.retrieve_entity_internal(uid.0).map( read_data
|entity| { .uid_allocator
DamageContributor::new( .retrieve_entity_internal(uid.0)
uid, .map(|entity| {
read_data.groups.get(entity).cloned(), DamageContributor::new(uid, read_data.groups.get(entity).cloned())
) })
},
)
}); });
server_emitter.emit(ServerEvent::HealthChange { server_emitter.emit(ServerEvent::HealthChange {
entity, entity,
@ -312,13 +366,11 @@ impl<'a> System<'a> for Sys {
// Apply energy change only once per second, per energy, or // Apply energy change only once per second, per energy, or
// when a buff is removed // when a buff is removed
if accumulated.abs() > rate.abs().min(10.0) if accumulated.abs() > rate.abs().min(10.0)
|| buff.time.map_or(false, |dur| dur == Duration::default()) || buff_time.map_or(false, |dur| dur == Duration::default())
{ {
let amount = match *kind { let amount = match *kind {
ModifierKind::Additive => *accumulated, ModifierKind::Additive => *accumulated,
ModifierKind::Fractional => { ModifierKind::Fractional => energy.maximum() as f32 * *accumulated,
energy.maximum() as f32 * *accumulated
},
}; };
server_emitter.emit(ServerEvent::EnergyChange { server_emitter.emit(ServerEvent::EnergyChange {
entity, entity,
@ -382,8 +434,7 @@ impl<'a> System<'a> for Sys {
// Potential progress towards target fraction, if // Potential progress towards target fraction, if
// target_fraction ~ 1.0 then set progress to 1.0 to avoid // target_fraction ~ 1.0 then set progress to 1.0 to avoid
// divide by zero // divide by zero
let progress = if (1.0 - *target_fraction).abs() > f32::EPSILON let progress = if (1.0 - *target_fraction).abs() > f32::EPSILON {
{
(1.0 - potential_fraction) / (1.0 - *target_fraction) (1.0 - potential_fraction) / (1.0 - *target_fraction)
} else { } else {
1.0 1.0
@ -416,34 +467,6 @@ impl<'a> System<'a> for Sys {
stat.friction_modifier *= *gf; stat.friction_modifier *= *gf;
}, },
}; };
}
}
}
// Remove buffs that expire
if !expired_buffs.is_empty() {
server_emitter.emit(ServerEvent::Buff {
entity,
buff_change: BuffChange::RemoveById(expired_buffs),
});
}
// Remove buffs that don't persist on death
if health.is_dead {
server_emitter.emit(ServerEvent::Buff {
entity,
buff_change: BuffChange::RemoveByCategory {
all_required: vec![],
any_required: vec![],
none_required: vec![BuffCategory::PersistOnDeath],
},
});
}
}
// Turned back to true
buffs.set_event_emission(true);
stats.set_event_emission(true);
}
} }
fn tick_buff(id: u64, buff: &mut Buff, dt: f32, mut expire_buff: impl FnMut(u64)) { fn tick_buff(id: u64, buff: &mut Buff, dt: f32, mut expire_buff: impl FnMut(u64)) {