evtc\buff/
remove.rs

1use crate::{
2    event::{impl_common, CommonEvent},
3    extract::Extract,
4    Event, EventCategory, TryExtract,
5};
6use num_enum::{FromPrimitive, IntoPrimitive};
7
8#[cfg(feature = "serde")]
9use serde::{Deserialize, Serialize};
10
11#[cfg(feature = "strum")]
12use strum::{Display, EnumCount, EnumIter, IntoStaticStr, VariantNames};
13
14/// Buff remove event.
15#[derive(Debug, Clone)]
16#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
17pub struct BuffRemoveEvent {
18    /// Common combat event information.
19    #[cfg_attr(feature = "serde", serde(flatten))]
20    pub common: CommonEvent,
21
22    /// Kind of buff remove.
23    pub remove: BuffRemoveKind,
24
25    /// Removed buff(s) as duration.
26    pub removed_duration: i32,
27
28    /// Removed buff(s) as intensity.
29    ///
30    /// **Warning:** may overflow on [`BuffRemove::All`].
31    pub removed_intensity: i32,
32}
33
34impl_common!(BuffRemoveEvent);
35
36impl Extract for BuffRemoveEvent {
37    #[inline]
38    unsafe fn extract(event: &Event) -> Self {
39        Self {
40            common: event.into(),
41            remove: event.extract(),
42            removed_duration: event.value,
43            removed_intensity: event.buff_dmg,
44        }
45    }
46}
47
48impl TryExtract for BuffRemoveEvent {
49    #[inline]
50    fn can_extract(event: &Event) -> bool {
51        event.categorize() == EventCategory::BuffRemove
52    }
53}
54
55/// Combat buff remove.
56#[derive(
57    Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, IntoPrimitive, FromPrimitive,
58)]
59#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
60#[cfg_attr(
61    feature = "strum",
62    derive(Display, EnumCount, EnumIter, IntoStaticStr, VariantNames)
63)]
64#[repr(u8)]
65pub enum BuffRemove {
66    /// Not used, different kind of event.
67    None = 0,
68
69    /// Last or all stacks removed.
70    ///
71    /// Sent by server.
72    All = 1,
73
74    /// Single stack removed.
75    ///
76    /// Happens for each stack on cleanse.
77    ///
78    /// Sent by server.
79    Single = 2,
80
81    /// Single stack removed.
82    ///
83    /// Automatically by Arc on out of combat or all stack.
84    /// Ignore for strip/cleanse calculation.
85    /// Use for in/out volume.
86    Manual = 3,
87
88    /// Unknown or invalid.
89    #[num_enum(catch_all)]
90    Unknown(u8),
91}
92
93/// Kind of buff remove.
94#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
95#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
96#[cfg_attr(feature = "serde", serde(tag = "kind"))]
97#[cfg_attr(
98    feature = "strum",
99    derive(Display, EnumCount, EnumIter, IntoStaticStr, VariantNames)
100)]
101pub enum BuffRemoveKind {
102    /// Last or all stacks removed.
103    ///
104    /// Sent by server.
105    All {
106        /// Number of stacks removed.
107        stacks_removed: u8,
108    },
109
110    /// Single stack removed.
111    ///
112    /// Happens for each stack on cleanse.
113    ///
114    /// Sent by server.
115    Single {
116        /// Stack (instance) id of removed buff.
117        stack_id: u32,
118    },
119
120    /// Single stack removed.
121    ///
122    /// Automatically by Arc on out of combat or all stack.
123    /// Ignore for strip/cleanse calculation.
124    /// Use for in/out volume.
125    Manual {
126        /// Stack (instance) id of removed buff.
127        stack_id: u32,
128    },
129
130    /// Unknown or invalid.
131    Unknown(u8),
132}
133
134impl Extract for BuffRemoveKind {
135    #[inline]
136    unsafe fn extract(event: &Event) -> Self {
137        match event.get_buffremove() {
138            BuffRemove::None => unreachable!("extract buffremove on non-buffremove event"),
139            BuffRemove::All => Self::All {
140                stacks_removed: event.result,
141            },
142            BuffRemove::Single => Self::Single {
143                stack_id: event.get_pad_id(),
144            },
145            BuffRemove::Manual => Self::Manual {
146                stack_id: event.get_pad_id(),
147            },
148            BuffRemove::Unknown(value) => Self::Unknown(value),
149        }
150    }
151}