From 4c79936c071a6a607b0b0bb933a645acd856480e Mon Sep 17 00:00:00 2001 From: Sam Date: Sat, 11 Mar 2023 16:44:57 -0500 Subject: [PATCH] Added wrapper type to durations related to buffs and auras. --- common/src/combat.rs | 3 ++- common/src/comp/ability.rs | 5 +++-- common/src/comp/aura.rs | 14 ++++++------- common/src/comp/buff.rs | 25 ++++++++++++------------ common/src/resources.rs | 15 ++++++++++++++ common/src/states/basic_aura.rs | 3 ++- common/src/states/self_buff.rs | 3 ++- common/systems/src/buff.rs | 10 +++++----- server/agent/src/action_nodes.rs | 2 +- server/src/cmd.rs | 8 ++++---- server/src/events/entity_creation.rs | 6 +++--- server/src/events/entity_manipulation.rs | 4 ++-- server/src/state_ext.rs | 4 ++-- voxygen/src/hud/buffs.rs | 6 +++--- voxygen/src/hud/group.rs | 2 +- voxygen/src/hud/mod.rs | 4 ++-- voxygen/src/hud/overhead.rs | 2 +- voxygen/src/hud/util.rs | 2 +- voxygen/src/scene/particle.rs | 4 ++-- 19 files changed, 71 insertions(+), 51 deletions(-) diff --git a/common/src/combat.rs b/common/src/combat.rs index 0d13f9a1a2..347343f6de 100644 --- a/common/src/combat.rs +++ b/common/src/combat.rs @@ -13,6 +13,7 @@ use crate::{ }, event::ServerEvent, outcome::Outcome, + resources::Secs, states::utils::StageSection, uid::{Uid, UidAllocator}, util::Dir, @@ -1049,7 +1050,7 @@ impl CombatBuff { self.kind, BuffData::new( self.strength.to_strength(damage, strength_modifier), - Some(self.dur_secs as f64), + Some(Secs(self.dur_secs as f64)), None, ), Vec::new(), diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index cbd243b179..de6bbdc6f7 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -20,6 +20,7 @@ use crate::{ }, Body, CharacterState, LightEmitter, StateUpdate, }, + resources::Secs, states::{ behavior::JoinData, utils::{AbilityInfo, StageSection}, @@ -696,7 +697,7 @@ pub enum CharacterAbility { recover_duration: f32, targets: combat::GroupTarget, auras: Vec, - aura_duration: f64, + aura_duration: Secs, range: f32, energy_cost: f32, scales_with_combo: bool, @@ -728,7 +729,7 @@ pub enum CharacterAbility { recover_duration: f32, buff_kind: buff::BuffKind, buff_strength: f32, - buff_duration: Option, + buff_duration: Option, energy_cost: f32, #[serde(default)] meta: AbilityMeta, diff --git a/common/src/comp/aura.rs b/common/src/comp/aura.rs index 8b95bd02c0..618abddff4 100644 --- a/common/src/comp/aura.rs +++ b/common/src/comp/aura.rs @@ -1,7 +1,7 @@ use crate::{ combat::GroupTarget, comp::buff::{BuffCategory, BuffData, BuffKind, BuffSource}, - resources::Time, + resources::{Secs, Time}, uid::Uid, }; use serde::{Deserialize, Serialize}; @@ -92,12 +92,12 @@ impl From<(Option, Option<&Uid>)> for AuraTarget { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct AuraData { - pub duration: Option, + pub duration: Option, } impl AuraData { #[must_use] - fn new(duration: Option) -> Self { Self { duration } } + fn new(duration: Option) -> Self { Self { duration } } } impl Aura { @@ -105,14 +105,14 @@ impl Aura { pub fn new( aura_kind: AuraKind, radius: f32, - duration: Option, + duration: Option, target: AuraTarget, time: Time, ) -> Self { Self { aura_kind, radius, - end_time: duration.map(|dur| Time(time.0 + dur)), + end_time: duration.map(|dur| Time(time.0 + dur.0)), target, data: AuraData::new(duration), } @@ -143,7 +143,7 @@ impl Auras { pub struct AuraBuffConstructor { pub kind: BuffKind, pub strength: f32, - pub duration: Option, + pub duration: Option, pub category: BuffCategory, } @@ -152,7 +152,7 @@ impl AuraBuffConstructor { self, uid: &Uid, radius: f32, - duration: Option, + duration: Option, target: AuraTarget, time: Time, ) -> Aura { diff --git a/common/src/comp/buff.rs b/common/src/comp/buff.rs index 72024114b5..36ea5e15bc 100644 --- a/common/src/comp/buff.rs +++ b/common/src/comp/buff.rs @@ -1,7 +1,7 @@ #![allow(clippy::nonstandard_macro_braces)] //tmp as of false positive !? use crate::{ comp::{aura::AuraKey, Stats}, - resources::Time, + resources::{Secs, Time}, uid::Uid, }; use core::cmp::Ordering; @@ -147,13 +147,13 @@ impl BuffKind { #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] pub struct BuffData { pub strength: f32, - pub duration: Option, - pub delay: Option, + pub duration: Option, + pub delay: Option, } #[cfg(not(target_arch = "wasm32"))] impl BuffData { - pub fn new(strength: f32, duration: Option, delay: Option) -> Self { + pub fn new(strength: f32, duration: Option, delay: Option) -> Self { Self { strength, duration, @@ -369,14 +369,14 @@ impl Buff { BuffKind::Parried => vec![BuffEffect::AttackSpeed(0.5)], BuffKind::PotionSickness => vec![BuffEffect::HealReduction(data.strength)], }; - let start_time = Time(time.0 + data.delay.unwrap_or(0.0)); + let start_time = Time(time.0 + data.delay.map_or(0.0, |delay| delay.0)); let end_time = if cat_ids .iter() .any(|cat_id| matches!(cat_id, BuffCategory::FromActiveAura(..))) { None } else { - data.duration.map(|dur| Time(start_time.0 + dur)) + data.duration.map(|dur| Time(start_time.0 + dur.0)) }; Buff { kind, @@ -390,7 +390,7 @@ impl Buff { } /// Calculate how much time has elapsed since the buff was applied - pub fn elapsed(&self, time: Time) -> f64 { time.0 - self.start_time.0 } + pub fn elapsed(&self, time: Time) -> Secs { Secs(time.0 - self.start_time.0) } } #[cfg(not(target_arch = "wasm32"))] @@ -603,6 +603,7 @@ pub mod tests { Vec::new(), BuffSource::Unknown, time, + None, ) } @@ -611,7 +612,7 @@ pub mod tests { /// queue has correct total duration fn test_queueable_buffs_three() { let mut buff_comp: Buffs = Default::default(); - let buff_data = BuffData::new(1.0, Some(10.0), None); + let buff_data = BuffData::new(1.0, Some(Secs(10.0)), None); let time_a = Time(0.0); buff_comp.insert(create_test_queueable_buff(buff_data, time_a), time_a); let time_b = Time(6.0); @@ -642,8 +643,8 @@ pub mod tests { /// queueable buff is added, delayed buff has correct start time fn test_queueable_buff_delay_start() { let mut buff_comp: Buffs = Default::default(); - let queued_buff_data = BuffData::new(1.0, Some(10.0), Some(10.0)); - let buff_data = BuffData::new(1.0, Some(10.0), None); + let queued_buff_data = BuffData::new(1.0, Some(Secs(10.0)), Some(Secs(10.0))); + let buff_data = BuffData::new(1.0, Some(Secs(10.0)), None); let time_a = Time(0.0); buff_comp.insert(create_test_queueable_buff(queued_buff_data, time_a), time_a); let time_b = Time(6.0); @@ -674,8 +675,8 @@ pub mod tests { /// does not move delayed buff start or end times fn test_queueable_buff_long_delay() { let mut buff_comp: Buffs = Default::default(); - let queued_buff_data = BuffData::new(1.0, Some(10.0), Some(50.0)); - let buff_data = BuffData::new(1.0, Some(10.0), None); + let queued_buff_data = BuffData::new(1.0, Some(Secs(10.0)), Some(Secs(50.0))); + let buff_data = BuffData::new(1.0, Some(Secs(10.0)), None); let time_a = Time(0.0); buff_comp.insert(create_test_queueable_buff(queued_buff_data, time_a), time_a); let time_b = Time(10.0); diff --git a/common/src/resources.rs b/common/src/resources.rs index 7e984ed569..4722c4e8b4 100644 --- a/common/src/resources.rs +++ b/common/src/resources.rs @@ -3,6 +3,7 @@ use crate::comp::Pos; use serde::{Deserialize, Serialize}; #[cfg(not(target_arch = "wasm32"))] use specs::Entity; +use std::ops::{Mul, MulAssign}; /// A resource that stores the time of day. #[derive(Copy, Clone, Debug, Serialize, Deserialize, Default)] @@ -16,6 +17,20 @@ pub struct Time(pub f64); #[derive(Default)] pub struct DeltaTime(pub f32); +/// A resource used to indicate a duration of time, in seconds +#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, PartialEq)] +#[serde(transparent)] +pub struct Secs(pub f64); + +impl Mul for Secs { + type Output = Self; + + fn mul(self, mult: f64) -> Self { Self(self.0 * mult) } +} +impl MulAssign for Secs { + fn mul_assign(&mut self, mult: f64) { *self = *self * mult; } +} + #[cfg(not(target_arch = "wasm32"))] #[derive(Default)] pub struct EntitiesDiedLastTick(pub Vec<(Entity, Pos)>); diff --git a/common/src/states/basic_aura.rs b/common/src/states/basic_aura.rs index f97ded1589..dbc5eb0124 100644 --- a/common/src/states/basic_aura.rs +++ b/common/src/states/basic_aura.rs @@ -6,6 +6,7 @@ use crate::{ CharacterState, StateUpdate, }, event::ServerEvent, + resources::Secs, states::{ behavior::{CharacterBehavior, JoinData}, utils::*, @@ -28,7 +29,7 @@ pub struct StaticData { /// Has information used to construct the auras pub auras: Vec, /// How long aura lasts - pub aura_duration: f64, + pub aura_duration: Secs, /// Radius of aura pub range: f32, /// What key is used to press ability diff --git a/common/src/states/self_buff.rs b/common/src/states/self_buff.rs index 8334bdb89d..c21fdb570f 100644 --- a/common/src/states/self_buff.rs +++ b/common/src/states/self_buff.rs @@ -5,6 +5,7 @@ use crate::{ CharacterState, StateUpdate, }, event::ServerEvent, + resources::Secs, states::{ behavior::{CharacterBehavior, JoinData}, utils::*, @@ -27,7 +28,7 @@ pub struct StaticData { /// Strength of the created buff pub buff_strength: f32, /// How long buff lasts - pub buff_duration: Option, + pub buff_duration: Option, /// What key is used to press ability pub ability_info: AbilityInfo, } diff --git a/common/systems/src/buff.rs b/common/systems/src/buff.rs index 13899c7f89..6abdb31779 100644 --- a/common/systems/src/buff.rs +++ b/common/systems/src/buff.rs @@ -13,7 +13,7 @@ use common::{ Pos, Stats, }, event::{Emitter, EventBus, ServerEvent}, - resources::{DeltaTime, Time}, + resources::{DeltaTime, Secs, Time}, terrain::SpriteKind, uid::{Uid, UidAllocator}, Damage, DamageSource, @@ -146,7 +146,7 @@ impl<'a> System<'a> for Sys { entity, buff_change: BuffChange::Add(Buff::new( BuffKind::Ensnared, - BuffData::new(1.0, Some(1.0), None), + BuffData::new(1.0, Some(Secs(1.0)), None), Vec::new(), BuffSource::World, *read_data.time, @@ -163,7 +163,7 @@ impl<'a> System<'a> for Sys { entity, buff_change: BuffChange::Add(Buff::new( BuffKind::Bleeding, - BuffData::new(1.0, Some(6.0), None), + BuffData::new(1.0, Some(Secs(6.0)), None), Vec::new(), BuffSource::World, *read_data.time, @@ -180,7 +180,7 @@ impl<'a> System<'a> for Sys { entity, buff_change: BuffChange::Add(Buff::new( BuffKind::Bleeding, - BuffData::new(15.0, Some(0.1), None), + BuffData::new(15.0, Some(Secs(0.1)), None), Vec::new(), BuffSource::World, *read_data.time, @@ -192,7 +192,7 @@ impl<'a> System<'a> for Sys { entity, buff_change: BuffChange::Add(Buff::new( BuffKind::Frozen, - BuffData::new(0.2, Some(1.0), None), + BuffData::new(0.2, Some(Secs(1.0)), None), Vec::new(), BuffSource::World, *read_data.time, diff --git a/server/agent/src/action_nodes.rs b/server/agent/src/action_nodes.rs index 9a18248732..c47e900879 100644 --- a/server/agent/src/action_nodes.rs +++ b/server/agent/src/action_nodes.rs @@ -558,7 +558,7 @@ impl<'a> AgentData<'a> { Effect::Buff(BuffEffect { kind, data, .. }) if matches!(kind, Regeneration | Saturation | Potion) => { - value += data.strength * data.duration.map_or(0.0, |d| d as f32); + value += data.strength * data.duration.map_or(0.0, |d| d.0 as f32); }, Effect::Buff(BuffEffect { kind, .. }) if matches!(kind, PotionSickness) => diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 307afc7529..6289bb40fd 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -42,7 +42,7 @@ use common::{ npc::{self, get_npc_name}, outcome::Outcome, parse_cmd_args, - resources::{BattleMode, PlayerPhysicsSettings, Time, TimeOfDay}, + resources::{BattleMode, PlayerPhysicsSettings, Secs, Time, TimeOfDay}, terrain::{Block, BlockKind, CoordinateConversions, SpriteKind, TerrainChunkSize}, uid::{Uid, UidAllocator}, vol::ReadVol, @@ -1479,7 +1479,7 @@ fn handle_spawn_campfire( Aura::new( AuraKind::Buff { kind: BuffKind::CampfireHeal, - data: BuffData::new(0.02, Some(1.0), None), + data: BuffData::new(0.02, Some(Secs(1.0)), None), category: BuffCategory::Natural, source: BuffSource::World, }, @@ -1491,7 +1491,7 @@ fn handle_spawn_campfire( Aura::new( AuraKind::Buff { kind: BuffKind::Burning, - data: BuffData::new(2.0, Some(10.0), None), + data: BuffData::new(2.0, Some(Secs(10.0)), None), category: BuffCategory::Natural, source: BuffSource::World, }, @@ -3522,7 +3522,7 @@ fn handle_buff( if let (Some(buff), strength, duration) = parse_cmd_args!(args, String, f32, f64) { let strength = strength.unwrap_or(0.01); let duration = duration.unwrap_or(1.0); - let buffdata = BuffData::new(strength, Some(duration), None); + let buffdata = BuffData::new(strength, Some(Secs(duration)), None); if buff != "all" { cast_buff(&buff, buffdata, server, target) } else { diff --git a/server/src/events/entity_creation.rs b/server/src/events/entity_creation.rs index 18990d6079..d174b77c5d 100644 --- a/server/src/events/entity_creation.rs +++ b/server/src/events/entity_creation.rs @@ -14,7 +14,7 @@ use common::{ event::{EventBus, UpdateCharacterMetadata}, lottery::LootSpec, outcome::Outcome, - resources::Time, + resources::{Secs, Time}, rtsim::RtSimEntity, uid::Uid, util::Dir, @@ -286,7 +286,7 @@ pub fn handle_create_waypoint(server: &mut Server, pos: Vec3) { Aura::new( AuraKind::Buff { kind: BuffKind::CampfireHeal, - data: BuffData::new(0.02, Some(1.0), None), + data: BuffData::new(0.02, Some(Secs(1.0)), None), category: BuffCategory::Natural, source: BuffSource::World, }, @@ -298,7 +298,7 @@ pub fn handle_create_waypoint(server: &mut Server, pos: Vec3) { Aura::new( AuraKind::Buff { kind: BuffKind::Burning, - data: BuffData::new(2.0, Some(10.0), None), + data: BuffData::new(2.0, Some(Secs(10.0)), None), category: BuffCategory::Natural, source: BuffSource::World, }, diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index b649b1f9e7..b45295b496 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -25,7 +25,7 @@ use common::{ }, event::{EventBus, ServerEvent}, outcome::{HealthChangeInfo, Outcome}, - resources::Time, + resources::{Secs, Time}, rtsim::RtSimEntity, states::utils::{AbilityInfo, StageSection}, terrain::{Block, BlockKind, TerrainGrid}, @@ -1311,7 +1311,7 @@ pub fn handle_parry_hook(server: &Server, defender: EcsEntity, attacker: Option< .map_or(0.5, |dur| dur.as_secs_f32()) .max(0.5) .mul(2.0); - let data = buff::BuffData::new(1.0, Some(duration as f64), None); + let data = buff::BuffData::new(1.0, Some(Secs(duration as f64)), None); let source = if let Some(uid) = ecs.read_storage::().get(defender) { BuffSource::Character { by: *uid } } else { diff --git a/server/src/state_ext.rs b/server/src/state_ext.rs index 17e4ef8706..c27781f7b4 100644 --- a/server/src/state_ext.rs +++ b/server/src/state_ext.rs @@ -23,7 +23,7 @@ use common::{ effect::Effect, link::{Link, LinkHandle}, mounting::Mounting, - resources::{Time, TimeOfDay}, + resources::{Secs, Time, TimeOfDay}, slowjob::SlowJobPool, uid::{Uid, UidAllocator}, LoadoutBuilder, ViewDistances, @@ -439,7 +439,7 @@ impl StateExt for State { .with(Auras::new(vec![Aura::new( AuraKind::Buff { kind: BuffKind::Invulnerability, - data: BuffData::new(1.0, Some(1.0), None), + data: BuffData::new(1.0, Some(Secs(1.0)), None), category: BuffCategory::Natural, source: BuffSource::World, }, diff --git a/voxygen/src/hud/buffs.rs b/voxygen/src/hud/buffs.rs index 9cbd474924..9e501e800f 100644 --- a/voxygen/src/hud/buffs.rs +++ b/voxygen/src/hud/buffs.rs @@ -227,7 +227,7 @@ impl<'a> Widget for BuffsBar<'a> { let max_duration = buff.kind.max_duration(); let current_duration = buff.end_time.map(|end| end - self.time.0); let duration_percentage = current_duration.map_or(1000.0, |cur| { - max_duration.map_or(1000.0, |max| cur / max * 1000.0) + max_duration.map_or(1000.0, |max| cur / max.0 * 1000.0) }) as u32; // Percentage to determine which frame of the timer overlay is displayed let buff_img = buff.kind.image(self.imgs); let buff_widget = Image::new(buff_img).w_h(40.0, 40.0); @@ -309,7 +309,7 @@ impl<'a> Widget for BuffsBar<'a> { let max_duration = debuff.kind.max_duration(); let current_duration = debuff.end_time.map(|end| end - self.time.0); let duration_percentage = current_duration.map_or(1000.0, |cur| { - max_duration.map_or(1000.0, |max| cur / max * 1000.0) + max_duration.map_or(1000.0, |max| cur / max.0 * 1000.0) }) as u32; // Percentage to determine which frame of the timer overlay is displayed let debuff_img = debuff.kind.image(self.imgs); let debuff_widget = Image::new(debuff_img).w_h(40.0, 40.0); @@ -408,7 +408,7 @@ impl<'a> Widget for BuffsBar<'a> { let current_duration = buff.end_time.map(|end| end - self.time.0); // Percentage to determine which frame of the timer overlay is displayed let duration_percentage = current_duration.map_or(1000.0, |cur| { - max_duration.map_or(1000.0, |max| cur / max * 1000.0) + max_duration.map_or(1000.0, |max| cur / max.0 * 1000.0) }) as u32; let buff_img = buff.kind.image(self.imgs); let buff_widget = Image::new(buff_img).w_h(40.0, 40.0); diff --git a/voxygen/src/hud/group.rs b/voxygen/src/hud/group.rs index 432565dde9..967e3890af 100644 --- a/voxygen/src/hud/group.rs +++ b/voxygen/src/hud/group.rs @@ -538,7 +538,7 @@ impl<'a> Widget for Group<'a> { let norm_col = Color::Rgba(1.0, 1.0, 1.0, 1.0); let current_duration = buff.end_time.map(|end| end - self.time.0); let duration_percentage = current_duration.map_or(1000.0, |cur| { - max_duration.map_or(1000.0, |max| cur / max * 1000.0) + max_duration.map_or(1000.0, |max| cur / max.0 * 1000.0) }) as u32; // Percentage to determine which frame of the timer overlay is displayed let buff_img = buff.kind.image(self.imgs); let buff_widget = Image::new(buff_img).w_h(15.0, 15.0); diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 9b03d4b472..1cf86eee68 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -104,7 +104,7 @@ use common::{ link::Is, mounting::Mount, outcome::Outcome, - resources::Time, + resources::{Secs, Time}, slowjob::SlowJobPool, terrain::{SpriteKind, TerrainChunk, UnlockKind}, trade::{ReducedInventory, TradeAction}, @@ -482,7 +482,7 @@ impl<'a> BuffIconKind<'a> { } } - pub fn max_duration(&self) -> Option { + pub fn max_duration(&self) -> Option { match self { Self::Buff { data, .. } => data.duration, Self::Ability { .. } => None, diff --git a/voxygen/src/hud/overhead.rs b/voxygen/src/hud/overhead.rs index 5dca4c36fe..910d7a06c9 100644 --- a/voxygen/src/hud/overhead.rs +++ b/voxygen/src/hud/overhead.rs @@ -272,7 +272,7 @@ impl<'a> Widget for Overhead<'a> { let max_duration = buff.kind.max_duration(); let current_duration = buff.end_time.map(|end| end - self.time.0); let duration_percentage = current_duration.map_or(1000.0, |cur| { - max_duration.map_or(1000.0, |max| cur / max * 1000.0) + max_duration.map_or(1000.0, |max| cur / max.0 * 1000.0) }) as u32; // Percentage to determine which frame of the timer overlay is displayed let buff_img = buff.kind.image(self.imgs); let buff_widget = Image::new(buff_img).w_h(20.0, 20.0); diff --git a/voxygen/src/hud/util.rs b/voxygen/src/hud/util.rs index f50b8eba17..66470586f5 100644 --- a/voxygen/src/hud/util.rs +++ b/voxygen/src/hud/util.rs @@ -146,7 +146,7 @@ pub fn consumable_desc(effects: &[Effect], i18n: &Localization) -> Vec { let mut description = String::new(); if let Effect::Buff(buff) = effect { let strength = buff.data.strength; - let dur_secs = buff.data.duration.map(|d| d as f32); + let dur_secs = buff.data.duration.map(|d| d.0 as f32); let str_total = dur_secs.map_or(strength, |secs| strength * secs); let format_float = diff --git a/voxygen/src/scene/particle.rs b/voxygen/src/scene/particle.rs index a108518cf2..a4b4279f05 100644 --- a/voxygen/src/scene/particle.rs +++ b/voxygen/src/scene/particle.rs @@ -1226,7 +1226,7 @@ impl ParticleMgr { } => { let is_new_aura = aura.data.duration.map_or(true, |max_dur| { let rem_dur = aura.end_time.map_or(time, |e| e.0) - time; - rem_dur > max_dur * 0.9 + rem_dur > max_dur.0 * 0.9 }); if is_new_aura { let heartbeats = self.scheduler.heartbeats(Duration::from_millis(5)); @@ -1316,7 +1316,7 @@ impl ParticleMgr { .iter() .filter_map(|id| buffs.buffs.get(id)) .any(|buff| { - matches!(buff.elapsed(Time(time)), dur if (1.0..=1.5).contains(&dur)) + matches!(buff.elapsed(Time(time)), dur if (1.0..=1.5).contains(&dur.0)) }) { multiplicity = 1;