Addressed comments.

This commit is contained in:
Samuel Keiffer 2020-10-11 16:39:52 -05:00 committed by Sam
parent f096bece5c
commit 60a5346a0b
4 changed files with 30 additions and 54 deletions

View File

@ -126,11 +126,6 @@ pub enum BuffSource {
/// and undone on removal of the buff (by the specs system).
/// Example could be decreasing max health, which, if repeated each tick,
/// would be probably an undesired effect).
///
/// TODO: Make this net/sync-friendly. Events could help there
/// (probably replacing `changes`). Also, the "buff ticking" is really
/// not needed to be synced often, only in case that a buff begins/ends
/// (as the buff ECS system will probably run on a client too).
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
pub struct Buffs {
/// Active de/buffs.

View File

@ -7,11 +7,6 @@ use crate::{
use specs::{Join, Read, ReadStorage, System, WriteStorage};
use std::time::Duration;
/// This system modifies entity stats, changing them using buffs
/// Currently, the system is VERY, VERY CRUDE and SYNC UN-FRIENDLY.
/// It does not use events and uses `Vec`s stored in component.
///
/// TODO: Make this production-quality system/design
pub struct Sys;
impl<'a> System<'a> for Sys {
#[allow(clippy::type_complexity)]
@ -29,11 +24,10 @@ impl<'a> System<'a> for Sys {
let (mut active_buff_indices_for_removal, mut inactive_buff_indices_for_removal) =
(Vec::<usize>::new(), Vec::<usize>::new());
// Tick all de/buffs on a Buffs component.
for i in 0..buff_comp.active_buffs.len() {
for (i, active_buff) in buff_comp.active_buffs.iter_mut().enumerate() {
// 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 buff_comp.active_buffs[i].time {
let buff_delta = if let Some(remaining_time) = &mut active_buff.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 {
@ -49,21 +43,16 @@ impl<'a> System<'a> for Sys {
pre_tick - post_tick
} else {
// The buff is indefinite, and it takes full tick (delta).
// TODO: Delta for indefinite buffs might be shorter since they can get removed
// *during a tick* and this treats it as it always happens on a *tick end*.
dt.0
};
let buff_owner =
if let BuffSource::Character { by: owner } = buff_comp.active_buffs[i].source {
Some(owner)
} else {
None
};
let buff_owner = if let BuffSource::Character { by: owner } = active_buff.source {
Some(owner)
} else {
None
};
// Now, execute the buff, based on it's delta
for effect in &mut buff_comp.active_buffs[i].effects {
#[allow(clippy::single_match)]
// Remove clippy when more effects are added here
for effect in &mut active_buff.effects {
match effect {
// Only add an effect here if it is continuous or it is not immediate
BuffEffect::HealthChangeOverTime { rate, accumulated } => {
@ -85,15 +74,16 @@ impl<'a> System<'a> for Sys {
*accumulated = 0.0;
};
},
_ => {},
BuffEffect::NameChange { .. } => {},
};
}
}
for i in 0..buff_comp.inactive_buffs.len() {
for (i, inactive_buff) in buff_comp.inactive_buffs.iter_mut().enumerate() {
// 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.
if let Some(remaining_time) = &mut buff_comp.inactive_buffs[i].time {
if let Some(remaining_time) = &mut inactive_buff.time {
let new_duration = remaining_time.checked_sub(Duration::from_secs_f32(dt.0));
if new_duration.is_some() {
// The buff still continues.

View File

@ -156,8 +156,8 @@ impl<'a> System<'a> for Sys {
uid: *uid_b,
buff_change: buff::BuffChange::Add(buff::Buff::new(
buff::BuffId::Bleeding {
strength: -damage.healthchange,
duration: Some(Duration::from_millis(10000)),
strength: attack.base_damage as f32,
duration: Some(Duration::from_secs(10)),
},
vec![buff::BuffCategoryId::Physical],
buff::BuffSource::Character { by: *uid },

View File

@ -747,33 +747,29 @@ pub fn handle_buff(server: &mut Server, uid: Uid, buff_change: buff::BuffChange)
},
BuffChange::RemoveById(id) => {
let some_predicate = |current_id: &buff::BuffId| *current_id == id;
for i in 0..buffs.active_buffs.len() {
if some_predicate(&mut buffs.active_buffs[i].id) {
for (i, buff) in buffs.active_buffs.iter().enumerate() {
if some_predicate(&buff.id) {
active_buff_indices_for_removal.push(i);
}
}
for i in 0..buffs.inactive_buffs.len() {
if some_predicate(&mut buffs.inactive_buffs[i].id) {
for (i, buff) in buffs.inactive_buffs.iter().enumerate() {
if some_predicate(&buff.id) {
inactive_buff_indices_for_removal.push(i);
}
}
},
BuffChange::RemoveByCategory(all_required, any_required) => {
for i in 0..buffs.active_buffs.len() {
for (i, buff) in buffs.active_buffs.iter().enumerate() {
let mut required_met = true;
for required in &all_required {
if !buffs.active_buffs[i]
.cat_ids
.iter()
.any(|cat| cat == required)
{
if !buff.cat_ids.iter().any(|cat| cat == required) {
required_met = false;
break;
}
}
let mut any_met = any_required.is_empty();
for any in &any_required {
if !buffs.active_buffs[i].cat_ids.iter().any(|cat| cat == any) {
if !buff.cat_ids.iter().any(|cat| cat == any) {
any_met = true;
break;
}
@ -782,21 +778,17 @@ pub fn handle_buff(server: &mut Server, uid: Uid, buff_change: buff::BuffChange)
active_buff_indices_for_removal.push(i);
}
}
for i in 0..buffs.inactive_buffs.len() {
for (i, buff) in buffs.inactive_buffs.iter().enumerate() {
let mut required_met = true;
for required in &all_required {
if !buffs.inactive_buffs[i]
.cat_ids
.iter()
.any(|cat| cat == required)
{
if !buff.cat_ids.iter().any(|cat| cat == required) {
required_met = false;
break;
}
}
let mut any_met = any_required.is_empty();
for any in &any_required {
if !buffs.inactive_buffs[i].cat_ids.iter().any(|cat| cat == any) {
if !buff.cat_ids.iter().any(|cat| cat == any) {
any_met = true;
break;
}
@ -833,16 +825,15 @@ pub fn handle_buff(server: &mut Server, uid: Uid, buff_change: buff::BuffChange)
}
let mut new_active_buff = None::<buff::Buff>;
let mut replacement_buff_index = 0;
for i in 0..buffs.inactive_buffs.len() {
let inactive_buff = buffs.inactive_buffs[i].clone();
for (i, inactive_buff) in buffs.inactive_buffs.iter().enumerate() {
if discriminant(&buff_id) == discriminant(&inactive_buff.id) {
if let Some(ref buff) = new_active_buff {
if determine_replace_active_buff(buff.clone(), inactive_buff.clone()) {
new_active_buff = Some(inactive_buff);
new_active_buff = Some(inactive_buff.clone());
replacement_buff_index = i;
}
} else {
new_active_buff = Some(inactive_buff);
new_active_buff = Some(inactive_buff.clone());
replacement_buff_index = i;
}
}
@ -894,17 +885,17 @@ fn determine_replace_active_buff(active_buff: buff::Buff, new_buff: buff::Buff)
fn add_buff_effects(buff: buff::Buff, mut stats: Option<&mut Stats>) {
for effect in &buff.effects {
#[allow(clippy::single_match)] // Remove clippy when there are more buff effects here
use buff::BuffEffect;
match effect {
// Only add an effect here if it is immediate and is not continuous
buff::BuffEffect::NameChange { prefix } => {
BuffEffect::NameChange { prefix } => {
if let Some(ref mut stats) = stats {
let mut pref = String::from(prefix);
pref.push_str(&stats.name);
stats.name = pref;
}
},
_ => {},
BuffEffect::HealthChangeOverTime { .. } => {},
}
}
}