diff --git a/common/src/combat.rs b/common/src/combat.rs index fc593c5d38..cf13842281 100644 --- a/common/src/combat.rs +++ b/common/src/combat.rs @@ -28,7 +28,7 @@ pub enum GroupTarget { OutOfGroup, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] // TODO: Yeet clone derive pub struct Attack { damages: Vec, effects: Vec, @@ -177,7 +177,7 @@ impl Attack { } } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct DamageComponent { damage: Damage, target: Option, @@ -199,7 +199,7 @@ impl DamageComponent { } } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct EffectComponent { target: Option, effect: AttackEffect, @@ -221,7 +221,7 @@ impl EffectComponent { } } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub enum AttackEffect { //Heal(f32), Buff(CombatBuff), @@ -230,12 +230,12 @@ pub enum AttackEffect { //Lifesteal(f32), } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub enum CombatRequirement { AnyDamage, } -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] pub enum DamageSource { Buff(BuffKind), Melee, diff --git a/common/src/comp/beam.rs b/common/src/comp/beam.rs index 7aafcedffd..f5d06266e2 100644 --- a/common/src/comp/beam.rs +++ b/common/src/comp/beam.rs @@ -1,22 +1,23 @@ -use crate::{uid::Uid, Damage, GroupTarget}; +use crate::{combat::Attack, uid::Uid}; use serde::{Deserialize, Serialize}; use specs::{Component, DerefFlaggedStorage}; use specs_idvs::IdvStorage; use std::time::Duration; -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct Properties { + pub attack: Attack, pub angle: f32, pub speed: f32, - pub damages: Vec<(Option, Damage)>, - pub lifesteal_eff: f32, - pub energy_regen: u32, - pub energy_cost: u32, + //pub lifesteal_eff: f32, + //pub energy_regen: u32, + //pub energy_cost: u32, pub duration: Duration, pub owner: Option, } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +// TODO: Separate components out for cheaper network syncing +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct BeamSegment { pub properties: Properties, #[serde(skip)] diff --git a/common/src/comp/projectile.rs b/common/src/comp/projectile.rs index d57978851f..06bb97f7e3 100644 --- a/common/src/comp/projectile.rs +++ b/common/src/comp/projectile.rs @@ -21,10 +21,10 @@ pub enum Effect { Vanish, Stick, Possess, - /*Buff { - * buff: BuffEffect, - * chance: Option, */ - /* */ + /* Buff { + * buff: BuffEffect, + * chance: Option, + * }, */ } #[derive(Debug, Serialize, Deserialize)] diff --git a/common/src/comp/shockwave.rs b/common/src/comp/shockwave.rs index a844bc29c3..cae93eb73c 100644 --- a/common/src/comp/shockwave.rs +++ b/common/src/comp/shockwave.rs @@ -4,7 +4,7 @@ use specs::{Component, DerefFlaggedStorage}; use specs_idvs::IdvStorage; use std::time::Duration; -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct Properties { pub angle: f32, pub vertical_angle: f32, @@ -16,7 +16,7 @@ pub struct Properties { pub owner: Option, } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct Shockwave { pub properties: Properties, #[serde(skip)] diff --git a/common/src/states/basic_beam.rs b/common/src/states/basic_beam.rs index 07bac71c76..5f23c595df 100644 --- a/common/src/states/basic_beam.rs +++ b/common/src/states/basic_beam.rs @@ -1,4 +1,8 @@ use crate::{ + combat::{ + Attack, AttackEffect, CombatRequirement, Damage, DamageComponent, DamageSource, + EffectComponent, GroupTarget, + }, comp::{beam, Body, CharacterState, EnergyChange, EnergySource, Ori, Pos, StateUpdate}, event::ServerEvent, states::{ @@ -6,7 +10,6 @@ use crate::{ utils::*, }, uid::Uid, - Damage, DamageSource, GroupTarget, }; use serde::{Deserialize, Serialize}; use std::time::Duration; @@ -129,16 +132,17 @@ impl CharacterBehavior for Data { }; let speed = self.static_data.range / self.static_data.beam_duration.as_secs_f32(); + + let energy = AttackEffect::EnergyReward(self.static_data.energy_regen); + let energy = EffectComponent::new(None, energy) + .with_requirement(CombatRequirement::AnyDamage); + let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup)); + let attack = Attack::default().with_damage(damage).with_effect(energy); + let properties = beam::Properties { + attack, angle: self.static_data.max_angle.to_radians(), speed, - damages: vec![ - (Some(GroupTarget::OutOfGroup), damage), - (Some(GroupTarget::InGroup), heal), - ], - lifesteal_eff: self.static_data.lifesteal_eff, - energy_regen: self.static_data.energy_regen, - energy_cost: self.static_data.energy_cost, duration: self.static_data.beam_duration, owner: Some(*data.uid), }; diff --git a/common/sys/src/beam.rs b/common/sys/src/beam.rs index 1dc2041117..6fa408b253 100644 --- a/common/sys/src/beam.rs +++ b/common/sys/src/beam.rs @@ -1,7 +1,7 @@ use common::{ comp::{ - group, Beam, BeamSegment, Body, Energy, EnergyChange, EnergySource, Health, HealthChange, - HealthSource, Inventory, Last, Ori, Pos, Scale, + group, Beam, BeamSegment, Body, Energy, Health, HealthSource, Inventory, Last, Ori, Pos, + Scale, }, event::{EventBus, ServerEvent}, resources::{DeltaTime, Time}, @@ -112,7 +112,16 @@ impl<'a> System<'a> for Sys { }; // Go through all other effectable entities - for (b, uid_b, pos_b, last_pos_b_maybe, scale_b_maybe, health_b, body_b) in ( + for ( + b, + uid_b, + pos_b, + last_pos_b_maybe, + scale_b_maybe, + health_b, + body_b, + inventory_b_maybe, + ) in ( &entities, &uids, &positions, @@ -121,6 +130,7 @@ impl<'a> System<'a> for Sys { scales.maybe(), &healths, &bodies, + inventories.maybe(), ) .join() { @@ -158,68 +168,96 @@ impl<'a> System<'a> for Sys { continue; } - for (target, damage) in beam_segment.damages.iter() { - if let Some(target) = target { - if *target != target_group { - continue; - } - } - - // Modify damage - let change = damage.modify_damage( - inventories.get(b), - beam_segment.owner, + if let (Some(beam_owner), Some(owner_uid)) = (beam_owner, beam_segment.owner) { + let server_events = beam_segment.properties.attack.apply_attack( + target_group, + beam_owner, + b, + inventory_b_maybe, + owner_uid, + ori.0, false, - 0.0, ); - match target { - Some(GroupTarget::OutOfGroup) => { - server_emitter.emit(ServerEvent::Damage { entity: b, change }); - if let Some(entity) = beam_owner { - server_emitter.emit(ServerEvent::Damage { - entity, - change: HealthChange { - amount: (-change.amount as f32 - * beam_segment.lifesteal_eff) - as i32, - cause: HealthSource::Heal { - by: beam_segment.owner, - }, - }, - }); - server_emitter.emit(ServerEvent::EnergyChange { - entity, - change: EnergyChange { - amount: beam_segment.energy_regen as i32, - source: EnergySource::HitEnemy, - }, - }); - } - }, - Some(GroupTarget::InGroup) => { - if let Some(energy) = beam_owner.and_then(|o| energies.get(o)) { - if energy.current() > beam_segment.energy_cost { - server_emitter.emit(ServerEvent::EnergyChange { - entity: beam_owner.unwrap(), /* If it's able to get an energy - * component, the entity exists */ - change: EnergyChange { - amount: -(beam_segment.energy_cost as i32), // Stamina use - source: EnergySource::Ability, - }, - }); - server_emitter - .emit(ServerEvent::Damage { entity: b, change }); - } - } - }, - None => {}, + if !server_events.is_empty() { + hit_entities.push(*uid_b); } - // Adds entities that were hit to the hit_entities list on the beam, sees if - // it needs to purge the hit_entities list - hit_entities.push(*uid_b); + for event in server_events { + server_emitter.emit(event); + } } + + // for (target, damage) in beam_segment.damages.iter() { + // if let Some(target) = target { + // if *target != target_group { + // continue; + // } + // } + + // // Modify damage + // let change = damage.modify_damage( + // inventories.get(b), + // beam_segment.owner, + // false, + // 0.0, + // ); + + // match target { + // Some(GroupTarget::OutOfGroup) => { + // server_emitter.emit(ServerEvent::Damage { + // entity: b, change }); if + // let Some(entity) = beam_owner { + // server_emitter.emit(ServerEvent::Damage { + // entity, + // change: HealthChange { + // amount: (-change.amount as f32 + // * beam_segment.lifesteal_eff) + // as i32, + // cause: HealthSource::Heal { + // by: beam_segment.owner, + // }, + // }, + // }); + // + // server_emitter.emit(ServerEvent::EnergyChange { + // entity, + // change: EnergyChange { + // amount: beam_segment.energy_regen + // as i32, + // source: EnergySource::HitEnemy, + // }, + // }); + // } + // }, + // Some(GroupTarget::InGroup) => { + // if let Some(energy) = beam_owner.and_then(|o| + // energies.get(o)) { if + // energy.current() > beam_segment.energy_cost { + // + // server_emitter.emit(ServerEvent::EnergyChange { + // entity: beam_owner.unwrap(), /* + // If it's able to get an energy + // * component, the entity exists */ + // change: EnergyChange { + // amount: + // -(beam_segment.energy_cost as i32), // Stamina use + // source: + // EnergySource::Ability, + // }, }); + // server_emitter + // .emit(ServerEvent::Damage { + // entity: b, change }); + // } } + // }, + // None => {}, + // } + + // // Adds entities that were hit to the hit_entities + // list on the beam, sees if // it needs + // to purge the hit_entities list + // hit_entities.push(*uid_b); + // } } } } diff --git a/server/src/events/entity_creation.rs b/server/src/events/entity_creation.rs index 03fa9dd55a..ca4930eb95 100644 --- a/server/src/events/entity_creation.rs +++ b/server/src/events/entity_creation.rs @@ -170,7 +170,7 @@ pub fn handle_beam(server: &mut Server, properties: beam::Properties, pos: Pos, let ecs = state.ecs(); ecs.write_resource::>().push(Outcome::Beam { pos: pos.0, - heal: properties.lifesteal_eff > 0.0, + heal: false, //properties.lifesteal_eff > 0.0, }); state.create_beam(properties, pos, ori).build(); }