mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Creatures and playrs now have buffs component, buffs that expire now only end their particular buff instead of every buff with the same type.
This commit is contained in:
parent
c50063ad0c
commit
125de0b46e
@ -44,7 +44,7 @@ pub enum BuffCategoryId {
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum BuffEffect {
|
||||
/// Periodically damages or heals entity
|
||||
RepeatedHealthChange { rate: f32, accumulated: f32 },
|
||||
HealthChangeOverTime { rate: f32, accumulated: f32 },
|
||||
/// Changes name on_add/on_remove
|
||||
NameChange { prefix: String },
|
||||
}
|
||||
@ -104,9 +104,9 @@ pub enum BuffSource {
|
||||
/// Component holding all de/buffs that gets resolved each tick.
|
||||
/// On each tick, remaining time of buffs get lowered and
|
||||
/// buff effect of each buff is applied or not, depending on the `BuffEffect`
|
||||
/// (specs system will decide based on `BuffEffect`, to simplify implementation).
|
||||
/// TODO: Something like `once` flag for `Buff` to remove the dependence on
|
||||
/// `BuffEffect` enum?
|
||||
/// (specs system will decide based on `BuffEffect`, to simplify
|
||||
/// implementation). TODO: Something like `once` flag for `Buff` to remove the
|
||||
/// dependence on `BuffEffect` enum?
|
||||
///
|
||||
/// In case of one-time buffs, buff effects will be applied on addition
|
||||
/// and undone on removal of the buff (by the specs system).
|
||||
|
@ -23,13 +23,13 @@ impl<'a> System<'a> for Sys {
|
||||
fn run(&mut self, (entities, dt, mut stats, mut buffs): Self::SystemData) {
|
||||
for (entity, mut buffs) in (&entities, &mut buffs.restrict_mut()).join() {
|
||||
let buff_comp = buffs.get_mut_unchecked();
|
||||
let mut buffs_for_removal = Vec::new();
|
||||
let mut buff_indices_for_removal = Vec::new();
|
||||
// Tick all de/buffs on a Buffs component.
|
||||
for active_buff in &mut buff_comp.buffs {
|
||||
for i in 0..buff_comp.buffs.len() {
|
||||
// First, tick the buff and subtract delta from it
|
||||
// and return how much "real" time the buff took (for tick independence).
|
||||
// TODO: handle delta for "indefinite" buffs, i.e. time since they got removed.
|
||||
let buff_delta = if let Some(remaining_time) = &mut active_buff.time {
|
||||
let buff_delta = if let Some(remaining_time) = &mut buff_comp.buffs[i].time {
|
||||
let pre_tick = remaining_time.as_secs_f32();
|
||||
let new_duration = remaining_time.checked_sub(Duration::from_secs_f32(dt.0));
|
||||
let post_tick = if let Some(dur) = new_duration {
|
||||
@ -38,9 +38,8 @@ impl<'a> System<'a> for Sys {
|
||||
dur.as_secs_f32()
|
||||
} else {
|
||||
// The buff has expired.
|
||||
// Mark it for removal.
|
||||
// TODO: This removes by ID! better method required
|
||||
buffs_for_removal.push(active_buff.id.clone());
|
||||
// Remove it.
|
||||
buff_indices_for_removal.push(i);
|
||||
0.0
|
||||
};
|
||||
pre_tick - post_tick
|
||||
@ -52,10 +51,10 @@ impl<'a> System<'a> for Sys {
|
||||
};
|
||||
|
||||
// Now, execute the buff, based on it's delta
|
||||
for effect in &mut active_buff.effects {
|
||||
for effect in &mut buff_comp.buffs[i].effects {
|
||||
match effect {
|
||||
// Only add an effect here if it is continuous or it is not immediate
|
||||
BuffEffect::RepeatedHealthChange { rate, accumulated } => {
|
||||
BuffEffect::HealthChangeOverTime { rate, accumulated } => {
|
||||
*accumulated += *rate * buff_delta;
|
||||
// Apply only 0.5 or higher damage
|
||||
if accumulated.abs() > 5.0 {
|
||||
@ -73,11 +72,16 @@ impl<'a> System<'a> for Sys {
|
||||
};
|
||||
}
|
||||
}
|
||||
// Truly mark expired buffs for removal.
|
||||
// TODO: Review this, as it is ugly.
|
||||
/*for to_remove in buffs_for_removal {
|
||||
buff_comp.remove_buff_by_id(to_remove);
|
||||
}*/
|
||||
// Remove buffs that have expired.
|
||||
// Since buffs are added into this vec as it iterates up through the list, it
|
||||
// will be in order of increasing values. Therefore to avoid
|
||||
// removing the incorrect buff, removal will start from the greatest index
|
||||
// value, which is the last in this vec.
|
||||
while !buff_indices_for_removal.is_empty() {
|
||||
if let Some(i) = buff_indices_for_removal.pop() {
|
||||
buff_comp.buffs.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
comp::{
|
||||
buff, group, Attacking, Body, CharacterState, Damage, DamageSource, HealthChange, HealthSource,
|
||||
Loadout, Ori, Pos, Scale, Stats,
|
||||
buff, group, Attacking, Body, CharacterState, Damage, DamageSource, HealthChange,
|
||||
HealthSource, Loadout, Ori, Pos, Scale, Stats,
|
||||
},
|
||||
event::{EventBus, LocalEvent, ServerEvent},
|
||||
metrics::SysMetrics,
|
||||
@ -158,9 +158,9 @@ impl<'a> System<'a> for Sys {
|
||||
id: buff::BuffId::Bleeding,
|
||||
cat_ids: vec![buff::BuffCategoryId::Physical],
|
||||
time: Some(Duration::from_millis(2000)),
|
||||
effects: vec![buff::BuffEffect::RepeatedHealthChange {
|
||||
rate: 50.0,
|
||||
accumulated: 0.0
|
||||
effects: vec![buff::BuffEffect::HealthChangeOverTime {
|
||||
rate: 10.0,
|
||||
accumulated: 0.0,
|
||||
}],
|
||||
}),
|
||||
});
|
||||
|
@ -6,8 +6,8 @@ use crate::{
|
||||
use common::{
|
||||
assets::Asset,
|
||||
comp::{
|
||||
self,
|
||||
buff, chat::{KillSource, KillType},
|
||||
self, buff,
|
||||
chat::{KillSource, KillType},
|
||||
object, Alignment, Body, Damage, DamageSource, Group, HealthChange, HealthSource, Item,
|
||||
Player, Pos, Stats,
|
||||
},
|
||||
@ -675,7 +675,7 @@ pub fn handle_level_up(server: &mut Server, entity: EcsEntity, new_level: u32) {
|
||||
));
|
||||
}
|
||||
|
||||
pub fn handle_buff(server: &mut Server, uid: Uid, buff: buff::BuffChange ) {
|
||||
pub fn handle_buff(server: &mut Server, uid: Uid, buff: buff::BuffChange) {
|
||||
let ecs = &server.state.ecs();
|
||||
let mut buffs_all = ecs.write_storage::<comp::Buffs>();
|
||||
if let Some(entity) = ecs.entity_from_uid(uid.into()) {
|
||||
@ -706,7 +706,8 @@ pub fn handle_buff(server: &mut Server, uid: Uid, buff: buff::BuffChange ) {
|
||||
let buff = buffs.buffs.remove(i);
|
||||
for effect in &buff.effects {
|
||||
match effect {
|
||||
// Only remove an effect here if its effect was not continuously applied
|
||||
// Only remove an effect here if its effect was not continuously
|
||||
// applied
|
||||
buff::BuffEffect::NameChange { prefix } => {
|
||||
if let Some(stats) = stats.get_mut(entity) {
|
||||
stats.name = stats.name.replace(prefix, "");
|
||||
|
@ -8,8 +8,8 @@ use entity_creation::{
|
||||
handle_loaded_character_data, handle_shockwave, handle_shoot,
|
||||
};
|
||||
use entity_manipulation::{
|
||||
handle_buff, handle_damage, handle_destroy, handle_explosion, handle_knockback, handle_land_on_ground,
|
||||
handle_level_up, handle_respawn,
|
||||
handle_buff, handle_damage, handle_destroy, handle_explosion, handle_knockback,
|
||||
handle_land_on_ground, handle_level_up, handle_respawn,
|
||||
};
|
||||
use group_manip::handle_group;
|
||||
use interaction::{handle_lantern, handle_mount, handle_possess, handle_unmount};
|
||||
@ -133,10 +133,7 @@ impl Server {
|
||||
ServerEvent::Chat(msg) => {
|
||||
chat_messages.push(msg);
|
||||
},
|
||||
ServerEvent::Buff {
|
||||
uid,
|
||||
buff,
|
||||
} => handle_buff(self, uid, buff),
|
||||
ServerEvent::Buff { uid, buff } => handle_buff(self, uid, buff),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,6 +111,7 @@ impl StateExt for State {
|
||||
.with(comp::Gravity(1.0))
|
||||
.with(comp::CharacterState::default())
|
||||
.with(loadout)
|
||||
.with(comp::Buffs::default())
|
||||
}
|
||||
|
||||
fn create_object(&mut self, pos: comp::Pos, object: comp::object::Body) -> EcsEntityBuilder {
|
||||
@ -202,6 +203,7 @@ impl StateExt for State {
|
||||
entity,
|
||||
comp::Alignment::Owned(self.read_component_copied(entity).unwrap()),
|
||||
);
|
||||
self.write_component(entity, comp::Buffs::default());
|
||||
|
||||
// Make sure physics components are updated
|
||||
self.write_component(entity, comp::ForceUpdate);
|
||||
|
Loading…
Reference in New Issue
Block a user