From 8664a8e06656c58481962514c1d0c178a0809f7f Mon Sep 17 00:00:00 2001 From: Llywelwyn Date: Fri, 21 Jul 2023 10:58:58 +0100 Subject: [PATCH] refactors entity spawning --- src/map_builders/bsp_dungeon.rs | 15 ++-- src/map_builders/bsp_interior.rs | 15 ++-- src/map_builders/cellular_automata.rs | 15 ++-- src/map_builders/dla.rs | 18 +++-- src/map_builders/drunkard.rs | 19 +++-- src/map_builders/maze.rs | 15 ++-- src/map_builders/mod.rs | 20 ++++- src/map_builders/prefab_builder/mod.rs | 60 ++++++++++++-- .../prefab_builder/prefab_sections.rs | 79 +++++++++++++++++++ src/map_builders/simple_map.rs | 15 ++-- src/map_builders/voronoi.rs | 17 ++-- src/map_builders/wfc/mod.rs | 15 ++-- src/spawner.rs | 66 +++++++++------- 13 files changed, 286 insertions(+), 83 deletions(-) create mode 100644 src/map_builders/prefab_builder/prefab_sections.rs diff --git a/src/map_builders/bsp_dungeon.rs b/src/map_builders/bsp_dungeon.rs index fb3cdb6..2784238 100644 --- a/src/map_builders/bsp_dungeon.rs +++ b/src/map_builders/bsp_dungeon.rs @@ -9,17 +9,13 @@ pub struct BspDungeonBuilder { rooms: Vec, history: Vec, rects: Vec, + spawn_list: Vec<(usize, String)>, } impl MapBuilder for BspDungeonBuilder { fn build_map(&mut self, rng: &mut RandomNumberGenerator) { return self.build(rng); } - fn spawn_entities(&mut self, ecs: &mut World) { - for room in self.rooms.iter().skip(1) { - spawner::spawn_room(ecs, room, self.depth); - } - } // Getters fn get_map(&mut self) -> Map { return self.map.clone(); @@ -27,6 +23,9 @@ impl MapBuilder for BspDungeonBuilder { fn get_starting_pos(&mut self) -> Position { return self.starting_position.clone(); } + fn get_spawn_list(&self) -> &Vec<(usize, String)> { + return &self.spawn_list; + } // Mapgen visualisation stuff fn get_snapshot_history(&self) -> Vec { return self.history.clone(); @@ -51,6 +50,7 @@ impl BspDungeonBuilder { rooms: Vec::new(), history: Vec::new(), rects: Vec::new(), + spawn_list: Vec::new(), } } @@ -97,6 +97,11 @@ impl BspDungeonBuilder { let stairs = self.rooms[self.rooms.len() - 1].centre(); let stairs_idx = self.map.xy_idx(stairs.0, stairs.1); self.map.tiles[stairs_idx] = TileType::DownStair; + + // Spawn entities + for room in self.rooms.iter().skip(1) { + spawner::spawn_room(&self.map, rng, room, self.depth, &mut self.spawn_list); + } } fn add_subrects(&mut self, rect: Rect) { diff --git a/src/map_builders/bsp_interior.rs b/src/map_builders/bsp_interior.rs index 0009ed8..595af5a 100644 --- a/src/map_builders/bsp_interior.rs +++ b/src/map_builders/bsp_interior.rs @@ -9,17 +9,13 @@ pub struct BspInteriorBuilder { rooms: Vec, history: Vec, rects: Vec, + spawn_list: Vec<(usize, String)>, } impl MapBuilder for BspInteriorBuilder { fn build_map(&mut self, rng: &mut RandomNumberGenerator) { return self.build(rng); } - fn spawn_entities(&mut self, ecs: &mut World) { - for room in self.rooms.iter().skip(1) { - spawner::spawn_room(ecs, room, self.depth); - } - } // Getters fn get_map(&mut self) -> Map { return self.map.clone(); @@ -27,6 +23,9 @@ impl MapBuilder for BspInteriorBuilder { fn get_starting_pos(&mut self) -> Position { return self.starting_position.clone(); } + fn get_spawn_list(&self) -> &Vec<(usize, String)> { + return &self.spawn_list; + } // Mapgen visualisation stuff fn get_snapshot_history(&self) -> Vec { return self.history.clone(); @@ -51,6 +50,7 @@ impl BspInteriorBuilder { rooms: Vec::new(), history: Vec::new(), rects: Vec::new(), + spawn_list: Vec::new(), } } @@ -94,6 +94,11 @@ impl BspInteriorBuilder { let stairs = self.rooms[self.rooms.len() - 1].centre(); let stairs_idx = self.map.xy_idx(stairs.0, stairs.1); self.map.tiles[stairs_idx] = TileType::DownStair; + + // Spawn entities + for room in self.rooms.iter().skip(1) { + spawner::spawn_room(&self.map, rng, room, self.depth, &mut self.spawn_list); + } } fn add_subrects(&mut self, rect: Rect, rng: &mut RandomNumberGenerator) { diff --git a/src/map_builders/cellular_automata.rs b/src/map_builders/cellular_automata.rs index 7d7aa2d..98c312e 100644 --- a/src/map_builders/cellular_automata.rs +++ b/src/map_builders/cellular_automata.rs @@ -14,17 +14,13 @@ pub struct CellularAutomataBuilder { depth: i32, history: Vec, noise_areas: HashMap>, + spawn_list: Vec<(usize, String)>, } impl MapBuilder for CellularAutomataBuilder { fn build_map(&mut self, rng: &mut RandomNumberGenerator) { return self.build(rng); } - fn spawn_entities(&mut self, ecs: &mut World) { - for area in self.noise_areas.iter() { - spawner::spawn_region(ecs, area.1, self.depth); - } - } // Getters fn get_map(&mut self) -> Map { return self.map.clone(); @@ -32,6 +28,9 @@ impl MapBuilder for CellularAutomataBuilder { fn get_starting_pos(&mut self) -> Position { return self.starting_position.clone(); } + fn get_spawn_list(&self) -> &Vec<(usize, String)> { + return &self.spawn_list; + } // Mapgen visualisation stuff fn get_snapshot_history(&self) -> Vec { return self.history.clone(); @@ -55,6 +54,7 @@ impl CellularAutomataBuilder { depth: new_depth, history: Vec::new(), noise_areas: HashMap::new(), + spawn_list: Vec::new(), } } @@ -135,5 +135,10 @@ impl CellularAutomataBuilder { // Noise map for spawning entities self.noise_areas = generate_voronoi_spawn_regions(&self.map, rng); + + // Spawn the entities + for area in self.noise_areas.iter() { + spawner::spawn_region(&self.map, rng, area.1, self.depth, &mut self.spawn_list); + } } } diff --git a/src/map_builders/dla.rs b/src/map_builders/dla.rs index 627216a..45616fc 100644 --- a/src/map_builders/dla.rs +++ b/src/map_builders/dla.rs @@ -23,17 +23,13 @@ pub struct DLABuilder { brush_size: i32, symmetry: Symmetry, floor_percent: f32, + spawn_list: Vec<(usize, String)>, } impl MapBuilder for DLABuilder { fn build_map(&mut self, rng: &mut RandomNumberGenerator) { return self.build(rng); } - fn spawn_entities(&mut self, ecs: &mut World) { - for area in self.noise_areas.iter() { - spawner::spawn_region(ecs, area.1, self.depth); - } - } // Getters fn get_map(&mut self) -> Map { return self.map.clone(); @@ -41,6 +37,9 @@ impl MapBuilder for DLABuilder { fn get_starting_pos(&mut self) -> Position { return self.starting_position.clone(); } + fn get_spawn_list(&self) -> &Vec<(usize, String)> { + return &self.spawn_list; + } // Mapgen visualisation stuff fn get_snapshot_history(&self) -> Vec { return self.history.clone(); @@ -68,6 +67,7 @@ impl DLABuilder { brush_size: 1, symmetry: Symmetry::None, floor_percent: 0.25, + spawn_list: Vec::new(), } } @@ -82,6 +82,7 @@ impl DLABuilder { brush_size: 2, symmetry: Symmetry::None, floor_percent: 0.25, + spawn_list: Vec::new(), } } @@ -96,6 +97,7 @@ impl DLABuilder { brush_size: 2, symmetry: Symmetry::None, floor_percent: 0.25, + spawn_list: Vec::new(), } } @@ -110,6 +112,7 @@ impl DLABuilder { brush_size: 2, symmetry: Symmetry::Horizontal, floor_percent: 0.25, + spawn_list: Vec::new(), } } @@ -236,5 +239,10 @@ impl DLABuilder { // Now we build a noise map for use in spawning entities later self.noise_areas = generate_voronoi_spawn_regions(&self.map, rng); + + // Spawn the entities + for area in self.noise_areas.iter() { + spawner::spawn_region(&self.map, rng, area.1, self.depth, &mut self.spawn_list); + } } } diff --git a/src/map_builders/drunkard.rs b/src/map_builders/drunkard.rs index 8d8749f..ed1567a 100644 --- a/src/map_builders/drunkard.rs +++ b/src/map_builders/drunkard.rs @@ -27,17 +27,13 @@ pub struct DrunkardsWalkBuilder { history: Vec, noise_areas: HashMap>, settings: DrunkardSettings, + spawn_list: Vec<(usize, String)>, } impl MapBuilder for DrunkardsWalkBuilder { fn build_map(&mut self, rng: &mut RandomNumberGenerator) { return self.build(rng); } - fn spawn_entities(&mut self, ecs: &mut World) { - for area in self.noise_areas.iter() { - spawner::spawn_region(ecs, area.1, self.depth); - } - } // Getters fn get_map(&mut self) -> Map { return self.map.clone(); @@ -45,6 +41,9 @@ impl MapBuilder for DrunkardsWalkBuilder { fn get_starting_pos(&mut self) -> Position { return self.starting_position.clone(); } + fn get_spawn_list(&self) -> &Vec<(usize, String)> { + return &self.spawn_list; + } // Mapgen visualisation stuff fn get_snapshot_history(&self) -> Vec { return self.history.clone(); @@ -75,6 +74,7 @@ impl DrunkardsWalkBuilder { brush_size: 1, symmetry: Symmetry::None, }, + spawn_list: Vec::new(), } } @@ -92,6 +92,7 @@ impl DrunkardsWalkBuilder { brush_size: 1, symmetry: Symmetry::None, }, + spawn_list: Vec::new(), } } @@ -109,6 +110,7 @@ impl DrunkardsWalkBuilder { brush_size: 1, symmetry: Symmetry::None, }, + spawn_list: Vec::new(), } } @@ -126,6 +128,7 @@ impl DrunkardsWalkBuilder { brush_size: 2, symmetry: Symmetry::None, }, + spawn_list: Vec::new(), } } @@ -143,6 +146,7 @@ impl DrunkardsWalkBuilder { brush_size: 1, symmetry: Symmetry::Both, }, + spawn_list: Vec::new(), } } @@ -242,5 +246,10 @@ impl DrunkardsWalkBuilder { // Noise map for spawning entities self.noise_areas = generate_voronoi_spawn_regions(&self.map, rng); + + // Spawn the entities + for area in self.noise_areas.iter() { + spawner::spawn_region(&self.map, rng, area.1, self.depth, &mut self.spawn_list); + } } } diff --git a/src/map_builders/maze.rs b/src/map_builders/maze.rs index f9d1d08..4f5341f 100644 --- a/src/map_builders/maze.rs +++ b/src/map_builders/maze.rs @@ -12,17 +12,13 @@ pub struct MazeBuilder { depth: i32, history: Vec, noise_areas: HashMap>, + spawn_list: Vec<(usize, String)>, } impl MapBuilder for MazeBuilder { fn build_map(&mut self, rng: &mut RandomNumberGenerator) { return self.build(rng); } - fn spawn_entities(&mut self, ecs: &mut World) { - for area in self.noise_areas.iter() { - spawner::spawn_region(ecs, area.1, self.depth); - } - } // Getters fn get_map(&mut self) -> Map { return self.map.clone(); @@ -30,6 +26,9 @@ impl MapBuilder for MazeBuilder { fn get_starting_pos(&mut self) -> Position { return self.starting_position.clone(); } + fn get_spawn_list(&self) -> &Vec<(usize, String)> { + return &self.spawn_list; + } // Mapgen visualisation stuff fn get_snapshot_history(&self) -> Vec { return self.history.clone(); @@ -53,6 +52,7 @@ impl MazeBuilder { depth: new_depth, history: Vec::new(), noise_areas: HashMap::new(), + spawn_list: Vec::new(), } } @@ -75,6 +75,11 @@ impl MazeBuilder { // Now we build a noise map for use in spawning entities later self.noise_areas = generate_voronoi_spawn_regions(&self.map, rng); + + // Spawn the entities + for area in self.noise_areas.iter() { + spawner::spawn_region(&self.map, rng, area.1, self.depth, &mut self.spawn_list); + } } } diff --git a/src/map_builders/mod.rs b/src/map_builders/mod.rs index 9c15ea5..5789b6b 100644 --- a/src/map_builders/mod.rs +++ b/src/map_builders/mod.rs @@ -16,6 +16,7 @@ mod simple_map; mod voronoi; use voronoi::VoronoiBuilder; mod prefab_builder; +use prefab_builder::PrefabBuilder; mod wfc; use common::*; use rltk::RandomNumberGenerator; @@ -24,9 +25,14 @@ use wfc::WaveFunctionCollapseBuilder; pub trait MapBuilder { fn build_map(&mut self, rng: &mut RandomNumberGenerator); - fn spawn_entities(&mut self, ecs: &mut World); + fn spawn_entities(&mut self, ecs: &mut World) { + for entity in self.get_spawn_list().iter() { + spawner::spawn_entity(ecs, &(&entity.0, &entity.1)); + } + } fn get_map(&mut self) -> Map; fn get_starting_pos(&mut self) -> Position; + fn get_spawn_list(&self) -> &Vec<(usize, String)>; fn get_snapshot_history(&self) -> Vec; fn take_snapshot(&mut self); } @@ -60,6 +66,14 @@ pub fn random_builder(new_depth: i32) -> Box { } result*/ - Box::new(prefab_builder::PrefabBuilder::new(new_depth)) - + Box::new( + PrefabBuilder::new( + new_depth, + Some( + Box::new( + CellularAutomataBuilder::new(new_depth) + ) + ) + ) + ) } diff --git a/src/map_builders/prefab_builder/mod.rs b/src/map_builders/prefab_builder/mod.rs index 4257d5b..56a805e 100644 --- a/src/map_builders/prefab_builder/mod.rs +++ b/src/map_builders/prefab_builder/mod.rs @@ -4,12 +4,14 @@ use super::{ use rltk::RandomNumberGenerator; use specs::prelude::*; mod prefab_levels; +mod prefab_sections; #[allow(dead_code)] #[derive(PartialEq, Clone)] pub enum PrefabMode { RexLevel { template: &'static str }, Constant { level: prefab_levels::PrefabLevel }, + Sectional { section: prefab_sections::PrefabSection }, } pub struct PrefabBuilder { @@ -19,6 +21,7 @@ pub struct PrefabBuilder { history: Vec, mode: PrefabMode, spawns: Vec<(usize, String)>, + previous_builder: Option>, } impl MapBuilder for PrefabBuilder { @@ -54,14 +57,15 @@ impl MapBuilder for PrefabBuilder { impl PrefabBuilder { #[allow(dead_code)] - pub fn new(new_depth: i32) -> PrefabBuilder { + pub fn new(new_depth: i32, previous_builder: Option>) -> PrefabBuilder { PrefabBuilder { map: Map::new(new_depth), starting_position: Position { x: 0, y: 0 }, depth: new_depth, history: Vec::new(), - mode: PrefabMode::Constant { level: prefab_levels::WFC_POPULATED }, + mode: PrefabMode::Sectional { section: prefab_sections::UNDERGROUND_FORT }, spawns: Vec::new(), + previous_builder, } } @@ -69,6 +73,7 @@ impl PrefabBuilder { match self.mode { PrefabMode::RexLevel { template } => self.load_rex_map(&template), PrefabMode::Constant { level } => self.load_ascii_map(&level), + PrefabMode::Sectional { section } => self.apply_sectional(§ion, rng), } self.take_snapshot(); @@ -92,6 +97,47 @@ impl PrefabBuilder { } } + pub fn apply_sectional(&mut self, section: &prefab_sections::PrefabSection, rng: &mut RandomNumberGenerator) { + // Build the map + let prev_builder = self.previous_builder.as_mut().unwrap(); + prev_builder.build_map(rng); + self.starting_position = prev_builder.get_starting_pos(); + self.map = prev_builder.get_map().clone(); + self.take_snapshot(); + + use prefab_sections::*; + + let string_vec = PrefabBuilder::read_ascii_to_vec(section.template); + + // Place the new section + let chunk_x; + match section.placement.0 { + HorizontalPlacement::Left => chunk_x = 0, + HorizontalPlacement::Center => chunk_x = (self.map.width / 2) - (section.width as i32 / 2), + HorizontalPlacement::Right => chunk_x = (self.map.width - 1) - section.width as i32, + } + + let chunk_y; + match section.placement.1 { + VerticalPlacement::Top => chunk_y = 0, + VerticalPlacement::Center => chunk_y = (self.map.height / 2) - (section.height as i32 / 2), + VerticalPlacement::Bottom => chunk_y = (self.map.height - 1) - section.height as i32, + } + println!("{},{}", chunk_x, chunk_y); + + let mut i = 0; + for ty in 0..section.height { + for tx in 0..section.width { + if tx < self.map.width as usize && ty < self.map.height as usize { + let idx = self.map.xy_idx(tx as i32 + chunk_x, ty as i32 + chunk_y); + self.char_to_map(string_vec[i], idx); + } + i += 1; + } + } + self.take_snapshot(); + } + fn char_to_map(&mut self, ch: char, idx: usize) { match ch { ' ' => self.map.tiles[idx] = TileType::Floor, @@ -105,23 +151,23 @@ impl PrefabBuilder { } 'g' => { self.map.tiles[idx] = TileType::Floor; - self.spawns.push((idx, "Goblin".to_string())); + self.spawns.push((idx, "goblin".to_string())); } 'o' => { self.map.tiles[idx] = TileType::Floor; - self.spawns.push((idx, "Orc".to_string())); + self.spawns.push((idx, "orc".to_string())); } '^' => { self.map.tiles[idx] = TileType::Floor; - self.spawns.push((idx, "Bear Trap".to_string())); + self.spawns.push((idx, "bear trap".to_string())); } '%' => { self.map.tiles[idx] = TileType::Floor; - self.spawns.push((idx, "Rations".to_string())); + self.spawns.push((idx, "rations".to_string())); } '!' => { self.map.tiles[idx] = TileType::Floor; - self.spawns.push((idx, "Health Potion".to_string())); + self.spawns.push((idx, "health potion".to_string())); } _ => { rltk::console::log(format!("Unknown glyph loading map: {}", (ch as u8) as char)); diff --git a/src/map_builders/prefab_builder/prefab_sections.rs b/src/map_builders/prefab_builder/prefab_sections.rs new file mode 100644 index 0000000..8e4d2ff --- /dev/null +++ b/src/map_builders/prefab_builder/prefab_sections.rs @@ -0,0 +1,79 @@ +#[allow(dead_code)] +#[derive(PartialEq, Copy, Clone)] +pub enum HorizontalPlacement { + Left, + Center, + Right, +} + +#[allow(dead_code)] +#[derive(PartialEq, Copy, Clone)] +pub enum VerticalPlacement { + Top, + Center, + Bottom, +} + +#[allow(dead_code)] +#[derive(PartialEq, Copy, Clone)] +pub struct PrefabSection { + pub template: &'static str, + pub width: usize, + pub height: usize, + pub placement: (HorizontalPlacement, VerticalPlacement), +} + +#[allow(dead_code)] +pub const UNDERGROUND_FORT: PrefabSection = PrefabSection { + template: RIGHT_FORT, + width: 15, + height: 43, + placement: (HorizontalPlacement::Right, VerticalPlacement::Top), +}; + +#[allow(dead_code)] +const RIGHT_FORT: &str = " +     # +  ####### +  #     # +  #     ####### +  #  g        # +  #     ####### +  #     # +  ### ### +    # # +    # # +    # ## +    ^ +    ^ +    # ## +    # # +    # # +    # # +    # # +  ### ### +  #     # +  #     # +  #  g  # +  #     # +  #     # +  ### ### +    # # +    # # +    # # +    # ## +    ^ +    ^ +    # ## +    # # +    # # +    # # +  ### ### +  #     # +  #     ####### +  #  g        # +  #     ####### +  #     # +  ####### +     # +"; diff --git a/src/map_builders/simple_map.rs b/src/map_builders/simple_map.rs index ee999fe..3294804 100644 --- a/src/map_builders/simple_map.rs +++ b/src/map_builders/simple_map.rs @@ -11,17 +11,13 @@ pub struct SimpleMapBuilder { depth: i32, rooms: Vec, history: Vec, + spawn_list: Vec<(usize, String)>, } impl MapBuilder for SimpleMapBuilder { fn build_map(&mut self, rng: &mut RandomNumberGenerator) { return self.rooms_and_corridors(rng); } - fn spawn_entities(&mut self, ecs: &mut World) { - for room in self.rooms.iter().skip(1) { - spawner::spawn_room(ecs, room, self.depth); - } - } // Getters fn get_map(&mut self) -> Map { return self.map.clone(); @@ -29,6 +25,9 @@ impl MapBuilder for SimpleMapBuilder { fn get_starting_pos(&mut self) -> Position { return self.starting_position.clone(); } + fn get_spawn_list(&self) -> &Vec<(usize, String)> { + return &self.spawn_list; + } // Mapgen visualisation stuff fn get_snapshot_history(&self) -> Vec { return self.history.clone(); @@ -52,6 +51,7 @@ impl SimpleMapBuilder { depth: new_depth, rooms: Vec::new(), history: Vec::new(), + spawn_list: Vec::new(), } } @@ -99,5 +99,10 @@ impl SimpleMapBuilder { let start_pos = self.rooms[0].centre(); self.starting_position = Position { x: start_pos.0, y: start_pos.1 }; + + // Spawn entities + for room in self.rooms.iter().skip(1) { + spawner::spawn_room(&self.map, rng, room, self.depth, &mut self.spawn_list); + } } } diff --git a/src/map_builders/voronoi.rs b/src/map_builders/voronoi.rs index 7bcfa42..71f87ce 100644 --- a/src/map_builders/voronoi.rs +++ b/src/map_builders/voronoi.rs @@ -21,17 +21,13 @@ pub struct VoronoiBuilder { noise_areas: HashMap>, n_seeds: usize, distance_algorithm: DistanceAlgorithm, + spawn_list: Vec<(usize, String)>, } impl MapBuilder for VoronoiBuilder { fn build_map(&mut self, rng: &mut RandomNumberGenerator) { return self.build(rng); } - fn spawn_entities(&mut self, ecs: &mut World) { - for area in self.noise_areas.iter() { - spawner::spawn_region(ecs, area.1, self.depth); - } - } // Getters fn get_map(&mut self) -> Map { return self.map.clone(); @@ -39,6 +35,9 @@ impl MapBuilder for VoronoiBuilder { fn get_starting_pos(&mut self) -> Position { return self.starting_position.clone(); } + fn get_spawn_list(&self) -> &Vec<(usize, String)> { + return &self.spawn_list; + } // Mapgen visualisation stuff fn get_snapshot_history(&self) -> Vec { return self.history.clone(); @@ -64,6 +63,7 @@ impl VoronoiBuilder { noise_areas: HashMap::new(), n_seeds: 64, distance_algorithm: DistanceAlgorithm::Pythagoras, + spawn_list: Vec::new(), } } pub fn manhattan(new_depth: i32) -> VoronoiBuilder { @@ -75,6 +75,7 @@ impl VoronoiBuilder { noise_areas: HashMap::new(), n_seeds: 64, distance_algorithm: DistanceAlgorithm::Manhattan, + spawn_list: Vec::new(), } } #[allow(dead_code)] @@ -87,6 +88,7 @@ impl VoronoiBuilder { noise_areas: HashMap::new(), n_seeds: 64, distance_algorithm: DistanceAlgorithm::Chebyshev, + spawn_list: Vec::new(), } } @@ -174,5 +176,10 @@ impl VoronoiBuilder { // Now we build a noise map for use in spawning entities later self.noise_areas = generate_voronoi_spawn_regions(&self.map, rng); + + // Spawn the entities + for area in self.noise_areas.iter() { + spawner::spawn_region(&self.map, rng, area.1, self.depth, &mut self.spawn_list); + } } } diff --git a/src/map_builders/wfc/mod.rs b/src/map_builders/wfc/mod.rs index d270880..9d6db4e 100644 --- a/src/map_builders/wfc/mod.rs +++ b/src/map_builders/wfc/mod.rs @@ -19,17 +19,13 @@ pub struct WaveFunctionCollapseBuilder { history: Vec, noise_areas: HashMap>, derive_from: Option>, + spawn_list: Vec<(usize, String)>, } impl MapBuilder for WaveFunctionCollapseBuilder { fn build_map(&mut self, rng: &mut RandomNumberGenerator) { return self.build(rng); } - fn spawn_entities(&mut self, ecs: &mut World) { - for area in self.noise_areas.iter() { - spawner::spawn_region(ecs, area.1, self.depth); - } - } // Getters fn get_map(&mut self) -> Map { return self.map.clone(); @@ -37,6 +33,9 @@ impl MapBuilder for WaveFunctionCollapseBuilder { fn get_starting_pos(&mut self) -> Position { return self.starting_position.clone(); } + fn get_spawn_list(&self) -> &Vec<(usize, String)> { + return &self.spawn_list; + } // Mapgen visualisation stuff fn get_snapshot_history(&self) -> Vec { return self.history.clone(); @@ -61,6 +60,7 @@ impl WaveFunctionCollapseBuilder { history: Vec::new(), noise_areas: HashMap::new(), derive_from, + spawn_list: Vec::new(), } } @@ -117,6 +117,11 @@ impl WaveFunctionCollapseBuilder { // Now we build a noise map for use in spawning entities later self.noise_areas = generate_voronoi_spawn_regions(&self.map, rng); + + // Spawn the entities + for area in self.noise_areas.iter() { + spawner::spawn_region(&self.map, rng, area.1, self.depth, &mut self.spawn_list); + } } fn render_tile_gallery(&mut self, constraints: &Vec, chunk_size: i32) { diff --git a/src/spawner.rs b/src/spawner.rs index 2d27a18..295fb8d 100644 --- a/src/spawner.rs +++ b/src/spawner.rs @@ -71,11 +71,17 @@ pub fn roll_hit_dice(ecs: &mut World, n: i32, d: i32) -> i32 { // Consts const MAX_ENTITIES: i32 = 2; -#[allow(clippy::map_entry)] -pub fn spawn_room(ecs: &mut World, room: &Rect, map_depth: i32) { +/// Fills a room with stuff! +pub fn spawn_room( + map: &Map, + rng: &mut RandomNumberGenerator, + room: &Rect, + map_depth: i32, + spawn_list: &mut Vec<(usize, String)>, +) { let mut possible_targets: Vec = Vec::new(); { - let map = ecs.fetch::(); + // Borrow scope - to keep access to the map separated for y in room.y1 + 1..room.y2 { for x in room.x1 + 1..room.x2 { let idx = map.xy_idx(x, y); @@ -86,38 +92,42 @@ pub fn spawn_room(ecs: &mut World, room: &Rect, map_depth: i32) { } } - spawn_region(ecs, &possible_targets, map_depth); + spawn_region(map, rng, &possible_targets, map_depth, spawn_list); } -pub fn spawn_region(ecs: &mut World, area: &[usize], map_depth: i32) { +pub fn spawn_region( + map: &Map, + rng: &mut RandomNumberGenerator, + area: &[usize], + map_depth: i32, + spawn_list: &mut Vec<(usize, String)>, +) { let mut spawn_points: HashMap = HashMap::new(); let mut areas: Vec = Vec::from(area); - { - let mut rng = ecs.write_resource::(); - let category = category_table().roll(&mut rng); - let spawn_table; - match category.as_ref() { - "mob" => spawn_table = mob_table(map_depth), - "item" => spawn_table = item_table(map_depth), - "food" => spawn_table = food_table(map_depth), - "trap" => spawn_table = trap_table(map_depth), - _ => spawn_table = debug_table(), - } - let num_spawns = i32::min(areas.len() as i32, rng.roll_dice(1, MAX_ENTITIES + 2) - 2); - if num_spawns <= 0 { - return; - } + let category = category_table().roll(rng); + let spawn_table; + match category.as_ref() { + "mob" => spawn_table = mob_table(map_depth), + "item" => spawn_table = item_table(map_depth), + "food" => spawn_table = food_table(map_depth), + "trap" => spawn_table = trap_table(map_depth), + _ => spawn_table = debug_table(), + } - for _i in 0..num_spawns { - let array_idx = if areas.len() == 1 { 0usize } else { (rng.roll_dice(1, areas.len() as i32) - 1) as usize }; - let map_idx = areas[array_idx]; - spawn_points.insert(map_idx, spawn_table.roll(&mut rng)); - areas.remove(array_idx); - } + let num_spawns = i32::min(areas.len() as i32, rng.roll_dice(1, MAX_ENTITIES + 2) - 2); + if num_spawns <= 0 { + return; + } + + for _i in 0..num_spawns { + let array_idx = if areas.len() == 1 { 0usize } else { (rng.roll_dice(1, areas.len() as i32) - 1) as usize }; + let map_idx = areas[array_idx]; + spawn_points.insert(map_idx, spawn_table.roll(rng)); + areas.remove(array_idx); } for spawn in spawn_points.iter() { - spawn_entity(ecs, &spawn); + spawn_list.push((*spawn.0, spawn.1.to_string())); } } @@ -154,7 +164,7 @@ pub fn spawn_entity(ecs: &mut World, spawn: &(&usize, &String)) { // Traps "bear trap" => bear_trap(ecs, x, y), "confusion trap" => confusion_trap(ecs, x, y), - _ => console::log("Tried to spawn nothing. Bugfix needed!"), + _ => console::log(format!("Tried to spawn nothing ({}). Bugfix needed!", spawn.1)), } }