WoWInterface SVN LibResInfo

Compare Revisions

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

Rev 61 → Rev 72

18/LibResInfo-1.0/LibResInfo-1.0.lua New file
0,0 → 1,680
--[[--------------------------------------------------------------------
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.
http://www.wowinterface.com/downloads/info21467-LibResInfo-1.0.html
http://wow.curseforge.com/addons/libresinfo/
------------------------------------------------------------------------
TODO:
* Handle Reincarnation
----------------------------------------------------------------------]]
 
local DEBUG_LEVEL = GetAddOnMetadata("LibResInfo-1.0", "Version") and 1 or 0
local DEBUG_FRAME = ChatFrame3
 
------------------------------------------------------------------------
 
local MAJOR, MINOR = "LibResInfo-1.0", 18
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
 
------------------------------------------------------------------------
 
local callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib)
local eventFrame = lib.eventFrame or CreateFrame("Frame")
 
local guidFromUnit = lib.guidFromUnit or {} -- t[unit] = guid -- table lookup is faster than calling UnitGUID
local nameFromGUID = lib.nameFromGUID or {} -- t[guid] = name
local unitFromGUID = lib.unitFromGUID or {} -- t[guid] = unit
 
local castingSingle = lib.castingSingle or {} -- t[casterGUID] = { startTime = <number>, endTime = <number>, target = <guid> }
local castingMass = lib.castingMass or {} -- t[casterGUID] = endTime
local hasPending = lib.hasPending or {} -- t[targetGUID] = endTime
 
local hasSoulstone = lib.hasSoulstone or {} -- t[targetGUID] = <boolean>
local isDead = lib.isDead or {} -- t[targetGUID] = <boolean>
local isGhost = lib.isGhost or {} -- t[targetGUID] = <boolean>
 
------------------------------------------------------------------------
 
lib.callbacks = callbacks
lib.eventFrame = eventFrame
 
lib.guidFromUnit = guidFromUnit
lib.nameFromGUID = nameFromGUID
lib.unitFromGUID = unitFromGUID
 
lib.castingSingle = castingSingle
lib.castingMass = castingMass
lib.hasPending = hasPending
 
lib.hasSoulstone = hasSoulstone
lib.isDead = isDead
lib.isGhost = isGhost
 
------------------------------------------------------------------------
 
local RESURRECT_PENDING_TIME = 60
local RELEASE_PENDING_TIME = 360
local RECENTLY_MASS_RESURRECTED = GetSpellInfo(95223)
local SOULSTONE = GetSpellInfo(20707)
 
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
}
 
------------------------------------------------------------------------
 
local next, pairs, GetNumGroupMembers, GetTime, IsInGroup, IsInRaid, UnitAura, UnitCastingInfo, UnitGUID, UnitHasIncomingResurrection, UnitHealth, UnitIsConnected, UnitIsDead, UnitIsDeadOrGhost, UnitIsGhost, UnitName
= next, pairs, GetNumGroupMembers, GetTime, IsInGroup, IsInRaid, UnitAura, UnitCastingInfo, UnitGUID, UnitHasIncomingResurrection, UnitHealth, UnitIsConnected, UnitIsDead, UnitIsDeadOrGhost, UnitIsGhost, UnitName
 
------------------------------------------------------------------------
 
local function debug(level, text, ...)
if level <= DEBUG_LEVEL then
if ... 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
 
local newTable, remTable
do
local pool = {}
function newTable()
local t = next(pool)
if t then
pool[t] = nil
return t
end
return {}
end
function remTable(t)
pool[wipe(t)] = true
return nil
end
end
 
------------------------------------------------------------------------
 
lib.callbacksInUse = lib.callbacksInUse or {}
 
eventFrame:SetScript("OnEvent", function(self, event, ...)
return self[event] and self[event](self, event, ...)
end)
 
function callbacks:OnUsed(lib, callback)
if not next(lib.callbacksInUse) then
debug(1, "Callbacks in use! Starting up...")
eventFrame:RegisterEvent("GROUP_ROSTER_UPDATE")
eventFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
eventFrame:RegisterEvent("INCOMING_RESURRECT_CHANGED")
eventFrame:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED")
eventFrame:RegisterEvent("UNIT_SPELLCAST_START")
eventFrame:RegisterEvent("UNIT_SPELLCAST_STOP")
eventFrame:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")
eventFrame:RegisterEvent("UNIT_AURA")
eventFrame:RegisterEvent("UNIT_CONNECTION")
eventFrame:RegisterEvent("UNIT_HEALTH")
eventFrame:GROUP_ROSTER_UPDATE("OnUsed")
end
lib.callbacksInUse[callback] = true
end
 
function callbacks:OnUnused(lib, callback)
lib.callbacksInUse[callback] = nil
if not next(lib.callbacksInUse) then
debug(1, "No callbacks in use. Shutting down...")
eventFrame:UnregisterAllEvents()
eventFrame:Hide()
wipe(guidFromUnit)
wipe(nameFromGUID)
wipe(unitFromGUID)
wipe(castingMass)
wipe(hasPending)
wipe(hasSoulstone)
wipe(isDead)
wipe(isGhost)
for caster, data in pairs(castingSingle) do
castingSingle[caster] = remTable(data)
end
end
end
 
------------------------------------------------------------------------
 
function lib.RegisterAllCallbacks(handler, method, includeMassRes)
lib.RegisterCallback(handler, "LibResInfo_ResCastStarted", method)
lib.RegisterCallback(handler, "LibResInfo_ResCastCancelled", method)
lib.RegisterCallback(handler, "LibResInfo_ResCastFinished", method)
 
if includeMassRes then
lib.RegisterCallback(handler, "LibResInfo_MassResStarted", method)
lib.RegisterCallback(handler, "LibResInfo_MassResCancelled", method)
lib.RegisterCallback(handler, "LibResInfo_MassResFinished", method)
end
 
lib.RegisterCallback(handler, "LibResInfo_ResPending", method)
lib.RegisterCallback(handler, "LibResInfo_ResUsed", method)
lib.RegisterCallback(handler, "LibResInfo_ResExpired", method)
end
 
------------------------------------------------------------------------
-- Returns information about the res being cast on the specified unit.
-- Arguments: unit (unitID or GUID)
-- Returns: resType (string), endTime (number), caster (unitID), casterGUID
-- * All returns are nil if no res is being cast on the unit.
-- * resType is one of:
-- - SELFRES if the unit has a Soulstone or other self-res ability available,
-- - PENDING if the unit already has a res available to accept, or
-- - CASTING if a res is being cast on the unit.
-- * caster and casterGUID are nil if the unit is being Mass Ressed.
------------------------------------------------------------------------
 
function lib:UnitHasIncomingRes(unit)
if type(unit) ~= "string" then return end
local guid
if strmatch(unit, "^0x") then
guid = unit
unit = unitFromGUID[guid]
else
guid = UnitGUID(unit)
unit = unitFromGUID[guid]
end
if not guid or not unit or not UnitIsDeadOrGhost(unit) or not UnitIsConnected(unit) then
return
end
if hasPending[guid] then
local state = hasSoulstone[guid] and "SELFRES" or "PENDING"
--debug(2, "UnitHasIncomingRes", nameFromGUID[guid], state)
return state, hasPending[guid]
end
 
local state, firstCaster, firstEnd
for caster, data in pairs(castingSingle) do
if data.target == guid then
if not firstEnd or data.endTime < firstEnd then
state, firstCaster, firstEnd = "CASTING", caster, data.endTime
end
end
end
if not UnitDebuff(unit, RECENTLY_MASS_RESURRECTED) then
for caster, endTime in pairs(castingMass) do
if not firstEnd or endTime < firstEnd then
state, firstCaster, firstEnd = "MASSRES", caster, endTime
end
end
end
if state and firstCaster and firstEnd then
--debug(2, "UnitHasIncomingRes", nameFromGUID[guid], state, nameFromGUID[firstCaster])
return state, firstEnd, unitFromGUID[firstCaster], firstCaster
end
--debug(3, "UnitHasIncomingRes", nameFromGUID[guid], "nil")
end
 
------------------------------------------------------------------------
-- Return information about the res being cast by the specified unit.
-- Arguments: unit (unitID or GUID)
-- Returns: endTime (number), target (unitID), targetGUID (guid), isFirst (boolean)
-- * all returns are nil if the unit is not casting a res
-- * target and targetGUID are nil if the unit is casting Mass Res
------------------------------------------------------------------------
 
function lib:UnitIsCastingRes(unit)
if type(unit) ~= "string" then return end
local guid
if strmatch(unit, "^0x") then
guid = unit
unit = unitFromGUID[guid]
else
guid = UnitGUID(unit)
unit = unitFromGUID[guid]
end
if not guid or not unit then
return
end
 
local casting = castingSingle[guid]
if casting then
local endTime, target, isFirst = casting.endTime, casting.target, true
-- TODO: Handle edge case where this function is called in between the cast start and the target identification?
for caster, data in pairs(castingSingle) do
if data.target == target and data.endTime < endTime then
isFirst = false
break
end
end
--debug(2, "UnitIsCastingRes", nameFromGUID[guid], "casting on", nameFromGUID[casting.target], isFirst and "(first)" or "(duplicate)")
return endTime, unitFromGUID[casting.target], casting.target, isFirst
end
 
casting = castingMass[guid]
if casting then
local endTime, isFirst = casting, true
for caster, endTime2 in pairs(castingMass) do
if endTime2 < endTime then
isFirst = false
break
end
end
--debug(2, "UnitIsCastingRes", nameFromGUID[guid], "casting Mass Res", isFirst and "(first)" or "(duplicate)")
return endTime, nil, nil, isFirst
end
 
--debug(3, "UnitIsCastingRes", nameFromGUID[guid], "nil")
end
 
------------------------------------------------------------------------
-- Handle group changes:
 
local function AddUnit(unit)
local guid = UnitGUID(unit)
if not guid then return end
guidFromUnit[unit] = guid
nameFromGUID[guid] = UnitName(unit)
unitFromGUID[guid] = unit
-- Check for soulstones:
eventFrame:UNIT_AURA("AddUnit", unit)
end
 
function eventFrame:GROUP_ROSTER_UPDATE(event)
debug(3, event)
 
-- Update guid <==> unit mappings:
wipe(guidFromUnit)
wipe(unitFromGUID)
if IsInRaid() then
for i = 1, GetNumGroupMembers() do
AddUnit("raid"..i)
AddUnit("raidpet"..i)
end
else
AddUnit("player")
AddUnit("pet")
if IsInGroup() then
for i = 1, GetNumGroupMembers() - 1 do
AddUnit("party"..i)
AddUnit("partypet"..i)
end
end
end
 
-- Remove data for single casters no longer in the group:
for caster, data in pairs(castingSingle) do
if not unitFromGUID[caster] then
local target = data.target
castingSingle[caster] = remTable(data)
debug(1, ">> ResCastCancelled on", nameFromGUID[target], "by", nameFromGUID[caster], "(caster left group)")
callbacks:Fire("LibResInfo_ResCastCancelled", unitFromGUID[target], target, nil, caster)
end
end
 
-- Remove data for mass casters no longer in the group:
for caster in pairs(castingMass) do
if not unitFromGUID[caster] then
castingMass[caster] = nil
debug(1, ">> MassResCancelled by", nameFromGUID[caster], "(left group)")
callbacks:Fire("LibResInfo_MassResCancelled", nil, caster)
end
end
 
-- Remove data for targets no longer in the group:
for caster, data in pairs(castingSingle) do
local target = data.target
if not unitFromGUID[target] then
castingSingle[caster] = remTable(data)
-- TODO: Is this callback needed, or will the cast cancel on its own?
debug(1, ">> ResCastCancelled on", nameFromGUID[target], "by", nameFromGUID[caster], "(target left group)")
callbacks:Fire("LibResInfo_ResCastCancelled", nil, target, unitFromGUID[caster], caster)
end
end
 
-- Remove data for waiters no longer in the group:
for target in pairs(hasPending) do
if not unitFromGUID[target] then
hasPending[target] = nil
debug(1, ">> ResExpired on", nameFromGUID[target], "(left group)")
callbacks:Fire("LibResInfo_ResExpired", nil, target)
end
end
 
-- Unregister unit events and stop the timer if there are no waiters:
if not next(hasPending) then
debug(3, "Nobody pending, stop timer")
self:Hide()
end
 
-- Unregister CLEU if there are no casts:
if not next(castingSingle) and not next(castingMass) then
debug(3, "Nobody casting, unregistering CLEU")
self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
end
 
-- Remove names no longer in the group:
for guid, name in pairs(nameFromGUID) do
if not unitFromGUID[guid] then
debug(4, name, "is no longer in the group")
nameFromGUID[guid] = nil
end
end
end
 
eventFrame.PLAYER_ENTERING_WORLD = eventFrame.GROUP_ROSTER_UPDATE
 
------------------------------------------------------------------------
 
function eventFrame:INCOMING_RESURRECT_CHANGED(event, unit)
local guid = guidFromUnit[unit]
if not guid then return end
 
local hasRes = UnitHasIncomingResurrection(unit)
debug(3, event, nameFromGUID[guid], hasRes)
 
if hasRes then
-- Unit has a res incoming. Match it to a spell.
local now = GetTime()
for caster, data in pairs(castingSingle) do
if not data.target and data.startTime - now < 10 then
-- Found it!
data.target = guid
debug(1, ">> ResCastStarted on", nameFromGUID[guid], "by", nameFromGUID[caster], "in", event)
callbacks:Fire("LibResInfo_ResCastStarted", unit, guid, unitFromGUID[caster], caster, data.endTime)
break
end
end
-- TODO: Why was I searching for finished casts here???
else
-- Check if unit previously had any resses.
for caster, data in pairs(castingSingle) do
if data.target == guid then
debug(4, nameFromGUID[caster], "was casting...")
if data.startTime then
debug(4, "...and stopped.")
castingSingle[caster] = remTable(data)
debug(1, ">> ResCastCancelled", "on", nameFromGUID[guid], "by", nameFromGUID[casterGUID], "in", event)
callbacks:Fire("LibResInfo_ResCastCancelled", unit, guid, unitFromGUID[casterGUID], casterGUID)
else
debug(4, "...and finished.")
castingSingle[caster] = remTable(data)
hasPending[guid] = nil
debug(1, ">> ResCastFinished", "on", nameFromGUID[guid], "by", nameFromGUID[casterGUID], "in", event)
callbacks:Fire("LibResInfo_ResCastFinished", unit, guid, unitFromGUID[casterGUID], casterGUID)
self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
end
end
end
end
end
 
------------------------------------------------------------------------
 
function eventFrame:UNIT_SPELLCAST_START(event, unit, spellName, _, _, spellID)
if not resSpells[spellID] then return end
local guid = guidFromUnit[unit]
if not guid then return end
debug(3, event, nameFromGUID[guid], "casting", spellName)
 
local _, _, _, _, startTime, endTime = UnitCastingInfo(unit)
 
if spellID == 83968 then -- Mass Resurrection
castingMass[guid] = endTime / 1000
debug(1, ">> MassResStarted", nameFromGUID[guid])
callbacks:Fire("LibResInfo_MassResStarted", unit, guid, endTime / 1000)
return
end
 
local data = newTable()
data.startTime = startTime / 1000
data.endTime = endTime / 1000
castingSingle[guid] = data
end
 
function eventFrame:UNIT_SPELLCAST_SUCCEEDED(event, unit, spellName, _, _, spellID)
if not resSpells[spellID] then return end
local guid = guidFromUnit[unit]
if not guid then return end
 
debug(3, event, nameFromGUID[guid], "finished", spellName)
 
if spellID == 83968 then -- Mass Resurrection
castingMass[guid] = nil
debug(1, ">> MassResFinished", nameFromGUID[guid])
callbacks:Fire("LibResInfo_MassResFinished", unit, guid)
self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
return
end
 
local data = castingSingle[guid]
if data then -- No START event for instant cast spells.
local target = data.target
if not target then
-- Probably Soulstone precast on a live target.
return
end
data.finished = true -- Flag so STOP can ignore this.
debug(1, ">> ResCastFinished", "on", nameFromGUID[target], "by", nameFromGUID[guid], "in", event)
callbacks:Fire("LibResInfo_ResCastFinished", unitFromGUID[target], target, unit, guid)
end
 
debug(3, "Registering CLEU")
self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
end
 
function eventFrame:UNIT_SPELLCAST_STOP(event, unit, spellName, _, _, spellID)
if not resSpells[spellID] then return end
local guid = guidFromUnit[unit]
if not guid then return end
 
debug(3, event, nameFromGUID[guid], "stopped", spellName)
 
if spellID == 83968 then -- Mass Resurrection
if not castingMass[guid] then return end -- already SUCCEEDED
castingMass[guid] = nil
debug(1, ">> MassResCancelled", nameFromGUID[guid])
callbacks:Fire("LibResInfo_MassResCancelled", unit, guid)
else
local data = castingSingle[guid]
if data then
local target = data.target
local finished = data.finished
castingSingle[guid] = remTable(data)
if finished or not target then
-- no target = Probably Soulstone precast on a live target.
-- finished = Cast finished. Don't fire a callback or unregister CLEU.
return
end
debug(1, ">> ResCastCancelled", "on", nameFromGUID[target], "by", nameFromGUID[guid])
callbacks:Fire("LibResInfo_ResCastCancelled", unitFromGUID[target], target, unit, guid)
end
end
 
-- Unregister CLEU if there are no casts:
if not next(castingSingle) and not next(castingMass) then
debug(3, "Nobody casting, unregistering CLEU")
self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
end
end
 
eventFrame.UNIT_SPELLCAST_INTERRUPTED = eventFrame.UNIT_SPELLCAST_STOP
 
------------------------------------------------------------------------
 
function eventFrame:COMBAT_LOG_EVENT_UNFILTERED(event, timestamp, combatEvent, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags, spellID, spellName, spellSchool)
if combatEvent ~= "SPELL_RESURRECT" then return end
 
local destUnit = unitFromGUID[destGUID]
if not destUnit then return end
debug(3, combatEvent, "on", destName, "by", sourceName)
 
local now = GetTime()
local endTime = now + RESURRECT_PENDING_TIME
 
hasPending[destGUID] = endTime
 
self:Show()
 
debug(1, ">> ResPending", "on", strmatch(destName, "[^%-]+"), "by", strmatch(sourceName, "[^%-]+"))
callbacks:Fire("LibResInfo_ResPending", destUnit, destGUID, endTime)
 
-- Unregister CLEU if there are no casts:
if not next(castingSingle) and not next(castingMass) then
-- TODO: Keep track of number of instant casts?
-- Seems unlikely that multiple casts would end so close together that this would be an issue.
debug(3, "Nobody casting, unregistering CLEU")
self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
end
end
 
------------------------------------------------------------------------
 
function eventFrame:UNIT_AURA(event, unit)
local guid = guidFromUnit[unit]
if not guid then return end
debug(5, event, unit)
 
if not isDead[guid] then
local stoned = UnitAura(unit, SOULSTONE)
if stoned ~= hasSoulstone[guid] then
if not stoned and UnitHealth(unit) <= 1 then
return
end
hasSoulstone[guid] = stoned
debug(2, nameFromGUID[guid], stoned and "gained" or "lost", SOULSTONE)
end
return
end
 
if UnitIsGhost(unit) and not isGhost[guid] then
isGhost[guid] = true
if hasPending[guid] then
hasPending[guid] = nil
debug(1, ">> ResExpired", nameFromGUID[guid], "(released)")
callbacks:Fire("LibResInfo_ResExpired", unit, guid)
end
end
end
 
function eventFrame:UNIT_CONNECTION(event, unit)
local guid = guidFromUnit[unit]
if not guid then return end
debug(4, event, unit)
 
if hasPending[unit] and not UnitIsConnected(unit) then
hasPending[guid] = nil
debug(1, ">> ResExpired", nameFromGUID[guid], "(offline)")
callbacks:Fire("LibResInfo_ResExpired", unit, guid)
end
end
 
function eventFrame:UNIT_HEALTH(event, unit)
local guid = guidFromUnit[unit]
if not guid then return end
debug(5, event, unit)
 
local dead = UnitIsDead(unit)
 
if dead and not isDead[guid] then
debug(2, nameFromGUID[guid], "is now dead")
isDead[guid] = true
if hasSoulstone[guid] then
local endTime = GetTime() + RELEASE_PENDING_TIME
hasPending[guid] = endTime
debug(1, ">> ResPending", nameFromGUID[guid], SOULSTONE)
callbacks:Fire("LibResInfo_ResPending", unit, guid, endTime, true)
end
 
elseif isDead[guid] and not dead then
debug(2, nameFromGUID[guid], "is now alive")
isDead[guid] = nil
if hasPending[guid] then
isGhost[guid] = nil
hasPending[guid] = nil
debug(1, ">> ResUsed", nameFromGUID[guid])
callbacks:Fire("LibResInfo_ResUsed", unit, guid)
end
end
end
 
------------------------------------------------------------------------
 
eventFrame:Hide()
 
local timer, INTERVAL = 0, 0.5
eventFrame:SetScript("OnUpdate", function(self, elapsed)
timer = timer + elapsed
if timer >= INTERVAL then
debug(6, "Timer update")
if not next(hasPending) then
debug(4, "Nobody pending, stop timer")
return self:Hide()
end
local now = GetTime()
for guid, endTime in pairs(hasPending) do
if endTime - now < INTERVAL then -- It will expire before the next update.
local unit = unitFromGUID[guid]
hasPending[guid] = nil
debug(1, ">> ResExpired", nameFromGUID[guid])
callbacks:Fire("LibResInfo_ResExpired", unit, guid, true)
end
end
timer = 0
end
end)
 
eventFrame:SetScript("OnShow", function()
debug(4, "Timer start")
end)
 
eventFrame: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) < 1 then return end
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
\ No newline at end of file
18/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-2013 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
18/LibResInfo-1.0/LICENSE.txt New file
0,0 → 1,35
Copyright (c) 2012-2013 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
18/LibResInfo-1.0.toc New file
0,0 → 1,24
## Interface: 50400
## Version: 18
 
## Title: Lib: ResInfo-1.0
## Notes: Library to provide information about resurrections.
## Notes-deDE: Eine Bibliothek, die Informationen über Wiederbelebungen liefert.
## Notes-esES: Una biblioteca para proporcionar información sobre resurreciones.
## Notes-esMX: Una biblioteca para proporcionar información sobre resurreciones.
 
## Author: Phanx
## X-Email: addons@phanx.net
## X-Copyright: Copyright (c) 2012-2013 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
18 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