summaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
authortroido <troido@protonmail.com>2020-03-05 12:50:25 +0100
committertroido <troido@protonmail.com>2020-03-05 12:50:25 +0100
commit170741fe959d30ee43ce689fd5fbae725cc1dae4 (patch)
treede337876fb9afc3ca20e5a99ef61689813f51ebe /src/components
parentea99b86b89659624133a63f03600f0b57592a5f4 (diff)
equipent now kinda works
Diffstat (limited to 'src/components')
-rw-r--r--src/components/equipment.rs164
-rw-r--r--src/components/interactable.rs20
-rw-r--r--src/components/item.rs28
-rw-r--r--src/components/messages.rs8
-rw-r--r--src/components/mod.rs21
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 {
}
-
-
-