game_features/
skill.rs

1use crate::*;
2use std::collections::HashMap;
3use std::fmt::Debug;
4use std::hash::Hash;
5
6// World interaction
7// or
8// Stat buff
9/// The definition of an usable skill.
10#[derive(new, Clone, Serialize, Deserialize, Debug, Builder)]
11pub struct SkillDefinition<K, E, S, I> {
12    /// The id of this skill.
13    pub key: S,
14    /// The name.
15    pub name: String,
16    /// The computer friendly name.
17    pub friendly_name: String,
18    /// The complete description of this skill.
19    pub description: String,
20    /// The cooldown between usages of this skill.
21    pub cooldown: f64,
22    /// Whether this skill is will activate automatically once all conditions are met or
23    /// if it needs to be manually activated.
24    pub passive: bool,
25    /// The stats conditions required to activate this skill.
26    pub conditions: Vec<StatCondition<K>>,
27    /// The item conditions required to activate this skill.
28    pub item_conditions: Vec<(I, usize, UseMode)>,
29    /// The caused stat effectors.
30    pub stat_effectors: Vec<E>,
31}
32
33/// # Generics
34/// K: Stat Key
35/// E: Effector Key
36/// S: Skill Key
37/// I: Item Key
38/// IT: Item Type
39/// CD: Item Custom Data
40impl<K: Hash + Eq + Debug, E, S, I: Hash + Eq + Clone + PartialEq + Debug>
41    SkillDefinition<K, E, S, I>
42{
43    /// Checks if all the conditions to use this skill are met.
44    pub fn check_conditions<IT: SlotType, CD: PartialEq + Default + Clone + Debug>(
45        &self,
46        stats: &StatSet<K>,
47        inventory: &Inventory<I, IT, CD>,
48        stat_defs: &StatDefinitions<K>,
49    ) -> bool {
50        for c in &self.conditions {
51            if !c.check(stats, stat_defs) {
52                return false;
53            }
54        }
55        for ic in &self.item_conditions {
56            if !inventory.has_quantity(&ic.0, ic.1) {
57                return false;
58            }
59        }
60        true
61    }
62}
63
64/// An instance of a skill.
65/// There is one per skill per entity that can use it.
66/// Holds the cooldown for each skill.
67#[derive(Debug, Clone, Serialize, Deserialize, new)]
68pub struct SkillInstance<S> {
69    /// The skill key.
70    pub skill_key: S,
71    /// The remaining time to wait before we can use this skill again.
72    pub current_cooldown: f64,
73}
74
75/// The set of skill that can be used by an entity.
76#[derive(Debug, Clone, Serialize, Deserialize, new)]
77pub struct SkillSet<S: Hash + Eq> {
78    /// The skills mapped by their key.
79    pub skills: HashMap<S, SkillInstance<S>>,
80}
81
82impl<S: Hash + Eq + Clone> From<Vec<S>> for SkillSet<S> {
83    fn from(t: Vec<S>) -> Self {
84        let mut h = HashMap::new();
85        for s in t {
86            h.insert(s.clone(), SkillInstance::new(s, 0.0));
87        }
88        Self { skills: h }
89    }
90}
91
92/// Holds the definitions of all known skills.
93#[derive(Debug, Clone, Serialize, Deserialize, new)]
94pub struct SkillDefinitions<K, E, S: Hash + Eq, I> {
95    /// The definitions.
96    pub defs: HashMap<S, SkillDefinition<K, E, S, I>>,
97}
98
99impl<K, E, S: Hash + Eq, I> Default for SkillDefinitions<K, E, S, I> {
100    fn default() -> Self {
101        Self {
102            defs: HashMap::default(),
103        }
104    }
105}
106
107impl<K, E, S: Hash + Eq + Clone, I> From<Vec<SkillDefinition<K, E, S, I>>>
108    for SkillDefinitions<K, E, S, I>
109{
110    fn from(t: Vec<SkillDefinition<K, E, S, I>>) -> Self {
111        let defs = t
112            .into_iter()
113            .map(|s| (s.key.clone(), s))
114            .collect::<HashMap<_, _>>();
115        Self::new(defs)
116    }
117}