fix
This commit is contained in:
+25
-18
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user