mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Buffs from auras no longer need to be mutably accessed every tick in aura system to prevent applying a buff every tick and ensure duration only starts after leaving aura
This commit is contained in:
parent
9efac9957d
commit
8a6a60d5bb
@ -1,5 +1,9 @@
|
||||
#![allow(clippy::nonstandard_macro_braces)] //tmp as of false positive !?
|
||||
use crate::{comp::Stats, resources::Time, uid::Uid};
|
||||
use crate::{
|
||||
comp::{aura::AuraKey, Stats},
|
||||
resources::Time,
|
||||
uid::Uid,
|
||||
};
|
||||
use core::cmp::Ordering;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use hashbrown::HashMap;
|
||||
@ -168,7 +172,7 @@ pub enum BuffCategory {
|
||||
Magical,
|
||||
Divine,
|
||||
PersistOnDeath,
|
||||
FromAura(bool), // bool used to check if buff recently set by aura
|
||||
FromActiveAura(Uid, AuraKey),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
@ -285,7 +289,7 @@ impl Buff {
|
||||
},
|
||||
BuffKind::Potion => {
|
||||
vec![BuffEffect::HealthChangeOverTime {
|
||||
rate: data.strength * dbg!(stats.map_or(1.0, |s| s.heal_multiplier)),
|
||||
rate: data.strength * stats.map_or(1.0, |s| s.heal_multiplier),
|
||||
kind: ModifierKind::Additive,
|
||||
instance,
|
||||
}]
|
||||
@ -366,12 +370,20 @@ impl Buff {
|
||||
BuffKind::PotionSickness => vec![BuffEffect::HealReduction(data.strength)],
|
||||
};
|
||||
let start_time = Time(time.0 + data.delay.unwrap_or(0.0));
|
||||
let end_time = if cat_ids
|
||||
.iter()
|
||||
.any(|cat_id| matches!(cat_id, BuffCategory::FromActiveAura(..)))
|
||||
{
|
||||
None
|
||||
} else {
|
||||
data.duration.map(|dur| Time(start_time.0 + dur))
|
||||
};
|
||||
Buff {
|
||||
kind,
|
||||
data,
|
||||
cat_ids,
|
||||
start_time,
|
||||
end_time: data.duration.map(|dur| Time(start_time.0 + dur)),
|
||||
end_time,
|
||||
effects,
|
||||
source,
|
||||
}
|
||||
|
@ -33,45 +33,32 @@ pub struct ReadData<'a> {
|
||||
groups: ReadStorage<'a, Group>,
|
||||
uids: ReadStorage<'a, Uid>,
|
||||
stats: ReadStorage<'a, Stats>,
|
||||
buffs: ReadStorage<'a, Buffs>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Sys;
|
||||
impl<'a> System<'a> for Sys {
|
||||
type SystemData = (
|
||||
ReadData<'a>,
|
||||
WriteStorage<'a, Auras>,
|
||||
WriteStorage<'a, Buffs>,
|
||||
);
|
||||
type SystemData = (ReadData<'a>, WriteStorage<'a, Auras>);
|
||||
|
||||
const NAME: &'static str = "aura";
|
||||
const ORIGIN: Origin = Origin::Common;
|
||||
const PHASE: Phase = Phase::Create;
|
||||
|
||||
fn run(_job: &mut Job<Self>, (read_data, mut auras, mut buffs): Self::SystemData) {
|
||||
fn run(_job: &mut Job<Self>, (read_data, mut auras): Self::SystemData) {
|
||||
let mut server_emitter = read_data.server_bus.emitter();
|
||||
let dt = read_data.dt.0;
|
||||
|
||||
auras.set_event_emission(false);
|
||||
buffs.set_event_emission(false);
|
||||
|
||||
// Iterate through all buffs, on any buffs that are from an aura, sets the check
|
||||
// for whether the buff recently set by aura to false
|
||||
for (_, mut buffs_comp) in (&read_data.entities, &mut buffs).join() {
|
||||
for (_, buff) in buffs_comp.buffs.iter_mut() {
|
||||
if let Some(cat_id) = buff
|
||||
.cat_ids
|
||||
.iter_mut()
|
||||
.find(|cat_id| matches!(cat_id, BuffCategory::FromAura(true)))
|
||||
{
|
||||
*cat_id = BuffCategory::FromAura(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate through all entities with an aura
|
||||
for (entity, pos, mut auras_comp) in
|
||||
(&read_data.entities, &read_data.positions, &mut auras).join()
|
||||
for (entity, pos, mut auras_comp, uid) in (
|
||||
&read_data.entities,
|
||||
&read_data.positions,
|
||||
&mut auras,
|
||||
&read_data.uids,
|
||||
)
|
||||
.join()
|
||||
{
|
||||
let mut expired_auras = Vec::<AuraKey>::new();
|
||||
// Iterate through the auras attached to this entity
|
||||
@ -108,7 +95,7 @@ impl<'a> System<'a> for Sys {
|
||||
})
|
||||
});
|
||||
target_iter.for_each(|(target, target_pos, health, target_uid, stats)| {
|
||||
let mut target_buffs = match buffs.get_mut(target) {
|
||||
let target_buffs = match read_data.buffs.get(target) {
|
||||
Some(buff) => buff,
|
||||
None => return,
|
||||
};
|
||||
@ -135,10 +122,12 @@ impl<'a> System<'a> for Sys {
|
||||
|
||||
if is_target {
|
||||
activate_aura(
|
||||
key,
|
||||
aura,
|
||||
*uid,
|
||||
target,
|
||||
health,
|
||||
&mut target_buffs,
|
||||
target_buffs,
|
||||
stats,
|
||||
&read_data,
|
||||
&mut server_emitter,
|
||||
@ -155,17 +144,18 @@ impl<'a> System<'a> for Sys {
|
||||
}
|
||||
}
|
||||
auras.set_event_emission(true);
|
||||
buffs.set_event_emission(true);
|
||||
}
|
||||
}
|
||||
|
||||
#[warn(clippy::pedantic)]
|
||||
//#[warn(clippy::nursery)]
|
||||
fn activate_aura(
|
||||
key: AuraKey,
|
||||
aura: &Aura,
|
||||
applier: Uid,
|
||||
target: EcsEntity,
|
||||
health: &Health,
|
||||
target_buffs: &mut Buffs,
|
||||
target_buffs: &Buffs,
|
||||
stats: Option<&Stats>,
|
||||
read_data: &ReadData,
|
||||
server_emitter: &mut Emitter<ServerEvent>,
|
||||
@ -247,13 +237,9 @@ fn activate_aura(
|
||||
let emit_buff = !target_buffs.buffs.iter().any(|(_, buff)| {
|
||||
buff.cat_ids
|
||||
.iter()
|
||||
.any(|cat_id| matches!(cat_id, BuffCategory::FromAura(_)))
|
||||
.any(|cat_id| matches!(cat_id, BuffCategory::FromActiveAura(uid, aura_key) if *aura_key == key && *uid == applier))
|
||||
&& buff.kind == kind
|
||||
&& buff.data.strength >= data.strength
|
||||
&& buff.end_time.map_or(true, |end| {
|
||||
data.duration
|
||||
.map_or(false, |dur| end.0 >= read_data.time.0 + dur)
|
||||
})
|
||||
});
|
||||
if emit_buff {
|
||||
server_emitter.emit(ServerEvent::Buff {
|
||||
@ -261,31 +247,13 @@ fn activate_aura(
|
||||
buff_change: BuffChange::Add(Buff::new(
|
||||
kind,
|
||||
data,
|
||||
vec![category, BuffCategory::FromAura(true)],
|
||||
vec![category, BuffCategory::FromActiveAura(applier, key)],
|
||||
source,
|
||||
*read_data.time,
|
||||
stats,
|
||||
)),
|
||||
});
|
||||
}
|
||||
// Finds all buffs on target that are from an aura, are of
|
||||
// the same buff kind, and are of at most the same strength.
|
||||
// For any such buffs, marks it as recently applied.
|
||||
for (_, buff) in target_buffs.buffs.iter_mut().filter(|(_, buff)| {
|
||||
buff.cat_ids
|
||||
.iter()
|
||||
.any(|cat_id| matches!(cat_id, BuffCategory::FromAura(_)))
|
||||
&& buff.kind == kind
|
||||
&& buff.data.strength <= data.strength
|
||||
}) {
|
||||
if let Some(cat_id) = buff
|
||||
.cat_ids
|
||||
.iter_mut()
|
||||
.find(|cat_id| matches!(cat_id, BuffCategory::FromAura(false)))
|
||||
{
|
||||
*cat_id = BuffCategory::FromAura(true);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use common::{
|
||||
combat::DamageContributor,
|
||||
comp::{
|
||||
aura::Auras,
|
||||
body::{object, Body},
|
||||
buff::{
|
||||
Buff, BuffCategory, BuffChange, BuffData, BuffEffect, BuffId, BuffKind, BuffSource,
|
||||
@ -9,7 +10,7 @@ use common::{
|
||||
fluid_dynamics::{Fluid, LiquidKind},
|
||||
item::MaterialStatManifest,
|
||||
Energy, Group, Health, HealthChange, Inventory, LightEmitter, ModifierKind, PhysicsState,
|
||||
Stats,
|
||||
Pos, Stats,
|
||||
},
|
||||
event::{Emitter, EventBus, ServerEvent},
|
||||
resources::{DeltaTime, Time},
|
||||
@ -39,6 +40,8 @@ pub struct ReadData<'a> {
|
||||
time: Read<'a, Time>,
|
||||
msm: ReadExpect<'a, MaterialStatManifest>,
|
||||
buffs: ReadStorage<'a, Buffs>,
|
||||
auras: ReadStorage<'a, Auras>,
|
||||
positions: ReadStorage<'a, Pos>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@ -233,6 +236,71 @@ impl<'a> System<'a> for Sys {
|
||||
}
|
||||
|
||||
let mut expired_buffs = Vec::<BuffId>::new();
|
||||
|
||||
// Replace buffs from an active aura with a normal buff when out of range of the
|
||||
// aura
|
||||
buff_comp
|
||||
.buffs
|
||||
.iter()
|
||||
.filter_map(|(id, buff)| {
|
||||
if let Some((uid, aura_key)) = buff.cat_ids.iter().find_map(|cat_id| {
|
||||
if let BuffCategory::FromActiveAura(uid, aura_key) = cat_id {
|
||||
Some((uid, aura_key))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}) {
|
||||
Some((id, buff, uid, aura_key))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.for_each(|(buff_id, buff, uid, aura_key)| {
|
||||
let replace = if let Some(aura_entity) = read_data
|
||||
.uid_allocator
|
||||
.retrieve_entity_internal((*uid).into())
|
||||
{
|
||||
if let Some(aura) = read_data
|
||||
.auras
|
||||
.get(aura_entity)
|
||||
.and_then(|auras| auras.auras.get(*aura_key))
|
||||
{
|
||||
if let (Some(pos), Some(aura_pos)) = (
|
||||
read_data.positions.get(entity),
|
||||
read_data.positions.get(aura_entity),
|
||||
) {
|
||||
pos.0.distance_squared(aura_pos.0) > aura.radius.powi(2)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else {
|
||||
true
|
||||
};
|
||||
if replace {
|
||||
expired_buffs.push(*buff_id);
|
||||
server_emitter.emit(ServerEvent::Buff {
|
||||
entity,
|
||||
buff_change: BuffChange::Add(Buff::new(
|
||||
buff.kind,
|
||||
buff.data,
|
||||
buff.cat_ids
|
||||
.iter()
|
||||
.copied()
|
||||
.filter(|cat_id| {
|
||||
!matches!(cat_id, BuffCategory::FromActiveAura(..))
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
buff.source,
|
||||
*read_data.time,
|
||||
Some(&stat),
|
||||
)),
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
buff_comp.buffs.iter().for_each(|(id, buff)| {
|
||||
if buff.end_time.map_or(false, |end| end.0 < read_data.time.0) {
|
||||
expired_buffs.push(*id)
|
||||
|
Loading…
Reference in New Issue
Block a user