fix?
This commit is contained in:
@@ -81,7 +81,7 @@ use crate::world::{
|
|||||||
use crate::{constants::*, entities::shared_components::Ambulatory};
|
use crate::{constants::*, entities::shared_components::Ambulatory};
|
||||||
use bevy::math::ivec3;
|
use bevy::math::ivec3;
|
||||||
use bevy_rand::prelude::*;
|
use bevy_rand::prelude::*;
|
||||||
use rand::RngExt;
|
use rand::{RngExt, SeedableRng};
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
static LOCAL_PATH_TIMES: RefCell<Vec<u128>> = const { RefCell::new(Vec::new()) };
|
static LOCAL_PATH_TIMES: RefCell<Vec<u128>> = const { RefCell::new(Vec::new()) };
|
||||||
@@ -236,6 +236,7 @@ impl Plugin for PathfindingPlugin {
|
|||||||
collect_pathfinding_dirty_chunks,
|
collect_pathfinding_dirty_chunks,
|
||||||
invalidate_paths_on_tile_change,
|
invalidate_paths_on_tile_change,
|
||||||
crate::entities::tasks::task_executor_system,
|
crate::entities::tasks::task_executor_system,
|
||||||
|
update_wandering_targets,
|
||||||
prepare_paths,
|
prepare_paths,
|
||||||
movement,
|
movement,
|
||||||
)
|
)
|
||||||
@@ -529,14 +530,19 @@ pub fn merge_benchmark_stats(mut bench: ResMut<PathfindingBenchmark>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_wandering_targets(
|
pub fn update_wandering_targets(
|
||||||
mut query: Query<(&mut Ambulatory, &Transform)>,
|
mut query: Query<(&mut Ambulatory, &Transform), Without<crate::entities::tasks::TaskQueue>>,
|
||||||
tilemap: Res<TileMap>,
|
tilemap: Res<TileMap>,
|
||||||
chunk_map: Res<ChunkMap>,
|
chunk_map: Res<ChunkMap>,
|
||||||
mut rng_q: Query<&mut WyRand, With<GlobalRng>>,
|
time: Res<Time>,
|
||||||
) {
|
) {
|
||||||
let Ok(mut rng) = rng_q.single_mut() else {
|
// Use deterministic RNG - seed from SEED + time
|
||||||
return;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
};
|
use std::hash::{Hash, Hasher};
|
||||||
|
let mut hasher = DefaultHasher::new();
|
||||||
|
crate::constants::SEED.hash(&mut hasher);
|
||||||
|
time.elapsed_secs().to_bits().hash(&mut hasher);
|
||||||
|
let seed = hasher.finish();
|
||||||
|
let mut rng = WyRand::seed_from_u64(seed);
|
||||||
|
|
||||||
for (mut ambulatory, transform) in query.iter_mut() {
|
for (mut ambulatory, transform) in query.iter_mut() {
|
||||||
if ambulatory.target.is_none() {
|
if ambulatory.target.is_none() {
|
||||||
|
|||||||
+22
-11
@@ -44,10 +44,11 @@ pub(super) fn execute_idle(
|
|||||||
|
|
||||||
// Only reset path if target changed or no path exists
|
// Only reset path if target changed or no path exists
|
||||||
if target_changed || ambulatory.current_path.is_none() {
|
if target_changed || ambulatory.current_path.is_none() {
|
||||||
|
// +1.0 sub-tile offset matching original wandering system
|
||||||
ambulatory.target = Some(Vec3::new(
|
ambulatory.target = Some(Vec3::new(
|
||||||
target.x as f32,
|
target.x as f32,
|
||||||
target.y as f32,
|
target.y as f32,
|
||||||
transform.translation.z,
|
target.z as f32 + 1.0,
|
||||||
));
|
));
|
||||||
ambulatory.current_path = None;
|
ambulatory.current_path = None;
|
||||||
ambulatory.path_index = 0;
|
ambulatory.path_index = 0;
|
||||||
@@ -56,6 +57,7 @@ pub(super) fn execute_idle(
|
|||||||
|
|
||||||
/// Pick a random standable tile within wander radius of origin.
|
/// Pick a random standable tile within wander radius of origin.
|
||||||
/// Uses reservoir sampling to avoid heap allocation.
|
/// Uses reservoir sampling to avoid heap allocation.
|
||||||
|
/// Searches for actual surface z at each XY position (like original wandering system).
|
||||||
fn pick_wander_target(
|
fn pick_wander_target(
|
||||||
origin: &IVec3,
|
origin: &IVec3,
|
||||||
radius: i32,
|
radius: i32,
|
||||||
@@ -67,16 +69,25 @@ fn pick_wander_target(
|
|||||||
|
|
||||||
for dx in -radius..=radius {
|
for dx in -radius..=radius {
|
||||||
for dy in -radius..=radius {
|
for dy in -radius..=radius {
|
||||||
let candidate = IVec3::new(
|
// Search for actual surface z at this XY - same logic as original wandering
|
||||||
origin.x + dx * ITILE_SIZE,
|
for z in -3i32..=4i32 {
|
||||||
origin.y + dy * ITILE_SIZE,
|
let floor_pos = IVec3::new(
|
||||||
origin.z,
|
origin.x + dx * ITILE_SIZE,
|
||||||
);
|
origin.y + dy * ITILE_SIZE,
|
||||||
if tilemap.is_standable(candidate) {
|
z * ITILE_SIZE,
|
||||||
count += 1;
|
);
|
||||||
// Reservoir sampling: 1/count chance to replace chosen
|
// Check if there's a floor tile at this z
|
||||||
if rng.random_range(0..count) == 0 {
|
if tilemap.floor_tiles.get(&floor_pos).is_some() {
|
||||||
chosen = Some(candidate);
|
// Check if standable one tile above
|
||||||
|
let above = IVec3::new(floor_pos.x, floor_pos.y, floor_pos.z + ITILE_SIZE);
|
||||||
|
if tilemap.is_standable(above) {
|
||||||
|
count += 1;
|
||||||
|
// Reservoir sampling: 1/count chance to replace chosen
|
||||||
|
if rng.random_range(0..count) == 0 {
|
||||||
|
chosen = Some(above);
|
||||||
|
}
|
||||||
|
break; // found surface at this XY, stop z search
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user