1use crate::{
2 Event, StateChange, TryExtract,
3 extract::{Extract, transmute_field},
4};
5
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8
9#[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 #[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#[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 #[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}