wowlab_engine_ports/
test_support.rs1use wowlab_engine_gamedata::ResolvedGameData;
2use wowlab_types::{
3 constants::{CURRENT_EXPANSION_ID, MAX_PLAYER_LEVEL},
4 sim::EncounterDefinition,
5};
6
7use crate::{
8 EncounterConstructionError, ResolvedEncounter, ResolvedEnemyCombatStats,
9 ResolvedEnemyEncounter, ResolvedEnemyIdentityMetadata,
10};
11
12const FIXTURE_MAX_HEALTH: f64 = 1_000_000.0;
13const FIXTURE_CREATURE_ARMOR: f64 = 377.0;
14const FIXTURE_ARMOR_CONSTANT: f64 = f32::from_bits(0x4475_22c1) as f64;
15const FIXTURE_AUTO_ATTACK_DPS: f64 = f32::from_bits(0x44b6_eb33) as f64;
16const FIXTURE_SPELL_DAMAGE: f64 = 65_851.0;
17
18pub fn introspection_fixture(
24 duration_s: f64,
25) -> Result<ResolvedEncounter, EncounterConstructionError> {
26 let definition =
27 EncounterDefinition::patchwerk(duration_s, MAX_PLAYER_LEVEL, CURRENT_EXPANSION_ID)?;
28 let enemy = definition
29 .enemies
30 .first()
31 .ok_or_else(|| EncounterConstructionError::resolved_enemy_count_mismatch(1, 0))?;
32 let group = definition
33 .groups
34 .get(enemy.group_id.0 as usize)
35 .ok_or_else(|| EncounterConstructionError::resolved_enemy_metadata_mismatch(enemy.id))?;
36 let identity = ResolvedEnemyIdentityMetadata::new(
37 enemy.id,
38 "Training Dummy".to_string(),
39 None,
40 None,
41 None,
42 )?;
43 let stats = ResolvedEnemyCombatStats::new(
44 enemy.id,
45 FIXTURE_MAX_HEALTH,
46 FIXTURE_CREATURE_ARMOR,
47 FIXTURE_ARMOR_CONSTANT,
48 Some(
49 enemy
50 .auto_attack_dps_override
51 .unwrap_or(FIXTURE_AUTO_ATTACK_DPS),
52 ),
53 Some(enemy.spell_damage_override.unwrap_or(FIXTURE_SPELL_DAMAGE)),
54 )?;
55 let resolved = ResolvedEnemyEncounter::new(enemy, &group.tags, enemy.level, identity, stats)?;
56
57 ResolvedEncounter::new(definition, vec![resolved])
58}
59
60#[must_use]
62pub fn introspection_game_data(encounter: &ResolvedEncounter) -> ResolvedGameData {
63 let primary = encounter.primary_enemy();
64
65 ResolvedGameData::from_environment(
66 u32::from(primary.level()),
67 primary.creature_armor(),
68 primary.armor_constant(),
69 )
70}
71
72#[macro_export]
97macro_rules! test_spec_handler {
98 (
99 impl $handler:ident {
100 defaults [$($default:ident),* $(,)?]
101 $($custom:item)*
102 }
103 ) => {
104 impl $crate::SpecHandler for $handler {
105 $(
106 $crate::__test_spec_handler_default!($default);
107 )*
108 $($custom)*
109 }
110 };
111}
112
113#[doc(hidden)]
114#[macro_export]
115macro_rules! __test_spec_handler_default {
116 (on_player_ready) => {
117 fn on_player_ready(&mut self, _ctx: &mut $crate::SimContext) -> Option<$crate::SpecAction> {
118 None
119 }
120 };
121 (on_cast_complete) => {
122 fn on_cast_complete(&mut self, _event: $crate::Event, _ctx: &mut $crate::SimContext) {}
123 };
124 (on_sim_start) => {
125 fn on_sim_start(&mut self, _ctx: &mut $crate::SimContext) {}
126 };
127 (total_damage) => {
128 fn total_damage(&self) -> f64 {
129 0.0
130 }
131 };
132 (cast_time_ms) => {
133 fn cast_time_ms(&self, _spell_id: $crate::__TestSpellIdx, _empower_rank: u8) -> u32 {
134 0
135 }
136 };
137 ($unknown:ident) => {
138 compile_error!(concat!(
139 "test_spec_handler! has no neutral implementation for `",
140 stringify!($unknown),
141 "`"
142 ));
143 };
144}
145
146#[cfg(test)]
147mod tests;