mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Auras now apply a buff only once, instead of applying a buff every second.
Also supports for buffs persisting a period of time after leaving the aura. Campfire regen slightly buffed.
This commit is contained in:
parent
ded0cd0302
commit
45dd36be07
@ -77,6 +77,7 @@ pub enum BuffCategory {
|
|||||||
Magical,
|
Magical,
|
||||||
Divine,
|
Divine,
|
||||||
PersistOnDeath,
|
PersistOnDeath,
|
||||||
|
FromAura(bool), // bool used to check freshness of buff being apllied from aura
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use common::{
|
use common::{
|
||||||
comp::{
|
comp::{
|
||||||
aura::{AuraChange, AuraKey, AuraKind, AuraTarget},
|
aura::{AuraChange, AuraKey, AuraKind, AuraTarget},
|
||||||
buff,
|
buff::{self, BuffCategory},
|
||||||
group::Group,
|
group::Group,
|
||||||
Auras, BuffKind, Buffs, CharacterState, Health, Pos,
|
Auras, BuffKind, Buffs, CharacterState, Health, Pos,
|
||||||
},
|
},
|
||||||
@ -25,19 +25,36 @@ pub struct ReadData<'a> {
|
|||||||
char_states: ReadStorage<'a, CharacterState>,
|
char_states: ReadStorage<'a, CharacterState>,
|
||||||
healths: ReadStorage<'a, Health>,
|
healths: ReadStorage<'a, Health>,
|
||||||
groups: ReadStorage<'a, Group>,
|
groups: ReadStorage<'a, Group>,
|
||||||
buffs: ReadStorage<'a, Buffs>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Sys;
|
pub struct Sys;
|
||||||
impl<'a> System<'a> for 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 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);
|
||||||
|
|
||||||
|
// Iterate through all buffs, on any buffs that are from an aura, sets the check
|
||||||
|
// for whether the buff is fresh 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) in
|
||||||
(&read_data.entities, &read_data.positions, &mut auras).join()
|
(&read_data.entities, &read_data.positions, &mut auras).join()
|
||||||
@ -56,10 +73,10 @@ impl<'a> System<'a> for Sys {
|
|||||||
expired_auras.push(key);
|
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.entities,
|
||||||
&read_data.positions,
|
&read_data.positions,
|
||||||
&read_data.buffs,
|
&mut buffs,
|
||||||
&read_data.healths,
|
&read_data.healths,
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
@ -89,35 +106,58 @@ impl<'a> System<'a> for Sys {
|
|||||||
category,
|
category,
|
||||||
source,
|
source,
|
||||||
} => {
|
} => {
|
||||||
// Checks if the buff is not active so it isn't applied
|
let apply_buff = match kind {
|
||||||
// every tick, but rather only once it runs out
|
BuffKind::CampfireHeal => {
|
||||||
// TODO: Check for stronger buff of same kind so it can replace
|
matches!(
|
||||||
// active buff.
|
read_data.char_states.get(target),
|
||||||
if !target_buffs.contains(kind) {
|
Some(CharacterState::Sit)
|
||||||
// Conditions for different buffs are in this match
|
) && health.current() < health.maximum()
|
||||||
// statement
|
},
|
||||||
let apply_buff = match kind {
|
// Add other specific buff conditions here
|
||||||
BuffKind::CampfireHeal => {
|
_ => true,
|
||||||
matches!(
|
};
|
||||||
read_data.char_states.get(target),
|
if apply_buff {
|
||||||
Some(CharacterState::Sit)
|
// Checks that target is not already receiving a buff from an
|
||||||
) && health.current() < health.maximum()
|
// aura, where the buff is of the same kind, and is of at least
|
||||||
},
|
// the same strength
|
||||||
// Add other specific buff conditions here
|
// If no such buff is present, adds the buff
|
||||||
_ => true,
|
let emit_buff = !target_buffs.buffs.iter().any(|(_, buff)| {
|
||||||
};
|
buff.cat_ids.iter().any(|cat_id| {
|
||||||
if apply_buff {
|
matches!(cat_id, BuffCategory::FromAura(_))
|
||||||
|
}) && buff.kind == kind
|
||||||
|
&& buff.data.strength >= data.strength
|
||||||
|
});
|
||||||
|
if emit_buff {
|
||||||
use buff::*;
|
use buff::*;
|
||||||
server_emitter.emit(ServerEvent::Buff {
|
server_emitter.emit(ServerEvent::Buff {
|
||||||
entity: target,
|
entity: target,
|
||||||
buff_change: BuffChange::Add(Buff::new(
|
buff_change: BuffChange::Add(Buff::new(
|
||||||
kind,
|
kind,
|
||||||
data,
|
data,
|
||||||
vec![category],
|
vec![category, BuffCategory::FromAura(true)],
|
||||||
source,
|
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, sets freshness to fresh
|
||||||
|
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,
|
kind,
|
||||||
} => {
|
} => {
|
||||||
*accumulated += *rate * dt;
|
*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
|
// 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())
|
|| buff.time.map_or(false, |dur| dur == Duration::default())
|
||||||
{
|
{
|
||||||
let cause = if *accumulated > 0.0 {
|
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)) {
|
fn tick_buff(id: u64, buff: &mut Buff, dt: f32, mut expire_buff: impl FnMut(u64)) {
|
||||||
|
// If a buff is freshly 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(remaining_time) = &mut buff.time {
|
||||||
if let Some(new_duration) = remaining_time.checked_sub(Duration::from_secs_f32(dt)) {
|
if let Some(new_duration) = remaining_time.checked_sub(Duration::from_secs_f32(dt)) {
|
||||||
// The buff still continues.
|
// The buff still continues.
|
||||||
|
@ -978,7 +978,7 @@ fn handle_spawn_campfire(
|
|||||||
.with(comp::Auras::new(Aura::new(
|
.with(comp::Auras::new(Aura::new(
|
||||||
AuraKind::Buff {
|
AuraKind::Buff {
|
||||||
kind: BuffKind::CampfireHeal,
|
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,
|
category: BuffCategory::Natural,
|
||||||
source: BuffSource::World,
|
source: BuffSource::World,
|
||||||
},
|
},
|
||||||
|
@ -194,7 +194,7 @@ pub fn handle_create_waypoint(server: &mut Server, pos: Vec3<f32>) {
|
|||||||
.with(comp::Auras::new(Aura::new(
|
.with(comp::Auras::new(Aura::new(
|
||||||
AuraKind::Buff {
|
AuraKind::Buff {
|
||||||
kind: BuffKind::CampfireHeal,
|
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,
|
category: BuffCategory::Natural,
|
||||||
source: BuffSource::World,
|
source: BuffSource::World,
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user