1#[derive(Clone, Copy, Debug, Eq, PartialEq)]
5#[non_exhaustive]
6pub enum ResolvedDamageKind {
7 Ap,
8 Sp,
9 Flat,
10 Weapon,
11 WeaponPercent,
12 NormalizedWeapon,
13}
14
15#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
17#[non_exhaustive]
18pub enum ResolvedDamageWeapon {
19 #[default]
20 MainHand,
21 OffHand,
22}
23
24#[derive(Clone, Copy, Debug)]
26pub struct ResolvedDamageDef {
27 pub kind: ResolvedDamageKind,
28 pub coefficient: f64,
29 pub base_points: f64,
30 pub is_physical: bool,
31 pub effect_index: u8,
32 pub weapon: ResolvedDamageWeapon,
33}
34
35#[derive(Clone, Debug, Default)]
37#[expect(
38 clippy::struct_excessive_bools,
39 reason = "this flat DBC transfer object preserves independent spell flags"
40)]
41pub struct SpellProps {
42 pub attributes: Vec<i32>,
43 pub defense_type: i32,
45 pub dispel_type: i32,
47 pub mechanic: i32,
49 pub can_empower: bool,
50 pub empower_stages: Vec<wowlab_types::data::EmpowerStage>,
51 pub equipped_item_requirement: Option<wowlab_types::data::EquippedItemRequirement>,
52 pub shapeshift_required_mask: u64,
53 pub shapeshift_excluded_mask: u64,
54 pub caster_aura_spell: i32,
55 pub caster_aura_state: i32,
56 pub exclude_caster_aura_spell: i32,
57 pub exclude_caster_aura_state: i32,
58 pub target_aura_spell: i32,
59 pub target_aura_state: i32,
60 pub exclude_target_aura_spell: i32,
61 pub exclude_target_aura_state: i32,
62 pub aura_interrupt_flags: u32,
64 pub spell_interrupt_flags: u32,
66 pub channel_interrupt_flags: u32,
68 pub cost: f64,
69 pub optional_cost: f64,
70 pub cost_pct: wowlab_types::data::ResourceCostPercent,
71 pub max_cost_pct: wowlab_types::data::ResourceCostPercent,
72 pub optional_cost_pct: wowlab_types::data::ResourceCostPercent,
73 pub gain: f64,
74 pub health_cost: f64,
76 pub health_cost_pct: f64,
78 pub health_max_cost_pct: f64,
80 pub health_optional_cost: f64,
82 pub health_optional_cost_pct: wowlab_types::data::ResourceCostPercent,
84 pub primary_cost_entry: u8,
86 pub secondary_cost_entry: u8,
88 pub secondary_cost: f64,
89 pub secondary_optional_cost: f64,
90 pub secondary_gain: f64,
91 pub cooldown_ms: i32,
92 pub cooldown_category: Option<wowlab_types::data::CooldownCategoryId>,
93 pub category_cooldown_ms: i32,
94 pub charge_category: Option<wowlab_types::data::CooldownCategoryId>,
95 pub cast_time_ms: i32,
96 pub duration_ms: i32,
97 pub max_stacks: i32,
98 pub max_charges: i32,
99 pub charge_cd_ms: i32,
100 pub start_recovery_category: Option<wowlab_types::data::CooldownCategoryId>,
101 pub gcd_ms: i32,
102 pub projectile_speed: f64,
104 pub launch_delay_s: f64,
106 pub hostile_min_range: f64,
108 pub hostile_max_range: f64,
110 pub radius: f64,
112 pub chain_target_range: f64,
114 pub max_affected_targets: u8,
116 pub cone_half_angle: f64,
118 pub fixed_travel_time: bool,
120 pub ignores_line_of_sight: bool,
121 pub explicit_target_mask: u32,
122 pub required_explicit_target_mask: u32,
124 pub cooldown_hasted: bool,
125 pub gcd_haste_type: wowlab_types::combat::GcdHasteType,
126 pub hasted_ticks: bool,
127 pub duration_hasted: bool,
128 pub mastery_affects_points: bool,
130 pub cannot_crit: bool,
131 pub requires_unshifted: bool,
132 pub allow_while_unshifted: bool,
133 pub requires_stealth: bool,
134 pub requires_behind_target: bool,
136 pub treat_as_periodic: bool,
137 pub treat_as_area_effect: bool,
138 pub does_not_break_stealth: bool,
139 pub usable_while_casting: bool,
140 pub usable_while_moving: bool,
141 pub asynchronous_stacks: bool,
142 pub disable_player_damage_multiplier: bool,
143 pub disable_target_damage_multiplier: bool,
144 pub disable_positive_target_damage_multiplier: bool,
145 pub requires_main_hand: bool,
146 pub requires_off_hand: bool,
147 pub refresh_behavior: wowlab_types::data::RefreshBehavior,
148 pub rolling_periodic: bool,
149 pub tick_may_crit: bool,
150 pub tick_on_application: bool,
151 pub proc_chance_pct: i32,
153 pub proc_charges: i32,
155 pub proc_attributes: u32,
157 pub proc_chance_multiplier_delta: f64,
159 pub proc_type_mask: u64,
161 pub proc_category_recovery_ms: i32,
163 pub rppm_base_rate: f64,
165 pub rppm_flags: i32,
167 pub rppm_haste_scales: bool,
169 pub rppm_crit_scales: bool,
171 pub hit_chance_flat: f64,
173 pub hit_chance_multiplier: f64,
174 pub target_resistance_flat: f64,
176 pub target_resistance_multiplier: f64,
177 pub dispel_resistance_flat: f64,
179 pub dispel_resistance_multiplier: f64,
180}
181
182pub(crate) const fn normalize_spell_modifier_defaults(mut props: SpellProps) -> SpellProps {
183 if props.hit_chance_multiplier.to_bits() == 0
184 && props.target_resistance_multiplier.to_bits() == 0
185 && props.dispel_resistance_multiplier.to_bits() == 0
186 {
187 props.hit_chance_multiplier = 1.0;
188 props.target_resistance_multiplier = 1.0;
189 props.dispel_resistance_multiplier = 1.0;
190 }
191
192 props
193}
194
195pub(crate) fn neutral_spell_props() -> SpellProps {
196 normalize_spell_modifier_defaults(SpellProps::default())
197}
198
199#[derive(Clone, Copy, Debug)]
201pub struct DamageSpellProperties {
202 pub defense_type: i32,
203 pub hit_chance_flat: f64,
204 pub hit_chance_multiplier: f64,
205 pub target_resistance_flat: f64,
206 pub target_resistance_multiplier: f64,
207 pub dispel_type: i32,
208 pub dispel_resistance_flat: f64,
209 pub dispel_resistance_multiplier: f64,
210 pub mastery_affects_points: bool,
211 pub primary_cost_entry: u8,
212 pub secondary_cost_entry: u8,
213}
214
215impl Default for DamageSpellProperties {
216 fn default() -> Self {
217 Self {
218 defense_type: 0,
219 hit_chance_flat: 0.0,
220 hit_chance_multiplier: 1.0,
221 target_resistance_flat: 0.0,
222 target_resistance_multiplier: 1.0,
223 dispel_type: 0,
224 dispel_resistance_flat: 0.0,
225 dispel_resistance_multiplier: 1.0,
226 mastery_affects_points: false,
227 primary_cost_entry: 0,
228 secondary_cost_entry: 0,
229 }
230 }
231}
232
233#[derive(Clone, Debug, Default)]
235pub struct AuraProps {
236 pub duration_ms: i32,
237 pub doses: i32,
239 pub max_stacks: i32,
240 pub tick_period_ms: i32,
241 pub pandemic: bool,
242}
243
244#[derive(Clone, Debug, Default)]
246pub struct PowerTypeProps {
247 pub display_modifier: f64,
248 pub max_base_power: f64,
249 pub default_power: f64,
250 pub regen_combat: f64,
251 pub regen_percent_of_max: f64,
252 pub auto_attack_gain_percent: f64,
253 pub cost_percent: f64,
254}
255
256pub(crate) const fn default_aura_props() -> AuraProps {
257 AuraProps {
258 duration_ms: 0,
259 doses: 1,
260 max_stacks: 1,
261 tick_period_ms: 0,
262 pandemic: false,
263 }
264}