Wechsel auf UNIT_COMBAT Engine (WoW Forever Beta Interface 16001)
- Entferne deaktiviertes COMBAT_LOG_EVENT_UNFILTERED - Implementiere UNIT_COMBAT mit Anti-Triplet Filter (unit == 'target') - Doppel-Auslösungs-Schutz bei Selbstheilung - Mapping von school auf lokalisierte Schadensschulen (SCHOOL_NAMES) - Parameter-Validierung mit issecretvalue - AGENT_GUIDE.md aktualisiert
This commit is contained in:
@@ -74,45 +74,71 @@ CritTrackerDB = {
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## 4. Logik- & Entscheidungsfluss (Core Engine)
|
||||
|
||||
### 4.1. Combat Log Filterung (`COMBAT_LOG_EVENT_UNFILTERED`)
|
||||
### 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.
|
||||
|
||||
Die Engine verwendet `CombatLogGetCurrentEventInfo()` mit folgenden Regeln:
|
||||
### 4.2. Filterregeln & Mehrfachauslösungs-Schutz
|
||||
`UNIT_COMBAT` feuert mit den Argumenten `(unit, action, modifier, amount, school)`.
|
||||
|
||||
1. **Source-Check:** Nur Events mit `sourceGUID == UnitGUID("player")` werden verarbeitet (Spieler-Treffer).
|
||||
2. **Sub-Events:**
|
||||
- **Schaden:** `SWING_DAMAGE`, `SPELL_DAMAGE`, `RANGE_DAMAGE`, `SPELL_PERIODIC_DAMAGE`, `SPELL_BUILDING_DAMAGE`.
|
||||
- Effektiver Schaden: `amount + absorbed` (Absorbe werden dem Treffer zugerechnet).
|
||||
- Bedingung: `critical == true`.
|
||||
- **Heilung:** `SPELL_HEAL`, `SPELL_PERIODIC_HEAL`, `SPELL_BUILDING_HEAL`.
|
||||
- Effektive Heilung: `amount + overhealing` (Overheal wird berücksichtigt, damit große Heiler-Crits bei voller HP nicht fälschlich als "Low Crit" eingestuft werden).
|
||||
- Bedingung: `critical == true`.
|
||||
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.2. Ablaufdiagramm der Crit-Verarbeitung
|
||||
### 4.3. Ablaufdiagramm der Crit-Verarbeitung
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["Combat Log Crit Event (Player)"] --> B{"Addon aktiviert?"}
|
||||
A["Event: UNIT_COMBAT(unit, action, modifier, amount, school)"] --> B{"IsPublic? modifier == 'CRITICAL'?"}
|
||||
B -- Nein --> End[Abbruch]
|
||||
B -- Ja --> C["Hole bisherigen Rekord (Schaden/Heilung)"]
|
||||
B -- Ja --> C{"action & unit Check"}
|
||||
|
||||
C --> D{"amount > currentRecord?"}
|
||||
D -- Ja --> E["Neuer Rekord! Aktualisiere charData (maxRecord = amount)"]
|
||||
D -- Nein --> F{"enableLowCrit UND currentRecord > 0 UND amount <= (currentRecord * threshold)?"}
|
||||
C -- "WOUND & unit == 'target'" --> D["isDamage = true"]
|
||||
C -- "HEAL & (target oder player ohne Self-Duplicate)" --> E["isHeal = true"]
|
||||
C -- Andere Units/Actions --> End
|
||||
|
||||
F -- Ja --> G["Als Low-Crit markieren (Sound: low.mp3)"]
|
||||
F -- Nein --> H["Als normaler Crit markieren (Sound: critX / healX)"]
|
||||
D --> F["Löse school via SCHOOL_NAMES auf"]
|
||||
E --> F
|
||||
|
||||
E --> I{"GetTime() - lastOutputTime < cooldown?"}
|
||||
G --> I
|
||||
H --> I
|
||||
F --> G["Hole bisherigen Rekord (charData.maxDamage / maxHeal)"]
|
||||
G --> H{"amount > currentRecord?"}
|
||||
|
||||
I -- Ja (im Cooldown) --> J["Ausgabe unterdrückt (Anti-Spam)"]
|
||||
I -- Nein (Cooldown frei) --> K["lastOutputTime = GetTime()"]
|
||||
H -- Ja --> I["Neuer Rekord! Aktualisiere charData (maxRecord = amount)"]
|
||||
H -- Nein --> J{"enableLowCrit UND currentRecord > 0 UND amount <= threshold?"}
|
||||
|
||||
K --> L["PlaySoundFile(soundPath, soundChannel)"]
|
||||
K --> M["DEFAULT_CHAT_FRAME:AddMessage(formatierte Nachricht)"]
|
||||
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)"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
182
CritTracker.lua
182
CritTracker.lua
@@ -1,6 +1,6 @@
|
||||
--[[
|
||||
CritTracker - Core Engine
|
||||
World of Warcraft - Forever (12.x Beta / Interface 16001)
|
||||
CritTracker - Core Engine (WoW Forever Edition)
|
||||
Optimiert für Interface 16001 / UNIT_COMBAT Engine
|
||||
]]
|
||||
|
||||
local addonName, addonTable = ...
|
||||
@@ -12,23 +12,45 @@ _G["CritTracker"] = CritTracker
|
||||
-- Timing & State
|
||||
CritTracker.lastOutputTime = 0
|
||||
|
||||
-- Defaults
|
||||
-- Standardeinstellungen
|
||||
local defaultSettings = {
|
||||
enabled = true,
|
||||
enableChat = true,
|
||||
enableSound = true,
|
||||
enableLowCrit = true,
|
||||
lowThreshold = 30, -- 30% of highest recorded crit
|
||||
cooldown = 5, -- 5 seconds output cooldown (1-30s)
|
||||
lowThreshold = 30, -- 30% des Rekords
|
||||
cooldown = 5, -- Cooldown in Sekunden
|
||||
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" (subject to cooldown) or "records_only"
|
||||
announceMode = "all", -- "all" oder "records_only"
|
||||
}
|
||||
|
||||
-- Dynamic Localization Proxy
|
||||
-- Schadensschulen-Übersetzung für UNIT_COMBAT
|
||||
local SCHOOL_NAMES = {
|
||||
[0] = { deDE = "Physisch", enUS = "Physical" },
|
||||
[1] = { deDE = "Physisch", enUS = "Physical" },
|
||||
[2] = { deDE = "Heilig", enUS = "Holy" },
|
||||
[4] = { deDE = "Feuer", enUS = "Fire" },
|
||||
[8] = { deDE = "Natur", enUS = "Nature" },
|
||||
[16] = { deDE = "Frost", enUS = "Frost" },
|
||||
[32] = { deDE = "Schatten", enUS = "Shadow" },
|
||||
[64] = { deDE = "Arkan", enUS = "Arcane" },
|
||||
}
|
||||
|
||||
-- Schutz vor Forever Secret Values
|
||||
local function IsPublic(val)
|
||||
if type(val) == "nil" then return false end
|
||||
if type(issecretvalue) == "function" then
|
||||
local ok, secret = pcall(issecretvalue, val)
|
||||
if ok and secret == true then return false end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Lokalisierungs-Proxy
|
||||
CritTracker.L = setmetatable({}, {
|
||||
__index = function(_, key)
|
||||
local lang = CritTracker:GetActiveLanguage()
|
||||
@@ -44,7 +66,6 @@ CritTracker.L = setmetatable({}, {
|
||||
end
|
||||
})
|
||||
|
||||
-- Language Resolution
|
||||
function CritTracker:GetActiveLanguage()
|
||||
local setting = (self.db and self.db.language) or "auto"
|
||||
if setting == "German" then
|
||||
@@ -52,25 +73,18 @@ function CritTracker:GetActiveLanguage()
|
||||
elseif setting == "English" then
|
||||
return "English"
|
||||
else
|
||||
-- Auto: German client -> German, all others -> English
|
||||
local locale = GetLocale()
|
||||
if locale == "deDE" then
|
||||
return "German"
|
||||
else
|
||||
return "English"
|
||||
end
|
||||
return (locale == "deDE") and "German" or "English"
|
||||
end
|
||||
end
|
||||
|
||||
-- Sound File Path
|
||||
function CritTracker:GetSoundFilePath(soundKey)
|
||||
local lang = self:GetActiveLanguage()
|
||||
return "Interface\\AddOns\\CritTracker\\sounds\\" .. lang .. "\\" .. soundKey .. ".mp3"
|
||||
end
|
||||
|
||||
-- Play Sound
|
||||
function CritTracker:PlaySound(soundKey)
|
||||
if not self.db.enableSound or not soundKey or soundKey == "none" then
|
||||
if not self.db or not self.db.enableSound or not soundKey or soundKey == "none" then
|
||||
return
|
||||
end
|
||||
local path = self:GetSoundFilePath(soundKey)
|
||||
@@ -78,7 +92,6 @@ function CritTracker:PlaySound(soundKey)
|
||||
PlaySoundFile(path, channel)
|
||||
end
|
||||
|
||||
-- Print Message (Visible strictly to the local player)
|
||||
function CritTracker:Print(msg)
|
||||
if not msg then return end
|
||||
if DEFAULT_CHAT_FRAME then
|
||||
@@ -88,7 +101,6 @@ function CritTracker:Print(msg)
|
||||
end
|
||||
end
|
||||
|
||||
-- Format Numbers with commas / dots
|
||||
function CritTracker:FormatNumber(n)
|
||||
if not n then return "0" end
|
||||
if BreakUpLargeNumbers then
|
||||
@@ -99,7 +111,6 @@ function CritTracker:FormatNumber(n)
|
||||
return left .. (num:reverse():gsub('(%d%d%d)', '%1.'):reverse()) .. right
|
||||
end
|
||||
|
||||
-- Character Data Accessor (strictly per character & realm)
|
||||
function CritTracker:GetCharKey()
|
||||
local name = UnitName("player") or "Unknown"
|
||||
local realm = GetRealmName() or "UnknownRealm"
|
||||
@@ -107,12 +118,8 @@ function CritTracker:GetCharKey()
|
||||
end
|
||||
|
||||
function CritTracker:GetCharData()
|
||||
if not CritTrackerDB then
|
||||
CritTrackerDB = {}
|
||||
end
|
||||
if not CritTrackerDB.chars then
|
||||
CritTrackerDB.chars = {}
|
||||
end
|
||||
if not CritTrackerDB then CritTrackerDB = {} end
|
||||
if not CritTrackerDB.chars then CritTrackerDB.chars = {} end
|
||||
local key = self:GetCharKey()
|
||||
if not CritTrackerDB.chars[key] then
|
||||
CritTrackerDB.chars[key] = {
|
||||
@@ -126,7 +133,6 @@ function CritTracker:GetCharData()
|
||||
return CritTrackerDB.chars[key]
|
||||
end
|
||||
|
||||
-- Reset Records for Current Character
|
||||
function CritTracker:ResetRecords()
|
||||
local charData = self:GetCharData()
|
||||
charData.maxDamage = 0
|
||||
@@ -143,7 +149,6 @@ function CritTracker:ResetRecords()
|
||||
end
|
||||
end
|
||||
|
||||
-- Level Up Handler
|
||||
function CritTracker:OnLevelUp(newLevel)
|
||||
local charData = self:GetCharData()
|
||||
charData.maxDamage = 0
|
||||
@@ -159,14 +164,9 @@ function CritTracker:OnLevelUp(newLevel)
|
||||
end
|
||||
end
|
||||
|
||||
-- Initialization
|
||||
function CritTracker:OnInitialize()
|
||||
if not CritTrackerDB then
|
||||
CritTrackerDB = {}
|
||||
end
|
||||
if not CritTrackerDB.settings then
|
||||
CritTrackerDB.settings = {}
|
||||
end
|
||||
if not CritTrackerDB then CritTrackerDB = {} end
|
||||
if not CritTrackerDB.settings then CritTrackerDB.settings = {} end
|
||||
for k, v in pairs(defaultSettings) do
|
||||
if CritTrackerDB.settings[k] == nil then
|
||||
CritTrackerDB.settings[k] = v
|
||||
@@ -174,11 +174,9 @@ function CritTracker:OnInitialize()
|
||||
end
|
||||
self.db = CritTrackerDB.settings
|
||||
|
||||
-- Initialize Character
|
||||
local charData = self:GetCharData()
|
||||
local curLevel = UnitLevel("player")
|
||||
if charData.level and charData.level > 0 and curLevel > charData.level then
|
||||
-- Leveled up while offline / addon disabled
|
||||
self:OnLevelUp(curLevel)
|
||||
else
|
||||
charData.level = curLevel
|
||||
@@ -189,8 +187,7 @@ function CritTracker:OnInitialize()
|
||||
end
|
||||
end
|
||||
|
||||
-- Main Crit Processing
|
||||
function CritTracker:ProcessCrit(isHeal, spellName, amount, destName)
|
||||
function CritTracker:ProcessCrit(isHeal, spellOrSchool, amount, destName)
|
||||
if not self.db or not self.db.enabled or not amount or amount <= 0 then
|
||||
return
|
||||
end
|
||||
@@ -203,19 +200,17 @@ function CritTracker:ProcessCrit(isHeal, spellName, amount, destName)
|
||||
local thresholdPercent = self.db.lowThreshold or 30
|
||||
local thresholdValue = math.floor(currentRecord * (thresholdPercent / 100))
|
||||
|
||||
-- Check for Low Crit
|
||||
if self.db.enableLowCrit and currentRecord > 0 and not isNewRecord and amount <= thresholdValue then
|
||||
isLowCrit = true
|
||||
end
|
||||
|
||||
-- Update Record if higher
|
||||
if isNewRecord then
|
||||
if isHeal then
|
||||
charData.maxHeal = amount
|
||||
charData.maxHealSpell = spellName or ""
|
||||
charData.maxHealSpell = spellOrSchool or ""
|
||||
else
|
||||
charData.maxDamage = amount
|
||||
charData.maxDamageSpell = spellName or ""
|
||||
charData.maxDamageSpell = spellOrSchool or ""
|
||||
end
|
||||
|
||||
if self.UpdateOptionsDisplay then
|
||||
@@ -223,19 +218,16 @@ function CritTracker:ProcessCrit(isHeal, spellName, amount, destName)
|
||||
end
|
||||
end
|
||||
|
||||
-- Cooldown Check for Audio and Text Output
|
||||
local now = GetTime()
|
||||
local cooldown = self.db.cooldown or 5
|
||||
if (now - self.lastOutputTime) < cooldown then
|
||||
-- Suppressed by Cooldown (Records are already preserved)
|
||||
return
|
||||
end
|
||||
|
||||
-- Determine Sound and Text
|
||||
local soundKey = nil
|
||||
local chatMsg = nil
|
||||
local destStr = (destName and destName ~= "") and string.format(self.L["TARGET_ON"], destName) or ""
|
||||
local spellStr = (spellName and spellName ~= "") and spellName or self.L["UNKNOWN"]
|
||||
local spellStr = (spellOrSchool and spellOrSchool ~= "") and spellOrSchool or (isHeal and "Heilung" or "Treffer")
|
||||
local amountStr = self:FormatNumber(amount)
|
||||
local recordStr = self:FormatNumber(currentRecord)
|
||||
|
||||
@@ -248,7 +240,6 @@ function CritTracker:ProcessCrit(isHeal, spellName, amount, destName)
|
||||
local formatStr = isHeal and self.L["NEW_RECORD_HEAL"] or self.L["NEW_RECORD_DAMAGE"]
|
||||
chatMsg = string.format(formatStr, destStr, spellStr, amountStr)
|
||||
else
|
||||
-- Normal Crit (between threshold and current record)
|
||||
if self.db.announceMode == "all" then
|
||||
soundKey = isHeal and (self.db.healSound or "heal1") or (self.db.damageSound or "crit1")
|
||||
local formatStr = isHeal and self.L["NORMAL_CRIT_HEAL"] or self.L["NORMAL_CRIT_DAMAGE"]
|
||||
@@ -256,7 +247,6 @@ function CritTracker:ProcessCrit(isHeal, spellName, amount, destName)
|
||||
end
|
||||
end
|
||||
|
||||
-- If something triggered, apply cooldown and output
|
||||
if soundKey or chatMsg then
|
||||
self.lastOutputTime = now
|
||||
|
||||
@@ -270,74 +260,56 @@ function CritTracker:ProcessCrit(isHeal, spellName, amount, destName)
|
||||
end
|
||||
end
|
||||
|
||||
-- Combat Log Parser
|
||||
function CritTracker:OnCombatLogEvent()
|
||||
local timestamp, subevent, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags,
|
||||
destGUID, destName, destFlags, destRaidFlags,
|
||||
arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19, arg20,
|
||||
arg21, arg22, arg23, arg24 = CombatLogGetCurrentEventInfo()
|
||||
|
||||
if not sourceGUID or sourceGUID ~= UnitGUID("player") then
|
||||
-- UNIT_COMBAT Parser
|
||||
function CritTracker:OnUnitCombat(unit, action, modifier, amount, school)
|
||||
if not IsPublic(unit) or not IsPublic(action) or not IsPublic(modifier) or not IsPublic(amount) then
|
||||
return
|
||||
end
|
||||
|
||||
if subevent == "SWING_DAMAGE" then
|
||||
local amount = arg12
|
||||
local overkill = arg13
|
||||
local school = arg14
|
||||
local resisted = arg15
|
||||
local blocked = arg16
|
||||
local absorbed = arg17
|
||||
local critical = arg18
|
||||
|
||||
if critical and critical ~= 0 then
|
||||
local totalDamage = (amount or 0) + (absorbed or 0)
|
||||
self:ProcessCrit(false, self.L["MELEE_ATTACK"], totalDamage, destName)
|
||||
if modifier ~= "CRITICAL" or type(amount) ~= "number" or amount <= 0 then
|
||||
return
|
||||
end
|
||||
|
||||
elseif subevent == "SPELL_DAMAGE" or subevent == "RANGE_DAMAGE"
|
||||
or subevent == "SPELL_PERIODIC_DAMAGE" or subevent == "SPELL_BUILDING_DAMAGE" then
|
||||
local spellId = arg12
|
||||
local spellName = arg13
|
||||
local spellSchool = arg14
|
||||
local amount = arg15
|
||||
local overkill = arg16
|
||||
local school = arg17
|
||||
local resisted = arg18
|
||||
local blocked = arg19
|
||||
local absorbed = arg20
|
||||
local critical = arg21
|
||||
local isDamage = false
|
||||
local isHeal = false
|
||||
|
||||
if critical and critical ~= 0 then
|
||||
local totalDamage = (amount or 0) + (absorbed or 0)
|
||||
self:ProcessCrit(false, spellName, totalDamage, destName)
|
||||
end
|
||||
-- Schaden: Nur 'target' werten (verhindert Alias-Triplets durch nameplate1/softenemy)
|
||||
if action == "WOUND" and unit == "target" then
|
||||
isDamage = true
|
||||
|
||||
elseif subevent == "SPELL_HEAL" or subevent == "SPELL_PERIODIC_HEAL" or subevent == "SPELL_BUILDING_HEAL" then
|
||||
local spellId = arg12
|
||||
local spellName = arg13
|
||||
local spellSchool = arg14
|
||||
local amount = arg15
|
||||
local overhealing = arg16
|
||||
local absorbed = arg17
|
||||
local critical = arg18
|
||||
|
||||
if critical and critical ~= 0 then
|
||||
local totalHeal = (amount or 0) + (overhealing or 0)
|
||||
self:ProcessCrit(true, spellName, totalHeal, destName)
|
||||
-- Heilung: 'target' oder 'player'
|
||||
elseif action == "HEAL" then
|
||||
if unit == "target" then
|
||||
isHeal = true
|
||||
elseif unit == "player" then
|
||||
-- Verhindert doppelte Auslösung bei Ziel auf sich selbst
|
||||
if not UnitIsUnit("player", "target") then
|
||||
isHeal = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Event Registration
|
||||
if not isDamage and not isHeal then return end
|
||||
|
||||
local targetName = UnitName(unit) or (isDamage and "Ziel" or "Spieler")
|
||||
|
||||
-- Schadensart / Schule auflösen
|
||||
local langKey = (self:GetActiveLanguage() == "German") and "deDE" or "enUS"
|
||||
local schoolName = (school and SCHOOL_NAMES[school] and SCHOOL_NAMES[school][langKey])
|
||||
or (isHeal and (langKey == "deDE" and "Heilung" or "Heal") or (langKey == "deDE" and "Angriff" or "Attack"))
|
||||
|
||||
self:ProcessCrit(isHeal, schoolName, amount, targetName)
|
||||
end
|
||||
|
||||
-- Event Registrierung
|
||||
CritTracker:RegisterEvent("ADDON_LOADED")
|
||||
CritTracker:RegisterEvent("PLAYER_LOGIN")
|
||||
CritTracker:RegisterEvent("PLAYER_LEVEL_UP")
|
||||
CritTracker:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
|
||||
CritTracker:RegisterEvent("UNIT_COMBAT")
|
||||
|
||||
CritTracker:SetScript("OnEvent", function(self, event, ...)
|
||||
if event == "COMBAT_LOG_EVENT_UNFILTERED" then
|
||||
self:OnCombatLogEvent()
|
||||
if event == "UNIT_COMBAT" then
|
||||
self:OnUnitCombat(...)
|
||||
elseif event == "PLAYER_LEVEL_UP" then
|
||||
local newLevel = ...
|
||||
self:OnLevelUp(newLevel)
|
||||
@@ -357,7 +329,7 @@ CritTracker:SetScript("OnEvent", function(self, event, ...)
|
||||
end
|
||||
end)
|
||||
|
||||
-- Slash Commands
|
||||
-- Slash Commands (/ctr & /crittracker)
|
||||
SLASH_CRITTRACKER1 = "/crittracker"
|
||||
SLASH_CRITTRACKER2 = "/ctr"
|
||||
SlashCmdList["CRITTRACKER"] = function(msg)
|
||||
@@ -380,13 +352,13 @@ SlashCmdList["CRITTRACKER"] = function(msg)
|
||||
elseif cmd == "test" then
|
||||
if arg == "heal" then
|
||||
CritTracker:PlaySound(CritTracker.db.healSound or "heal1")
|
||||
CritTracker:Print(string.format(CritTracker.L["NORMAL_CRIT_HEAL"], "", "Test Heal", CritTracker:FormatNumber(50000)))
|
||||
CritTracker:Print(string.format(CritTracker.L["NORMAL_CRIT_HEAL"], "", "Heilig", CritTracker:FormatNumber(50000)))
|
||||
elseif arg == "low" then
|
||||
CritTracker:PlaySound("low")
|
||||
CritTracker:Print(string.format(CritTracker.L["LOW_CRIT_DAMAGE"], "", "Test Low Hit", CritTracker:FormatNumber(150), CritTracker.db.lowThreshold, CritTracker:FormatNumber(1000)))
|
||||
CritTracker:Print(string.format(CritTracker.L["LOW_CRIT_DAMAGE"], "", "Physisch", CritTracker:FormatNumber(150), CritTracker.db.lowThreshold, CritTracker:FormatNumber(1000)))
|
||||
else
|
||||
CritTracker:PlaySound(CritTracker.db.damageSound or "crit1")
|
||||
CritTracker:Print(string.format(CritTracker.L["NORMAL_CRIT_DAMAGE"], "", "Test Strike", CritTracker:FormatNumber(125000)))
|
||||
CritTracker:Print(string.format(CritTracker.L["NORMAL_CRIT_DAMAGE"], "", "Feuer", CritTracker:FormatNumber(125000)))
|
||||
end
|
||||
else
|
||||
CritTracker:Print(CritTracker.L["SLASH_HELP_HEADER"])
|
||||
|
||||
Reference in New Issue
Block a user