wowlab_engine_domain/dbc/semantics/
coverage.rs1use wowlab_types::data::SpellEffect;
2
3use super::{
4 AuraSubtypeSemantic, ModifierPropertySemantic, SemanticSupport, SpellEffectKind,
5 SpellEffectSemantic, aura_subtype_semantic, modifier_combination_supported,
6 modifier_property_semantic, spell_effect_semantic,
7};
8
9#[derive(Clone, Copy, Debug, Eq, PartialEq)]
11#[non_exhaustive]
12pub enum EffectSemanticCoverage {
13 Supported {
14 effect: &'static SpellEffectSemantic,
15 aura: Option<&'static AuraSubtypeSemantic>,
16 property: Option<&'static ModifierPropertySemantic>,
17 },
18 Partial {
19 effect: &'static SpellEffectSemantic,
20 aura: Option<&'static AuraSubtypeSemantic>,
21 property: Option<&'static ModifierPropertySemantic>,
22 },
23 ContentRequired {
24 effect: &'static SpellEffectSemantic,
25 aura: Option<&'static AuraSubtypeSemantic>,
26 property: Option<&'static ModifierPropertySemantic>,
27 },
28 Ignored {
29 effect: &'static SpellEffectSemantic,
30 aura: Option<&'static AuraSubtypeSemantic>,
31 property: Option<&'static ModifierPropertySemantic>,
32 },
33 UnsupportedRegistered {
34 effect: &'static SpellEffectSemantic,
35 aura: Option<&'static AuraSubtypeSemantic>,
36 property: Option<&'static ModifierPropertySemantic>,
37 },
38 UnsupportedEffectType(i32),
39 UnsupportedAuraSubtype(i32),
40 UnsupportedModifierProperty(i32),
41 UnsupportedModifierCombination {
42 aura: &'static AuraSubtypeSemantic,
43 property: &'static ModifierPropertySemantic,
44 },
45}
46
47#[must_use]
49pub fn effect_semantic_coverage(effect: &SpellEffect) -> EffectSemanticCoverage {
50 let Some(effect_semantic) = spell_effect_semantic(effect.effect) else {
51 return EffectSemanticCoverage::UnsupportedEffectType(effect.effect);
52 };
53
54 if !matches!(
55 effect_semantic.kind,
56 SpellEffectKind::ApplyAura | SpellEffectKind::ApplyPartyAura
57 ) {
58 return coverage_for_support(effect_semantic, None, None, effect_semantic.support);
59 }
60
61 let Some(aura) = aura_subtype_semantic(effect.aura) else {
62 return EffectSemanticCoverage::UnsupportedAuraSubtype(effect.aura);
63 };
64 let property = if aura.modifier.is_some() {
65 let Some(property) = modifier_property_semantic(effect.misc_value_0) else {
66 return EffectSemanticCoverage::UnsupportedModifierProperty(effect.misc_value_0);
67 };
68
69 if !modifier_combination_supported(aura, property) {
70 return EffectSemanticCoverage::UnsupportedModifierCombination { aura, property };
71 }
72
73 Some(property)
74 } else {
75 None
76 };
77 let support = property.map_or(aura.support, |property| {
78 combine_semantic_support(aura.support, property.support)
79 });
80
81 coverage_for_support(effect_semantic, Some(aura), property, support)
82}
83
84const fn coverage_for_support(
85 effect: &'static SpellEffectSemantic,
86 aura: Option<&'static AuraSubtypeSemantic>,
87 property: Option<&'static ModifierPropertySemantic>,
88 support: SemanticSupport,
89) -> EffectSemanticCoverage {
90 match support {
91 SemanticSupport::Generic => EffectSemanticCoverage::Supported {
92 effect,
93 aura,
94 property,
95 },
96 SemanticSupport::Partial => EffectSemanticCoverage::Partial {
97 effect,
98 aura,
99 property,
100 },
101 SemanticSupport::ContentRequired => EffectSemanticCoverage::ContentRequired {
102 effect,
103 aura,
104 property,
105 },
106 SemanticSupport::Ignored => EffectSemanticCoverage::Ignored {
107 effect,
108 aura,
109 property,
110 },
111 SemanticSupport::Unsupported => EffectSemanticCoverage::UnsupportedRegistered {
112 effect,
113 aura,
114 property,
115 },
116 }
117}
118
119const fn combine_semantic_support(
120 left: SemanticSupport,
121 right: SemanticSupport,
122) -> SemanticSupport {
123 use SemanticSupport::{ContentRequired, Generic, Ignored, Partial, Unsupported};
124
125 match (left, right) {
126 (Unsupported, _) | (_, Unsupported) => Unsupported,
127 (ContentRequired, _) | (_, ContentRequired) => ContentRequired,
128 (Ignored, _) | (_, Ignored) => Ignored,
129 (Partial, _) | (_, Partial) => Partial,
130 (Generic, Generic) => Generic,
131 }
132}