Replace individual spawners with data-driven ones
This commit is contained in:
parent
269cf501cf
commit
e92160244a
21
src/main.rs
21
src/main.rs
@ -47,10 +47,7 @@ impl State {
|
||||
let exit_idx = map_builder.map.point2d_to_index(map_builder.amulet_start);
|
||||
map_builder.map.tiles[exit_idx] = TileType::Exit;
|
||||
|
||||
map_builder
|
||||
.monster_spawns
|
||||
.iter()
|
||||
.for_each(|pos| spawn_entity(&mut ecs, &mut rng, *pos));
|
||||
spawn_level(&mut ecs, &mut rng, 0, &map_builder.monster_spawns);
|
||||
|
||||
resources.insert(map_builder.map);
|
||||
resources.insert(Camera::new(map_builder.player_start));
|
||||
@ -78,10 +75,7 @@ impl State {
|
||||
let exit_idx = map_builder.map.point2d_to_index(map_builder.amulet_start);
|
||||
map_builder.map.tiles[exit_idx] = TileType::Exit;
|
||||
|
||||
map_builder
|
||||
.monster_spawns
|
||||
.iter()
|
||||
.for_each(|pos| spawn_entity(&mut self.ecs, &mut rng, *pos));
|
||||
spawn_level(&mut self.ecs, &mut rng, 0, &map_builder.monster_spawns);
|
||||
|
||||
self.resources.insert(map_builder.map);
|
||||
self.resources.insert(Camera::new(map_builder.player_start));
|
||||
@ -189,10 +183,13 @@ impl State {
|
||||
map_builder.map.tiles[exit_idx] = TileType::Exit;
|
||||
}
|
||||
|
||||
map_builder
|
||||
.monster_spawns
|
||||
.iter()
|
||||
.for_each(|pos| spawn_entity(&mut self.ecs, &mut rng, *pos));
|
||||
spawn_level(
|
||||
&mut self.ecs,
|
||||
&mut rng,
|
||||
map_level as usize,
|
||||
&map_builder.monster_spawns,
|
||||
);
|
||||
|
||||
self.resources.insert(map_builder.map);
|
||||
self.resources.insert(Camera::new(map_builder.player_start));
|
||||
self.resources.insert(TurnState::AwaitingInput);
|
||||
|
@ -1,97 +0,0 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
pub fn spawn_player(ecs: &mut World, pos: Point) {
|
||||
ecs.push((
|
||||
Player { map_level: 0 },
|
||||
pos,
|
||||
Render {
|
||||
color: ColorPair::new(WHITE, BLACK),
|
||||
glyph: to_cp437('@'),
|
||||
},
|
||||
Health {
|
||||
current: 10,
|
||||
max: 10,
|
||||
},
|
||||
Name("Player 1".to_string()),
|
||||
FieldOfView::new(8),
|
||||
));
|
||||
}
|
||||
|
||||
pub fn spawn_monster(ecs: &mut World, rng: &mut RandomNumberGenerator, pos: Point) {
|
||||
let (hp, name, glyph) = match rng.roll_dice(1, 10) {
|
||||
1..=8 => goblin(),
|
||||
_ => orc(),
|
||||
};
|
||||
|
||||
ecs.push((
|
||||
Enemy,
|
||||
pos,
|
||||
Render {
|
||||
color: ColorPair::new(WHITE, BLACK),
|
||||
glyph,
|
||||
},
|
||||
ChasingPlayer,
|
||||
Health {
|
||||
current: hp,
|
||||
max: hp,
|
||||
},
|
||||
Name(name),
|
||||
FieldOfView::new(6),
|
||||
));
|
||||
}
|
||||
|
||||
pub fn spawn_amulet_of_yala(ecs: &mut World, pos: Point) {
|
||||
ecs.push((
|
||||
Item,
|
||||
AmuletOfYala,
|
||||
pos,
|
||||
Render {
|
||||
color: ColorPair::new(WHITE, BLACK),
|
||||
glyph: to_cp437('|'),
|
||||
},
|
||||
Name("Amulet of Yala".to_string()),
|
||||
));
|
||||
}
|
||||
|
||||
pub fn spawn_healing_potion(ecs: &mut World, pos: Point) {
|
||||
ecs.push((
|
||||
Item,
|
||||
pos,
|
||||
Render {
|
||||
color: ColorPair::new(WHITE, BLACK),
|
||||
glyph: to_cp437('!'),
|
||||
},
|
||||
Name("Healing Potion".to_string()),
|
||||
ProvidesHealing { amount: 6 },
|
||||
));
|
||||
}
|
||||
|
||||
pub fn spawn_magic_mapper(ecs: &mut World, pos: Point) {
|
||||
ecs.push((
|
||||
Item,
|
||||
pos,
|
||||
Render {
|
||||
color: ColorPair::new(WHITE, BLACK),
|
||||
glyph: to_cp437('{'),
|
||||
},
|
||||
Name("Dungeon Map".to_string()),
|
||||
ProvidesDungeonMap,
|
||||
));
|
||||
}
|
||||
|
||||
pub fn spawn_entity(ecs: &mut World, rng: &mut RandomNumberGenerator, pos: Point) {
|
||||
let roll = rng.roll_dice(1, 6);
|
||||
match roll {
|
||||
1 => spawn_healing_potion(ecs, pos),
|
||||
2 => spawn_magic_mapper(ecs, pos),
|
||||
_ => spawn_monster(ecs, rng, pos),
|
||||
}
|
||||
}
|
||||
|
||||
fn goblin() -> (i32, String, FontCharType) {
|
||||
(1, "Goblin".to_string(), to_cp437('g'))
|
||||
}
|
||||
|
||||
fn orc() -> (i32, String, FontCharType) {
|
||||
(2, "Orc".to_string(), to_cp437('o'))
|
||||
}
|
44
src/spawner/mod.rs
Normal file
44
src/spawner/mod.rs
Normal file
@ -0,0 +1,44 @@
|
||||
mod template;
|
||||
|
||||
use crate::prelude::*;
|
||||
use template::Templates;
|
||||
|
||||
pub fn spawn_player(ecs: &mut World, pos: Point) {
|
||||
ecs.push((
|
||||
Player { map_level: 0 },
|
||||
pos,
|
||||
Render {
|
||||
color: ColorPair::new(WHITE, BLACK),
|
||||
glyph: to_cp437('@'),
|
||||
},
|
||||
Health {
|
||||
current: 10,
|
||||
max: 10,
|
||||
},
|
||||
Name("Player 1".to_string()),
|
||||
FieldOfView::new(8),
|
||||
));
|
||||
}
|
||||
|
||||
pub fn spawn_amulet_of_yala(ecs: &mut World, pos: Point) {
|
||||
ecs.push((
|
||||
Item,
|
||||
AmuletOfYala,
|
||||
pos,
|
||||
Render {
|
||||
color: ColorPair::new(WHITE, BLACK),
|
||||
glyph: to_cp437('|'),
|
||||
},
|
||||
Name("Amulet of Yala".to_string()),
|
||||
));
|
||||
}
|
||||
|
||||
pub fn spawn_level(
|
||||
ecs: &mut World,
|
||||
rng: &mut RandomNumberGenerator,
|
||||
level: usize,
|
||||
spawn_points: &[Point],
|
||||
) {
|
||||
let template = Templates::load();
|
||||
template.spawn_entities(ecs, rng, level, spawn_points);
|
||||
}
|
99
src/spawner/template.rs
Normal file
99
src/spawner/template.rs
Normal file
@ -0,0 +1,99 @@
|
||||
use crate::prelude::*;
|
||||
use legion::systems::CommandBuffer;
|
||||
use ron::de::from_reader;
|
||||
use serde::Deserialize;
|
||||
use std::collections::HashSet;
|
||||
use std::fs::File;
|
||||
|
||||
#[derive(Clone, Deserialize, Debug)]
|
||||
pub struct Template {
|
||||
pub entity_type: EntityType,
|
||||
pub levels: HashSet<usize>,
|
||||
pub frequency: i32,
|
||||
pub name: String,
|
||||
pub glyph: char,
|
||||
pub provides: Option<Vec<(String, i32)>>,
|
||||
pub hp: Option<i32>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Debug, PartialEq)]
|
||||
pub enum EntityType {
|
||||
Enemy,
|
||||
Item,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Debug)]
|
||||
pub struct Templates {
|
||||
pub entities: Vec<Template>,
|
||||
}
|
||||
|
||||
impl Templates {
|
||||
pub fn load() -> Self {
|
||||
let file = File::open("resources/template.ron").expect("Failed opening file");
|
||||
from_reader(file).expect("Unable to load templates")
|
||||
}
|
||||
|
||||
pub fn spawn_entities(
|
||||
&self,
|
||||
ecs: &mut World,
|
||||
rng: &mut RandomNumberGenerator,
|
||||
level: usize,
|
||||
spawn_points: &[Point],
|
||||
) {
|
||||
let mut available_entities = Vec::new();
|
||||
self.entities
|
||||
.iter()
|
||||
.filter(|e| e.levels.contains(&level))
|
||||
.for_each(|t| {
|
||||
for _ in 0..t.frequency {
|
||||
available_entities.push(t);
|
||||
}
|
||||
});
|
||||
|
||||
let mut commands = CommandBuffer::new(ecs);
|
||||
spawn_points.iter().for_each(|pt| {
|
||||
if let Some(entity) = rng.random_slice_entry(&available_entities) {
|
||||
self.spawn_entity(pt, entity, &mut commands);
|
||||
}
|
||||
});
|
||||
|
||||
commands.flush(ecs);
|
||||
}
|
||||
|
||||
fn spawn_entity(&self, pt: &Point, template: &Template, commands: &mut CommandBuffer) {
|
||||
let entity = commands.push((
|
||||
pt.clone(),
|
||||
Render {
|
||||
color: ColorPair::new(WHITE, BLACK),
|
||||
glyph: to_cp437(template.glyph),
|
||||
},
|
||||
Name(template.name.clone()),
|
||||
));
|
||||
|
||||
match template.entity_type {
|
||||
EntityType::Item => commands.add_component(entity, Item),
|
||||
EntityType::Enemy => {
|
||||
commands.add_component(entity, Enemy);
|
||||
commands.add_component(entity, FieldOfView::new(6));
|
||||
commands.add_component(entity, ChasingPlayer);
|
||||
commands.add_component(
|
||||
entity,
|
||||
Health {
|
||||
current: template.hp.unwrap(),
|
||||
max: template.hp.unwrap(),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(effects) = &template.provides {
|
||||
effects
|
||||
.iter()
|
||||
.for_each(|(provides, n)| match provides.as_str() {
|
||||
"Healing" => commands.add_component(entity, ProvidesHealing { amount: *n }),
|
||||
"MagicMap" => commands.add_component(entity, ProvidesDungeonMap),
|
||||
_ => println!("Warning: we don't know how to provide {}", provides),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user