Skip to main content

wowlab_engine_content/generated/specs/
frost_mage.rs

1//! @generated by codegen-cli from manifests/specs/mage/frost/manifest.toml -- do not edit by hand.
2// Generated code: naming follows game data conventions
3#![allow(non_snake_case, dead_code)]
4use wowlab_types::{combat::ResourceType, game::SpecId};
5use wowlab_engine_domain::dbc::ProcAttributes;
6use wowlab_engine_combat::{
7    BuiltCombatSystem, AuraDefinitionDraft, LocalAuraIdx, LocalSpellIdx,
8    SpellDefinitionDraft,
9};
10use wowlab_engine_ports::{
11    DeclaredSpecMetadata, SpecDescriptor, SpecHandler, HeroTalentTreeDesc,
12    DeclaredServerProcEntry,
13};
14use wowlab_engine_gamedata::ResolvedGameData;
15pub(crate) mod SPELL {
16    ///<https://wowlab.gg/inspect/spell/116>
17    pub(crate) const FROSTBOLT: u32 = 116;
18    ///<https://wowlab.gg/inspect/spell/30455>
19    pub(crate) const ICE_LANCE: u32 = 30455;
20    ///<https://wowlab.gg/inspect/spell/44614>
21    pub(crate) const FLURRY: u32 = 44614;
22    ///<https://wowlab.gg/inspect/spell/199786>
23    pub(crate) const GLACIAL_SPIKE: u32 = 199_786;
24    ///<https://wowlab.gg/inspect/spell/84714>
25    pub(crate) const FROZEN_ORB: u32 = 84714;
26    ///<https://wowlab.gg/inspect/spell/84721>
27    pub(crate) const FROZEN_ORB_BOLT: u32 = 84721;
28    ///<https://wowlab.gg/inspect/spell/228354>
29    pub(crate) const FLURRY_BOLT: u32 = 228_354;
30    ///<https://wowlab.gg/inspect/spell/1246949>
31    pub(crate) const SHATTER_ICE_LANCE: u32 = 1_246_949;
32    ///<https://wowlab.gg/inspect/spell/443722>
33    pub(crate) const FROST_SPLINTER: u32 = 443_722;
34    ///<https://wowlab.gg/inspect/spell/190356>
35    pub(crate) const BLIZZARD: u32 = 190_356;
36    ///<https://wowlab.gg/inspect/spell/153595>
37    pub(crate) const COMET_STORM: u32 = 153_595;
38    ///<https://wowlab.gg/inspect/spell/205021>
39    pub(crate) const RAY_OF_FROST: u32 = 205_021;
40    ///<https://wowlab.gg/inspect/spell/1262769>
41    pub(crate) const HAND_OF_FROST: u32 = 1_262_769;
42    ///<https://wowlab.gg/inspect/spell/120>
43    pub(crate) const CONE_OF_COLD: u32 = 120;
44    ///<https://wowlab.gg/inspect/spell/1459>
45    pub(crate) const ARCANE_INTELLECT: u32 = 1459;
46}
47pub(crate) mod AURA {
48    ///<https://wowlab.gg/inspect/spell/44544>
49    pub(crate) const FINGERS_OF_FROST: u32 = 44544;
50    ///<https://wowlab.gg/inspect/spell/190446>
51    pub(crate) const BRAIN_FREEZE: u32 = 190_446;
52    ///<https://wowlab.gg/inspect/spell/1222865>
53    pub(crate) const GLACIAL_SPIKE: u32 = 1_222_865;
54    ///<https://wowlab.gg/inspect/spell/1247778>
55    pub(crate) const COMET_STORM: u32 = 1_247_778;
56    ///<https://wowlab.gg/inspect/spell/1221389>
57    pub(crate) const FREEZING: u32 = 1_221_389;
58    ///<https://wowlab.gg/inspect/spell/1247908>
59    pub(crate) const SPLINTERSTORM: u32 = 1_247_908;
60    ///<https://wowlab.gg/inspect/spell/1247730>
61    pub(crate) const THERMAL_VOID: u32 = 1_247_730;
62    ///<https://wowlab.gg/inspect/spell/270232>
63    pub(crate) const FREEZING_RAIN: u32 = 270_232;
64    ///<https://wowlab.gg/inspect/spell/455122>
65    pub(crate) const PERMAFROST_LANCES: u32 = 455_122;
66    ///<https://wowlab.gg/inspect/spell/1263263>
67    pub(crate) const HAND_OF_FROST: u32 = 1_263_263;
68    ///<https://wowlab.gg/inspect/spell/431177>
69    pub(crate) const FROSTFIRE_EMPOWERMENT: u32 = 431_177;
70    ///<https://wowlab.gg/inspect/spell/1459>
71    pub(crate) const ARCANE_INTELLECT_HIGHLIGHT: u32 = 1459;
72    ///<https://wowlab.gg/inspect/spell/1246811>
73    pub(crate) const IMPROVED_SHATTER: u32 = 1_246_811;
74}
75pub(crate) mod TALENT {
76    ///<https://wowlab.gg/inspect/spell/1280165>
77    pub(crate) const AUGURY_ABOUNDS: u32 = 1_280_165;
78    ///<https://wowlab.gg/inspect/spell/190356>
79    pub(crate) const BLIZZARD_1: u32 = 190_356;
80    ///<https://wowlab.gg/inspect/spell/1248829>
81    pub(crate) const BLIZZARD_2: u32 = 1_248_829;
82    ///<https://wowlab.gg/inspect/spell/190447>
83    pub(crate) const BRAIN_FREEZE: u32 = 190_447;
84    ///<https://wowlab.gg/inspect/spell/235219>
85    pub(crate) const COLD_SNAP: u32 = 235_219;
86    ///<https://wowlab.gg/inspect/spell/153595>
87    pub(crate) const COMET_STORM: u32 = 153_595;
88    ///<https://wowlab.gg/inspect/spell/378835>
89    pub(crate) const CONE_OF_FROST: u32 = 378_835;
90    ///<https://wowlab.gg/inspect/spell/1247544>
91    pub(crate) const CRYSTALLINE_REFRACTION: u32 = 1_247_544;
92    ///<https://wowlab.gg/inspect/spell/1247025>
93    pub(crate) const DEEP_SHATTER: u32 = 1_247_025;
94    ///<https://wowlab.gg/inspect/spell/385167>
95    pub(crate) const EVERLASTING_FROST: u32 = 385_167;
96    ///<https://wowlab.gg/inspect/spell/112965>
97    pub(crate) const FINGERS_OF_FROST: u32 = 112_965;
98    ///<https://wowlab.gg/inspect/spell/379993>
99    pub(crate) const FLASH_FREEZE: u32 = 379_993;
100    ///<https://wowlab.gg/inspect/spell/44614>
101    pub(crate) const FLURRY: u32 = 44614;
102    ///<https://wowlab.gg/inspect/spell/444719>
103    pub(crate) const FORCE_OF_WILL: u32 = 444_719;
104    ///<https://wowlab.gg/inspect/spell/378448>
105    pub(crate) const FRACTURED_FROST: u32 = 378_448;
106    ///<https://wowlab.gg/inspect/spell/270233>
107    pub(crate) const FREEZING_RAIN: u32 = 270_233;
108    ///<https://wowlab.gg/inspect/spell/1248825>
109    pub(crate) const FROSTBITE: u32 = 1_248_825;
110    ///<https://wowlab.gg/inspect/spell/84714>
111    pub(crate) const FROZEN_ORB: u32 = 84714;
112    ///<https://wowlab.gg/inspect/spell/205030>
113    pub(crate) const FROZEN_TOUCH: u32 = 205_030;
114    ///<https://wowlab.gg/inspect/spell/378947>
115    pub(crate) const GLACIAL_ASSAULT: u32 = 378_947;
116    ///<https://wowlab.gg/inspect/spell/451022>
117    pub(crate) const GLACIAL_SHATTER: u32 = 451_022;
118    ///<https://wowlab.gg/inspect/spell/1247798>
119    pub(crate) const GLACIATE: u32 = 1_247_798;
120    ///<https://wowlab.gg/inspect/spell/1262935>
121    pub(crate) const HAND_OF_FROST_1: u32 = 1_262_935;
122    ///<https://wowlab.gg/inspect/spell/1262981>
123    pub(crate) const HAND_OF_FROST_2: u32 = 1_262_981;
124    ///<https://wowlab.gg/inspect/spell/1263249>
125    pub(crate) const HAND_OF_FROST_3: u32 = 1_263_249;
126    ///<https://wowlab.gg/inspect/spell/1247799>
127    pub(crate) const HEART_OF_ICE: u32 = 1_247_799;
128    ///<https://wowlab.gg/inspect/spell/30455>
129    pub(crate) const ICE_LANCE: u32 = 30455;
130    ///<https://wowlab.gg/inspect/spell/1246832>
131    pub(crate) const ICICLES: u32 = 1_246_832;
132    ///<https://wowlab.gg/inspect/spell/1247769>
133    pub(crate) const IMPROVED_FLURRY: u32 = 1_247_769;
134    ///<https://wowlab.gg/inspect/spell/1261080>
135    pub(crate) const INFUSED_SPLINTERS: u32 = 1_261_080;
136    ///<https://wowlab.gg/inspect/spell/205024>
137    pub(crate) const LONELY_WINTER: u32 = 205_024;
138    ///<https://wowlab.gg/inspect/spell/460590>
139    pub(crate) const PERMAFROST_LANCES: u32 = 460_590;
140    ///<https://wowlab.gg/inspect/spell/378919>
141    pub(crate) const PIERCING_COLD: u32 = 378_919;
142    ///<https://wowlab.gg/inspect/spell/1261082>
143    pub(crate) const POLISHED_FOCUS: u32 = 1_261_082;
144    ///<https://wowlab.gg/inspect/spell/205021>
145    pub(crate) const RAY_OF_FROST: u32 = 205_021;
146    ///<https://wowlab.gg/inspect/spell/470021>
147    pub(crate) const SIGNATURE_SPELL: u32 = 470_021;
148    ///<https://wowlab.gg/inspect/spell/444986>
149    pub(crate) const SPELLFROST_TEACHINGS: u32 = 444_986;
150    ///<https://wowlab.gg/inspect/spell/444256>
151    pub(crate) const SPLINTERING_ORBS: u32 = 444_256;
152    ///<https://wowlab.gg/inspect/spell/418733>
153    pub(crate) const SPLINTERING_RAY: u32 = 418_733;
154    ///<https://wowlab.gg/inspect/spell/443739>
155    pub(crate) const SPLINTERING_SORCERY: u32 = 443_739;
156    ///<https://wowlab.gg/inspect/spell/443783>
157    pub(crate) const SPLINTERSTORM: u32 = 443_783;
158    ///<https://wowlab.gg/inspect/spell/56377>
159    pub(crate) const SPLITTING_ICE: u32 = 56377;
160    ///<https://wowlab.gg/inspect/spell/205024>
161    pub(crate) const SUMMON_WATER_ELEMENTAL: u32 = 205_024;
162    ///<https://wowlab.gg/inspect/spell/451030>
163    pub(crate) const THERMAL_VOID: u32 = 451_030;
164    ///<https://wowlab.gg/inspect/spell/1247729>
165    pub(crate) const THERMAL_VOID_TRAIT: u32 = 1_247_729;
166    ///<https://wowlab.gg/inspect/spell/451117>
167    pub(crate) const WHITE_OUT: u32 = 451_117;
168    ///<https://wowlab.gg/inspect/spell/378398>
169    pub(crate) const WINTERTIDE: u32 = 378_398;
170    ///<https://wowlab.gg/inspect/spell/378406>
171    pub(crate) const WINTERTIDE_TRAIT: u32 = 378_406;
172}
173pub(crate) mod SET_BONUS {
174    ///<https://wowlab.gg/inspect/spell/1264836>
175    pub(crate) const MID1_FROST_2PC: u32 = 1_264_836;
176    ///<https://wowlab.gg/inspect/spell/1264837>
177    pub(crate) const MID1_FROST_4PC: u32 = 1_264_837;
178}
179pub(crate) mod REPORTED_SPELL {
180    ///<https://wowlab.gg/inspect/spell/190357>
181    pub(crate) const BLIZZARD_DAMAGE: u32 = 190_357;
182    ///<https://wowlab.gg/inspect/spell/1247554>
183    pub(crate) const CRYSTALLINE_REFRACTION_DAMAGE: u32 = 1_247_554;
184    ///<https://wowlab.gg/inspect/spell/228596>
185    pub(crate) const FLURRY: u32 = 228_596;
186    ///<https://wowlab.gg/inspect/spell/228597>
187    pub(crate) const FROSTBOLT: u32 = 228_597;
188    ///<https://wowlab.gg/inspect/spell/468655>
189    pub(crate) const FROSTFIRE_BOLT_DAMAGE: u32 = 468_655;
190    ///<https://wowlab.gg/inspect/spell/228600>
191    pub(crate) const GLACIAL_SPIKE: u32 = 228_600;
192    ///<https://wowlab.gg/inspect/spell/228598>
193    pub(crate) const ICE_LANCE: u32 = 228_598;
194    ///<https://wowlab.gg/inspect/spell/443763>
195    pub(crate) const SPLINTERSTORM_DAMAGE: u32 = 443_763;
196    ///<https://wowlab.gg/inspect/spell/157997>
197    pub(crate) const WATER_JET: u32 = 157_997;
198}
199pub(crate) mod HERO {
200    pub(crate) mod FROSTFIRE {
201        pub(crate) mod SPELL {
202            ///<https://wowlab.gg/inspect/spell/1262863>
203            pub(crate) const DUALITY_PYROBLAST: u32 = 1_262_863;
204            ///<https://wowlab.gg/inspect/spell/1278079>
205            pub(crate) const FLASH_FREEZEBURN_DAMAGE: u32 = 1_278_079;
206            ///<https://wowlab.gg/inspect/spell/431044>
207            pub(crate) const FROSTFIRE_BOLT: u32 = 431_044;
208            ///<https://wowlab.gg/inspect/spell/431186>
209            pub(crate) const FROSTFIRE_EMPOWERMENT_DAMAGE: u32 = 431_186;
210            ///<https://wowlab.gg/inspect/spell/351140>
211            pub(crate) const ISOTHERMIC_METEOR: u32 = 351_140;
212            ///<https://wowlab.gg/inspect/spell/1262887>
213            pub(crate) const MOLTEN_CHILL_IGNITE: u32 = 1_262_887;
214        }
215        pub(crate) mod AURA {
216            ///<https://wowlab.gg/inspect/spell/431177>
217            pub(crate) const FROSTFIRE_EMPOWERMENT: u32 = 431_177;
218        }
219    }
220    pub(crate) mod SPELLSLINGER {
221        pub(crate) mod SPELL {
222            ///<https://wowlab.gg/inspect/spell/444487>
223            pub(crate) const CONTROLLED_INSTINCTS: u32 = 444_487;
224            ///<https://wowlab.gg/inspect/spell/379029>
225            pub(crate) const GLACIAL_ASSAULT: u32 = 379_029;
226            ///<https://wowlab.gg/inspect/spell/1262769>
227            pub(crate) const HAND_OF_FROST: u32 = 1_262_769;
228            ///<https://wowlab.gg/inspect/spell/443722>
229            pub(crate) const SPLINTER: u32 = 443_722;
230            ///<https://wowlab.gg/inspect/spell/1280757>
231            pub(crate) const WINTERS_END: u32 = 1_280_757;
232        }
233        pub(crate) mod AURA {
234            ///<https://wowlab.gg/inspect/spell/1247908>
235            pub(crate) const SPLINTERSTORM: u32 = 1_247_908;
236        }
237    }
238}
239static HERO_TREE_FROSTFIRE_SPELLS: &[(&str, u32)] = &[
240    ("DUALITY_PYROBLAST", 1_262_863),
241    ("FLASH_FREEZEBURN_DAMAGE", 1_278_079),
242    ("FROSTFIRE_BOLT", 431_044),
243    ("FROSTFIRE_EMPOWERMENT_DAMAGE", 431_186),
244    ("ISOTHERMIC_METEOR", 351_140),
245    ("MOLTEN_CHILL_IGNITE", 1_262_887),
246];
247static HERO_TREE_FROSTFIRE_AURAS: &[(&str, u32)] = &[("FROSTFIRE_EMPOWERMENT", 431_177)];
248static HERO_TREE_SPELLSLINGER_SPELLS: &[(&str, u32)] = &[
249    ("CONTROLLED_INSTINCTS", 444_487),
250    ("GLACIAL_ASSAULT", 379_029),
251    ("HAND_OF_FROST", 1_262_769),
252    ("SPLINTER", 443_722),
253    ("WINTERS_END", 1_280_757),
254];
255static HERO_TREE_SPELLSLINGER_AURAS: &[(&str, u32)] = &[("SPLINTERSTORM", 1_247_908)];
256pub(crate) const AURA_FINGERS_OF_FROST: LocalAuraIdx = LocalAuraIdx::new(0);
257pub(crate) const AURA_BRAIN_FREEZE: LocalAuraIdx = LocalAuraIdx::new(1);
258pub(crate) const AURA_GLACIAL_SPIKE: LocalAuraIdx = LocalAuraIdx::new(2);
259pub(crate) const AURA_COMET_STORM: LocalAuraIdx = LocalAuraIdx::new(3);
260pub(crate) const AURA_FREEZING: LocalAuraIdx = LocalAuraIdx::new(4);
261pub(crate) const AURA_SPLINTERSTORM: LocalAuraIdx = LocalAuraIdx::new(5);
262pub(crate) const AURA_THERMAL_VOID: LocalAuraIdx = LocalAuraIdx::new(6);
263pub(crate) const AURA_FREEZING_RAIN: LocalAuraIdx = LocalAuraIdx::new(7);
264pub(crate) const AURA_PERMAFROST_LANCES: LocalAuraIdx = LocalAuraIdx::new(8);
265pub(crate) const AURA_HAND_OF_FROST: LocalAuraIdx = LocalAuraIdx::new(9);
266pub(crate) const AURA_FROSTFIRE_EMPOWERMENT: LocalAuraIdx = LocalAuraIdx::new(10);
267pub(crate) const AURA_ARCANE_INTELLECT_HIGHLIGHT: LocalAuraIdx = LocalAuraIdx::new(11);
268pub(crate) const AURA_IMPROVED_SHATTER: LocalAuraIdx = LocalAuraIdx::new(12);
269pub(crate) const AURA_COUNT: usize = 13;
270const _: () = assert!(
271    AURA_COUNT == 13, "AURA index ABI: count changed -- update positional hook consumers"
272);
273pub(crate) const SPELL_FROSTBOLT: LocalSpellIdx = LocalSpellIdx::new(0);
274pub(crate) const SPELL_ICE_LANCE: LocalSpellIdx = LocalSpellIdx::new(1);
275pub(crate) const SPELL_FLURRY: LocalSpellIdx = LocalSpellIdx::new(2);
276pub(crate) const SPELL_GLACIAL_SPIKE: LocalSpellIdx = LocalSpellIdx::new(3);
277pub(crate) const SPELL_FROZEN_ORB: LocalSpellIdx = LocalSpellIdx::new(4);
278pub(crate) const SPELL_FROZEN_ORB_BOLT: LocalSpellIdx = LocalSpellIdx::new(5);
279pub(crate) const SPELL_FLURRY_BOLT: LocalSpellIdx = LocalSpellIdx::new(6);
280pub(crate) const SPELL_SHATTER_ICE_LANCE: LocalSpellIdx = LocalSpellIdx::new(7);
281pub(crate) const SPELL_FROST_SPLINTER: LocalSpellIdx = LocalSpellIdx::new(8);
282pub(crate) const SPELL_BLIZZARD: LocalSpellIdx = LocalSpellIdx::new(9);
283pub(crate) const SPELL_COMET_STORM: LocalSpellIdx = LocalSpellIdx::new(10);
284pub(crate) const SPELL_RAY_OF_FROST: LocalSpellIdx = LocalSpellIdx::new(11);
285pub(crate) const SPELL_HAND_OF_FROST: LocalSpellIdx = LocalSpellIdx::new(12);
286pub(crate) const SPELL_CONE_OF_COLD: LocalSpellIdx = LocalSpellIdx::new(13);
287pub(crate) const SPELL_ARCANE_INTELLECT: LocalSpellIdx = LocalSpellIdx::new(14);
288pub(crate) const SPELL_COUNT: usize = 15;
289const _: () = assert!(
290    SPELL_COUNT == 15,
291    "SPELL index ABI: count changed -- update positional hook consumers"
292);
293pub(crate) mod EFFECT {
294    ///<https://wowlab.gg/inspect/spell/190447>
295    pub(crate) const BRAIN_FREEZE_CHANCE: (u32, u8) = (190_447, 1);
296    ///<https://wowlab.gg/inspect/spell/1247025>
297    pub(crate) const DEEP_SHATTER_BONUS: (u32, u8) = (1_247_025, 1);
298    ///<https://wowlab.gg/inspect/spell/112965>
299    pub(crate) const FINGERS_OF_FROST_CHANCE: (u32, u8) = (112_965, 1);
300    ///<https://wowlab.gg/inspect/spell/379993>
301    pub(crate) const FLASH_FREEZE_FOF_CHANCE: (u32, u8) = (379_993, 1);
302    ///<https://wowlab.gg/inspect/spell/228354>
303    pub(crate) const FLURRY_BOLT_DAMAGE: (u32, u8) = (228_354, 1);
304    ///<https://wowlab.gg/inspect/spell/1246752>
305    pub(crate) const FREEZE_AND_SHATTER_DAMAGE: (u32, u8) = (1_246_752, 1);
306    ///<https://wowlab.gg/inspect/spell/1246752>
307    pub(crate) const FREEZE_AND_SHATTER_LABEL_DAMAGE: (u32, u8) = (1_246_752, 5);
308    ///<https://wowlab.gg/inspect/spell/1246752>
309    pub(crate) const FREEZE_AND_SHATTER_PERIODIC: (u32, u8) = (1_246_752, 3);
310    ///<https://wowlab.gg/inspect/spell/1246752>
311    pub(crate) const FREEZE_AND_SHATTER_SHATTER_DAMAGE: (u32, u8) = (1_246_752, 2);
312    ///<https://wowlab.gg/inspect/spell/1246752>
313    pub(crate) const FREEZE_AND_SHATTER_SHATTER_PERIODIC: (u32, u8) = (1_246_752, 4);
314    ///<https://wowlab.gg/inspect/spell/443722>
315    pub(crate) const FROST_SPLINTER_DAMAGE: (u32, u8) = (443_722, 1);
316    ///<https://wowlab.gg/inspect/spell/84721>
317    pub(crate) const FROZEN_ORB_BOLT_DAMAGE: (u32, u8) = (84721, 1);
318    ///<https://wowlab.gg/inspect/spell/1262981>
319    pub(crate) const HAND_OF_FROST_CHANCE: (u32, u8) = (1_262_981, 1);
320    ///<https://wowlab.gg/inspect/spell/1246832>
321    pub(crate) const ICICLES_PERIOD: (u32, u8) = (1_246_832, 1);
322    ///<https://wowlab.gg/inspect/spell/1264836>
323    pub(crate) const MID1_FROST_2PC_FOF_CHANCE: (u32, u8) = (1_264_836, 3);
324    ///<https://wowlab.gg/inspect/spell/1264837>
325    pub(crate) const MID1_FROST_4PC_FOF_SHATTER: (u32, u8) = (1_264_837, 1);
326    ///<https://wowlab.gg/inspect/spell/1246949>
327    pub(crate) const SHATTER_ICE_LANCE_DAMAGE: (u32, u8) = (1_246_949, 1);
328}
329static REPORTED_SPELLS: &[(&str, u32)] = &[
330    ("blizzard_damage", 190_357),
331    ("crystalline_refraction_damage", 1_247_554),
332    ("flurry", 228_596),
333    ("frostbolt", 228_597),
334    ("frostfire_bolt_damage", 468_655),
335    ("glacial_spike", 228_600),
336    ("ice_lance", 228_598),
337    ("splinterstorm_damage", 443_763),
338    ("water_jet", 157_997),
339];
340static DECLARED_SPELL_IDS: &[u32] = &[
341    116, 30455, 44614, 199_786, 84714, 84721, 228_354, 1_246_949, 443_722, 190_356,
342    153_595, 205_021, 1_262_769, 120, 1459, 44544, 190_446, 1_222_865, 1_247_778,
343    1_221_389, 1_247_908, 1_247_730, 270_232, 455_122, 1_263_263, 431_177, 1459,
344    1_246_811, 84721, 112_965, 157_997, 190_357, 190_447, 205_021, 228_354, 228_596,
345    228_597, 228_598, 228_600, 379_993, 443_722, 443_763, 468_655, 1_246_752, 1_246_832,
346    1_246_949, 1_247_025, 1_247_554, 1_262_981, 1_264_836, 1_264_837, 190_357, 1_247_554,
347    228_596, 228_597, 468_655, 228_600, 228_598, 443_763, 157_997, 1_262_863, 1_278_079,
348    431_044, 431_186, 351_140, 1_262_887, 431_177, 444_487, 379_029, 1_262_769, 443_722,
349    1_280_757, 1_247_908,
350];
351static DECLARED_AURA_IDS: &[u32] = &[
352    44544, 190_446, 1_222_865, 1_247_778, 1_221_389, 1_247_908, 1_247_730, 270_232,
353    455_122, 1_263_263, 431_177, 1459, 1_246_811, 431_177, 1_247_908,
354];
355static TALENTS: &[(&str, u32)] = &[
356    ("AUGURY_ABOUNDS", TALENT::AUGURY_ABOUNDS),
357    ("BLIZZARD_1", TALENT::BLIZZARD_1),
358    ("BLIZZARD_2", TALENT::BLIZZARD_2),
359    ("BRAIN_FREEZE", TALENT::BRAIN_FREEZE),
360    ("COLD_SNAP", TALENT::COLD_SNAP),
361    ("COMET_STORM", TALENT::COMET_STORM),
362    ("CONE_OF_FROST", TALENT::CONE_OF_FROST),
363    ("CRYSTALLINE_REFRACTION", TALENT::CRYSTALLINE_REFRACTION),
364    ("DEEP_SHATTER", TALENT::DEEP_SHATTER),
365    ("EVERLASTING_FROST", TALENT::EVERLASTING_FROST),
366    ("FINGERS_OF_FROST", TALENT::FINGERS_OF_FROST),
367    ("FLASH_FREEZE", TALENT::FLASH_FREEZE),
368    ("FLURRY", TALENT::FLURRY),
369    ("FORCE_OF_WILL", TALENT::FORCE_OF_WILL),
370    ("FRACTURED_FROST", TALENT::FRACTURED_FROST),
371    ("FREEZING_RAIN", TALENT::FREEZING_RAIN),
372    ("FROSTBITE", TALENT::FROSTBITE),
373    ("FROZEN_ORB", TALENT::FROZEN_ORB),
374    ("FROZEN_TOUCH", TALENT::FROZEN_TOUCH),
375    ("GLACIAL_ASSAULT", TALENT::GLACIAL_ASSAULT),
376    ("GLACIAL_SHATTER", TALENT::GLACIAL_SHATTER),
377    ("GLACIATE", TALENT::GLACIATE),
378    ("HAND_OF_FROST_1", TALENT::HAND_OF_FROST_1),
379    ("HAND_OF_FROST_2", TALENT::HAND_OF_FROST_2),
380    ("HAND_OF_FROST_3", TALENT::HAND_OF_FROST_3),
381    ("HEART_OF_ICE", TALENT::HEART_OF_ICE),
382    ("ICE_LANCE", TALENT::ICE_LANCE),
383    ("ICICLES", TALENT::ICICLES),
384    ("IMPROVED_FLURRY", TALENT::IMPROVED_FLURRY),
385    ("INFUSED_SPLINTERS", TALENT::INFUSED_SPLINTERS),
386    ("LONELY_WINTER", TALENT::LONELY_WINTER),
387    ("PERMAFROST_LANCES", TALENT::PERMAFROST_LANCES),
388    ("PIERCING_COLD", TALENT::PIERCING_COLD),
389    ("POLISHED_FOCUS", TALENT::POLISHED_FOCUS),
390    ("RAY_OF_FROST", TALENT::RAY_OF_FROST),
391    ("SIGNATURE_SPELL", TALENT::SIGNATURE_SPELL),
392    ("SPELLFROST_TEACHINGS", TALENT::SPELLFROST_TEACHINGS),
393    ("SPLINTERING_ORBS", TALENT::SPLINTERING_ORBS),
394    ("SPLINTERING_RAY", TALENT::SPLINTERING_RAY),
395    ("SPLINTERING_SORCERY", TALENT::SPLINTERING_SORCERY),
396    ("SPLINTERSTORM", TALENT::SPLINTERSTORM),
397    ("SPLITTING_ICE", TALENT::SPLITTING_ICE),
398    ("SUMMON_WATER_ELEMENTAL", TALENT::SUMMON_WATER_ELEMENTAL),
399    ("THERMAL_VOID", TALENT::THERMAL_VOID),
400    ("THERMAL_VOID_TRAIT", TALENT::THERMAL_VOID_TRAIT),
401    ("WHITE_OUT", TALENT::WHITE_OUT),
402    ("WINTERTIDE", TALENT::WINTERTIDE),
403    ("WINTERTIDE_TRAIT", TALENT::WINTERTIDE_TRAIT),
404];
405pub(crate) mod FROST_MAGE {
406    pub(crate) const FROSTBOLT_CASTS: u32 = 0;
407    pub(crate) const ICE_LANCE_CASTS: u32 = 1;
408    pub(crate) const FLURRY_CASTS: u32 = 2;
409    pub(crate) const GLACIAL_SPIKE_CASTS: u32 = 3;
410    pub(crate) const FROZEN_ORB_CASTS: u32 = 4;
411    pub(crate) const RAY_OF_FROST_CASTS: u32 = 5;
412    pub(crate) const COMET_STORM_CASTS: u32 = 6;
413    pub(crate) const FINGERS_OF_FROST_UPTIME_MS: u32 = 7;
414}
415fn aura_fingers_of_frost(
416    a: AuraDefinitionDraft,
417    data: &ResolvedGameData,
418) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
419    Ok(
420        a
421            .on_player()
422            .apply_base_from_data(data, 44544)?
423            .max_stacks(
424                data
425                    .require_aura_max_stacks(
426                        wowlab_types::sim::SpellIdx::from_raw(44544),
427                    )?,
428            ),
429    )
430}
431fn aura_brain_freeze(
432    a: AuraDefinitionDraft,
433    data: &ResolvedGameData,
434) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
435    Ok(
436        a
437            .on_player()
438            .apply_base_from_data(data, 190_446)?
439            .max_stacks(
440                data
441                    .require_aura_max_stacks(
442                        wowlab_types::sim::SpellIdx::from_raw(190_446),
443                    )?,
444            ),
445    )
446}
447fn aura_glacial_spike(
448    a: AuraDefinitionDraft,
449    data: &ResolvedGameData,
450) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
451    Ok(
452        a
453            .on_player()
454            .apply_base_from_data(data, 1_222_865)?
455            .max_stacks(
456                wowlab_engine_combat::validated_max_stacks(
457                    5.0,
458                    1_222_865,
459                    "aura.max_stacks",
460                )?,
461            ),
462    )
463}
464fn aura_comet_storm(
465    a: AuraDefinitionDraft,
466    data: &ResolvedGameData,
467) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
468    Ok(
469        a
470            .on_player()
471            .apply_base_from_data(data, 1_247_778)?
472            .max_stacks(
473                data
474                    .require_aura_max_stacks(
475                        wowlab_types::sim::SpellIdx::from_raw(1_247_778),
476                    )?,
477            ),
478    )
479}
480fn aura_freezing(
481    a: AuraDefinitionDraft,
482    data: &ResolvedGameData,
483) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
484    Ok(
485        a
486            .on_target()
487            .apply_base_from_data(data, 1_221_389)?
488            .max_stacks(
489                data
490                    .require_aura_max_stacks(
491                        wowlab_types::sim::SpellIdx::from_raw(1_221_389),
492                    )?,
493            ),
494    )
495}
496fn aura_splinterstorm(
497    a: AuraDefinitionDraft,
498    data: &ResolvedGameData,
499) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
500    Ok(
501        a
502            .on_player()
503            .apply_base_from_data(data, 1_247_908)?
504            .max_stacks(
505                data
506                    .require_aura_max_stacks(
507                        wowlab_types::sim::SpellIdx::from_raw(1_247_908),
508                    )?,
509            ),
510    )
511}
512fn aura_thermal_void(
513    a: AuraDefinitionDraft,
514    data: &ResolvedGameData,
515) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
516    Ok(
517        a
518            .on_player()
519            .apply_base_from_data(data, 1_247_730)?
520            .max_stacks(
521                data
522                    .require_aura_max_stacks(
523                        wowlab_types::sim::SpellIdx::from_raw(1_247_730),
524                    )?,
525            ),
526    )
527}
528fn aura_freezing_rain(
529    a: AuraDefinitionDraft,
530    data: &ResolvedGameData,
531) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
532    Ok(
533        a
534            .on_player()
535            .apply_base_from_data(data, 270_232)?
536            .max_stacks(
537                data
538                    .require_aura_max_stacks(
539                        wowlab_types::sim::SpellIdx::from_raw(270_232),
540                    )?,
541            ),
542    )
543}
544fn aura_permafrost_lances(
545    a: AuraDefinitionDraft,
546    data: &ResolvedGameData,
547) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
548    Ok(
549        a
550            .on_player()
551            .apply_base_from_data(data, 455_122)?
552            .max_stacks(
553                data
554                    .require_aura_max_stacks(
555                        wowlab_types::sim::SpellIdx::from_raw(455_122),
556                    )?,
557            ),
558    )
559}
560fn aura_hand_of_frost(
561    a: AuraDefinitionDraft,
562    data: &ResolvedGameData,
563) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
564    Ok(
565        a
566            .on_player()
567            .apply_base_from_data(data, 1_263_263)?
568            .max_stacks(
569                data
570                    .require_aura_max_stacks(
571                        wowlab_types::sim::SpellIdx::from_raw(1_263_263),
572                    )?,
573            )
574            .async_stacks(),
575    )
576}
577fn aura_frostfire_empowerment(
578    a: AuraDefinitionDraft,
579    data: &ResolvedGameData,
580) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
581    Ok(
582        a
583            .on_player()
584            .apply_base_from_data(data, 431_177)?
585            .max_stacks(
586                data
587                    .require_aura_max_stacks(
588                        wowlab_types::sim::SpellIdx::from_raw(431_177),
589                    )?,
590            ),
591    )
592}
593fn aura_arcane_intellect_highlight(
594    a: AuraDefinitionDraft,
595    data: &ResolvedGameData,
596) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
597    Ok(
598        a
599            .on_player()
600            .apply_base_from_data(data, 1459)?
601            .max_stacks(
602                data
603                    .require_aura_max_stacks(
604                        wowlab_types::sim::SpellIdx::from_raw(1459),
605                    )?,
606            ),
607    )
608}
609fn aura_improved_shatter(
610    a: AuraDefinitionDraft,
611    data: &ResolvedGameData,
612) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
613    Ok(
614        a
615            .on_player()
616            .apply_base_from_data(data, 1_246_811)?
617            .max_stacks(
618                data
619                    .require_aura_max_stacks(
620                        wowlab_types::sim::SpellIdx::from_raw(1_246_811),
621                    )?,
622            ),
623    )
624}
625fn spell_frostbolt(
626    s: SpellDefinitionDraft,
627    data: &ResolvedGameData,
628) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
629    Ok(
630        s
631            .apply_base_from_data(data, 116)?
632            .apply_aoe_from_data(data)
633            .on_cast(crate::hooks::frost_mage::frostbolt_hook)
634            .overridden_by(SPELL::GLACIAL_SPIKE, AURA::GLACIAL_SPIKE)
635            .override_at_min_stacks(5),
636    )
637}
638fn spell_ice_lance(
639    s: SpellDefinitionDraft,
640    data: &ResolvedGameData,
641) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
642    Ok(
643        s
644            .apply_base_from_data(data, 30455)?
645            .damage_sp_from_data(
646                wowlab_engine_domain::dbc::EffectLookup::new(
647                    data,
648                    wowlab_types::sim::EffectRef::new(
649                        wowlab_types::sim::SpellIdx::from_raw(228_598),
650                        1,
651                    ),
652                ),
653            )?
654            .apply_aoe_from_data(data)
655            .on_cast(crate::hooks::frost_mage::ice_lance_hook),
656    )
657}
658fn spell_flurry(
659    s: SpellDefinitionDraft,
660    data: &ResolvedGameData,
661) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
662    Ok(
663        s
664            .apply_base_from_data(data, 44614)?
665            .damage_flat(0.0)
666            .apply_aoe_from_data(data)
667            .on_cast(crate::hooks::frost_mage::flurry_hook),
668    )
669}
670fn spell_glacial_spike(
671    s: SpellDefinitionDraft,
672    data: &ResolvedGameData,
673) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
674    Ok(
675        s
676            .apply_base_from_data(data, 199_786)?
677            .damage_sp_from_data(
678                wowlab_engine_domain::dbc::EffectLookup::new(
679                    data,
680                    wowlab_types::sim::EffectRef::new(
681                        wowlab_types::sim::SpellIdx::from_raw(228_600),
682                        1,
683                    ),
684                ),
685            )?
686            .applies_inferred_aura(AURA_GLACIAL_SPIKE, 1_222_865)
687            .apply_aoe_from_data(data)
688            .on_cast(crate::hooks::frost_mage::glacial_spike_hook),
689    )
690}
691fn spell_frozen_orb(
692    s: SpellDefinitionDraft,
693    data: &ResolvedGameData,
694) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
695    Ok(
696        s
697            .apply_base_from_data(data, 84714)?
698            .apply_aoe_from_data(data)
699            .on_cast(crate::hooks::frost_mage::frozen_orb_hook),
700    )
701}
702fn spell_frozen_orb_bolt(
703    s: SpellDefinitionDraft,
704    data: &ResolvedGameData,
705) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
706    Ok(s.apply_base_from_data(data, 84721)?.apply_aoe_from_data(data))
707}
708fn spell_flurry_bolt(
709    s: SpellDefinitionDraft,
710    data: &ResolvedGameData,
711) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
712    Ok(s.apply_base_from_data(data, 228_354)?.apply_aoe_from_data(data))
713}
714fn spell_shatter_ice_lance(
715    s: SpellDefinitionDraft,
716    data: &ResolvedGameData,
717) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
718    Ok(s.apply_base_from_data(data, 1_246_949)?.apply_aoe_from_data(data))
719}
720fn spell_frost_splinter(
721    s: SpellDefinitionDraft,
722    data: &ResolvedGameData,
723) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
724    Ok(s.apply_base_from_data(data, 443_722)?.apply_aoe_from_data(data))
725}
726fn spell_blizzard(
727    s: SpellDefinitionDraft,
728    data: &ResolvedGameData,
729) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
730    Ok(s.apply_base_from_data(data, 190_356)?.apply_aoe_from_data(data))
731}
732fn spell_comet_storm(
733    s: SpellDefinitionDraft,
734    data: &ResolvedGameData,
735) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
736    Ok(
737        s
738            .apply_base_from_data(data, 153_595)?
739            .applies_aura(AURA_COMET_STORM)
740            .apply_aoe_from_data(data),
741    )
742}
743fn spell_ray_of_frost(
744    s: SpellDefinitionDraft,
745    data: &ResolvedGameData,
746) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
747    Ok(
748        s
749            .apply_base_from_data(data, 205_021)?
750            .apply_aoe_from_data(data)
751            .channel(
752                wowlab_engine_combat::validated_channel_tick_count(
753                    8.0,
754                    205_021,
755                    "channel.tick_count",
756                )?,
757            )
758            .channel_tick_damage_sp_from_data(
759                wowlab_engine_domain::dbc::EffectLookup::new(
760                    data,
761                    wowlab_types::sim::EffectRef::new(
762                        wowlab_types::sim::SpellIdx::from_raw(205_021),
763                        1,
764                    ),
765                ),
766            )?
767            .on_cast(crate::hooks::frost_mage::ray_of_frost_hook),
768    )
769}
770fn spell_hand_of_frost(
771    s: SpellDefinitionDraft,
772    data: &ResolvedGameData,
773) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
774    Ok(
775        s
776            .apply_base_from_data(data, 1_262_769)?
777            .applies_inferred_aura(AURA_HAND_OF_FROST, 1_263_263)
778            .apply_aoe_from_data(data),
779    )
780}
781fn spell_cone_of_cold(
782    s: SpellDefinitionDraft,
783    data: &ResolvedGameData,
784) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
785    Ok(s.apply_base_from_data(data, 120)?.apply_aoe_from_data(data))
786}
787fn spell_arcane_intellect(
788    s: SpellDefinitionDraft,
789    data: &ResolvedGameData,
790) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
791    Ok(
792        s
793            .apply_base_from_data(data, 1459)?
794            .applies_inferred_aura(AURA_ARCANE_INTELLECT_HIGHLIGHT, 1459)
795            .apply_aoe_from_data(data),
796    )
797}
798pub(crate) fn build_combat_system(
799    params: &wowlab_engine_ports::HandlerParams<'_>,
800) -> Result<BuiltCombatSystem, wowlab_engine_ports::EngineError> {
801    let builder = BuiltCombatSystem::builder(params.stats.clone())
802        .spec_id(SpecId::FrostMage)
803        .hero_talent_trees(DECLARED_METADATA.hero_talent_trees)
804        .mastery_spell(1_246_752)
805        .mastery_hook(crate::hooks::frost_mage::mastery)
806        .resource(
807            "mana",
808            100_000.0,
809            params
810                .game_data
811                .power_regen_for_max(0, 100_000.0)
812                .ok_or_else(|| {
813                    wowlab_engine_ports::EngineError::spec_construction(
814                        "missing power-type power_regen_for_max for type_id 0",
815                    )
816                })?,
817        )
818        .resource_type_id(0)
819        .resource_start(100_000.0)
820        .mastery_crit_damage_hook(crate::hooks::frost_mage::crit_damage)
821        .aura(
822            "fingers_of_frost",
823            AURA::FINGERS_OF_FROST,
824            |a| aura_fingers_of_frost(a, &params.game_data),
825        )
826        .aura(
827            "brain_freeze",
828            AURA::BRAIN_FREEZE,
829            |a| aura_brain_freeze(a, &params.game_data),
830        )
831        .aura(
832            "glacial_spike",
833            AURA::GLACIAL_SPIKE,
834            |a| aura_glacial_spike(a, &params.game_data),
835        )
836        .aura(
837            "comet_storm",
838            AURA::COMET_STORM,
839            |a| aura_comet_storm(a, &params.game_data),
840        )
841        .aura("freezing", AURA::FREEZING, |a| aura_freezing(a, &params.game_data))
842        .aura(
843            "splinterstorm",
844            AURA::SPLINTERSTORM,
845            |a| aura_splinterstorm(a, &params.game_data),
846        )
847        .aura(
848            "thermal_void",
849            AURA::THERMAL_VOID,
850            |a| aura_thermal_void(a, &params.game_data),
851        )
852        .aura(
853            "freezing_rain",
854            AURA::FREEZING_RAIN,
855            |a| aura_freezing_rain(a, &params.game_data),
856        )
857        .aura(
858            "permafrost_lances",
859            AURA::PERMAFROST_LANCES,
860            |a| aura_permafrost_lances(a, &params.game_data),
861        )
862        .aura(
863            "hand_of_frost",
864            AURA::HAND_OF_FROST,
865            |a| aura_hand_of_frost(a, &params.game_data),
866        )
867        .aura(
868            "frostfire_empowerment",
869            AURA::FROSTFIRE_EMPOWERMENT,
870            |a| aura_frostfire_empowerment(a, &params.game_data),
871        )
872        .aura(
873            "arcane_intellect_highlight",
874            AURA::ARCANE_INTELLECT_HIGHLIGHT,
875            |a| aura_arcane_intellect_highlight(a, &params.game_data),
876        )
877        .aura(
878            "improved_shatter",
879            AURA::IMPROVED_SHATTER,
880            |a| aura_improved_shatter(a, &params.game_data),
881        )
882        .spell("frostbolt", SPELL::FROSTBOLT, |s| spell_frostbolt(s, &params.game_data))
883        .spell("ice_lance", SPELL::ICE_LANCE, |s| spell_ice_lance(s, &params.game_data))
884        .spell("flurry", SPELL::FLURRY, |s| spell_flurry(s, &params.game_data))
885        .spell(
886            "glacial_spike",
887            SPELL::GLACIAL_SPIKE,
888            |s| spell_glacial_spike(s, &params.game_data),
889        )
890        .spell(
891            "frozen_orb",
892            SPELL::FROZEN_ORB,
893            |s| spell_frozen_orb(s, &params.game_data),
894        )
895        .spell(
896            "frozen_orb_bolt",
897            SPELL::FROZEN_ORB_BOLT,
898            |s| spell_frozen_orb_bolt(s, &params.game_data),
899        )
900        .spell(
901            "flurry_bolt",
902            SPELL::FLURRY_BOLT,
903            |s| spell_flurry_bolt(s, &params.game_data),
904        )
905        .spell(
906            "shatter_ice_lance",
907            SPELL::SHATTER_ICE_LANCE,
908            |s| spell_shatter_ice_lance(s, &params.game_data),
909        )
910        .spell(
911            "frost_splinter",
912            SPELL::FROST_SPLINTER,
913            |s| spell_frost_splinter(s, &params.game_data),
914        )
915        .spell("blizzard", SPELL::BLIZZARD, |s| spell_blizzard(s, &params.game_data))
916        .spell(
917            "comet_storm",
918            SPELL::COMET_STORM,
919            |s| spell_comet_storm(s, &params.game_data),
920        )
921        .spell(
922            "ray_of_frost",
923            SPELL::RAY_OF_FROST,
924            |s| spell_ray_of_frost(s, &params.game_data),
925        )
926        .spell(
927            "hand_of_frost",
928            SPELL::HAND_OF_FROST,
929            |s| spell_hand_of_frost(s, &params.game_data),
930        )
931        .spell(
932            "cone_of_cold",
933            SPELL::CONE_OF_COLD,
934            |s| spell_cone_of_cold(s, &params.game_data),
935        )
936        .spell(
937            "arcane_intellect",
938            SPELL::ARCANE_INTELLECT,
939            |s| spell_arcane_intellect(s, &params.game_data),
940        )
941        .game_data(params.game_data.clone())
942        .talent_spell_ids(TALENTS)
943        .talent_selections(params.talent_selections)
944        .set_bonus_auras(params.set_bonus_auras)
945        .encounter(params.encounter.clone());
946    let builder = crate::generated::items::register_equipped(
947        builder,
948        &params.game_data,
949        params.equipped_items,
950    )?;
951
952    builder
953        .build(params.rotation)
954        .map_err(wowlab_engine_ports::EngineError::rotation_compile)
955}
956fn new_handler(
957    params: wowlab_engine_ports::HandlerParams<'_>,
958) -> Result<Box<dyn SpecHandler>, wowlab_engine_ports::EngineError> {
959    let handler = crate::composition::compose_handler(
960        build_combat_system,
961        &params,
962        crate::hooks::frost_mage::FrostHandler::try_new,
963    )?;
964
965    Ok(Box::new(handler))
966}
967static DECLARED_METADATA: DeclaredSpecMetadata = DeclaredSpecMetadata {
968    primary_resource: ResourceType::Mana,
969    secondary_resource: None,
970    spell_ids: DECLARED_SPELL_IDS,
971    aura_ids: DECLARED_AURA_IDS,
972    server_proc_entries: &[
973        DeclaredServerProcEntry {
974            spell_id: 44544,
975            attributes: ProcAttributes::USE_STACKS_FOR_CHARGES.bits(),
976        },
977    ],
978    talents: TALENTS,
979    rotation_field_schema: &[],
980    metrics_plugin_id: None,
981    hero_talent_trees: &[
982        HeroTalentTreeDesc {
983            name: "Frostfire",
984            spells: HERO_TREE_FROSTFIRE_SPELLS,
985            auras: HERO_TREE_FROSTFIRE_AURAS,
986        },
987        HeroTalentTreeDesc {
988            name: "Spellslinger",
989            spells: HERO_TREE_SPELLSLINGER_SPELLS,
990            auras: HERO_TREE_SPELLSLINGER_AURAS,
991        },
992    ],
993    reported_spells: REPORTED_SPELLS,
994    masked_passive_effects: &[],
995    passive_effect_overrides: &[],
996};
997pub(super) const SPEC_DESCRIPTOR: SpecDescriptor = SpecDescriptor {
998    spec_id: SpecId::FrostMage,
999    display_name: "Frost Mage",
1000    metadata: DECLARED_METADATA,
1001    handler_factory: new_handler,
1002};
1003wowlab_engine_combat::smoke_test!(build_combat_system);