use crate::sys::agent::ReadData; 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, tgt: Vec3) -> Option { 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 { read_data.uid_allocator.retrieve_entity_internal(id) }