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

View File

@ -1,12 +1,12 @@
use crate::{
combat::GroupTarget,
comp::buff::{BuffCategory, BuffData, BuffKind, BuffSource},
resources::Time,
uid::Uid,
};
use serde::{Deserialize, Serialize};
use slotmap::{new_key_type, SlotMap};
use specs::{Component, DerefFlaggedStorage, VecStorage};
use std::time::Duration;
new_key_type! { pub struct AuraKey; }
@ -36,8 +36,8 @@ pub struct Aura {
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>,
// None corresponds to an indefinite aura
pub end_time: Option<Time>,
/* TODO: Add functionality for fading or a gradient */
/// Used to filter which entities this aura will apply to. For example,
/// 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)]
pub struct AuraData {
pub duration: Option<Duration>,
pub duration: Option<f64>,
}
impl AuraData {
#[must_use]
fn new(duration: Option<Duration>) -> Self { Self { duration } }
fn new(duration: Option<f64>) -> Self { Self { duration } }
}
impl Aura {
@ -105,13 +105,14 @@ impl Aura {
pub fn new(
aura_kind: AuraKind,
radius: f32,
duration: Option<Duration>,
duration: Option<f64>,
target: AuraTarget,
time: Time,
) -> Self {
Self {
aura_kind,
radius,
duration,
end_time: duration.map(|dur| Time(time.0 + dur)),
target,
data: AuraData::new(duration),
}
@ -151,8 +152,9 @@ impl AuraBuffConstructor {
self,
uid: &Uid,
radius: f32,
duration: Option<Duration>,
duration: Option<f64>,
target: AuraTarget,
time: Time,
) -> Aura {
let aura_kind = AuraKind::Buff {
kind: self.kind,
@ -164,7 +166,7 @@ impl AuraBuffConstructor {
category: self.category,
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
pub auras: Vec<AuraBuffConstructor>,
/// How long aura lasts
pub aura_duration: Duration,
pub aura_duration: f64,
/// Radius of aura
pub range: f32,
/// What key is used to press ability
@ -79,6 +79,7 @@ impl CharacterBehavior for Data {
self.static_data.range,
Some(self.static_data.aura_duration),
targets,
*data.time,
);
if self.static_data.scales_with_combo {
match aura.aura_kind {

View File

@ -7,21 +7,19 @@ use common::{
Alignment, Aura, Auras, BuffKind, Buffs, CharacterState, Health, Player, Pos, Stats,
},
event::{Emitter, EventBus, ServerEvent},
resources::{DeltaTime, Time},
resources::Time,
uid::{Uid, UidAllocator},
};
use common_ecs::{Job, Origin, Phase, System};
use specs::{
saveload::MarkerAllocator, shred::ResourceId, Entities, Entity as EcsEntity, Join, Read,
ReadStorage, SystemData, World, WriteStorage,
ReadStorage, SystemData, World,
};
use std::time::Duration;
#[derive(SystemData)]
pub struct ReadData<'a> {
entities: Entities<'a>,
players: ReadStorage<'a, Player>,
dt: Read<'a, DeltaTime>,
time: Read<'a, Time>,
server_bus: Read<'a, EventBus<ServerEvent>>,
uid_allocator: Read<'a, UidAllocator>,
@ -34,43 +32,36 @@ pub struct ReadData<'a> {
uids: ReadStorage<'a, Uid>,
stats: ReadStorage<'a, Stats>,
buffs: ReadStorage<'a, Buffs>,
auras: ReadStorage<'a, Auras>,
}
#[derive(Default)]
pub struct Sys;
impl<'a> System<'a> for Sys {
type SystemData = (ReadData<'a>, WriteStorage<'a, Auras>);
type SystemData = ReadData<'a>;
const NAME: &'static str = "aura";
const ORIGIN: Origin = Origin::Common;
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 dt = read_data.dt.0;
auras.set_event_emission(false);
// 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.positions,
&mut auras,
&read_data.auras,
&read_data.uids,
)
.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() {
for (key, aura) in auras_comp.auras.iter() {
// 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))
{
*remaining_time = new_duration;
} else {
*remaining_time = Duration::default();
if let Some(end_time) = aura.end_time {
if read_data.time.0 > end_time.0 {
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,
) -> CmdResult<()> {
let pos = position(server, target, "target")?;
let time = server.state.get_time();
server
.state
.create_object(pos, comp::object::Body::CampfireLit)
@ -1485,6 +1486,7 @@ fn handle_spawn_campfire(
5.0,
None,
AuraTarget::All,
Time(time),
),
Aura::new(
AuraKind::Buff {
@ -1496,6 +1498,7 @@ fn handle_spawn_campfire(
0.7,
None,
AuraTarget::All,
Time(time),
),
]))
.build();

View File

@ -14,6 +14,7 @@ use common::{
event::{EventBus, UpdateCharacterMetadata},
lottery::LootSpec,
outcome::Outcome,
resources::Time,
rtsim::RtSimEntity,
uid::Uid,
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>) {
let time = server.state.get_time();
server
.state
.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,
None,
AuraTarget::All,
Time(time),
),
Aura::new(
AuraKind::Buff {
@ -302,6 +305,7 @@ pub fn handle_create_waypoint(server: &mut Server, pos: Vec3<f32>) {
0.7,
None,
AuraTarget::All,
Time(time),
),
]))
.build();

View File

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

View File

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

View File

@ -1113,9 +1113,13 @@ impl ParticleMgr {
|| {
let rand_dist = aura.radius * (1.0 - rng.gen::<f32>().powi(100));
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(
aura.duration.map_or(max_dur, |dur| dur.min(max_dur)),
duration,
time,
ParticleMode::EnergyNature,
pos,
@ -1145,9 +1149,13 @@ impl ParticleMgr {
|| {
let rand_dist = aura.radius * (1.0 - rng.gen::<f32>().powi(100));
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(
aura.duration.map_or(max_dur, |dur| dur.min(max_dur)),
duration,
time,
ParticleMode::EnergyHealing,
pos,
@ -1172,9 +1180,13 @@ impl ParticleMgr {
let y = radius * theta.cos();
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(
aura.duration.map_or(max_dur, |dur| dur.min(max_dur)),
duration,
time,
ParticleMode::FlameThrower,
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 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(
aura.duration.map_or(max_dur, |dur| dur.min(max_dur)),
duration,
time,
ParticleMode::EnergyBuffing,
pos,
@ -1209,9 +1225,8 @@ impl ParticleMgr {
..
} => {
let is_new_aura = aura.data.duration.map_or(true, |max_dur| {
aura.duration.map_or(true, |rem_dur| {
rem_dur.as_secs_f32() > max_dur.as_secs_f32() * 0.9
})
let rem_dur = aura.end_time.map_or(time, |e| e.0) - time;
rem_dur > max_dur * 0.9
});
if is_new_aura {
let heartbeats = self.scheduler.heartbeats(Duration::from_millis(5));