mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Beams now have spherical hit detection.
This commit is contained in:
parent
6bb680f372
commit
03b5cac2f9
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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(
|
||||
|
@ -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 {
|
||||
|
@ -155,6 +155,7 @@ impl CharacterBehavior for Data {
|
||||
knockback: 10.0,
|
||||
is_melee: true,
|
||||
lifesteal_eff: 0.0,
|
||||
look_dir: None,
|
||||
});
|
||||
|
||||
CharacterState::TripleStrike(Data {
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user