forge/manifest_ledger/collect/
relations.rs1use wowlab_manifest_schema::{EventEffectDef, Manifest};
5
6use super::{base_row, effect_coordinate};
7use crate::manifest_ledger::types::{LedgerDisposition, LedgerRow, OperationCategory};
8
9pub(super) fn collect_manifest_relations(
10 rows: &mut Vec<LedgerRow>,
11 slug: &str,
12 path: &str,
13 manifest: &Manifest,
14) {
15 for (talent, auras) in &manifest.talent_companion_auras {
16 for (index, aura) in auras.iter().enumerate() {
17 rows.push(base_row(
18 slug,
19 path,
20 format!("talent_companion_auras.{talent}[{index}] ({aura})"),
21 OperationCategory::AuraApply,
22 LedgerDisposition::GenericGap,
23 "talent-selected companion aura activation",
24 ));
25 }
26 }
27
28 for (index, _) in manifest.spell_groups.iter().enumerate() {
29 rows.push(base_row(
30 slug,
31 path,
32 format!("spell_groups[{index}]"),
33 OperationCategory::Gate,
34 LedgerDisposition::ContentOrdering,
35 "authored mutually exclusive aura group",
36 ));
37 }
38
39 for (name, effect) in &manifest.effects {
40 rows.push(
41 base_row(
42 slug,
43 path,
44 format!("effects.{name}"),
45 OperationCategory::OrderedContent,
46 LedgerDisposition::Unresolved,
47 "hook reads a retained DBC scalar",
48 )
49 .effect(effect.spell_id, effect.effect),
50 );
51 }
52
53 for (name, declaration) in &manifest.content_effects {
54 rows.push(
55 base_row(
56 slug,
57 path,
58 format!("content_effects.{name}"),
59 OperationCategory::OrderedContent,
60 LedgerDisposition::Unresolved,
61 declaration.reason.clone(),
62 )
63 .effect(declaration.spell_id, declaration.effect),
64 );
65 }
66
67 for (name, spell_id) in &manifest.reported_spells {
68 rows.push(
69 base_row(
70 slug,
71 path,
72 format!("reported_spells.{name}"),
73 OperationCategory::TelemetryOnly,
74 LedgerDisposition::TelemetryBinding,
75 "damage attribution alias",
76 )
77 .owner(*spell_id),
78 );
79 }
80
81 for (index, proc) in manifest.impact_procs.iter().enumerate() {
82 let mut registration = base_row(
83 slug,
84 path,
85 format!("impact_procs[{index}]"),
86 OperationCategory::Proc,
87 LedgerDisposition::GenericGap,
88 "declarative impact subscription candidate",
89 );
90
91 if let Some(spell) = &proc.spell {
92 if let Some(definition) = manifest.spells.get(spell) {
93 registration = registration.owner(definition.id);
94 }
95 }
96
97 rows.push(registration);
98
99 for (effect_index, effect) in proc.effects.iter().enumerate() {
100 event_effect(
101 rows,
102 slug,
103 path,
104 &format!("impact_procs[{index}].effects[{effect_index}]"),
105 0,
106 effect,
107 );
108 }
109 }
110}
111
112pub(super) fn event_effect(
113 rows: &mut Vec<LedgerRow>,
114 owner: &str,
115 path: &str,
116 key: &str,
117 spell_id: u32,
118 effect: &EventEffectDef,
119) {
120 let (category, disposition, evidence) = match effect {
121 EventEffectDef::Energize { .. } => (
122 OperationCategory::Resource,
123 LedgerDisposition::GenericGap,
124 "typed energize child operation",
125 ),
126 EventEffectDef::ExtendAura { .. } => (
127 OperationCategory::AuraApply,
128 LedgerDisposition::GenericGap,
129 "typed aura-duration child operation",
130 ),
131 _ => (
132 OperationCategory::OrderedContent,
133 LedgerDisposition::Unresolved,
134 "unrecognized event operation",
135 ),
136 };
137 let mut row = base_row(owner, path, key, category, disposition, evidence);
138
139 if spell_id != 0 {
140 row = row.owner(spell_id);
141 }
142
143 if let EventEffectDef::Energize { amount, .. } = effect {
144 if let Some((effect_spell, effect_index)) = effect_coordinate(amount) {
145 row = row.effect(effect_spell, effect_index);
146 }
147 }
148
149 rows.push(row);
150}