gamemstr_common/action/
attack.rs

1use core::fmt;
2
3use serde::{Deserialize, Serialize};
4
5use crate::{DamageType, DieStat};
6
7#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
8pub enum Attack {
9    MeleeWeaponAttack {
10        name: String,
11        modifier: i32,
12        reach: Option<i32>,
13        target_type: TargetType,
14        damage: DieStat,
15        damage_type: DamageType,
16        description: String,
17    },
18    RangedWeaponAttack {
19        name: String,
20        modifier: i32,
21        range: Option<Range>,
22        target_type: TargetType,
23        damage: DieStat,
24        damage_type: DamageType,
25        description: String,
26    },
27    MeleeOrRangedWeaponAttack {
28        name: String,
29        modifier: i32,
30        reach: Option<i32>,
31        range: Option<Range>,
32        target_type: TargetType,
33        damage: DieStat,
34        damage_type: DamageType,
35        description: String,
36    },
37    MeleeSpellAttack {
38        name: String,
39        modifier: i32,
40        reach: Option<i32>,
41        target_type: TargetType,
42        damage: DieStat,
43        damage_type: DamageType,
44        description: String,
45    },
46    RangedSpellAttack {
47        name: String,
48        modifier: i32,
49        range: Option<Range>,
50        target_type: TargetType,
51        damage: DieStat,
52        damage_type: DamageType,
53        description: String,
54    },
55}
56
57impl fmt::Display for Attack {
58    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59        match &self {
60            Attack::MeleeWeaponAttack {
61                name,
62                modifier,
63                reach,
64                target_type,
65                damage,
66                damage_type,
67                description,
68            } => {
69                write!(
70                    f,
71                    "{}. {}: {} to hit, reach {}, {}. Hit: {} {}. {}",
72                    name,
73                    "Melee Weapon Attack",
74                    modifier,
75                    if let Some(x) = reach {
76                        x.to_string()
77                    } else {
78                        String::new()
79                    },
80                    target_type.to_string(),
81                    damage.to_string(),
82                    damage_type,
83                    description
84                )
85            }
86            Attack::RangedWeaponAttack {
87                name,
88                modifier,
89                range,
90                target_type,
91                damage,
92                damage_type,
93                description,
94            } => {
95                write!(
96                    f,
97                    "{}. {}: {} to hit, range {}, {}. Hit: {} {}. {}",
98                    name,
99                    "Ranged Weapon Attack",
100                    modifier,
101                    if let Some(x) = range {
102                        format!("{}/{} ft.", x.close_range, x.long_range)
103                    } else {
104                        String::from("")
105                    },
106                    target_type.to_string(),
107                    damage.to_string(),
108                    damage_type,
109                    description
110                )
111            }
112            Attack::MeleeOrRangedWeaponAttack {
113                name,
114                modifier,
115                reach,
116                range,
117                target_type,
118                damage,
119                damage_type,
120                description,
121            } => {
122                write!(
123                    f,
124                    "{}. {}: {} to hit, reach {} or range {}, {}. Hit: {} {}. {}",
125                    name,
126                    "",
127                    modifier,
128                    if let Some(x) = reach {
129                        x.to_string()
130                    } else {
131                        String::new()
132                    },
133                    if let Some(x) = range {
134                        format!("{}/{} ft.", x.close_range, x.long_range)
135                    } else {
136                        String::new()
137                    },
138                    target_type.to_string(),
139                    damage.to_string(),
140                    damage_type,
141                    description
142                )
143            }
144            Attack::MeleeSpellAttack {
145                name,
146                modifier,
147                reach,
148                target_type,
149                damage,
150                damage_type,
151                description,
152            } => {
153                write!(
154                    f,
155                    "{}. {}: {} to hit, reach {}, {}. Hit: {} {}. {}",
156                    name,
157                    "Melee Spell Attack",
158                    modifier,
159                    if let Some(x) = reach {
160                        x.to_string()
161                    } else {
162                        String::new()
163                    },
164                    target_type.to_string(),
165                    damage.to_string(),
166                    damage_type,
167                    description
168                )
169            }
170            Attack::RangedSpellAttack {
171                name,
172                modifier,
173                range,
174                target_type,
175                damage,
176                damage_type,
177                description,
178            } => {
179                write!(
180                    f,
181                    "{}. {}: {} to hit, range {}, {}. Hit: {} {}. {}",
182                    name,
183                    "Ranged Spell Attack",
184                    modifier,
185                    if let Some(x) = range {
186                        format!("{}/{} ft.", x.close_range, x.long_range)
187                    } else {
188                        String::new()
189                    },
190                    target_type.to_string(),
191                    damage.to_string(),
192                    damage_type,
193                    description
194                )
195            }
196        }
197    }
198}
199
200#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
201pub enum TargetType {
202    OneTarget,
203    MultipleTargets(i32),
204    Cone(i32),
205    Line(i32),
206    Cube(i32),
207    Sphere(i32),
208}
209
210impl fmt::Display for TargetType {
211    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
212        match &self {
213            TargetType::OneTarget => write!(f, "one target"),
214            TargetType::MultipleTargets(x) => write!(
215                f,
216                "{} targets",
217                num_to_words::integer_to_en_us(*x as i64).expect("Number of Targets")
218            ),
219            TargetType::Cone(x) => write!(
220                f,
221                "{} ft. Cone",
222                num_to_words::integer_to_en_us(*x as i64).expect("Number of Feet")
223            ),
224            TargetType::Line(x) => write!(
225                f,
226                "{} ft. Line",
227                num_to_words::integer_to_en_us(*x as i64).expect("Number of Feet")
228            ),
229            TargetType::Cube(x) => write!(
230                f,
231                "{} ft. Cube",
232                num_to_words::integer_to_en_us(*x as i64).expect("Number of Feet")
233            ),
234            TargetType::Sphere(x) => write!(
235                f,
236                "{} ft. Sphere",
237                num_to_words::integer_to_en_us(*x as i64).expect("Number of Feet")
238            ),
239        }
240    }
241}
242
243#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
244pub struct Range {
245    pub close_range: i32,
246    pub long_range: i32,
247}
248
249impl fmt::Display for Range {
250    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
251        write!(f, "{} ft. / {} ft.", self.close_range, self.long_range)
252    }
253}