mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Made auras no longer need to be mutably accessed every tick.
This commit is contained in:
parent
8a6a60d5bb
commit
663db06844
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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),
|
||||
)]))
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
});
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user