use std::collections::VecDeque; use bevy::prelude::*; use crate::{ items::{Carrying, ItemAssets}, jobs::{CurrentJob, IdleTimer}, pathfinding::find_path, sim::{SimPos, SimSystems, sim_pos}, world::{TILE_SIZE, TilePos, WorldMap}, worldgen::{WorldGenerated, spawn_tiles}, }; pub struct ColonistPlugin; impl Plugin for ColonistPlugin { fn build(&self, app: &mut App) { app.add_systems(Update, spawn_colonists.run_if(on_message::)) .add_systems(FixedUpdate, follow_path.in_set(SimSystems::Move)); } } const TILES_PER_SECOND: f32 = 4.0; const STARTING_COLONISTS: [(&str, Color); 3] = [ ("Ada", Color::srgb(0.9, 0.3, 0.3)), ("Bram", Color::srgb(0.3, 0.5, 0.95)), ("Cleo", Color::srgb(0.95, 0.75, 0.3)), ]; #[derive(Component, Debug)] #[require(Transform, SimPos, TilePos, Path, CurrentJob, IdleTimer, Carrying)] pub struct Colonist { pub name: String, } #[derive(Component, Default, Debug)] pub struct Path(pub VecDeque); fn spawn_colonists( mut commands: Commands, map: Res, existing: Query>, item_assets: Res, mut meshes: ResMut>, mut materials: ResMut>, ) { for entity in &existing { commands.entity(entity).despawn(); } let mesh = meshes.add(Circle::new(TILE_SIZE * 0.35)); let tiles = spawn_tiles(&map, STARTING_COLONISTS.len()); for ((name, color), tile) in STARTING_COLONISTS.into_iter().zip(tiles) { commands.spawn(( Name::new(name), Colonist { name: name.into() }, TilePos(tile), Mesh2d(mesh.clone()), MeshMaterial2d(materials.add(color)), sim_pos(WorldMap::tile_center(tile)), Transform::from_translation(WorldMap::tile_center(tile).extend(1.0)), children![item_assets.carried_visual()], )); } } pub fn repath( map: &WorldMap, tile: UVec2, current: &VecDeque, goal: UVec2, ) -> Option> { match current.front() { Some(&next) => { let mut path: VecDeque<_> = find_path(map, next, goal)?.into(); path.push_front(next); Some(path) } None => find_path(map, tile, goal).map(VecDeque::from), } } pub fn follow_path( time: Res