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 b31c6877b4
commit 007d3c09ac
6 changed files with 77 additions and 20 deletions

View File

@ -41,6 +41,7 @@ pub enum BuffCategoryId {
Divine,
Debuff,
Buff,
PersistOnDeath,
}
/// Data indicating and configuring behaviour of a de/buff.
@ -93,9 +94,12 @@ pub enum BuffChange {
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>),
/// required, third vec is of categories that will not be removed)
RemoveByCategory {
required: Vec<BuffCategoryId>,
optional: Vec<BuffCategoryId>,
blacklisted: Vec<BuffCategoryId>,
},
}
/// Source of the de/buff
@ -173,6 +177,13 @@ impl Buff {
duration,
),
};
assert_eq!(
cat_ids
.iter()
.any(|cat| *cat == BuffCategoryId::Buff || *cat == BuffCategoryId::Debuff),
true,
"Buff must have either buff or debuff category."
);
Buff {
id,
cat_ids,

View File

@ -1,5 +1,8 @@
use crate::{
comp::{BuffChange, BuffEffect, BuffSource, Buffs, HealthChange, HealthSource},
comp::{
BuffCategoryId, BuffChange, BuffEffect, BuffSource, Buffs, HealthChange, HealthSource,
Stats,
},
event::{EventBus, ServerEvent},
state::DeltaTime,
sync::Uid,
@ -14,12 +17,13 @@ impl<'a> System<'a> for Sys {
Read<'a, DeltaTime>,
Read<'a, EventBus<ServerEvent>>,
ReadStorage<'a, Uid>,
ReadStorage<'a, Stats>,
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();
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 (mut active_buff_indices_for_removal, mut inactive_buff_indices_for_removal) =
(Vec::<usize>::new(), Vec::<usize>::new());
@ -95,6 +99,7 @@ impl<'a> System<'a> for Sys {
};
}
}
server_emitter.emit(ServerEvent::Buff {
uid: *uid,
buff_change: BuffChange::RemoveByIndex(
@ -102,6 +107,17 @@ impl<'a> System<'a> for Sys {
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,
duration: Some(Duration::from_secs(10)),
},
vec![buff::BuffCategoryId::Physical],
vec![buff::BuffCategoryId::Physical, buff::BuffCategoryId::Debuff],
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() {
let mut required_met = true;
for required in &all_required {
@ -774,7 +778,14 @@ pub fn handle_buff(server: &mut Server, uid: Uid, buff_change: buff::BuffChange)
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);
}
}

View File

@ -8,7 +8,7 @@ use crate::{
GlobalState,
};
use client::Client;
use common::comp::Stats;
use common::comp::{self, Buffs};
use conrod_core::{
color,
widget::{self, Button, Image, Rectangle, Text},
@ -24,8 +24,15 @@ widget_ids! {
debuff_test,
}
}
pub struct BuffInfo {
id: comp::BuffId,
is_buff: bool,
dur: f32,
}
#[derive(WidgetCommon)]
pub struct Buffs<'a> {
pub struct BuffsBar<'a> {
client: &'a Client,
imgs: &'a Imgs,
fonts: &'a ConrodVoxygenFonts,
@ -35,10 +42,10 @@ pub struct Buffs<'a> {
rot_imgs: &'a ImgsRot,
tooltip_manager: &'a mut TooltipManager,
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
pub fn new(
client: &'a Client,
@ -48,7 +55,7 @@ impl<'a> Buffs<'a> {
rot_imgs: &'a ImgsRot,
tooltip_manager: &'a mut TooltipManager,
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
stats: &'a Stats,
buffs: &'a Buffs,
) -> Self {
Self {
client,
@ -59,7 +66,7 @@ impl<'a> Buffs<'a> {
rot_imgs,
tooltip_manager,
localized_strings,
stats,
buffs,
}
}
}
@ -68,7 +75,7 @@ pub struct State {
ids: Ids,
}
impl<'a> Widget for Buffs<'a> {
impl<'a> Widget for BuffsBar<'a> {
type Event = ();
type State = State;
type Style = ();
@ -123,3 +130,14 @@ impl<'a> Widget for Buffs<'a> {
.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;
use bag::Bag;
use buffs::Buffs;
use buffs::BuffsBar;
use buttons::Buttons;
use chat::Chat;
use chrono::NaiveTime;
@ -1733,6 +1733,7 @@ impl Hud {
// Bag button and nearby icons
let ecs = client.state().ecs();
let stats = ecs.read_storage::<comp::Stats>();
let buffs = ecs.read_storage::<comp::Buffs>();
if let Some(player_stats) = stats.get(client.entity()) {
match Buttons::new(
client,
@ -1758,8 +1759,8 @@ impl Hud {
}
// Buffs and Debuffs
if let Some(player_stats) = stats.get(client.entity()) {
match Buffs::new(
if let Some(player_buffs) = buffs.get(client.entity()) {
match BuffsBar::new(
client,
&self.imgs,
&self.fonts,
@ -1767,7 +1768,7 @@ impl Hud {
&self.rot_imgs,
tooltip_manager,
&self.voxygen_i18n,
&player_stats,
&player_buffs,
)
.set(self.ids.buffs, ui_widgets)
{