1mod guid;
4
5#[cfg(feature = "serde")]
6pub mod serde_guid;
7
8use crate::{
9 extract::{transmute_field, Extract},
10 Event, StateChange, TryExtract,
11};
12use num_enum::{IntoPrimitive, TryFromPrimitive};
13
14#[cfg(feature = "serde")]
15use serde::{Deserialize, Serialize};
16
17#[cfg(feature = "strum")]
18use strum::{Display, EnumCount, EnumIter, IntoStaticStr, VariantNames};
19
20pub use self::guid::*;
21
22#[derive(Debug, Clone)]
30#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
31pub struct ContentInfo {
32 pub content_id: u32,
34
35 #[cfg_attr(feature = "serde", serde(with = "serde_guid"))]
37 pub guid: GUID,
38
39 pub content_type: ContentType,
41}
42
43impl ContentInfo {
44 #[inline]
46 pub fn guid_string(&self) -> String {
47 self.guid.format_simple()
48 }
49
50 #[inline]
52 pub fn is_effect(&self) -> bool {
53 matches!(self.content_type, ContentType::Effect { .. })
54 }
55
56 #[inline]
58 pub fn is_marker(&self) -> bool {
59 matches!(self.content_type, ContentType::Marker { .. })
60 }
61
62 #[inline]
64 pub fn is_skill(&self) -> bool {
65 matches!(self.content_type, ContentType::Skill)
66 }
67
68 #[inline]
70 pub fn is_species(&self) -> bool {
71 matches!(self.content_type, ContentType::Species)
72 }
73}
74
75impl Extract for ContentInfo {
76 #[inline]
77 unsafe fn extract(event: &Event) -> Self {
78 Self {
79 content_id: event.skill_id,
80 guid: transmute_field!(event.src_agent as GUID),
81 content_type: event.extract(),
82 }
83 }
84}
85
86impl TryExtract for ContentInfo {
87 #[inline]
88 fn can_extract(event: &Event) -> bool {
89 event.get_statechange() == StateChange::IdToGUID
90 }
91}
92
93#[derive(Debug, Clone)]
95#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
96pub enum ContentType {
97 Effect {
99 effect_type: u16,
101
102 default_duration: f32,
104 },
105
106 Marker {
108 is_commander_tag: bool,
110 },
111
112 Skill,
116
117 Species,
119
120 Unknown(u32),
122}
123
124impl Extract for ContentType {
125 #[inline]
126 unsafe fn extract(event: &Event) -> Self {
127 match event.overstack_value.try_into() {
128 Ok(ContentLocal::Effect) => Self::Effect {
129 effect_type: event.src_instance_id,
130 default_duration: transmute_field!(event.buff_dmg as f32),
131 },
132 Ok(ContentLocal::Marker) => Self::Marker {
133 is_commander_tag: event.src_instance_id != 0,
134 },
135 Ok(ContentLocal::Skill) => Self::Skill,
136 Ok(ContentLocal::Species) => Self::Species,
137 Err(err) => Self::Unknown(err.number),
138 }
139 }
140}
141
142impl TryExtract for ContentType {
143 #[inline]
144 fn can_extract(event: &Event) -> bool {
145 event.get_statechange() == StateChange::IdToGUID
146 }
147}
148
149#[derive(
151 Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, IntoPrimitive, TryFromPrimitive,
152)]
153#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
154#[cfg_attr(
155 feature = "strum",
156 derive(Display, EnumCount, EnumIter, IntoStaticStr, VariantNames)
157)]
158#[repr(u32)]
159pub enum ContentLocal {
160 Effect = 0,
165
166 Marker = 1,
168
169 Skill = 2,
173
174 Species = 3,
176}