From 42a10a6059524c439a4c524111a595f13db097b7 Mon Sep 17 00:00:00 2001 From: scott-c Date: Mon, 29 Jun 2020 19:18:19 +0800 Subject: [PATCH] Add ParticleEmitter Component --- common/src/comp/ability.rs | 6 +- common/src/comp/inventory/item/tool.rs | 140 ++++++++++++++----------- common/src/comp/mod.rs | 2 +- common/src/comp/visual.rs | 34 ++++++ common/src/event.rs | 1 + common/src/msg/ecs_packet.rs | 7 ++ common/src/state.rs | 1 + common/src/states/basic_ranged.rs | 7 +- server/src/cmd.rs | 1 + server/src/events/entity_creation.rs | 9 +- server/src/events/mod.rs | 3 +- server/src/sys/sentinel.rs | 22 +++- 12 files changed, 161 insertions(+), 72 deletions(-) diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index 79292b797e..e37e6bf26d 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -2,7 +2,8 @@ use crate::{ comp::{ ability::Stage, item::{armor::Protection, Item, ItemKind}, - Body, CharacterState, EnergySource, Gravity, LightEmitter, Projectile, StateUpdate, + Body, CharacterState, EnergySource, Gravity, LightEmitter, ParticleEmitter, Projectile, + StateUpdate, }, states::{triple_strike::*, *}, sys::character_behavior::JoinData, @@ -61,6 +62,7 @@ pub enum CharacterAbility { projectile: Projectile, projectile_body: Body, projectile_light: Option, + projectile_particles: Option, projectile_gravity: Option, }, Boost { @@ -247,6 +249,7 @@ impl From<&CharacterAbility> for CharacterState { projectile, projectile_body, projectile_light, + projectile_particles, projectile_gravity, energy_cost: _, } => CharacterState::BasicRanged(basic_ranged::Data { @@ -258,6 +261,7 @@ impl From<&CharacterAbility> for CharacterState { projectile: projectile.clone(), projectile_body: *projectile_body, projectile_light: *projectile_light, + projectile_particles: *projectile_particles, projectile_gravity: *projectile_gravity, }), CharacterAbility::Boost { duration, only_up } => CharacterState::Boost(boost::Data { diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index 401f9925c7..d7b4524243 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -2,7 +2,8 @@ // version in voxygen\src\meta.rs in order to reset save files to being empty use crate::comp::{ - body::object, projectile, Body, CharacterAbility, Gravity, LightEmitter, Projectile, + body::object, projectile, Body, CharacterAbility, Gravity, HealthChange, HealthSource, + LightEmitter, Projectile, ParticleEmitter, }; use serde::{Deserialize, Serialize}; use std::time::Duration; @@ -179,6 +180,7 @@ impl Tool { }, projectile_body: Body::Object(object::Body::Arrow), projectile_light: None, + projectile_particles: None, projectile_gravity: Some(Gravity(0.2)), }, ChargedRanged { @@ -193,6 +195,8 @@ impl Tool { recover_duration: Duration::from_millis(500), projectile_body: Body::Object(object::Body::Arrow), projectile_light: None, + projectile_particles: None, + projectile_gravity: Some(Gravity(0.05)), }, ], Dagger(_) => vec![ @@ -261,40 +265,68 @@ impl Tool { col: (0.85, 0.5, 0.11).into(), ..Default::default() }), - projectile_gravity: None, - }, - BasicRanged { - energy_cost: 400, - holdable: true, - prepare_duration: Duration::from_millis(800), - recover_duration: Duration::from_millis(50), - projectile: Projectile { - hit_solid: vec![ - projectile::Effect::Explode { - power: 1.4 * self.base_power(), - }, - projectile::Effect::Vanish, - ], - hit_entity: vec![ - projectile::Effect::Explode { - power: 1.4 * self.base_power(), - }, - projectile::Effect::Vanish, - ], - time_left: Duration::from_secs(20), - owner: None, - }, - projectile_body: Body::Object(object::Body::BoltFireBig), - projectile_light: Some(LightEmitter { - col: (1.0, 0.75, 0.11).into(), - ..Default::default() - }), - - projectile_gravity: None, - }, - ] - } - }, + projectile::Effect::RewardEnergy(150), + projectile::Effect::Vanish, + ], + time_left: Duration::from_secs(20), + owner: None, + }, + projectile_body: Body::Object(object::Body::BoltFire), + projectile_light: Some(LightEmitter { + col: (0.85, 0.5, 0.11).into(), + ..Default::default() + }), + projectile_particles: Some(ParticleEmitter { + mode: 0, + }), + projectile_gravity: None, + }, + BasicRanged { + energy_cost: 400, + holdable: true, + prepare_duration: Duration::from_millis(800), + recover_duration: Duration::from_millis(50), + projectile: Projectile { + hit_solid: vec![ + projectile::Effect::Explode { power: 1.4 }, + projectile::Effect::Vanish, + ], + hit_entity: vec![ + projectile::Effect::Explode { power: 1.4 }, + projectile::Effect::Vanish, + ], + time_left: Duration::from_secs(20), + owner: None, + }, + projectile_body: Body::Object(object::Body::BoltFireBig), + projectile_light: Some(LightEmitter { + col: (1.0, 0.75, 0.11).into(), + ..Default::default() + }), + projectile_particles: Some(ParticleEmitter { + mode: 0, + }), + projectile_gravity: None, + }, + ], + Staff(StaffKind::Sceptre) => vec![ + BasicMelee { + energy_cost: 0, + buildup_duration: Duration::from_millis(0), + recover_duration: Duration::from_millis(300), + base_healthchange: -1, + range: 10.0, + max_angle: 45.0, + }, + BasicMelee { + energy_cost: 350, + buildup_duration: Duration::from_millis(0), + recover_duration: Duration::from_millis(1000), + base_healthchange: 15, + range: 10.0, + max_angle: 45.0, + }, + ], Shield(_) => vec![ BasicMelee { energy_cost: 0, @@ -313,35 +345,15 @@ impl Tool { duration: Duration::from_millis(50), only_up: false, }, - CharacterAbility::Boost { - duration: Duration::from_millis(50), - only_up: true, - }, - BasicRanged { - energy_cost: 0, - holdable: false, - prepare_duration: Duration::from_millis(0), - recover_duration: Duration::from_millis(10), - projectile: Projectile { - hit_solid: vec![projectile::Effect::Stick], - hit_entity: vec![ - projectile::Effect::Stick, - projectile::Effect::Possess, - ], - time_left: Duration::from_secs(10), - owner: None, - }, - projectile_body: Body::Object(object::Body::ArrowSnake), - projectile_light: Some(LightEmitter { - col: (0.0, 1.0, 0.33).into(), - ..Default::default() - }), - projectile_gravity: None, - }, - ] - } else { - vec![] - } + projectile_body: Body::Object(object::Body::ArrowSnake), + projectile_light: Some(LightEmitter { + col: (0.0, 1.0, 0.33).into(), + ..Default::default() + }), + projectile_particles: None, + projectile_gravity: None, + }, + ], }, Empty => vec![BasicMelee { energy_cost: 0, diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index ccef80dc8b..a17da95189 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -53,4 +53,4 @@ pub use player::{Player, MAX_MOUNT_RANGE_SQR}; pub use projectile::Projectile; pub use skills::{Skill, SkillGroup, SkillGroupType, SkillSet}; pub use stats::{Exp, HealthChange, HealthSource, Level, Stats}; -pub use visual::{LightAnimation, LightEmitter}; +pub use visual::{LightAnimation, LightEmitter, ParticleEmitter}; diff --git a/common/src/comp/visual.rs b/common/src/comp/visual.rs index 013f27aa2c..b1d0f29cae 100644 --- a/common/src/comp/visual.rs +++ b/common/src/comp/visual.rs @@ -46,3 +46,37 @@ impl Default for LightAnimation { impl Component for LightAnimation { type Storage = FlaggedStorage>; } + + +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct ParticleEmitter { + + /// Mode 1: sprinkler (inital_velocity, lifespan) + /// Mode 2: smoke (initial_position, boyancy_const, wind, lifespan) + pub mode: u8, // enum? + + // pub vertices: Vec, + // pub texture: RasterFooBar, + + // // mode 1 -- sprinkler. + // pub initial_position: [i8; 3], + // pub initial_velocity: [i8; 3], + // pub lifespan: u32, // in ticks? + + // // mode 2 -- smoke + // pub initial_position: [i8; 3], + // pub boyancy_const: [i8; 3], + // pub wind_sway: [i8; 3], +} + +impl Default for ParticleEmitter { + fn default() -> Self { + Self { + mode: 0, + } + } +} + +impl Component for ParticleEmitter { + type Storage = FlaggedStorage>; +} \ No newline at end of file diff --git a/common/src/event.rs b/common/src/event.rs index 943757a2a7..f291971c25 100644 --- a/common/src/event.rs +++ b/common/src/event.rs @@ -43,6 +43,7 @@ pub enum ServerEvent { dir: Dir, body: comp::Body, light: Option, + particles: Option, projectile: comp::Projectile, gravity: Option, }, diff --git a/common/src/msg/ecs_packet.rs b/common/src/msg/ecs_packet.rs index 726d67321a..e8fa12c33d 100644 --- a/common/src/msg/ecs_packet.rs +++ b/common/src/msg/ecs_packet.rs @@ -15,6 +15,7 @@ sum_type! { Stats(comp::Stats), Energy(comp::Energy), LightEmitter(comp::LightEmitter), + ParticleEmitter(comp::ParticleEmitter), Item(comp::Item), Scale(comp::Scale), Group(comp::Group), @@ -42,6 +43,7 @@ sum_type! { Stats(PhantomData), Energy(PhantomData), LightEmitter(PhantomData), + ParticleEmitter(PhantomData), Item(PhantomData), Scale(PhantomData), Group(PhantomData), @@ -69,6 +71,7 @@ impl sync::CompPacket for EcsCompPacket { EcsCompPacket::Stats(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Energy(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::LightEmitter(comp) => sync::handle_insert(comp, entity, world), + EcsCompPacket::ParticleEmitter(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Item(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Scale(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Group(comp) => sync::handle_insert(comp, entity, world), @@ -94,6 +97,7 @@ impl sync::CompPacket for EcsCompPacket { EcsCompPacket::Stats(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Energy(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::LightEmitter(comp) => sync::handle_modify(comp, entity, world), + EcsCompPacket::ParticleEmitter(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Item(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Scale(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Group(comp) => sync::handle_modify(comp, entity, world), @@ -121,6 +125,9 @@ impl sync::CompPacket for EcsCompPacket { EcsCompPhantom::LightEmitter(_) => { sync::handle_remove::(entity, world) }, + EcsCompPhantom::ParticleEmitter(_) => { + sync::handle_remove::(entity, world) + }, EcsCompPhantom::Item(_) => sync::handle_remove::(entity, world), EcsCompPhantom::Scale(_) => sync::handle_remove::(entity, world), EcsCompPhantom::Group(_) => sync::handle_remove::(entity, world), diff --git a/common/src/state.rs b/common/src/state.rs index 3d003b7a4f..c4798c5813 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -113,6 +113,7 @@ impl State { ecs.register::(); ecs.register::(); ecs.register::(); + ecs.register::(); ecs.register::(); ecs.register::(); ecs.register::(); diff --git a/common/src/states/basic_ranged.rs b/common/src/states/basic_ranged.rs index b41bd6c208..647b166230 100644 --- a/common/src/states/basic_ranged.rs +++ b/common/src/states/basic_ranged.rs @@ -1,5 +1,5 @@ use crate::{ - comp::{Body, CharacterState, Gravity, LightEmitter, Projectile, StateUpdate}, + comp::{Body, CharacterState, Gravity, LightEmitter, ParticleEmitter, Projectile, StateUpdate}, event::ServerEvent, states::utils::*, sys::character_behavior::*, @@ -20,6 +20,7 @@ pub struct Data { pub projectile: Projectile, pub projectile_body: Body, pub projectile_light: Option, + pub projectile_particles: Option, pub projectile_gravity: Option, /// Whether the attack fired already pub exhausted: bool, @@ -48,6 +49,7 @@ impl CharacterBehavior for Data { projectile: self.projectile.clone(), projectile_body: self.projectile_body, projectile_light: self.projectile_light, + projectile_particles: self.projectile_particles, projectile_gravity: self.projectile_gravity, exhausted: false, }); @@ -61,6 +63,7 @@ impl CharacterBehavior for Data { body: self.projectile_body, projectile, light: self.projectile_light, + particles: self.projectile_particles, gravity: self.projectile_gravity, }); @@ -72,6 +75,7 @@ impl CharacterBehavior for Data { projectile: self.projectile.clone(), projectile_body: self.projectile_body, projectile_light: self.projectile_light, + projectile_particles: self.projectile_particles, projectile_gravity: self.projectile_gravity, exhausted: true, }); @@ -88,6 +92,7 @@ impl CharacterBehavior for Data { projectile: self.projectile.clone(), projectile_body: self.projectile_body, projectile_light: self.projectile_light, + projectile_particles: self.projectile_particles, projectile_gravity: self.projectile_gravity, exhausted: true, }); diff --git a/server/src/cmd.rs b/server/src/cmd.rs index b580cfbd98..14c7b39338 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -910,6 +910,7 @@ fn handle_light( .create_entity_synced() .with(pos) .with(comp::ForceUpdate) + .with(comp::ParticleEmitter { mode: 0 }) .with(light_emitter); if let Some(light_offset) = light_offset_opt { builder.with(light_offset).build(); diff --git a/server/src/events/entity_creation.rs b/server/src/events/entity_creation.rs index b2924d9d15..d2f3b9d774 100644 --- a/server/src/events/entity_creation.rs +++ b/server/src/events/entity_creation.rs @@ -1,8 +1,8 @@ use crate::{sys, Server, StateExt}; use common::{ comp::{ - self, group, Agent, Alignment, Body, Gravity, Item, ItemDrop, LightEmitter, Loadout, Pos, - Projectile, Scale, Stats, Vel, WaypointArea, + self, Agent, Alignment, Body, Gravity, Item, ItemDrop, LightEmitter, Loadout, + ParticleEmitter, Pos, Projectile, Scale, Stats, Vel, WaypointArea, }, util::Dir, }; @@ -77,6 +77,7 @@ pub fn handle_shoot( dir: Dir, body: Body, light: Option, + particles: Option, projectile: Projectile, gravity: Option, ) { @@ -96,6 +97,9 @@ pub fn handle_shoot( if let Some(light) = light { builder = builder.with(light) } + if let Some(particles) = particles { + builder = builder.with(particles) + } if let Some(gravity) = gravity { builder = builder.with(gravity) } @@ -113,6 +117,7 @@ pub fn handle_create_waypoint(server: &mut Server, pos: Vec3) { flicker: 1.0, animated: true, }) + .with(ParticleEmitter { mode: 0 }) .with(WaypointArea::default()) .build(); } diff --git a/server/src/events/mod.rs b/server/src/events/mod.rs index 412d9a536a..9761e1d869 100644 --- a/server/src/events/mod.rs +++ b/server/src/events/mod.rs @@ -61,9 +61,10 @@ impl Server { dir, body, light, + particles, projectile, gravity, - } => handle_shoot(self, entity, dir, body, light, projectile, gravity), + } => handle_shoot(self, entity, dir, body, light, particles, projectile, gravity), ServerEvent::Damage { uid, change } => handle_damage(&self, uid, change), ServerEvent::Destroy { entity, cause } => handle_destroy(self, entity, cause), ServerEvent::InventoryManip(entity, manip) => handle_inventory(self, entity, manip), diff --git a/server/src/sys/sentinel.rs b/server/src/sys/sentinel.rs index adcc76bd30..0fe4af0a3d 100644 --- a/server/src/sys/sentinel.rs +++ b/server/src/sys/sentinel.rs @@ -1,8 +1,9 @@ use super::SysTimer; use common::{ comp::{ - Body, CanBuild, CharacterState, Collider, Energy, Gravity, Group, Item, LightEmitter, - Loadout, Mass, MountState, Mounting, Ori, Player, Pos, Scale, Stats, Sticky, Vel, + Alignment, Body, CanBuild, CharacterState, Collider, Energy, Gravity, Item, LightEmitter, + Loadout, Mass, MountState, Mounting, Ori, ParticleEmitter, Player, Pos, Scale, Stats, + Sticky, Vel, }, msg::EcsCompPacket, sync::{CompSyncPackage, EntityPackage, EntitySyncPackage, Uid, UpdateTracker, WorldSyncExt}, @@ -44,6 +45,7 @@ pub struct TrackedComps<'a> { pub energy: ReadStorage<'a, Energy>, pub can_build: ReadStorage<'a, CanBuild>, pub light_emitter: ReadStorage<'a, LightEmitter>, + pub particle_emitter: ReadStorage<'a, ParticleEmitter>, pub item: ReadStorage<'a, Item>, pub scale: ReadStorage<'a, Scale>, pub mounting: ReadStorage<'a, Mounting>, @@ -92,6 +94,10 @@ impl<'a> TrackedComps<'a> { .get(entity) .copied() .map(|c| comps.push(c.into())); + self.particle_emitter + .get(entity) + .copied() + .map(|c| comps.push(c.into())); self.item.get(entity).cloned().map(|c| comps.push(c.into())); self.scale .get(entity) @@ -147,6 +153,7 @@ pub struct ReadTrackers<'a> { pub energy: ReadExpect<'a, UpdateTracker>, pub can_build: ReadExpect<'a, UpdateTracker>, pub light_emitter: ReadExpect<'a, UpdateTracker>, + pub particle_emitter: ReadExpect<'a, UpdateTracker>, pub item: ReadExpect<'a, UpdateTracker>, pub scale: ReadExpect<'a, UpdateTracker>, pub mounting: ReadExpect<'a, UpdateTracker>, @@ -180,6 +187,12 @@ impl<'a> ReadTrackers<'a> { &comps.light_emitter, filter, ) + .with_component( + &comps.uid, + &*self.particle_emitter, + &comps.particle_emitter, + filter, + ) .with_component(&comps.uid, &*self.item, &comps.item, filter) .with_component(&comps.uid, &*self.scale, &comps.scale, filter) .with_component(&comps.uid, &*self.mounting, &comps.mounting, filter) @@ -210,6 +223,7 @@ pub struct WriteTrackers<'a> { energy: WriteExpect<'a, UpdateTracker>, can_build: WriteExpect<'a, UpdateTracker>, light_emitter: WriteExpect<'a, UpdateTracker>, + particle_emitter: WriteExpect<'a, UpdateTracker>, item: WriteExpect<'a, UpdateTracker>, scale: WriteExpect<'a, UpdateTracker>, mounting: WriteExpect<'a, UpdateTracker>, @@ -232,6 +246,9 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) { trackers.energy.record_changes(&comps.energy); trackers.can_build.record_changes(&comps.can_build); trackers.light_emitter.record_changes(&comps.light_emitter); + trackers + .particle_emitter + .record_changes(&comps.particle_emitter); trackers.item.record_changes(&comps.item); trackers.scale.record_changes(&comps.scale); trackers.mounting.record_changes(&comps.mounting); @@ -287,6 +304,7 @@ pub fn register_trackers(world: &mut World) { world.register_tracker::(); world.register_tracker::(); world.register_tracker::(); + world.register_tracker::(); world.register_tracker::(); world.register_tracker::(); world.register_tracker::();