diff --git a/Cargo.lock b/Cargo.lock index 49be6f0..1479d90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,6 +60,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "base64" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + [[package]] name = "bit-set" version = "0.5.2" @@ -556,6 +562,8 @@ version = "0.1.0" dependencies = [ "bracket-lib", "legion", + "ron", + "serde", ] [[package]] @@ -1432,6 +1440,17 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +[[package]] +name = "ron" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a9d94cee22c8a4b5e2a1c7f9a20fdc315668ee8a75835949bb40d7456934634" +dependencies = [ + "base64", + "bitflags", + "serde", +] + [[package]] name = "rusttype" version = "0.9.2" @@ -1480,18 +1499,18 @@ checksum = "a0eddf2e8f50ced781f288c19f18621fa72a3779e3cb58dbf23b07469b0abeb4" [[package]] name = "serde" -version = "1.0.129" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1f72836d2aa753853178eda473a3b9d8e4eefdaf20523b919677e6de489f8f1" +checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.129" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e57ae87ad533d9a56427558b516d0adac283614e347abf85b0dc0cbbf0a249f3" +checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index fc0b7d8..4abd1fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,6 @@ edition = "2018" [dependencies] bracket-lib = "~0.8.1" -legion = "~0.3.1" \ No newline at end of file +legion = "~0.3.1" +serde = { version = "=1.0.115"} +ron = "=0.6.1" \ No newline at end of file diff --git a/resources/template.ron b/resources/template.ron new file mode 100644 index 0000000..d2964ab --- /dev/null +++ b/resources/template.ron @@ -0,0 +1,64 @@ +Templates( + entities: [ + Template( + entity_type: Item, + name: "Healing Potion", + glyph: '!', + levels : [0,1,2], + provides: Some([("Healing", 6)]), + frequency: 2 + ), + Template( + entity_type: Item, + name: "Dungoen Map", + glyph: '{', + levels : [0, 1, 2], + provides: Some([("MagicMap", 0)]), + frequency: 1 + ), + Template( + entity_type: Enemy, + name: "Goblin", + glyph: 'g', + levels : [0, 1, 2], + hp: Some(1), + frequency: 3, + base_damage: Some(1) + ), + Template( + entity_type: Enemy, + name: "Orc", + glyph: 'o', + levels : [0, 1, 2], + hp: Some(2), + frequency: 2, + base_damage: Some(1) + ), + Template( + entity_type: Enemy, + name: "Ogre", + glyph: 'O', + levels : [1, 2], + hp: Some(5), + frequency: 1, + base_damage: Some(2) + ), + Template( + entity_type: Enemy, + name: "Ettin", + glyph: 'E', + levels : [2], + hp: Some(10), + frequency: 2, + base_damage: Some(3) + ), + Template( + entity_type: Item, + name : "Rusty Sword", + glyph: '/', + levels : [0,1,2], + frequency: 2, + base_damage: Some(2) + ) + ] +) \ No newline at end of file diff --git a/src/components.rs b/src/components.rs index f060405..357f056 100644 --- a/src/components.rs +++ b/src/components.rs @@ -87,3 +87,9 @@ pub struct ActivateItem { pub used_by: Entity, pub item: Entity, } + +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Damage(pub i32); + +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Weapon; diff --git a/src/main.rs b/src/main.rs index f872a06..3e536b2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -79,12 +79,12 @@ 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, + 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); @@ -101,10 +101,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)); resources.insert(TurnState::AwaitingInput); @@ -153,10 +150,7 @@ impl State { //spawn_amulet_of_yala(&mut self.ecs, map_builder.amulet_start); 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)); self.resources.insert(TurnState::AwaitingInput); diff --git a/src/spawners.rs b/src/spawners.rs deleted file mode 100644 index b7cbf34..0000000 --- a/src/spawners.rs +++ /dev/null @@ -1,93 +0,0 @@ -pub 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, - }, - 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), - )); -} - -fn goblin() -> (i32, String, FontCharType) { - (1, "Goblin".to_string(), to_cp437('g')) -} -fn orc() -> (i32, String, FontCharType) { - (2, "orc".to_string(), to_cp437('o')) -} - -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("Magic 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), - } -} diff --git a/src/spawners/mod.rs b/src/spawners/mod.rs new file mode 100644 index 0000000..4ceafe5 --- /dev/null +++ b/src/spawners/mod.rs @@ -0,0 +1,44 @@ +mod template; +use template::*; + +pub use crate::prelude::*; + +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); +} + +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, + }, + FieldOfView::new(8), + Damage(1), + )); +} + +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()), + )); +} diff --git a/src/spawners/template.rs b/src/spawners/template.rs new file mode 100644 index 0000000..50cf7b5 --- /dev/null +++ b/src/spawners/template.rs @@ -0,0 +1,107 @@ +pub 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, + pub frequency: i32, + pub name: String, + pub glyph: char, + pub provides: Option>, + pub hp: Option, + pub base_damage: Option, +} + +#[derive(Clone, Deserialize, Debug, PartialEq)] +pub enum EntityType { + Enemy, + Item, +} + +#[derive(Clone, Deserialize, Debug)] +pub struct Templates { + pub entities: Vec