# CritTracker – Entwickler- & Agenten-Leitfaden (Developer & Agent Guide) Dieses Dokument dient als technische Referenz für Entwickler und KI-Agenten, die das Addon **CritTracker** nachvollziehen, erweitern oder in einer vergleichbaren Umgebung reproduzieren möchten. --- ## 1. System- & Zielumgebung - **Spiel / Client:** World of Warcraft - Forever (Beta) - **Engine-Basis:** WoW Retail 12.x Engine - **TOC Interface-Version:** `16001` (`## Interface: 16001`) - **Addon-Verzeichnis:** `Interface/AddOns/CritTracker/` - **Slash-Befehle:** `/ctr`, `/crittracker` (Hinweis: `/ct` wurde bewusst vermieden, um Namenskonflikte mit anderen Addons wie CTMod auszuschließen). --- ## 2. Projektstruktur ``` CritTracker/ ├── CritTracker.toc # Addon-Manifest für Interface 16001 ├── Localization.lua # Lokalisierungs-Strings (deDE und enUS) ├── CritTracker.lua # Core Engine: Event-Handling, Combat-Log, Cooldown, Reset ├── Config.lua # UI: 2-Spalten Einstellungsmenü (Modern Settings API + Standalone) ├── README.md # Benutzerdokumentation ├── AGENT_GUIDE.md # Diese technische Spezifikation für Agenten └── sounds/ ├── German/ # Deutsche Audio-Dateien │ ├── crit1.mp3 .. crit4.mp3 │ ├── heal1.mp3 .. heal4.mp3 │ └── low.mp3 └── English/ # Englische Audio-Dateien ├── crit1.mp3 .. crit4.mp3 ├── heal1.mp3 .. heal4.mp3 └── low.mp3 ``` > [!IMPORTANT] > **Audio-Asset-Korrektur:** Die ursprüngliche Datei `sounds/English/low.mp3` war eine fehlerhafte 1.024-Byte-Null-Datei (Stille). Sie wurde durch die funktionierende Audiodatei aus `sounds/German/low.mp3` ersetzt, damit englische Clients nicht stumm bleiben. --- ## 3. Datenarchitektur (`SavedVariables: CritTrackerDB`) Die Daten werden in `CritTrackerDB` gespeichert. Die Konfiguration ist accountweit geteilt, während die Rekorde strikt pro Charakter und Realm isoliert sind. ```lua CritTrackerDB = { settings = { enabled = true, -- Addon an/aus enableChat = true, -- Lokale Chat-Ausgabe an/aus enableSound = true, -- Soundausgabe an/aus enableLowCrit = true, -- Erkennung schwacher Crits an/aus lowThreshold = 30, -- Grenzwert in Prozent (Standard: 30%) cooldown = 5, -- Cooldown in Sekunden (1-30s, Schieberegler) damageSound = "crit1", -- "crit1", "crit2", "crit3", "crit4", "none" healSound = "heal1", -- "heal1", "heal2", "heal3", "heal4", "none" lowSound = "low", -- "low", "none" soundChannel = "Master", -- "Master", "Dialog", "SFX" language = "auto", -- "auto", "German", "English" announceMode = "all", -- "all" oder "records_only" }, chars = { ["CharakterName - RealmName"] = { level = 80, maxDamage = 152000, maxDamageSpell = "Feuerball", maxHeal = 89000, maxHealSpell = "Lichtblitz", } } } ``` --- --- ## 4. Logik- & Entscheidungsfluss (Core Engine) ### 4.1. Warum `UNIT_COMBAT` statt `COMBAT_LOG_EVENT_UNFILTERED`? (Root Cause) Im "WoW Forever"-Client (Interface 16001 / 12.x Engine) ist die sogenannte Addon-Apokalypse aktiv: - `COMBAT_LOG_EVENT_UNFILTERED` wurde von Blizzard für Addons **vollständig deaktiviert** und feuert niemals. - Kritische Treffer und Heilungen müssen zwingend über das Event `UNIT_COMBAT` abgefangen werden. ### 4.2. Filterregeln & Mehrfachauslösungs-Schutz `UNIT_COMBAT` feuert mit den Argumenten `(unit, action, modifier, amount, school)`. 1. **Forever Secret Values Schutz:** Parameter werden mit `issecretvalue(val)` geprüft. Handelt es sich um ein geschütztes Geheimnis oder `nil`, wird das Event verworfen. 2. **Krit-Filter:** Nur Events mit `modifier == "CRITICAL"` und numerischem `amount > 0` werden akzeptiert. 3. **Schaden-Filter (Crucial Anti-Triplet):** - Es wird ausschließlich `action == "WOUND"` und `unit == "target"` ausgewertet. - Alle Pseudo-Einheiten wie `nameplate*`, `softenemy` etc. werden verworfen, da der Client denselben Treffer sonst 3-fach meldet. 4. **Heilung-Filter (Anti-Selfheal-Duplicate):** - Akzeptiert `action == "HEAL"` für `unit == "target"` oder `unit == "player"`. - Bei Selbstheilung mit sich selbst im Ziel (`UnitIsUnit("player", "target")`) wird die Auswertung auf `unit == "target"` beschränkt, um doppelte Auslösungen zu verhindern. 5. **Schadensschulen-Mapping (`SCHOOL_NAMES`):** Da `UNIT_COMBAT` keine konkreten Zaubernamen liefert, wird das Argument `school` auf die jeweilige Schadensart gemappt: - `0` / `1` = Physisch / Physical - `2` = Heilig / Holy - `4` = Feuer / Fire - `8` = Natur / Nature - `16` = Frost / Frost - `32` = Schatten / Shadow - `64` = Arkan / Arcane ### 4.3. Ablaufdiagramm der Crit-Verarbeitung ```mermaid flowchart TD A["Event: UNIT_COMBAT(unit, action, modifier, amount, school)"] --> B{"IsPublic? modifier == 'CRITICAL'?"} B -- Nein --> End[Abbruch] B -- Ja --> C{"action & unit Check"} C -- "WOUND & unit == 'target'" --> D["isDamage = true"] C -- "HEAL & (target oder player ohne Self-Duplicate)" --> E["isHeal = true"] C -- Andere Units/Actions --> End D --> F["Löse school via SCHOOL_NAMES auf"] E --> F F --> G["Hole bisherigen Rekord (charData.maxDamage / maxHeal)"] G --> H{"amount > currentRecord?"} H -- Ja --> I["Neuer Rekord! Aktualisiere charData (maxRecord = amount)"] H -- Nein --> J{"enableLowCrit UND currentRecord > 0 UND amount <= threshold?"} J -- Ja --> K["Als Low-Crit markieren (Sound: low.mp3)"] J -- Nein --> L["Als normaler Crit markieren (Sound: critX / healX)"] I --> M{"GetTime() - lastOutputTime < cooldown?"} K --> M L --> M M -- Ja (im Cooldown) --> N["Ausgabe unterdrückt (Anti-Spam)"] M -- Nein (Cooldown frei) --> O["lastOutputTime = GetTime()"] O --> P["PlaySoundFile(soundPath, soundChannel)"] O --> Q["DEFAULT_CHAT_FRAME:AddMessage(formatierte Nachricht)"] ``` --- ## 5. Kernfunktionen im Detail ### 5.1. Level-Up Reset - **Event:** `PLAYER_LEVEL_UP` - **Sicherheits-Check:** Beim Login (`PLAYER_LOGIN`) wird geprüft, ob `UnitLevel("player") > charData.level`. Falls der Spieler offline oder bei deaktiviertem Addon aufgestiegen ist, wird der Reset nachträglich durchgeführt. - **Wirkung:** `maxDamage = 0`, `maxHeal = 0`, `level = newLevel`. - **Chat-Meldung:** Gibt lokalen Hinweis aus: `[CritTracker] Stufenaufstieg! Krit-Rekorde wurden auf 0 zurückgesetzt.` ### 5.2. Cooldown für Audio- & Chat-Ausgabe - Einstellbar von **1 bis 30 Sekunden** über den Schieberegler in den Optionen. - **Wichtig für Agenten:** Der Cooldown blockiert **nicht** das Speichern neuer Rekorde! Trifft ein Spieler während des Cooldowns einen neuen Rekordwert, wird `charData.maxDamage` sofort aktualisiert. Lediglich die Soundwiedergabe und der Textchat werden gedrosselt, um Tonaussetzer und Chatüberflutung zu verhindern. ### 5.3. Lokale Chat-Ausgabe - Alle Chat-Meldungen verwenden `DEFAULT_CHAT_FRAME:AddMessage(msg)` oder `print(msg)`. - Es werden **keine** öffentlichen Chatkanäle (`SAY`, `PARTY`, `RAID`) angesprochen. Die Ausgabe ist garantiert nur für den lokalen Client sichtbar. - Abschaltbar über `CritTrackerDB.settings.enableChat`. ### 5.4. Zweisprachigkeit (Localization Architecture) - Lokalisierungs-Proxy via Lua-Metatable in `CritTracker.L`: ```lua CritTracker.L = setmetatable({}, { __index = function(_, key) local lang = CritTracker:GetActiveLanguage() local locKey = (lang == "German") and "deDE" or "enUS" return addonTable.Locales[locKey][key] or addonTable.Locales["enUS"][key] or key end }) ``` - **Sprachauflösung:** - `auto`: Prüft `GetLocale()`. Bei `deDE` wird Deutsch gewählt, bei allen anderen Sprachen Englisch. - `German`: Erzwingt Deutsch. - `English`: Erzwingt Englisch. - **Audio-Pfad:** `Interface\AddOns\CritTracker\sounds\\.mp3` --- ## 6. UI-Architektur (`Config.lua`) Das Einstellungsmenü ist für maximale Kompatibilität mit modernem Retail WoW (Dragonflight, War Within, Midnight / 12.x) ausgelegt: 1. **Modern Settings API:** - Registrierung über `Settings.RegisterCanvasLayoutCategory(panel, "CritTracker")` und `Settings.RegisterAddOnCategory(category)`. - Öffnen über `Settings.OpenToCategory(category:GetID())`. 2. **Standalone-Fallback:** - Sollte das Settings-Menü im Betastatus nicht ansprechbar sein oder während des Kampfes aufgerufen werden, öffnet sich das Panel automatisch als bewegliches Standalone-Fenster (`BackdropTemplateMixin`, Close-Button, Dragging). 3. **2-Spalten-Layout:** - **Linke Spalte:** Checkboxen (Addon, Chat, Sound, Low-Crit), Cooldown-Slider (1–30s), Schwellenwert-Slider (5–100%), Charakter-Rekordanzeige und Reset-Button. - **Rechte Spalte:** Sound-Auswahl (Schaden, Heilung, Low, Kanal), Sprachauswahl und Test-Buttons (`►`). --- ## 7. Anleitung zur Nachbildung / Testen 1. **Dateien anlegen:** Die Dateien `CritTracker.toc`, `Localization.lua`, `CritTracker.lua` und `Config.lua` wie spezifiziert erstellen. 2. **Sounds ablegen:** - `sounds/German/`: `crit1.mp3` bis `crit4.mp3`, `heal1.mp3` bis `heal4.mp3`, `low.mp3`. - `sounds/English/`: `crit1.mp3` bis `crit4.mp3`, `heal1.mp3` bis `heal4.mp3`, `low.mp3`. 3. **Im Spiel testen:** - `/ctr` eingeben -> Einstellungsfenster muss sich öffnen. - Auf die `►`-Buttons klicken -> Die jeweiligen MP3-Dateien müssen hörbar abgespielt werden. - `/ctr test crit` -> Testet Schadensmeldung und Audio. - `/ctr test heal` -> Testet Heilungsmeldung und Audio. - `/ctr test low` -> Testet Low-Crit-Meldung und `low.mp3`. - Schieberegler verstellen -> Werte in `CritTrackerDB.settings` müssen persistieren. - `/ctr reset` -> Rekorde werden auf 0 gesetzt.