2022-02-13 01:52:01 +00:00
|
|
|
use crate::sys::agent::{AgentData, ReadData};
|
2022-01-18 03:02:43 +00:00
|
|
|
use common::{
|
|
|
|
comp::{buff::BuffKind, Alignment, Pos},
|
|
|
|
consts::GRAVITY,
|
|
|
|
terrain::{Block, TerrainGrid},
|
|
|
|
util::Dir,
|
|
|
|
vol::ReadVol,
|
|
|
|
};
|
|
|
|
use specs::{
|
|
|
|
saveload::{Marker, MarkerAllocator},
|
|
|
|
Entity as EcsEntity,
|
|
|
|
};
|
|
|
|
use vek::*;
|
|
|
|
|
|
|
|
pub fn can_see_tgt(terrain: &TerrainGrid, pos: &Pos, tgt_pos: &Pos, dist_sqrd: f32) -> bool {
|
|
|
|
terrain
|
|
|
|
.ray(pos.0 + Vec3::unit_z(), tgt_pos.0 + Vec3::unit_z())
|
|
|
|
.until(Block::is_opaque)
|
|
|
|
.cast()
|
|
|
|
.0
|
|
|
|
.powi(2)
|
|
|
|
>= dist_sqrd
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_dead_or_invulnerable(entity: EcsEntity, read_data: &ReadData) -> bool {
|
|
|
|
is_dead(entity, read_data) || is_invulnerable(entity, read_data)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_dead(entity: EcsEntity, read_data: &ReadData) -> bool {
|
|
|
|
let health = read_data.healths.get(entity);
|
|
|
|
health.map_or(false, |a| a.is_dead)
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: The logic that is used in this function and throughout the code
|
|
|
|
// shouldn't be used to mean that a character is in a safezone.
|
|
|
|
pub fn is_invulnerable(entity: EcsEntity, read_data: &ReadData) -> bool {
|
|
|
|
let buffs = read_data.buffs.get(entity);
|
|
|
|
|
|
|
|
buffs.map_or(false, |b| b.kinds.contains_key(&BuffKind::Invulnerability))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Attempts to get alignment of owner if entity has Owned alignment
|
|
|
|
pub fn try_owner_alignment<'a>(
|
|
|
|
alignment: Option<&'a Alignment>,
|
|
|
|
read_data: &'a ReadData,
|
|
|
|
) -> Option<&'a Alignment> {
|
|
|
|
if let Some(Alignment::Owned(owner_uid)) = alignment {
|
|
|
|
if let Some(owner) = get_entity_by_id(owner_uid.id(), read_data) {
|
|
|
|
return read_data.alignments.get(owner);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
alignment
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Projectile motion: Returns the direction to aim for the projectile to reach
|
|
|
|
/// target position. Does not take any forces but gravity into account.
|
|
|
|
pub fn aim_projectile(speed: f32, pos: Vec3<f32>, tgt: Vec3<f32>) -> Option<Dir> {
|
|
|
|
let mut to_tgt = tgt - pos;
|
|
|
|
let dist_sqrd = to_tgt.xy().magnitude_squared();
|
|
|
|
let u_sqrd = speed.powi(2);
|
|
|
|
to_tgt.z = (u_sqrd
|
|
|
|
- (u_sqrd.powi(2) - GRAVITY * (GRAVITY * dist_sqrd + 2.0 * to_tgt.z * u_sqrd))
|
|
|
|
.sqrt()
|
|
|
|
.max(0.0))
|
|
|
|
/ GRAVITY;
|
|
|
|
|
|
|
|
Dir::from_unnormalized(to_tgt)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_entity_by_id(id: u64, read_data: &ReadData) -> Option<EcsEntity> {
|
|
|
|
read_data.uid_allocator.retrieve_entity_internal(id)
|
|
|
|
}
|
2022-02-13 01:52:01 +00:00
|
|
|
|
|
|
|
impl<'a> AgentData<'a> {
|
|
|
|
pub fn has_buff(&self, read_data: &ReadData, buff: BuffKind) -> bool {
|
|
|
|
read_data
|
|
|
|
.buffs
|
|
|
|
.get(*self.entity)
|
|
|
|
.map_or(false, |b| b.kinds.contains_key(&buff))
|
|
|
|
}
|
|
|
|
}
|