From 5a4d8bc2340da835565387649aa4e59570e40dd8 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Mon, 3 Jan 2022 15:21:12 -0500 Subject: [PATCH] Add attributes to Player and NPCs --- raws/spawns.json | 174 +++++++++++----------------------------- src/components.rs | 26 ++++++ src/gamesystem.rs | 3 + src/main.rs | 2 + src/raws/mob_structs.rs | 9 +++ src/raws/rawmaster.rs | 21 +++++ src/saveload_system.rs | 2 + src/spawner.rs | 6 ++ 8 files changed, 117 insertions(+), 126 deletions(-) create mode 100644 src/gamesystem.rs diff --git a/raws/spawns.json b/raws/spawns.json index 6fd9508..036199d 100644 --- a/raws/spawns.json +++ b/raws/spawns.json @@ -258,14 +258,14 @@ "order": 1 }, "blocks_tile": true, - "stats": { - "max_hp": 16, - "hp": 16, - "defense": 1, - "power": 4 - }, "vision_range": 4, - "ai": "vendor" + "ai": "vendor", + "attributes": { + "intelligence": 13 + }, + "skills": { + "Melee": 2 + } }, { "name": "Shady Salesman", @@ -276,14 +276,9 @@ "order": 1 }, "blocks_tile": true, - "stats": { - "max_hp": 16, - "hp": 16, - "defense": 1, - "power": 4 - }, "vision_range": 4, - "ai": "vendor" + "ai": "vendor", + "attributes": {} }, { "name": "Patron", @@ -294,19 +289,14 @@ "order": 1 }, "blocks_tile": true, - "stats": { - "max_hp": 16, - "hp": 16, - "defense": 1, - "power": 4 - }, "vision_range": 4, "ai": "bystander", "quips": [ "Quiet down, it's too early!", "Oh my, I drank too much.", "Still saving the world, eh?" - ] + ], + "attributes": {} }, { "name": "Priest", @@ -317,14 +307,9 @@ "order": 1 }, "blocks_tile": true, - "stats": { - "max_hp": 16, - "hp": 16, - "defense": 1, - "power": 4 - }, "vision_range": 4, - "ai": "bystander" + "ai": "bystander", + "attributes": {} }, { "name": "Parishioner", @@ -335,19 +320,14 @@ "order": 1 }, "blocks_tile": true, - "stats": { - "max_hp": 16, - "hp": 16, - "defense": 1, - "power": 4 - }, "vision_range": 4, "ai": "bystander", "quips": [ "Great to see a new face here!", "I hear there's going to be a good sermon on tea", "Want some cake?" - ] + ], + "attributes": {} }, { "name": "Blacksmith", @@ -358,14 +338,9 @@ "order": 1 }, "blocks_tile": true, - "stats": { - "max_hp": 16, - "hp": 16, - "defense": 1, - "power": 4 - }, "vision_range": 4, - "ai": "vendor" + "ai": "vendor", + "attributes": {} }, { "name": "Clothier", @@ -376,14 +351,9 @@ "order": 1 }, "blocks_tile": true, - "stats": { - "max_hp": 16, - "hp": 16, - "defense": 1, - "power": 4 - }, "vision_range": 4, - "ai": "vendor" + "ai": "vendor", + "attributes": {} }, { "name": "Alchemist", @@ -394,14 +364,9 @@ "order": 1 }, "blocks_tile": true, - "stats": { - "max_hp": 16, - "hp": 16, - "defense": 1, - "power": 4 - }, "vision_range": 4, - "ai": "vendor" + "ai": "vendor", + "attributes": {} }, { "name": "Mom", @@ -412,12 +377,6 @@ "order": 1 }, "blocks_tile": true, - "stats": { - "max_hp": 16, - "hp": 16, - "defense": 1, - "power": 4 - }, "vision_range": 4, "ai": "bystander", "quips": [ @@ -425,7 +384,8 @@ "Off saving the world again?", "Be careful in the dungeon!", "Your father would be so proud, were he here." - ] + ], + "attributes": {} }, { "name": "Peasant", @@ -436,17 +396,12 @@ "order": 1 }, "blocks_tile": true, - "stats": { - "max_hp": 16, - "hp": 16, - "defense": 1, - "power": 4 - }, "vision_range": 4, "ai": "bystander", "quips": [ "Why are you in my house?" - ] + ], + "attributes": {} }, { "name": "Dock Worker", @@ -457,19 +412,14 @@ "order": 1 }, "blocks_tile": true, - "stats": { - "max_hp": 16, - "hp": 16, - "defense": 1, - "power": 4 - }, "vision_range": 4, "ai": "bystander", "quips": [ "Lovely day, eh?", "Nice weather", "Hello" - ] + ], + "attributes": {} }, { "name": "Fisher", @@ -480,19 +430,14 @@ "order": 1 }, "blocks_tile": true, - "stats": { - "max_hp": 16, - "hp": 16, - "defense": 1, - "power": 4 - }, "vision_range": 4, "ai": "bystander", "quips": [ "They're biting today!", "I caught something, but it wasn't a fish!", "Looks like rain" - ] + ], + "attributes": {} }, { "name": "Wannabe Pirate", @@ -503,19 +448,14 @@ "order": 1 }, "blocks_tile": true, - "stats": { - "max_hp": 16, - "hp": 16, - "defense": 1, - "power": 4 - }, "vision_range": 4, "ai": "bystander", "quips": [ "Arrr", "Grog!", "Booze!" - ] + ], + "attributes": {} }, { "name": "Drunk", @@ -526,19 +466,14 @@ "order": 1 }, "blocks_tile": true, - "stats": { - "max_hp": 16, - "hp": 16, - "defense": 1, - "power": 4 - }, "vision_range": 4, "ai": "bystander", "quips": [ "Hic", "Need... more... booze!", "Spare a copper?" - ] + ], + "attributes": {} }, { "name": "Rat", @@ -549,14 +484,16 @@ "order": 1 }, "blocks_tile": true, - "stats": { - "max_hp": 2, - "hp": 2, - "defense": 1, - "power": 3 - }, "vision_range": 8, - "ai": "melee" + "ai": "melee", + "attributes": { + "Might": 3, + "Fitness": 3 + }, + "skills": { + "Melee": -1, + "Defense": -1 + } }, { "name": "Orc", @@ -567,14 +504,9 @@ "order": 1 }, "blocks_tile": true, - "stats": { - "max_hp": 16, - "hp": 16, - "defense": 1, - "power": 4 - }, "vision_range": 8, - "ai": "melee" + "ai": "melee", + "attributes": {} }, { "name": "Goblin", @@ -585,14 +517,9 @@ "order": 1 }, "blocks_tile": true, - "stats": { - "max_hp": 8, - "hp": 8, - "defense": 1, - "power": 3 - }, "vision_range": 8, - "ai": "melee" + "ai": "melee", + "attributes": {} }, { "name": "Kobold", @@ -603,14 +530,9 @@ "order": 1 }, "blocks_tile": true, - "stats": { - "max_hp": 4, - "hp": 4, - "defense": 0, - "power": 2 - }, "vision_range": 4, - "ai": "melee" + "ai": "melee", + "attributes": {} } ], "props": [ diff --git a/src/components.rs b/src/components.rs index 8d5d411..9bf44de 100644 --- a/src/components.rs +++ b/src/components.rs @@ -1,3 +1,4 @@ +use crate::gamesystem::attr_bonus; use ::rltk::{Point, RGB}; use ::serde::{Deserialize, Serialize}; use ::specs::error::NoError; @@ -248,6 +249,31 @@ pub struct Quips { pub available: Vec, } +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct Attribute { + pub base: i32, + pub modifiers: i32, + pub bonus: i32, +} + +impl Attribute { + pub fn new(base: i32) -> Self { + Attribute { + base, + modifiers: 0, + bonus: attr_bonus(base), + } + } +} + +#[derive(Component, Debug, Serialize, Deserialize, Clone)] +pub struct Attributes { + pub might: Attribute, + pub fitness: Attribute, + pub quickness: Attribute, + pub intelligence: Attribute, +} + // Serialization helper code. We need to implement ConvertSaveLoad for each type that contains an // Entity. diff --git a/src/gamesystem.rs b/src/gamesystem.rs new file mode 100644 index 0000000..06f83c4 --- /dev/null +++ b/src/gamesystem.rs @@ -0,0 +1,3 @@ +pub fn attr_bonus(value: i32) -> i32 { + (value - 10) / 2 // See: https://roll20.net/compendium/dnd5e/Ability%20Scores#content +} diff --git a/src/main.rs b/src/main.rs index 301229e..cc79b95 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ pub mod camera; mod components; mod damage_system; mod game_log; +mod gamesystem; mod gui; mod hunger_system; mod inventory_system; @@ -541,6 +542,7 @@ fn main() -> ::rltk::BError { Bystander, Vendor, Quips, + Attributes, ); gs.ecs.insert(SimpleMarkerAllocator::::new()); diff --git a/src/raws/mob_structs.rs b/src/raws/mob_structs.rs index 6b1eab8..2c2ae77 100644 --- a/src/raws/mob_structs.rs +++ b/src/raws/mob_structs.rs @@ -11,6 +11,7 @@ pub struct Mob { pub vision_range: i32, pub ai: String, pub quips: Option>, + pub attributes: MobAttributes, } #[derive(Deserialize, Debug)] @@ -20,3 +21,11 @@ pub struct MobStats { pub power: i32, pub defense: i32, } + +#[derive(Deserialize, Debug)] +pub struct MobAttributes { + pub might: Option, + pub fitness: Option, + pub quickness: Option, + pub intelligence: Option, +} diff --git a/src/raws/rawmaster.rs b/src/raws/rawmaster.rs index e1737c1..46b0672 100644 --- a/src/raws/rawmaster.rs +++ b/src/raws/rawmaster.rs @@ -226,6 +226,27 @@ pub fn spawn_named_mob( }); } + let mut attr = Attributes { + might: Attribute::new(11), + fitness: Attribute::new(11), + quickness: Attribute::new(11), + intelligence: Attribute::new(11), + }; + if let Some(might) = mob_template.attributes.might { + attr.might = Attribute::new(might); + } + if let Some(fitness) = mob_template.attributes.fitness { + attr.fitness = Attribute::new(fitness); + } + if let Some(quickness) = mob_template.attributes.quickness { + attr.quickness = Attribute::new(quickness); + } + if let Some(intelligence) = mob_template.attributes.intelligence { + attr.intelligence = Attribute::new(intelligence); + } + + eb = eb.with(attr); + if mob_template.blocks_tile { eb = eb.with(BlocksTile {}); } diff --git a/src/saveload_system.rs b/src/saveload_system.rs index 00b43fc..303b341 100644 --- a/src/saveload_system.rs +++ b/src/saveload_system.rs @@ -92,6 +92,7 @@ pub fn save_game(ecs: &mut World) { Bystander, Vendor, Quips, + Attributes, ); } @@ -186,6 +187,7 @@ pub fn load_game(ecs: &mut World) { Bystander, Vendor, Quips, + Attributes, ); } diff --git a/src/spawner.rs b/src/spawner.rs index 651dedb..9287cde 100644 --- a/src/spawner.rs +++ b/src/spawner.rs @@ -35,6 +35,12 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity { state: HungerState::WellFed, duration: 20, }) + .with(Attributes { + might: Attribute::new(11), + fitness: Attribute::new(11), + quickness: Attribute::new(11), + intelligence: Attribute::new(11), + }) .marked::>() .build() }