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 !?
|
#![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;
|
use core::cmp::Ordering;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
@ -168,7 +172,7 @@ pub enum BuffCategory {
|
|||||||
Magical,
|
Magical,
|
||||||
Divine,
|
Divine,
|
||||||
PersistOnDeath,
|
PersistOnDeath,
|
||||||
FromAura(bool), // bool used to check if buff recently set by aura
|
FromActiveAura(Uid, AuraKey),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
@ -285,7 +289,7 @@ impl Buff {
|
|||||||
},
|
},
|
||||||
BuffKind::Potion => {
|
BuffKind::Potion => {
|
||||||
vec![BuffEffect::HealthChangeOverTime {
|
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,
|
kind: ModifierKind::Additive,
|
||||||
instance,
|
instance,
|
||||||
}]
|
}]
|
||||||
@ -366,12 +370,20 @@ impl Buff {
|
|||||||
BuffKind::PotionSickness => vec![BuffEffect::HealReduction(data.strength)],
|
BuffKind::PotionSickness => vec![BuffEffect::HealReduction(data.strength)],
|
||||||
};
|
};
|
||||||
let start_time = Time(time.0 + data.delay.unwrap_or(0.0));
|
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 {
|
Buff {
|
||||||
kind,
|
kind,
|
||||||
data,
|
data,
|
||||||
cat_ids,
|
cat_ids,
|
||||||
start_time,
|
start_time,
|
||||||
end_time: data.duration.map(|dur| Time(start_time.0 + dur)),
|
end_time,
|
||||||
effects,
|
effects,
|
||||||
source,
|
source,
|
||||||
}
|
}
|
||||||
|
@ -33,45 +33,32 @@ pub struct ReadData<'a> {
|
|||||||
groups: ReadStorage<'a, Group>,
|
groups: ReadStorage<'a, Group>,
|
||||||
uids: ReadStorage<'a, Uid>,
|
uids: ReadStorage<'a, Uid>,
|
||||||
stats: ReadStorage<'a, Stats>,
|
stats: ReadStorage<'a, Stats>,
|
||||||
|
buffs: ReadStorage<'a, Buffs>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Sys;
|
pub struct Sys;
|
||||||
impl<'a> System<'a> for Sys {
|
impl<'a> System<'a> for Sys {
|
||||||
type SystemData = (
|
type SystemData = (ReadData<'a>, WriteStorage<'a, Auras>);
|
||||||
ReadData<'a>,
|
|
||||||
WriteStorage<'a, Auras>,
|
|
||||||
WriteStorage<'a, Buffs>,
|
|
||||||
);
|
|
||||||
|
|
||||||
const NAME: &'static str = "aura";
|
const NAME: &'static str = "aura";
|
||||||
const ORIGIN: Origin = Origin::Common;
|
const ORIGIN: Origin = Origin::Common;
|
||||||
const PHASE: Phase = Phase::Create;
|
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 mut server_emitter = read_data.server_bus.emitter();
|
||||||
let dt = read_data.dt.0;
|
let dt = read_data.dt.0;
|
||||||
|
|
||||||
auras.set_event_emission(false);
|
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
|
// Iterate through all entities with an aura
|
||||||
for (entity, pos, mut auras_comp) in
|
for (entity, pos, mut auras_comp, uid) in (
|
||||||
(&read_data.entities, &read_data.positions, &mut auras).join()
|
&read_data.entities,
|
||||||
|
&read_data.positions,
|
||||||
|
&mut auras,
|
||||||
|
&read_data.uids,
|
||||||
|
)
|
||||||
|
.join()
|
||||||
{
|
{
|
||||||
let mut expired_auras = Vec::<AuraKey>::new();
|
let mut expired_auras = Vec::<AuraKey>::new();
|
||||||
// Iterate through the auras attached to this entity
|
// 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)| {
|
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,
|
Some(buff) => buff,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
@ -135,10 +122,12 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
if is_target {
|
if is_target {
|
||||||
activate_aura(
|
activate_aura(
|
||||||
|
key,
|
||||||
aura,
|
aura,
|
||||||
|
*uid,
|
||||||
target,
|
target,
|
||||||
health,
|
health,
|
||||||
&mut target_buffs,
|
target_buffs,
|
||||||
stats,
|
stats,
|
||||||
&read_data,
|
&read_data,
|
||||||
&mut server_emitter,
|
&mut server_emitter,
|
||||||
@ -155,17 +144,18 @@ impl<'a> System<'a> for Sys {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
auras.set_event_emission(true);
|
auras.set_event_emission(true);
|
||||||
buffs.set_event_emission(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[warn(clippy::pedantic)]
|
#[warn(clippy::pedantic)]
|
||||||
//#[warn(clippy::nursery)]
|
//#[warn(clippy::nursery)]
|
||||||
fn activate_aura(
|
fn activate_aura(
|
||||||
|
key: AuraKey,
|
||||||
aura: &Aura,
|
aura: &Aura,
|
||||||
|
applier: Uid,
|
||||||
target: EcsEntity,
|
target: EcsEntity,
|
||||||
health: &Health,
|
health: &Health,
|
||||||
target_buffs: &mut Buffs,
|
target_buffs: &Buffs,
|
||||||
stats: Option<&Stats>,
|
stats: Option<&Stats>,
|
||||||
read_data: &ReadData,
|
read_data: &ReadData,
|
||||||
server_emitter: &mut Emitter<ServerEvent>,
|
server_emitter: &mut Emitter<ServerEvent>,
|
||||||
@ -247,13 +237,9 @@ fn activate_aura(
|
|||||||
let emit_buff = !target_buffs.buffs.iter().any(|(_, buff)| {
|
let emit_buff = !target_buffs.buffs.iter().any(|(_, buff)| {
|
||||||
buff.cat_ids
|
buff.cat_ids
|
||||||
.iter()
|
.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.kind == kind
|
||||||
&& buff.data.strength >= data.strength
|
&& 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 {
|
if emit_buff {
|
||||||
server_emitter.emit(ServerEvent::Buff {
|
server_emitter.emit(ServerEvent::Buff {
|
||||||
@ -261,31 +247,13 @@ fn activate_aura(
|
|||||||
buff_change: BuffChange::Add(Buff::new(
|
buff_change: BuffChange::Add(Buff::new(
|
||||||
kind,
|
kind,
|
||||||
data,
|
data,
|
||||||
vec![category, BuffCategory::FromAura(true)],
|
vec![category, BuffCategory::FromActiveAura(applier, key)],
|
||||||
source,
|
source,
|
||||||
*read_data.time,
|
*read_data.time,
|
||||||
stats,
|
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::{
|
use common::{
|
||||||
combat::DamageContributor,
|
combat::DamageContributor,
|
||||||
comp::{
|
comp::{
|
||||||
|
aura::Auras,
|
||||||
body::{object, Body},
|
body::{object, Body},
|
||||||
buff::{
|
buff::{
|
||||||
Buff, BuffCategory, BuffChange, BuffData, BuffEffect, BuffId, BuffKind, BuffSource,
|
Buff, BuffCategory, BuffChange, BuffData, BuffEffect, BuffId, BuffKind, BuffSource,
|
||||||
@ -9,7 +10,7 @@ use common::{
|
|||||||
fluid_dynamics::{Fluid, LiquidKind},
|
fluid_dynamics::{Fluid, LiquidKind},
|
||||||
item::MaterialStatManifest,
|
item::MaterialStatManifest,
|
||||||
Energy, Group, Health, HealthChange, Inventory, LightEmitter, ModifierKind, PhysicsState,
|
Energy, Group, Health, HealthChange, Inventory, LightEmitter, ModifierKind, PhysicsState,
|
||||||
Stats,
|
Pos, Stats,
|
||||||
},
|
},
|
||||||
event::{Emitter, EventBus, ServerEvent},
|
event::{Emitter, EventBus, ServerEvent},
|
||||||
resources::{DeltaTime, Time},
|
resources::{DeltaTime, Time},
|
||||||
@ -39,6 +40,8 @@ pub struct ReadData<'a> {
|
|||||||
time: Read<'a, Time>,
|
time: Read<'a, Time>,
|
||||||
msm: ReadExpect<'a, MaterialStatManifest>,
|
msm: ReadExpect<'a, MaterialStatManifest>,
|
||||||
buffs: ReadStorage<'a, Buffs>,
|
buffs: ReadStorage<'a, Buffs>,
|
||||||
|
auras: ReadStorage<'a, Auras>,
|
||||||
|
positions: ReadStorage<'a, Pos>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@ -233,6 +236,71 @@ impl<'a> System<'a> for Sys {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut expired_buffs = Vec::<BuffId>::new();
|
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)| {
|
buff_comp.buffs.iter().for_each(|(id, buff)| {
|
||||||
if buff.end_time.map_or(false, |end| end.0 < read_data.time.0) {
|
if buff.end_time.map_or(false, |end| end.0 < read_data.time.0) {
|
||||||
expired_buffs.push(*id)
|
expired_buffs.push(*id)
|
||||||
|
Loading…
Reference in New Issue
Block a user