From be8df9aef653bfdb39397cbb4d8222191f6489d8 Mon Sep 17 00:00:00 2001 From: Sam Date: Tue, 2 Feb 2021 13:02:40 -0500 Subject: [PATCH] Addressed comments. --- common/src/combat.rs | 215 +++++++++++++---------- common/src/comp/character_state.rs | 4 +- common/src/comp/mod.rs | 2 +- common/src/comp/poise.rs | 10 +- common/src/comp/projectile.rs | 88 +++++----- common/src/states/basic_beam.rs | 43 +++-- common/src/states/basic_melee.rs | 53 +++--- common/src/states/behavior.rs | 6 +- common/src/states/charged_melee.rs | 60 ++++--- common/src/states/charged_ranged.rs | 39 ++-- common/src/states/combo_melee.rs | 57 +++--- common/src/states/dash_melee.rs | 62 +++---- common/src/states/leap_melee.rs | 50 +++--- common/src/states/shockwave.rs | 32 ++-- common/src/states/spin_melee.rs | 50 +++--- common/sys/src/beam.rs | 25 +-- common/sys/src/character_behavior.rs | 6 +- common/sys/src/melee.rs | 26 +-- common/sys/src/projectile.rs | 69 ++------ common/sys/src/shockwave.rs | 25 +-- common/sys/src/state.rs | 2 +- server/src/events/entity_creation.rs | 2 +- server/src/events/entity_manipulation.rs | 37 ++-- server/src/state_ext.rs | 8 +- 24 files changed, 505 insertions(+), 466 deletions(-) diff --git a/common/src/combat.rs b/common/src/combat.rs index 4dae84f8a7..610925b447 100644 --- a/common/src/combat.rs +++ b/common/src/combat.rs @@ -30,10 +30,17 @@ pub enum GroupTarget { OutOfGroup, } +#[derive(Copy, Clone)] +pub struct AttackerInfo<'a> { + pub entity: EcsEntity, + pub uid: Uid, + pub energy: Option<&'a Energy>, +} + #[derive(Clone, Debug, Serialize, Deserialize)] // TODO: Yeet clone derive pub struct Attack { - damages: Vec, - effects: Vec, + damages: Vec, + effects: Vec, crit_chance: f32, crit_multiplier: f32, } @@ -50,50 +57,48 @@ impl Default for Attack { } impl Attack { - pub fn with_damage(mut self, damage: DamageComponent) -> Self { + pub fn with_damage(mut self, damage: AttackDamage) -> Self { self.damages.push(damage); self } - pub fn with_effect(mut self, effect: EffectComponent) -> Self { + pub fn with_effect(mut self, effect: AttackEffect) -> Self { self.effects.push(effect); self } - pub fn with_crit(mut self, cc: f32, cm: f32) -> Self { - self.crit_chance = cc; - self.crit_multiplier = cm; + pub fn with_crit(mut self, crit_chance: f32, crit_multiplier: f32) -> Self { + self.crit_chance = crit_chance; + self.crit_multiplier = crit_multiplier; self } - pub fn effects(&self) -> impl Iterator { self.effects.iter() } + pub fn effects(&self) -> impl Iterator { self.effects.iter() } #[allow(clippy::too_many_arguments)] pub fn apply_attack( &self, target_group: GroupTarget, - attacker_entity: Option, + attacker_info: Option, target_entity: EcsEntity, target_inventory: Option<&Inventory>, - attacker_uid: Option, - attacker_energy: Option<&Energy>, dir: Dir, target_dodging: bool, // Currently just modifies damage, maybe look into modifying strength of other effects? strength_modifier: f32, - ) -> Vec { + mut emit: impl FnMut(ServerEvent), + ) { let is_crit = thread_rng().gen::() < self.crit_chance; let mut accumulated_damage = 0.0; - let mut server_events = Vec::new(); for damage in self .damages .iter() .filter(|d| d.target.map_or(true, |t| t == target_group)) .filter(|d| !(matches!(d.target, Some(GroupTarget::OutOfGroup)) && target_dodging)) { - let change = damage.damage.modify_damage( + let change = damage.damage.calculate_health_change( target_inventory, - attacker_uid, + attacker_info.map(|a| a.uid), is_crit, self.crit_multiplier, strength_modifier, @@ -101,24 +106,24 @@ impl Attack { let applied_damage = -change.amount as f32; accumulated_damage += applied_damage; if change.amount != 0 { - server_events.push(ServerEvent::Damage { + emit(ServerEvent::Damage { entity: target_entity, change, }); for effect in damage.effects.iter() { match effect { - AttackEffect::Knockback(kb) => { + CombatEffect::Knockback(kb) => { let impulse = kb.calculate_impulse(dir); if !impulse.is_approx_zero() { - server_events.push(ServerEvent::Knockback { + emit(ServerEvent::Knockback { entity: target_entity, impulse, }); } }, - AttackEffect::EnergyReward(ec) => { - if let Some(attacker_entity) = attacker_entity { - server_events.push(ServerEvent::EnergyChange { + CombatEffect::EnergyReward(ec) => { + if let Some(attacker_entity) = attacker_info.map(|a| a.entity) { + emit(ServerEvent::EnergyChange { entity: attacker_entity, change: EnergyChange { amount: *ec as i32, @@ -127,45 +132,55 @@ impl Attack { }); } }, - AttackEffect::Buff(b) => { + CombatEffect::Buff(b) => { if thread_rng().gen::() < b.chance { - server_events.push(ServerEvent::Buff { + emit(ServerEvent::Buff { entity: target_entity, buff_change: BuffChange::Add( - b.to_buff(attacker_uid, applied_damage), + b.to_buff(attacker_info.map(|a| a.uid), applied_damage), ), }); } }, - AttackEffect::Lifesteal(l) => { - if let Some(attacker_entity) = attacker_entity { + CombatEffect::Lifesteal(l) => { + if let Some(attacker_entity) = attacker_info.map(|a| a.entity) { let change = HealthChange { amount: (applied_damage * l) as i32, - cause: HealthSource::Heal { by: attacker_uid }, + cause: HealthSource::Heal { + by: attacker_info.map(|a| a.uid), + }, }; - server_events.push(ServerEvent::Damage { - entity: attacker_entity, + if change.amount != 0 { + emit(ServerEvent::Damage { + entity: attacker_entity, + change, + }); + } + } + }, + CombatEffect::Poise(p) => { + let change = PoiseChange::from_value(*p, target_inventory); + if change.amount != 0 { + emit(ServerEvent::PoiseChange { + entity: target_entity, change, + kb_dir: *dir, }); } }, - AttackEffect::Poise(p) => { - let change = PoiseChange::from_attack(*p, target_inventory); - server_events.push(ServerEvent::PoiseChange { - entity: target_entity, - change, - kb_dir: *dir, - }); - }, - AttackEffect::Heal(h) => { + CombatEffect::Heal(h) => { let change = HealthChange { amount: *h as i32, - cause: HealthSource::Heal { by: attacker_uid }, + cause: HealthSource::Heal { + by: attacker_info.map(|a| a.uid), + }, }; - server_events.push(ServerEvent::Damage { - entity: target_entity, - change, - }); + if change.amount != 0 { + emit(ServerEvent::Damage { + entity: target_entity, + change, + }); + } }, } } @@ -180,17 +195,24 @@ impl Attack { if match &effect.requirement { Some(CombatRequirement::AnyDamage) => accumulated_damage > 0.0, Some(CombatRequirement::SufficientEnergy(r)) => { - if attacker_energy.map_or(true, |e| e.current() >= *r) { - if let Some(attacker_entity) = attacker_entity { - server_events.push(ServerEvent::EnergyChange { - entity: attacker_entity, + if let Some(AttackerInfo { + entity, + energy: Some(e), + .. + }) = attacker_info + { + let sufficient_energy = e.current() >= *r; + if sufficient_energy { + emit(ServerEvent::EnergyChange { + entity, change: EnergyChange { amount: -(*r as i32), source: EnergySource::Ability, }, }); } - true + + sufficient_energy } else { false } @@ -198,18 +220,18 @@ impl Attack { None => true, } { match effect.effect { - AttackEffect::Knockback(kb) => { + CombatEffect::Knockback(kb) => { let impulse = kb.calculate_impulse(dir); if !impulse.is_approx_zero() { - server_events.push(ServerEvent::Knockback { + emit(ServerEvent::Knockback { entity: target_entity, impulse, }); } }, - AttackEffect::EnergyReward(ec) => { - if let Some(attacker_entity) = attacker_entity { - server_events.push(ServerEvent::EnergyChange { + CombatEffect::EnergyReward(ec) => { + if let Some(attacker_entity) = attacker_info.map(|a| a.entity) { + emit(ServerEvent::EnergyChange { entity: attacker_entity, change: EnergyChange { amount: ec as i32, @@ -218,61 +240,70 @@ impl Attack { }); } }, - AttackEffect::Buff(b) => { + CombatEffect::Buff(b) => { if thread_rng().gen::() < b.chance { - server_events.push(ServerEvent::Buff { + emit(ServerEvent::Buff { entity: target_entity, buff_change: BuffChange::Add( - b.to_buff(attacker_uid, accumulated_damage), + b.to_buff(attacker_info.map(|a| a.uid), accumulated_damage), ), }); } }, - AttackEffect::Lifesteal(l) => { - if let Some(attacker_entity) = attacker_entity { + CombatEffect::Lifesteal(l) => { + if let Some(attacker_entity) = attacker_info.map(|a| a.entity) { let change = HealthChange { amount: (accumulated_damage * l) as i32, - cause: HealthSource::Heal { by: attacker_uid }, + cause: HealthSource::Heal { + by: attacker_info.map(|a| a.uid), + }, }; - server_events.push(ServerEvent::Damage { - entity: attacker_entity, + if change.amount != 0 { + emit(ServerEvent::Damage { + entity: attacker_entity, + change, + }); + } + } + }, + CombatEffect::Poise(p) => { + let change = PoiseChange::from_value(p, target_inventory); + if change.amount != 0 { + emit(ServerEvent::PoiseChange { + entity: target_entity, + change, + kb_dir: *dir, + }); + } + }, + CombatEffect::Heal(h) => { + let change = HealthChange { + amount: h as i32, + cause: HealthSource::Heal { + by: attacker_info.map(|a| a.uid), + }, + }; + if change.amount != 0 { + emit(ServerEvent::Damage { + entity: target_entity, change, }); } }, - AttackEffect::Poise(p) => { - let change = PoiseChange::from_attack(p, target_inventory); - server_events.push(ServerEvent::PoiseChange { - entity: target_entity, - change, - kb_dir: *dir, - }); - }, - AttackEffect::Heal(h) => { - let change = HealthChange { - amount: h as i32, - cause: HealthSource::Heal { by: attacker_uid }, - }; - server_events.push(ServerEvent::Damage { - entity: target_entity, - change, - }); - }, } } } - server_events } } #[derive(Clone, Debug, Serialize, Deserialize)] -pub struct DamageComponent { +pub struct AttackDamage { damage: Damage, target: Option, - effects: Vec, + effects: Vec, } -impl DamageComponent { +impl AttackDamage { pub fn new(damage: Damage, target: Option) -> Self { Self { damage, @@ -281,21 +312,21 @@ impl DamageComponent { } } - pub fn with_effect(mut self, effect: AttackEffect) -> Self { + pub fn with_effect(mut self, effect: CombatEffect) -> Self { self.effects.push(effect); self } } #[derive(Clone, Debug, Serialize, Deserialize)] -pub struct EffectComponent { +pub struct AttackEffect { target: Option, - effect: AttackEffect, + effect: CombatEffect, requirement: Option, } -impl EffectComponent { - pub fn new(target: Option, effect: AttackEffect) -> Self { +impl AttackEffect { + pub fn new(target: Option, effect: CombatEffect) -> Self { Self { target, effect, @@ -308,11 +339,11 @@ impl EffectComponent { self } - pub fn effect(&self) -> &AttackEffect { &self.effect } + pub fn effect(&self) -> &CombatEffect { &self.effect } } #[derive(Clone, Debug, Serialize, Deserialize)] -pub enum AttackEffect { +pub enum CombatEffect { Heal(f32), Buff(CombatBuff), Knockback(Knockback), @@ -368,7 +399,7 @@ impl Damage { } } - pub fn modify_damage( + pub fn calculate_health_change( self, inventory: Option<&Inventory>, uid: Option, @@ -377,7 +408,7 @@ impl Damage { damage_modifier: f32, ) -> HealthChange { let mut damage = self.value * damage_modifier; - let damage_reduction = inventory.map_or(0.0, |inv| Damage::compute_damage_reduction(inv)); + let damage_reduction = inventory.map_or(0.0, Damage::compute_damage_reduction); match self.source { DamageSource::Melee => { // Critical hit diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs index d0fb1541d1..eaeee7da8b 100644 --- a/common/src/comp/character_state.rs +++ b/common/src/comp/character_state.rs @@ -170,7 +170,7 @@ impl Component for CharacterState { } #[derive(Debug, Serialize, Deserialize)] -pub struct MeleeAttack { +pub struct Melee { pub attack: Attack, pub range: f32, pub max_angle: f32, @@ -178,6 +178,6 @@ pub struct MeleeAttack { pub hit_count: u32, } -impl Component for MeleeAttack { +impl Component for Melee { type Storage = VecStorage; } diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index 76e4438573..72dad9fa85 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -40,7 +40,7 @@ pub use buff::{ Buff, BuffCategory, BuffChange, BuffData, BuffEffect, BuffId, BuffKind, BuffSource, Buffs, ModifierKind, }; -pub use character_state::{CharacterState, MeleeAttack, StateUpdate}; +pub use character_state::{CharacterState, Melee, StateUpdate}; pub use chat::{ ChatMode, ChatMsg, ChatType, Faction, SpeechBubble, SpeechBubbleType, UnresolvedChatMsg, }; diff --git a/common/src/comp/poise.rs b/common/src/comp/poise.rs index ab2ffb46f4..1e13be2f13 100644 --- a/common/src/comp/poise.rs +++ b/common/src/comp/poise.rs @@ -21,8 +21,7 @@ pub struct PoiseChange { impl PoiseChange { /// Alters poise damage as a result of armor poise damage reduction pub fn modify_poise_damage(self, inventory: Option<&Inventory>) -> PoiseChange { - let poise_damage_reduction = - inventory.map_or(0.0, |inv| Poise::compute_poise_damage_reduction(inv)); + let poise_damage_reduction = inventory.map_or(0.0, Poise::compute_poise_damage_reduction); let poise_damage = self.amount as f32 * (1.0 - poise_damage_reduction); // Add match on poise source when different calculations per source // are needed/wanted @@ -32,10 +31,9 @@ impl PoiseChange { } } - /// Creates a poise change from an attack - pub fn from_attack(poise_damage: f32, inventory: Option<&Inventory>) -> Self { - let poise_damage_reduction = - inventory.map_or(0.0, |inv| Poise::compute_poise_damage_reduction(inv)); + /// Creates a poise change from a float + pub fn from_value(poise_damage: f32, inventory: Option<&Inventory>) -> Self { + let poise_damage_reduction = inventory.map_or(0.0, Poise::compute_poise_damage_reduction); let poise_change = -poise_damage * (1.0 - poise_damage_reduction); Self { amount: poise_change as i32, diff --git a/common/src/comp/projectile.rs b/common/src/comp/projectile.rs index b35b512f44..ac80d554ff 100644 --- a/common/src/comp/projectile.rs +++ b/common/src/comp/projectile.rs @@ -1,7 +1,7 @@ use crate::{ combat::{ - Attack, AttackEffect, CombatBuff, CombatRequirement, Damage, DamageComponent, DamageSource, - EffectComponent, GroupTarget, Knockback, KnockbackDir, + Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement, Damage, + DamageSource, GroupTarget, Knockback, KnockbackDir, }, uid::Uid, Explosion, RadiusEffect, @@ -14,16 +14,10 @@ use std::time::Duration; #[derive(Debug, Serialize, Deserialize)] pub enum Effect { Attack(Attack), - //Knockback(Knockback), - //RewardEnergy(u32), Explode(Explosion), Vanish, Stick, Possess, - /* Buff { - * buff: BuffEffect, - * chance: Option, - * }, */ } #[derive(Debug, Serialize, Deserialize)] @@ -76,22 +70,25 @@ impl ProjectileConstructor { knockback, energy_regen, } => { - let knockback = AttackEffect::Knockback(Knockback { - strength: knockback, - direction: KnockbackDir::Away, - }); - let knockback = EffectComponent::new(Some(GroupTarget::OutOfGroup), knockback) + let knockback = AttackEffect::new( + Some(GroupTarget::OutOfGroup), + CombatEffect::Knockback(Knockback { + strength: knockback, + direction: KnockbackDir::Away, + }), + ) + .with_requirement(CombatRequirement::AnyDamage); + let energy = AttackEffect::new(None, CombatEffect::EnergyReward(energy_regen)) .with_requirement(CombatRequirement::AnyDamage); - let energy = AttackEffect::EnergyReward(energy_regen); - let energy = EffectComponent::new(None, energy) - .with_requirement(CombatRequirement::AnyDamage); - let buff = AttackEffect::Buff(CombatBuff::default_physical()); - let damage = Damage { - source: DamageSource::Projectile, - value: damage, - }; - let damage = - DamageComponent::new(damage, Some(GroupTarget::OutOfGroup)).with_effect(buff); + let buff = CombatEffect::Buff(CombatBuff::default_physical()); + let damage = AttackDamage::new( + Damage { + source: DamageSource::Projectile, + value: damage, + }, + Some(GroupTarget::OutOfGroup), + ) + .with_effect(buff); let attack = Attack::default() .with_damage(damage) .with_crit(0.5, 1.2) @@ -111,14 +108,15 @@ impl ProjectileConstructor { radius, energy_regen, } => { - let energy = AttackEffect::EnergyReward(energy_regen); - let energy = EffectComponent::new(None, energy) + let energy = AttackEffect::new(None, CombatEffect::EnergyReward(energy_regen)) .with_requirement(CombatRequirement::AnyDamage); - let damage = Damage { - source: DamageSource::Explosion, - value: damage, - }; - let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup)); + let damage = AttackDamage::new( + Damage { + source: DamageSource::Explosion, + value: damage, + }, + Some(GroupTarget::OutOfGroup), + ); let attack = Attack::default().with_damage(damage).with_effect(energy); let explosion = Explosion { effects: vec![ @@ -139,14 +137,15 @@ impl ProjectileConstructor { damage, energy_regen, } => { - let energy = AttackEffect::EnergyReward(energy_regen); - let energy = EffectComponent::new(None, energy) + let energy = AttackEffect::new(None, CombatEffect::EnergyReward(energy_regen)) .with_requirement(CombatRequirement::AnyDamage); - let damage = Damage { - source: DamageSource::Energy, - value: damage, - }; - let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup)); + let damage = AttackDamage::new( + Damage { + source: DamageSource::Energy, + value: damage, + }, + Some(GroupTarget::OutOfGroup), + ); let attack = Attack::default().with_damage(damage).with_effect(energy); Projectile { @@ -162,13 +161,14 @@ impl ProjectileConstructor { damage, radius, } => { - let damage = Damage { - source: DamageSource::Explosion, - value: damage, - }; - let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup)); - let heal = AttackEffect::Heal(heal); - let heal = EffectComponent::new(Some(GroupTarget::InGroup), heal); + let damage = AttackDamage::new( + Damage { + source: DamageSource::Explosion, + value: damage, + }, + Some(GroupTarget::OutOfGroup), + ); + let heal = AttackEffect::new(Some(GroupTarget::InGroup), CombatEffect::Heal(heal)); let attack = Attack::default().with_damage(damage).with_effect(heal); let explosion = Explosion { effects: vec![RadiusEffect::Attack(attack)], diff --git a/common/src/states/basic_beam.rs b/common/src/states/basic_beam.rs index ccaab77a04..f5b127fed7 100644 --- a/common/src/states/basic_beam.rs +++ b/common/src/states/basic_beam.rs @@ -1,7 +1,7 @@ use crate::{ combat::{ - Attack, AttackEffect, CombatRequirement, Damage, DamageComponent, DamageSource, - EffectComponent, GroupTarget, + Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement, Damage, DamageSource, + GroupTarget, }, comp::{beam, Body, CharacterState, EnergyChange, EnergySource, Ori, Pos, StateUpdate}, event::ServerEvent, @@ -122,25 +122,32 @@ impl CharacterBehavior for Data { if ability_key_is_pressed(data, self.static_data.ability_key) && (self.static_data.energy_drain == 0 || update.energy.current() > 0) { - let damage = Damage { - source: DamageSource::Energy, - value: self.static_data.base_dps as f32 / self.static_data.tick_rate, - }; - let heal = self.static_data.base_hps as f32 / self.static_data.tick_rate; - let heal = AttackEffect::Heal(heal); 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 lifesteal = AttackEffect::Lifesteal(self.static_data.lifesteal_eff); - let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup)) - .with_effect(lifesteal); - let heal = EffectComponent::new(Some(GroupTarget::InGroup), heal) - .with_requirement(CombatRequirement::SufficientEnergy( - self.static_data.energy_cost, - )); + let energy = AttackEffect::new( + None, + CombatEffect::EnergyReward(self.static_data.energy_regen), + ) + .with_requirement(CombatRequirement::AnyDamage); + let lifesteal = CombatEffect::Lifesteal(self.static_data.lifesteal_eff); + let damage = AttackDamage::new( + Damage { + source: DamageSource::Energy, + value: self.static_data.base_dps as f32 / self.static_data.tick_rate, + }, + Some(GroupTarget::OutOfGroup), + ) + .with_effect(lifesteal); + let heal = AttackEffect::new( + Some(GroupTarget::InGroup), + CombatEffect::Heal( + self.static_data.base_hps as f32 / self.static_data.tick_rate, + ), + ) + .with_requirement(CombatRequirement::SufficientEnergy( + self.static_data.energy_cost, + )); let attack = Attack::default() .with_damage(damage) .with_effect(energy) diff --git a/common/src/states/basic_melee.rs b/common/src/states/basic_melee.rs index 778d624fbb..38c7a0972f 100644 --- a/common/src/states/basic_melee.rs +++ b/common/src/states/basic_melee.rs @@ -1,8 +1,6 @@ use crate::{ - combat::{ - Attack, AttackEffect, CombatBuff, CombatRequirement, DamageComponent, EffectComponent, - }, - comp::{CharacterState, MeleeAttack, StateUpdate}, + combat::{Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement}, + comp::{CharacterState, Melee, StateUpdate}, states::{ behavior::{CharacterBehavior, JoinData}, utils::*, @@ -92,25 +90,30 @@ impl CharacterBehavior for Data { ..*self }); - let poise = AttackEffect::Poise(self.static_data.base_poise_damage as f32); - let poise = EffectComponent::new(Some(GroupTarget::OutOfGroup), poise) + let poise = AttackEffect::new( + Some(GroupTarget::OutOfGroup), + CombatEffect::Poise(self.static_data.base_poise_damage as f32), + ) + .with_requirement(CombatRequirement::AnyDamage); + let knockback = AttackEffect::new( + Some(GroupTarget::OutOfGroup), + CombatEffect::Knockback(Knockback { + strength: self.static_data.knockback, + direction: KnockbackDir::Away, + }), + ) + .with_requirement(CombatRequirement::AnyDamage); + let energy = AttackEffect::new(None, CombatEffect::EnergyReward(50)) .with_requirement(CombatRequirement::AnyDamage); - let knockback = AttackEffect::Knockback(Knockback { - strength: self.static_data.knockback, - direction: KnockbackDir::Away, - }); - let knockback = EffectComponent::new(Some(GroupTarget::OutOfGroup), knockback) - .with_requirement(CombatRequirement::AnyDamage); - let energy = AttackEffect::EnergyReward(50); - let energy = EffectComponent::new(None, energy) - .with_requirement(CombatRequirement::AnyDamage); - let buff = AttackEffect::Buff(CombatBuff::default_physical()); - let damage = Damage { - source: DamageSource::Melee, - value: self.static_data.base_damage as f32, - }; - let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup)) - .with_effect(buff); + let buff = CombatEffect::Buff(CombatBuff::default_physical()); + let damage = AttackDamage::new( + Damage { + source: DamageSource::Melee, + value: self.static_data.base_damage as f32, + }, + Some(GroupTarget::OutOfGroup), + ) + .with_effect(buff); let attack = Attack::default() .with_damage(damage) .with_crit(0.5, 1.3) @@ -119,7 +122,7 @@ impl CharacterBehavior for Data { .with_effect(knockback); // Hit attempt - data.updater.insert(data.entity, MeleeAttack { + data.updater.insert(data.entity, Melee { attack, range: self.static_data.range, max_angle: self.static_data.max_angle, @@ -158,14 +161,14 @@ impl CharacterBehavior for Data { // Done update.character = CharacterState::Wielding; // Make sure attack component is removed - data.updater.remove::(data.entity); + data.updater.remove::(data.entity); } }, _ => { // If it somehow ends up in an incorrect stage section update.character = CharacterState::Wielding; // Make sure attack component is removed - data.updater.remove::(data.entity); + data.updater.remove::(data.entity); }, } diff --git a/common/src/states/behavior.rs b/common/src/states/behavior.rs index c6c66df258..0e0a9e4917 100644 --- a/common/src/states/behavior.rs +++ b/common/src/states/behavior.rs @@ -1,7 +1,7 @@ use crate::{ comp::{ Beam, Body, CharacterState, ControlAction, Controller, ControllerInputs, Energy, Health, - Inventory, MeleeAttack, Ori, PhysicsState, Pos, StateUpdate, Stats, Vel, + Inventory, Melee, Ori, PhysicsState, Pos, StateUpdate, Stats, Vel, }, resources::DeltaTime, uid::Uid, @@ -57,7 +57,7 @@ pub struct JoinData<'a> { pub inventory: &'a Inventory, pub body: &'a Body, pub physics: &'a PhysicsState, - pub melee_attack: Option<&'a MeleeAttack>, + pub melee_attack: Option<&'a Melee>, pub updater: &'a LazyUpdate, pub stats: &'a Stats, } @@ -84,7 +84,7 @@ pub type JoinTuple<'a> = ( &'a Health, &'a Body, &'a PhysicsState, - Option<&'a MeleeAttack>, + Option<&'a Melee>, Option<&'a Beam>, &'a Stats, ); diff --git a/common/src/states/charged_melee.rs b/common/src/states/charged_melee.rs index d8144b96b0..8ebc6749d6 100644 --- a/common/src/states/charged_melee.rs +++ b/common/src/states/charged_melee.rs @@ -1,8 +1,6 @@ use crate::{ - combat::{ - Attack, AttackEffect, CombatBuff, CombatRequirement, DamageComponent, EffectComponent, - }, - comp::{CharacterState, EnergyChange, EnergySource, MeleeAttack, StateUpdate}, + combat::{Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement}, + comp::{CharacterState, EnergyChange, EnergySource, Melee, StateUpdate}, states::{ behavior::{CharacterBehavior, JoinData}, utils::{StageSection, *}, @@ -155,27 +153,33 @@ impl CharacterBehavior for Data { exhausted: true, ..*self }); - let poise = self.static_data.initial_poise_damage as f32 - + self.charge_amount * self.static_data.scaled_poise_damage as f32; - let poise = AttackEffect::Poise(poise); - let poise = EffectComponent::new(Some(GroupTarget::OutOfGroup), poise) - .with_requirement(CombatRequirement::AnyDamage); - let knockback = self.static_data.initial_knockback - + self.charge_amount * self.static_data.scaled_knockback; - let knockback = AttackEffect::Knockback(Knockback { - strength: knockback, - direction: KnockbackDir::Away, - }); - let knockback = EffectComponent::new(Some(GroupTarget::OutOfGroup), knockback) - .with_requirement(CombatRequirement::AnyDamage); - let buff = AttackEffect::Buff(CombatBuff::default_physical()); - let damage = Damage { - source: DamageSource::Melee, - value: self.static_data.initial_damage as f32 - + self.charge_amount * self.static_data.scaled_damage as f32, - }; - let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup)) - .with_effect(buff); + let poise = AttackEffect::new( + Some(GroupTarget::OutOfGroup), + CombatEffect::Poise( + self.static_data.initial_poise_damage as f32 + + self.charge_amount * self.static_data.scaled_poise_damage as f32, + ), + ) + .with_requirement(CombatRequirement::AnyDamage); + let knockback = AttackEffect::new( + Some(GroupTarget::OutOfGroup), + CombatEffect::Knockback(Knockback { + strength: self.static_data.initial_knockback + + self.charge_amount * self.static_data.scaled_knockback, + direction: KnockbackDir::Away, + }), + ) + .with_requirement(CombatRequirement::AnyDamage); + let buff = CombatEffect::Buff(CombatBuff::default_physical()); + let damage = AttackDamage::new( + Damage { + source: DamageSource::Melee, + value: self.static_data.initial_damage as f32 + + self.charge_amount * self.static_data.scaled_damage as f32, + }, + Some(GroupTarget::OutOfGroup), + ) + .with_effect(buff); let attack = Attack::default() .with_damage(damage) .with_crit(0.5, 1.3) @@ -183,7 +187,7 @@ impl CharacterBehavior for Data { .with_effect(knockback); // Hit attempt - data.updater.insert(data.entity, MeleeAttack { + data.updater.insert(data.entity, Melee { attack, range: self.static_data.range, max_angle: self.static_data.max_angle.to_radians(), @@ -222,14 +226,14 @@ impl CharacterBehavior for Data { // Done update.character = CharacterState::Wielding; // Make sure attack component is removed - data.updater.remove::(data.entity); + data.updater.remove::(data.entity); } }, _ => { // If it somehow ends up in an incorrect stage section update.character = CharacterState::Wielding; // Make sure attack component is removed - data.updater.remove::(data.entity); + data.updater.remove::(data.entity); }, } diff --git a/common/src/states/charged_ranged.rs b/common/src/states/charged_ranged.rs index 5759024143..9e6e16995b 100644 --- a/common/src/states/charged_ranged.rs +++ b/common/src/states/charged_ranged.rs @@ -1,7 +1,7 @@ use crate::{ combat::{ - Attack, AttackEffect, CombatBuff, CombatRequirement, Damage, DamageComponent, DamageSource, - EffectComponent, GroupTarget, Knockback, KnockbackDir, + Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement, Damage, + DamageSource, GroupTarget, Knockback, KnockbackDir, }, comp::{ projectile, Body, CharacterState, EnergyChange, EnergySource, Gravity, LightEmitter, @@ -103,22 +103,25 @@ impl CharacterBehavior for Data { let charge_frac = (self.timer.as_secs_f32() / self.static_data.charge_duration.as_secs_f32()) .min(1.0); - let knockback = self.static_data.initial_knockback - + charge_frac * self.static_data.scaled_knockback; - let knockback = AttackEffect::Knockback(Knockback { - strength: knockback, - direction: KnockbackDir::Away, - }); - let knockback = EffectComponent::new(Some(GroupTarget::OutOfGroup), knockback) - .with_requirement(CombatRequirement::AnyDamage); - let buff = AttackEffect::Buff(CombatBuff::default_physical()); - let damage = Damage { - source: DamageSource::Projectile, - value: self.static_data.initial_damage as f32 - + charge_frac * self.static_data.scaled_damage as f32, - }; - let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup)) - .with_effect(buff); + let knockback = AttackEffect::new( + Some(GroupTarget::OutOfGroup), + CombatEffect::Knockback(Knockback { + strength: self.static_data.initial_knockback + + charge_frac * self.static_data.scaled_knockback, + direction: KnockbackDir::Away, + }), + ) + .with_requirement(CombatRequirement::AnyDamage); + let buff = CombatEffect::Buff(CombatBuff::default_physical()); + let damage = AttackDamage::new( + Damage { + source: DamageSource::Projectile, + value: self.static_data.initial_damage as f32 + + charge_frac * self.static_data.scaled_damage as f32, + }, + Some(GroupTarget::OutOfGroup), + ) + .with_effect(buff); let attack = Attack::default() .with_damage(damage) .with_crit(0.5, 1.2) diff --git a/common/src/states/combo_melee.rs b/common/src/states/combo_melee.rs index 3a24c54151..caffd8d35a 100644 --- a/common/src/states/combo_melee.rs +++ b/common/src/states/combo_melee.rs @@ -1,8 +1,6 @@ use crate::{ - combat::{ - Attack, AttackEffect, CombatBuff, CombatRequirement, DamageComponent, EffectComponent, - }, - comp::{CharacterState, MeleeAttack, StateUpdate}, + combat::{Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement}, + comp::{CharacterState, Melee, StateUpdate}, states::{ behavior::{CharacterBehavior, JoinData}, utils::*, @@ -174,37 +172,40 @@ impl CharacterBehavior for Data { .scales_from_combo .min(self.combo / self.static_data.num_stages) * self.static_data.stage_data[stage_index].damage_increase; - let poise = self.static_data.stage_data[stage_index].base_poise_damage + self .static_data .scales_from_combo .min(self.combo / self.static_data.num_stages) * self.static_data.stage_data[stage_index].poise_damage_increase; - let poise = AttackEffect::Poise(poise as f32); - let poise = EffectComponent::new(Some(GroupTarget::OutOfGroup), poise) - .with_requirement(CombatRequirement::AnyDamage); - - let knockback = AttackEffect::Knockback(Knockback { - strength: self.static_data.stage_data[stage_index].knockback, - direction: KnockbackDir::Away, - }); - let knockback = EffectComponent::new(Some(GroupTarget::OutOfGroup), knockback) - .with_requirement(CombatRequirement::AnyDamage); + let poise = AttackEffect::new( + Some(GroupTarget::OutOfGroup), + CombatEffect::Poise(poise as f32), + ) + .with_requirement(CombatRequirement::AnyDamage); + let knockback = AttackEffect::new( + Some(GroupTarget::OutOfGroup), + CombatEffect::Knockback(Knockback { + strength: self.static_data.stage_data[stage_index].knockback, + direction: KnockbackDir::Away, + }), + ) + .with_requirement(CombatRequirement::AnyDamage); let energy = self.static_data.max_energy_gain.min( self.static_data.initial_energy_gain + self.combo * self.static_data.energy_increase, ); - let energy = AttackEffect::EnergyReward(energy); - let energy = EffectComponent::new(None, energy) + let energy = AttackEffect::new(None, CombatEffect::EnergyReward(energy)) .with_requirement(CombatRequirement::AnyDamage); - let buff = AttackEffect::Buff(CombatBuff::default_physical()); - let damage = Damage { - source: DamageSource::Melee, - value: damage as f32, - }; - let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup)) - .with_effect(buff); + let buff = CombatEffect::Buff(CombatBuff::default_physical()); + let damage = AttackDamage::new( + Damage { + source: DamageSource::Melee, + value: damage as f32, + }, + Some(GroupTarget::OutOfGroup), + ) + .with_effect(buff); let attack = Attack::default() .with_damage(damage) .with_crit(0.5, 1.3) @@ -212,7 +213,7 @@ impl CharacterBehavior for Data { .with_effect(poise) .with_effect(knockback); - data.updater.insert(data.entity, MeleeAttack { + data.updater.insert(data.entity, Melee { attack, range: self.static_data.stage_data[stage_index].range, max_angle: self.static_data.stage_data[stage_index].angle.to_radians(), @@ -290,14 +291,14 @@ impl CharacterBehavior for Data { // Done update.character = CharacterState::Wielding; // Make sure attack component is removed - data.updater.remove::(data.entity); + data.updater.remove::(data.entity); } }, _ => { // If it somehow ends up in an incorrect stage section update.character = CharacterState::Wielding; // Make sure attack component is removed - data.updater.remove::(data.entity); + data.updater.remove::(data.entity); }, } @@ -312,7 +313,7 @@ impl CharacterBehavior for Data { stage_section: self.stage_section, next_stage: self.next_stage, }); - data.updater.remove::(data.entity); + data.updater.remove::(data.entity); } } diff --git a/common/src/states/dash_melee.rs b/common/src/states/dash_melee.rs index 74191a1c42..c7875efe91 100644 --- a/common/src/states/dash_melee.rs +++ b/common/src/states/dash_melee.rs @@ -1,8 +1,6 @@ use crate::{ - combat::{ - Attack, AttackEffect, CombatBuff, CombatRequirement, DamageComponent, EffectComponent, - }, - comp::{CharacterState, EnergyChange, EnergySource, MeleeAttack, StateUpdate}, + combat::{Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement}, + comp::{CharacterState, EnergyChange, EnergySource, Melee, StateUpdate}, states::{ behavior::{CharacterBehavior, JoinData}, utils::*, @@ -132,36 +130,40 @@ impl CharacterBehavior for Data { if !self.exhausted { // Hit attempt (also checks if player is moving) if update.vel.0.distance_squared(Vec3::zero()) > 1.0 { - let poise = self.static_data.base_poise_damage as f32 - + charge_frac * self.static_data.scaled_poise_damage as f32; - let poise = AttackEffect::Poise(poise); - let poise = EffectComponent::new(Some(GroupTarget::OutOfGroup), poise) - .with_requirement(CombatRequirement::AnyDamage); - let knockback = self.static_data.base_knockback - + charge_frac * self.static_data.scaled_knockback; - let knockback = AttackEffect::Knockback(Knockback { - strength: knockback, - direction: KnockbackDir::Away, - }); - let knockback = - EffectComponent::new(Some(GroupTarget::OutOfGroup), knockback) - .with_requirement(CombatRequirement::AnyDamage); - let buff = AttackEffect::Buff(CombatBuff::default_physical()); - let damage = Damage { - source: DamageSource::Melee, - value: self.static_data.base_damage as f32 - + charge_frac * self.static_data.scaled_damage as f32, - }; - let damage = - DamageComponent::new(damage, Some(GroupTarget::OutOfGroup)) - .with_effect(buff); + let poise = AttackEffect::new( + Some(GroupTarget::OutOfGroup), + CombatEffect::Poise( + self.static_data.base_poise_damage as f32 + + charge_frac * self.static_data.scaled_poise_damage as f32, + ), + ) + .with_requirement(CombatRequirement::AnyDamage); + let knockback = AttackEffect::new( + Some(GroupTarget::OutOfGroup), + CombatEffect::Knockback(Knockback { + strength: self.static_data.base_knockback + + charge_frac * self.static_data.scaled_knockback, + direction: KnockbackDir::Away, + }), + ) + .with_requirement(CombatRequirement::AnyDamage); + let buff = CombatEffect::Buff(CombatBuff::default_physical()); + let damage = AttackDamage::new( + Damage { + source: DamageSource::Melee, + value: self.static_data.base_damage as f32 + + charge_frac * self.static_data.scaled_damage as f32, + }, + Some(GroupTarget::OutOfGroup), + ) + .with_effect(buff); let attack = Attack::default() .with_damage(damage) .with_crit(0.5, 1.3) .with_effect(poise) .with_effect(knockback); - data.updater.insert(data.entity, MeleeAttack { + data.updater.insert(data.entity, Melee { attack, range: self.static_data.range, max_angle: self.static_data.angle.to_radians(), @@ -246,14 +248,14 @@ impl CharacterBehavior for Data { // Done update.character = CharacterState::Wielding; // Make sure attack component is removed - data.updater.remove::(data.entity); + data.updater.remove::(data.entity); } }, _ => { // If it somehow ends up in an incorrect stage section update.character = CharacterState::Wielding; // Make sure attack component is removed - data.updater.remove::(data.entity); + data.updater.remove::(data.entity); }, } diff --git a/common/src/states/leap_melee.rs b/common/src/states/leap_melee.rs index 799bc37337..7c970282dd 100644 --- a/common/src/states/leap_melee.rs +++ b/common/src/states/leap_melee.rs @@ -1,8 +1,6 @@ use crate::{ - combat::{ - Attack, AttackEffect, CombatBuff, CombatRequirement, DamageComponent, EffectComponent, - }, - comp::{CharacterState, MeleeAttack, StateUpdate}, + combat::{Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement}, + comp::{CharacterState, Melee, StateUpdate}, states::{ behavior::{CharacterBehavior, JoinData}, utils::{StageSection, *}, @@ -150,22 +148,28 @@ impl CharacterBehavior for Data { }, StageSection::Recover => { if !self.exhausted { - let poise = AttackEffect::Poise(self.static_data.base_poise_damage as f32); - let poise = EffectComponent::new(Some(GroupTarget::OutOfGroup), poise) - .with_requirement(CombatRequirement::AnyDamage); - let knockback = AttackEffect::Knockback(Knockback { - strength: self.static_data.knockback, - direction: KnockbackDir::Away, - }); - let knockback = EffectComponent::new(Some(GroupTarget::OutOfGroup), knockback) - .with_requirement(CombatRequirement::AnyDamage); - let buff = AttackEffect::Buff(CombatBuff::default_physical()); - let damage = Damage { - source: DamageSource::Melee, - value: self.static_data.base_damage as f32, - }; - let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup)) - .with_effect(buff); + let poise = AttackEffect::new( + Some(GroupTarget::OutOfGroup), + CombatEffect::Poise(self.static_data.base_poise_damage as f32), + ) + .with_requirement(CombatRequirement::AnyDamage); + let knockback = AttackEffect::new( + Some(GroupTarget::OutOfGroup), + CombatEffect::Knockback(Knockback { + strength: self.static_data.knockback, + direction: KnockbackDir::Away, + }), + ) + .with_requirement(CombatRequirement::AnyDamage); + let buff = CombatEffect::Buff(CombatBuff::default_physical()); + let damage = AttackDamage::new( + Damage { + source: DamageSource::Melee, + value: self.static_data.base_damage as f32, + }, + Some(GroupTarget::OutOfGroup), + ) + .with_effect(buff); let attack = Attack::default() .with_damage(damage) .with_crit(0.5, 1.3) @@ -173,7 +177,7 @@ impl CharacterBehavior for Data { .with_effect(knockback); // Hit attempt, when animation plays - data.updater.insert(data.entity, MeleeAttack { + data.updater.insert(data.entity, Melee { attack, range: self.static_data.range, max_angle: self.static_data.max_angle.to_radians(), @@ -202,14 +206,14 @@ impl CharacterBehavior for Data { // Done update.character = CharacterState::Wielding; // Make sure attack component is removed - data.updater.remove::(data.entity); + data.updater.remove::(data.entity); } }, _ => { // If it somehow ends up in an incorrect stage section update.character = CharacterState::Wielding; // Make sure attack component is removed - data.updater.remove::(data.entity); + data.updater.remove::(data.entity); }, } diff --git a/common/src/states/shockwave.rs b/common/src/states/shockwave.rs index 2cb3ca6071..cb73d6aafa 100644 --- a/common/src/states/shockwave.rs +++ b/common/src/states/shockwave.rs @@ -1,7 +1,7 @@ use crate::{ combat::{ - Attack, AttackEffect, CombatRequirement, Damage, DamageComponent, DamageSource, - EffectComponent, GroupTarget, Knockback, + Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement, Damage, DamageSource, + GroupTarget, Knockback, }, comp::{shockwave, CharacterState, StateUpdate}, event::ServerEvent, @@ -83,17 +83,23 @@ impl CharacterBehavior for Data { }); } else { // Attack - let poise = AttackEffect::Poise(self.static_data.poise_damage as f32); - let poise = EffectComponent::new(Some(GroupTarget::OutOfGroup), poise) - .with_requirement(CombatRequirement::AnyDamage); - let knockback = AttackEffect::Knockback(self.static_data.knockback); - let knockback = EffectComponent::new(Some(GroupTarget::OutOfGroup), knockback) - .with_requirement(CombatRequirement::AnyDamage); - let damage = Damage { - source: DamageSource::Shockwave, - value: self.static_data.damage as f32, - }; - let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup)); + let poise = AttackEffect::new( + Some(GroupTarget::OutOfGroup), + CombatEffect::Poise(self.static_data.poise_damage as f32), + ) + .with_requirement(CombatRequirement::AnyDamage); + let knockback = AttackEffect::new( + Some(GroupTarget::OutOfGroup), + CombatEffect::Knockback(self.static_data.knockback), + ) + .with_requirement(CombatRequirement::AnyDamage); + let damage = AttackDamage::new( + Damage { + source: DamageSource::Shockwave, + value: self.static_data.damage as f32, + }, + Some(GroupTarget::OutOfGroup), + ); let attack = Attack::default() .with_damage(damage) .with_effect(poise) diff --git a/common/src/states/spin_melee.rs b/common/src/states/spin_melee.rs index ca0b1f6220..75ad25649c 100644 --- a/common/src/states/spin_melee.rs +++ b/common/src/states/spin_melee.rs @@ -1,8 +1,6 @@ use crate::{ - combat::{ - Attack, AttackEffect, CombatBuff, CombatRequirement, DamageComponent, EffectComponent, - }, - comp::{CharacterState, EnergyChange, EnergySource, MeleeAttack, StateUpdate}, + combat::{Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement}, + comp::{CharacterState, EnergyChange, EnergySource, Melee, StateUpdate}, consts::GRAVITY, states::{ behavior::{CharacterBehavior, JoinData}, @@ -115,22 +113,28 @@ impl CharacterBehavior for Data { ..*self }); - let poise = AttackEffect::Poise(self.static_data.base_poise_damage as f32); - let poise = EffectComponent::new(Some(GroupTarget::OutOfGroup), poise) - .with_requirement(CombatRequirement::AnyDamage); - let knockback = AttackEffect::Knockback(Knockback { - strength: self.static_data.knockback, - direction: KnockbackDir::Away, - }); - let knockback = EffectComponent::new(Some(GroupTarget::OutOfGroup), knockback) - .with_requirement(CombatRequirement::AnyDamage); - let buff = AttackEffect::Buff(CombatBuff::default_physical()); - let damage = Damage { - source: DamageSource::Melee, - value: self.static_data.base_damage as f32, - }; - let damage = DamageComponent::new(damage, Some(GroupTarget::OutOfGroup)) - .with_effect(buff); + let poise = AttackEffect::new( + Some(GroupTarget::OutOfGroup), + CombatEffect::Poise(self.static_data.base_poise_damage as f32), + ) + .with_requirement(CombatRequirement::AnyDamage); + let knockback = AttackEffect::new( + Some(GroupTarget::OutOfGroup), + CombatEffect::Knockback(Knockback { + strength: self.static_data.knockback, + direction: KnockbackDir::Away, + }), + ) + .with_requirement(CombatRequirement::AnyDamage); + let buff = CombatEffect::Buff(CombatBuff::default_physical()); + let damage = AttackDamage::new( + Damage { + source: DamageSource::Melee, + value: self.static_data.base_damage as f32, + }, + Some(GroupTarget::OutOfGroup), + ) + .with_effect(buff); let attack = Attack::default() .with_damage(damage) .with_crit(0.5, 1.3) @@ -138,7 +142,7 @@ impl CharacterBehavior for Data { .with_effect(knockback); // Hit attempt - data.updater.insert(data.entity, MeleeAttack { + data.updater.insert(data.entity, Melee { attack, range: self.static_data.range, max_angle: 180_f32.to_radians(), @@ -213,14 +217,14 @@ impl CharacterBehavior for Data { // Done update.character = CharacterState::Wielding; // Make sure attack component is removed - data.updater.remove::(data.entity); + data.updater.remove::(data.entity); } }, _ => { // If it somehow ends up in an incorrect stage section update.character = CharacterState::Wielding; // Make sure attack component is removed - data.updater.remove::(data.entity); + data.updater.remove::(data.entity); }, } diff --git a/common/sys/src/beam.rs b/common/sys/src/beam.rs index 5ebb3ccefa..aa8ec3d1ce 100644 --- a/common/sys/src/beam.rs +++ b/common/sys/src/beam.rs @@ -1,4 +1,5 @@ use common::{ + combat::AttackerInfo, comp::{ group, Beam, BeamSegment, Body, Energy, Health, HealthSource, Inventory, Last, Ori, Pos, Scale, @@ -168,25 +169,27 @@ impl<'a> System<'a> for Sys { continue; } - let server_events = beam_segment.properties.attack.apply_attack( + let attacker_info = + beam_owner + .zip(beam_segment.owner) + .map(|(entity, uid)| AttackerInfo { + entity, + uid, + energy: energies.get(entity), + }); + + beam_segment.properties.attack.apply_attack( target_group, - beam_owner, + attacker_info, b, inventory_b_maybe, - beam_segment.owner, - beam_owner.and_then(|e| energies.get(e)), ori.0, false, 1.0, + |e| server_emitter.emit(e), ); - if !server_events.is_empty() { - hit_entities.push(*uid_b); - } - - for event in server_events { - server_emitter.emit(event); - } + hit_entities.push(*uid_b); } } } diff --git a/common/sys/src/character_behavior.rs b/common/sys/src/character_behavior.rs index 8802ed7dba..b927d3483f 100644 --- a/common/sys/src/character_behavior.rs +++ b/common/sys/src/character_behavior.rs @@ -3,8 +3,8 @@ use specs::{Entities, Join, LazyUpdate, Read, ReadExpect, ReadStorage, System, W use common::{ comp::{ inventory::slot::{EquipSlot, Slot}, - Beam, Body, CharacterState, Controller, Energy, Health, Inventory, MeleeAttack, Mounting, - Ori, PhysicsState, Poise, PoiseState, Pos, StateUpdate, Stats, Vel, + Beam, Body, CharacterState, Controller, Energy, Health, Inventory, Melee, Mounting, Ori, + PhysicsState, Poise, PoiseState, Pos, StateUpdate, Stats, Vel, }, event::{EventBus, LocalEvent, ServerEvent}, metrics::SysMetrics, @@ -69,7 +69,7 @@ impl<'a> System<'a> for Sys { WriteStorage<'a, Poise>, ReadStorage<'a, Body>, ReadStorage<'a, PhysicsState>, - ReadStorage<'a, MeleeAttack>, + ReadStorage<'a, Melee>, ReadStorage<'a, Beam>, ReadStorage<'a, Uid>, ReadStorage<'a, Mounting>, diff --git a/common/sys/src/melee.rs b/common/sys/src/melee.rs index b373ba5b70..5c5253362e 100644 --- a/common/sys/src/melee.rs +++ b/common/sys/src/melee.rs @@ -1,5 +1,6 @@ use common::{ - comp::{group, Body, CharacterState, Energy, Health, Inventory, MeleeAttack, Ori, Pos, Scale}, + combat::AttackerInfo, + comp::{group, Body, CharacterState, Energy, Health, Inventory, Melee, Ori, Pos, Scale}, event::{EventBus, LocalEvent, ServerEvent}, metrics::SysMetrics, span, @@ -29,7 +30,7 @@ impl<'a> System<'a> for Sys { ReadStorage<'a, Energy>, ReadStorage<'a, Inventory>, ReadStorage<'a, group::Group>, - WriteStorage<'a, MeleeAttack>, + WriteStorage<'a, Melee>, ReadStorage<'a, CharacterState>, ); @@ -129,25 +130,24 @@ impl<'a> System<'a> for Sys { let dir = Dir::new((pos_b.0 - pos.0).try_normalized().unwrap_or(*ori.0)); - let server_events = attack.attack.apply_attack( + let attacker_info = Some(AttackerInfo { + entity, + uid: *uid, + energy: energies.get(entity), + }); + + attack.attack.apply_attack( target_group, - Some(entity), + attacker_info, b, inventory_b_maybe, - Some(*uid), - energies.get(entity), dir, is_dodge, 1.0, + |e| server_emitter.emit(e), ); - if !server_events.is_empty() { - attack.hit_count += 1; - } - - for event in server_events { - server_emitter.emit(event); - } + attack.hit_count += 1; } } } diff --git a/common/sys/src/projectile.rs b/common/sys/src/projectile.rs index c80986deb2..67ff616534 100644 --- a/common/sys/src/projectile.rs +++ b/common/sys/src/projectile.rs @@ -1,4 +1,5 @@ use common::{ + combat::AttackerInfo, comp::{ projectile, Energy, Group, HealthSource, Inventory, Ori, PhysicsState, Pos, Projectile, Vel, }, @@ -109,50 +110,28 @@ impl<'a> System<'a> for Sys { let owner_entity = projectile .owner .and_then(|u| uid_allocator.retrieve_entity_internal(u.into())); - let server_events = attack.apply_attack( + + let attacker_info = + owner_entity.zip(projectile.owner).map(|(entity, uid)| { + AttackerInfo { + entity, + uid, + energy: energies.get(entity), + } + }); + + attack.apply_attack( target_group, - owner_entity, + attacker_info, target_entity, inventories.get(target_entity), - projectile.owner, - owner_entity.and_then(|e| energies.get(e)), ori.0, false, 1.0, + |e| server_emitter.emit(e), ); - - for event in server_events { - server_emitter.emit(event); - } } }, - // projectile::Effect::Knockback(knockback) => { - // if let Some(other_entity) = - // uid_allocator.retrieve_entity_internal(other.into()) - // { - // let impulse = knockback.calculate_impulse(ori.0); - // if !impulse.is_approx_zero() { - // server_emitter.emit(ServerEvent::Knockback { - // entity: other_entity, - // impulse, - // }); - // } - // } - // }, - // projectile::Effect::RewardEnergy(energy) => { - // if let Some(entity_owner) = projectile - // .owner - // .and_then(|u| uid_allocator.retrieve_entity_internal(u.into())) - // { - // server_emitter.emit(ServerEvent::EnergyChange { - // entity: entity_owner, - // change: EnergyChange { - // amount: energy as i32, - // source: EnergySource::HitEnemy, - // }, - // }); - // } - // }, projectile::Effect::Explode(e) => { server_emitter.emit(ServerEvent::Explosion { pos: pos.0, @@ -175,26 +154,6 @@ impl<'a> System<'a> for Sys { } } }, - // TODO: Change to effect after !1472 merges - // projectile::Effect::Buff { buff, chance } => { - // if let Some(entity) = - // uid_allocator.retrieve_entity_internal(other.into()) - // { - // if chance.map_or(true, |c| thread_rng().gen::() < c) { - // let source = if let Some(owner) = projectile.owner { - // BuffSource::Character { by: owner } - // } else { - // BuffSource::Unknown - // }; - // let buff = - // Buff::new(buff.kind, buff.data, buff.cat_ids, source); - // server_emitter.emit(ServerEvent::Buff { - // entity, - // buff_change: BuffChange::Add(buff), - // }); - // } - // } - // }, _ => {}, } } diff --git a/common/sys/src/shockwave.rs b/common/sys/src/shockwave.rs index f40be3f9d2..e5547a7761 100644 --- a/common/sys/src/shockwave.rs +++ b/common/sys/src/shockwave.rs @@ -1,4 +1,5 @@ use common::{ + combat::AttackerInfo, comp::{ group, Body, Energy, Health, HealthSource, Inventory, Last, Ori, PhysicsState, Pos, Scale, Shockwave, ShockwaveHitEntities, @@ -195,25 +196,27 @@ impl<'a> System<'a> for Sys { if hit { let dir = Dir::new((pos_b.0 - pos.0).try_normalized().unwrap_or(*ori.0)); - let server_events = shockwave.properties.attack.apply_attack( + let attacker_info = + shockwave_owner + .zip(shockwave.owner) + .map(|(entity, uid)| AttackerInfo { + entity, + uid, + energy: energies.get(entity), + }); + + shockwave.properties.attack.apply_attack( target_group, - shockwave_owner, + attacker_info, b, inventories.get(b), - shockwave.owner, - shockwave_owner.and_then(|e| energies.get(e)), dir, false, 1.0, + |e| server_emitter.emit(e), ); - if !server_events.is_empty() { - shockwave_hit_list.hit_entities.push(*uid_b); - } - - for event in server_events { - server_emitter.emit(event); - } + shockwave_hit_list.hit_entities.push(*uid_b); } } } diff --git a/common/sys/src/state.rs b/common/sys/src/state.rs index 9dea038ee0..136c4e7102 100644 --- a/common/sys/src/state.rs +++ b/common/sys/src/state.rs @@ -163,7 +163,7 @@ impl State { ecs.register::(); ecs.register::(); ecs.register::(); - ecs.register::(); + ecs.register::(); ecs.register::(); ecs.register::(); ecs.register::(); diff --git a/server/src/events/entity_creation.rs b/server/src/events/entity_creation.rs index 052c5be8e5..cdae5475eb 100644 --- a/server/src/events/entity_creation.rs +++ b/server/src/events/entity_creation.rs @@ -174,7 +174,7 @@ pub fn handle_beam(server: &mut Server, properties: beam::Properties, pos: Pos, heal: properties .attack .effects() - .any(|e| matches!(e.effect(), combat::AttackEffect::Heal(h) if *h > 0.0)), + .any(|e| matches!(e.effect(), combat::CombatEffect::Heal(h) if *h > 0.0)), }); state.create_beam(properties, pos, ori).build(); } diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index 3041ae58ea..eafae8edca 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -510,7 +510,8 @@ pub fn handle_land_on_ground(server: &Server, entity: EcsEntity, vel: Vec3) source: DamageSource::Falling, value: falldmg, }; - let change = damage.modify_damage(inventories.get(entity), None, false, 0.0, 1.0); + let change = + damage.calculate_health_change(inventories.get(entity), None, false, 0.0, 1.0); health.change_by(change); } // Handle poise change @@ -578,7 +579,7 @@ pub fn handle_explosion( // Add an outcome // Uses radius as outcome power, makes negative if explosion has healing effect let outcome_power = explosion.radius - * if explosion.effects.iter().any(|e| matches!(e, RadiusEffect::Attack(a) if a.effects().any(|e| matches!(e.effect(), combat::AttackEffect::Heal(h) if *h > 0.0)))) { + * if explosion.effects.iter().any(|e| matches!(e, RadiusEffect::Attack(a) if a.effects().any(|e| matches!(e.effect(), combat::CombatEffect::Heal(h) if *h > 0.0)))) { -1.0 } else { 1.0 @@ -708,23 +709,27 @@ pub fn handle_explosion( .unwrap_or_else(Vec3::unit_z), ); - let server_events = attack.apply_attack( - target_group, - owner_entity, - entity_b, - inventory_b_maybe, - owner, - owner_entity.and_then(|e| energies.get(e)), - dir, - false, - strength, - ); + let attacker_info = + owner_entity + .zip(owner) + .map(|(entity, uid)| combat::AttackerInfo { + entity, + uid, + energy: energies.get(entity), + }); let server_eventbus = ecs.read_resource::>(); - for event in server_events { - server_eventbus.emit_now(event); - } + attack.apply_attack( + target_group, + attacker_info, + entity_b, + inventory_b_maybe, + dir, + false, + strength, + |e| server_eventbus.emit_now(e), + ); } } }, diff --git a/server/src/state_ext.rs b/server/src/state_ext.rs index af04924032..430d0ac0fd 100644 --- a/server/src/state_ext.rs +++ b/server/src/state_ext.rs @@ -90,7 +90,13 @@ impl StateExt for State { }, Effect::Damage(damage) => { let inventories = self.ecs().read_storage::(); - let change = damage.modify_damage(inventories.get(entity), source, false, 0.0, 1.0); + let change = damage.calculate_health_change( + inventories.get(entity), + source, + false, + 0.0, + 1.0, + ); self.ecs() .write_storage::() .get_mut(entity)