Task Infrastructure — Task Enum, Queue, Events, Executor
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
//! Idle task implementation — wandering behaviour refactored here.
|
||||
//!
|
||||
//! This module contains the logic that was previously in the wandering
|
||||
//! system. Now it's called by the task executor when Task::Idle is active.
|
||||
|
||||
use crate::constants::ITILE_SIZE;
|
||||
use crate::entities::shared_components::Ambulatory;
|
||||
use crate::entities::tasks::components::Task;
|
||||
use crate::world::tiles::tilemap::TileMap;
|
||||
use bevy::prelude::*;
|
||||
use bevy_rand::prelude::*;
|
||||
use rand::RngExt;
|
||||
|
||||
/// Execute Idle task: set target for wandering, let pathfinding handle movement.
|
||||
pub(super) fn execute_idle(
|
||||
entity: Entity,
|
||||
task: &mut Task,
|
||||
transform: &Transform,
|
||||
ambulatory: &mut Ambulatory,
|
||||
tilemap: &TileMap,
|
||||
rng: &mut WyRand,
|
||||
) {
|
||||
let Task::Idle {
|
||||
target,
|
||||
wander_radius,
|
||||
origin,
|
||||
} = task
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
let entity_pos = (transform.translation / ITILE_SIZE as f32).as_ivec3();
|
||||
|
||||
// If reached target or target is no longer standable, pick new target
|
||||
if entity_pos == *target || !tilemap.is_standable(*target) {
|
||||
if let Some(new_target) = pick_wander_target(origin, *wander_radius, tilemap, rng) {
|
||||
*target = new_target;
|
||||
}
|
||||
}
|
||||
|
||||
// Set ambulatory target - pathfinding system will compute path
|
||||
ambulatory.target = Some(Vec3::new(
|
||||
target.x as f32,
|
||||
target.y as f32,
|
||||
transform.translation.z,
|
||||
));
|
||||
ambulatory.current_path = None;
|
||||
ambulatory.path_index = 0;
|
||||
}
|
||||
|
||||
/// Pick a random standable tile within wander radius of origin.
|
||||
fn pick_wander_target(
|
||||
origin: &IVec3,
|
||||
radius: i32,
|
||||
tilemap: &TileMap,
|
||||
rng: &mut WyRand,
|
||||
) -> Option<IVec3> {
|
||||
let mut candidates = smallvec::SmallVec::<[IVec3; 16]>::new();
|
||||
|
||||
// Collect valid tiles within radius
|
||||
for dx in -radius..=radius {
|
||||
for dy in -radius..=radius {
|
||||
let candidate = IVec3::new(
|
||||
origin.x + dx * ITILE_SIZE,
|
||||
origin.y + dy * ITILE_SIZE,
|
||||
origin.z,
|
||||
);
|
||||
if tilemap.is_standable(candidate) {
|
||||
candidates.push(candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if candidates.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let idx = rng.random_range(0..candidates.len());
|
||||
Some(candidates[idx])
|
||||
}
|
||||
Reference in New Issue
Block a user