Beams now have spherical hit detection.

This commit is contained in:
Sam 2020-08-31 18:21:17 -05:00
parent 6bb680f372
commit 03b5cac2f9
7 changed files with 86 additions and 9 deletions

View File

@ -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<Vec3<f32>>,
}
impl Component for Attacking {

View File

@ -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 {

View File

@ -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 {

View File

@ -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(

View File

@ -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 {

View File

@ -155,6 +155,7 @@ impl CharacterBehavior for Data {
knockback: 10.0,
is_melee: true,
lifesteal_eff: 0.0,
look_dir: None,
});
CharacterState::TripleStrike(Data {

View File

@ -89,11 +89,6 @@ impl<'a> System<'a> for Sys {
)
.join()
{
// 2D versions
let pos2 = Vec2::from(pos.0);
let pos_b2 = Vec2::<f32>::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::<f32>::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<f32>,
) -> 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();
}