This commit is contained in:
2026-03-22 22:30:15 +00:00
parent bf81f42ced
commit 3632836016
2 changed files with 28 additions and 50 deletions
+6 -7
View File
@@ -20,16 +20,15 @@ use crate::world::VisibleGameEntity;
/// Weight of a single log in kg. Enough to encumber a dorf carrying one. /// Weight of a single log in kg. Enough to encumber a dorf carrying one.
pub const LOG_WEIGHT_KG: u32 = 15; pub const LOG_WEIGHT_KG: u32 = 15;
/// Find the standable surface tile at world XY. Returns the tile one above /// Find the standable surface tile at world XY. Returns the floor tile
/// the highest floor tile where an entity can stand, or None if not found. /// where an entity can stand, or None if not found.
/// The standable position IS the floor tile itself (has can_stand_in=true),
/// not the air above it.
fn find_surface_at(world_x: i32, world_y: i32, tilemap: &TileMap) -> Option<IVec3> { fn find_surface_at(world_x: i32, world_y: i32, tilemap: &TileMap) -> Option<IVec3> {
for z in -3i32..=4i32 { for z in -3i32..=4i32 {
let floor_pos = IVec3::new(world_x, world_y, z * ITILE_SIZE); let floor_pos = IVec3::new(world_x, world_y, z * ITILE_SIZE);
if tilemap.floor_tiles.contains_key(&floor_pos) { if tilemap.floor_tiles.contains_key(&floor_pos) && tilemap.is_standable(floor_pos) {
let above = IVec3::new(world_x, world_y, floor_pos.z + ITILE_SIZE); return Some(floor_pos);
if tilemap.is_standable(above) {
return Some(above);
}
} }
} }
None None
+22 -43
View File
@@ -150,54 +150,33 @@ pub fn task_executor_system(
if approach.is_none() { if approach.is_none() {
// First entry: compute approach tile and set target. // First entry: compute approach tile and set target.
// Check 8 surrounding XY positions at the trunk's ground z. // Neighbours at the same z as the trunk base — this IS the floor level.
let offsets = [ let trunk_z = trunk_pos.z;
(-1, 0),
(1, 0),
(0, -1),
(0, 1),
(-1, -1),
(-1, 1),
(1, -1),
(1, 1),
];
// Find the ground z at the trunk XY (for z reference) // Search expanding outward from the trunk for a standable tile
let ground_z = (-3i32..=4i32) let approach_target = (1..=4).find_map(|radius: i32| {
.find_map(|z| { for dx in -radius..=radius {
let floor_pos = for dy in -radius..=radius {
IVec3::new(trunk_pos.x, trunk_pos.y, z * ITILE_SIZE); // Only check the outer ring of this radius
if tilemap_mut.floor_tiles.contains_key(&floor_pos) { if dx.abs() != radius && dy.abs() != radius {
let above = IVec3::new( continue;
trunk_pos.x, }
trunk_pos.y, let candidate = IVec3::new(
floor_pos.z + ITILE_SIZE, trunk_pos.x + dx * ITILE_SIZE,
trunk_pos.y + dy * ITILE_SIZE,
trunk_z,
); );
if tilemap_mut.is_standable(above) { if tilemap_mut.is_standable(candidate) {
return Some(above.z); *approach = Some(candidate);
return Some(Vec3::new(
candidate.x as f32,
candidate.y as f32,
candidate.z as f32 + 1.0,
));
} }
} }
None
})
.unwrap_or(trunk_pos.z);
// Find nearest standable neighbour
let approach_target = offsets.iter().find_map(|(dx, dy)| {
let candidate = IVec3::new(
trunk_pos.x + dx * ITILE_SIZE,
trunk_pos.y + dy * ITILE_SIZE,
ground_z,
);
if tilemap_mut.is_standable(candidate) {
*approach = Some(candidate);
Some(Vec3::new(
candidate.x as f32,
candidate.y as f32,
candidate.z as f32 + 1.0,
))
} else {
None
} }
None
}); });
match approach_target { match approach_target {