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)] #[derive(Clone, Debug, PartialEq)]
pub enum ChopStep { pub enum ChopStep {
/// Walking to within range of the trunk. /// 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. /// Entity is in range and actively chopping.
Chopping { ticks_remaining: u32 }, Chopping { ticks_remaining: u32 },
/// Chopping complete. /// Chopping complete.
+1 -1
View File
@@ -181,7 +181,7 @@ pub fn demo_system(
queue.push(Task::ChopTree { queue.push(Task::ChopTree {
trunk_pos: lowest_trunk, trunk_pos: lowest_trunk,
chop_ticks: CHOP_TICKS_DEFAULT, chop_ticks: CHOP_TICKS_DEFAULT,
step: ChopStep::MovingToTree, step: ChopStep::MovingToTree { approach: None },
}); });
*state = TaskState::Pending; *state = TaskState::Pending;
} }
+33 -20
View File
@@ -135,7 +135,7 @@ pub fn task_executor_system(
chop_ticks, chop_ticks,
step, step,
} => match step { } => match step {
ChopStep::MovingToTree => { ChopStep::MovingToTree { ref mut approach } => {
if !tilemap_mut.fixture_tiles.contains_key(trunk_pos) { if !tilemap_mut.fixture_tiles.contains_key(trunk_pos) {
failed_writer.write(TaskFailed { failed_writer.write(TaskFailed {
entity, entity,
@@ -145,11 +145,11 @@ pub fn task_executor_system(
*state = TaskState::Failed; *state = TaskState::Failed;
continue; continue;
} }
if ambulatory.target.is_none() {
use crate::constants::ITILE_SIZE;
// The trunk tile itself is impassable (can_stand_in=false). use crate::constants::ITILE_SIZE;
// Path to the nearest standable tile adjacent to the trunk instead.
if approach.is_none() {
// First entry: compute approach tile and set target.
// Check 8 surrounding XY positions at the trunk's ground z. // Check 8 surrounding XY positions at the trunk's ground z.
let offsets = [ let offsets = [
(-1, 0), (-1, 0),
@@ -162,7 +162,7 @@ pub fn task_executor_system(
(1, 1), (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) let ground_z = (-3i32..=4i32)
.find_map(|z| { .find_map(|z| {
let floor_pos = let floor_pos =
@@ -181,7 +181,7 @@ pub fn task_executor_system(
}) })
.unwrap_or(trunk_pos.z); .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 approach_target = offsets.iter().find_map(|(dx, dy)| {
let candidate = IVec3::new( let candidate = IVec3::new(
trunk_pos.x + dx * ITILE_SIZE, trunk_pos.x + dx * ITILE_SIZE,
@@ -189,6 +189,7 @@ pub fn task_executor_system(
ground_z, ground_z,
); );
if tilemap_mut.is_standable(candidate) { if tilemap_mut.is_standable(candidate) {
*approach = Some(candidate);
Some(Vec3::new( Some(Vec3::new(
candidate.x as f32, candidate.x as f32,
candidate.y as f32, candidate.y as f32,
@@ -205,7 +206,6 @@ pub fn task_executor_system(
ambulatory.current_path = None; ambulatory.current_path = None;
} }
None => { None => {
// No adjacent standable tile — tree may be surrounded
failed_writer.write(TaskFailed { failed_writer.write(TaskFailed {
entity, entity,
task: current_task.clone(), task: current_task.clone(),
@@ -215,19 +215,32 @@ pub fn task_executor_system(
continue; 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; // If target is Some, pathfinding is handling movement — nothing to do
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,
};
}
} }
ChopStep::Chopping { ticks_remaining } => { ChopStep::Chopping { ticks_remaining } => {
if *ticks_remaining == 0 { if *ticks_remaining == 0 {