From 221d4c8cdc84bcc9ee5a40d69aeb0ff721d13fa3 Mon Sep 17 00:00:00 2001 From: jiminycrick Date: Wed, 9 Dec 2020 16:32:24 -0800 Subject: [PATCH] Add knockback to poise --- common/src/comp/body.rs | 4 +-- common/src/comp/character_state.rs | 11 ++++--- common/src/comp/poise.rs | 3 ++ common/src/event.rs | 1 + common/src/states/combo_melee.rs | 1 - common/sys/src/beam.rs | 3 ++ common/sys/src/melee.rs | 18 ++++++----- common/sys/src/projectile.rs | 1 + common/sys/src/shockwave.rs | 9 +++--- common/sys/src/stats.rs | 38 ++++++++++++++++++++---- server/src/events/entity_manipulation.rs | 36 +++++++++++++--------- server/src/events/mod.rs | 6 +++- server/src/sys/object.rs | 2 +- 13 files changed, 94 insertions(+), 39 deletions(-) diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index 67bd47876e..81e5ba2ee0 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -612,8 +612,8 @@ impl Body { pub fn base_poise_dmg(&self) -> u32 { match self { - Body::Humanoid(_) => 100, - _ => 50, + Body::Humanoid(_) => 5, + _ => 10, } } diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs index 4b8c528bb5..125ca1e4e0 100644 --- a/common/src/comp/character_state.rs +++ b/common/src/comp/character_state.rs @@ -108,10 +108,6 @@ impl CharacterState { matches!(self, CharacterState::Sneak | CharacterState::Roll(_)) } - pub fn is_stunned(&self) -> bool { - matches!(self, CharacterState::Stunned { .. } | CharacterState::Staggered { .. }) - } - pub fn is_attack(&self) -> bool { matches!( self, @@ -155,6 +151,13 @@ impl CharacterState { matches!(self, CharacterState::Roll(d) if d.static_data.immune_melee) } + pub fn is_stunned(&self) -> bool { + matches!( + self, + CharacterState::Stunned(_) | CharacterState::Staggered(_) + ) + } + /// Compares for shallow equality (does not check internal struct equality) pub fn same_variant(&self, other: &Self) -> bool { // Check if state is the same without looking at the inner data diff --git a/common/src/comp/poise.rs b/common/src/comp/poise.rs index aaaa42f6c6..8f32734932 100644 --- a/common/src/comp/poise.rs +++ b/common/src/comp/poise.rs @@ -83,6 +83,7 @@ pub enum PoiseSource { Shockwave, Falling, Revive, + Regen, Other, } @@ -95,6 +96,7 @@ pub struct Poise { pub is_stunned: bool, pub is_dazed: bool, pub is_knockeddown: bool, + pub regen_rate: f32, } impl Default for Poise { @@ -107,6 +109,7 @@ impl Default for Poise { is_stunned: false, is_dazed: false, is_knockeddown: false, + regen_rate: 0.0, } } } diff --git a/common/src/event.rs b/common/src/event.rs index 7bd9590d35..d9794c803b 100644 --- a/common/src/event.rs +++ b/common/src/event.rs @@ -39,6 +39,7 @@ pub enum ServerEvent { PoiseChange { entity: EcsEntity, change: comp::PoiseChange, + kb_dir: Vec3, }, Delete(EcsEntity), Destroy { diff --git a/common/src/states/combo_melee.rs b/common/src/states/combo_melee.rs index 4b95cf475c..2411702b82 100644 --- a/common/src/states/combo_melee.rs +++ b/common/src/states/combo_melee.rs @@ -170,7 +170,6 @@ impl CharacterBehavior for Data { .min(self.combo / self.static_data.num_stages) * self.static_data.stage_data[stage_index].damage_increase; let poise_damage = self.static_data.stage_data[stage_index].base_poise_damage; - println!("Combo melee poise damage: {:?}", poise_damage); data.updater.insert(data.entity, Attacking { effects: vec![( Some(GroupTarget::OutOfGroup), diff --git a/common/sys/src/beam.rs b/common/sys/src/beam.rs index c0c81bf5ff..feb3d734ca 100644 --- a/common/sys/src/beam.rs +++ b/common/sys/src/beam.rs @@ -6,6 +6,7 @@ use common::{ event::{EventBus, ServerEvent}, resources::{DeltaTime, Time}, uid::{Uid, UidAllocator}, + util::Dir, GroupTarget, }; use specs::{saveload::MarkerAllocator, Entities, Join, Read, ReadStorage, System, WriteStorage}; @@ -170,6 +171,7 @@ impl<'a> System<'a> for Sys { let poise_change = poise_damage .modify_poise_damage(inventories.get(b), beam_segment.owner); + let kb_dir = Dir::new((pos_b.0 - pos.0).try_normalized().unwrap_or(*ori.0)); match target { Some(GroupTarget::OutOfGroup) => { server_emitter.emit(ServerEvent::Damage { entity: b, change }); @@ -188,6 +190,7 @@ impl<'a> System<'a> for Sys { server_emitter.emit(ServerEvent::PoiseChange { entity, change: poise_change, + kb_dir: *kb_dir, }); server_emitter.emit(ServerEvent::EnergyChange { entity, diff --git a/common/sys/src/melee.rs b/common/sys/src/melee.rs index 50ad8423d0..7d4cee0162 100644 --- a/common/sys/src/melee.rs +++ b/common/sys/src/melee.rs @@ -101,6 +101,9 @@ impl<'a> System<'a> for Sys { // Check if entity is dodging let is_dodge = char_state_b_maybe.map_or(false, |c_s| c_s.is_melee_dodge()); + // Check if entity is stunned + let is_stunned = char_state_b_maybe.map_or(false, |c_s| c_s.is_stunned()); + // Check if it is a hit if entity != b && !health_b.is_dead @@ -123,7 +126,8 @@ impl<'a> System<'a> for Sys { for (target, damage, poise_change) in attack.effects.iter() { if let Some(target) = target { if *target != target_group - || (!matches!(target, GroupTarget::InGroup) && is_dodge) + || (!matches!(target, GroupTarget::InGroup) + && (is_dodge || is_stunned)) { continue; } @@ -132,13 +136,7 @@ impl<'a> System<'a> for Sys { let change = damage.modify_damage(inventories.get(b), Some(*uid)); //let poise_change = // poise_change.modify_poise_damage(loadouts.get(b), Some(*uid)); - println!("poise_change in melee: {:?}", poise_change); - server_emitter.emit(ServerEvent::Damage { entity: b, change }); - server_emitter.emit(ServerEvent::PoiseChange { - entity: b, - change: *poise_change, - }); // Apply bleeding buff on melee hits with 10% chance // TODO: Don't have buff uniformly applied on all melee attacks if change.amount < 0 && thread_rng().gen::() < 0.1 { @@ -162,6 +160,12 @@ impl<'a> System<'a> for Sys { server_emitter.emit(ServerEvent::Knockback { entity: b, impulse }); } + server_emitter.emit(ServerEvent::PoiseChange { + entity: b, + change: *poise_change, + kb_dir: *kb_dir, + }); + attack.hit_count += 1; } } diff --git a/common/sys/src/projectile.rs b/common/sys/src/projectile.rs index c1a5e32c3d..3c58a18369 100644 --- a/common/sys/src/projectile.rs +++ b/common/sys/src/projectile.rs @@ -128,6 +128,7 @@ impl<'a> System<'a> for Sys { server_emitter.emit(ServerEvent::PoiseChange { entity: other_entity, change: poise_change, + kb_dir: *ori.0, }); } }, diff --git a/common/sys/src/shockwave.rs b/common/sys/src/shockwave.rs index fae49b339e..56f5f91159 100644 --- a/common/sys/src/shockwave.rs +++ b/common/sys/src/shockwave.rs @@ -204,10 +204,6 @@ impl<'a> System<'a> for Sys { poise_damage.modify_poise_damage(inventories.get(b), Some(owner_uid)); server_emitter.emit(ServerEvent::Damage { entity: b, change }); - server_emitter.emit(ServerEvent::PoiseChange { - entity: b, - change: poise_change, - }); shockwave_hit_list.hit_entities.push(*uid_b); let kb_dir = Dir::new((pos_b.0 - pos.0).try_normalized().unwrap_or(*ori.0)); @@ -215,6 +211,11 @@ impl<'a> System<'a> for Sys { if !impulse.is_approx_zero() { server_emitter.emit(ServerEvent::Knockback { entity: b, impulse }); } + server_emitter.emit(ServerEvent::PoiseChange { + entity: b, + change: poise_change, + kb_dir: *kb_dir, + }); } } } diff --git a/common/sys/src/stats.rs b/common/sys/src/stats.rs index 7cbe221915..7298c5b509 100644 --- a/common/sys/src/stats.rs +++ b/common/sys/src/stats.rs @@ -1,7 +1,8 @@ use common::{ comp::{ skills::{GeneralSkill, Skill}, - Body, CharacterState, Energy, EnergyChange, EnergySource, Health, Pos, Stats, + Body, CharacterState, Energy, EnergyChange, EnergySource, Health, Poise, PoiseChange, + PoiseSource, Pos, Stats, }, event::{EventBus, ServerEvent}, metrics::SysMetrics, @@ -14,6 +15,7 @@ use hashbrown::HashSet; use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, Write, WriteStorage}; const ENERGY_REGEN_ACCEL: f32 = 10.0; +//const POISE_REGEN_ACCEL: f32 = 5.0; /// This system kills players, levels them up, and regenerates energy. pub struct Sys; @@ -27,6 +29,7 @@ impl<'a> System<'a> for Sys { ReadStorage<'a, CharacterState>, WriteStorage<'a, Stats>, WriteStorage<'a, Health>, + WriteStorage<'a, Poise>, WriteStorage<'a, Energy>, ReadStorage<'a, Uid>, ReadStorage<'a, Pos>, @@ -44,6 +47,7 @@ impl<'a> System<'a> for Sys { character_states, mut stats, mut healths, + mut poises, mut energies, uids, positions, @@ -147,9 +151,13 @@ impl<'a> System<'a> for Sys { } } - // Update energies - for (character_state, mut energy) in - (&character_states, &mut energies.restrict_mut()).join() + // Update energies and poises + for (character_state, mut energy, mut poise) in ( + &character_states, + &mut energies.restrict_mut(), + &mut poises.restrict_mut(), + ) + .join() { match character_state { // Accelerate recharging energy. @@ -179,6 +187,23 @@ impl<'a> System<'a> for Sys { energy.regen_rate = (energy.regen_rate + ENERGY_REGEN_ACCEL * dt.0).min(100.0); } + + //let res_poise = { + // let poise = poise.get_unchecked(); + // poise.current() < poise.maximum() + //}; + + //if res_poise { + // let mut poise = poise.get_mut_unchecked(); + // poise.change_by(PoiseChange { + // amount: (poise.regen_rate * dt.0 + // + POISE_REGEN_ACCEL * dt.0.powi(2) / 2.0) + // as i32, + // source: PoiseSource::Regen, + // }); + // poise.regen_rate = (poise.regen_rate + + // POISE_REGEN_ACCEL * dt.0).min(100.0); + //} }, // Ability and glider use does not regen and sets the rate back to zero. CharacterState::Glide { .. } @@ -217,7 +242,10 @@ impl<'a> System<'a> for Sys { CharacterState::Roll { .. } | CharacterState::Climb { .. } | CharacterState::Stunned { .. } - | CharacterState::Staggered { .. } => {}, + | CharacterState::Staggered { .. } => { + let poise = poise.get_unchecked(); + println!("Poise: {:?}", poise.current()); + }, } } sys_metrics.stats_ns.store( diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index f7ef50c0bb..1aa3040e0f 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -36,7 +36,12 @@ use std::time::Duration; use tracing::error; use vek::Vec3; -pub fn handle_poise(server: &Server, entity: EcsEntity, change: PoiseChange) { +pub fn handle_poise( + server: &Server, + entity: EcsEntity, + change: PoiseChange, + knockback_dir: Vec3, +) { let ecs = &server.state.ecs(); if let Some(poise) = ecs.write_storage::().get_mut(entity) { poise.change_by(change); @@ -57,7 +62,7 @@ pub fn handle_poise(server: &Server, entity: EcsEntity, change: PoiseChange) { static_data: common::states::stunned::StaticData { buildup_duration: Duration::from_millis(250), recover_duration: Duration::from_millis(250), - knockback: Knockback::Away(0.0), + knockback: Knockback::Away(20.0), }, timer: Duration::default(), stage_section: common::states::utils::StageSection::Buildup, @@ -71,47 +76,50 @@ pub fn handle_poise(server: &Server, entity: EcsEntity, change: PoiseChange) { entity, comp::CharacterState::Stunned(common::states::stunned::Data { static_data: common::states::stunned::StaticData { - buildup_duration: Duration::from_millis(250), - recover_duration: Duration::from_millis(250), - knockback: Knockback::Away(0.0), + buildup_duration: Duration::from_millis(500), + recover_duration: Duration::from_millis(500), + knockback: Knockback::Away(40.0), }, timer: Duration::default(), stage_section: common::states::utils::StageSection::Buildup, was_wielded, }), ); + handle_knockback(server, entity, 50.0 * knockback_dir); }, PoiseState::Dazed => { poise.reset(); let _ = ecs.write_storage::().insert( entity, - comp::CharacterState::Stunned(common::states::stunned::Data { - static_data: common::states::stunned::StaticData { - buildup_duration: Duration::from_millis(250), - recover_duration: Duration::from_millis(250), - knockback: Knockback::Away(0.0), + comp::CharacterState::Staggered(common::states::staggered::Data { + static_data: common::states::staggered::StaticData { + buildup_duration: Duration::from_millis(1000), + recover_duration: Duration::from_millis(1000), + knockback: Knockback::Away(50.0), }, timer: Duration::default(), stage_section: common::states::utils::StageSection::Buildup, was_wielded, }), ); + handle_knockback(server, entity, 50.0 * knockback_dir); }, PoiseState::KnockedDown => { poise.reset(); let _ = ecs.write_storage::().insert( entity, - comp::CharacterState::Stunned(common::states::stunned::Data { - static_data: common::states::stunned::StaticData { - buildup_duration: Duration::from_millis(250), + comp::CharacterState::Staggered(common::states::staggered::Data { + static_data: common::states::staggered::StaticData { + buildup_duration: Duration::from_millis(5000), recover_duration: Duration::from_millis(250), - knockback: Knockback::Away(0.0), + knockback: Knockback::Away(200.0), }, timer: Duration::default(), stage_section: common::states::utils::StageSection::Buildup, was_wielded, }), ); + handle_knockback(server, entity, 100.0 * knockback_dir); }, } } diff --git a/server/src/events/mod.rs b/server/src/events/mod.rs index f939c8bd0e..5c98f18a25 100644 --- a/server/src/events/mod.rs +++ b/server/src/events/mod.rs @@ -83,7 +83,11 @@ impl Server { handle_knockback(&self, entity, impulse) }, ServerEvent::Damage { entity, change } => handle_damage(&self, entity, change), - ServerEvent::PoiseChange { entity, change } => handle_poise(&self, entity, change), + ServerEvent::PoiseChange { + entity, + change, + kb_dir, + } => handle_poise(&self, entity, change, kb_dir), ServerEvent::Delete(entity) => handle_delete(self, entity), ServerEvent::Destroy { entity, cause } => handle_destroy(self, entity, cause), ServerEvent::InventoryManip(entity, manip) => handle_inventory(self, entity, manip), diff --git a/server/src/sys/object.rs b/server/src/sys/object.rs index 5220f61044..7812aad09b 100644 --- a/server/src/sys/object.rs +++ b/server/src/sys/object.rs @@ -55,7 +55,7 @@ impl<'a> System<'a> for Sys { value: 500.0, }), Effect::Poise(PoiseChange { - amount: -60, + amount: -80, source: PoiseSource::Explosion, }), ]),