WoWInterface SVN LibResInfo

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /tags
    from Rev 45 to Rev 61
    Reverse comparison

Rev 45 → Rev 61

r58/LibResInfo-1.0.toc New file
0,0 → 1,21
## Interface: 50200
## Version: v10
 
## Title: Lib: ResInfo-1.0
## Notes: Library to provide information about resurrections.
 
## Author: Phanx
## X-Email: addons@phanx.net
## X-Copyright: Copyright (c) 2012 A. "Phanx" Kinley. All rights reserved.
## X-License: See accompanying LICENSE file for details.
## X-Website: http://www.wowinterface.com/downloads/info21467-LibResInfo-1.0.html
## X-AceForum: 2525
## X-Curse-Project-ID: libresinfo
## X-WoWI-ID: 21467
 
## OptionalDeps: LibStub, CallbackHandler-1.0
 
LibStub\LibStub.lua
CallbackHandler-1.0\CallbackHandler-1.0.lua
 
LibResInfo-1.0\LibResInfo-1.0.lua
\ No newline at end of file
r58/LibResInfo-1.0/LibResInfo-1.0.lua New file
0,0 → 1,733
--[[--------------------------------------------------------------------
LibResInfo-1.0
Library to provide information about resurrections in your group.
Copyright (c) 2012-2013 A. Kinley <addons@phanx.net>. All rights reserved.
See the accompanying README and LICENSE files for more information.
 
Things to do:
* Refactor messy and redundant sections.
* Fire ResCastStarted for units who die while Mass Res is casting.
* Fire ResCastStopped for units who res while Mass Res is casting.
 
Things that can't be done:
* Detect when a pending res is declined manually.
* Detect resurrections cast by or on players outside the group.
* Detect pending resurrections on units who were not in the group
when the res spell was cast.
----------------------------------------------------------------------]]
 
local DEBUG_LEVEL = GetAddOnMetadata("LibResInfo-1.0", "Version") and 1 or 0
local DEBUG_FRAME = ChatFrame1
 
------------------------------------------------------------------------
 
local MAJOR, MINOR = "LibResInfo-1.0", 12
assert(LibStub, MAJOR.." requires LibStub")
assert(LibStub("CallbackHandler-1.0"), MAJOR.." requires CallbackHandler-1.0")
local lib, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not lib then return end
 
------------------------------------------------------------------------
 
lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib)
 
lib.eventFrame = lib.eventFrame or CreateFrame("Frame")
 
lib.guidFromUnit = lib.guidFromUnit or {}
lib.nameFromGUID = lib.nameFromGUID or {}
lib.unitFromGUID = lib.unitFromGUID or {}
 
lib.castStart = lib.castStart or {}
lib.castEnd = lib.castEnd or {}
lib.castTarget = lib.castTarget or {}
lib.castMass = lib.castMass or {}
 
lib.resCasting = lib.resCasting or {}
lib.resPending = lib.resPending or {}
 
lib.total = lib.total or {}
 
lib.ghost = lib.ghost or {}
 
------------------------------------------------------------------------
 
local callbacks = lib.callbacks
local f = lib.eventFrame
 
local guidFromUnit = lib.guidFromUnit -- unit = guid
local nameFromGUID = lib.nameFromGUID -- guid = name
local unitFromGUID = lib.unitFromGUID -- guid = unit
 
local castStart = lib.castStart -- caster guid = cast start time
local castEnd = lib.castEnd -- caster guid = cast end time
local castTarget = lib.castTarget -- caster guid = target guid
local castMass = lib.castMass -- caster guid = casting Mass Res
 
local resCasting = lib.resCasting -- dead guid = # res spells being cast on them
local resPending = lib.resPending -- dead guid = expiration time
 
local total = lib.total
total.casting = total.casting or 0 -- # res spells being cast
total.pending = total.pending or 0 -- # resses available to take
 
local ghost = lib.ghost
 
if DEBUG_LEVEL > 0 then
LibResInfo = lib
end
 
------------------------------------------------------------------------
 
local RESURRECT_PENDING_TIME = 60
local RECENTLY_MASS_RESURRECTED = GetSpellInfo(95223)
 
local resSpells = {
[2008] = GetSpellInfo(2008), -- Ancestral Spirit (shaman)
[8342] = GetSpellInfo(8342), -- Defibrillate (item: Goblin Jumper Cables)
[22999] = GetSpellInfo(22999), -- Defibrillate (item: Goblin Jumper Cables XL)
[54732] = GetSpellInfo(54732), -- Defibrillate (item: Gnomish Army Knife)
[126393] = GetSpellInfo(126393), -- Eternal Guardian (hunter pet: quilien)
[61999] = GetSpellInfo(61999), -- Raise Ally (death knight)
[20484] = GetSpellInfo(20484), -- Rebirth (druid)
[113269] = GetSpellInfo(113269), -- Rebirth (prot/holy paladin symbiosis)
[7328] = GetSpellInfo(7328), -- Redemption (paladin)
[2006] = GetSpellInfo(2006), -- Resurrection (priest)
[115178] = GetSpellInfo(115178), -- Resuscitate (monk)
[50769] = GetSpellInfo(50769), -- Revive (druid)
[982] = GetSpellInfo(982), -- Revive Pet (hunter)
[20707] = GetSpellInfo(20707), -- Soulstone (warlock)
[83968] = GetSpellInfo(83968), -- Mass Resurrection
}
 
------------------------------------------------------------------------
 
f:SetScript("OnEvent", function(self, event, ...)
return self[event] and self[event](self, event, ...)
end)
 
f:RegisterEvent("GROUP_ROSTER_UPDATE")
f:RegisterEvent("INCOMING_RESURRECT_CHANGED")
f:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED")
f:RegisterEvent("UNIT_SPELLCAST_START")
f:RegisterEvent("UNIT_SPELLCAST_STOP")
f:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")
 
------------------------------------------------------------------------
 
local function debug(level, text, ...)
if level <= DEBUG_LEVEL then
if select("#", ...) > 0 then
if type(text) == "string" and strfind(text, "%%[dfqsx%d%.]") then
text = format(text, ...)
else
text = strjoin(" ", tostringall(text, ...))
end
else
text = tostring(text)
end
DEBUG_FRAME:AddMessage("|cff00ddba[LRI]|r " .. text)
end
end
 
------------------------------------------------------------------------
 
function lib.RegisterAllCallbacks(handler, method)
lib.RegisterCallback(handler, "LibResInfo_ResCastStarted", method)
lib.RegisterCallback(handler, "LibResInfo_ResCastCancelled", method)
lib.RegisterCallback(handler, "LibResInfo_ResCastFinished", method)
lib.RegisterCallback(handler, "LibResInfo_ResPending", method)
lib.RegisterCallback(handler, "LibResInfo_ResUsed", method)
lib.RegisterCallback(handler, "LibResInfo_ResExpired", method)
end
 
------------------------------------------------------------------------
 
function lib:UnitHasIncomingRes(unit)
if type(unit) == "string" then
local guid
if strmatch(unit, "^0x") then
guid = unit
unit = unitFromGUID[unit]
else
guid = UnitGUID(unit)
unit = unitFromGUID[guid]
end
if guid and unit and UnitIsDeadOrGhost(unit) and UnitIsConnected(unit) then
if resPending[guid] then
debug(2, "UnitHasIncomingRes", nameFromGUID[guid], "PENDING")
return "PENDING", resPending[guid]
else
local firstCaster, firstEnd
for casterGUID, targetGUID in pairs(castTarget) do
if targetGUID == guid then
local endTime = castEnd[casterGUID]
if endTime and (not firstEnd or endTime < firstEnd) then
firstCaster, firstEnd = casterGUID, endTime
end
end
end
if not UnitDebuff(unit, RECENTLY_MASS_RESURRECTED) then
for casterGUID in pairs(castMass) do
local endTime = castEnd[casterGUID]
if endTime and (not firstEnd or endTime < firstEnd) then
firstCaster, firstEnd = casterGUID, endTime
end
end
end
if firstCaster and firstEnd then
debug(2, "UnitHasIncomingRes", nameFromGUID[guid], "CASTING", nameFromGUID[firstCaster])
return "CASTING", firstEnd, unitFromGUID[firstCaster], firstCaster
end
end
end
debug(3, "UnitHasIncomingRes", nameFromGUID[guid], "nil")
end
end
 
function lib:UnitIsCastingRes(unit)
if type(unit) == "string" then
local guid
if strmatch(unit, "^0x") then
guid = unit
unit = unitFromGUID[unit]
else
guid = UnitGUID(unit)
unit = unitFromGUID[guid]
end
if guid and unit then
debug(4, unit, guid, nameFromGUID[guid])
local isFirst, targetGUID, endTime = true, castTarget[guid], castEnd[guid]
if targetGUID then
if resPending[targetGUID] then
isFirst = nil
else
for k, v in pairs(castTarget) do
if k ~= guid and v == targetGUID and castEnd[k] < endTime then
isFirst = nil
break
end
end
for k in pairs(castMass) do
if k ~= guid and castEnd[k] < endTime then
isFirst = nil
break
end
end
end
debug(2, "UnitIsCastingRes", nameFromGUID[guid], nameFromGUID[targetGUID], isFirst)
return endTime, unitFromGUID[targetGUID], targetGUID, isFirst
 
elseif castMass[guid] then
for k in pairs(castMass) do
if not castEnd[k] then
castMass[k], castStart[k] = nil, nil
elseif k ~= guid and castEnd[k] < endTime then
isFirst = nil
break
end
end
debug(2, "UnitIsCastingRes", nameFromGUID[guid], "MASS", isFirst)
return endTime, nil, nil, isFirst
end
return debug(3, "UnitIsCastingRes", nameFromGUID[guid], "NIL")
end
return debug(3, "UnitIsCastingRes", unit, "INVALID")
end
debug(3, "UnitIsCastingRes", tostring(unit), "INVALID", type(unit))
end
 
------------------------------------------------------------------------
 
local unitFromGUID_old, guidFromUnit_old = {}, {}
 
function f:GROUP_ROSTER_UPDATE()
debug(3, "GROUP_ROSTER_UPDATE")
 
wipe(guidFromUnit_old)
wipe(unitFromGUID_old)
for guid, unit in pairs(unitFromGUID) do
unitFromGUID_old[guid] = unit
unitFromGUID[guid] = nil
end
for unit, guid in pairs(guidFromUnit) do
guidFromUnit_old[unit] = guid
guidFromUnit[unit] = nil
end
 
if IsInRaid() then
debug(4, "raid")
for i = 1, GetNumGroupMembers() do
local unit = "raid"..i
local guid = UnitGUID(unit)
if guid then
guidFromUnit[unit] = guid
nameFromGUID[guid] = UnitName(unit)
unitFromGUID[guid] = unit
end
unit = "raidpet"..i
guid = UnitGUID(unit)
if guid then
guidFromUnit[unit] = guid
nameFromGUID[guid] = UnitName(unit)
unitFromGUID[guid] = unit
end
end
else
local unit, guid = "player", UnitGUID("player")
guidFromUnit[unit] = guid
nameFromGUID[guid] = UnitName(unit)
unitFromGUID[guid] = unit
 
unit, guid = "pet", UnitGUID("pet")
if guid then
guidFromUnit[unit] = guid
nameFromGUID[guid] = UnitName(unit)
unitFromGUID[guid] = unit
end
 
if IsInGroup() then
debug(4, "party")
for i = 1, GetNumGroupMembers() - 1 do
unit = "party"..i
guid = UnitGUID(unit)
if guid then
guidFromUnit[unit] = guid
nameFromGUID[guid] = UnitName(unit)
unitFromGUID[guid] = unit
end
unit = "partypet"..i
guid = UnitGUID(unit)
if guid then
guidFromUnit[unit] = guid
nameFromGUID[guid] = UnitName(unit)
unitFromGUID[guid] = unit
end
end
else
debug(4, "solo")
end
end
 
-- Someone left the group while casting a res.
-- Find who they were casting on and cancel it.
for caster in pairs(castEnd) do
if not unitFromGUID[caster] then
debug(4, nameFromGUID[caster], "left while casting on", nameFromGUID[target])
local startTime, endTime = castStart[caster] or 0, castEnd[caster] or 0
castStart[caster], castEnd[caster] = nil, nil
local target = castTarget[caster]
if target then
if resCasting[target] and resCasting[target] > 1 then
resCasting[target] = resCasting[target] - 1
else
resCasting[target] = nil
end
castTarget[caster] = nil
debug(1, ">> ResCastCancelled", "on", nameFromGUID[target], "by", nameFromGUID[caster], resCasting[target])
callbacks:Fire("LibResInfo_ResCastCancelled", unitFromGUID[target], target, unitFromGUID_old[caster], caster)
elseif castMass[caster] then
castMass[caster] = nil
for guid, unit in pairs(guidFromUnit) do
if UnitIsDeadOrGhost(unit) and UnitIsConnected(unit) and not UnitDebuff(unit, RECENTLY_MASS_RESURRECTED) then
if resCasting[guid] and resCasting[guid] > 1 then
resCasting[guid] = resCasting[guid] - 1
else
resCasting[guid] = nil
end
debug(1, ">> ResCastCancelled", "on", nameFromGUID[caster], "by", nameFromGUID[guid])
callbacks:Fire("LibResInfo_ResCastCancelled", unitFromGUID[target], target, unitFromGUID_old[caster], caster)
end
end
end
end
end
 
-- Someone left the group while a res was being cast on them.
-- Find the cast and cancel it.
for target, n in pairs(resCasting) do
if not unitFromGUID[target] then
debug(4, nameFromGUID[target], "left while incoming.")
for caster, castertarget in pairs(castTarget) do
if target == castertarget then
resCasting[target] = nil
castTarget[caster], castStart[caster], castEnd[caster] = nil, nil, nil
debug(1, ">> ResCastCancelled", "on", nameFromGUID[target], "by", nameFromGUID[caster])
callbacks:Fire("LibResInfo_ResCastCancelled", unitFromGUID[target], target, unitFromGUID_old[caster], caster)
end
end
for caster in pairs(castMass) do
debug(1, ">> ResCastCancelled", "on", nameFromGUID[target], "by", nameFromGUID[caster])
callbacks:Fire("LibResInfo_ResCastCancelled", unitFromGUID[target], target, unitFromGUID_old[caster], caster)
end
end
end
 
-- Someone left the group when they had a res available.
-- Find the res and cancel it.
for target in pairs(resPending) do
if not unitFromGUID[target] then
debug(3, nameFromGUID[target], "left while pending.")
resPending[target] = nil
total.pending = total.pending - 1
debug(1, ">> ResExpired", "on", nameFromGUID[target])
callbacks:Fire("LibResInfo_ResExpired", unitFromGUID_old[target], target)
end
end
 
-- Check events
debug(3, "# pending:", total.pending)
if total.pending == 0 then
self:UnregisterEvent("UNIT_HEALTH")
self:Hide()
end
 
local most = 0
for _, n in pairs(resCasting) do
most = max(n, most)
end
debug(3, "highest # casting:", most)
if most < 2 then
self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
end
 
for guid, name in pairs(nameFromGUID) do
if not unitFromGUID[guid] then
nameFromGUID[guid] = nil
end
end
end
 
------------------------------------------------------------------------
 
function f:INCOMING_RESURRECT_CHANGED(event, unit)
if guidFromUnit[unit] then
local guid = UnitGUID(unit)
local hasRes = UnitHasIncomingResurrection(unit)
debug(3, "INCOMING_RESURRECT_CHANGED", nameFromGUID[guid], hasRes)
 
if hasRes then
local now, found = GetTime()
for casterGUID, startTime in pairs(castStart) do
if startTime - now < 10 and not castTarget[casterGUID] and not castMass[casterGUID] then -- time in ms between cast start and res gain
if not castMass[casterGUID] then
castTarget[casterGUID] = guid
end
resCasting[guid] = 1 + (resCasting[guid] or 0)
local casterUnit = unitFromGUID[casterGUID]
debug(1, ">> ResCastStarted", "on", nameFromGUID[guid], "by", nameFromGUID[casterGUID], "DIFF", floor(now - startTime * 100) / 100, "#", resCasting[guid])
callbacks:Fire("LibResInfo_ResCastStarted", unit, guid, casterUnit, casterGUID, castEnd[casterGUID])
found = true
end
end
if not found then
debug(4, "No new cast found.")
end
for casterGUID, endTime in pairs(castEnd) do
if endTime - now < 10 and not castStart[casterGUID] and not castMass[casterGUID] then -- time in ms between cast end and res loss
local targetGUID = castTarget[casterGUID]
if targetGUID == guid then
local casterUnit = unitFromGUID[casterGUID]
castTarget[casterGUID], castEnd[casterGUID] = nil, nil
debug(1, ">> ResCastFinished", "on",nameFromGUID[guid], "by", nameFromGUID[casterGUID], "#", resCasting[guid], "hasRes")
callbacks:Fire("LibResInfo_ResCastFinished", unit, guid, casterUnit, casterGUID)
end
total.casting = total.casting + 1
debug(4, n, "casting, waiting for CLEU.")
self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
end
end
 
elseif resCasting[guid] then
-- had a res, doesn't anymore
local finished, stopped
for casterGUID, targetGUID in pairs(castTarget) do
if targetGUID == guid then
debug(4, nameFromGUID[casterGUID], "was casting...")
if castStart[casterGUID] then
debug(4, "...and stopped.")
castStart[casterGUID], castEnd[casterGUID], castTarget[casterGUID] = nil, nil, nil
 
debug(1, ">> ResCastCancelled", "on", nameFromGUID[guid], "by", nameFromGUID[casterGUID], "#", resCasting[guid] - 1)
resCasting[guid] = nil
callbacks:Fire("LibResInfo_ResCastCancelled", unit, guid, unitFromGUID[casterGUID], casterGUID)
else
debug(4, "...and finished.")
castStart[casterGUID], castEnd[casterGUID], castTarget[casterGUID] = nil, nil, nil
 
debug(1, ">> ResCastFinished", "on", nameFromGUID[guid], "by", nameFromGUID[casterGUID], "#", resCasting[guid] - 1, "resCasting")
callbacks:Fire("LibResInfo_ResCastFinished", unit, guid, unitFromGUID[casterGUID], casterGUID)
 
total.casting = total.casting + 1
debug(3, n, "casting, waiting for CLEU")
self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
end
break
end
end
end
end
end
 
------------------------------------------------------------------------
 
function f:UNIT_SPELLCAST_START(event, unit, spellName, _, _, spellID)
if guidFromUnit[unit] and resSpells[spellID] then
local guid = UnitGUID(unit)
debug(3, event, "=>", nameFromGUID[guid], "=>", spellName)
 
local _, _, _, _, startTime, endTime = UnitCastingInfo(unit)
debug(4, "UnitCastingInfo =>", spellID, spellName, floor(startTime / 1000), floor(endTime / 1000))
 
castStart[guid] = startTime / 1000
castEnd[guid] = endTime / 1000
 
if spellID == 83968 then -- Mass Resurrection
castMass[guid] = true
for targetGUID, targetUnit in pairs(unitFromGUID) do
if UnitIsDeadOrGhost(targetUnit) and UnitIsConnected(targetUnit) and not UnitDebuff(targetUnit, RECENTLY_MASS_RESURRECTED) then
debug(1, ">> ResCastStarted", "on", nameFromGUID[targetGUID], "by", nameFromGUID[guid])
callbacks:Fire("LibResInfo_ResCastStarted", targetUnit, targetGUID, unit, guid, endTime / 1000)
end
end
end
end
end
 
function f:UNIT_SPELLCAST_SUCCEEDED(event, unit, spellName, _, _, spellID)
if guidFromUnit[unit] and resSpells[spellID] then
local guid = UnitGUID(unit)
if castStart[guid] then
debug(3, event, "=>", nameFromGUID[guid], "=>", spellName)
castStart[guid] = nil
 
if castMass[guid] then -- Mass Resurrection
castEnd[guid] = nil
 
local n = total.casting
 
for targetGUID, targetUnit in pairs(unitFromGUID) do
if UnitIsDeadOrGhost(targetUnit) and UnitIsConnected(targetUnit) and not UnitDebuff(targetUnit, RECENTLY_MASS_RESURRECTED) then
debug(1, ">> ResCastFinished", "on", nameFromGUID[targetGUID], "by", nameFromGUID[guid])
callbacks:Fire("LibResInfo_ResCastFinished", targetUnit, targetGUID, unit, guid)
n = n + 1
end
end
 
if n > 0 then
debug(4, n, "casting, waiting for CLEU")
self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
end
end
else
-- instant cast
resCasting[guid] = 1 + (resCasting[guid] or 1)
debug(3, event, "=>", nameFromGUID[guid], "=>", spellName)
debug(3, "instant cast, waiting for CLEU")
self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
end
end
end
 
function f:UNIT_SPELLCAST_STOP(event, unit, spellName, _, _, spellID)
if guidFromUnit[unit] and resSpells[spellID] then
local guid = UnitGUID(unit)
if castStart[guid] then
debug(3, event, "=>", nameFromGUID[guid], "=>", spellName)
local targetGUID = castTarget[guid]
if targetGUID then
local n = resCasting[targetGUID]
if n and n > 1 then
-- someone else is still casting, send cancellation here
local targetUnit = unitFromGUID[targetGUID]
castStart[guid], castEnd[guid], castTarget[guid] = nil, nil
resCasting[targetGUID] = n - 1
debug(1, ">> ResCastCancelled", "on", nameFromGUID[targetGUID], "by", nameFromGUID[guid])
callbacks:Fire("LibResInfo_ResCastCancelled", targetUnit, targetGUID, unit, guid)
else
debug(4, "Waiting for IRC.")
end
 
elseif castMass[guid] then -- Mass Resurrection
castStart[guid], castEnd[guid], castMass[guid] = nil, nil, nil
for targetGUID, targetUnit in pairs(unitFromGUID) do
if UnitIsDeadOrGhost(targetUnit) and UnitIsConnected(targetUnit) and not UnitDebuff(targetUnit, RECENTLY_MASS_RESURRECTED) then
local n = resCasting[targetGUID]
if n and n > 1 then
resCasting[targetGUID] = n - 1
else
resCasting[targetGUID] = nil
end
debug(1, ">> ResCastCancelled", "on", nameFromGUID[targetGUID], "by", nameFromGUID[guid])
callbacks:Fire("LibResInfo_ResCastCancelled", targetUnit, targetGUID, unit, guid)
end
end
end
end
end
end
 
f.UNIT_SPELLCAST_INTERRUPTED = f.UNIT_SPELLCAST_STOP
 
------------------------------------------------------------------------
 
function f:COMBAT_LOG_EVENT_UNFILTERED(event, timestamp, combatEvent, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags, spellID, spellName, spellSchool)
if combatEvent == "SPELL_RESURRECT" then
local destUnit = unitFromGUID[destGUID]
if destUnit then
local now = GetTime()
debug(3, combatEvent, "=>", sourceName, "=>", spellName, "=>", destName)
 
local casting = resCasting[destGUID]
if casting or castMass[sourceGUID] then
debug(4, "yes")
 
if casting and casting > 1 then
resCasting[destGUID] = casting - 1
else
resCasting[destGUID] = nil
end
 
local new = not resPending[destGUID]
resPending[destGUID] = now + RESURRECT_PENDING_TIME
 
total.casting = total.casting - 1
if total.casting == 0 then
debug(4, "0 casting, unregister CLEU")
self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
end
 
if castMass[sourceGUID] then
local n = 0
for guid, unit in pairs(unitFromGUID) do
if guid ~= destGUID and (not resPending[guid] or resPending[guid] - now > RESURRECT_PENDING_TIME) and UnitIsDeadOrGhost(unit) and UnitIsConnected(unit) and not UnitDebuff(unit, RECENTLY_MASS_RESURRECTED) then
n = n + 1
end
end
if n == 0 then
castMass[sourceGUID] = nil
end
debug(4, n, "mass targets left")
end
 
ghost[destGUID] = UnitIsGhost(destUnit)
 
if new then
total.pending = total.pending + 1
debug(4, total.pending, "pending, start timer, register UNIT_HEALTH/AURA")
self:RegisterEvent("UNIT_HEALTH")
self:RegisterEvent("UNIT_AURA")
self:Show()
else
debug(4, total.pending, "pending, timer already running")
end
 
debug(1, ">> ResPending", "on", strmatch(destName, "[^%-]+"), "by", strmatch(sourceName, "[^%-]+"))
callbacks:Fire("LibResInfo_ResPending", destUnit, destGUID, now + RESURRECT_PENDING_TIME)
end
end
end
end
 
------------------------------------------------------------------------
 
function f:UNIT_HEALTH(event, unit)
local guid = guidFromUnit[unit]
if guidFromUnit[unit] then
if resPending[guid] then
debug(3, event, nameFromGUID[guid], "Dead", UnitIsDead(unit), "Ghost", UnitIsGhost(unit), "Offline", not UnitIsConnected(unit))
 
local callback
 
if not UnitIsConnected(unit) then
callback = "LibResInfo_ResExpired"
 
elseif UnitIsGhost(unit) and not ghost[guid] then
ghost[guid] = true
callback = "LibResInfo_ResExpired"
 
elseif not UnitIsDead(unit) then
ghost[guid] = nil
callback = "LibResInfo_ResUsed"
end
 
if callback then
resPending[guid] = nil
debug(1, ">>", callback, nameFromGUID[guid])
callbacks:Fire(callback, unit, guid)
 
total.pending = total.pending - 1
if total.pending == 0 then
debug(4, "0 pending, unregister UNIT_HEALTH/AURA")
self:UnregisterEvent("UNIT_AURA")
self:UnregisterEvent("UNIT_HEALTH")
end
end
end
end
end
 
f.UNIT_AURA = f.UNIT_HEALTH
 
------------------------------------------------------------------------
 
f:Hide()
 
local timer = 0
local INTERVAL = 0.5
f:SetScript("OnUpdate", function(self, elapsed)
timer = timer + elapsed
if timer >= INTERVAL then
debug(6, "timer update")
local now = GetTime()
for guid, expiry in pairs(resPending) do
if expiry - now < INTERVAL then -- will expire before next update
local unit = unitFromGUID[guid]
resPending[guid] = nil
debug(1, ">> ResExpired", nameFromGUID[guid])
callbacks:Fire("LibResInfo_ResExpired", unit, guid, true)
 
total.pending = total.pending - 1
if total.pending == 0 then
self:UnregisterEvent("UNIT_HEALTH")
self:Hide()
end
end
end
timer = 0
end
end)
 
f:SetScript("OnShow", function()
debug(4, "timer start")
end)
 
f:SetScript("OnHide", function()
debug(4, "timer stop")
timer = 0
end)
 
------------------------------------------------------------------------
 
SLASH_LIBRESINFO1 = "/lri"
SlashCmdList.LIBRESINFO = function(input)
input = gsub(input, "[^A-Za-z0-9]", "")
if strlen(input) > 0 then
if strmatch(input, "%D") then
local f = _G[input]
if type(f) == "table" and type(f.AddMessage) == "function" then
DEBUG_FRAME = f
debug(0, "Debug frame set to", input)
else
debug(0, input, "is not a valid debug output frame!")
end
else
local v = tonumber(input)
if v and v >= 0 then
DEBUG_LEVEL = v
debug(0, "Debug level set to", input)
else
debug(0, input, "is not a valid debug level!")
end
end
end
end
\ No newline at end of file
r58/LibResInfo-1.0/README.txt New file
0,0 → 1,47
LibResInfo-1.0
==================
 
* Library to provide information about resurrections cast in your group.
* Copyright (c) 2012 A. "Phanx" Kinley. All rights reserved.
* See the accompanying LICENSE file for details.
* http://www.wowinterface.com/downloads/info21467-LibResInfo-1.0.html
* http://wow.curseforge.com/addons/libresinfo/
 
 
Description
---------------
 
LibResInfo detects resurrection spell casts and identifies who they are
being cast on, and provides that information to addons through callbacks
and API functions.
 
LibResInfo was written to replace LibResComm. It works locally without
the need for addon communication, so it is not necessary for anyone else
in your group to have it installed.
 
Requires [LibStub] [1] and [CallbackHandler-1.0] [2].
 
[1]: http://www.wowace.com/addons/libstub/
[2]: http://www.wowace.com/addons/callbackhandler/
 
 
API Documentation
---------------------
 
Information about the callbacks and functions LibResInfo provides are
available on the [CurseForge project page] [3].
 
[3]: http://wow.curseforge.com/addons/librescomm/pages/api/
 
 
Feedback
------------
 
Please direct all bug reports, suggestions, questions, and comments to
the [WoWInterface forum thread] [4].
 
If you need to contact me privately for a reason other than those listed
above, you can send me a private message on either download site, or
email me at <addons@phanx.net>.
 
[4]: http://www.wowinterface.com/forums/showthread.php?t=43933
\ No newline at end of file
r58/LibResInfo-1.0/LICENSE.txt New file
0,0 → 1,35
Copyright (c) 2012 A. "Phanx" Kinley <addons@phanx.net>
 
All rights reserved.
 
Permission is granted for anyone to use, read, or otherwise interpret
this software for any purpose, without any restrictions.
 
Permission is granted for anyone to modify this software or sample from
it, and to distribute such modified versions or derivative works as long
as neither the names of this software nor its author are used in the
name or title of the work or in any other way that may cause it to be
confused with this software.
 
Permission is granted for anyone to embed or include this software in
another work not derived from this software that makes use of the
interface provided by this software for the purpose of creating a
package of the work and its required libraries, and to distribute such
packages as long as the software is not modified in any way, including
by modifying or removing any files.
 
This software may not be distributed standalone or in any other way, in
whole or in part, modified or unmodified, without specific prior written
permission from the author of this software.
 
The names of this software and/or its author may not be used to
promote or endorse works derived from this software without specific
prior written permission from the author of this software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
r58 Property changes : Added: svn:externals + svn://svn.wowace.com/wow/libstub/mainline/tags/1.0 LibStub svn://svn.wowace.com/wow/callbackhandler/mainline/tags/1.0.7/CallbackHandler-1.0 CallbackHandler-1.0