Task fix attempt
This commit is contained in:
+122
-36
@@ -14,7 +14,7 @@ use crate::entities::shared_components::Ambulatory;
|
||||
use crate::entities::tasks::components::{
|
||||
ChopStep, DropStep, HaulStep, IdleState, Task, TaskQueue, TaskState,
|
||||
};
|
||||
use crate::entities::tasks::events::{TaskClaimed, TaskCompleted, TaskFailed};
|
||||
use crate::entities::tasks::events::{LogsSpawned, TaskClaimed, TaskCompleted, TaskFailed};
|
||||
use crate::entities::tasks::idle::execute_idle;
|
||||
use crate::world::chunks::ChunkMap;
|
||||
use crate::world::generation::forestry::{fell_tree, TreePart};
|
||||
@@ -23,6 +23,7 @@ use crate::world::tiles::visibility::TileOcclusionEvent;
|
||||
use crate::world::tiles::TileMap;
|
||||
use bevy::prelude::*;
|
||||
use bevy_rand::prelude::*;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
/// Main task executor. Runs in FixedUpdate.
|
||||
pub fn task_executor_system(
|
||||
@@ -47,6 +48,7 @@ pub fn task_executor_system(
|
||||
mut claimed_writer: MessageWriter<TaskClaimed>,
|
||||
mut completed_writer: MessageWriter<TaskCompleted>,
|
||||
mut failed_writer: MessageWriter<TaskFailed>,
|
||||
mut logs_spawned_writer: MessageWriter<LogsSpawned>,
|
||||
mut tile_changed: MessageWriter<TileChangedEvent>,
|
||||
mut occlusion: MessageWriter<TileOcclusionEvent>,
|
||||
) {
|
||||
@@ -241,15 +243,27 @@ pub fn task_executor_system(
|
||||
fall_dir = Vec2::new(1.0, 0.0); // default: fall east
|
||||
}
|
||||
let log_sprite: Handle<Image> = asset_server.load("log_cargo.png");
|
||||
let mut log_entities: SmallVec<[Entity; 8]> = SmallVec::new();
|
||||
for &pos in trunk_positions.iter() {
|
||||
crate::entities::cargo::spawn_log_cargo(
|
||||
&mut commands,
|
||||
&mut tilemap_mut,
|
||||
pos,
|
||||
fall_dir,
|
||||
log_sprite.clone(),
|
||||
&mut rng,
|
||||
);
|
||||
if let Some(log_entity) =
|
||||
crate::entities::cargo::spawn_log_cargo(
|
||||
&mut commands,
|
||||
&mut tilemap_mut,
|
||||
pos,
|
||||
fall_dir,
|
||||
log_sprite.clone(),
|
||||
&mut rng,
|
||||
)
|
||||
{
|
||||
log_entities.push(log_entity);
|
||||
}
|
||||
}
|
||||
// Emit event so demo can queue HaulCargo tasks for these logs
|
||||
if !log_entities.is_empty() {
|
||||
logs_spawned_writer.write(LogsSpawned {
|
||||
log_entities,
|
||||
dest: IVec3::ZERO,
|
||||
});
|
||||
}
|
||||
*step = ChopStep::Done;
|
||||
} else {
|
||||
@@ -277,7 +291,9 @@ pub fn task_executor_system(
|
||||
};
|
||||
|
||||
match step {
|
||||
HaulStep::MovingToCargo => {
|
||||
HaulStep::MovingToCargo { approach } => {
|
||||
use crate::constants::ITILE_SIZE;
|
||||
|
||||
if !tilemap_mut.cargo_tiles.contains_key(cargo_pos) {
|
||||
failed_writer.write(TaskFailed {
|
||||
entity,
|
||||
@@ -287,22 +303,75 @@ pub fn task_executor_system(
|
||||
*state = TaskState::Failed;
|
||||
continue;
|
||||
}
|
||||
if ambulatory.target.is_none() {
|
||||
ambulatory.target = Some(Vec3::new(
|
||||
cargo_pos.x as f32,
|
||||
cargo_pos.y as f32,
|
||||
cargo_pos.z as f32 + 1.0,
|
||||
));
|
||||
ambulatory.current_path = None;
|
||||
|
||||
if approach.is_none() {
|
||||
// Search for nearest standable tile to approach cargo.
|
||||
// Radius 0 = cargo tile itself (can stand in same tile as cargo).
|
||||
// Radius 1-2 = adjacent tiles if cargo tile is blocked.
|
||||
let cargo_z = cargo_pos.z;
|
||||
let approach_tile = (0..=2i32).find_map(|radius: i32| {
|
||||
for dx in -radius..=radius {
|
||||
for dy in -radius..=radius {
|
||||
if radius > 0
|
||||
&& dx.abs() != radius
|
||||
&& dy.abs() != radius
|
||||
{
|
||||
continue;
|
||||
}
|
||||
let candidate = IVec3::new(
|
||||
cargo_pos.x + dx * ITILE_SIZE,
|
||||
cargo_pos.y + dy * ITILE_SIZE,
|
||||
cargo_z,
|
||||
);
|
||||
if tilemap_mut.is_standable(candidate) {
|
||||
return Some(candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
});
|
||||
|
||||
match approach_tile {
|
||||
Some(tile) => {
|
||||
*approach = Some(tile);
|
||||
info!(
|
||||
"[HAUL] {:?} target set: cargo={:?} approach={:?}",
|
||||
entity, cargo_pos, tile
|
||||
);
|
||||
// +1.0 z-offset for entity standing height (same as trees)
|
||||
ambulatory.target = Some(Vec3::new(
|
||||
tile.x as f32,
|
||||
tile.y as f32,
|
||||
tile.z as f32 + 1.0,
|
||||
));
|
||||
ambulatory.current_path = None;
|
||||
}
|
||||
None => {
|
||||
failed_writer.write(TaskFailed {
|
||||
entity,
|
||||
task: current_task.clone(),
|
||||
reason: "no standable tile near cargo",
|
||||
});
|
||||
*state = TaskState::Failed;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
let dx = transform.translation.x - cargo_pos.x as f32;
|
||||
let dy = transform.translation.y - cargo_pos.y as f32;
|
||||
let dist_sq = dx * dx + dy * dy;
|
||||
let pickup_range_sq = (crate::constants::TILE_SIZE * 1.5)
|
||||
* (crate::constants::TILE_SIZE * 1.5);
|
||||
if dist_sq <= pickup_range_sq {
|
||||
ambulatory.target = None;
|
||||
*step = HaulStep::PickingUp;
|
||||
|
||||
// Check arrival at cargo tile
|
||||
if approach.is_some() && ambulatory.target.is_none() {
|
||||
let dx = transform.translation.x - cargo_pos.x as f32;
|
||||
let dy = transform.translation.y - cargo_pos.y as f32;
|
||||
let dist_sq = dx * dx + dy * dy;
|
||||
let pickup_range_sq =
|
||||
(ITILE_SIZE as f32 * 1.5) * (ITILE_SIZE as f32 * 1.5);
|
||||
if dist_sq <= pickup_range_sq {
|
||||
info!(
|
||||
"[HAUL] {:?} arrived at cargo {:?}, picking up",
|
||||
entity, cargo_entity
|
||||
);
|
||||
*step = HaulStep::PickingUp;
|
||||
}
|
||||
}
|
||||
}
|
||||
HaulStep::PickingUp => {
|
||||
@@ -317,6 +386,10 @@ pub fn task_executor_system(
|
||||
}
|
||||
if let Some(_) = tilemap_mut.remove_cargo(cargo_pos) {
|
||||
haul.pick_up(*cargo_entity);
|
||||
info!(
|
||||
"[HAUL] {:?} picked up {:?} → hauling to {:?}",
|
||||
entity, cargo_entity, dest
|
||||
);
|
||||
*step = HaulStep::MovingToDest { chosen_drop: None };
|
||||
} else {
|
||||
failed_writer.write(TaskFailed {
|
||||
@@ -337,6 +410,8 @@ pub fn task_executor_system(
|
||||
}
|
||||
let drop_pos = chosen_drop.unwrap();
|
||||
if ambulatory.target.is_none() {
|
||||
info!("[HAUL] {:?} target set: drop at {:?}", entity, drop_pos);
|
||||
// +1.0 z-offset for entity standing height (same as approach)
|
||||
ambulatory.target = Some(Vec3::new(
|
||||
drop_pos.x as f32,
|
||||
drop_pos.y as f32,
|
||||
@@ -344,19 +419,28 @@ pub fn task_executor_system(
|
||||
));
|
||||
ambulatory.current_path = None;
|
||||
}
|
||||
let target_pos = ambulatory.target.unwrap_or(Vec3::ZERO);
|
||||
let dx = transform.translation.x - target_pos.x;
|
||||
let dy = transform.translation.y - target_pos.y;
|
||||
|
||||
// Always check arrival distance, not gated by target status
|
||||
let dx = transform.translation.x - drop_pos.x as f32;
|
||||
let dy = transform.translation.y - drop_pos.y as f32;
|
||||
let dist_sq = dx * dx + dy * dy;
|
||||
let arrive_sq = (crate::constants::TILE_SIZE * 1.5)
|
||||
* (crate::constants::TILE_SIZE * 1.5);
|
||||
let arrive_sq = (crate::constants::TILE_SIZE as f32 * 1.5)
|
||||
* (crate::constants::TILE_SIZE as f32 * 1.5);
|
||||
if dist_sq <= arrive_sq {
|
||||
ambulatory.target = None;
|
||||
info!(
|
||||
"[HAUL] {:?} arrived at drop point {:?}",
|
||||
entity, drop_pos
|
||||
);
|
||||
*step = HaulStep::Dropping { drop_pos };
|
||||
}
|
||||
}
|
||||
HaulStep::Dropping { drop_pos } => {
|
||||
if let Some(cargo_entity) = haul.release() {
|
||||
info!(
|
||||
"[HAUL] {:?} dropped {:?} at {:?}",
|
||||
entity, cargo_entity, drop_pos
|
||||
);
|
||||
if tilemap_mut.place_cargo(*drop_pos, cargo_entity).is_err() {
|
||||
warn!(
|
||||
"place_cargo failed at {:?} — tile occupied. \
|
||||
@@ -371,6 +455,7 @@ pub fn task_executor_system(
|
||||
*step = HaulStep::Done;
|
||||
}
|
||||
HaulStep::Done => {
|
||||
info!("[HAUL] {:?} haul task COMPLETE", entity);
|
||||
*state = TaskState::Completed;
|
||||
}
|
||||
}
|
||||
@@ -395,16 +480,17 @@ pub fn task_executor_system(
|
||||
ambulatory.target = Some(Vec3::new(
|
||||
drop_pos.x as f32,
|
||||
drop_pos.y as f32,
|
||||
drop_pos.z as f32 + 1.0,
|
||||
drop_pos.z as f32,
|
||||
));
|
||||
ambulatory.current_path = None;
|
||||
}
|
||||
let target_pos = ambulatory.target.unwrap_or(Vec3::ZERO);
|
||||
let dx = transform.translation.x - target_pos.x;
|
||||
let dy = transform.translation.y - target_pos.y;
|
||||
|
||||
// Always check arrival distance, not gated by target status
|
||||
let dx = transform.translation.x - drop_pos.x as f32;
|
||||
let dy = transform.translation.y - drop_pos.y as f32;
|
||||
let dist_sq = dx * dx + dy * dy;
|
||||
let arrive_sq = (crate::constants::TILE_SIZE * 1.5)
|
||||
* (crate::constants::TILE_SIZE * 1.5);
|
||||
let arrive_sq = (crate::constants::TILE_SIZE as f32 * 1.5)
|
||||
* (crate::constants::TILE_SIZE as f32 * 1.5);
|
||||
if dist_sq <= arrive_sq {
|
||||
ambulatory.target = None;
|
||||
*step = DropStep::Dropping { drop_pos };
|
||||
|
||||
Reference in New Issue
Block a user