Skip to main content

wowlab_engine_combat/builder/def/
spell.rs

1use wowlab_engine_macros::LowerData;
2use wowlab_types::game::CdrEffect;
3
4use super::{BuilderDamageDef, BuilderSpellEffect, BuilderTriggerProgramPredicate};
5use crate::{
6    builder::lower::{self, BuilderToRuntimeCtx, InfoCtx},
7    state::LocalAuraIdx,
8};
9
10#[derive(Clone, Debug, LowerData)]
11#[expect(
12    clippy::struct_excessive_bools,
13    reason = "lowered spell behavior preserves independent DBC flags"
14)]
15#[lower(
16    data = "crate::state::SpellData",
17    ctx = "BuilderToRuntimeCtx<'_>",
18    extra(
19        behavior = lower::spell_behavior,
20        damage_policy = lower::spell_damage_policy,
21        cost = lower::spell_cost,
22        cooldown = lower::spell_cooldown,
23        channel = lower::spell_channel,
24        targeting = lower::spell_targeting,
25        requirements = lower::spell_requirements,
26        overrides = lower::spell_override,
27        followup_effects = lower::spell_followup_effects,
28        empower_cast_time_offset = lower::spell_empower_cast_time_offset,
29        empower_rank_count = lower::spell_empower_rank_count,
30    ),
31    info = "wowlab_types::game::SpellInfo",
32    info_ctx = "InfoCtx<'_>",
33    info_fields(
34        spell_id,
35        name = lower::spell_name,
36        slug = lower::spell_slug,
37        cast_time_ms,
38        start_recovery_category = lower::spell_info_start_recovery_category,
39        off_gcd = lower::spell_info_off_gcd,
40        gcd_ms,
41        is_pet = lower::spell_info_is_pet,
42        breaks_stealth = lower::spell_info_breaks_stealth,
43        resource_cost = lower::spell_info_resource_cost,
44        resource_gain = lower::spell_info_resource_gain,
45        secondary_resource_cost = lower::spell_info_secondary_resource_cost,
46        secondary_resource_gain = lower::spell_info_secondary_resource_gain,
47        damage = lower::spell_damage_info,
48        applies_aura_id = lower::spell_applies_aura_id,
49        cooldown = lower::spell_cooldown_info,
50        cdr_effects = lower::spell_cdr_effects_info,
51    ),
52    finalize = "crate::builder::spell_builder::SpellDefinitionDraft",
53    finalize_method = "from_draft",
54    finalize_args(
55        spell_id: u32,
56        name: String,
57        travel: crate::travel::SpellTravelData,
58        cooldown: Option<CooldownDef>,
59        damage_effect: crate::state::DamageEffectRef,
60        channel_tick_spell_id: u32,
61    ),
62)]
63pub(crate) struct BuilderSpellDef {
64    #[lower(copy)]
65    pub(crate) spell_id: u32,
66    #[lower(name_idx = lower::resolve_name_idx)]
67    pub(crate) name: String,
68    #[lower(copy)]
69    pub(crate) cast_time_ms: u32,
70    #[lower(skip)]
71    pub(crate) empower_cast_times_ms: Vec<u32>,
72    #[lower(copy)]
73    pub(crate) max_empower_aura_id: u32,
74    #[lower(skip)]
75    pub(crate) cooldown_hasted: bool,
76    #[lower(copy)]
77    pub(crate) gcd_haste_type: wowlab_types::combat::GcdHasteType,
78    #[lower(skip)]
79    pub(crate) start_recovery_category: Option<wowlab_types::data::CooldownCategoryId>,
80    #[lower(skip)]
81    pub(crate) usable_while_casting: bool,
82    #[lower(skip)]
83    pub(crate) usable_while_moving: bool,
84    #[lower(skip)]
85    pub(crate) explicit_target_mask: u32,
86    #[lower(skip)]
87    pub(crate) required_explicit_target_mask: u32,
88    #[lower(skip)]
89    pub(crate) shapeshift_required_mask: u64,
90    #[lower(skip)]
91    pub(crate) shapeshift_excluded_mask: u64,
92    #[lower(skip)]
93    pub(crate) caster_aura_spell: i32,
94    #[lower(skip)]
95    pub(crate) caster_aura_state: Option<crate::state::AuraState>,
96    #[lower(skip)]
97    pub(crate) exclude_caster_aura_spell: i32,
98    #[lower(skip)]
99    pub(crate) exclude_caster_aura_state: Option<crate::state::AuraState>,
100    #[lower(skip)]
101    pub(crate) target_aura_spell: i32,
102    #[lower(skip)]
103    pub(crate) target_aura_state: Option<crate::state::AuraState>,
104    #[lower(skip)]
105    pub(crate) exclude_target_aura_spell: i32,
106    #[lower(skip)]
107    pub(crate) exclude_target_aura_state: Option<crate::state::AuraState>,
108    #[lower(copy)]
109    pub(crate) travel: crate::travel::SpellTravelData,
110    #[lower(copy)]
111    pub(crate) gcd_ms: u32,
112    #[lower(skip)]
113    pub(crate) cooldown: Option<CooldownDef>,
114    #[lower(skip)]
115    pub(crate) resource_cost: f64,
116    #[lower(skip)]
117    pub(crate) optional_resource_cost: f64,
118    #[lower(skip)]
119    pub(crate) resource_cost_pct: wowlab_types::data::ResourceCostPercent,
120    #[lower(skip)]
121    pub(crate) maximum_resource_cost_pct: wowlab_types::data::ResourceCostPercent,
122    #[lower(skip)]
123    pub(crate) optional_resource_cost_pct: wowlab_types::data::ResourceCostPercent,
124    #[lower(skip)]
125    pub(crate) resource_gain: f64,
126    #[lower(skip)]
127    pub(crate) secondary_resource_cost: f64,
128    #[lower(skip)]
129    pub(crate) secondary_optional_resource_cost: f64,
130    #[lower(skip)]
131    pub(crate) secondary_resource_gain: f64,
132    #[lower(skip)]
133    pub(crate) health_cost: f64,
134    #[lower(skip)]
135    pub(crate) health_cost_pct: f64,
136    #[lower(skip)]
137    pub(crate) health_max_cost_pct: f64,
138    #[lower(skip)]
139    pub(crate) health_optional_cost: f64,
140    #[lower(skip)]
141    pub(crate) health_optional_cost_pct: wowlab_types::data::ResourceCostPercent,
142    #[lower(convert = lower::spell_damage)]
143    pub(crate) damage: BuilderDamageDef,
144    #[lower(skip)]
145    pub(crate) damage_may_crit: bool,
146    #[lower(copy)]
147    pub(crate) damage_attribute_flags: crate::DamageFlags,
148    #[lower(copy)]
149    pub(crate) damage_effect: crate::state::DamageEffectRef,
150    #[lower(copy)]
151    pub(crate) base_points: f64,
152    #[lower(copy)]
153    pub(crate) applies_aura: Option<LocalAuraIdx>,
154    #[lower(skip)]
155    pub(crate) followup_effects: Vec<BuilderSpellEffect>,
156    #[lower(skip)]
157    pub(crate) trigger_program_predicates: Vec<BuilderTriggerProgramPredicate>,
158    #[lower(skip)]
159    pub(crate) infer_data_damage: bool,
160    #[lower(skip)]
161    pub(crate) cdr_effects: Vec<CdrEffect>,
162    #[lower(skip)]
163    pub(crate) is_pet: bool,
164    #[lower(skip)]
165    pub(crate) requires_unshifted: bool,
166    #[lower(skip)]
167    pub(crate) allow_while_unshifted: bool,
168    #[lower(skip)]
169    pub(crate) requires_stealth: bool,
170    #[lower(skip)]
171    pub(crate) requires_behind_target: bool,
172    #[lower(skip)]
173    pub(crate) requires_main_hand: bool,
174    #[lower(skip)]
175    pub(crate) requires_off_hand: bool,
176    #[lower(skip)]
177    pub(crate) equipped_item_requirement: Option<wowlab_types::data::EquippedItemRequirement>,
178    #[lower(skip)]
179    pub(crate) breaks_stealth: bool,
180    #[lower(skip)]
181    pub(crate) aoe_max_targets: u8,
182    #[lower(skip)]
183    pub(crate) aoe_reduced_targets: u8,
184    #[lower(skip)]
185    pub(crate) aoe_full_targets: u8,
186    #[lower(skip)]
187    pub(crate) aoe_base_mult: f64,
188    #[lower(skip)]
189    pub(crate) chain_targeting: bool,
190    #[lower(skip)]
191    pub(crate) chain_multiplier: f64,
192    #[lower(skip)]
193    pub(crate) split: bool,
194    #[lower(skip)]
195    pub(crate) is_aoe: bool,
196    #[lower(skip)]
197    pub(crate) is_channel: bool,
198    #[lower(skip)]
199    pub(crate) channel_tick_count: u8,
200    #[lower(skip)]
201    pub(crate) channel_tick_interval_ms: u32,
202    #[lower(skip)]
203    pub(crate) channel_tick_zero: bool,
204    #[lower(skip)]
205    pub(crate) channel_tick_is_periodic: bool,
206    #[lower(skip)]
207    pub(crate) channel_hasted_ticks: bool,
208    #[lower(skip)]
209    pub(crate) channel_duration_hasted: bool,
210    #[lower(skip)]
211    pub(crate) channel_tick_damage: BuilderDamageDef,
212    #[lower(skip)]
213    pub(crate) channel_tick_may_crit: bool,
214    #[lower(skip)]
215    pub(crate) channel_tick_spell_id: u32,
216    #[lower(skip)]
217    pub(crate) channel_tick_damage_alt: BuilderDamageDef,
218    #[lower(skip)]
219    pub(crate) channel_tick_damage_alt_may_crit: bool,
220    #[lower(skip)]
221    pub(crate) channel_tick_damage_alt_spell_id: u32,
222    #[lower(skip)]
223    pub(crate) channel_tick_damage_aura: u32,
224    #[lower(skip)]
225    pub(crate) channel_tick_cost: f64,
226    #[lower(skip)]
227    pub(crate) channel_tick_cost_alt: f64,
228    #[lower(skip)]
229    pub(crate) channel_tick_cost_aura: u32,
230    #[lower(skip)]
231    pub(crate) channel_tick_effects: Vec<BuilderSpellEffect>,
232    #[lower(skip)]
233    pub(crate) channel_complete_effects: Vec<BuilderSpellEffect>,
234    #[lower(skip)]
235    pub(crate) channel_gcd_on_start: bool,
236    #[lower(skip)]
237    pub(crate) channel_apply_lag: bool,
238    #[lower(skip)]
239    pub(crate) gating_aura_id: u32,
240    #[lower(skip)]
241    pub(crate) gating_aura_min_stacks: u8,
242    #[lower(skip)]
243    pub(crate) cost_bypass_aura_id: u32,
244    #[lower(skip)]
245    pub(crate) consume_aura_on_cast_id: u32,
246    #[lower(skip)]
247    pub(crate) cooldown_bypass_aura_id: u32,
248    #[lower(skip)]
249    pub(crate) execute_below_pct: f64,
250    #[lower(skip)]
251    pub(crate) instant_cast_aura_id: u32,
252    #[lower(skip)]
253    pub(crate) override_aura_id: u32,
254    #[lower(skip)]
255    pub(crate) override_spell_id: u32,
256    #[lower(skip)]
257    pub(crate) override_aura_min_stacks: u8,
258    #[lower(skip)]
259    pub(crate) override_shares_base_cooldown: bool,
260    #[lower(skip)]
261    pub(crate) override_preserves_aura: bool,
262    #[lower(skip)]
263    pub(crate) guaranteed_crit: bool,
264}
265
266#[derive(Clone, Debug)]
267pub(crate) struct CooldownDef {
268    pub(crate) duration_secs: f64,
269    pub(crate) category: Option<wowlab_types::data::CooldownCategoryId>,
270    pub(crate) category_duration_secs: f64,
271    pub(crate) charge_category: Option<wowlab_types::data::CooldownCategoryId>,
272    pub(crate) max_charges: u8,
273    pub(crate) recharge_secs: f64,
274}