1#![expect(
2 clippy::multiple_crate_versions,
3 reason = "the workspace dependency graph currently includes independently versioned transitive dependencies"
4)]
5#![expect(
6 clippy::redundant_feature_names,
7 reason = "the cross-crate test-support capability name is mandated by the shared fixture contract"
9)]
10
11#[cfg(test)]
15extern crate self as wowlab_engine_combat;
16
17mod builder;
18mod context;
19mod handler;
20#[cfg(test)]
21mod integration_tests;
22mod keys;
23mod pipeline;
24mod state;
25mod systems;
26mod targeting;
27#[cfg(any(test, feature = "test-support"))]
28#[doc(hidden)]
29pub mod test_alloc;
30#[cfg(any(test, feature = "test-support"))]
31pub mod test_support;
32mod travel;
33
34#[doc(hidden)]
39#[expect(
40 non_snake_case,
41 reason = "generated identity namespaces mirror the established constant-module convention"
42)]
43pub mod generated_identities {
44 include!(concat!(
45 env!("CARGO_MANIFEST_DIR"),
46 "/../engine-content/src/generated/identity_values.rs"
47 ));
48}
49
50#[cfg(test)]
51#[global_allocator]
52static TEST_ALLOCATOR: test_alloc::TestAllocator = test_alloc::TestAllocator;
53
54#[rustfmt::skip]
55pub use builder::{
56 BuilderError, validated_channel_tick_count, validated_max_stacks,
57 validated_milliseconds, validated_nonnegative,
58};
59pub use builder::{
60 aura_builder::{AuraDefinitionDraft, PeriodicDamageDataInput},
61 auto_attack_builder::AutoAttackDefinitionDraft,
62 built::BuiltCombatSystem,
63 combat_builder::{CombatSystemBuilder, RppmScalingOptions},
64 draft::CombatSystemDraft,
65 impact_effect_proc_builder::ImpactEffectProcDefinition,
66 spell_builder::draft::SpellDefinitionDraft,
67};
68pub use wowlab_types::combat::PeriodicDamageMode;
69#[rustfmt::skip]
70pub use context::{
71 FreeActionSource, HookCtx, HookCtxRequest, HookCtxServices,
72};
73pub use context::{
74 combat_ctx::{CombatCtx, CombatView, HookProgramView, HookView},
75 damage::DamageOutcome,
76 hook::{AuraOps, CooldownOps, DamageOps, GuardianOps, ProcOps, ResourceOps, SchedulingOps},
77};
78#[rustfmt::skip]
79pub use handler::CombatHandler;
80#[rustfmt::skip]
81pub use state::buff_effect::{
82 BuffEffect, BuffTotals, MAX_AURA_BUFF_EFFECTS, try_push_effect,
83};
84pub use state::{
85 config::BaseStats,
86 damage::{
87 DamageEffectRef, DamageReplication, DamageSource, HealthThresholdDirection,
88 RuntimeDamageDef, WeaponApType,
89 },
90 defs::{
91 aura::{AuraData, AuraTickBehavior, DynamicTickAction},
92 drivers::{
93 DriverSpellModifier, DriverSpellModifierResult, PassiveDriverEffect, PeriodicDriver,
94 WeaponEnchantBinding,
95 },
96 guardians::{
97 GuardianAbility, GuardianActionFn, GuardianEvent, GuardianHandle, GuardianSpec,
98 GuardianSummonError,
99 },
100 periodic::{PeriodicData, PeriodicKind},
101 },
102 program::{DamageActionId, DamageEffectId, config::AttackPosition},
103};
104#[rustfmt::skip]
105pub use state::defs::procs::{
106 AccumulatingImpactProc, ImpactActorFilter, ImpactChanceScale, ImpactEvent, ImpactEventData,
107 ImpactProc, ImpactProcFn, ImpactSource, LandedImpactEvent, LandedImpactProc, LandedImpactProcFn,
108 ProcDriver, ProcEventKind, ProcHitMask, ProcPhaseMask, ProcPolicy, ProcProvenance,
109 ProcTriggerSide, ResourceGainEvent, ResourceGainProc, SwingEvent, SwingHand, SwingReplacement,
110};
111pub use state::{
112 AuraBinding, CombatInstance, CombatProgram, LocalAuraIdx, LocalRppmIdx, LocalSpellIdx,
113 LocalThresholdIdx, PeriodicDriverBinding, PetResourceBinding, ProcCategoryBinding,
114 ProcCounterBinding, RppmBinding, SpecAuraBinding, SpecIdentityProof, SpecSpellBinding,
115 SpellBinding, SystemRppmBinding,
116 defs::{
117 pets::{PetAbility, PetActionBar, PetResourceModel, PetStatInheritance},
118 spell::{
119 CastHookFn, EmpowerReleaseAdjustment, MAX_AURA_APPLICATION_EXCLUSIONS, ResourcePool,
120 SpellEffectData, SpellEffectRange,
121 },
122 },
123 ground_effect::{GroundEffectDefinition, GroundEffectId},
124 resource::ResourceGainSource,
125};
126pub use wowlab_engine_rng::{RppmTracker, ThresholdTracker};
127
128#[rustfmt::skip]
129pub use systems::auras::apply::{apply_aura, apply_aura_with_duration};
130#[cfg(test)]
131pub use systems::damage_pipeline::deal_damage_ap;
132pub use systems::{
133 auras::{
134 expire::expire_aura,
135 stacks::{extend_aura, is_aura_active},
136 },
137 buffs::buff_totals,
138 channel::{clip_active_channel, process_channel_tick_for},
139 damage_pipeline::api::{DamageFlags, DamagePayload},
140 mastery::{MasteryCtx, MasteryEvent, MasteryFn, no_crit_damage, no_damage_bonus},
141 periodic::tick::process_single_aura_tick_for,
142 resources::set_primary_resource_base_regen,
143 spell_gates::set_spell_gate,
144};
145#[macro_export]
147macro_rules! smoke_test {
148 ($build_fn:path) => {
149 #[cfg(test)]
150 mod tests {
151 use super::*;
152
153 #[googletest::gtest]
154 fn build_combat_system_draft_does_not_panic() -> googletest::Result<()> {
155 let stats = wowlab_engine_ports::CombatStats::default();
156 let encounter = wowlab_engine_ports::test_support::introspection_fixture(300.0)
157 .expect("valid smoke-test encounter proof");
158 let game_data =
159 wowlab_engine_ports::test_support::introspection_game_data(&encounter);
160 let rotation = wowlab_types::sim::Rotation::empty();
161 let params = wowlab_engine_ports::HandlerParams {
162 game_data,
163 rotation: &rotation,
164 stats: &stats,
165 talent_selections: &[],
166 encounter: &encounter,
167 fight_duration_secs: encounter.fight_duration_secs(),
168 equipped_items: &[],
169 set_bonus_auras: &[],
170 bloodlust: false,
171 pre_pot_tempered: false,
172 flask: false,
173 augment_rune: false,
174 race: wowlab_types::game::RaceId::Human,
175 weapon_enchant_procs: &[],
176 bugs: wowlab_engine_ports::BugSettings::default(),
177 cast_latency: wowlab_engine_ports::CastLatency::default(),
178 raid_events: &[],
179 external_buffs: &[],
180 }
181 .validate()
182 .expect("valid handler params");
183 let _built = $build_fn(¶ms);
184 Ok(())
185 }
186 }
187 };
188}