evtc\buff/
formula.rs

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