This commit is contained in:
2026-03-22 22:05:08 +00:00
parent c448ef4bff
commit 57764fbcbb
3 changed files with 36 additions and 22 deletions
+2 -1
View File
@@ -43,7 +43,8 @@ pub enum IdleState {
#[derive(Clone, Debug, PartialEq)]
pub enum ChopStep {
/// Walking to within range of the trunk.
MovingToTree,
/// `approach` is the computed standable tile adjacent to the trunk (impassable).
MovingToTree { approach: Option<IVec3> },
/// Entity is in range and actively chopping.
Chopping { ticks_remaining: u32 },
/// Chopping complete.
+1 -1
View File
@@ -181,7 +181,7 @@ pub fn demo_system(
queue.push(Task::ChopTree {
trunk_pos: lowest_trunk,
chop_ticks: CHOP_TICKS_DEFAULT,
step: ChopStep::MovingToTree,
step: ChopStep::MovingToTree { approach: None },
});
*state = TaskState::Pending;
}
+33 -20
View File
@@ -135,7 +135,7 @@ pub fn task_executor_system(
chop_ticks,
step,
} => match step {
ChopStep::MovingToTree => {
ChopStep::MovingToTree { ref mut approach } => {
if !tilemap_mut.fixture_tiles.contains_key(trunk_pos) {
failed_writer.write(TaskFailed {
entity,
@@ -145,11 +145,11 @@ pub fn task_executor_system(
*state = TaskState::Failed;
continue;
}
if ambulatory.target.is_none() {
use crate::constants::ITILE_SIZE;
// The trunk tile itself is impassable (can_stand_in=false).
// Path to the nearest standable tile adjacent to the trunk instead.
use crate::constants::ITILE_SIZE;
if approach.is_none() {
// First entry: compute approach tile and set target.
// Check 8 surrounding XY positions at the trunk's ground z.
let offsets = [
(-1, 0),
@@ -162,7 +162,7 @@ pub fn task_executor_system(
(1, 1),
];
// First find the ground z at the trunk XY (for z reference)
// Find the ground z at the trunk XY (for z reference)
let ground_z = (-3i32..=4i32)
.find_map(|z| {
let floor_pos =
@@ -181,7 +181,7 @@ pub fn task_executor_system(
})
.unwrap_or(trunk_pos.z);
// Find nearest standable neighbour to path toward
// Find nearest standable neighbour
let approach_target = offsets.iter().find_map(|(dx, dy)| {
let candidate = IVec3::new(
trunk_pos.x + dx * ITILE_SIZE,
@@ -189,6 +189,7 @@ pub fn task_executor_system(
ground_z,
);
if tilemap_mut.is_standable(candidate) {
*approach = Some(candidate);
Some(Vec3::new(
candidate.x as f32,
candidate.y as f32,
@@ -205,7 +206,6 @@ pub fn task_executor_system(
ambulatory.current_path = None;
}
None => {
// No adjacent standable tile — tree may be surrounded
failed_writer.write(TaskFailed {
entity,
task: current_task.clone(),
@@ -215,19 +215,32 @@ pub fn task_executor_system(
continue;
}
}
} else if ambulatory.target.is_none() {
// Arrived at approach tile (or path failed and target cleared).
// Check distance to trunk; if close enough, start chopping.
let dx = transform.translation.x - trunk_pos.x as f32;
let dy = transform.translation.y - trunk_pos.y as f32;
let dist_sq = dx * dx + dy * dy;
let chop_range_sq =
(ITILE_SIZE as f32 * 2.5) * (ITILE_SIZE as f32 * 2.5);
if dist_sq <= chop_range_sq {
// Close enough — transition to chopping
ambulatory.current_path = None;
*step = ChopStep::Chopping {
ticks_remaining: *chop_ticks,
};
} else if let Some(approach_tile) = *approach {
// Not in range — re-set target to approach tile
ambulatory.target = Some(Vec3::new(
approach_tile.x as f32,
approach_tile.y as f32,
approach_tile.z as f32 + 1.0,
));
ambulatory.current_path = None;
}
}
let dx = transform.translation.x - trunk_pos.x as f32;
let dy = transform.translation.y - trunk_pos.y as f32;
let dist_sq = dx * dx + dy * dy;
let chop_range_sq = (crate::constants::TILE_SIZE * 2.5)
* (crate::constants::TILE_SIZE * 2.5);
if dist_sq <= chop_range_sq {
ambulatory.target = None;
ambulatory.current_path = None;
*step = ChopStep::Chopping {
ticks_remaining: *chop_ticks,
};
}
// If target is Some, pathfinding is handling movement — nothing to do
}
ChopStep::Chopping { ticks_remaining } => {
if *ticks_remaining == 0 {