mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Changed buffs from using hash maps to an enum map and a slot map.
This commit is contained in:
parent
d7b07ee250
commit
3f19c61426
@ -5,58 +5,65 @@ ItemDef(
|
|||||||
kind: Drink,
|
kind: Drink,
|
||||||
effects: Any([
|
effects: Any([
|
||||||
Buff((
|
Buff((
|
||||||
kind: Polymorphed(QuadrupedSmall(( species: Frog, body_type: Female ))),
|
kind: Polymorphed,
|
||||||
data: (
|
data: (
|
||||||
strength: 0.0,
|
strength: 0.0,
|
||||||
duration: Some(60),
|
duration: Some(60),
|
||||||
|
misc_data: Some(Body(QuadrupedSmall(( species: Frog, body_type: Female )))),
|
||||||
),
|
),
|
||||||
cat_ids: [Natural],
|
cat_ids: [Natural],
|
||||||
)),
|
)),
|
||||||
Buff((
|
Buff((
|
||||||
kind: Polymorphed(QuadrupedSmall(( species: Rabbit, body_type: Female ))),
|
kind: Polymorphed,
|
||||||
data: (
|
data: (
|
||||||
strength: 0.0,
|
strength: 0.0,
|
||||||
duration: Some(60),
|
duration: Some(60),
|
||||||
|
misc_data: Some(Body(QuadrupedSmall(( species: Rabbit, body_type: Female )))),
|
||||||
),
|
),
|
||||||
cat_ids: [Natural],
|
cat_ids: [Natural],
|
||||||
)),
|
)),
|
||||||
Buff((
|
Buff((
|
||||||
kind: Polymorphed(QuadrupedSmall(( species: Rat, body_type: Female ))),
|
kind: Polymorphed,
|
||||||
data: (
|
data: (
|
||||||
strength: 0.0,
|
strength: 0.0,
|
||||||
duration: Some(60),
|
duration: Some(60),
|
||||||
|
misc_data: Some(Body(QuadrupedSmall(( species: Rat, body_type: Female )))),
|
||||||
),
|
),
|
||||||
cat_ids: [Natural],
|
cat_ids: [Natural],
|
||||||
)),
|
)),
|
||||||
Buff((
|
Buff((
|
||||||
kind: Polymorphed(QuadrupedSmall(( species: Squirrel, body_type: Female ))),
|
kind: Polymorphed,
|
||||||
data: (
|
data: (
|
||||||
strength: 0.0,
|
strength: 0.0,
|
||||||
duration: Some(60),
|
duration: Some(60),
|
||||||
|
misc_data: Some(Body(QuadrupedSmall(( species: Squirrel, body_type: Female )))),
|
||||||
),
|
),
|
||||||
cat_ids: [Natural],
|
cat_ids: [Natural],
|
||||||
)),
|
)),
|
||||||
Buff((
|
Buff((
|
||||||
kind: Polymorphed(QuadrupedSmall(( species: Cat, body_type: Female ))),
|
kind: Polymorphed,
|
||||||
data: (
|
data: (
|
||||||
strength: 0.0,
|
strength: 0.0,
|
||||||
duration: Some(60),
|
duration: Some(60),
|
||||||
|
misc_data: Some(Body(QuadrupedSmall(( species: Cat, body_type: Female )))),
|
||||||
),
|
),
|
||||||
cat_ids: [Natural],
|
cat_ids: [Natural],
|
||||||
)),
|
)),
|
||||||
Buff((
|
Buff((
|
||||||
kind: Polymorphed(QuadrupedSmall(( species: Fungome, body_type: Female ))),
|
kind: Polymorphed,
|
||||||
data: (
|
data: (
|
||||||
strength: 0.0,
|
strength: 0.0,
|
||||||
duration: Some(60),
|
duration: Some(60),
|
||||||
|
misc_data: Some(Body(QuadrupedSmall(( species: Fungome, body_type: Female )))),
|
||||||
),
|
),
|
||||||
cat_ids: [Natural],
|
cat_ids: [Natural],
|
||||||
)),
|
)),
|
||||||
Buff((
|
Buff((
|
||||||
kind: Polymorphed(QuadrupedSmall(( species: Pig, body_type: Female ))),
|
kind: Polymorphed,
|
||||||
data: (
|
data: (
|
||||||
strength: 0.0,
|
strength: 0.0,
|
||||||
duration: Some(60),
|
duration: Some(60),
|
||||||
|
misc_data: Some(Body(QuadrupedSmall(( species: Pig, body_type: Female )))),
|
||||||
),
|
),
|
||||||
cat_ids: [Natural],
|
cat_ids: [Natural],
|
||||||
)),
|
)),
|
||||||
|
@ -172,7 +172,7 @@ lazy_static! {
|
|||||||
BuffKind::Parried => "parried",
|
BuffKind::Parried => "parried",
|
||||||
BuffKind::PotionSickness => "potion_sickness",
|
BuffKind::PotionSickness => "potion_sickness",
|
||||||
BuffKind::Reckless => "reckless",
|
BuffKind::Reckless => "reckless",
|
||||||
BuffKind::Polymorphed(_) => "polymorphed",
|
BuffKind::Polymorphed => "polymorphed",
|
||||||
BuffKind::Flame => "flame",
|
BuffKind::Flame => "flame",
|
||||||
BuffKind::Frigid => "frigid",
|
BuffKind::Frigid => "frigid",
|
||||||
BuffKind::Lifesteal => "lifesteal",
|
BuffKind::Lifesteal => "lifesteal",
|
||||||
|
@ -10,18 +10,21 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
use hashbrown::HashMap;
|
use enum_map::{Enum, EnumMap};
|
||||||
use itertools::Either;
|
use itertools::Either;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use slotmap::{new_key_type, SlotMap};
|
||||||
use specs::{Component, DerefFlaggedStorage, VecStorage};
|
use specs::{Component, DerefFlaggedStorage, VecStorage};
|
||||||
use strum::EnumIter;
|
use strum::EnumIter;
|
||||||
|
|
||||||
use super::Body;
|
use super::Body;
|
||||||
|
|
||||||
|
new_key_type! { pub struct BuffKey; }
|
||||||
|
|
||||||
/// De/buff Kind.
|
/// De/buff Kind.
|
||||||
/// This is used to determine what effects a buff will have
|
/// This is used to determine what effects a buff will have
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize, PartialOrd, Ord, EnumIter,
|
Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize, PartialOrd, Ord, EnumIter, Enum,
|
||||||
)]
|
)]
|
||||||
pub enum BuffKind {
|
pub enum BuffKind {
|
||||||
// Buffs
|
// Buffs
|
||||||
@ -157,7 +160,7 @@ pub enum BuffKind {
|
|||||||
/// Decreases the health gained from subsequent potions.
|
/// Decreases the health gained from subsequent potions.
|
||||||
PotionSickness,
|
PotionSickness,
|
||||||
/// Changed into another body.
|
/// Changed into another body.
|
||||||
Polymorphed(Body),
|
Polymorphed,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BuffKind {
|
impl BuffKind {
|
||||||
@ -197,7 +200,7 @@ impl BuffKind {
|
|||||||
| BuffKind::Poisoned
|
| BuffKind::Poisoned
|
||||||
| BuffKind::Parried
|
| BuffKind::Parried
|
||||||
| BuffKind::PotionSickness
|
| BuffKind::PotionSickness
|
||||||
| BuffKind::Polymorphed(_) => false,
|
| BuffKind::Polymorphed => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,7 +351,13 @@ impl BuffKind {
|
|||||||
BuffEffect::DamageReduction(-data.strength),
|
BuffEffect::DamageReduction(-data.strength),
|
||||||
BuffEffect::AttackDamage(1.0 + data.strength),
|
BuffEffect::AttackDamage(1.0 + data.strength),
|
||||||
],
|
],
|
||||||
BuffKind::Polymorphed(body) => vec![BuffEffect::BodyChange(*body)],
|
BuffKind::Polymorphed => {
|
||||||
|
let mut effects = Vec::new();
|
||||||
|
if let Some(MiscBuffData::Body(body)) = data.misc_data {
|
||||||
|
effects.push(BuffEffect::BodyChange(body));
|
||||||
|
}
|
||||||
|
effects
|
||||||
|
},
|
||||||
BuffKind::Flame => vec![BuffEffect::AttackEffect(AttackEffect::new(
|
BuffKind::Flame => vec![BuffEffect::AttackEffect(AttackEffect::new(
|
||||||
None,
|
None,
|
||||||
CombatEffect::Buff(CombatBuff {
|
CombatEffect::Buff(CombatBuff {
|
||||||
@ -433,6 +442,13 @@ pub struct BuffData {
|
|||||||
pub force_immediate: bool,
|
pub force_immediate: bool,
|
||||||
/// Used for buffs that have rider buffs (e.g. Flame, Frigid)
|
/// Used for buffs that have rider buffs (e.g. Flame, Frigid)
|
||||||
pub secondary_duration: Option<Secs>,
|
pub secondary_duration: Option<Secs>,
|
||||||
|
/// Used to add random data to buffs if needed (e.g. polymorphed)
|
||||||
|
pub misc_data: Option<MiscBuffData>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub enum MiscBuffData {
|
||||||
|
Body(Body),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BuffData {
|
impl BuffData {
|
||||||
@ -443,6 +459,7 @@ impl BuffData {
|
|||||||
force_immediate: false,
|
force_immediate: false,
|
||||||
delay: None,
|
delay: None,
|
||||||
secondary_duration: None,
|
secondary_duration: None,
|
||||||
|
misc_data: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,6 +478,11 @@ impl BuffData {
|
|||||||
self.force_immediate = force_immediate;
|
self.force_immediate = force_immediate;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_misc_data(mut self, misc_data: MiscBuffData) -> Self {
|
||||||
|
self.misc_data = Some(misc_data);
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// De/buff category ID.
|
/// De/buff category ID.
|
||||||
@ -588,9 +610,8 @@ pub enum BuffChange {
|
|||||||
RemoveByKind(BuffKind),
|
RemoveByKind(BuffKind),
|
||||||
/// Removes all buffs with this ID, but not debuffs.
|
/// Removes all buffs with this ID, but not debuffs.
|
||||||
RemoveFromController(BuffKind),
|
RemoveFromController(BuffKind),
|
||||||
/// Removes buffs of these indices (first vec is for active buffs, second is
|
/// Removes buffs of these indices, should only be called when buffs expire
|
||||||
/// for inactive buffs), should only be called when buffs expire
|
RemoveByKey(Vec<BuffKey>),
|
||||||
RemoveById(Vec<BuffId>),
|
|
||||||
/// 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, third vec is of categories that will not be removed)
|
/// required, third vec is of categories that will not be removed)
|
||||||
@ -704,93 +725,88 @@ pub enum BuffSource {
|
|||||||
/// would be probably an undesired effect).
|
/// would be probably an undesired effect).
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
|
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
|
||||||
pub struct Buffs {
|
pub struct Buffs {
|
||||||
/// Uid used for synchronization
|
/// Maps kinds of buff to currently applied buffs of that kind and
|
||||||
id_counter: u64,
|
|
||||||
/// Maps Kinds of buff to Id's of currently applied buffs of that kind and
|
|
||||||
/// the time that the first buff was added (time gets reset if entity no
|
/// the time that the first buff was added (time gets reset if entity no
|
||||||
/// longer has buffs of that kind)
|
/// longer has buffs of that kind)
|
||||||
pub kinds: HashMap<BuffKind, (Vec<BuffId>, Time)>,
|
pub kinds: EnumMap<BuffKind, Option<(Vec<BuffKey>, Time)>>,
|
||||||
// All currently applied buffs stored by Id
|
// All buffs currently present on an entity
|
||||||
pub buffs: HashMap<BuffId, Buff>,
|
pub buffs: SlotMap<BuffKey, Buff>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Buffs {
|
impl Buffs {
|
||||||
fn sort_kind(&mut self, kind: BuffKind) {
|
fn sort_kind(&mut self, kind: BuffKind) {
|
||||||
if let Some(buff_order) = self.kinds.get_mut(&kind) {
|
if let Some(buff_order) = self.kinds[kind].as_mut() {
|
||||||
if buff_order.0.is_empty() {
|
if buff_order.0.is_empty() {
|
||||||
self.kinds.remove(&kind);
|
self.kinds[kind] = None;
|
||||||
} else {
|
} else {
|
||||||
let buffs = &self.buffs;
|
let buffs = &self.buffs;
|
||||||
// Intentionally sorted in reverse so that the strongest buffs are earlier in
|
// Intentionally sorted in reverse so that the strongest buffs are earlier in
|
||||||
// the vector
|
// the vector
|
||||||
buff_order
|
buff_order
|
||||||
.0
|
.0
|
||||||
.sort_by(|a, b| buffs[b].partial_cmp(&buffs[a]).unwrap_or(Ordering::Equal));
|
.sort_by(|a, b| buffs[*b].partial_cmp(&buffs[*a]).unwrap_or(Ordering::Equal));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_kind(&mut self, kind: BuffKind) {
|
pub fn remove_kind(&mut self, kind: BuffKind) {
|
||||||
if let Some(buff_ids) = self.kinds.get_mut(&kind) {
|
if let Some((buff_keys, _)) = self.kinds[kind].as_ref() {
|
||||||
for id in &buff_ids.0 {
|
for key in buff_keys {
|
||||||
self.buffs.remove(id);
|
self.buffs.remove(*key);
|
||||||
}
|
}
|
||||||
self.kinds.remove(&kind);
|
self.kinds[kind] = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn force_insert(&mut self, id: BuffId, buff: Buff, current_time: Time) -> BuffId {
|
pub fn insert(&mut self, buff: Buff, current_time: Time) -> BuffKey {
|
||||||
let kind = buff.kind;
|
let kind = buff.kind;
|
||||||
self.kinds
|
let key = self.buffs.insert(buff);
|
||||||
.entry(kind)
|
self.kinds[kind]
|
||||||
.or_insert((Vec::new(), current_time))
|
.get_or_insert_with(|| (Vec::new(), current_time))
|
||||||
.0
|
.0
|
||||||
.push(id);
|
.push(key);
|
||||||
self.buffs.insert(id, buff);
|
|
||||||
self.sort_kind(kind);
|
self.sort_kind(kind);
|
||||||
if kind.queues() {
|
if kind.queues() {
|
||||||
self.delay_queueable_buffs(kind, current_time);
|
self.delay_queueable_buffs(kind, current_time);
|
||||||
}
|
}
|
||||||
id
|
key
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, buff: Buff, current_time: Time) -> BuffId {
|
pub fn contains(&self, kind: BuffKind) -> bool { self.kinds[kind].is_some() }
|
||||||
self.id_counter += 1;
|
|
||||||
self.force_insert(self.id_counter, buff, current_time)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn contains(&self, kind: BuffKind) -> bool { self.kinds.contains_key(&kind) }
|
|
||||||
|
|
||||||
// Iterate through buffs of a given kind in effect order (most powerful first)
|
// Iterate through buffs of a given kind in effect order (most powerful first)
|
||||||
pub fn iter_kind(&self, kind: BuffKind) -> impl Iterator<Item = (BuffId, &Buff)> + '_ {
|
pub fn iter_kind(&self, kind: BuffKind) -> impl Iterator<Item = (BuffKey, &Buff)> + '_ {
|
||||||
self.kinds
|
self.kinds[kind]
|
||||||
.get(&kind)
|
.as_ref()
|
||||||
.map(|ids| ids.0.iter())
|
.map(|keys| keys.0.iter())
|
||||||
.unwrap_or_else(|| [].iter())
|
.unwrap_or_else(|| [].iter())
|
||||||
.map(move |id| (*id, &self.buffs[id]))
|
.map(move |&key| (key, &self.buffs[key]))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterates through all active buffs (the most powerful buff of each
|
// Iterates through all active buffs (the most powerful buff of each
|
||||||
// non-stacking kind, and all of the stacking ones)
|
// non-stacking kind, and all of the stacking ones)
|
||||||
pub fn iter_active(&self) -> impl Iterator<Item = impl Iterator<Item = &Buff>> + '_ {
|
pub fn iter_active(&self) -> impl Iterator<Item = impl Iterator<Item = &Buff>> + '_ {
|
||||||
self.kinds.iter().map(move |(kind, ids)| {
|
self.kinds
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(kind, keys)| keys.as_ref().map(|keys| (kind, keys)))
|
||||||
|
.map(move |(kind, keys)| {
|
||||||
if kind.stacks() {
|
if kind.stacks() {
|
||||||
// Iterate stackable buffs in reverse order to show the timer of the soonest one
|
// Iterate stackable buffs in reverse order to show the timer of the soonest one
|
||||||
// to expire
|
// to expire
|
||||||
Either::Left(ids.0.iter().filter_map(|id| self.buffs.get(id)).rev())
|
Either::Left(keys.0.iter().filter_map(|key| self.buffs.get(*key)).rev())
|
||||||
} else {
|
} else {
|
||||||
Either::Right(self.buffs.get(&ids.0[0]).into_iter())
|
Either::Right(self.buffs.get(keys.0[0]).into_iter())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets most powerful buff of a given kind
|
// Gets most powerful buff of a given kind
|
||||||
pub fn remove(&mut self, buff_id: BuffId) {
|
pub fn remove(&mut self, buff_key: BuffKey) {
|
||||||
if let Some(kind) = self.buffs.remove(&buff_id) {
|
if let Some(buff) = self.buffs.remove(buff_key) {
|
||||||
let kind = kind.kind;
|
let kind = buff.kind;
|
||||||
self.kinds
|
self.kinds[kind]
|
||||||
.get_mut(&kind)
|
.as_mut()
|
||||||
.map(|ids| ids.0.retain(|id| *id != buff_id));
|
.map(|keys| keys.0.retain(|key| *key != buff_key));
|
||||||
self.sort_kind(kind);
|
self.sort_kind(kind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -798,9 +814,9 @@ impl Buffs {
|
|||||||
fn delay_queueable_buffs(&mut self, kind: BuffKind, current_time: Time) {
|
fn delay_queueable_buffs(&mut self, kind: BuffKind, current_time: Time) {
|
||||||
let mut next_start_time: Option<Time> = None;
|
let mut next_start_time: Option<Time> = None;
|
||||||
debug_assert!(kind.queues());
|
debug_assert!(kind.queues());
|
||||||
if let Some(buffs) = self.kinds.get(&kind) {
|
if let Some(buffs) = self.kinds[kind].as_mut() {
|
||||||
buffs.0.iter().for_each(|id| {
|
buffs.0.iter().for_each(|key| {
|
||||||
if let Some(buff) = self.buffs.get_mut(id) {
|
if let Some(buff) = self.buffs.get_mut(*key) {
|
||||||
// End time only being updated when there is some next_start_time will
|
// End time only being updated when there is some next_start_time will
|
||||||
// technically cause buffs to "end early" if they have a weaker strength than a
|
// technically cause buffs to "end early" if they have a weaker strength than a
|
||||||
// buff with an infinite duration, but this is fine since those buffs wouldn't
|
// buff with an infinite duration, but this is fine since those buffs wouldn't
|
||||||
@ -826,8 +842,6 @@ impl Buffs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type BuffId = u64;
|
|
||||||
|
|
||||||
impl Component for Buffs {
|
impl Component for Buffs {
|
||||||
type Storage = DerefFlaggedStorage<Self, VecStorage<Self>>;
|
type Storage = DerefFlaggedStorage<Self, VecStorage<Self>>;
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ pub use self::{
|
|||||||
quadruped_small, ship, theropod, AllBodies, Body, BodyData,
|
quadruped_small, ship, theropod, AllBodies, Body, BodyData,
|
||||||
},
|
},
|
||||||
buff::{
|
buff::{
|
||||||
Buff, BuffCategory, BuffChange, BuffData, BuffEffect, BuffId, BuffKind, BuffSource, Buffs,
|
Buff, BuffCategory, BuffChange, BuffData, BuffEffect, BuffKey, BuffKind, BuffSource, Buffs,
|
||||||
ModifierKind,
|
ModifierKind,
|
||||||
},
|
},
|
||||||
character_state::{CharacterActivity, CharacterState, StateUpdate},
|
character_state::{CharacterActivity, CharacterState, StateUpdate},
|
||||||
|
@ -4,7 +4,7 @@ use common::{
|
|||||||
aura::Auras,
|
aura::Auras,
|
||||||
body::{object, Body},
|
body::{object, Body},
|
||||||
buff::{
|
buff::{
|
||||||
Buff, BuffCategory, BuffChange, BuffData, BuffEffect, BuffId, BuffKind, BuffSource,
|
Buff, BuffCategory, BuffChange, BuffData, BuffEffect, BuffKey, BuffKind, BuffSource,
|
||||||
Buffs,
|
Buffs,
|
||||||
},
|
},
|
||||||
fluid_dynamics::{Fluid, LiquidKind},
|
fluid_dynamics::{Fluid, LiquidKind},
|
||||||
@ -281,7 +281,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
kind: LiquidKind::Water,
|
kind: LiquidKind::Water,
|
||||||
..
|
..
|
||||||
})
|
})
|
||||||
) && buff_comp.kinds.contains_key(&BuffKind::Burning)
|
) && buff_comp.kinds[BuffKind::Burning].is_some()
|
||||||
{
|
{
|
||||||
// If in water fluid and currently burning, remove burning debuffs
|
// If in water fluid and currently burning, remove burning debuffs
|
||||||
server_emitter.emit(ServerEvent::Buff {
|
server_emitter.emit(ServerEvent::Buff {
|
||||||
@ -291,14 +291,14 @@ impl<'a> System<'a> for Sys {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut expired_buffs = Vec::<BuffId>::new();
|
let mut expired_buffs = Vec::<BuffKey>::new();
|
||||||
|
|
||||||
// Replace buffs from an active aura with a normal buff when out of range of the
|
// Replace buffs from an active aura with a normal buff when out of range of the
|
||||||
// aura
|
// aura
|
||||||
buff_comp
|
buff_comp
|
||||||
.buffs
|
.buffs
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(id, buff)| {
|
.filter_map(|(buff_key, buff)| {
|
||||||
if let Some((uid, aura_key)) = buff.cat_ids.iter().find_map(|cat_id| {
|
if let Some((uid, aura_key)) = buff.cat_ids.iter().find_map(|cat_id| {
|
||||||
if let BuffCategory::FromActiveAura(uid, aura_key) = cat_id {
|
if let BuffCategory::FromActiveAura(uid, aura_key) = cat_id {
|
||||||
Some((uid, aura_key))
|
Some((uid, aura_key))
|
||||||
@ -306,12 +306,12 @@ impl<'a> System<'a> for Sys {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
Some((id, buff, uid, aura_key))
|
Some((buff_key, buff, uid, aura_key))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.for_each(|(buff_id, buff, uid, aura_key)| {
|
.for_each(|(buff_key, buff, uid, aura_key)| {
|
||||||
let replace = if let Some(aura_entity) = read_data.id_maps.uid_entity(*uid) {
|
let replace = if let Some(aura_entity) = read_data.id_maps.uid_entity(*uid) {
|
||||||
if let Some(aura) = read_data
|
if let Some(aura) = read_data
|
||||||
.auras
|
.auras
|
||||||
@ -333,7 +333,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
true
|
true
|
||||||
};
|
};
|
||||||
if replace {
|
if replace {
|
||||||
expired_buffs.push(*buff_id);
|
expired_buffs.push(buff_key);
|
||||||
server_emitter.emit(ServerEvent::Buff {
|
server_emitter.emit(ServerEvent::Buff {
|
||||||
entity,
|
entity,
|
||||||
buff_change: BuffChange::Add(Buff::new(
|
buff_change: BuffChange::Add(Buff::new(
|
||||||
@ -355,9 +355,9 @@ impl<'a> System<'a> for Sys {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
buff_comp.buffs.iter().for_each(|(id, buff)| {
|
buff_comp.buffs.iter().for_each(|(buff_key, buff)| {
|
||||||
if buff.end_time.map_or(false, |end| end.0 < read_data.time.0) {
|
if buff.end_time.map_or(false, |end| end.0 < read_data.time.0) {
|
||||||
expired_buffs.push(*id)
|
expired_buffs.push(buff_key)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -370,9 +370,9 @@ impl<'a> System<'a> for Sys {
|
|||||||
.abs()
|
.abs()
|
||||||
< f32::EPSILON;
|
< f32::EPSILON;
|
||||||
if infinite_damage_reduction {
|
if infinite_damage_reduction {
|
||||||
for (id, buff) in buff_comp.buffs.iter() {
|
for (key, buff) in buff_comp.buffs.iter() {
|
||||||
if !buff.kind.is_buff() {
|
if !buff.kind.is_buff() {
|
||||||
expired_buffs.push(*id);
|
expired_buffs.push(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -386,24 +386,24 @@ impl<'a> System<'a> for Sys {
|
|||||||
let mut buff_kinds = buff_comp
|
let mut buff_kinds = buff_comp
|
||||||
.kinds
|
.kinds
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(kind, ids)| (*kind, ids.clone()))
|
.filter_map(|(kind, keys)| keys.as_ref().map(|keys| (kind, keys.clone())))
|
||||||
.collect::<Vec<(BuffKind, (Vec<BuffId>, Time))>>();
|
.collect::<Vec<(BuffKind, (Vec<BuffKey>, Time))>>();
|
||||||
buff_kinds.sort_by_key(|(kind, _)| !kind.affects_subsequent_buffs());
|
buff_kinds.sort_by_key(|(kind, _)| !kind.affects_subsequent_buffs());
|
||||||
for (buff_kind, (buff_ids, kind_start_time)) in buff_kinds.into_iter() {
|
for (buff_kind, (buff_keys, kind_start_time)) in buff_kinds.into_iter() {
|
||||||
let mut active_buff_ids = Vec::new();
|
let mut active_buff_keys = Vec::new();
|
||||||
if infinite_damage_reduction && !buff_kind.is_buff() {
|
if infinite_damage_reduction && !buff_kind.is_buff() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if buff_kind.stacks() {
|
if buff_kind.stacks() {
|
||||||
// Process all the buffs of this kind
|
// Process all the buffs of this kind
|
||||||
active_buff_ids = buff_ids;
|
active_buff_keys = buff_keys;
|
||||||
} else {
|
} else {
|
||||||
// Only process the strongest of this buff kind
|
// Only process the strongest of this buff kind
|
||||||
active_buff_ids.push(buff_ids[0]);
|
active_buff_keys.push(buff_keys[0]);
|
||||||
}
|
}
|
||||||
for buff_id in active_buff_ids.into_iter() {
|
for buff_key in active_buff_keys.into_iter() {
|
||||||
if let Some(buff) = buff_comp.buffs.get(&buff_id) {
|
if let Some(buff) = buff_comp.buffs.get(buff_key) {
|
||||||
// Skip the effect of buffs whose start delay hasn't expired.
|
// Skip the effect of buffs whose start delay hasn't expired.
|
||||||
if buff.start_time.0 > read_data.time.0 {
|
if buff.start_time.0 > read_data.time.0 {
|
||||||
continue;
|
continue;
|
||||||
@ -434,7 +434,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
&mut server_emitter,
|
&mut server_emitter,
|
||||||
dt,
|
dt,
|
||||||
*read_data.time,
|
*read_data.time,
|
||||||
expired_buffs.contains(&buff_id),
|
expired_buffs.contains(&buff_key),
|
||||||
buff_comp,
|
buff_comp,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -452,7 +452,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
if !expired_buffs.is_empty() {
|
if !expired_buffs.is_empty() {
|
||||||
server_emitter.emit(ServerEvent::Buff {
|
server_emitter.emit(ServerEvent::Buff {
|
||||||
entity,
|
entity,
|
||||||
buff_change: BuffChange::RemoveById(expired_buffs),
|
buff_change: BuffChange::RemoveByKey(expired_buffs),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ pub fn is_dead(entity: EcsEntity, read_data: &ReadData) -> bool {
|
|||||||
pub fn is_invulnerable(entity: EcsEntity, read_data: &ReadData) -> bool {
|
pub fn is_invulnerable(entity: EcsEntity, read_data: &ReadData) -> bool {
|
||||||
let buffs = read_data.buffs.get(entity);
|
let buffs = read_data.buffs.get(entity);
|
||||||
|
|
||||||
buffs.map_or(false, |b| b.kinds.contains_key(&BuffKind::Invulnerability))
|
buffs.map_or(false, |b| b.kinds[BuffKind::Invulnerability].is_some())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets alignment of owner if alignment given is `Owned`.
|
/// Gets alignment of owner if alignment given is `Owned`.
|
||||||
@ -204,7 +204,7 @@ impl<'a> AgentData<'a> {
|
|||||||
read_data
|
read_data
|
||||||
.buffs
|
.buffs
|
||||||
.get(*self.entity)
|
.get(*self.entity)
|
||||||
.map_or(false, |b| b.kinds.contains_key(&buff))
|
.map_or(false, |b| b.kinds[buff].is_some())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_ability(&self, input: AbilityInput) -> Option<AbilityData> {
|
pub fn extract_ability(&self, input: AbilityInput) -> Option<AbilityData> {
|
||||||
|
@ -1226,9 +1226,9 @@ pub fn handle_buff(server: &mut Server, entity: EcsEntity, buff_change: buff::Bu
|
|||||||
buffs.insert(new_buff, *time);
|
buffs.insert(new_buff, *time);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
BuffChange::RemoveById(ids) => {
|
BuffChange::RemoveByKey(keys) => {
|
||||||
for id in ids {
|
for key in keys {
|
||||||
buffs.remove(id);
|
buffs.remove(key);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
BuffChange::RemoveByKind(kind) => {
|
BuffChange::RemoveByKind(kind) => {
|
||||||
@ -1244,8 +1244,8 @@ pub fn handle_buff(server: &mut Server, entity: EcsEntity, buff_change: buff::Bu
|
|||||||
any_required,
|
any_required,
|
||||||
none_required,
|
none_required,
|
||||||
} => {
|
} => {
|
||||||
let mut ids_to_remove = Vec::new();
|
let mut keys_to_remove = Vec::new();
|
||||||
for (id, buff) in buffs.buffs.iter() {
|
for (key, buff) in buffs.buffs.iter() {
|
||||||
let mut required_met = true;
|
let mut required_met = true;
|
||||||
for required in &all_required {
|
for required in &all_required {
|
||||||
if !buff.cat_ids.iter().any(|cat| cat == required) {
|
if !buff.cat_ids.iter().any(|cat| cat == required) {
|
||||||
@ -1268,11 +1268,11 @@ pub fn handle_buff(server: &mut Server, entity: EcsEntity, buff_change: buff::Bu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if required_met && any_met && none_met {
|
if required_met && any_met && none_met {
|
||||||
ids_to_remove.push(*id);
|
keys_to_remove.push(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for id in ids_to_remove {
|
for key in keys_to_remove {
|
||||||
buffs.remove(id);
|
buffs.remove(key);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
BuffChange::Refresh(kind) => {
|
BuffChange::Refresh(kind) => {
|
||||||
|
@ -213,7 +213,7 @@ fn react_if_on_fire(bdata: &mut BehaviorData) -> bool {
|
|||||||
.read_data
|
.read_data
|
||||||
.buffs
|
.buffs
|
||||||
.get(*bdata.agent_data.entity)
|
.get(*bdata.agent_data.entity)
|
||||||
.map_or(false, |b| b.kinds.contains_key(&BuffKind::Burning));
|
.map_or(false, |b| b.kinds[BuffKind::Burning].is_some());
|
||||||
|
|
||||||
if is_on_fire
|
if is_on_fire
|
||||||
&& bdata.agent_data.body.map_or(false, |b| b.is_humanoid())
|
&& bdata.agent_data.body.map_or(false, |b| b.is_humanoid())
|
||||||
|
@ -137,7 +137,7 @@ pub fn localize_chat_message(
|
|||||||
| BuffKind::Poisoned
|
| BuffKind::Poisoned
|
||||||
| BuffKind::Parried
|
| BuffKind::Parried
|
||||||
| BuffKind::PotionSickness
|
| BuffKind::PotionSickness
|
||||||
| BuffKind::Polymorphed(_) => {
|
| BuffKind::Polymorphed => {
|
||||||
tracing::error!("Player was killed by a debuff that doesn't do damage!");
|
tracing::error!("Player was killed by a debuff that doesn't do damage!");
|
||||||
"mysterious"
|
"mysterious"
|
||||||
},
|
},
|
||||||
|
@ -5191,7 +5191,7 @@ pub fn get_buff_image(buff: BuffKind, imgs: &Imgs) -> conrod_core::image::Id {
|
|||||||
BuffKind::Poisoned => imgs.debuff_poisoned_0,
|
BuffKind::Poisoned => imgs.debuff_poisoned_0,
|
||||||
BuffKind::Parried => imgs.debuff_parried_0,
|
BuffKind::Parried => imgs.debuff_parried_0,
|
||||||
BuffKind::PotionSickness => imgs.debuff_potionsickness_0,
|
BuffKind::PotionSickness => imgs.debuff_potionsickness_0,
|
||||||
BuffKind::Polymorphed(_) => imgs.debuff_polymorphed,
|
BuffKind::Polymorphed => imgs.debuff_polymorphed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5232,7 +5232,7 @@ pub fn get_buff_title(buff: BuffKind, localized_strings: &Localization) -> Cow<s
|
|||||||
BuffKind::Poisoned => localized_strings.get_msg("buff-title-poisoned"),
|
BuffKind::Poisoned => localized_strings.get_msg("buff-title-poisoned"),
|
||||||
BuffKind::Parried => localized_strings.get_msg("buff-title-parried"),
|
BuffKind::Parried => localized_strings.get_msg("buff-title-parried"),
|
||||||
BuffKind::PotionSickness => localized_strings.get_msg("buff-title-potionsickness"),
|
BuffKind::PotionSickness => localized_strings.get_msg("buff-title-potionsickness"),
|
||||||
BuffKind::Polymorphed(_) => localized_strings.get_msg("buff-title-polymorphed"),
|
BuffKind::Polymorphed => localized_strings.get_msg("buff-title-polymorphed"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5277,7 +5277,7 @@ pub fn get_buff_desc(buff: BuffKind, data: BuffData, localized_strings: &Localiz
|
|||||||
BuffKind::Poisoned => localized_strings.get_msg("buff-desc-poisoned"),
|
BuffKind::Poisoned => localized_strings.get_msg("buff-desc-poisoned"),
|
||||||
BuffKind::Parried => localized_strings.get_msg("buff-desc-parried"),
|
BuffKind::Parried => localized_strings.get_msg("buff-desc-parried"),
|
||||||
BuffKind::PotionSickness => localized_strings.get_msg("buff-desc-potionsickness"),
|
BuffKind::PotionSickness => localized_strings.get_msg("buff-desc-potionsickness"),
|
||||||
BuffKind::Polymorphed(_) => localized_strings.get_msg("buff-desc-polymorphed"),
|
BuffKind::Polymorphed => localized_strings.get_msg("buff-desc-polymorphed"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ pub fn consumable_desc(effects: &Effects, i18n: &Localization) -> Vec<String> {
|
|||||||
| BuffKind::Fortitude
|
| BuffKind::Fortitude
|
||||||
| BuffKind::Parried
|
| BuffKind::Parried
|
||||||
| BuffKind::Reckless
|
| BuffKind::Reckless
|
||||||
| BuffKind::Polymorphed(_)
|
| BuffKind::Polymorphed
|
||||||
| BuffKind::Flame
|
| BuffKind::Flame
|
||||||
| BuffKind::Frigid
|
| BuffKind::Frigid
|
||||||
| BuffKind::Lifesteal
|
| BuffKind::Lifesteal
|
||||||
@ -233,7 +233,7 @@ pub fn consumable_desc(effects: &Effects, i18n: &Localization) -> Vec<String> {
|
|||||||
| BuffKind::IncreaseMaxHealth
|
| BuffKind::IncreaseMaxHealth
|
||||||
| BuffKind::Invulnerability
|
| BuffKind::Invulnerability
|
||||||
| BuffKind::PotionSickness
|
| BuffKind::PotionSickness
|
||||||
| BuffKind::Polymorphed(_) => {
|
| BuffKind::Polymorphed => {
|
||||||
i18n.get_msg_ctx("buff-text-for_seconds", &i18n::fluent_args! {
|
i18n.get_msg_ctx("buff-text-for_seconds", &i18n::fluent_args! {
|
||||||
"dur_secs" => dur_secs
|
"dur_secs" => dur_secs
|
||||||
})
|
})
|
||||||
|
@ -1482,7 +1482,11 @@ impl ParticleMgr {
|
|||||||
{
|
{
|
||||||
let pos = interp.map_or(pos.0, |i| i.pos);
|
let pos = interp.map_or(pos.0, |i| i.pos);
|
||||||
|
|
||||||
for (buff_kind, buff_ids) in buffs.kinds.iter() {
|
for (buff_kind, buff_keys) in buffs
|
||||||
|
.kinds
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(kind, keys)| keys.as_ref().map(|keys| (kind, keys)))
|
||||||
|
{
|
||||||
use buff::BuffKind;
|
use buff::BuffKind;
|
||||||
match buff_kind {
|
match buff_kind {
|
||||||
BuffKind::Cursed | BuffKind::Burning => {
|
BuffKind::Cursed | BuffKind::Burning => {
|
||||||
@ -1519,9 +1523,9 @@ impl ParticleMgr {
|
|||||||
let mut multiplicity = 0;
|
let mut multiplicity = 0;
|
||||||
// Only show particles for potion sickness at the beginning, after the
|
// Only show particles for potion sickness at the beginning, after the
|
||||||
// drinking animation finishes
|
// drinking animation finishes
|
||||||
if buff_ids.0
|
if buff_keys.0
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|id| buffs.buffs.get(id))
|
.filter_map(|key| buffs.buffs.get(*key))
|
||||||
.any(|buff| {
|
.any(|buff| {
|
||||||
matches!(buff.elapsed(Time(time)), dur if (1.0..=1.5).contains(&dur.0))
|
matches!(buff.elapsed(Time(time)), dur if (1.0..=1.5).contains(&dur.0))
|
||||||
})
|
})
|
||||||
@ -1583,13 +1587,13 @@ impl ParticleMgr {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
BuffKind::Polymorphed(_) => {
|
BuffKind::Polymorphed => {
|
||||||
let mut multiplicity = 0;
|
let mut multiplicity = 0;
|
||||||
// Only show particles for polymorph at the beginning, after the
|
// Only show particles for polymorph at the beginning, after the
|
||||||
// drinking animation finishes
|
// drinking animation finishes
|
||||||
if buff_ids.0
|
if buff_keys.0
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|id| buffs.buffs.get(id))
|
.filter_map(|key| buffs.buffs.get(*key))
|
||||||
.any(|buff| {
|
.any(|buff| {
|
||||||
matches!(buff.elapsed(Time(time)), dur if (0.1..=0.3).contains(&dur.0))
|
matches!(buff.elapsed(Time(time)), dur if (0.1..=0.3).contains(&dur.0))
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user