2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-12-13 17:11:55 +00:00
|
|
|
use crate::uid::Uid;
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-12-12 01:45:46 +00:00
|
|
|
use hashbrown::HashMap;
|
2020-08-10 22:54:45 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2021-01-07 20:25:12 +00:00
|
|
|
use specs::{Component, DerefFlaggedStorage};
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-08-10 22:54:45 +00:00
|
|
|
use specs_idvs::IdvStorage;
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-12-12 01:45:46 +00:00
|
|
|
use std::{cmp::Ordering, time::Duration};
|
2020-08-10 22:54:45 +00:00
|
|
|
|
2020-10-19 03:00:35 +00:00
|
|
|
/// De/buff Kind.
|
2020-10-27 01:17:46 +00:00
|
|
|
/// This is used to determine what effects a buff will have
|
2020-12-22 15:40:57 +00:00
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize, PartialOrd, Ord)]
|
2020-10-19 03:00:35 +00:00
|
|
|
pub enum BuffKind {
|
2020-08-10 22:54:45 +00:00
|
|
|
/// Restores health/time for some period
|
2020-10-24 20:12:37 +00:00
|
|
|
Regeneration,
|
2020-10-27 21:27:19 +00:00
|
|
|
/// Restores health/time for some period for consumables
|
|
|
|
Saturation,
|
2020-10-01 00:40:46 +00:00
|
|
|
/// Lowers health over time for some duration
|
2020-10-24 20:12:37 +00:00
|
|
|
Bleeding,
|
2020-10-27 01:17:46 +00:00
|
|
|
/// Lower a creature's max health
|
2020-10-01 17:33:35 +00:00
|
|
|
/// Currently placeholder buff to show other stuff is possible
|
2020-10-24 20:12:37 +00:00
|
|
|
Cursed,
|
2020-12-04 22:24:56 +00:00
|
|
|
/// Applied when drinking a potion
|
2020-11-05 20:02:54 +00:00
|
|
|
Potion,
|
2020-12-04 22:24:56 +00:00
|
|
|
/// Applied when sitting at a campfire
|
|
|
|
CampfireHeal,
|
StaminaPlus buff, modifying stamina via buffs
trying to fix this, coming back to this later
please remember to change potion back future self!
this ALMOST works. maybe MR ready, kinda jank tho
so close, and yet so far...
IT WORKS IT WORKS IT WORKS IT WORKS IT WORKS IT WO
did the same with health, ill fix this garbage l8r
think we're basically done here
whoops forgot to change the food back
fixing and cleaning up part 1
fixed everything part 2 now with buff images
ran clippy + fmt, fixed items that i modified
bracket bulldozing, boldly
hopefully this should be good?
need to rebase real quick
please let me be done
StaminaPlus buff, modifying stamina via buffs
trying to fix this, coming back to this later
please remember to change potion back future self!
this ALMOST works. maybe MR ready, kinda jank tho
so close, and yet so far...
IT WORKS IT WORKS IT WORKS IT WORKS IT WORKS IT WO
did the same with health, ill fix this garbage l8r
think we're basically done here
whoops forgot to change the food back
fixing and cleaning up part 1
fixed everything part 2 now with buff images
ran clippy + fmt, fixed items that i modified
hopefully this should be good?
cargo clippy fmt stuff
deleted an extraneous file?? how did that even...?
2021-01-26 22:47:55 +00:00
|
|
|
/// Raises maximum stamina
|
|
|
|
IncreaseMaxEnergy,
|
|
|
|
/// Raises maximum health
|
|
|
|
IncreaseMaxHealth,
|
2021-02-28 20:02:03 +00:00
|
|
|
/// Makes you immune to attacks
|
|
|
|
Invulnerability,
|
2021-03-04 03:43:11 +00:00
|
|
|
/// Reduces incoming damage
|
|
|
|
ProtectingWard,
|
2020-10-24 20:12:37 +00:00
|
|
|
}
|
|
|
|
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-10-24 20:12:37 +00:00
|
|
|
impl BuffKind {
|
2021-02-20 20:37:46 +00:00
|
|
|
/// Checks if buff is buff or debuff
|
2020-10-24 20:12:37 +00:00
|
|
|
pub fn is_buff(self) -> bool {
|
|
|
|
match self {
|
2021-02-20 20:37:46 +00:00
|
|
|
BuffKind::Regeneration => true,
|
|
|
|
BuffKind::Saturation => true,
|
|
|
|
BuffKind::Bleeding => false,
|
|
|
|
BuffKind::Cursed => false,
|
|
|
|
BuffKind::Potion => true,
|
|
|
|
BuffKind::CampfireHeal => true,
|
|
|
|
BuffKind::IncreaseMaxEnergy => true,
|
|
|
|
BuffKind::IncreaseMaxHealth => true,
|
2021-02-28 20:02:03 +00:00
|
|
|
BuffKind::Invulnerability => true,
|
2021-03-04 03:43:11 +00:00
|
|
|
BuffKind::ProtectingWard => true,
|
2020-10-24 20:12:37 +00:00
|
|
|
}
|
|
|
|
}
|
2021-02-20 20:37:46 +00:00
|
|
|
|
|
|
|
/// Checks if buff should queue
|
|
|
|
pub fn queues(self) -> bool { matches!(self, BuffKind::Saturation) }
|
2020-10-24 20:12:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Struct used to store data relevant to a buff
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-10-27 21:27:19 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
2020-10-24 20:12:37 +00:00
|
|
|
pub struct BuffData {
|
|
|
|
pub strength: f32,
|
|
|
|
pub duration: Option<Duration>,
|
2020-08-10 22:54:45 +00:00
|
|
|
}
|
|
|
|
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-12-04 22:24:56 +00:00
|
|
|
impl BuffData {
|
|
|
|
pub fn new(strength: f32, duration: Option<Duration>) -> Self { Self { strength, duration } }
|
|
|
|
}
|
|
|
|
|
2020-08-10 22:54:45 +00:00
|
|
|
/// De/buff category ID.
|
2020-10-19 03:00:35 +00:00
|
|
|
/// Similar to `BuffKind`, but to mark a category (for more generic usage, like
|
2020-08-10 22:54:45 +00:00
|
|
|
/// positive/negative buffs).
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-10-02 19:09:19 +00:00
|
|
|
#[derive(Clone, Copy, Eq, PartialEq, Debug, Serialize, Deserialize)]
|
2020-10-24 20:12:37 +00:00
|
|
|
pub enum BuffCategory {
|
2020-08-10 22:54:45 +00:00
|
|
|
Natural,
|
2020-10-01 00:40:46 +00:00
|
|
|
Physical,
|
2020-08-10 22:54:45 +00:00
|
|
|
Magical,
|
|
|
|
Divine,
|
2020-10-13 00:48:25 +00:00
|
|
|
PersistOnDeath,
|
2021-02-26 23:15:24 +00:00
|
|
|
FromAura(bool), // bool used to check if buff recently set by aura
|
2020-08-10 22:54:45 +00:00
|
|
|
}
|
|
|
|
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-10-24 23:07:38 +00:00
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
|
|
pub enum ModifierKind {
|
|
|
|
Additive,
|
2020-12-04 22:24:56 +00:00
|
|
|
Fractional,
|
2020-10-24 23:07:38 +00:00
|
|
|
}
|
|
|
|
|
2020-08-10 22:54:45 +00:00
|
|
|
/// Data indicating and configuring behaviour of a de/buff.
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-08-10 22:54:45 +00:00
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
2020-10-01 00:40:46 +00:00
|
|
|
pub enum BuffEffect {
|
|
|
|
/// Periodically damages or heals entity
|
2020-12-04 22:24:56 +00:00
|
|
|
HealthChangeOverTime {
|
|
|
|
rate: f32,
|
|
|
|
accumulated: f32,
|
|
|
|
kind: ModifierKind,
|
|
|
|
},
|
2020-10-24 23:07:38 +00:00
|
|
|
/// Changes maximum health by a certain amount
|
2021-03-04 03:43:11 +00:00
|
|
|
MaxHealthModifier { value: f32, kind: ModifierKind },
|
StaminaPlus buff, modifying stamina via buffs
trying to fix this, coming back to this later
please remember to change potion back future self!
this ALMOST works. maybe MR ready, kinda jank tho
so close, and yet so far...
IT WORKS IT WORKS IT WORKS IT WORKS IT WORKS IT WO
did the same with health, ill fix this garbage l8r
think we're basically done here
whoops forgot to change the food back
fixing and cleaning up part 1
fixed everything part 2 now with buff images
ran clippy + fmt, fixed items that i modified
bracket bulldozing, boldly
hopefully this should be good?
need to rebase real quick
please let me be done
StaminaPlus buff, modifying stamina via buffs
trying to fix this, coming back to this later
please remember to change potion back future self!
this ALMOST works. maybe MR ready, kinda jank tho
so close, and yet so far...
IT WORKS IT WORKS IT WORKS IT WORKS IT WORKS IT WO
did the same with health, ill fix this garbage l8r
think we're basically done here
whoops forgot to change the food back
fixing and cleaning up part 1
fixed everything part 2 now with buff images
ran clippy + fmt, fixed items that i modified
hopefully this should be good?
cargo clippy fmt stuff
deleted an extraneous file?? how did that even...?
2021-01-26 22:47:55 +00:00
|
|
|
/// Changes maximum stamina by a certain amount
|
2021-03-04 03:43:11 +00:00
|
|
|
MaxEnergyModifier { value: f32, kind: ModifierKind },
|
|
|
|
/// Reduces damage after armor is accounted for by this fraction
|
|
|
|
DamageReduction(f32),
|
2020-08-10 22:54:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Actual de/buff.
|
|
|
|
/// Buff can timeout after some time if `time` is Some. If `time` is None,
|
|
|
|
/// Buff will last indefinitely, until removed manually (by some action, like
|
2020-10-19 03:00:35 +00:00
|
|
|
/// uncursing).
|
2020-08-10 22:54:45 +00:00
|
|
|
///
|
2020-10-19 03:00:35 +00:00
|
|
|
/// Buff has a kind, which is used to determine the effects in a builder
|
|
|
|
/// function.
|
2020-08-10 22:54:45 +00:00
|
|
|
///
|
|
|
|
/// To provide more classification info when needed,
|
|
|
|
/// buff can be in one or more buff category.
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-08-10 22:54:45 +00:00
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
|
|
pub struct Buff {
|
2020-10-19 03:00:35 +00:00
|
|
|
pub kind: BuffKind,
|
2020-10-24 20:12:37 +00:00
|
|
|
pub data: BuffData,
|
|
|
|
pub cat_ids: Vec<BuffCategory>,
|
2020-08-10 22:54:45 +00:00
|
|
|
pub time: Option<Duration>,
|
2020-10-01 00:40:46 +00:00
|
|
|
pub effects: Vec<BuffEffect>,
|
2020-10-03 18:48:56 +00:00
|
|
|
pub source: BuffSource,
|
2020-08-10 22:54:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Information about whether buff addition or removal was requested.
|
|
|
|
/// This to implement "on_add" and "on_remove" hooks for constant buffs.
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-10-24 20:12:37 +00:00
|
|
|
#[derive(Clone, Debug)]
|
2020-08-10 22:54:45 +00:00
|
|
|
pub enum BuffChange {
|
|
|
|
/// Adds this buff.
|
|
|
|
Add(Buff),
|
|
|
|
/// Removes all buffs with this ID.
|
2020-10-19 03:00:35 +00:00
|
|
|
RemoveByKind(BuffKind),
|
|
|
|
/// Removes all buffs with this ID, but not debuffs.
|
2020-10-24 20:12:37 +00:00
|
|
|
RemoveFromController(BuffKind),
|
2020-10-02 19:09:19 +00:00
|
|
|
/// Removes buffs of these indices (first vec is for active buffs, second is
|
2020-10-19 03:00:35 +00:00
|
|
|
/// for inactive buffs), should only be called when buffs expire
|
2020-10-24 20:12:37 +00:00
|
|
|
RemoveById(Vec<BuffId>),
|
2020-10-02 19:09:19 +00:00
|
|
|
/// 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
|
2020-10-27 21:27:19 +00:00
|
|
|
/// required, third vec is of categories that will not be removed)
|
2020-10-13 00:48:25 +00:00
|
|
|
RemoveByCategory {
|
2020-10-24 20:12:37 +00:00
|
|
|
all_required: Vec<BuffCategory>,
|
|
|
|
any_required: Vec<BuffCategory>,
|
|
|
|
none_required: Vec<BuffCategory>,
|
2020-10-13 00:48:25 +00:00
|
|
|
},
|
2020-08-10 22:54:45 +00:00
|
|
|
}
|
|
|
|
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-10-24 20:12:37 +00:00
|
|
|
impl Buff {
|
|
|
|
/// Builder function for buffs
|
|
|
|
pub fn new(
|
|
|
|
kind: BuffKind,
|
|
|
|
data: BuffData,
|
|
|
|
cat_ids: Vec<BuffCategory>,
|
|
|
|
source: BuffSource,
|
|
|
|
) -> Self {
|
|
|
|
let (effects, time) = match kind {
|
|
|
|
BuffKind::Bleeding => (
|
|
|
|
vec![BuffEffect::HealthChangeOverTime {
|
|
|
|
rate: -data.strength,
|
|
|
|
accumulated: 0.0,
|
2020-12-04 22:24:56 +00:00
|
|
|
kind: ModifierKind::Additive,
|
2020-10-24 20:12:37 +00:00
|
|
|
}],
|
|
|
|
data.duration,
|
|
|
|
),
|
2020-11-05 20:02:54 +00:00
|
|
|
BuffKind::Regeneration | BuffKind::Saturation | BuffKind::Potion => (
|
2020-10-24 20:12:37 +00:00
|
|
|
vec![BuffEffect::HealthChangeOverTime {
|
|
|
|
rate: data.strength,
|
|
|
|
accumulated: 0.0,
|
2020-12-04 22:24:56 +00:00
|
|
|
kind: ModifierKind::Additive,
|
|
|
|
}],
|
|
|
|
data.duration,
|
|
|
|
),
|
|
|
|
BuffKind::CampfireHeal => (
|
|
|
|
vec![BuffEffect::HealthChangeOverTime {
|
|
|
|
rate: data.strength,
|
|
|
|
accumulated: 0.0,
|
|
|
|
kind: ModifierKind::Fractional,
|
2020-10-24 20:12:37 +00:00
|
|
|
}],
|
|
|
|
data.duration,
|
2020-11-05 20:56:45 +00:00
|
|
|
),
|
2020-10-24 20:12:37 +00:00
|
|
|
BuffKind::Cursed => (
|
2020-10-24 23:07:38 +00:00
|
|
|
vec![BuffEffect::MaxHealthModifier {
|
2020-10-25 01:20:03 +00:00
|
|
|
value: -100. * data.strength,
|
2020-10-24 23:07:38 +00:00
|
|
|
kind: ModifierKind::Additive,
|
2020-10-24 20:12:37 +00:00
|
|
|
}],
|
|
|
|
data.duration,
|
|
|
|
),
|
StaminaPlus buff, modifying stamina via buffs
trying to fix this, coming back to this later
please remember to change potion back future self!
this ALMOST works. maybe MR ready, kinda jank tho
so close, and yet so far...
IT WORKS IT WORKS IT WORKS IT WORKS IT WORKS IT WO
did the same with health, ill fix this garbage l8r
think we're basically done here
whoops forgot to change the food back
fixing and cleaning up part 1
fixed everything part 2 now with buff images
ran clippy + fmt, fixed items that i modified
bracket bulldozing, boldly
hopefully this should be good?
need to rebase real quick
please let me be done
StaminaPlus buff, modifying stamina via buffs
trying to fix this, coming back to this later
please remember to change potion back future self!
this ALMOST works. maybe MR ready, kinda jank tho
so close, and yet so far...
IT WORKS IT WORKS IT WORKS IT WORKS IT WORKS IT WO
did the same with health, ill fix this garbage l8r
think we're basically done here
whoops forgot to change the food back
fixing and cleaning up part 1
fixed everything part 2 now with buff images
ran clippy + fmt, fixed items that i modified
hopefully this should be good?
cargo clippy fmt stuff
deleted an extraneous file?? how did that even...?
2021-01-26 22:47:55 +00:00
|
|
|
BuffKind::IncreaseMaxEnergy => (
|
|
|
|
vec![BuffEffect::MaxEnergyModifier {
|
|
|
|
value: data.strength,
|
|
|
|
kind: ModifierKind::Additive,
|
|
|
|
}],
|
|
|
|
data.duration,
|
|
|
|
),
|
|
|
|
BuffKind::IncreaseMaxHealth => (
|
|
|
|
vec![BuffEffect::MaxHealthModifier {
|
|
|
|
value: data.strength,
|
|
|
|
kind: ModifierKind::Additive,
|
|
|
|
}],
|
|
|
|
data.duration,
|
|
|
|
),
|
2021-03-04 03:43:11 +00:00
|
|
|
BuffKind::Invulnerability => (vec![BuffEffect::DamageReduction(1.0)], data.duration),
|
|
|
|
BuffKind::ProtectingWard => (
|
|
|
|
vec![BuffEffect::DamageReduction(
|
|
|
|
// Causes non-linearity in effect strength, but necessary to allow for tool
|
|
|
|
// power and other things to affect the strength. 0.5 also still provides 50%
|
|
|
|
// damage reduction.
|
|
|
|
data.strength / (0.5 + data.strength),
|
|
|
|
)],
|
|
|
|
data.duration,
|
|
|
|
),
|
2020-10-24 20:12:37 +00:00
|
|
|
};
|
|
|
|
Buff {
|
|
|
|
kind,
|
|
|
|
data,
|
|
|
|
cat_ids,
|
|
|
|
time,
|
|
|
|
effects,
|
|
|
|
source,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-10-25 01:20:03 +00:00
|
|
|
impl PartialOrd for Buff {
|
|
|
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
2020-10-27 01:17:46 +00:00
|
|
|
if self == other {
|
|
|
|
Some(Ordering::Equal)
|
|
|
|
} else if self.data.strength > other.data.strength {
|
2020-10-25 01:20:03 +00:00
|
|
|
Some(Ordering::Greater)
|
|
|
|
} else if self.data.strength < other.data.strength {
|
|
|
|
Some(Ordering::Less)
|
|
|
|
} else if compare_duration(self.time, other.time) {
|
|
|
|
Some(Ordering::Greater)
|
|
|
|
} else if compare_duration(other.time, self.time) {
|
|
|
|
Some(Ordering::Less)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-10-25 01:20:03 +00:00
|
|
|
fn compare_duration(a: Option<Duration>, b: Option<Duration>) -> bool {
|
|
|
|
a.map_or(true, |dur_a| b.map_or(false, |dur_b| dur_a > dur_b))
|
|
|
|
}
|
|
|
|
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-10-25 01:20:03 +00:00
|
|
|
impl PartialEq for Buff {
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
2020-10-27 01:17:46 +00:00
|
|
|
self.data.strength == other.data.strength && self.time == other.time
|
2020-10-25 01:20:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-10 22:54:45 +00:00
|
|
|
/// Source of the de/buff
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-08-10 22:54:45 +00:00
|
|
|
#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)]
|
|
|
|
pub enum BuffSource {
|
|
|
|
/// Applied by a character
|
|
|
|
Character { by: Uid },
|
|
|
|
/// Applied by world, like a poisonous fumes from a swamp
|
|
|
|
World,
|
|
|
|
/// Applied by command
|
|
|
|
Command,
|
|
|
|
/// Applied by an item
|
|
|
|
Item,
|
|
|
|
/// Applied by another buff (like an after-effect)
|
|
|
|
Buff,
|
|
|
|
/// Some other source
|
|
|
|
Unknown,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Component holding all de/buffs that gets resolved each tick.
|
|
|
|
/// On each tick, remaining time of buffs get lowered and
|
2020-10-01 00:40:46 +00:00
|
|
|
/// buff effect of each buff is applied or not, depending on the `BuffEffect`
|
2020-10-01 01:35:57 +00:00
|
|
|
/// (specs system will decide based on `BuffEffect`, to simplify
|
|
|
|
/// implementation). TODO: Something like `once` flag for `Buff` to remove the
|
|
|
|
/// dependence on `BuffEffect` enum?
|
2020-08-10 22:54:45 +00:00
|
|
|
///
|
|
|
|
/// In case of one-time buffs, buff effects will be applied on addition
|
|
|
|
/// 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).
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-08-10 22:54:45 +00:00
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
|
|
|
|
pub struct Buffs {
|
2020-10-24 20:17:49 +00:00
|
|
|
/// Uid used for synchronization
|
2020-10-24 20:12:37 +00:00
|
|
|
id_counter: u64,
|
2020-10-24 20:17:49 +00:00
|
|
|
/// Maps Kinds of buff to Id's of currently applied buffs of that kind
|
2020-10-24 20:12:37 +00:00
|
|
|
pub kinds: HashMap<BuffKind, Vec<BuffId>>,
|
2020-10-24 20:17:49 +00:00
|
|
|
// All currently applied buffs stored by Id
|
2020-10-24 20:12:37 +00:00
|
|
|
pub buffs: HashMap<BuffId, Buff>,
|
2020-08-10 22:54:45 +00:00
|
|
|
}
|
|
|
|
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-10-24 20:12:37 +00:00
|
|
|
impl Buffs {
|
|
|
|
fn sort_kind(&mut self, kind: BuffKind) {
|
|
|
|
if let Some(buff_order) = self.kinds.get_mut(&kind) {
|
2020-10-25 01:20:03 +00:00
|
|
|
if buff_order.is_empty() {
|
2020-10-24 20:12:37 +00:00
|
|
|
self.kinds.remove(&kind);
|
|
|
|
} else {
|
|
|
|
let buffs = &self.buffs;
|
2020-10-25 01:20:03 +00:00
|
|
|
// Intentionally sorted in reverse so that the strongest buffs are earlier in
|
|
|
|
// the vector
|
|
|
|
buff_order.sort_by(|a, b| buffs[&b].partial_cmp(&buffs[&a]).unwrap());
|
2020-10-24 20:12:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn remove_kind(&mut self, kind: BuffKind) {
|
|
|
|
if let Some(buff_ids) = self.kinds.get_mut(&kind) {
|
|
|
|
for id in buff_ids {
|
|
|
|
self.buffs.remove(id);
|
|
|
|
}
|
|
|
|
self.kinds.remove(&kind);
|
2020-10-01 17:33:35 +00:00
|
|
|
}
|
2020-10-24 20:12:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn force_insert(&mut self, id: BuffId, buff: Buff) -> BuffId {
|
|
|
|
let kind = buff.kind;
|
|
|
|
self.kinds.entry(kind).or_default().push(id);
|
|
|
|
self.buffs.insert(id, buff);
|
|
|
|
self.sort_kind(kind);
|
|
|
|
id
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn insert(&mut self, buff: Buff) -> BuffId {
|
|
|
|
self.id_counter += 1;
|
|
|
|
self.force_insert(self.id_counter, buff)
|
|
|
|
}
|
|
|
|
|
2020-12-04 22:24:56 +00:00
|
|
|
pub fn contains(&self, kind: BuffKind) -> bool { self.kinds.contains_key(&kind) }
|
|
|
|
|
2020-10-24 20:12:37 +00:00
|
|
|
// 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)> + '_ {
|
|
|
|
self.kinds
|
|
|
|
.get(&kind)
|
|
|
|
.map(|ids| ids.iter())
|
2020-10-25 01:20:03 +00:00
|
|
|
.unwrap_or_else(|| (&[]).iter())
|
2020-10-24 20:12:37 +00:00
|
|
|
.map(move |id| (*id, &self.buffs[id]))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Iterates through all active buffs (the most powerful buff of each kind)
|
|
|
|
pub fn iter_active(&self) -> impl Iterator<Item = &Buff> + '_ {
|
|
|
|
self.kinds
|
|
|
|
.values()
|
|
|
|
.map(move |ids| self.buffs.get(&ids[0]))
|
|
|
|
.filter(|buff| buff.is_some())
|
|
|
|
.map(|buff| buff.unwrap())
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gets most powerful buff of a given kind
|
|
|
|
// pub fn get_active_kind(&self, kind: BuffKind) -> Buff
|
|
|
|
pub fn remove(&mut self, buff_id: BuffId) {
|
|
|
|
let kind = self.buffs.remove(&buff_id).unwrap().kind;
|
|
|
|
self.kinds
|
|
|
|
.get_mut(&kind)
|
|
|
|
.map(|ids| ids.retain(|id| *id != buff_id));
|
|
|
|
self.sort_kind(kind);
|
2020-10-01 17:33:35 +00:00
|
|
|
}
|
2021-02-20 20:37:46 +00:00
|
|
|
|
|
|
|
/// Returns an immutable reference to the buff kinds on an entity, and a
|
|
|
|
/// mutable reference to the buffs
|
|
|
|
pub fn parts(&mut self) -> (&HashMap<BuffKind, Vec<BuffId>>, &mut HashMap<BuffId, Buff>) {
|
|
|
|
(&self.kinds, &mut self.buffs)
|
|
|
|
}
|
2020-10-01 17:33:35 +00:00
|
|
|
}
|
|
|
|
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-10-24 20:12:37 +00:00
|
|
|
pub type BuffId = u64;
|
|
|
|
|
2021-02-17 13:03:20 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-08-10 22:54:45 +00:00
|
|
|
impl Component for Buffs {
|
2021-01-07 20:25:12 +00:00
|
|
|
type Storage = DerefFlaggedStorage<Self, IdvStorage<Self>>;
|
2020-08-10 22:54:45 +00:00
|
|
|
}
|