From 03b5cac2f947bf918454e231c2ad09126093dd54 Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 31 Aug 2020 18:21:17 -0500 Subject: [PATCH] Beams now have spherical hit detection. --- common/src/comp/character_state.rs | 2 + common/src/states/basic_beam.rs | 1 + common/src/states/basic_melee.rs | 1 + common/src/states/dash_melee.rs | 27 +++++++++++++ common/src/states/leap_melee.rs | 1 + common/src/states/triple_strike.rs | 1 + common/src/sys/combat.rs | 62 +++++++++++++++++++++++++----- 7 files changed, 86 insertions(+), 9 deletions(-) diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs index 70d24d24d4..d24f137847 100644 --- a/common/src/comp/character_state.rs +++ b/common/src/comp/character_state.rs @@ -8,6 +8,7 @@ use serde::{Deserialize, Serialize}; use specs::{Component, FlaggedStorage, VecStorage}; use specs_idvs::IdvStorage; use std::collections::VecDeque; +use vek::Vec3; /// Data returned from character behavior fn's to Character Behavior System. pub struct StateUpdate { @@ -151,6 +152,7 @@ pub struct Attacking { pub knockback: f32, pub is_melee: bool, pub lifesteal_eff: f32, + pub look_dir: Option>, } impl Component for Attacking { diff --git a/common/src/states/basic_beam.rs b/common/src/states/basic_beam.rs index 8b2ade60a4..c22e1220fa 100644 --- a/common/src/states/basic_beam.rs +++ b/common/src/states/basic_beam.rs @@ -76,6 +76,7 @@ impl CharacterBehavior for Data { knockback: 0.0, is_melee: false, lifesteal_eff: self.lifesteal_eff, + look_dir: self.particle_ori, }); update.character = CharacterState::BasicBeam(Data { diff --git a/common/src/states/basic_melee.rs b/common/src/states/basic_melee.rs index 1520b824f4..6527113814 100644 --- a/common/src/states/basic_melee.rs +++ b/common/src/states/basic_melee.rs @@ -65,6 +65,7 @@ impl CharacterBehavior for Data { knockback: self.knockback, is_melee: true, lifesteal_eff: 0.0, + look_dir: None, }); update.character = CharacterState::BasicMelee(Data { diff --git a/common/src/states/dash_melee.rs b/common/src/states/dash_melee.rs index ce120d68e2..ba9e04a623 100644 --- a/common/src/states/dash_melee.rs +++ b/common/src/states/dash_melee.rs @@ -130,6 +130,7 @@ impl CharacterBehavior for Data { }); } +<<<<<<< HEAD // This logic basically just decides if a charge should end, and prevents the // character state spamming attacks while checking if it has hit something if !self.exhausted { @@ -190,6 +191,32 @@ impl CharacterBehavior for Data { exhausted: self.exhausted, }) } +======= + update.character = CharacterState::DashMelee(Data { + buildup_duration: self + .buildup_duration + .checked_sub(Duration::from_secs_f32(data.dt.0)) + .unwrap_or_default(), + recover_duration: self.recover_duration, + base_damage: self.base_damage, + exhausted: false, + initialize: false, + }); + } else if !self.exhausted { + // Hit attempt + data.updater.insert(data.entity, Attacking { + base_damage: self.base_damage, + base_heal: 0, + range: 3.5, + max_angle: 45_f32.to_radians(), + applied: false, + hit_count: 0, + knockback: 0.0, + is_melee: true, + lifesteal_eff: 0.0, + look_dir: None, + }); +>>>>>>> 8e6d0821c... Beams now have spherical hit detection. // Consumes energy if there's enough left and charge has not stopped update.energy.change_by( diff --git a/common/src/states/leap_melee.rs b/common/src/states/leap_melee.rs index 99cbeca86b..f4e4f9b013 100644 --- a/common/src/states/leap_melee.rs +++ b/common/src/states/leap_melee.rs @@ -82,6 +82,7 @@ impl CharacterBehavior for Data { knockback: 25.0, is_melee: true, lifesteal_eff: 0.0, + look_dir: None, }); update.character = CharacterState::LeapMelee(Data { diff --git a/common/src/states/triple_strike.rs b/common/src/states/triple_strike.rs index 97ca4d0364..17091bb676 100644 --- a/common/src/states/triple_strike.rs +++ b/common/src/states/triple_strike.rs @@ -155,6 +155,7 @@ impl CharacterBehavior for Data { knockback: 10.0, is_melee: true, lifesteal_eff: 0.0, + look_dir: None, }); CharacterState::TripleStrike(Data { diff --git a/common/src/sys/combat.rs b/common/src/sys/combat.rs index a4b4d3664b..9b15967481 100644 --- a/common/src/sys/combat.rs +++ b/common/src/sys/combat.rs @@ -89,11 +89,6 @@ impl<'a> System<'a> for Sys { ) .join() { - // 2D versions - let pos2 = Vec2::from(pos.0); - let pos_b2 = Vec2::::from(pos_b.0); - let ori2 = Vec2::from(*ori.0); - // Scales let scale = scale_maybe.map_or(1.0, |s| s.0); let scale_b = scale_b_maybe.map_or(1.0, |s| s.0); @@ -102,9 +97,26 @@ impl<'a> System<'a> for Sys { // Check if it is a damaging hit if entity != b && !stats_b.is_dead - // Spherical wedge shaped attack field - && pos.0.distance_squared(pos_b.0) < (rad_b + scale * attack.range).powi(2) - && ori2.angle_between(pos_b2 - pos2) < attack.max_angle + (rad_b / pos2.distance(pos_b2)).atan() + && ((attack.is_melee + && cylindrical_hit_detection( + *pos, + *ori, + *pos_b, + rad_b, + scale, + attack.range, + attack.max_angle, + )) + || (!attack.is_melee + && spherical_hit_detection( + *pos, + *pos_b, + rad_b, + scale, + attack.range, + attack.max_angle, + attack.look_dir.unwrap_or(*ori.0), + ))) { // See if entities are in the same group let same_group = groups @@ -163,7 +175,8 @@ impl<'a> System<'a> for Sys { server_emitter.emit(ServerEvent::Damage { uid: *uid, change: HealthChange { - amount: (-damage.healthchange * attack.lifesteal_eff) as i32, + amount: (-damage.healthchange * attack.lifesteal_eff) + as i32, cause: HealthSource::Healing { by: Some(*uid) }, }, }); @@ -188,3 +201,34 @@ impl<'a> System<'a> for Sys { ); } } + +fn cylindrical_hit_detection( + pos: Pos, + ori: Ori, + pos_b: Pos, + rad_b: f32, + scale: f32, + range: f32, + angle: f32, +) -> bool { + // 2D versions + let pos2 = Vec2::from(pos.0); + let pos_b2 = Vec2::::from(pos_b.0); + let ori2 = Vec2::from(*ori.0); + + return pos.0.distance_squared(pos_b.0) < (rad_b + scale * range).powi(2) + && ori2.angle_between(pos_b2 - pos2) < angle + (rad_b / pos2.distance(pos_b2)).atan(); +} + +fn spherical_hit_detection( + pos: Pos, + pos_b: Pos, + rad_b: f32, + scale: f32, + range: f32, + angle: f32, + ori: Vec3, +) -> bool { + return pos.0.distance_squared(pos_b.0) < (rad_b + scale * range).powi(2) + && ori.angle_between(pos_b.0 - pos.0) < angle + (rad_b / pos.0.distance(pos_b.0)).atan(); +}