wowlab_engine_domain/dbc/semantics/
mod.rs1use wowlab_types::data::SpellEffect;
4
5use self::{
6 modifier_property_is as raw_modifier_property_is,
7 modifier_property_is_any as raw_modifier_property_is_any,
8};
9
10mod aura_interrupt_flags;
11mod aura_states;
12mod aura_subtypes;
13mod control;
14mod coverage;
15mod defense_types;
16mod difficulty;
17mod enchantments;
18mod implicit_targets;
19mod items;
20mod loot;
21mod mechanics;
22mod modifier_properties;
23mod power_types;
24mod proc_attributes;
25mod proc_types;
26mod ratings;
27mod resolved_game_data;
28mod schools;
29mod spell_attributes;
30mod spell_cast_target_flags;
31mod spell_effect_attributes;
32mod spell_effect_targets;
33mod spell_effects;
34mod spell_interrupt_flags;
35mod spell_targets;
36mod stances;
37mod stat_masks;
38mod traits;
39
40pub use aura_interrupt_flags::SpellAuraInterruptFlags;
41pub use aura_states::AuraState;
42pub use control::{
43 CrowdControlKind, CrowdControlSemantic, DiminishingGroup, crowd_control_semantic,
44};
45pub use coverage::{EffectSemanticCoverage, effect_semantic_coverage};
46pub use defense_types::DefenseType;
47pub use difficulty::DifficultyId;
48pub use implicit_targets::{
49 IMPLICIT_TARGET_SEMANTICS, ImplicitTargetCheck, ImplicitTargetDirection, ImplicitTargetObject,
50 ImplicitTargetReference, ImplicitTargetSelection, ImplicitTargetSelector,
51 ImplicitTargetSemantic, implicit_target_semantic,
52};
53pub use items::{
54 ArmorSubclass, ConsumableSubclass, GemSubclass, InventoryType, ItemClass, ItemEffectTrigger,
55 WeaponSubclass, item_matches_consumable_query, resolve_item_budget,
56};
57pub use loot::{
58 DungeonDifficultyFlags, ItemBonusListGroupEntryFlags, ItemBonusType, ItemContext,
59 RaidDifficultyFlags,
60};
61pub use mechanics::{DispelType, Mechanic, MechanicMask};
62pub use power_types::PowerType;
63pub use proc_attributes::{
64 CONSUMED_PROC_ATTRIBUTES, PROC_ATTRIBUTE_SEMANTICS, ProcAttributeKind, ProcAttributeSemantic,
65 ProcAttributes, proc_attribute_semantic,
66};
67pub use proc_types::ProcTypeMask;
68pub use schools::SpellSchoolMask;
69pub use spell_cast_target_flags::{
70 SPELL_CAST_TARGET_FLAG_SEMANTICS, SpellCastTargetFlagSemantic, SpellCastTargetFlags,
71 spell_cast_target_flag_semantic,
72};
73pub use spell_effect_attributes::SpellEffectAttributes;
74pub use spell_effect_targets::{
75 SpellEffectImplicitTarget, SpellEffectTargetSemantic, spell_effect_target_semantic,
76};
77pub use spell_interrupt_flags::SpellInterruptFlags;
78pub use spell_targets::{SpellTargetMasks, spell_target_masks};
79pub use stat_masks::{AttributeMask, RatingMultiplierMask};
80
81#[derive(Clone, Copy, Debug, Eq, PartialEq)]
83#[non_exhaustive]
84pub enum SemanticSupport {
85 Generic,
87 Partial,
89 ContentRequired,
91 Ignored,
93 Unsupported,
95}
96
97pub use spell_attributes::{
98 SPELL_ATTRIBUTE_SEMANTICS, SpellAttributeKind, SpellAttributeSemantic, spell_attribute_is,
99 spell_attribute_is_any, spell_attribute_semantic,
100};
101pub use spell_effects::{
102 SPELL_EFFECT_SEMANTICS, SpellEffectKind, SpellEffectSemantic, spell_effect_semantic,
103};
104#[derive(Clone, Copy, Debug, Eq, PartialEq)]
106#[non_exhaustive]
107pub enum ModifierOperation {
108 Flat,
109 Percent,
110}
111
112#[derive(Clone, Copy, Debug, Eq, PartialEq)]
114#[non_exhaustive]
115pub enum ModifierFilter {
116 ClassFamilyMask,
117 Label,
118}
119
120pub use aura_subtypes::{
121 AURA_SUBTYPE_SEMANTICS, AuraSubtypeKind, AuraSubtypeSemantic, PetStatKind, StatModifierKind,
122 is_primary_stat_misc,
123};
124pub use enchantments::{
125 EnchantEffectKind, EnchantTriggerSemantic, enchant_effect_is, enchant_effect_kind,
126 enchant_trigger_semantic, rppm_crit_scaled, rppm_haste_scaled,
127};
128pub use modifier_properties::{
129 MODIFIER_PROPERTY_SEMANTICS, ModifierOperations, ModifierPropertyKind,
130 ModifierPropertySemantic, modifier_property_for_effect,
131};
132pub use ratings::{CombatRating, CombatRatingMask};
133pub use resolved_game_data::ResolvedGameDataSemanticExt;
134pub use stances::{ShapeshiftForm, SpellShapeshiftFormFlags, stance_mask_allows};
135pub use traits::{
136 TraitConditionType, TraitCurrencyFlags, TraitEffectOperation, TraitNodeType, TraitTreeIndex,
137};
138macro_rules! semantic_registry {
139 (
140 kind = $kind_fn:ident,
141 is = $is_fn:ident,
142 is_any = $is_any_fn:ident,
143 raw = $raw_fn:ident,
144 semantic = $semantic_fn:ident,
145 registry = $registry:ident,
146 type = $kind_ty:ty
147 ) => {
148 #[must_use]
149 pub fn $kind_fn(raw: i32) -> Option<$kind_ty> {
150 $semantic_fn(raw).map(|semantic| semantic.kind)
151 }
152
153 #[must_use]
154 pub fn $is_fn(raw: i32, expected: $kind_ty) -> bool {
155 $semantic_fn(raw).is_some_and(|semantic| semantic.kind == expected)
156 }
157
158 #[must_use]
159 pub fn $is_any_fn(raw: i32, expected: &[$kind_ty]) -> bool {
160 $kind_fn(raw).is_some_and(|kind| expected.contains(&kind))
161 }
162
163 #[must_use]
164 pub fn $raw_fn(kind: $kind_ty) -> i32 {
165 $registry
166 .iter()
167 .find(|entry| entry.kind == kind)
168 .map_or(0, |entry| entry.kind as i32)
169 }
170 };
171}
172
173semantic_registry! {
174 kind = spell_effect_kind,
175 is = spell_effect_is,
176 is_any = spell_effect_is_any,
177 raw = spell_effect_raw,
178 semantic = spell_effect_semantic,
179 registry = SPELL_EFFECT_SEMANTICS,
180 type = SpellEffectKind
181}
182
183#[must_use]
185pub fn aura_subtype_semantic(raw: i32) -> Option<&'static AuraSubtypeSemantic> {
186 AURA_SUBTYPE_SEMANTICS
187 .iter()
188 .find(|entry| entry.kind as i32 == raw)
189}
190
191#[must_use]
193pub fn aura_subtype_modifier(raw: i32) -> Option<(ModifierOperation, ModifierFilter)> {
194 aura_subtype_semantic(raw).and_then(|semantic| semantic.modifier)
195}
196
197semantic_registry! {
198 kind = aura_subtype_kind,
199 is = aura_subtype_is,
200 is_any = aura_subtype_is_any,
201 raw = aura_subtype_raw,
202 semantic = aura_subtype_semantic,
203 registry = AURA_SUBTYPE_SEMANTICS,
204 type = AuraSubtypeKind
205}
206
207#[must_use]
209pub const fn pet_stat_kind(raw: i32) -> Option<PetStatKind> {
210 match raw {
211 2 => Some(PetStatKind::AttackPowerInheritance),
212 3 => Some(PetStatKind::SpellPowerInheritance),
213 _ => None,
214 }
215}
216
217#[must_use]
219pub fn modifier_property_semantic(raw: i32) -> Option<&'static ModifierPropertySemantic> {
220 MODIFIER_PROPERTY_SEMANTICS
221 .iter()
222 .find(|entry| entry.kind as i32 == raw)
223}
224
225semantic_registry! {
226 kind = modifier_property_kind,
227 is = modifier_property_is,
228 is_any = modifier_property_is_any,
229 raw = modifier_property_raw,
230 semantic = modifier_property_semantic,
231 registry = MODIFIER_PROPERTY_SEMANTICS,
232 type = ModifierPropertyKind
233}
234
235pub trait SpellEffectSemanticExt {
237 fn effect_is(&self, expected: SpellEffectKind) -> bool;
238 fn effect_is_any(&self, expected: &[SpellEffectKind]) -> bool;
239 fn aura_is(&self, expected: AuraSubtypeKind) -> bool;
240 fn aura_is_any(&self, expected: &[AuraSubtypeKind]) -> bool;
241 fn modifier_property_is(&self, expected: ModifierPropertyKind) -> bool;
242 fn modifier_property_is_any(&self, expected: &[ModifierPropertyKind]) -> bool;
243}
244
245impl SpellEffectSemanticExt for SpellEffect {
246 fn effect_is(&self, expected: SpellEffectKind) -> bool {
247 spell_effect_is(self.effect, expected)
248 }
249
250 fn effect_is_any(&self, expected: &[SpellEffectKind]) -> bool {
251 spell_effect_is_any(self.effect, expected)
252 }
253
254 fn aura_is(&self, expected: AuraSubtypeKind) -> bool {
255 aura_subtype_is(self.aura, expected)
256 }
257
258 fn aura_is_any(&self, expected: &[AuraSubtypeKind]) -> bool {
259 aura_subtype_is_any(self.aura, expected)
260 }
261
262 fn modifier_property_is(&self, expected: ModifierPropertyKind) -> bool {
263 raw_modifier_property_is(self.misc_value_0, expected)
264 }
265
266 fn modifier_property_is_any(&self, expected: &[ModifierPropertyKind]) -> bool {
267 raw_modifier_property_is_any(self.misc_value_0, expected)
268 }
269}
270
271#[must_use]
273pub fn modifier_combination_supported(
274 aura: &AuraSubtypeSemantic,
275 property: &ModifierPropertySemantic,
276) -> bool {
277 aura.modifier.is_some_and(|(operation, _)| {
278 let required = match operation {
279 ModifierOperation::Flat => ModifierOperations::FLAT,
280 ModifierOperation::Percent => ModifierOperations::PERCENT,
281 };
282
283 property.operations.contains(required)
284 })
285}
286
287#[cfg(test)]
288mod tests;