diff options
| author | troido <troido@protonmail.com> | 2020-03-05 12:50:25 +0100 |
|---|---|---|
| committer | troido <troido@protonmail.com> | 2020-03-05 12:50:25 +0100 |
| commit | 170741fe959d30ee43ce689fd5fbae725cc1dae4 (patch) | |
| tree | de337876fb9afc3ca20e5a99ef61689813f51ebe /src/components | |
| parent | ea99b86b89659624133a63f03600f0b57592a5f4 (diff) | |
equipent now kinda works
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/equipment.rs | 164 | ||||
| -rw-r--r-- | src/components/interactable.rs | 20 | ||||
| -rw-r--r-- | src/components/item.rs | 28 | ||||
| -rw-r--r-- | src/components/messages.rs | 8 | ||||
| -rw-r--r-- | src/components/mod.rs | 21 |
5 files changed, 223 insertions, 18 deletions
diff --git a/src/components/equipment.rs b/src/components/equipment.rs new file mode 100644 index 0000000..1d86e95 --- /dev/null +++ b/src/components/equipment.rs @@ -0,0 +1,164 @@ + +use std::collections::HashMap; +use serde_json::{json, Value}; +use specs::{ + Component, + HashMapStorage +}; + + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum Slot { + Hand, + Body +} + +impl Slot { + pub fn from_str(txt: &str) -> Option<Self> { + match txt { + "hand" => Some(Self::Hand), + "body" => Some(Self::Body), + _ => None + } + } + pub fn to_string(&self) -> String { + match self { + Self::Hand => "hand", + Self::Body => "body" + }.to_string() + } +} + + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum Stat { + Strength, + Defence +} + +impl Stat { + pub fn from_str(txt: &str) -> Option<Self> { + match txt { + "strength" => Some(Self::Strength), + "defence" => Some(Self::Defence), + _ => None + } + } + pub fn to_string(&self) -> String { + match self { + Self::Strength => "strength", + Self::Defence => "defence" + }.to_string() + } +} + + +#[derive(Debug, Clone, PartialEq)] +pub struct Equippable { + pub slot: Slot, + pub stats: HashMap<Stat, i64> +} + +impl Equippable { + pub fn from_json(val: &Value) -> Option<Self> { + Some(Equippable{ + slot: Slot::from_str(val.get("slot")?.as_str()?)?, + stats: val + .get("stats")? + .as_object()? + .into_iter() + .map(|(k, v)| + Some((Stat::from_str(k.as_str())?, v.as_i64()?)) + ) + .collect::<Option<HashMap<Stat, i64>>>()? + }) + } + pub fn to_json(&self) -> Value { + json!({ + "slot": self.slot.to_string(), + "stats": self.stats.iter().map(|(k, v)| (k.to_string(), *v)).collect::<HashMap<String, i64>>() + }) + } +} + + + +#[derive(Component, Debug, Clone)] +#[storage(HashMapStorage)] +pub struct Equipment { + pub equipment: HashMap<Slot, Option<Equippable>> +} + +impl Equipment { + pub fn get_bonus(&self, stat: Stat) -> i64 { + let mut bonus = 0; + for v in self.equipment.values() { + if let Some(equippable) = v { + if let Some(s) = equippable.stats.get(&stat) { + bonus += s; + } + } + } + bonus + } + pub fn all_bonuses(&self) -> HashMap<Stat, i64> { + let mut bonuses: HashMap<Stat, i64> = HashMap::new(); + for v in self.equipment.values() { + if let Some(equippable) = v { + for (stat, s) in equippable.stats.iter(){ + let current: i64 = *bonuses.entry(*stat).or_insert(0); + bonuses.insert(*stat, current + s); + } + } + } + bonuses + } +} + + +#[cfg(test)] +mod tests { + use super::*; + use crate::hashmap; + + + #[test] + fn slots() { + assert_eq!(Slot::from_str("hand"), Some(Slot::Hand)); + assert_eq!(Slot::from_str("body"), Some(Slot::Body)); + assert_eq!(Slot::from_str("hands"), None); + assert_eq!(Slot::from_str("head"), None); + } + + #[test] + fn stats() { + assert_eq!(Stat::from_str("strength"), Some(Stat::Strength)); + assert_eq!(Stat::from_str("defence"), Some(Stat::Defence)); + assert_eq!(Stat::from_str("hand"), None); + assert_eq!(Stat::from_str("body"), None); + assert_eq!(Stat::from_str("attack"), None); + } + + #[test] + fn equippable_from_json() { + assert_eq!( + Equippable::from_json(&json!({"slot": "hand", "stats": {"strength": 10}})), + Some(Equippable {slot: Slot::Hand, stats: hashmap!(Stat::Strength => 10)}) + ); + } + + + #[test] + fn bonus_value() { + assert_eq!( + Equipment{equipment: hashmap!( + Slot::Hand => Some(Equippable{ + slot: Slot::Hand, + stats: hashmap!(Stat::Strength => 15) + }), + Slot::Body => None + )}.get_bonus(Stat::Strength), + 15 + ); + } +} diff --git a/src/components/interactable.rs b/src/components/interactable.rs new file mode 100644 index 0000000..f6ce8c4 --- /dev/null +++ b/src/components/interactable.rs @@ -0,0 +1,20 @@ + +use specs::{ + Component, + HashMapStorage +}; + +#[derive(Component, Debug, Clone, PartialEq, Eq)] +#[storage(HashMapStorage)] +pub enum Interactable { + Harvest +} + +impl Interactable { + pub fn from_str(txt: &str) -> Option<Interactable> { + match txt { + "harvest" => Some(Interactable::Harvest), + _ => None + } + } +} diff --git a/src/components/item.rs b/src/components/item.rs index bcc672a..9e61567 100644 --- a/src/components/item.rs +++ b/src/components/item.rs @@ -2,6 +2,8 @@ use specs::{Component, DenseVecStorage}; use crate::{Template}; +use super::equipment::Equippable; + #[derive(Component, Debug, Clone)] pub struct Item { pub ent: Template, @@ -17,16 +19,18 @@ use serde_json::{json, Value}; pub enum ItemAction { Eat(i64), Build(Template), + Equip(Equippable), None } -use ItemAction::{Eat, Build, None}; +use ItemAction::{Eat, Build, Equip, None}; impl ItemAction { pub fn to_json(&self) -> Value { match self { Eat(health) => json!(["eat", health]), Build(template) => json!(["build", template.to_json()]), + Equip(equippable) => json!(["equip", equippable.to_json()]), None => json!(["none", null]) } } @@ -38,7 +42,29 @@ impl ItemAction { "eat" => Eat(arg.as_i64()?), "build" => Build(Template::from_json(arg).ok()?), "none" => None, + "equip" => Equip(Equippable::from_json(arg)?), _ => {return Option::None} }) } } + + +#[cfg(test)] +mod tests { + use super::*; + use crate::hashmap; + use super::super::equipment::*; + + #[test] + fn equip_from_json() { + assert_eq!( + ItemAction::from_json(&json!(["equip", {"slot": "hand", "stats": {"strength": 10}}])), + Some(ItemAction::Equip(Equippable {slot: Slot::Hand, stats: hashmap!(Stat::Strength => 10)})) + ); + assert_eq!( + ItemAction::from_json(&json!(["equip", {"slot": "hand", "stats": {"attack": 50}}])), + Option::None + ); + } +} + diff --git a/src/components/messages.rs b/src/components/messages.rs index ae615f1..8fe38e3 100644 --- a/src/components/messages.rs +++ b/src/components/messages.rs @@ -1,4 +1,5 @@ +use std::collections::HashMap; use std::any::Any; use specs::{ Component, @@ -6,6 +7,7 @@ use specs::{ Entity, WriteStorage }; +use super::equipment::Stat; @@ -46,6 +48,12 @@ impl AttackType { Self::Heal(_) => false } } + pub fn apply_bonuses(self, bonuses: &HashMap<Stat, i64>) -> AttackType { + match self { + Self::Attack(strength) => Self::Attack(strength + *bonuses.get(&Stat::Strength).unwrap_or(&0)), + Self::Heal(_) => self + } + } } #[derive(Debug, Clone)] diff --git a/src/components/mod.rs b/src/components/mod.rs index ac6c9e6..5dd83bd 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -2,6 +2,8 @@ pub mod item; pub mod messages; pub mod faction; +pub mod interactable; +pub mod equipment; pub use item::Item; pub use messages::{ @@ -10,6 +12,8 @@ pub use messages::{ AttackType }; pub use faction::Faction; +pub use interactable::Interactable; +pub use equipment::Equipment; use specs::{ DenseVecStorage, @@ -216,20 +220,6 @@ pub struct Clan { pub name: String, } -#[derive(Component, Debug, Clone, PartialEq, Eq)] -#[storage(HashMapStorage)] -pub enum Interactable { - Harvest -} - -impl Interactable { - pub fn from_str(txt: &str) -> Option<Interactable> { - match txt { - "harvest" => Some(Interactable::Harvest), - _ => None - } - } -} #[derive(Component, Debug, Clone)] #[storage(HashMapStorage)] @@ -247,6 +237,3 @@ pub struct Grow { } - - - |
