Buffs now get removed on death by default. Buffs are now required to have either the 'Buff' or 'Debuff' tag. RemoveByCategory function now has support for blacklisting certain categories. Support for UI stuffs.

This commit is contained in:
Sam 2020-10-12 19:48:25 -05:00
parent 6495684dc2
commit e83e219d4b
6 changed files with 77 additions and 20 deletions

View File

@ -41,6 +41,7 @@ pub enum BuffCategoryId {
Divine, Divine,
Debuff, Debuff,
Buff, Buff,
PersistOnDeath,
} }
/// Data indicating and configuring behaviour of a de/buff. /// Data indicating and configuring behaviour of a de/buff.
@ -93,9 +94,12 @@ pub enum BuffChange {
RemoveByIndex(Vec<usize>, Vec<usize>), RemoveByIndex(Vec<usize>, Vec<usize>),
/// Removes buffs of these categories (first vec is of categories of which /// 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 /// all are required, second vec is of categories of which at least one is
/// required) Note that this functionality is currently untested and /// required, third vec is of categories that will not be removed)
/// should be tested when doing so is possible RemoveByCategory {
RemoveByCategory(Vec<BuffCategoryId>, Vec<BuffCategoryId>), required: Vec<BuffCategoryId>,
optional: Vec<BuffCategoryId>,
blacklisted: Vec<BuffCategoryId>,
},
} }
/// Source of the de/buff /// Source of the de/buff
@ -173,6 +177,13 @@ impl Buff {
duration, duration,
), ),
}; };
assert_eq!(
cat_ids
.iter()
.any(|cat| *cat == BuffCategoryId::Buff || *cat == BuffCategoryId::Debuff),
true,
"Buff must have either buff or debuff category."
);
Buff { Buff {
id, id,
cat_ids, cat_ids,

View File

@ -1,5 +1,8 @@
use crate::{ use crate::{
comp::{BuffChange, BuffEffect, BuffSource, Buffs, HealthChange, HealthSource}, comp::{
BuffCategoryId, BuffChange, BuffEffect, BuffSource, Buffs, HealthChange, HealthSource,
Stats,
},
event::{EventBus, ServerEvent}, event::{EventBus, ServerEvent},
state::DeltaTime, state::DeltaTime,
sync::Uid, sync::Uid,
@ -14,12 +17,13 @@ impl<'a> System<'a> for Sys {
Read<'a, DeltaTime>, Read<'a, DeltaTime>,
Read<'a, EventBus<ServerEvent>>, Read<'a, EventBus<ServerEvent>>,
ReadStorage<'a, Uid>, ReadStorage<'a, Uid>,
ReadStorage<'a, Stats>,
WriteStorage<'a, Buffs>, WriteStorage<'a, Buffs>,
); );
fn run(&mut self, (dt, server_bus, uids, mut buffs): Self::SystemData) { fn run(&mut self, (dt, server_bus, uids, stats, mut buffs): Self::SystemData) {
let mut server_emitter = server_bus.emitter(); let mut server_emitter = server_bus.emitter();
for (uid, mut buffs) in (&uids, &mut buffs.restrict_mut()).join() { for (uid, stat, mut buffs) in (&uids, &stats, &mut buffs.restrict_mut()).join() {
let buff_comp = buffs.get_mut_unchecked(); let buff_comp = buffs.get_mut_unchecked();
let (mut active_buff_indices_for_removal, mut inactive_buff_indices_for_removal) = let (mut active_buff_indices_for_removal, mut inactive_buff_indices_for_removal) =
(Vec::<usize>::new(), Vec::<usize>::new()); (Vec::<usize>::new(), Vec::<usize>::new());
@ -95,6 +99,7 @@ impl<'a> System<'a> for Sys {
}; };
} }
} }
server_emitter.emit(ServerEvent::Buff { server_emitter.emit(ServerEvent::Buff {
uid: *uid, uid: *uid,
buff_change: BuffChange::RemoveByIndex( buff_change: BuffChange::RemoveByIndex(
@ -102,6 +107,17 @@ impl<'a> System<'a> for Sys {
inactive_buff_indices_for_removal, inactive_buff_indices_for_removal,
), ),
}); });
if stat.is_dead {
server_emitter.emit(ServerEvent::Buff {
uid: *uid,
buff_change: BuffChange::RemoveByCategory {
required: vec![],
optional: vec![],
blacklisted: vec![BuffCategoryId::PersistOnDeath],
},
});
}
} }
} }
} }

View File

@ -159,7 +159,7 @@ impl<'a> System<'a> for Sys {
strength: attack.base_damage as f32, strength: attack.base_damage as f32,
duration: Some(Duration::from_secs(10)), duration: Some(Duration::from_secs(10)),
}, },
vec![buff::BuffCategoryId::Physical], vec![buff::BuffCategoryId::Physical, buff::BuffCategoryId::Debuff],
buff::BuffSource::Character { by: *uid }, buff::BuffSource::Character { by: *uid },
)), )),
}); });

View File

@ -758,7 +758,11 @@ pub fn handle_buff(server: &mut Server, uid: Uid, buff_change: buff::BuffChange)
} }
} }
}, },
BuffChange::RemoveByCategory(all_required, any_required) => { BuffChange::RemoveByCategory {
required: all_required,
optional: any_required,
blacklisted: none_required,
} => {
for (i, buff) in buffs.active_buffs.iter().enumerate() { for (i, buff) in buffs.active_buffs.iter().enumerate() {
let mut required_met = true; let mut required_met = true;
for required in &all_required { for required in &all_required {
@ -774,7 +778,14 @@ pub fn handle_buff(server: &mut Server, uid: Uid, buff_change: buff::BuffChange)
break; break;
} }
} }
if required_met && any_met { let mut none_met = true;
for none in &none_required {
if buff.cat_ids.iter().any(|cat| cat == none) {
none_met = false;
break;
}
}
if required_met && any_met && none_met {
active_buff_indices_for_removal.push(i); active_buff_indices_for_removal.push(i);
} }
} }

View File

@ -8,7 +8,7 @@ use crate::{
GlobalState, GlobalState,
}; };
use client::Client; use client::Client;
use common::comp::Stats; use common::comp::{self, Buffs};
use conrod_core::{ use conrod_core::{
color, color,
widget::{self, Button, Image, Rectangle, Text}, widget::{self, Button, Image, Rectangle, Text},
@ -24,8 +24,15 @@ widget_ids! {
debuff_test, debuff_test,
} }
} }
pub struct BuffInfo {
id: comp::BuffId,
is_buff: bool,
dur: f32,
}
#[derive(WidgetCommon)] #[derive(WidgetCommon)]
pub struct Buffs<'a> { pub struct BuffsBar<'a> {
client: &'a Client, client: &'a Client,
imgs: &'a Imgs, imgs: &'a Imgs,
fonts: &'a ConrodVoxygenFonts, fonts: &'a ConrodVoxygenFonts,
@ -35,10 +42,10 @@ pub struct Buffs<'a> {
rot_imgs: &'a ImgsRot, rot_imgs: &'a ImgsRot,
tooltip_manager: &'a mut TooltipManager, tooltip_manager: &'a mut TooltipManager,
localized_strings: &'a std::sync::Arc<VoxygenLocalization>, localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
stats: &'a Stats, buffs: &'a Buffs,
} }
impl<'a> Buffs<'a> { impl<'a> BuffsBar<'a> {
#[allow(clippy::too_many_arguments)] // TODO: Pending review in #587 #[allow(clippy::too_many_arguments)] // TODO: Pending review in #587
pub fn new( pub fn new(
client: &'a Client, client: &'a Client,
@ -48,7 +55,7 @@ impl<'a> Buffs<'a> {
rot_imgs: &'a ImgsRot, rot_imgs: &'a ImgsRot,
tooltip_manager: &'a mut TooltipManager, tooltip_manager: &'a mut TooltipManager,
localized_strings: &'a std::sync::Arc<VoxygenLocalization>, localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
stats: &'a Stats, buffs: &'a Buffs,
) -> Self { ) -> Self {
Self { Self {
client, client,
@ -59,7 +66,7 @@ impl<'a> Buffs<'a> {
rot_imgs, rot_imgs,
tooltip_manager, tooltip_manager,
localized_strings, localized_strings,
stats, buffs,
} }
} }
} }
@ -68,7 +75,7 @@ pub struct State {
ids: Ids, ids: Ids,
} }
impl<'a> Widget for Buffs<'a> { impl<'a> Widget for BuffsBar<'a> {
type Event = (); type Event = ();
type State = State; type State = State;
type Style = (); type Style = ();
@ -123,3 +130,14 @@ impl<'a> Widget for Buffs<'a> {
.set(state.ids.buff_test, ui); .set(state.ids.buff_test, ui);
} }
} }
fn get_buff_info(buff: comp::Buff) -> BuffInfo {
BuffInfo {
id: buff.id,
is_buff: buff
.cat_ids
.iter()
.any(|cat| *cat == comp::BuffCategoryId::Buff),
dur: buff.time.map(|dur| dur.as_secs_f32()).unwrap_or(100.0),
}
}

View File

@ -25,7 +25,7 @@ pub use hotbar::{SlotContents as HotbarSlotContents, State as HotbarState};
pub use settings_window::ScaleChange; pub use settings_window::ScaleChange;
use bag::Bag; use bag::Bag;
use buffs::Buffs; use buffs::BuffsBar;
use buttons::Buttons; use buttons::Buttons;
use chat::Chat; use chat::Chat;
use chrono::NaiveTime; use chrono::NaiveTime;
@ -1733,6 +1733,7 @@ impl Hud {
// Bag button and nearby icons // Bag button and nearby icons
let ecs = client.state().ecs(); let ecs = client.state().ecs();
let stats = ecs.read_storage::<comp::Stats>(); let stats = ecs.read_storage::<comp::Stats>();
let buffs = ecs.read_storage::<comp::Buffs>();
if let Some(player_stats) = stats.get(client.entity()) { if let Some(player_stats) = stats.get(client.entity()) {
match Buttons::new( match Buttons::new(
client, client,
@ -1758,8 +1759,8 @@ impl Hud {
} }
// Buffs and Debuffs // Buffs and Debuffs
if let Some(player_stats) = stats.get(client.entity()) { if let Some(player_buffs) = buffs.get(client.entity()) {
match Buffs::new( match BuffsBar::new(
client, client,
&self.imgs, &self.imgs,
&self.fonts, &self.fonts,
@ -1767,7 +1768,7 @@ impl Hud {
&self.rot_imgs, &self.rot_imgs,
tooltip_manager, tooltip_manager,
&self.voxygen_i18n, &self.voxygen_i18n,
&player_stats, &player_buffs,
) )
.set(self.ids.buffs, ui_widgets) .set(self.ids.buffs, ui_widgets)
{ {