evtc\buff/
formula.rs

1use crate::{
2    Event, StateChange, TryExtract,
3    extract::{Extract, transmute_field},
4};
5
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8
9/// Buff formula from an [`Event`] with [`StateChange::BuffFormula`].
10#[derive(Debug, Clone)]
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12pub struct BuffFormula {
13    pub skill_id: u32,
14    pub formula: u32,
15    pub attr1: u32,
16    pub attr2: u32,
17    pub param1: f32,
18    pub param2: f32,
19    pub param3: f32,
20    pub trait_src: u32,
21    pub trait_self: u32,
22    pub buff_src: u32,
23    pub buff_self: u32,
24    pub content_reference: f32,
25    pub content_reference_type: u8,
26    pub not_npc: bool,
27    pub not_player: bool,
28    pub is_break: bool,
29}
30
31impl BuffFormula {
32    /// Whether the buff formula is always active.
33    #[inline]
34    pub fn is_unconditional(&self) -> bool {
35        self.trait_src == 0 && self.trait_self == 0 && self.buff_src == 0 && self.buff_self == 0
36    }
37}
38
39impl Extract for BuffFormula {
40    #[inline]
41    unsafe fn extract(event: &Event) -> Self {
42        unsafe { RawBuffFormula::extract(event) }.into()
43    }
44}
45
46impl TryExtract for BuffFormula {
47    #[inline]
48    fn can_extract(event: &Event) -> bool {
49        RawBuffFormula::can_extract(event)
50    }
51}
52
53impl From<RawBuffFormula> for BuffFormula {
54    #[inline]
55    fn from(raw: RawBuffFormula) -> Self {
56        Self {
57            skill_id: raw.skill_id,
58            formula: raw.formula as _,
59            attr1: raw.attr1 as _,
60            attr2: raw.attr2 as _,
61            param1: raw.param1,
62            param2: raw.param2,
63            param3: raw.param3,
64            trait_src: raw.trait_src as _,
65            trait_self: raw.trait_self as _,
66            buff_src: raw.buff_src as _,
67            buff_self: raw.buff_self as _,
68            content_reference: raw.content_reference,
69            content_reference_type: raw.content_reference_type,
70            not_npc: raw.not_npc != 0,
71            not_player: raw.not_player != 0,
72            is_break: raw.is_break != 0,
73        }
74    }
75}
76
77/// Buff formula from an [`Event`] with [`StateChange::BuffFormula`].
78#[derive(Debug, Clone)]
79#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
80pub struct RawBuffFormula {
81    pub skill_id: u32,
82    pub formula: f32,
83    pub attr1: f32,
84    pub attr2: f32,
85    pub param1: f32,
86    pub param2: f32,
87    pub param3: f32,
88    pub trait_src: f32,
89    pub trait_self: f32,
90    pub buff_src: f32,
91    pub buff_self: f32,
92    pub content_reference: f32,
93    pub content_reference_type: u8,
94    pub not_npc: u8,
95    pub not_player: u8,
96    pub is_break: u8,
97}
98
99impl RawBuffFormula {
100    /// Whether the buff formula is always active.
101    #[inline]
102    pub fn is_unconditional(&self) -> bool {
103        self.trait_src == 0.0
104            && self.trait_self == 0.0
105            && self.buff_src == 0.0
106            && self.buff_self == 0.0
107    }
108}
109
110impl Extract for RawBuffFormula {
111    #[inline]
112    unsafe fn extract(event: &Event) -> Self {
113        let [
114            kind,
115            attr1,
116            attr2,
117            param1,
118            param2,
119            param3,
120            trait_src,
121            trait_self,
122            content_reference,
123        ] = transmute_field!(event.time as [f32; 9]);
124        let [buff_src, buff_self] = transmute_field!(event.src_instance_id as [f32; 2]);
125
126        Self {
127            skill_id: event.skill_id,
128            formula: kind,
129            attr1,
130            attr2,
131            param1,
132            param2,
133            param3,
134            trait_src,
135            trait_self,
136            buff_src,
137            buff_self,
138            content_reference,
139            content_reference_type: event.pad61,
140            not_npc: event.is_flanking,
141            not_player: event.is_shields,
142            is_break: event.is_offcycle,
143        }
144    }
145}
146
147impl TryExtract for RawBuffFormula {
148    #[inline]
149    fn can_extract(event: &Event) -> bool {
150        event.get_statechange() == StateChange::BuffFormula
151    }
152}