Polymorph effect now more correctly handles when multiple polymorph buffs are applied.

This commit is contained in:
Sam 2023-04-01 13:11:59 -04:00
parent d1a7884ac8
commit f40ef0d5dd
4 changed files with 71 additions and 28 deletions

View File

@ -242,6 +242,13 @@ pub enum ServerEvent {
entity: EcsEntity,
stance: comp::Stance,
},
ChangeBody {
entity: EcsEntity,
new_body: comp::Body,
},
RemoveLightEmitter {
entity: EcsEntity,
},
}
pub struct EventBus<E> {

View File

@ -42,26 +42,20 @@ pub struct ReadData<'a> {
buffs: ReadStorage<'a, Buffs>,
auras: ReadStorage<'a, Auras>,
positions: ReadStorage<'a, Pos>,
bodies: ReadStorage<'a, Body>,
light_emitters: ReadStorage<'a, LightEmitter>,
}
#[derive(Default)]
pub struct Sys;
impl<'a> System<'a> for Sys {
type SystemData = (
ReadData<'a>,
WriteStorage<'a, Stats>,
WriteStorage<'a, Body>,
WriteStorage<'a, LightEmitter>,
);
type SystemData = (ReadData<'a>, WriteStorage<'a, Stats>);
const NAME: &'static str = "buff";
const ORIGIN: Origin = Origin::Common;
const PHASE: Phase = Phase::Create;
fn run(
job: &mut Job<Self>,
(read_data, mut stats, mut bodies, mut light_emitters): Self::SystemData,
) {
fn run(job: &mut Job<Self>, (read_data, mut stats): Self::SystemData) {
let mut server_emitter = read_data.server_bus.emitter();
let dt = read_data.dt.0;
// Set to false to avoid spamming server
@ -73,9 +67,9 @@ impl<'a> System<'a> for Sys {
job.cpu_stats.measure(ParMode::Rayon);
let to_put_out_campfires = (
&read_data.entities,
&bodies,
&read_data.bodies,
&read_data.physics_states,
&light_emitters, //to improve iteration speed
&read_data.light_emitters, //to improve iteration speed
)
.par_join()
.map_init(
@ -117,19 +111,20 @@ impl<'a> System<'a> for Sys {
// slower than parallel checking above
for e in to_put_out_campfires {
{
bodies
.get_mut(e)
.map(|mut body| *body = Body::Object(object::Body::Campfire));
light_emitters.remove(e);
server_emitter.emit(ServerEvent::ChangeBody {
entity: e,
new_body: Body::Object(object::Body::Campfire),
});
server_emitter.emit(ServerEvent::RemoveLightEmitter { entity: e });
}
}
}
for (entity, buff_comp, mut stat, mut body, health, energy, physics_state) in (
for (entity, buff_comp, mut stat, body, health, energy, physics_state) in (
&read_data.entities,
&read_data.buffs,
&mut stats,
&mut bodies,
&read_data.bodies,
&read_data.healths,
&read_data.energies,
read_data.physics_states.maybe(),
@ -331,7 +326,7 @@ impl<'a> System<'a> for Sys {
// Call to reset stats to base values
stat.reset_temp_modifiers();
let mut body_override = stat.original_body;
let mut body_override = None;
// Iterator over the lists of buffs by kind
let mut buff_kinds = buff_comp
@ -371,6 +366,7 @@ impl<'a> System<'a> for Sys {
kind_start_time,
&read_data,
&mut stat,
body,
&mut body_override,
health,
energy,
@ -387,8 +383,9 @@ impl<'a> System<'a> for Sys {
}
// Update body if needed.
if body_override != *body {
*body = body_override;
let new_body = body_override.unwrap_or(stat.original_body);
if new_body != *body {
server_emitter.emit(ServerEvent::ChangeBody { entity, new_body });
}
// Remove buffs that expire
@ -416,6 +413,8 @@ impl<'a> System<'a> for Sys {
}
}
// TODO: Globally disable this clippy lint
#[allow(clippy::too_many_arguments)]
fn execute_effect(
effect: &BuffEffect,
buff_kind: BuffKind,
@ -423,7 +422,8 @@ fn execute_effect(
buff_kind_start_time: Time,
read_data: &ReadData,
stat: &mut Stats,
body_override: &mut Body,
current_body: &Body,
body_override: &mut Option<Body>,
health: &Health,
energy: &Energy,
entity: Entity,
@ -618,6 +618,16 @@ fn execute_effect(
BuffEffect::CriticalChance(cc) => {
stat.crit_chance_modifier *= *cc;
},
BuffEffect::BodyChange(b) => *body_override = *b,
BuffEffect::BodyChange(b) => {
// For when an entity is under the effects of multiple de/buffs that change the
// body, to avoid flickering between many bodies only change the body if the
// override body is not equal to the current body. (If the buff that caused the
// current body is still active, body override will eventually pick up on it,
// otherwise this will end up with a new body, though random depending on
// iteration order)
if Some(current_body) != body_override.as_ref() {
*body_override = Some(*b)
}
},
};
}

View File

@ -1465,3 +1465,22 @@ pub fn handle_stance_change(server: &mut Server, entity: EcsEntity, new_stance:
*stance = new_stance;
}
}
pub fn handle_change_body(server: &mut Server, entity: EcsEntity, new_body: comp::Body) {
if let Some(mut body) = server
.state
.ecs_mut()
.write_storage::<comp::Body>()
.get_mut(entity)
{
*body = new_body;
}
}
pub fn handle_remove_light_emitter(server: &mut Server, entity: EcsEntity) {
server
.state
.ecs_mut()
.write_storage::<comp::LightEmitter>()
.remove(entity);
}

View File

@ -10,11 +10,12 @@ use entity_creation::{
handle_shockwave, handle_shoot,
};
use entity_manipulation::{
handle_aura, handle_bonk, handle_buff, handle_change_ability, handle_combo_change,
handle_delete, handle_destroy, handle_energy_change, handle_entity_attacked_hook,
handle_explosion, handle_health_change, handle_knockback, handle_land_on_ground,
handle_make_admin, handle_parry_hook, handle_poise, handle_respawn, handle_stance_change,
handle_teleport_to, handle_update_map_marker,
handle_aura, handle_bonk, handle_buff, handle_change_ability, handle_change_body,
handle_combo_change, handle_delete, handle_destroy, handle_energy_change,
handle_entity_attacked_hook, handle_explosion, handle_health_change, handle_knockback,
handle_land_on_ground, handle_make_admin, handle_parry_hook, handle_poise,
handle_remove_light_emitter, handle_respawn, handle_stance_change, handle_teleport_to,
handle_update_map_marker,
};
use group_manip::handle_group;
use information::handle_site_info;
@ -303,6 +304,12 @@ impl Server {
ServerEvent::ChangeStance { entity, stance } => {
handle_stance_change(self, entity, stance)
},
ServerEvent::ChangeBody { entity, new_body } => {
handle_change_body(self, entity, new_body)
},
ServerEvent::RemoveLightEmitter { entity } => {
handle_remove_light_emitter(self, entity)
},
}
}