Compare with Previous | Blame | View Log
local MAJOR_VERSION = "LibDiminishing-1.0" local MINOR_VERSION = tonumber(("$Rev: 1 $"):match("%d+")) local lib = LibStub:NewLibrary(MAJOR_VERSION, MINOR_VERSION) --local lib = {} if not lib then return end lib.targets = lib.targets or {} lib.listeners = lib.listeners or { start = { }, finish = { }, } if not lib.frame then lib.frame = CreateFrame("Frame") end local spells = LibDiminishingSpells local DR_POLYMORPH = 0 local DR_STUN = 1 local DR_STUN_PROC = 2 local DR_FEAR = 3 local DR_HORROR = 4 local DR_ROOT = 5 local DR_ROOT_PROC = 6 local DR_CYCLONE = 7 local DR_SLEEP = 8 local DR_CHARM = 9 local DR_KIDNEY_SHOT = 10 local DR_MAX = 11 lib.DR_POLYMORPH = DR_POLYMORPH lib.DR_STUN = DR_STUN lib.DR_STUN_PROC = DR_STUN_PROC lib.DR_FEAR = DR_FEAR lib.DR_HORROR = DR_HORROR lib.DR_ROOT = DR_ROOT lib.DR_ROOT_PROC = DR_ROOT_PROC lib.DR_CYCLONE = DR_CYCLONE lib.DR_SLEEP = DR_SLEEP lib.DR_CHARM = DR_CHARM lib.DR_KIDNEY_SHOT = DR_KIDNEY_SHOT local COMBATLOG_OBJECT_AFFILIATION_MINE = COMBATLOG_OBJECT_AFFILIATION_MINE local COMBATLOG_OBJECT_AFFILIATION_PARTY = COMBATLOG_OBJECT_AFFILIATION_PARTY local COMBATLOG_OBJECT_AFFILIATION_RAID = COMBATLOG_OBJECT_AFFILIATION_RAID local COMBATLOG_OBJECT_REACTION_HOSTILE = COMBATLOG_OBJECT_REACTION_HOSTILE local COMBATLOG_OBJECT_CONTROL_PLAYER = COMBATLOG_OBJECT_CONTROL_PLAYER local COMBATLOG_OBJECT_CONTROL_NPC = COMBATLOG_OBJECT_CONTROL_NPC local GROUP_AFFILIATION = bit.bor(COMBATLOG_OBJECT_AFFILIATION_PARTY, COMBATLOG_OBJECT_AFFILIATION_RAID, COMBATLOG_OBJECT_AFFILIATION_MINE) local function p(msg) DEFAULT_CHAT_FRAME:AddMessage(tostring(msg)) end function lib:AddStartListener(func) table.insert(self.listeners.start, func) end function lib:AddFinishListener(func) table.insert(self.listeners.finish, func) end function lib:RemoveStartListener(func) local found = table.foreachi(self.listeners.start, function(i, v) return func == v and i or nil end) if found then table.remove(self.listeners.start, found) end end function lib:RemoveFinishListener(func) local found = table.foreachi(self.listeners.finish, function(i, v) return func == v and i or nil end) if found then table.remove(self.listeners.finish, found) end end function lib:GetSpellCat(spellId) local spell = spells[spellId] or nil if type(spell) == "number" then spell = spells[spell] end return spell end function lib:GetGUIDCatStatus(guid, cat) if not self.targets[guid] or not self.targets[guid][cat] then return 0, 1, nil else local unitCat = self.targets[guid][cat] return unitCat.count, unitCat.factor, unitCat.remaining end end function lib:GetGUIDStatus(guid) if not self.targets[guid] then return nil end return pairs(self.targets[guid]) end function lib:GetUnitCatStatus(unitid, cat) local guid = UnitGUID(unitid) return self:GetGUIDCatStatus(guid) end function lib:GetUnitStatus(unitid) local guid = UnitGUID(unitid) return self:GetGUIDStatus(guid) end local function OnCombatEvent(timestamp, eventType, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, ...) if eventType == "SPELL_AURA_REMOVED" then local spellId, spellName, spellSchool, auraType = ... --p(spellName) local spell = spells[spellId] or nil if type(spell) == "number" then spell = spells[spell] end if not spell then return end local pve = (bit.band(dstFlags, COMBATLOG_OBJECT_CONTROL_NPC) == COMBATLOG_OBJECT_CONTROL_NPC) if pve and not spell.pve then return end lib.targets[dstGUID] = lib.targets[dstGUID] or {} if not lib.targets[dstGUID][spell.cat] then lib.targets[dstGUID][spell.cat] = { count = 1, factor = 0.5, } elseif lib.targets[dstGUID][spell.cat].count < 3 then lib.targets[dstGUID][spell.cat].count = lib.targets[dstGUID][spell.cat].count + 1 lib.targets[dstGUID][spell.cat].factor = (lib.targets[dstGUID][spell.cat].factor * 0.5 > 0.2 and 0.25) or 0 end local curTime = GetTime() lib.targets[dstGUID][spell.cat].remaining = 15 lib.targets[dstGUID][spell.cat].last = GetTime() table.foreachi(lib.listeners.start, function(i, func) func(dstGUID, spell.cat, lib.targets[dstGUID][spell.cat].count, lib.targets[dstGUID][spell.cat].factor) end) local ispve = "no" if pve then ispve = "yes" end --p("Spell end: " .. spellName .. " at " .. timestamp .. " (" .. GetTime() .. ") - count at " .. lib.targets[dstGUID][spell.cat].count .. " in pve? " .. ispve) end end local updateInterval = 0.2 local sinceUpdate = 0 local function OnUpdate(this, delta) sinceUpdate = sinceUpdate + delta while (sinceUpdate > updateInterval) do local curTime = GetTime() table.foreach(lib.targets, function(guid, v) local count = 0 for cat = 0, DR_MAX do if v[cat] then v[cat].remaining = curTime - v[cat].last if v[cat].remaining <= 0 then v[cat] = nil --p(i .. " + " .. cat .. " timed out") table.foreachi(lib.listeners.finish, function(i, func) func(guid, cat) end) else count = count + 1 end end end if count == 0 then lib.targets[i] = nil --p(i .. " timed out") end end) sinceUpdate = sinceUpdate - updateInterval end end local function OnEvent(this, event, ...) --p("OnEvent: " .. event) if event == "COMBAT_LOG_EVENT_UNFILTERED" then OnCombatEvent(...) end end lib.frame:SetScript("OnUpdate", OnUpdate) lib.frame:SetScript("OnEvent", OnEvent) lib.frame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")