boseiju/ability_tree/imperative/
deals_damage_imperative.rs

1use crate::ability_tree::AbilityTreeNode;
2use crate::ability_tree::MAX_CHILDREN_PER_NODE;
3
4const MAX_DAMAGES_DEALT: usize = MAX_CHILDREN_PER_NODE - 1;
5
6/// Imperative to deal damage to things.
7///
8/// The imperative can deals multiple damages to multiple targets,
9/// for instance Drakuseth, Maw of Flames states: "it deals 4 damage to any
10/// target and 3 damage to each of up to two other targets."
11#[derive(serde::Serialize, serde::Deserialize)]
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct DealsDamageImperative {
14    pub dealer: crate::ability_tree::object::ObjectReference,
15    pub damages: crate::utils::HeapArrayVec<DamagesDealt, MAX_DAMAGES_DEALT>,
16    #[cfg(feature = "spanned_tree")]
17    pub span: crate::ability_tree::span::TreeSpan,
18}
19
20impl AbilityTreeNode for DealsDamageImperative {
21    fn node_id(&self) -> usize {
22        use idris::Idris;
23        crate::ability_tree::NodeKind::DealsDamageImperative.id()
24    }
25
26    fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE> {
27        let mut children = arrayvec::ArrayVec::new_const();
28        children.push(&self.dealer as &dyn AbilityTreeNode);
29        for damage in self.damages.iter() {
30            children.push(damage as &dyn AbilityTreeNode);
31        }
32        children
33    }
34
35    fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()> {
36        use std::io::Write;
37        write!(out, "deals damage:")?;
38        out.push_inter_branch()?;
39        write!(out, "dealer:")?;
40        out.push_final_branch()?;
41        self.dealer.display(out)?;
42        out.pop_branch();
43        out.next_final_branch()?;
44        write!(out, "damages dealt:")?;
45        for (i, damage) in self.damages.iter().enumerate() {
46            if i == self.damages.len() - 1 {
47                out.push_final_branch()?;
48            } else {
49                out.push_inter_branch()?;
50            }
51            damage.display(out)?;
52            out.pop_branch();
53        }
54        out.pop_branch();
55        Ok(())
56    }
57
58    fn node_tag(&self) -> &'static str {
59        "deal damage imperative"
60    }
61
62    #[cfg(feature = "spanned_tree")]
63    fn node_span(&self) -> crate::ability_tree::span::TreeSpan {
64        self.span
65    }
66}
67
68#[cfg(feature = "parser")]
69impl crate::utils::DummyInit for DealsDamageImperative {
70    fn dummy_init() -> Self {
71        Self {
72            dealer: crate::utils::dummy(),
73            damages: crate::utils::HeapArrayVec::new(),
74            #[cfg(feature = "spanned_tree")]
75            span: Default::default(),
76        }
77    }
78}
79
80/// Single damage dealing action.
81///
82/// This can be the same damage to multiple targets, or shared damage among targets,
83/// or anything that was mentionned in a single damage dealing action.
84#[derive(serde::Serialize, serde::Deserialize)]
85#[derive(Debug, Clone, PartialEq, Eq)]
86pub struct DamagesDealt {
87    pub to: crate::ability_tree::object::ObjectReference,
88    pub amount: crate::ability_tree::number::Number,
89    #[cfg(feature = "spanned_tree")]
90    pub span: crate::ability_tree::span::TreeSpan,
91}
92
93impl AbilityTreeNode for DamagesDealt {
94    fn node_id(&self) -> usize {
95        use idris::Idris;
96        crate::ability_tree::NodeKind::DamagesDealt.id()
97    }
98
99    fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE> {
100        let mut children = arrayvec::ArrayVec::new_const();
101        children.push(&self.to as &dyn AbilityTreeNode);
102        children.push(&self.amount as &dyn AbilityTreeNode);
103        children
104    }
105
106    fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()> {
107        use std::io::Write;
108        write!(out, "damage dealt:")?;
109        out.push_inter_branch()?;
110        write!(out, "to:")?;
111        out.push_final_branch()?;
112        self.to.display(out)?;
113        out.pop_branch();
114        out.next_final_branch()?;
115        write!(out, "amount:")?;
116        out.push_final_branch()?;
117        self.amount.display(out)?;
118        out.pop_branch();
119        out.pop_branch();
120        Ok(())
121    }
122
123    fn node_tag(&self) -> &'static str {
124        "damage dealt"
125    }
126
127    #[cfg(feature = "spanned_tree")]
128    fn node_span(&self) -> crate::ability_tree::span::TreeSpan {
129        self.span
130    }
131}
132
133#[cfg(feature = "parser")]
134impl crate::utils::DummyInit for DamagesDealt {
135    fn dummy_init() -> Self {
136        Self {
137            to: crate::utils::dummy(),
138            amount: crate::utils::dummy(),
139            #[cfg(feature = "spanned_tree")]
140            span: Default::default(),
141        }
142    }
143}