mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'sam/improve-aura-buffs' into 'master'
Auras now apply a buff only once, instead of applying a buff every second. See merge request veloren/veloren!1824
This commit is contained in:
commit
a99a78abdb
@ -77,6 +77,7 @@ pub enum BuffCategory {
|
||||
Magical,
|
||||
Divine,
|
||||
PersistOnDeath,
|
||||
FromAura(bool), // bool used to check if buff recently set by aura
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
|
@ -1,7 +1,7 @@
|
||||
use common::{
|
||||
comp::{
|
||||
aura::{AuraChange, AuraKey, AuraKind, AuraTarget},
|
||||
buff,
|
||||
buff::{self, BuffCategory},
|
||||
group::Group,
|
||||
Auras, BuffKind, Buffs, CharacterState, Health, Pos,
|
||||
},
|
||||
@ -25,19 +25,36 @@ pub struct ReadData<'a> {
|
||||
char_states: ReadStorage<'a, CharacterState>,
|
||||
healths: ReadStorage<'a, Health>,
|
||||
groups: ReadStorage<'a, Group>,
|
||||
buffs: ReadStorage<'a, Buffs>,
|
||||
}
|
||||
|
||||
pub struct Sys;
|
||||
impl<'a> System<'a> for Sys {
|
||||
type SystemData = (ReadData<'a>, WriteStorage<'a, Auras>);
|
||||
type SystemData = (
|
||||
ReadData<'a>,
|
||||
WriteStorage<'a, Auras>,
|
||||
WriteStorage<'a, Buffs>,
|
||||
);
|
||||
|
||||
fn run(&mut self, (read_data, mut auras): Self::SystemData) {
|
||||
fn run(&mut self, (read_data, mut auras, mut buffs): Self::SystemData) {
|
||||
let mut server_emitter = read_data.server_bus.emitter();
|
||||
let dt = read_data.dt.0;
|
||||
|
||||
auras.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()
|
||||
@ -56,10 +73,10 @@ impl<'a> System<'a> for Sys {
|
||||
expired_auras.push(key);
|
||||
}
|
||||
}
|
||||
for (target, target_pos, target_buffs, health) in (
|
||||
for (target, target_pos, mut target_buffs, health) in (
|
||||
&read_data.entities,
|
||||
&read_data.positions,
|
||||
&read_data.buffs,
|
||||
&mut buffs,
|
||||
&read_data.healths,
|
||||
)
|
||||
.join()
|
||||
@ -89,35 +106,58 @@ impl<'a> System<'a> for Sys {
|
||||
category,
|
||||
source,
|
||||
} => {
|
||||
// Checks if the buff is not active so it isn't applied
|
||||
// every tick, but rather only once it runs out
|
||||
// TODO: Check for stronger buff of same kind so it can replace
|
||||
// active buff.
|
||||
if !target_buffs.contains(kind) {
|
||||
// Conditions for different buffs are in this match
|
||||
// statement
|
||||
let apply_buff = match kind {
|
||||
BuffKind::CampfireHeal => {
|
||||
matches!(
|
||||
read_data.char_states.get(target),
|
||||
Some(CharacterState::Sit)
|
||||
) && health.current() < health.maximum()
|
||||
},
|
||||
// Add other specific buff conditions here
|
||||
_ => true,
|
||||
};
|
||||
if apply_buff {
|
||||
let apply_buff = match kind {
|
||||
BuffKind::CampfireHeal => {
|
||||
matches!(
|
||||
read_data.char_states.get(target),
|
||||
Some(CharacterState::Sit)
|
||||
) && health.current() < health.maximum()
|
||||
},
|
||||
// Add other specific buff conditions here
|
||||
_ => true,
|
||||
};
|
||||
if apply_buff {
|
||||
// Checks that target is not already receiving a buff from an
|
||||
// aura, where the buff is of the same kind, and is of at least
|
||||
// the same strength
|
||||
// If no such buff is present, adds the buff
|
||||
let emit_buff = !target_buffs.buffs.iter().any(|(_, buff)| {
|
||||
buff.cat_ids.iter().any(|cat_id| {
|
||||
matches!(cat_id, BuffCategory::FromAura(_))
|
||||
}) && buff.kind == kind
|
||||
&& buff.data.strength >= data.strength
|
||||
});
|
||||
if emit_buff {
|
||||
use buff::*;
|
||||
server_emitter.emit(ServerEvent::Buff {
|
||||
entity: target,
|
||||
buff_change: BuffChange::Add(Buff::new(
|
||||
kind,
|
||||
data,
|
||||
vec![category],
|
||||
vec![category, BuffCategory::FromAura(true)],
|
||||
source,
|
||||
)),
|
||||
});
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -99,9 +99,9 @@ impl<'a> System<'a> for Sys {
|
||||
kind,
|
||||
} => {
|
||||
*accumulated += *rate * dt;
|
||||
// Apply damage only once a second (with a minimum of 1 damage), or
|
||||
// Apply health change only once a second or
|
||||
// when a buff is removed
|
||||
if accumulated.abs() > rate.abs().max(10.0)
|
||||
if accumulated.abs() > rate.abs()
|
||||
|| buff.time.map_or(false, |dur| dur == Duration::default())
|
||||
{
|
||||
let cause = if *accumulated > 0.0 {
|
||||
@ -180,6 +180,14 @@ impl<'a> System<'a> for Sys {
|
||||
}
|
||||
|
||||
fn tick_buff(id: u64, buff: &mut Buff, dt: f32, mut expire_buff: impl FnMut(u64)) {
|
||||
// If a buff is recently applied from an aura, do not tick duration
|
||||
if buff
|
||||
.cat_ids
|
||||
.iter()
|
||||
.any(|cat_id| matches!(cat_id, BuffCategory::FromAura(true)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if let Some(remaining_time) = &mut buff.time {
|
||||
if let Some(new_duration) = remaining_time.checked_sub(Duration::from_secs_f32(dt)) {
|
||||
// The buff still continues.
|
||||
|
@ -978,7 +978,7 @@ fn handle_spawn_campfire(
|
||||
.with(comp::Auras::new(Aura::new(
|
||||
AuraKind::Buff {
|
||||
kind: BuffKind::CampfireHeal,
|
||||
data: BuffData::new(0.01, Some(Duration::from_secs(1))),
|
||||
data: BuffData::new(0.02, Some(Duration::from_secs(1))),
|
||||
category: BuffCategory::Natural,
|
||||
source: BuffSource::World,
|
||||
},
|
||||
|
@ -194,7 +194,7 @@ pub fn handle_create_waypoint(server: &mut Server, pos: Vec3<f32>) {
|
||||
.with(comp::Auras::new(Aura::new(
|
||||
AuraKind::Buff {
|
||||
kind: BuffKind::CampfireHeal,
|
||||
data: BuffData::new(0.01, Some(Duration::from_secs(1))),
|
||||
data: BuffData::new(0.02, Some(Duration::from_secs(1))),
|
||||
category: BuffCategory::Natural,
|
||||
source: BuffSource::World,
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user