This commit is contained in:
2026-03-22 00:52:06 +00:00
parent cafe376841
commit 71653350d8
4 changed files with 42 additions and 36 deletions
+25 -18
View File
@@ -31,33 +31,42 @@ pub(super) fn execute_idle(
let entity_pos = (transform.translation / ITILE_SIZE as f32).as_ivec3();
// Track if target actually changed this tick
let mut target_changed = false;
// 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;
target_changed = true;
}
}
// 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;
// Only reset path if target changed or no path exists
// This avoids forcing pathfinding to recompute every frame
if target_changed || ambulatory.current_path.is_none() {
ambulatory.target = Some(Vec3::new(
target.x as f32,
target.y as f32,
transform.translation.z,
));
ambulatory.current_path = None;
ambulatory.path_index = 0;
}
// Otherwise: keep existing path, let movement system continue along it
}
/// Pick a random standable tile within wander radius of origin.
/// Uses reservoir sampling to avoid heap allocation.
fn pick_wander_target(
origin: &IVec3,
radius: i32,
tilemap: &TileMap,
rng: &mut WyRand,
) -> Option<IVec3> {
let mut candidates = smallvec::SmallVec::<[IVec3; 16]>::new();
let mut chosen = None;
let mut count = 0u32;
// Collect valid tiles within radius
for dx in -radius..=radius {
for dy in -radius..=radius {
let candidate = IVec3::new(
@@ -66,15 +75,13 @@ fn pick_wander_target(
origin.z,
);
if tilemap.is_standable(candidate) {
candidates.push(candidate);
count += 1;
// Reservoir sampling: 1/count chance to replace chosen
if rng.random_range(0..count) == 0 {
chosen = Some(candidate);
}
}
}
}
if candidates.is_empty() {
return None;
}
let idx = rng.random_range(0..candidates.len());
Some(candidates[idx])
chosen
}