// This self-contained factory also runs in the browser's QA context. It only // subscribes to committed state; it never writes the game stores. function createWeaponEvidenceRecorder(store, options = {}) { const capacity = options.capacity ?? 50_000; const clock = options.clock ?? Date.now; const initial = store.getState(); const baselineEventId = initial.combatEvents?.at(-1)?.id ?? 0; let lastEventId = baselineEventId; let stopped = false; const events = [], gaps = [], mobSamples = [], auraSamples = [], errors = []; const signatures = new Map(); let auraSignature = null; let discardedEvents = 0, discardedStates = 0; const retain = (array, entry, event = false) => { if (array.length < capacity) array.push(entry); else if (event) discardedEvents += 1; else discardedStates += 1; }; const observe = (state) => { if (stopped) return; try { const fresh = (state.combatEvents ?? []).filter((event) => event.id > lastEventId); for (const event of fresh) { if (event.id > lastEventId + 1) gaps.push({ afterId: lastEventId, beforeId: event.id }); retain(events, { ...event }, true); lastEventId = event.id; } const observedAt = clock(); for (const mob of Object.values(state.mobs ?? {})) { const entry = { id: mob.id, name: mob.name, serverEntry: mob.serverEntry ?? null, sourceCreatureGuid: mob.sourceCreatureGuid ?? null, sourceEquipment: mob.sourceEquipment ? JSON.parse(JSON.stringify(mob.sourceEquipment)) : null, engaged: Boolean(mob.engaged), dead: Boolean(mob.dead), dualWieldEnabled: mob.dualWieldEnabled ?? null, nextEnemyOffhandAttackAt: mob.nextEnemyOffhandAttackAt ?? null, pendingExtraAttacks: mob.pendingExtraAttacks?.map((queued) => ({ ...queued })) ?? null, lastDamagedActorId: mob.lastDamagedActorId ?? null, }; const signature = JSON.stringify(entry); if (signatures.get(mob.id) !== signature) { signatures.set(mob.id, signature); retain(mobSamples, { observedAt, ...entry }); } } const active = (state.auras ?? []).filter((aura) => /^(?:enemy-source-spell-(?:6742|6713|17230|3419)|enemy-control:source-spell-(?:5246|19134|20511|29544))$/.test(aura.definition?.id ?? '')).map((aura) => ({ instanceId: aura.instanceId, definitionId: aura.definition.id, sourceId: aura.sourceId, targetId: aura.targetId, appliedAt: aura.appliedAt, expiresAt: aura.expiresAt, stacks: aura.stacks, dispelCategory: aura.definition.dispelCategory ?? null, })); const nextAuraSignature = JSON.stringify(active); if (nextAuraSignature !== auraSignature) { auraSignature = nextAuraSignature; retain(auraSamples, { observedAt, auras: active }); } } catch (error) { if (errors.length < 10) errors.push(String(error?.message ?? error)); } }; observe(initial); const unsubscribe = store.subscribe(observe); return { stop() { if (!stopped) { observe(store.getState()); stopped = true; unsubscribe(); } return { baselineEventId, lastEventId, events, gaps, mobSamples, auraSamples, discardedEvents, discardedStates, errors, eventCoverage: 'Committed-store subscription with event-ID gap auditing; pre-start events excluded.', stateCoverage: 'Weapon and source-aura changes at store commits, including combat between route checkpoints.' }; }, }; } module.exports = { createWeaponEvidenceRecorder };