mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Aura System and Campfire Health Regen
This commit is contained in:
parent
30563f59f3
commit
71303fecfd
@ -10,11 +10,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added chat commands for inviting, kicking, leaving, and promoting in groups
|
- Added chat commands for inviting, kicking, leaving, and promoting in groups
|
||||||
|
- Aura system
|
||||||
|
- Campfire resting heal
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Doubled range of ScaleMode slider when set to Custom
|
- Doubled range of ScaleMode slider when set to Custom
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- SSAAx4 option
|
- SSAAx4 option
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -4393,6 +4393,15 @@ version = "0.4.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slotmap"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c46a3482db8f247956e464d783693ece164ca056e6e67563ee5505bdb86452cd"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "0.6.13"
|
version = "0.6.13"
|
||||||
@ -5373,6 +5382,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
"slab",
|
"slab",
|
||||||
|
"slotmap",
|
||||||
"specs",
|
"specs",
|
||||||
"specs-idvs",
|
"specs-idvs",
|
||||||
"spin_sleep",
|
"spin_sleep",
|
||||||
|
BIN
assets/voxygen/element/icons/de_buffs/buff_campfire_heal_0.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/icons/de_buffs/buff_campfire_heal_0.png
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -550,6 +550,8 @@ Protection
|
|||||||
"buff.desc.potion": "Drinking...",
|
"buff.desc.potion": "Drinking...",
|
||||||
"buff.title.saturation": "Saturation",
|
"buff.title.saturation": "Saturation",
|
||||||
"buff.desc.saturation": "Gain health over time from consumables.",
|
"buff.desc.saturation": "Gain health over time from consumables.",
|
||||||
|
"buff.title.campfire_heal": "Campfire Heal",
|
||||||
|
"buff.desc.campfire_heal": "Resting at a campfire heals 1% per second.",
|
||||||
// Debuffs
|
// Debuffs
|
||||||
"debuff.title.bleed": "Bleeding",
|
"debuff.title.bleed": "Bleeding",
|
||||||
"debuff.desc.bleed": "Inflicts regular damage.",
|
"debuff.desc.bleed": "Inflicts regular damage.",
|
||||||
|
@ -39,6 +39,7 @@ authc = { git = "https://gitlab.com/veloren/auth.git", rev = "b943c85e4a38f5ec60
|
|||||||
|
|
||||||
# Data structures
|
# Data structures
|
||||||
hashbrown = { version = "0.7.2", features = ["rayon", "serde", "nightly"] }
|
hashbrown = { version = "0.7.2", features = ["rayon", "serde", "nightly"] }
|
||||||
|
slotmap = { version = "0.4.0", features = ["serde", "unstable"] }
|
||||||
indexmap = "1.3.0"
|
indexmap = "1.3.0"
|
||||||
slab = "0.4.2"
|
slab = "0.4.2"
|
||||||
|
|
||||||
|
83
common/src/comp/aura.rs
Normal file
83
common/src/comp/aura.rs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
use crate::comp::buff::{BuffCategory, BuffData, BuffKind, BuffSource};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use slotmap::{new_key_type, SlotMap};
|
||||||
|
use specs::{Component, FlaggedStorage};
|
||||||
|
use specs_idvs::IdvStorage;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
new_key_type! { pub struct AuraKey; }
|
||||||
|
|
||||||
|
/// AuraKind is what kind of effect an aura applies
|
||||||
|
/// Currently only buffs are implemented
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||||
|
pub enum AuraKind {
|
||||||
|
/// The Buff kind is (surprise!) a buff :D
|
||||||
|
Buff {
|
||||||
|
kind: BuffKind,
|
||||||
|
data: BuffData,
|
||||||
|
category: BuffCategory,
|
||||||
|
source: BuffSource,
|
||||||
|
},
|
||||||
|
/* TODO: Implement other effects here. Things to think about
|
||||||
|
* are terrain/sprite effects, collision and physics, and
|
||||||
|
* environmental conditions like temperature and humidity
|
||||||
|
* Multiple auras can be given to an entity. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Aura
|
||||||
|
/// Applies a buff to entities in the radius if meeting
|
||||||
|
/// conditions set forth in the aura system.
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Aura {
|
||||||
|
/// The kind of aura applied
|
||||||
|
pub aura_kind: AuraKind,
|
||||||
|
/// The radius of the aura
|
||||||
|
pub radius: f32,
|
||||||
|
/// How long the aura lasts. None corresponds to an indefinite length
|
||||||
|
pub duration: Option<Duration>,
|
||||||
|
/* TODO: Add functionality for fading or a gradient
|
||||||
|
* TODO: Make alignment specific auras work */
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Information about whether aura addition or removal was requested.
|
||||||
|
/// This to implement "on_add" and "on_remove" hooks for auras
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum AuraChange {
|
||||||
|
/// Adds this aura
|
||||||
|
Add(Aura),
|
||||||
|
/// Removes auras of these indices
|
||||||
|
RemoveByKey(Vec<AuraKey>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Aura {
|
||||||
|
/// Creates a new Aura to be assigned to an entity
|
||||||
|
pub fn new(aura_kind: AuraKind, radius: f32, duration: Option<Duration>) -> Self {
|
||||||
|
Self {
|
||||||
|
aura_kind,
|
||||||
|
radius,
|
||||||
|
duration,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Component holding all auras emitted by an entity.
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
|
||||||
|
pub struct Auras {
|
||||||
|
pub auras: SlotMap<AuraKey, Aura>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Auras {
|
||||||
|
pub fn new(aura: Aura) -> Self {
|
||||||
|
let mut auras: SlotMap<AuraKey, Aura> = SlotMap::with_key();
|
||||||
|
auras.insert(aura);
|
||||||
|
Self { auras }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert(&mut self, aura: Aura) { self.auras.insert(aura); }
|
||||||
|
|
||||||
|
pub fn remove(&mut self, key: AuraKey) { self.auras.remove(key); }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for Auras {
|
||||||
|
type Storage = FlaggedStorage<Self, IdvStorage<Self>>;
|
||||||
|
}
|
@ -17,8 +17,10 @@ pub enum BuffKind {
|
|||||||
/// Lower a creature's max health
|
/// Lower a creature's max health
|
||||||
/// Currently placeholder buff to show other stuff is possible
|
/// Currently placeholder buff to show other stuff is possible
|
||||||
Cursed,
|
Cursed,
|
||||||
// Applied when drinking a potion
|
/// Applied when drinking a potion
|
||||||
Potion,
|
Potion,
|
||||||
|
/// Applied when sitting at a campfire
|
||||||
|
CampfireHeal,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BuffKind {
|
impl BuffKind {
|
||||||
@ -30,6 +32,7 @@ impl BuffKind {
|
|||||||
BuffKind::Bleeding { .. } => false,
|
BuffKind::Bleeding { .. } => false,
|
||||||
BuffKind::Cursed { .. } => false,
|
BuffKind::Cursed { .. } => false,
|
||||||
BuffKind::Potion { .. } => true,
|
BuffKind::Potion { .. } => true,
|
||||||
|
BuffKind::CampfireHeal { .. } => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,6 +44,10 @@ pub struct BuffData {
|
|||||||
pub duration: Option<Duration>,
|
pub duration: Option<Duration>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BuffData {
|
||||||
|
pub fn new(strength: f32, duration: Option<Duration>) -> Self { Self { strength, duration } }
|
||||||
|
}
|
||||||
|
|
||||||
/// De/buff category ID.
|
/// De/buff category ID.
|
||||||
/// Similar to `BuffKind`, but to mark a category (for more generic usage, like
|
/// Similar to `BuffKind`, but to mark a category (for more generic usage, like
|
||||||
/// positive/negative buffs).
|
/// positive/negative buffs).
|
||||||
@ -56,14 +63,18 @@ pub enum BuffCategory {
|
|||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub enum ModifierKind {
|
pub enum ModifierKind {
|
||||||
Additive,
|
Additive,
|
||||||
Multiplicative,
|
Fractional,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data indicating and configuring behaviour of a de/buff.
|
/// Data indicating and configuring behaviour of a de/buff.
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub enum BuffEffect {
|
pub enum BuffEffect {
|
||||||
/// Periodically damages or heals entity
|
/// Periodically damages or heals entity
|
||||||
HealthChangeOverTime { rate: f32, accumulated: f32 },
|
HealthChangeOverTime {
|
||||||
|
rate: f32,
|
||||||
|
accumulated: f32,
|
||||||
|
kind: ModifierKind,
|
||||||
|
},
|
||||||
/// Changes maximum health by a certain amount
|
/// Changes maximum health by a certain amount
|
||||||
MaxHealthModifier { value: f32, kind: ModifierKind },
|
MaxHealthModifier { value: f32, kind: ModifierKind },
|
||||||
}
|
}
|
||||||
@ -124,6 +135,7 @@ impl Buff {
|
|||||||
vec![BuffEffect::HealthChangeOverTime {
|
vec![BuffEffect::HealthChangeOverTime {
|
||||||
rate: -data.strength,
|
rate: -data.strength,
|
||||||
accumulated: 0.0,
|
accumulated: 0.0,
|
||||||
|
kind: ModifierKind::Additive,
|
||||||
}],
|
}],
|
||||||
data.duration,
|
data.duration,
|
||||||
),
|
),
|
||||||
@ -131,6 +143,15 @@ impl Buff {
|
|||||||
vec![BuffEffect::HealthChangeOverTime {
|
vec![BuffEffect::HealthChangeOverTime {
|
||||||
rate: data.strength,
|
rate: data.strength,
|
||||||
accumulated: 0.0,
|
accumulated: 0.0,
|
||||||
|
kind: ModifierKind::Additive,
|
||||||
|
}],
|
||||||
|
data.duration,
|
||||||
|
),
|
||||||
|
BuffKind::CampfireHeal => (
|
||||||
|
vec![BuffEffect::HealthChangeOverTime {
|
||||||
|
rate: data.strength,
|
||||||
|
accumulated: 0.0,
|
||||||
|
kind: ModifierKind::Fractional,
|
||||||
}],
|
}],
|
||||||
data.duration,
|
data.duration,
|
||||||
),
|
),
|
||||||
@ -255,6 +276,8 @@ impl Buffs {
|
|||||||
self.force_insert(self.id_counter, buff)
|
self.force_insert(self.id_counter, buff)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 = (BuffId, &Buff)> + '_ {
|
||||||
self.kinds
|
self.kinds
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
mod ability;
|
mod ability;
|
||||||
mod admin;
|
mod admin;
|
||||||
pub mod agent;
|
pub mod agent;
|
||||||
|
pub mod aura;
|
||||||
pub mod beam;
|
pub mod beam;
|
||||||
pub mod body;
|
pub mod body;
|
||||||
pub mod buff;
|
pub mod buff;
|
||||||
@ -28,6 +29,7 @@ pub mod visual;
|
|||||||
pub use ability::{CharacterAbility, CharacterAbilityType, ItemConfig, Loadout};
|
pub use ability::{CharacterAbility, CharacterAbilityType, ItemConfig, Loadout};
|
||||||
pub use admin::Admin;
|
pub use admin::Admin;
|
||||||
pub use agent::{Agent, Alignment};
|
pub use agent::{Agent, Alignment};
|
||||||
|
pub use aura::{Aura, AuraChange, AuraKind, Auras};
|
||||||
pub use beam::{Beam, BeamSegment};
|
pub use beam::{Beam, BeamSegment};
|
||||||
pub use body::{
|
pub use body::{
|
||||||
biped_large, bird_medium, bird_small, dragon, fish_medium, fish_small, golem, humanoid, object,
|
biped_large, bird_medium, bird_small, dragon, fish_medium, fish_small, golem, humanoid, object,
|
||||||
|
@ -116,6 +116,10 @@ pub enum ServerEvent {
|
|||||||
ChatCmd(EcsEntity, String),
|
ChatCmd(EcsEntity, String),
|
||||||
/// Send a chat message to the player from an npc or other player
|
/// Send a chat message to the player from an npc or other player
|
||||||
Chat(comp::UnresolvedChatMsg),
|
Chat(comp::UnresolvedChatMsg),
|
||||||
|
Aura {
|
||||||
|
entity: EcsEntity,
|
||||||
|
aura_change: comp::AuraChange,
|
||||||
|
},
|
||||||
Buff {
|
Buff {
|
||||||
entity: EcsEntity,
|
entity: EcsEntity,
|
||||||
buff_change: comp::BuffChange,
|
buff_change: comp::BuffChange,
|
||||||
|
@ -14,6 +14,7 @@ sum_type! {
|
|||||||
CanBuild(comp::CanBuild),
|
CanBuild(comp::CanBuild),
|
||||||
Stats(comp::Stats),
|
Stats(comp::Stats),
|
||||||
Buffs(comp::Buffs),
|
Buffs(comp::Buffs),
|
||||||
|
Auras(comp::Auras),
|
||||||
Energy(comp::Energy),
|
Energy(comp::Energy),
|
||||||
Health(comp::Health),
|
Health(comp::Health),
|
||||||
LightEmitter(comp::LightEmitter),
|
LightEmitter(comp::LightEmitter),
|
||||||
@ -45,6 +46,7 @@ sum_type! {
|
|||||||
CanBuild(PhantomData<comp::CanBuild>),
|
CanBuild(PhantomData<comp::CanBuild>),
|
||||||
Stats(PhantomData<comp::Stats>),
|
Stats(PhantomData<comp::Stats>),
|
||||||
Buffs(PhantomData<comp::Buffs>),
|
Buffs(PhantomData<comp::Buffs>),
|
||||||
|
Auras(PhantomData<comp::Auras>),
|
||||||
Energy(PhantomData<comp::Energy>),
|
Energy(PhantomData<comp::Energy>),
|
||||||
Health(PhantomData<comp::Health>),
|
Health(PhantomData<comp::Health>),
|
||||||
LightEmitter(PhantomData<comp::LightEmitter>),
|
LightEmitter(PhantomData<comp::LightEmitter>),
|
||||||
@ -76,6 +78,7 @@ impl sync::CompPacket for EcsCompPacket {
|
|||||||
EcsCompPacket::CanBuild(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::CanBuild(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::Stats(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::Stats(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::Buffs(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::Buffs(comp) => sync::handle_insert(comp, entity, world),
|
||||||
|
EcsCompPacket::Auras(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::Energy(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::Energy(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::Health(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::Health(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::LightEmitter(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::LightEmitter(comp) => sync::handle_insert(comp, entity, world),
|
||||||
@ -105,6 +108,7 @@ impl sync::CompPacket for EcsCompPacket {
|
|||||||
EcsCompPacket::CanBuild(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::CanBuild(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::Stats(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::Stats(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::Buffs(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::Buffs(comp) => sync::handle_modify(comp, entity, world),
|
||||||
|
EcsCompPacket::Auras(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::Energy(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::Energy(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::Health(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::Health(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::LightEmitter(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::LightEmitter(comp) => sync::handle_modify(comp, entity, world),
|
||||||
@ -134,6 +138,7 @@ impl sync::CompPacket for EcsCompPacket {
|
|||||||
EcsCompPhantom::CanBuild(_) => sync::handle_remove::<comp::CanBuild>(entity, world),
|
EcsCompPhantom::CanBuild(_) => sync::handle_remove::<comp::CanBuild>(entity, world),
|
||||||
EcsCompPhantom::Stats(_) => sync::handle_remove::<comp::Stats>(entity, world),
|
EcsCompPhantom::Stats(_) => sync::handle_remove::<comp::Stats>(entity, world),
|
||||||
EcsCompPhantom::Buffs(_) => sync::handle_remove::<comp::Buffs>(entity, world),
|
EcsCompPhantom::Buffs(_) => sync::handle_remove::<comp::Buffs>(entity, world),
|
||||||
|
EcsCompPhantom::Auras(_) => sync::handle_remove::<comp::Auras>(entity, world),
|
||||||
EcsCompPhantom::Energy(_) => sync::handle_remove::<comp::Energy>(entity, world),
|
EcsCompPhantom::Energy(_) => sync::handle_remove::<comp::Energy>(entity, world),
|
||||||
EcsCompPhantom::Health(_) => sync::handle_remove::<comp::Health>(entity, world),
|
EcsCompPhantom::Health(_) => sync::handle_remove::<comp::Health>(entity, world),
|
||||||
EcsCompPhantom::LightEmitter(_) => {
|
EcsCompPhantom::LightEmitter(_) => {
|
||||||
|
104
common/sys/src/aura.rs
Normal file
104
common/sys/src/aura.rs
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
use common::{
|
||||||
|
comp::{
|
||||||
|
aura::AuraKey, buff, AuraChange, AuraKind, Auras, BuffKind, Buffs, CharacterState, Pos,
|
||||||
|
},
|
||||||
|
event::{EventBus, ServerEvent},
|
||||||
|
resources::DeltaTime,
|
||||||
|
};
|
||||||
|
use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
pub struct Sys;
|
||||||
|
impl<'a> System<'a> for Sys {
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
type SystemData = (
|
||||||
|
Entities<'a>,
|
||||||
|
Read<'a, DeltaTime>,
|
||||||
|
ReadStorage<'a, Pos>,
|
||||||
|
Read<'a, EventBus<ServerEvent>>,
|
||||||
|
ReadStorage<'a, CharacterState>,
|
||||||
|
WriteStorage<'a, Auras>,
|
||||||
|
WriteStorage<'a, Buffs>,
|
||||||
|
);
|
||||||
|
|
||||||
|
fn run(
|
||||||
|
&mut self,
|
||||||
|
(entities, dt, positions, server_bus, character_states, mut auras, mut buffs): Self::SystemData,
|
||||||
|
) {
|
||||||
|
let mut server_emitter = server_bus.emitter();
|
||||||
|
|
||||||
|
auras.set_event_emission(false);
|
||||||
|
|
||||||
|
// Iterate through all entities with an aura
|
||||||
|
for (entity, pos, auras_comp) in (&entities, &positions, &mut auras).join() {
|
||||||
|
let mut expired_auras = Vec::<AuraKey>::new();
|
||||||
|
// Iterate through the auras attached to this entity
|
||||||
|
for (key, aura) in auras_comp.auras.iter_mut() {
|
||||||
|
// Tick the aura and subtract dt from it
|
||||||
|
if let Some(remaining_time) = &mut aura.duration {
|
||||||
|
if let Some(new_duration) =
|
||||||
|
remaining_time.checked_sub(Duration::from_secs_f32(dt.0))
|
||||||
|
{
|
||||||
|
*remaining_time = new_duration;
|
||||||
|
} else {
|
||||||
|
*remaining_time = Duration::default();
|
||||||
|
expired_auras.push(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (target_entity, target_pos, target_character_state_maybe, target_buffs) in
|
||||||
|
(&entities, &positions, character_states.maybe(), &mut buffs).join()
|
||||||
|
{
|
||||||
|
// Ensure entity is within the aura radius
|
||||||
|
if target_pos.0.distance_squared(pos.0) < aura.radius.powi(2) {
|
||||||
|
// TODO: When more aura kinds (besides Buff) are
|
||||||
|
// implemented, match on them here
|
||||||
|
match aura.aura_kind {
|
||||||
|
AuraKind::Buff {
|
||||||
|
kind,
|
||||||
|
data,
|
||||||
|
category,
|
||||||
|
source,
|
||||||
|
} => {
|
||||||
|
// Checks if the buff is not active so it isn't applied
|
||||||
|
// every tick, but rather only once it runs out
|
||||||
|
// TODO: Check for stronger buff of same kind so it can replace
|
||||||
|
// active buff.
|
||||||
|
if !target_buffs.contains(kind) {
|
||||||
|
// Conditions for different buffs are in this match
|
||||||
|
// statement
|
||||||
|
let apply_buff = match kind {
|
||||||
|
BuffKind::CampfireHeal => matches!(
|
||||||
|
target_character_state_maybe,
|
||||||
|
Some(CharacterState::Sit)
|
||||||
|
),
|
||||||
|
// Add other specific buff conditions here
|
||||||
|
_ => true,
|
||||||
|
};
|
||||||
|
if apply_buff {
|
||||||
|
use buff::*;
|
||||||
|
server_emitter.emit(ServerEvent::Buff {
|
||||||
|
entity: target_entity,
|
||||||
|
buff_change: BuffChange::Add(Buff::new(
|
||||||
|
kind,
|
||||||
|
data,
|
||||||
|
vec![category],
|
||||||
|
source,
|
||||||
|
)),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !expired_auras.is_empty() {
|
||||||
|
server_emitter.emit(ServerEvent::Aura {
|
||||||
|
entity,
|
||||||
|
aura_change: AuraChange::RemoveByKey(expired_auras),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auras.set_event_emission(true);
|
||||||
|
}
|
||||||
|
}
|
@ -79,7 +79,11 @@ impl<'a> System<'a> for Sys {
|
|||||||
// Now, execute the buff, based on it's delta
|
// Now, execute the buff, based on it's delta
|
||||||
for effect in &mut buff.effects {
|
for effect in &mut buff.effects {
|
||||||
match effect {
|
match effect {
|
||||||
BuffEffect::HealthChangeOverTime { rate, accumulated } => {
|
BuffEffect::HealthChangeOverTime {
|
||||||
|
rate,
|
||||||
|
accumulated,
|
||||||
|
kind,
|
||||||
|
} => {
|
||||||
*accumulated += *rate * dt.0;
|
*accumulated += *rate * dt.0;
|
||||||
// Apply damage only once a second (with a minimum of 1 damage), or
|
// Apply damage only once a second (with a minimum of 1 damage), or
|
||||||
// when a buff is removed
|
// when a buff is removed
|
||||||
@ -94,23 +98,26 @@ impl<'a> System<'a> for Sys {
|
|||||||
by: buff_owner,
|
by: buff_owner,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let amount = match *kind {
|
||||||
|
ModifierKind::Additive => *accumulated as i32,
|
||||||
|
ModifierKind::Fractional => {
|
||||||
|
(health.maximum() as f32 * *accumulated) as i32
|
||||||
|
},
|
||||||
|
};
|
||||||
server_emitter.emit(ServerEvent::Damage {
|
server_emitter.emit(ServerEvent::Damage {
|
||||||
entity,
|
entity,
|
||||||
change: HealthChange {
|
change: HealthChange { amount, cause },
|
||||||
amount: *accumulated as i32,
|
|
||||||
cause,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
*accumulated = 0.0;
|
*accumulated = 0.0;
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
BuffEffect::MaxHealthModifier { value, kind } => match kind {
|
BuffEffect::MaxHealthModifier { value, kind } => match kind {
|
||||||
ModifierKind::Multiplicative => {
|
|
||||||
health.set_maximum((health.maximum() as f32 * *value) as u32);
|
|
||||||
},
|
|
||||||
ModifierKind::Additive => {
|
ModifierKind::Additive => {
|
||||||
health.set_maximum((health.maximum() as f32 + *value) as u32);
|
health.set_maximum((health.maximum() as f32 + *value) as u32);
|
||||||
},
|
},
|
||||||
|
ModifierKind::Fractional => {
|
||||||
|
health.set_maximum((health.maximum() as f32 * *value) as u32);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#![feature(label_break_value, bool_to_option)]
|
#![feature(label_break_value, bool_to_option)]
|
||||||
|
|
||||||
pub mod agent;
|
pub mod agent;
|
||||||
|
mod aura;
|
||||||
mod beam;
|
mod beam;
|
||||||
mod buff;
|
mod buff;
|
||||||
pub mod character_behavior;
|
pub mod character_behavior;
|
||||||
@ -28,6 +29,7 @@ pub const PROJECTILE_SYS: &str = "projectile_sys";
|
|||||||
pub const SHOCKWAVE_SYS: &str = "shockwave_sys";
|
pub const SHOCKWAVE_SYS: &str = "shockwave_sys";
|
||||||
pub const STATS_SYS: &str = "stats_sys";
|
pub const STATS_SYS: &str = "stats_sys";
|
||||||
pub const BUFFS_SYS: &str = "buffs_sys";
|
pub const BUFFS_SYS: &str = "buffs_sys";
|
||||||
|
pub const AURAS_SYS: &str = "auras_sys";
|
||||||
|
|
||||||
pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) {
|
pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) {
|
||||||
dispatch_builder.add(agent::Sys, AGENT_SYS, &[]);
|
dispatch_builder.add(agent::Sys, AGENT_SYS, &[]);
|
||||||
@ -43,4 +45,5 @@ pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) {
|
|||||||
dispatch_builder.add(shockwave::Sys, SHOCKWAVE_SYS, &[PHYS_SYS]);
|
dispatch_builder.add(shockwave::Sys, SHOCKWAVE_SYS, &[PHYS_SYS]);
|
||||||
dispatch_builder.add(beam::Sys, BEAM_SYS, &[PHYS_SYS]);
|
dispatch_builder.add(beam::Sys, BEAM_SYS, &[PHYS_SYS]);
|
||||||
dispatch_builder.add(melee::Sys, MELEE_SYS, &[PROJECTILE_SYS]);
|
dispatch_builder.add(melee::Sys, MELEE_SYS, &[PROJECTILE_SYS]);
|
||||||
|
dispatch_builder.add(aura::Sys, AURAS_SYS, &[]);
|
||||||
}
|
}
|
||||||
|
@ -101,6 +101,7 @@ impl State {
|
|||||||
ecs.register::<comp::Player>();
|
ecs.register::<comp::Player>();
|
||||||
ecs.register::<comp::Stats>();
|
ecs.register::<comp::Stats>();
|
||||||
ecs.register::<comp::Buffs>();
|
ecs.register::<comp::Buffs>();
|
||||||
|
ecs.register::<comp::Auras>();
|
||||||
ecs.register::<comp::Energy>();
|
ecs.register::<comp::Energy>();
|
||||||
ecs.register::<comp::Health>();
|
ecs.register::<comp::Health>();
|
||||||
ecs.register::<comp::CanBuild>();
|
ecs.register::<comp::CanBuild>();
|
||||||
|
@ -9,7 +9,12 @@ use crate::{
|
|||||||
use chrono::{NaiveTime, Timelike};
|
use chrono::{NaiveTime, Timelike};
|
||||||
use common::{
|
use common::{
|
||||||
cmd::{ChatCommand, CHAT_COMMANDS, CHAT_SHORTCUTS},
|
cmd::{ChatCommand, CHAT_COMMANDS, CHAT_SHORTCUTS},
|
||||||
comp::{self, ChatType, Item, LightEmitter, WaypointArea},
|
comp::{
|
||||||
|
self,
|
||||||
|
aura::{Aura, AuraKind},
|
||||||
|
buff::{BuffCategory, BuffData, BuffKind, BuffSource},
|
||||||
|
ChatType, Item, LightEmitter, WaypointArea,
|
||||||
|
},
|
||||||
effect::Effect,
|
effect::Effect,
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
msg::{DisconnectReason, Notification, PlayerListUpdate, ServerGeneral},
|
msg::{DisconnectReason, Notification, PlayerListUpdate, ServerGeneral},
|
||||||
@ -23,7 +28,7 @@ use common::{
|
|||||||
};
|
};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use specs::{Builder, Entity as EcsEntity, Join, WorldExt};
|
use specs::{Builder, Entity as EcsEntity, Join, WorldExt};
|
||||||
use std::convert::TryFrom;
|
use std::{convert::TryFrom, time::Duration};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
use world::util::Sampler;
|
use world::util::Sampler;
|
||||||
|
|
||||||
@ -875,6 +880,16 @@ fn handle_spawn_campfire(
|
|||||||
animated: true,
|
animated: true,
|
||||||
})
|
})
|
||||||
.with(WaypointArea::default())
|
.with(WaypointArea::default())
|
||||||
|
.with(comp::Auras::new(Aura::new(
|
||||||
|
AuraKind::Buff {
|
||||||
|
kind: BuffKind::CampfireHeal,
|
||||||
|
data: BuffData::new(0.01, Some(Duration::from_secs(1))),
|
||||||
|
category: BuffCategory::Natural,
|
||||||
|
source: BuffSource::World,
|
||||||
|
},
|
||||||
|
5.0,
|
||||||
|
None,
|
||||||
|
)))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
server.notify_client(
|
server.notify_client(
|
||||||
|
@ -2,15 +2,19 @@ use crate::{sys, Server, StateExt};
|
|||||||
use common::{
|
use common::{
|
||||||
character::CharacterId,
|
character::CharacterId,
|
||||||
comp::{
|
comp::{
|
||||||
self, beam, shockwave, Agent, Alignment, Body, Gravity, Health, HomeChunk, Item, ItemDrop,
|
self,
|
||||||
|
aura::{Aura, AuraKind},
|
||||||
|
beam,
|
||||||
|
buff::{BuffCategory, BuffData, BuffKind, BuffSource},
|
||||||
|
group, shockwave, Agent, Alignment, Body, Gravity, Health, HomeChunk, Item, ItemDrop,
|
||||||
LightEmitter, Loadout, Ori, Pos, Projectile, Scale, Stats, Vel, WaypointArea,
|
LightEmitter, Loadout, Ori, Pos, Projectile, Scale, Stats, Vel, WaypointArea,
|
||||||
},
|
},
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
rtsim::RtSimEntity,
|
rtsim::RtSimEntity,
|
||||||
util::Dir,
|
util::Dir,
|
||||||
};
|
};
|
||||||
use comp::group;
|
|
||||||
use specs::{Builder, Entity as EcsEntity, WorldExt};
|
use specs::{Builder, Entity as EcsEntity, WorldExt};
|
||||||
|
use std::time::Duration;
|
||||||
use vek::{Rgb, Vec3};
|
use vek::{Rgb, Vec3};
|
||||||
|
|
||||||
pub fn handle_initialize_character(
|
pub fn handle_initialize_character(
|
||||||
@ -180,5 +184,15 @@ pub fn handle_create_waypoint(server: &mut Server, pos: Vec3<f32>) {
|
|||||||
})
|
})
|
||||||
.with(WaypointArea::default())
|
.with(WaypointArea::default())
|
||||||
.with(comp::Mass(10_f32.powi(10)))
|
.with(comp::Mass(10_f32.powi(10)))
|
||||||
|
.with(comp::Auras::new(Aura::new(
|
||||||
|
AuraKind::Buff {
|
||||||
|
kind: BuffKind::CampfireHeal,
|
||||||
|
data: BuffData::new(0.01, Some(Duration::from_secs(1))),
|
||||||
|
category: BuffCategory::Natural,
|
||||||
|
source: BuffSource::World,
|
||||||
|
},
|
||||||
|
5.0,
|
||||||
|
None,
|
||||||
|
)))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
use common::{
|
use common::{
|
||||||
assets::Asset,
|
assets::Asset,
|
||||||
comp::{
|
comp::{
|
||||||
self, buff,
|
self, aura, buff,
|
||||||
chat::{KillSource, KillType},
|
chat::{KillSource, KillType},
|
||||||
object, Alignment, Body, Energy, EnergyChange, Group, Health, HealthChange, HealthSource,
|
object, Alignment, Body, Energy, EnergyChange, Group, Health, HealthChange, HealthSource,
|
||||||
Item, Player, Pos, Stats,
|
Item, Player, Pos, Stats,
|
||||||
@ -740,6 +740,24 @@ pub fn handle_level_up(server: &mut Server, entity: EcsEntity, new_level: u32) {
|
|||||||
.push(Outcome::LevelUp { pos });
|
.push(Outcome::LevelUp { pos });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_aura(server: &mut Server, entity: EcsEntity, aura_change: aura::AuraChange) {
|
||||||
|
let ecs = &server.state.ecs();
|
||||||
|
let mut auras_all = ecs.write_storage::<comp::Auras>();
|
||||||
|
if let Some(auras) = auras_all.get_mut(entity) {
|
||||||
|
use aura::AuraChange;
|
||||||
|
match aura_change {
|
||||||
|
AuraChange::Add(new_aura) => {
|
||||||
|
auras.insert(new_aura);
|
||||||
|
},
|
||||||
|
AuraChange::RemoveByKey(keys) => {
|
||||||
|
for key in keys {
|
||||||
|
auras.remove(key);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handle_buff(server: &mut Server, entity: EcsEntity, buff_change: buff::BuffChange) {
|
pub fn handle_buff(server: &mut Server, entity: EcsEntity, buff_change: buff::BuffChange) {
|
||||||
let ecs = &server.state.ecs();
|
let ecs = &server.state.ecs();
|
||||||
let mut buffs_all = ecs.write_storage::<comp::Buffs>();
|
let mut buffs_all = ecs.write_storage::<comp::Buffs>();
|
||||||
|
@ -8,7 +8,7 @@ use entity_creation::{
|
|||||||
handle_loaded_character_data, handle_shockwave, handle_shoot,
|
handle_loaded_character_data, handle_shockwave, handle_shoot,
|
||||||
};
|
};
|
||||||
use entity_manipulation::{
|
use entity_manipulation::{
|
||||||
handle_buff, handle_damage, handle_delete, handle_destroy, handle_energy_change,
|
handle_aura, handle_buff, handle_damage, handle_delete, handle_destroy, handle_energy_change,
|
||||||
handle_explosion, handle_knockback, handle_land_on_ground, handle_level_up, handle_respawn,
|
handle_explosion, handle_knockback, handle_land_on_ground, handle_level_up, handle_respawn,
|
||||||
};
|
};
|
||||||
use group_manip::handle_group;
|
use group_manip::handle_group;
|
||||||
@ -147,6 +147,10 @@ impl Server {
|
|||||||
ServerEvent::Chat(msg) => {
|
ServerEvent::Chat(msg) => {
|
||||||
chat_messages.push(msg);
|
chat_messages.push(msg);
|
||||||
},
|
},
|
||||||
|
ServerEvent::Aura {
|
||||||
|
entity,
|
||||||
|
aura_change,
|
||||||
|
} => handle_aura(self, entity, aura_change),
|
||||||
ServerEvent::Buff {
|
ServerEvent::Buff {
|
||||||
entity,
|
entity,
|
||||||
buff_change,
|
buff_change,
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use super::SysTimer;
|
use super::SysTimer;
|
||||||
use common::{
|
use common::{
|
||||||
comp::{
|
comp::{
|
||||||
BeamSegment, Body, Buffs, CanBuild, CharacterState, Collider, Energy, Gravity, Group,
|
Auras, BeamSegment, Body, Buffs, CanBuild, CharacterState, Collider, Energy, Gravity,
|
||||||
Health, Item, LightEmitter, Loadout, Mass, MountState, Mounting, Ori, Player, Pos, Scale,
|
Group, Health, Item, LightEmitter, Loadout, Mass, MountState, Mounting, Ori, Player, Pos,
|
||||||
Shockwave, Stats, Sticky, Vel,
|
Scale, Shockwave, Stats, Sticky, Vel,
|
||||||
},
|
},
|
||||||
msg::EcsCompPacket,
|
msg::EcsCompPacket,
|
||||||
span,
|
span,
|
||||||
@ -45,6 +45,7 @@ pub struct TrackedComps<'a> {
|
|||||||
pub player: ReadStorage<'a, Player>,
|
pub player: ReadStorage<'a, Player>,
|
||||||
pub stats: ReadStorage<'a, Stats>,
|
pub stats: ReadStorage<'a, Stats>,
|
||||||
pub buffs: ReadStorage<'a, Buffs>,
|
pub buffs: ReadStorage<'a, Buffs>,
|
||||||
|
pub auras: ReadStorage<'a, Auras>,
|
||||||
pub energy: ReadStorage<'a, Energy>,
|
pub energy: ReadStorage<'a, Energy>,
|
||||||
pub health: ReadStorage<'a, Health>,
|
pub health: ReadStorage<'a, Health>,
|
||||||
pub can_build: ReadStorage<'a, CanBuild>,
|
pub can_build: ReadStorage<'a, CanBuild>,
|
||||||
@ -91,6 +92,10 @@ impl<'a> TrackedComps<'a> {
|
|||||||
.get(entity)
|
.get(entity)
|
||||||
.cloned()
|
.cloned()
|
||||||
.map(|c| comps.push(c.into()));
|
.map(|c| comps.push(c.into()));
|
||||||
|
self.auras
|
||||||
|
.get(entity)
|
||||||
|
.cloned()
|
||||||
|
.map(|c| comps.push(c.into()));
|
||||||
self.energy
|
self.energy
|
||||||
.get(entity)
|
.get(entity)
|
||||||
.cloned()
|
.cloned()
|
||||||
@ -168,6 +173,7 @@ pub struct ReadTrackers<'a> {
|
|||||||
pub player: ReadExpect<'a, UpdateTracker<Player>>,
|
pub player: ReadExpect<'a, UpdateTracker<Player>>,
|
||||||
pub stats: ReadExpect<'a, UpdateTracker<Stats>>,
|
pub stats: ReadExpect<'a, UpdateTracker<Stats>>,
|
||||||
pub buffs: ReadExpect<'a, UpdateTracker<Buffs>>,
|
pub buffs: ReadExpect<'a, UpdateTracker<Buffs>>,
|
||||||
|
pub auras: ReadExpect<'a, UpdateTracker<Auras>>,
|
||||||
pub energy: ReadExpect<'a, UpdateTracker<Energy>>,
|
pub energy: ReadExpect<'a, UpdateTracker<Energy>>,
|
||||||
pub health: ReadExpect<'a, UpdateTracker<Health>>,
|
pub health: ReadExpect<'a, UpdateTracker<Health>>,
|
||||||
pub can_build: ReadExpect<'a, UpdateTracker<CanBuild>>,
|
pub can_build: ReadExpect<'a, UpdateTracker<CanBuild>>,
|
||||||
@ -200,6 +206,7 @@ impl<'a> ReadTrackers<'a> {
|
|||||||
.with_component(&comps.uid, &*self.player, &comps.player, filter)
|
.with_component(&comps.uid, &*self.player, &comps.player, filter)
|
||||||
.with_component(&comps.uid, &*self.stats, &comps.stats, filter)
|
.with_component(&comps.uid, &*self.stats, &comps.stats, filter)
|
||||||
.with_component(&comps.uid, &*self.buffs, &comps.buffs, filter)
|
.with_component(&comps.uid, &*self.buffs, &comps.buffs, filter)
|
||||||
|
.with_component(&comps.uid, &*self.auras, &comps.auras, filter)
|
||||||
.with_component(&comps.uid, &*self.energy, &comps.energy, filter)
|
.with_component(&comps.uid, &*self.energy, &comps.energy, filter)
|
||||||
.with_component(&comps.uid, &*self.health, &comps.health, filter)
|
.with_component(&comps.uid, &*self.health, &comps.health, filter)
|
||||||
.with_component(&comps.uid, &*self.can_build, &comps.can_build, filter)
|
.with_component(&comps.uid, &*self.can_build, &comps.can_build, filter)
|
||||||
@ -239,6 +246,7 @@ pub struct WriteTrackers<'a> {
|
|||||||
player: WriteExpect<'a, UpdateTracker<Player>>,
|
player: WriteExpect<'a, UpdateTracker<Player>>,
|
||||||
stats: WriteExpect<'a, UpdateTracker<Stats>>,
|
stats: WriteExpect<'a, UpdateTracker<Stats>>,
|
||||||
buffs: WriteExpect<'a, UpdateTracker<Buffs>>,
|
buffs: WriteExpect<'a, UpdateTracker<Buffs>>,
|
||||||
|
auras: WriteExpect<'a, UpdateTracker<Auras>>,
|
||||||
energy: WriteExpect<'a, UpdateTracker<Energy>>,
|
energy: WriteExpect<'a, UpdateTracker<Energy>>,
|
||||||
health: WriteExpect<'a, UpdateTracker<Health>>,
|
health: WriteExpect<'a, UpdateTracker<Health>>,
|
||||||
can_build: WriteExpect<'a, UpdateTracker<CanBuild>>,
|
can_build: WriteExpect<'a, UpdateTracker<CanBuild>>,
|
||||||
@ -265,6 +273,7 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) {
|
|||||||
trackers.player.record_changes(&comps.player);
|
trackers.player.record_changes(&comps.player);
|
||||||
trackers.stats.record_changes(&comps.stats);
|
trackers.stats.record_changes(&comps.stats);
|
||||||
trackers.buffs.record_changes(&comps.buffs);
|
trackers.buffs.record_changes(&comps.buffs);
|
||||||
|
trackers.auras.record_changes(&comps.auras);
|
||||||
trackers.energy.record_changes(&comps.energy);
|
trackers.energy.record_changes(&comps.energy);
|
||||||
trackers.health.record_changes(&comps.health);
|
trackers.health.record_changes(&comps.health);
|
||||||
trackers.can_build.record_changes(&comps.can_build);
|
trackers.can_build.record_changes(&comps.can_build);
|
||||||
@ -302,6 +311,7 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) {
|
|||||||
log_counts!(uid, "Uids");
|
log_counts!(uid, "Uids");
|
||||||
log_counts!(body, "Bodies");
|
log_counts!(body, "Bodies");
|
||||||
log_counts!(buffs, "Buffs");
|
log_counts!(buffs, "Buffs");
|
||||||
|
log_counts!(auras, "Auras");
|
||||||
log_counts!(player, "Players");
|
log_counts!(player, "Players");
|
||||||
log_counts!(stats, "Stats");
|
log_counts!(stats, "Stats");
|
||||||
log_counts!(energy, "Energies");
|
log_counts!(energy, "Energies");
|
||||||
@ -328,6 +338,7 @@ pub fn register_trackers(world: &mut World) {
|
|||||||
world.register_tracker::<Player>();
|
world.register_tracker::<Player>();
|
||||||
world.register_tracker::<Stats>();
|
world.register_tracker::<Stats>();
|
||||||
world.register_tracker::<Buffs>();
|
world.register_tracker::<Buffs>();
|
||||||
|
world.register_tracker::<Auras>();
|
||||||
world.register_tracker::<Energy>();
|
world.register_tracker::<Energy>();
|
||||||
world.register_tracker::<Health>();
|
world.register_tracker::<Health>();
|
||||||
world.register_tracker::<CanBuild>();
|
world.register_tracker::<CanBuild>();
|
||||||
|
@ -184,6 +184,7 @@ impl<'a> Widget for BuffsBar<'a> {
|
|||||||
BuffKind::Regeneration { .. } => self.imgs.buff_plus_0,
|
BuffKind::Regeneration { .. } => self.imgs.buff_plus_0,
|
||||||
BuffKind::Saturation { .. } => self.imgs.buff_saturation_0,
|
BuffKind::Saturation { .. } => self.imgs.buff_saturation_0,
|
||||||
BuffKind::Potion { .. } => self.imgs.buff_potion_0,
|
BuffKind::Potion { .. } => self.imgs.buff_potion_0,
|
||||||
|
BuffKind::CampfireHeal { .. } => self.imgs.buff_campfire_heal_0,
|
||||||
_ => self.imgs.missing_icon,
|
_ => self.imgs.missing_icon,
|
||||||
};
|
};
|
||||||
let buff_widget = Image::new(buff_img).w_h(40.0, 40.0);
|
let buff_widget = Image::new(buff_img).w_h(40.0, 40.0);
|
||||||
@ -211,6 +212,9 @@ impl<'a> Widget for BuffsBar<'a> {
|
|||||||
localized_strings.get("buff.title.saturation")
|
localized_strings.get("buff.title.saturation")
|
||||||
},
|
},
|
||||||
BuffKind::Potion { .. } => localized_strings.get("buff.title.potion"),
|
BuffKind::Potion { .. } => localized_strings.get("buff.title.potion"),
|
||||||
|
BuffKind::CampfireHeal { .. } => {
|
||||||
|
localized_strings.get("buff.title.campfire_heal")
|
||||||
|
},
|
||||||
_ => localized_strings.get("buff.title.missing"),
|
_ => localized_strings.get("buff.title.missing"),
|
||||||
};
|
};
|
||||||
let remaining_time = if current_duration.is_none() {
|
let remaining_time = if current_duration.is_none() {
|
||||||
@ -225,6 +229,9 @@ impl<'a> Widget for BuffsBar<'a> {
|
|||||||
localized_strings.get("buff.desc.saturation")
|
localized_strings.get("buff.desc.saturation")
|
||||||
},
|
},
|
||||||
BuffKind::Potion { .. } => localized_strings.get("buff.desc.potion"),
|
BuffKind::Potion { .. } => localized_strings.get("buff.desc.potion"),
|
||||||
|
BuffKind::CampfireHeal { .. } => {
|
||||||
|
localized_strings.get("buff.desc.campfire_heal")
|
||||||
|
},
|
||||||
_ => localized_strings.get("buff.desc.missing"),
|
_ => localized_strings.get("buff.desc.missing"),
|
||||||
};
|
};
|
||||||
let desc = format!("{}\n\n{}\n\n{}", desc_txt, remaining_time, click_to_remove);
|
let desc = format!("{}\n\n{}\n\n{}", desc_txt, remaining_time, click_to_remove);
|
||||||
@ -385,6 +392,7 @@ impl<'a> Widget for BuffsBar<'a> {
|
|||||||
BuffKind::Bleeding { .. } => self.imgs.debuff_bleed_0,
|
BuffKind::Bleeding { .. } => self.imgs.debuff_bleed_0,
|
||||||
BuffKind::Cursed { .. } => self.imgs.debuff_skull_0,
|
BuffKind::Cursed { .. } => self.imgs.debuff_skull_0,
|
||||||
BuffKind::Potion { .. } => self.imgs.buff_potion_0,
|
BuffKind::Potion { .. } => self.imgs.buff_potion_0,
|
||||||
|
BuffKind::CampfireHeal { .. } => self.imgs.buff_campfire_heal_0,
|
||||||
};
|
};
|
||||||
let buff_widget = Image::new(buff_img).w_h(40.0, 40.0);
|
let buff_widget = Image::new(buff_img).w_h(40.0, 40.0);
|
||||||
// Sort buffs into rows of 6 slots
|
// Sort buffs into rows of 6 slots
|
||||||
@ -412,6 +420,9 @@ impl<'a> Widget for BuffsBar<'a> {
|
|||||||
},
|
},
|
||||||
BuffKind::Potion { .. } => localized_strings.get("buff.title.potion"),
|
BuffKind::Potion { .. } => localized_strings.get("buff.title.potion"),
|
||||||
BuffKind::Bleeding { .. } => localized_strings.get("debuff.title.bleed"),
|
BuffKind::Bleeding { .. } => localized_strings.get("debuff.title.bleed"),
|
||||||
|
BuffKind::CampfireHeal { .. } => {
|
||||||
|
localized_strings.get("buff.title.campfire_heal")
|
||||||
|
},
|
||||||
_ => localized_strings.get("buff.title.missing"),
|
_ => localized_strings.get("buff.title.missing"),
|
||||||
};
|
};
|
||||||
let remaining_time = if current_duration.is_none() {
|
let remaining_time = if current_duration.is_none() {
|
||||||
@ -427,6 +438,9 @@ impl<'a> Widget for BuffsBar<'a> {
|
|||||||
},
|
},
|
||||||
BuffKind::Potion { .. } => localized_strings.get("buff.desc.potion"),
|
BuffKind::Potion { .. } => localized_strings.get("buff.desc.potion"),
|
||||||
BuffKind::Bleeding { .. } => localized_strings.get("debuff.desc.bleed"),
|
BuffKind::Bleeding { .. } => localized_strings.get("debuff.desc.bleed"),
|
||||||
|
BuffKind::CampfireHeal { .. } => {
|
||||||
|
localized_strings.get("buff.desc.campfire_heal")
|
||||||
|
},
|
||||||
_ => localized_strings.get("buff.desc.missing"),
|
_ => localized_strings.get("buff.desc.missing"),
|
||||||
};
|
};
|
||||||
let desc = if buff.is_buff {
|
let desc = if buff.is_buff {
|
||||||
|
@ -486,6 +486,7 @@ impl<'a> Widget for Group<'a> {
|
|||||||
BuffKind::Bleeding { .. } => self.imgs.debuff_bleed_0,
|
BuffKind::Bleeding { .. } => self.imgs.debuff_bleed_0,
|
||||||
BuffKind::Cursed { .. } => self.imgs.debuff_skull_0,
|
BuffKind::Cursed { .. } => self.imgs.debuff_skull_0,
|
||||||
BuffKind::Potion { .. } => self.imgs.buff_potion_0,
|
BuffKind::Potion { .. } => self.imgs.buff_potion_0,
|
||||||
|
BuffKind::CampfireHeal { .. } => self.imgs.buff_campfire_heal_0,
|
||||||
};
|
};
|
||||||
let buff_widget = Image::new(buff_img).w_h(15.0, 15.0);
|
let buff_widget = Image::new(buff_img).w_h(15.0, 15.0);
|
||||||
let buff_widget = if let Some(id) = prev_id {
|
let buff_widget = if let Some(id) = prev_id {
|
||||||
|
@ -375,6 +375,7 @@ image_ids! {
|
|||||||
buff_plus_0: "voxygen.element.icons.de_buffs.buff_plus_0",
|
buff_plus_0: "voxygen.element.icons.de_buffs.buff_plus_0",
|
||||||
buff_saturation_0: "voxygen.element.icons.de_buffs.buff_saturation_0",
|
buff_saturation_0: "voxygen.element.icons.de_buffs.buff_saturation_0",
|
||||||
buff_potion_0: "voxygen.element.icons.de_buffs.buff_potion_0",
|
buff_potion_0: "voxygen.element.icons.de_buffs.buff_potion_0",
|
||||||
|
buff_campfire_heal_0: "voxygen.element.icons.de_buffs.buff_campfire_heal_0",
|
||||||
|
|
||||||
// Debuffs
|
// Debuffs
|
||||||
debuff_skull_0: "voxygen.element.icons.de_buffs.debuff_skull_0",
|
debuff_skull_0: "voxygen.element.icons.de_buffs.debuff_skull_0",
|
||||||
|
@ -247,6 +247,7 @@ impl<'a> Widget for Overhead<'a> {
|
|||||||
BuffKind::Bleeding { .. } => self.imgs.debuff_bleed_0,
|
BuffKind::Bleeding { .. } => self.imgs.debuff_bleed_0,
|
||||||
BuffKind::Cursed { .. } => self.imgs.debuff_skull_0,
|
BuffKind::Cursed { .. } => self.imgs.debuff_skull_0,
|
||||||
BuffKind::Potion { .. } => self.imgs.buff_potion_0,
|
BuffKind::Potion { .. } => self.imgs.buff_potion_0,
|
||||||
|
BuffKind::CampfireHeal { .. } => self.imgs.buff_campfire_heal_0,
|
||||||
};
|
};
|
||||||
let buff_widget = Image::new(buff_img).w_h(20.0, 20.0);
|
let buff_widget = Image::new(buff_img).w_h(20.0, 20.0);
|
||||||
// Sort buffs into rows of 5 slots
|
// Sort buffs into rows of 5 slots
|
||||||
|
Loading…
Reference in New Issue
Block a user