wowlab_types/types/combat/
damage.rs1#[derive(
2 Clone,
3 Copy,
4 Debug,
5 Default,
6 Eq,
7 Hash,
8 PartialEq,
9 num_enum::IntoPrimitive,
10 num_enum::TryFromPrimitive,
11 serde::Deserialize,
12 serde::Serialize,
13 strum::Display,
14 strum::EnumCount,
15 strum::EnumIter,
16 strum::EnumString,
17)]
18#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
19#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi))]
20#[repr(u8)]
21pub enum DamageSchool {
23 #[default]
24 Physical = 0,
25 Holy = 1,
26 Fire = 2,
27 Nature = 3,
28 Frost = 4,
29 Shadow = 5,
30 Arcane = 6,
31 Chaos = 7,
32}
33
34impl DamageSchool {
35 pub const COUNT: usize = <Self as strum::EnumCount>::COUNT;
36
37 #[must_use]
38 pub const fn is_physical(self) -> bool {
39 matches!(self, Self::Physical)
40 }
41
42 #[must_use]
43 pub const fn is_magic(self) -> bool {
44 !self.is_physical()
45 }
46}
47
48#[derive(
49 Clone,
50 Copy,
51 Debug,
52 Default,
53 Eq,
54 Hash,
55 PartialEq,
56 num_enum::IntoPrimitive,
57 num_enum::TryFromPrimitive,
58 serde::Deserialize,
59 serde::Serialize,
60 strum::Display,
61 strum::EnumCount,
62 strum::EnumIter,
63 strum::EnumString,
64)]
65#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
66#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi))]
67#[repr(u8)]
68pub enum HitResult {
70 #[default]
71 Hit = 0,
72 Crit = 1,
73 Miss = 2,
74 Dodge = 3,
75 Parry = 4,
76 Glance = 5,
77 Block = 6,
78 CritBlock = 7,
79}
80
81impl HitResult {
82 #[must_use]
83 pub const fn is_hit(self) -> bool {
84 matches!(
85 self,
86 Self::Hit | Self::Crit | Self::Glance | Self::Block | Self::CritBlock
87 )
88 }
89
90 #[must_use]
91 pub const fn is_crit(self) -> bool {
92 matches!(self, Self::Crit)
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use googletest::prelude::*;
99 use rstest::rstest;
100
101 use super::*;
102
103 #[gtest]
104 #[rstest]
105 #[case::physical(DamageSchool::Physical, true, false)]
106 #[case::fire(DamageSchool::Fire, false, true)]
107 #[case::holy(DamageSchool::Holy, false, true)]
108 #[case::shadow(DamageSchool::Shadow, false, true)]
109 #[case::chaos(DamageSchool::Chaos, false, true)]
110 fn damage_school_physical_magic(
111 #[case] school: DamageSchool,
112 #[case] is_physical: bool,
113 #[case] is_magic: bool,
114 ) -> Result<()> {
115 verify_that!(school.is_physical(), eq(is_physical))?;
116
117 verify_that!(school.is_magic(), eq(is_magic))
118 }
119
120 #[gtest]
121 #[rstest]
122 #[case::physical(0, DamageSchool::Physical)]
123 #[case::chaos(7, DamageSchool::Chaos)]
124 fn damage_school_try_from_ok(#[case] raw: u8, #[case] expected: DamageSchool) -> Result<()> {
125 verify_that!(DamageSchool::try_from(raw).ok(), some(eq(expected)))
126 }
127
128 #[gtest]
129 fn damage_school_try_from_out_of_range() -> Result<()> {
130 verify_that!(DamageSchool::try_from(8u8).ok(), none())
131 }
132
133 #[gtest]
134 #[rstest]
135 #[case::hit(HitResult::Hit, true, false)]
136 #[case::crit(HitResult::Crit, true, true)]
137 #[case::miss(HitResult::Miss, false, false)]
138 #[case::dodge(HitResult::Dodge, false, false)]
139 #[case::parry(HitResult::Parry, false, false)]
140 #[case::glance(HitResult::Glance, true, false)]
141 #[case::block(HitResult::Block, true, false)]
142 #[case::critical_block(HitResult::CritBlock, true, false)]
143 fn hit_result_predicates(
144 #[case] result: HitResult,
145 #[case] is_hit: bool,
146 #[case] is_crit: bool,
147 ) -> Result<()> {
148 verify_that!(result.is_hit(), eq(is_hit))?;
149
150 verify_that!(result.is_crit(), eq(is_crit))
151 }
152}