Made auras no longer need to be mutably accessed every tick.

This commit is contained in:
Sam 2023-03-09 21:03:08 -05:00
parent 8a6a60d5bb
commit 663db06844
9 changed files with 64 additions and 45 deletions

View File

@ -696,7 +696,7 @@ pub enum CharacterAbility {
recover_duration: f32, recover_duration: f32,
targets: combat::GroupTarget, targets: combat::GroupTarget,
auras: Vec<aura::AuraBuffConstructor>, auras: Vec<aura::AuraBuffConstructor>,
aura_duration: f32, aura_duration: f64,
range: f32, range: f32,
energy_cost: f32, energy_cost: f32,
scales_with_combo: bool, scales_with_combo: bool,
@ -2602,7 +2602,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
recover_duration: Duration::from_secs_f32(*recover_duration), recover_duration: Duration::from_secs_f32(*recover_duration),
targets: *targets, targets: *targets,
auras: auras.clone(), auras: auras.clone(),
aura_duration: Duration::from_secs_f32(*aura_duration), aura_duration: *aura_duration,
range: *range, range: *range,
ability_info, ability_info,
scales_with_combo: *scales_with_combo, scales_with_combo: *scales_with_combo,

View File

@ -1,12 +1,12 @@
use crate::{ use crate::{
combat::GroupTarget, combat::GroupTarget,
comp::buff::{BuffCategory, BuffData, BuffKind, BuffSource}, comp::buff::{BuffCategory, BuffData, BuffKind, BuffSource},
resources::Time,
uid::Uid, uid::Uid,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use slotmap::{new_key_type, SlotMap}; use slotmap::{new_key_type, SlotMap};
use specs::{Component, DerefFlaggedStorage, VecStorage}; use specs::{Component, DerefFlaggedStorage, VecStorage};
use std::time::Duration;
new_key_type! { pub struct AuraKey; } new_key_type! { pub struct AuraKey; }
@ -36,8 +36,8 @@ pub struct Aura {
pub aura_kind: AuraKind, pub aura_kind: AuraKind,
/// The radius of the aura /// The radius of the aura
pub radius: f32, pub radius: f32,
/// How long the aura lasts. None corresponds to an indefinite length // None corresponds to an indefinite aura
pub duration: Option<Duration>, pub end_time: Option<Time>,
/* TODO: Add functionality for fading or a gradient */ /* TODO: Add functionality for fading or a gradient */
/// Used to filter which entities this aura will apply to. For example, /// Used to filter which entities this aura will apply to. For example,
/// globally neutral auras which affect all entities will have the type /// globally neutral auras which affect all entities will have the type
@ -92,12 +92,12 @@ impl From<(Option<GroupTarget>, Option<&Uid>)> for AuraTarget {
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AuraData { pub struct AuraData {
pub duration: Option<Duration>, pub duration: Option<f64>,
} }
impl AuraData { impl AuraData {
#[must_use] #[must_use]
fn new(duration: Option<Duration>) -> Self { Self { duration } } fn new(duration: Option<f64>) -> Self { Self { duration } }
} }
impl Aura { impl Aura {
@ -105,13 +105,14 @@ impl Aura {
pub fn new( pub fn new(
aura_kind: AuraKind, aura_kind: AuraKind,
radius: f32, radius: f32,
duration: Option<Duration>, duration: Option<f64>,
target: AuraTarget, target: AuraTarget,
time: Time,
) -> Self { ) -> Self {
Self { Self {
aura_kind, aura_kind,
radius, radius,
duration, end_time: duration.map(|dur| Time(time.0 + dur)),
target, target,
data: AuraData::new(duration), data: AuraData::new(duration),
} }
@ -151,8 +152,9 @@ impl AuraBuffConstructor {
self, self,
uid: &Uid, uid: &Uid,
radius: f32, radius: f32,
duration: Option<Duration>, duration: Option<f64>,
target: AuraTarget, target: AuraTarget,
time: Time,
) -> Aura { ) -> Aura {
let aura_kind = AuraKind::Buff { let aura_kind = AuraKind::Buff {
kind: self.kind, kind: self.kind,
@ -164,7 +166,7 @@ impl AuraBuffConstructor {
category: self.category, category: self.category,
source: BuffSource::Character { by: *uid }, source: BuffSource::Character { by: *uid },
}; };
Aura::new(aura_kind, radius, duration, target) Aura::new(aura_kind, radius, duration, target, time)
} }
} }

View File

@ -28,7 +28,7 @@ pub struct StaticData {
/// Has information used to construct the auras /// Has information used to construct the auras
pub auras: Vec<AuraBuffConstructor>, pub auras: Vec<AuraBuffConstructor>,
/// How long aura lasts /// How long aura lasts
pub aura_duration: Duration, pub aura_duration: f64,
/// Radius of aura /// Radius of aura
pub range: f32, pub range: f32,
/// What key is used to press ability /// What key is used to press ability
@ -79,6 +79,7 @@ impl CharacterBehavior for Data {
self.static_data.range, self.static_data.range,
Some(self.static_data.aura_duration), Some(self.static_data.aura_duration),
targets, targets,
*data.time,
); );
if self.static_data.scales_with_combo { if self.static_data.scales_with_combo {
match aura.aura_kind { match aura.aura_kind {

View File

@ -7,21 +7,19 @@ use common::{
Alignment, Aura, Auras, BuffKind, Buffs, CharacterState, Health, Player, Pos, Stats, Alignment, Aura, Auras, BuffKind, Buffs, CharacterState, Health, Player, Pos, Stats,
}, },
event::{Emitter, EventBus, ServerEvent}, event::{Emitter, EventBus, ServerEvent},
resources::{DeltaTime, Time}, resources::Time,
uid::{Uid, UidAllocator}, uid::{Uid, UidAllocator},
}; };
use common_ecs::{Job, Origin, Phase, System}; use common_ecs::{Job, Origin, Phase, System};
use specs::{ use specs::{
saveload::MarkerAllocator, shred::ResourceId, Entities, Entity as EcsEntity, Join, Read, saveload::MarkerAllocator, shred::ResourceId, Entities, Entity as EcsEntity, Join, Read,
ReadStorage, SystemData, World, WriteStorage, ReadStorage, SystemData, World,
}; };
use std::time::Duration;
#[derive(SystemData)] #[derive(SystemData)]
pub struct ReadData<'a> { pub struct ReadData<'a> {
entities: Entities<'a>, entities: Entities<'a>,
players: ReadStorage<'a, Player>, players: ReadStorage<'a, Player>,
dt: Read<'a, DeltaTime>,
time: Read<'a, Time>, time: Read<'a, Time>,
server_bus: Read<'a, EventBus<ServerEvent>>, server_bus: Read<'a, EventBus<ServerEvent>>,
uid_allocator: Read<'a, UidAllocator>, uid_allocator: Read<'a, UidAllocator>,
@ -34,43 +32,36 @@ pub struct ReadData<'a> {
uids: ReadStorage<'a, Uid>, uids: ReadStorage<'a, Uid>,
stats: ReadStorage<'a, Stats>, stats: ReadStorage<'a, Stats>,
buffs: ReadStorage<'a, Buffs>, buffs: ReadStorage<'a, Buffs>,
auras: ReadStorage<'a, Auras>,
} }
#[derive(Default)] #[derive(Default)]
pub struct Sys; pub struct Sys;
impl<'a> System<'a> for Sys { impl<'a> System<'a> for Sys {
type SystemData = (ReadData<'a>, WriteStorage<'a, Auras>); type SystemData = ReadData<'a>;
const NAME: &'static str = "aura"; const NAME: &'static str = "aura";
const ORIGIN: Origin = Origin::Common; const ORIGIN: Origin = Origin::Common;
const PHASE: Phase = Phase::Create; const PHASE: Phase = Phase::Create;
fn run(_job: &mut Job<Self>, (read_data, mut auras): Self::SystemData) { fn run(_job: &mut Job<Self>, read_data: Self::SystemData) {
let mut server_emitter = read_data.server_bus.emitter(); let mut server_emitter = read_data.server_bus.emitter();
let dt = read_data.dt.0;
auras.set_event_emission(false);
// Iterate through all entities with an aura // Iterate through all entities with an aura
for (entity, pos, mut auras_comp, uid) in ( for (entity, pos, auras_comp, uid) in (
&read_data.entities, &read_data.entities,
&read_data.positions, &read_data.positions,
&mut auras, &read_data.auras,
&read_data.uids, &read_data.uids,
) )
.join() .join()
{ {
let mut expired_auras = Vec::<AuraKey>::new(); let mut expired_auras = Vec::<AuraKey>::new();
// Iterate through the auras attached to this entity // Iterate through the auras attached to this entity
for (key, aura) in auras_comp.auras.iter_mut() { for (key, aura) in auras_comp.auras.iter() {
// Tick the aura and subtract dt from it // Tick the aura and subtract dt from it
if let Some(remaining_time) = &mut aura.duration { if let Some(end_time) = aura.end_time {
if let Some(new_duration) = if read_data.time.0 > end_time.0 {
remaining_time.checked_sub(Duration::from_secs_f32(dt))
{
*remaining_time = new_duration;
} else {
*remaining_time = Duration::default();
expired_auras.push(key); expired_auras.push(key);
} }
} }
@ -143,7 +134,6 @@ impl<'a> System<'a> for Sys {
}); });
} }
} }
auras.set_event_emission(true);
} }
} }

View File

@ -1464,6 +1464,7 @@ fn handle_spawn_campfire(
_action: &ServerChatCommand, _action: &ServerChatCommand,
) -> CmdResult<()> { ) -> CmdResult<()> {
let pos = position(server, target, "target")?; let pos = position(server, target, "target")?;
let time = server.state.get_time();
server server
.state .state
.create_object(pos, comp::object::Body::CampfireLit) .create_object(pos, comp::object::Body::CampfireLit)
@ -1485,6 +1486,7 @@ fn handle_spawn_campfire(
5.0, 5.0,
None, None,
AuraTarget::All, AuraTarget::All,
Time(time),
), ),
Aura::new( Aura::new(
AuraKind::Buff { AuraKind::Buff {
@ -1496,6 +1498,7 @@ fn handle_spawn_campfire(
0.7, 0.7,
None, None,
AuraTarget::All, AuraTarget::All,
Time(time),
), ),
])) ]))
.build(); .build();

View File

@ -14,6 +14,7 @@ use common::{
event::{EventBus, UpdateCharacterMetadata}, event::{EventBus, UpdateCharacterMetadata},
lottery::LootSpec, lottery::LootSpec,
outcome::Outcome, outcome::Outcome,
resources::Time,
rtsim::RtSimEntity, rtsim::RtSimEntity,
uid::Uid, uid::Uid,
util::Dir, util::Dir,
@ -269,6 +270,7 @@ pub fn handle_beam(server: &mut Server, properties: beam::Properties, pos: Pos,
} }
pub fn handle_create_waypoint(server: &mut Server, pos: Vec3<f32>) { pub fn handle_create_waypoint(server: &mut Server, pos: Vec3<f32>) {
let time = server.state.get_time();
server server
.state .state
.create_object(Pos(pos), comp::object::Body::CampfireLit) .create_object(Pos(pos), comp::object::Body::CampfireLit)
@ -291,6 +293,7 @@ pub fn handle_create_waypoint(server: &mut Server, pos: Vec3<f32>) {
5.0, 5.0,
None, None,
AuraTarget::All, AuraTarget::All,
Time(time),
), ),
Aura::new( Aura::new(
AuraKind::Buff { AuraKind::Buff {
@ -302,6 +305,7 @@ pub fn handle_create_waypoint(server: &mut Server, pos: Vec3<f32>) {
0.7, 0.7,
None, None,
AuraTarget::All, AuraTarget::All,
Time(time),
), ),
])) ]))
.build(); .build();

View File

@ -432,6 +432,7 @@ impl StateExt for State {
aura::{Aura, AuraKind, AuraTarget, Auras}, aura::{Aura, AuraKind, AuraTarget, Auras},
buff::{BuffCategory, BuffData, BuffKind, BuffSource}, buff::{BuffCategory, BuffData, BuffKind, BuffSource},
}; };
let time = self.get_time();
self.ecs_mut() self.ecs_mut()
.create_entity_synced() .create_entity_synced()
.with(pos) .with(pos)
@ -445,6 +446,7 @@ impl StateExt for State {
range.unwrap_or(100.0), range.unwrap_or(100.0),
None, None,
AuraTarget::All, AuraTarget::All,
Time(time),
)])) )]))
} }

View File

@ -13,6 +13,7 @@ use common::{
cmd::ServerChatCommand, cmd::ServerChatCommand,
comp, comp,
comp::{inventory::item::armor::Friction, Poise, PoiseState}, comp::{inventory::item::armor::Friction, Poise, PoiseState},
resources::Time,
}; };
use core::mem; use core::mem;
use egui::{ use egui::{
@ -535,6 +536,7 @@ fn selected_entity_window(
.join() .join()
.filter(|(e, _, _, _, _, _, _, _, _, _, _, _, _, _, (_, _, _))| e.id() == entity_id) .filter(|(e, _, _, _, _, _, _, _, _, _, _, _, _, _, (_, _, _))| e.id() == entity_id)
{ {
let time = ecs.read_resource::<Time>();
if let Some(pos) = pos { if let Some(pos) = pos {
if let Some(shape_id) = selected_entity_info.debug_shape_id { if let Some(shape_id) = selected_entity_info.debug_shape_id {
egui_actions.actions.push(EguiAction::DebugShape( egui_actions.actions.push(EguiAction::DebugShape(
@ -646,7 +648,7 @@ fn selected_entity_window(
ui.label(format!("{:?}", v.kind)); ui.label(format!("{:?}", v.kind));
ui.label( ui.label(
v.end_time.map_or("-".to_string(), |end| { v.end_time.map_or("-".to_string(), |end| {
format!("{:?}", end.0 - v.start_time.0) format!("{:?}", end.0 - time.0)
}), }),
); );
ui.label(format!("{:?}", v.source)); ui.label(format!("{:?}", v.source));
@ -672,7 +674,7 @@ fn selected_entity_window(
Buff { kind, .. } => format!("Buff - {:?}", kind) Buff { kind, .. } => format!("Buff - {:?}", kind)
}); });
ui.label(format!("{:1}", v.radius)); ui.label(format!("{:1}", v.radius));
ui.label(v.duration.map_or("-".to_owned(), |x| format!("{:1}s", x.as_secs()))); ui.label(v.end_time.map_or("-".to_owned(), |x| format!("{:1}s", x.0 - time.0)));
ui.label(format!("{:?}", v.target)); ui.label(format!("{:?}", v.target));
ui.end_row(); ui.end_row();
}); });

View File

@ -1113,9 +1113,13 @@ impl ParticleMgr {
|| { || {
let rand_dist = aura.radius * (1.0 - rng.gen::<f32>().powi(100)); let rand_dist = aura.radius * (1.0 - rng.gen::<f32>().powi(100));
let init_pos = Vec3::new(rand_dist, 0_f32, 0_f32); let init_pos = Vec3::new(rand_dist, 0_f32, 0_f32);
let max_dur = Duration::from_secs(1); let duration = Duration::from_secs_f64(
aura.end_time
.map_or(1.0, |end| end.0 - time)
.clamp(0.0, 1.0),
);
Particle::new_directed( Particle::new_directed(
aura.duration.map_or(max_dur, |dur| dur.min(max_dur)), duration,
time, time,
ParticleMode::EnergyNature, ParticleMode::EnergyNature,
pos, pos,
@ -1145,9 +1149,13 @@ impl ParticleMgr {
|| { || {
let rand_dist = aura.radius * (1.0 - rng.gen::<f32>().powi(100)); let rand_dist = aura.radius * (1.0 - rng.gen::<f32>().powi(100));
let init_pos = Vec3::new(rand_dist, 0_f32, 0_f32); let init_pos = Vec3::new(rand_dist, 0_f32, 0_f32);
let max_dur = Duration::from_secs(1); let duration = Duration::from_secs_f64(
aura.end_time
.map_or(1.0, |end| end.0 - time)
.clamp(0.0, 1.0),
);
Particle::new_directed( Particle::new_directed(
aura.duration.map_or(max_dur, |dur| dur.min(max_dur)), duration,
time, time,
ParticleMode::EnergyHealing, ParticleMode::EnergyHealing,
pos, pos,
@ -1172,9 +1180,13 @@ impl ParticleMgr {
let y = radius * theta.cos(); let y = radius * theta.cos();
Vec2::new(x, y) + pos.xy() Vec2::new(x, y) + pos.xy()
}; };
let max_dur = Duration::from_secs(1); let duration = Duration::from_secs_f64(
aura.end_time
.map_or(1.0, |end| end.0 - time)
.clamp(0.0, 1.0),
);
Particle::new_directed( Particle::new_directed(
aura.duration.map_or(max_dur, |dur| dur.min(max_dur)), duration,
time, time,
ParticleMode::FlameThrower, ParticleMode::FlameThrower,
rand_pos.with_z(pos.z), rand_pos.with_z(pos.z),
@ -1193,9 +1205,13 @@ impl ParticleMgr {
|| { || {
let rand_dist = aura.radius * (1.0 - rng.gen::<f32>().powi(100)); let rand_dist = aura.radius * (1.0 - rng.gen::<f32>().powi(100));
let init_pos = Vec3::new(rand_dist, 0_f32, 0_f32); let init_pos = Vec3::new(rand_dist, 0_f32, 0_f32);
let max_dur = Duration::from_secs(1); let duration = Duration::from_secs_f64(
aura.end_time
.map_or(1.0, |end| end.0 - time)
.clamp(0.0, 1.0),
);
Particle::new_directed( Particle::new_directed(
aura.duration.map_or(max_dur, |dur| dur.min(max_dur)), duration,
time, time,
ParticleMode::EnergyBuffing, ParticleMode::EnergyBuffing,
pos, pos,
@ -1209,9 +1225,8 @@ impl ParticleMgr {
.. ..
} => { } => {
let is_new_aura = aura.data.duration.map_or(true, |max_dur| { let is_new_aura = aura.data.duration.map_or(true, |max_dur| {
aura.duration.map_or(true, |rem_dur| { let rem_dur = aura.end_time.map_or(time, |e| e.0) - time;
rem_dur.as_secs_f32() > max_dur.as_secs_f32() * 0.9 rem_dur > max_dur * 0.9
})
}); });
if is_new_aura { if is_new_aura {
let heartbeats = self.scheduler.heartbeats(Duration::from_millis(5)); let heartbeats = self.scheduler.heartbeats(Duration::from_millis(5));