Skip to main content

wowlab_engine_domain/rotation/context/
schema.rs

1use wowlab_types::sim::{AuraOn, FastMap};
2
3use crate::rotation::{
4    buffer::{BufferOffsets, DescriptorId},
5    condition::{ResolvedFieldRead, ResolvedKey},
6    expr::FieldType,
7};
8
9/// Extra offsets used by the composite `spell.is_usable` evaluation.
10#[derive(Clone, Copy, Debug)]
11pub struct SpellUsableOffsets {
12    pub resource_current: Option<usize>,
13    pub secondary_resource_current: Option<usize>,
14    pub cooldown_base: Option<usize>,
15    pub gating_aura_offset: Option<usize>,
16    pub gating_aura_min_stacks: u8,
17    pub cost_bypass_aura_offset: Option<usize>,
18    pub cooldown_bypass_aura_offset: Option<usize>,
19    pub override_spell_offset: Option<usize>,
20    pub override_cooldown_base: Option<usize>,
21    pub override_aura_offset: Option<usize>,
22}
23
24/// Fully resolved runtime context layout.
25#[derive(Clone, Debug)]
26pub struct ContextSchema {
27    pub size: usize,
28    pub fields: Vec<ContextField>,
29    pub buffer_offsets: BufferOffsets,
30    pub(super) user_var_offsets: FastMap<String, usize>,
31    pub(super) user_var_types: FastMap<String, FieldType>,
32    pub(super) spell_usable_offsets: FastMap<usize, SpellUsableOffsets>,
33    pub(super) cooldown_bypass_offsets: FastMap<usize, usize>,
34}
35
36/// One resolved context field and its byte offset.
37#[derive(Clone, Debug)]
38pub struct ContextField {
39    pub descriptor_id: DescriptorId,
40    pub offset: usize,
41    pub field_type: FieldType,
42    pub key: Option<ResolvedKey>,
43    pub on: Option<AuraOn>,
44}
45
46impl ContextSchema {
47    #[must_use]
48    pub fn field_offset(&self, resolved: &ResolvedFieldRead) -> Option<usize> {
49        self.fields
50            .iter()
51            .find(|field| {
52                field.descriptor_id == resolved.descriptor_id
53                    && field.key == resolved.key
54                    && field.on == resolved.on
55            })
56            .map(|field| field.offset)
57    }
58
59    #[must_use]
60    pub fn user_var_offset(&self, name: &str) -> Option<usize> {
61        self.user_var_offsets.get(name).copied()
62    }
63
64    #[must_use]
65    pub fn user_var_type(&self, name: &str) -> Option<FieldType> {
66        self.user_var_types.get(name).copied()
67    }
68
69    #[must_use]
70    pub fn spell_usable_extras_map(&self) -> &FastMap<usize, SpellUsableOffsets> {
71        &self.spell_usable_offsets
72    }
73
74    #[must_use]
75    pub(crate) fn spell_usable_offsets(&self, field_offset: usize) -> Option<&SpellUsableOffsets> {
76        self.spell_usable_offsets.get(&field_offset)
77    }
78
79    #[must_use]
80    pub(crate) fn cooldown_bypass_aura_offset(&self, cooldown_offset: usize) -> Option<usize> {
81        self.cooldown_bypass_offsets.get(&cooldown_offset).copied()
82    }
83}