diff --git a/common/src/comp/buff.rs b/common/src/comp/buff.rs index 24c13a40d7..8a8338c605 100644 --- a/common/src/comp/buff.rs +++ b/common/src/comp/buff.rs @@ -29,14 +29,14 @@ pub enum BuffId { /// De/buff category ID. /// Similar to `BuffId`, but to mark a category (for more generic usage, like /// positive/negative buffs). -#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)] +#[derive(Clone, Copy, Eq, PartialEq, Debug, Serialize, Deserialize)] pub enum BuffCategoryId { Natural, Physical, Magical, Divine, - Negative, - Positive, + Debuff, + Buff, } /// Data indicating and configuring behaviour of a de/buff. @@ -83,8 +83,14 @@ pub enum BuffChange { Add(Buff), /// Removes all buffs with this ID. RemoveById(BuffId), - /// Removes buff of this index + /// Removes buffs of these indices (first vec is for active buffs, second is + /// for inactive buffs) RemoveByIndex(Vec<usize>, Vec<usize>), + /// Removes buffs of these categories (first vec is of categories of which + /// all are required, second vec is of categories of which at least one is + /// required) Note that this functionality is currently untested and + /// should be tested when doing so is possible + RemoveByCategory(Vec<BuffCategoryId>, Vec<BuffCategoryId>), } /// Source of the de/buff diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index 3cfb11af64..8ac6ed2ed2 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -684,8 +684,9 @@ pub fn handle_buff(server: &mut Server, uid: Uid, buff_change: buff::BuffChange) let mut stats = ecs.write_storage::<comp::Stats>(); let (mut active_buff_indices_for_removal, mut inactive_buff_indices_for_removal) = (Vec::new(), Vec::new()); + use buff::BuffChange; match buff_change { - buff::BuffChange::Add(new_buff) => { + BuffChange::Add(new_buff) => { if buffs.active_buffs.is_empty() { add_buff_effects(new_buff.clone(), stats.get_mut(entity)); buffs.active_buffs.push(new_buff); @@ -716,11 +717,11 @@ pub fn handle_buff(server: &mut Server, uid: Uid, buff_change: buff::BuffChange) } } }, - buff::BuffChange::RemoveByIndex(active_indices, inactive_indices) => { + BuffChange::RemoveByIndex(active_indices, inactive_indices) => { active_buff_indices_for_removal = active_indices; inactive_buff_indices_for_removal = inactive_indices; }, - buff::BuffChange::RemoveById(id) => { + 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) { @@ -733,6 +734,54 @@ pub fn handle_buff(server: &mut Server, uid: Uid, buff_change: buff::BuffChange) } } }, + BuffChange::RemoveByCategory(all_required, any_required) => { + for i in 0..buffs.active_buffs.len() { + let mut required_met = true; + for required in &all_required { + if !buffs.active_buffs[i] + .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) { + any_met = true; + break; + } + } + if required_met && any_met { + active_buff_indices_for_removal.push(i); + } + } + for i in 0..buffs.inactive_buffs.len() { + let mut required_met = true; + for required in &all_required { + if !buffs.inactive_buffs[i] + .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) { + any_met = true; + break; + } + } + if required_met && any_met { + inactive_buff_indices_for_removal.push(i); + } + } + }, } let mut removed_active_buff_ids = Vec::new(); while !active_buff_indices_for_removal.is_empty() {