2021-07-28 22:36:41 +00:00
|
|
|
use common::{
|
|
|
|
comp::{Alignment, Pet, PhysicsState, Pos},
|
|
|
|
terrain::TerrainGrid,
|
2023-04-26 04:31:14 +00:00
|
|
|
uid::IdMaps,
|
2021-07-28 22:36:41 +00:00
|
|
|
};
|
|
|
|
use common_ecs::{Job, Origin, Phase, System};
|
2023-04-23 05:58:29 +00:00
|
|
|
use specs::{Entities, Entity, Join, Read, ReadExpect, ReadStorage, WriteStorage};
|
2021-07-28 22:36:41 +00:00
|
|
|
|
|
|
|
/// This system is responsible for handling pets
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct Sys;
|
|
|
|
impl<'a> System<'a> for Sys {
|
|
|
|
type SystemData = (
|
|
|
|
Entities<'a>,
|
|
|
|
ReadExpect<'a, TerrainGrid>,
|
|
|
|
WriteStorage<'a, Pos>,
|
|
|
|
ReadStorage<'a, Alignment>,
|
|
|
|
ReadStorage<'a, Pet>,
|
|
|
|
ReadStorage<'a, PhysicsState>,
|
2023-04-26 04:31:14 +00:00
|
|
|
Read<'a, IdMaps>,
|
2021-07-28 22:36:41 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
const NAME: &'static str = "pets";
|
|
|
|
const ORIGIN: Origin = Origin::Server;
|
|
|
|
const PHASE: Phase = Phase::Create;
|
|
|
|
|
|
|
|
fn run(
|
|
|
|
_job: &mut Job<Self>,
|
2023-04-26 04:31:14 +00:00
|
|
|
(entities, terrain, mut positions, alignments, pets, physics, id_maps): Self::SystemData,
|
2021-07-28 22:36:41 +00:00
|
|
|
) {
|
|
|
|
const LOST_PET_DISTANCE_THRESHOLD: f32 = 200.0;
|
|
|
|
|
|
|
|
// Find pets that are too far away from their owner
|
|
|
|
let lost_pets: Vec<(Entity, Pos)> = (&entities, &positions, &alignments, &pets)
|
|
|
|
.join()
|
|
|
|
.filter_map(|(entity, pos, alignment, _)| match alignment {
|
2023-04-23 05:58:29 +00:00
|
|
|
Alignment::Owned(owner_uid) => Some((entity, pos, *owner_uid)),
|
2021-07-28 22:36:41 +00:00
|
|
|
_ => None,
|
|
|
|
})
|
|
|
|
.filter_map(|(pet_entity, pet_pos, owner_uid)| {
|
2023-05-21 20:32:51 +00:00
|
|
|
id_maps.uid_entity(owner_uid).and_then(|owner_entity| {
|
|
|
|
match (positions.get(owner_entity), physics.get(owner_entity)) {
|
|
|
|
(Some(position), Some(physics)) => {
|
|
|
|
Some((pet_entity, position, physics, pet_pos))
|
|
|
|
},
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
})
|
2021-07-28 22:36:41 +00:00
|
|
|
})
|
|
|
|
.filter(|(_, owner_pos, owner_physics, pet_pos)| {
|
|
|
|
// Don't teleport pets to the player if they're in the air, nobody wants
|
|
|
|
// pets to go splat :(
|
|
|
|
owner_physics.on_ground.is_some()
|
|
|
|
&& owner_pos.0.distance_squared(pet_pos.0) > LOST_PET_DISTANCE_THRESHOLD.powi(2)
|
|
|
|
})
|
|
|
|
.map(|(entity, owner_pos, _, _)| (entity, *owner_pos))
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
for (pet_entity, owner_pos) in lost_pets.iter() {
|
|
|
|
if let Some(mut pet_pos) = positions.get_mut(*pet_entity) {
|
|
|
|
// Move the pets to their owner's position
|
|
|
|
// TODO: Create a teleportation event to handle this instead of
|
|
|
|
// processing the entity position move here
|
|
|
|
pet_pos.0 = terrain
|
2023-04-12 08:17:49 +00:00
|
|
|
.find_ground(owner_pos.0.map(|e| e.floor() as i32))
|
2021-07-28 22:36:41 +00:00
|
|
|
.map(|e| e as f32);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|