WoWInterface SVN oUF_Smee2

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 5 to Rev 6
    Reverse comparison

Rev 5 → Rev 6

trunk/oUF_Smee2/core.lua
2,15 → 2,17
local _,playerClass = UnitClass("player")
local tinsert = table.insert
local layoutName = "oUF_Smee2"
 
_G[layoutName] = LibStub("AceAddon-3.0"):NewAddon(layoutName,"AceConsole-3.0")
local addon = _G[layoutName];
addon.LSM = LibStub("LibSharedMedia-3.0")
addon.build = {}
addon.build.version, addon.build.build, addon.build.date, addon.build.tocversion = GetBuildInfo()
addon.LSM = LibStub("LibSharedMedia-3.0")
addon.build = {}
addon.build.version, addon.build.build, addon.build.date, addon.build.tocversion = GetBuildInfo()
addon.oUF = oUFSmee2_embed
oUFSmee2_embed = nil
 
 
---------------
-- UI tweaks --
-- LDB --
---------------
local LDB = LibStub:GetLibrary("LibDataBroker-1.1"):NewDataObject(layoutName, {
label = "|cFF006699oUF|r_|cFFFF3300Smee|r",
trunk/oUF_Smee2/oUF_Smee2.toc
5,10 → 5,19
## X-eMail: airtonix@gmail.com
## Version: 30100.008
## SavedVariables: oUF_Smee2DB
## OptionalDeps: Ace3, SharedMedia, oUF_PowerSpark, oUF_Banzai, oUF_Smooth, oUF_CombatFeedback, oUF_HealComm, oUF_DebuffHighlight, oUF_SpellRange, oUF_ReadyCheck, oUF_TagEditor
## RequiredDeps: oUF, oUF_TagEditor
## OptionalDeps: Ace3, SharedMedia, oUF_PowerSpark, oUF_Banzai, oUF_Smooth, oUF_CombatFeedback, oUF_HealComm, oUF_DebuffHighlight, oUF_SpellRange, oUF_ReadyCheck
## DefaultState: enabled
## X-oUF: oUFSmee2_embed
oUFembed/oUF.xml
 
## Libraries
embeds.xml
 
## Plugins
oUF_SmeeRunes.lua
oUF_HealComm.lua
 
## Core
tagEditor.lua
settings.lua
core.lua
trunk/oUF_Smee2/Libs/LibHealComm-3.0.lua New file
0,0 → 1,1396
local MAJOR_VERSION = "LibHealComm-3.0";
local MINOR_VERSION = 90000 + tonumber(("$Revision: 48 $"):match("%d+"));
 
local lib = LibStub:NewLibrary(MAJOR_VERSION, MINOR_VERSION);
if not lib then return end
 
local playerName = UnitName('player');
local playerRealm = GetRealmName();
local playerClass = select(2, UnitClass('player'));
local isHealer = (playerClass == "PRIEST") or (playerClass == "SHAMAN") or (playerClass == "DRUID") or (playerClass == "PALADIN");
 
 
-----------------
-- Event Frame --
-----------------
 
lib.EventFrame = lib.EventFrame or CreateFrame("Frame");
lib.EventFrame:SetScript("OnEvent", function (this, event, ...) lib[event](lib, ...) end);
lib.EventFrame:UnregisterAllEvents();
 
-- Register Events
lib.EventFrame:RegisterEvent("PLAYER_ALIVE");
lib.EventFrame:RegisterEvent("LEARNED_SPELL_IN_TAB");
lib.EventFrame:RegisterEvent("CHAT_MSG_ADDON");
lib.EventFrame:RegisterEvent("UNIT_SPELLCAST_DELAYED");
lib.EventFrame:RegisterEvent("UNIT_AURA");
lib.EventFrame:RegisterEvent("UNIT_TARGET");
lib.EventFrame:RegisterEvent("PLAYER_TARGET_CHANGED");
lib.EventFrame:RegisterEvent("PLAYER_FOCUS_CHANGED");
lib.EventFrame:RegisterEvent("GLYPH_ADDED");
lib.EventFrame:RegisterEvent("GLYPH_REMOVED");
lib.EventFrame:RegisterEvent("GLYPH_UPDATED");
 
-- For keeping track of versions
lib.EventFrame:RegisterEvent("PARTY_MEMBERS_CHANGED");
lib.EventFrame:RegisterEvent("RAID_ROSTER_UPDATE");
 
-- Prune data at zone change
lib.EventFrame:RegisterEvent("PLAYER_ENTERING_WORLD");
 
-- Only listen to these events if player is healing class
if (isHealer) then
lib.EventFrame:RegisterEvent("UNIT_SPELLCAST_SENT");
lib.EventFrame:RegisterEvent("UNIT_SPELLCAST_START");
lib.EventFrame:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED");
lib.EventFrame:RegisterEvent("UNIT_SPELLCAST_STOP");
end
 
 
----------------------
-- Scanning Tooltip --
----------------------
 
if (not lib.Tooltip) then
lib.Tooltip = CreateFrame("GameTooltip");
lib.Tooltip:SetOwner(UIParent, "ANCHOR_NONE");
for i = 1, 4 do
lib["TooltipTextLeft" .. i] = lib.Tooltip:CreateFontString();
lib["TooltipTextRight" .. i] = lib.Tooltip:CreateFontString();
lib.Tooltip:AddFontStrings(lib["TooltipTextLeft" .. i], lib["TooltipTextRight" .. i]);
end
end
 
 
-------------------------------
-- Embed CallbackHandler-1.0 --
-------------------------------
 
lib.Callbacks = LibStub("CallbackHandler-1.0"):New(lib);
 
 
-----------------
-- Static Data --
-----------------
 
-- Cache of spells and heal sizes
local SpellCache = {};
 
-- Cache of glyphs
local GlyphCache = {};
 
-- Info about spells being cast by other players
local HealTime = {};
local HealTarget = {};
local HealSize = {};
 
-- Healing Modifiers (by name)
local HealModifier = {};
 
-- Last target name from UNIT_SPELLCAST_SENT
local SentTargetName;
 
-- Last spellCastIndex from UNIT_SPELLCAST_STOP
local LastSpellCastIndex;
 
-- Info about the spell being cast by the player
local CastInfoIsCasting;
local CastInfoHealingTargetUnitID;
local CastInfoHealingTargetNames;
local CastInfoHealingSize;
local CastInfoEndTime;
 
-- Latency Measurement
local SentTime = 0;
local Latency = 0;
 
-- Version Information Table
local Versions = {};
 
-- Battleground/Arena/Group Indicators
local InBattlegroundOrArena;
local InRaidOrParty;
 
 
---------------------------------
-- Frequently Accessed Globals --
---------------------------------
 
local type = type;
local tonumber = tonumber;
local math = math;
local string = string;
local select = select;
local pairs = pairs;
local unpack = unpack;
local UnitName = UnitName;
local SendAddonMessage = SendAddonMessage;
local IsInInstance = IsInInstance;
local UnitBuff = UnitBuff;
local UnitDebuff = UnitDebuff;
local UnitLevel = UnitLevel;
local GetInventoryItemLink = GetInventoryItemLink;
local GetTime = GetTime;
local UnitCastingInfo = UnitCastingInfo;
local GetSpellBonusHealing = GetSpellBonusHealing;
local GetTalentInfo = GetTalentInfo;
local UnitExists = UnitExists;
local tinsert = table.insert;
local tconcat = table.concat;
 
 
---------------
-- Utilities --
---------------
 
local function unitFullName(unit)
local name, realm = UnitName(unit);
if (realm and realm ~= "") then
return name .. "-" .. realm;
else
return name;
end
end
 
local function extractRealm(fullName)
return fullName:match("^[^%-]+%-(.+)$");
end
 
-- Convert a remotely generated fully qualified name to
-- a local fully qualified name.
local function convertRealm(fullName, remoteRealm)
if (remoteRealm) then
local name, realm = fullName:match("^([^%-]+)%-(.+)$");
if (not realm) then
-- Apply remote realm if there is no realm on the target
return fullName .. "-" .. remoteRealm;
elseif (realm == playerRealm) then
-- Strip realm if it is equal to the local realm
return name;
end
end
return fullName;
end
 
local function commSend(contents, distribution, target)
SendAddonMessage("HealComm", contents, distribution or (InBattlegroundOrArena and "BATTLEGROUND" or "RAID"), target);
end
 
-- Spellbook Scanner --
local function getBaseHealSize(name)
 
-- Check if info is already cached
if (SpellCache[name]) then
return SpellCache[name];
end
 
SpellCache[name] = {};
 
-- Gather info (only done if not in cache)
local i = 1;
 
while true do
 
local spellName, spellRank = GetSpellName(i, BOOKTYPE_SPELL);
 
if (not spellName) then
break
end
 
if (spellName == name) then
-- This is the spell we're looking for, gather info
 
-- Determine rank
spellRank = tonumber(spellRank:match("(%d+)"));
lib.Tooltip:SetSpell(i, BOOKTYPE_SPELL);
 
-- Determine healing
local HealMin, HealMax = select(3, string.find(lib.TooltipTextLeft4:GetText() or lib.TooltipTextLeft3:GetText() or "", "(%d+) ?[\195\160tobisa到~\-]+ ?(%d+)"));
HealMin, HealMax = tonumber(HealMin) or 0, tonumber(HealMax) or 0;
local Heal = (HealMin + HealMax) / 2;
 
SpellCache[spellName][spellRank] = Heal;
end
i = i + 1;
end
 
return SpellCache[name];
end
 
local function detectGlyph(id)
 
-- Check if info is already cached
if (GlyphCache[id] ~= nil) then
return GlyphCache[id];
end
 
GlyphCache[id] = false;
 
-- Gather info (only done if not in cache)
for i = 1, GetNumGlyphSockets() do
local enabled, _, glyphId = GetGlyphSocketInfo(i);
if (enabled and glyphId) then
GlyphCache[glyphId] = true;
end
end
 
return GlyphCache[id];
end
 
-- Detects if a buff is present on the unit and returns the application number.
-- Optionally, if the third argument is provided and is true, then only return
-- true if the buff was placed by the player.
local function detectBuff(unit, buffName, mineOnly)
local name, _, _, count, _, _, _, isMine = UnitBuff(unit, buffName);
return name and (not mineOnly or isMine) and count or false;
end
 
--[[
[GetSpellInfo(604)] = -20, -- Dampen Magic (Rank 1)
[GetSpellInfo(8450)] = -40, -- Dampen Magic (Rank 2)
[GetSpellInfo(8451)] = -80, -- Dampen Magic (Rank 3)
[GetSpellInfo(10173)] = -120, -- Dampen Magic (Rank 4)
[GetSpellInfo(10174)] = -180, -- Dampen Magic (Rank 5)
[GetSpellInfo(33944)] = -240, -- Dampen Magic (Rank 6)
[GetSpellInfo(1008)] = 30, -- Amplify Magic (Rank 1)
[GetSpellInfo(8455)] = 60, -- Amplify Magic (Rank 2)
[GetSpellInfo(10169)] = 100, -- Amplify Magic (Rank 3)
[GetSpellInfo(10170)] = 150, -- Amplify Magic (Rank 4)
[GetSpellInfo(27130)] = 180, -- Amplify Magic (Rank 5)
[GetSpellInfo(33946)] = 240, -- Amplify Magic (Rank 6)
[GetSpellInfo(32858)] = -345 -- Touch of the Forgotten (Auchenai Crypts)
[GetSpellInfo(38377)] = -690 -- Touch of the Forgotten (Auchenai Crypts)
]]--
 
local healingBuffs =
{
[GetSpellInfo(706)] = 1.20, -- Demon Armor
[GetSpellInfo(45234)] = function (count, rank) return (1.0 + (0.04 + 0.03 * (rank - 1)) * count) end, -- Focused Will
[GetSpellInfo(34123)] = 1.06, -- Tree of Life
[GetSpellInfo(58549)] = function (count, rank, texture) return ((texture == "Interface\\Icons\\Ability_Warrior_StrengthOfArms") and (1.18 ^ count) or 1.0) end, -- Tenacity (Wintergrasp)
}
 
local healingDebuffs =
{
[GetSpellInfo(25646)] = function (count) return (1.0 - count * 0.10) end, -- Mortal Wound (Temporus - The Black Morass)
[GetSpellInfo(45347)] = function (count) return (1.0 - count * 0.04) end, -- Dark Touched (Grand Warlock Alythess - Sunwell Plateau)
[GetSpellInfo(30423)] = function (count) return (1.0 - count * 0.01) end, -- Nether Portal - Dominance (Netherspite - Karazhan)
[GetSpellInfo(13218)] = function (count) return (1.0 - count * 0.10) end, -- Wound Poison
[GetSpellInfo(19434)] = 0.50, -- Aimed Shot
[GetSpellInfo(12294)] = 0.50, -- Mortal Strike
[GetSpellInfo(40599)] = 0.50, -- Arcing Smash (Gurtogg Bloodboil)
[GetSpellInfo(23169)] = 0.50, -- Brood Affliction: Green (Chromaggus)
[GetSpellInfo(34073)] = 0.85, -- Curse of the Bleeding Hollow (Hellfire Peninsula)
[GetSpellInfo(13583)] = 0.50, -- Curse of the Deadwood (Deadwood Furbolgs - Felwood)
[GetSpellInfo(36023)] = 0.50, -- Deathblow
[GetSpellInfo(34625)] = 0.25, -- Demolish (Negatron - Netherstorm)
[GetSpellInfo(34366)] = 0.75, -- Ebon Poison (Black Morass)
[GetSpellInfo(32378)] = 0.50, -- Filet (Spectral Chef - Karazhan)
[GetSpellInfo(19716)] = 0.25, -- Gehennas' Curse (Gehennas - Molten Core)
[GetSpellInfo(36917)] = 0.50, -- Magma-Thrower's Curse (Sulfuron Magma-Thrower - The Arcatraz)
[GetSpellInfo(22859)] = 0.50, -- Mortal Cleave (High Priestess Thekal - Zul'Gurub)
[GetSpellInfo(38572)] = 0.50, -- Mortal Cleave (High Priestess Thekal - Zul'Gurub)
[GetSpellInfo(39595)] = 0.50, -- Mortal Cleave (High Priestess Thekal - Zul'Gurub)
[GetSpellInfo(28776)] = 0.10, -- Necrotic Poison (Maexxna - Naxxramas)
[GetSpellInfo(35189)] = 0.50, -- Solar Strike (The Mechanar)
[GetSpellInfo(32315)] = 0.50, -- Soul Strike (Ethereal Crypt Raiders - Mana-Tombs)
[GetSpellInfo(7068)] = 0.25, -- Veil of Shadow (Nefarian - Blackwing Lair)
[GetSpellInfo(38387)] = 1.50, -- Bane of Infinity (CoT: Escape from Durholde)
[GetSpellInfo(31977)] = 1.50, -- Curse of Infinity (CoT: Escape from Durholde)
[GetSpellInfo(41292)] = 0.00, -- Aura of Suffering (Essence of Souls - Black Temple)
[GetSpellInfo(41350)] = 2.00, -- Aura of Desire (Essence of Souls - Black Temple)
[GetSpellInfo(30843)] = 0.00, -- Enfeeble (Prince Malchezaar - Karazhan)
}
 
local function calculateHealModifier(unit)
local modifier = 1.0;
 
for i = 1, 40 do
local name, rank, texture, count = UnitDebuff(unit, i);
if (not name) then
break;
end
local mark = healingDebuffs[name];
if (mark) then
if (type(mark) == "function") then
mark = mark(count);
end
if (mark < modifier) then
modifier = mark;
end
end
end
for i = 1, 40 do
local name, rank, texture, count = UnitBuff(unit, i);
if (not name) then
break;
end
local mark = healingBuffs[name];
if (mark) then
if (type(mark) == "function") then
mark = mark(count, rank and tonumber(rank:match("(%d+)")), texture);
end
modifier = modifier * mark;
end
end
 
return modifier;
end
 
local function getDownrankingFactor(spellLevel, playerLevel)
local factor = 0.05 * ((spellLevel + 7) - playerLevel) + 1;
if (factor > 1.0) then
return 1;
elseif (factor < 0.0) then
return 0;
else
return factor;
end
end
 
local relicSlotNumber = GetInventorySlotInfo("RangedSlot");
local function getEquippedRelicID()
local itemLink = GetInventoryItemLink('player', relicSlotNumber);
if (itemLink) then
return tonumber(itemLink:match("(%d+):"));
end
end
 
 
-----------------------------
-- Healing Data Management --
-----------------------------
 
local function entryDelete(healerName)
local targetNames = HealTarget[healerName];
HealTime[healerName] = nil;
HealTarget[healerName] = nil;
if (type(targetNames) == "table") then
for i, targetName in pairs(targetNames) do
if HealSize[targetName] then
HealSize[targetName][healerName] = nil;
end
end
elseif (targetNames and HealSize[targetNames]) then
HealSize[targetNames][healerName] = nil;
end
end
 
local function entryUpdate(healerName, targetNames, healSize, healTime)
entryDelete(healerName);
HealTime[healerName] = healTime;
HealTarget[healerName] = targetNames;
if (type(targetNames) == "table") then
for i, targetName in pairs(targetNames) do
if (not HealSize[targetName]) then
HealSize[targetName] = {};
end
HealSize[targetName][healerName] = healSize;
end
elseif (targetNames) then
if (not HealSize[targetNames]) then
HealSize[targetNames] = {};
end
HealSize[targetNames][healerName] = healSize;
end
end
 
local function entryRetrieve(healerName)
local healTime = HealTime[healerName];
if (healTime) then
local targetNames = HealTarget[healerName];
if (type(targetNames) == "table") then
return targetNames, HealSize[targetNames[1]][healerName], healTime;
elseif (targetNames) then
return targetNames, HealSize[targetNames][healerName], healTime;
end
end
end
 
 
----------------------
-- Public Functions --
----------------------
 
--[[ UnitIncomingHealGet(unit, time)
 
Description: Retrieve info about the incoming heals to a specific
target. The second argument specifies a boundary time,
relative to the current time. Examples:
 
UnitIncomingHealGet("Kaki", GetTime() + 3)
UnitIncomingHealGet("Kaki-Emerald Dream", GetTime() + 3)
UnitIncomingHealGet("player", GetTime() + 3)
UnitIncomingHealGet("raid10", GetTime() + 3)
UnitIncomingHealGet("target", GetTime() + 3)
 
Retrieves info about the incoming heals on the specified
target. incomingHealBefore will contain the sum of heals
that will land within the next 3 seconds, and
incomingHealAfter will contain the sum of heals that will
land after 3 seconds.
 
Input:
unit - The exact name or UnitID of the unit to retrieve information about.
time - the desired boundary time of the inquiry.
 
Output:
incomingHealBefore - The total size of the incoming heals before the boundary time.
incomingHealAfter - The total size of the incoming heals after the boundary time.
nextTime - the time left until the next incoming heal will land.
nextSize - the size of the next incoming heal.
nextName - the name of the healer casting the next incoming heal.
 
]]--
 
function lib:UnitIncomingHealGet(unit, time)
if (type(unit) ~= "string") then return end
if (type(time) ~= "number") then return end
 
local targetName = unitFullName(unit);
if (HealSize[targetName]) then
local now = GetTime();
local incomingHealBefore, incomingHealAfter = 0, 0;
local nextTime, nextSize, nextName;
for healerName, size in pairs(HealSize[targetName]) do
local healTime = HealTime[healerName];
if (size and healTime) then
healTime = healTime + Latency;
if (healTime > now) then
if (healTime < time) then
-- Due before boundary time
incomingHealBefore = incomingHealBefore + size;
else
-- Due after boundary time
incomingHealAfter = incomingHealAfter + size;
end
if ((not nextTime) or (healTime < nextTime)) then
nextTime = healTime;
nextSize = size;
nextName = healerName;
end
end
end
end
if ((incomingHealBefore > 0) or (incomingHealAfter > 0)) then
return incomingHealBefore, incomingHealAfter, nextTime, nextSize, nextName;
end
end
end
 
--[[ UnitCastingHealGet(unit)
 
Description: Retrieve info about the direct healing spell
currently being cast by any unit. Examples:
 
UnitCastingHealGet("Kaki");
UnitCastingHealGet("Kaki-Emerald Dream");
UnitCastingHealGet("player")
UnitCastingHealGet("raid10")
UnitCastingHealGet("target")
 
Input:
unit - The name or UnitID of the unit to retrieve information about.
 
Output:
healSize - Size of the healing being cast.
endTime - The time when the healing completes.
targetName - Name of the unit(s) being targeted for heal.
 
]]--
 
function lib:UnitCastingHealGet(unit)
if (type(unit) ~= "string") then return end
local healerName = unitFullName(unit);
 
if (healerName == playerName) then
if (CastInfoIsCasting) then
return CastInfoHealingSize, CastInfoEndTime, CastInfoHealingTargetNames;
end
else
local targetNames, healSize, endTime = entryRetrieve(healerName);
if (targetNames) then
return healSize, endTime, targetNames;
end
end
end
 
--[[ UnitHealModifierGet(unit)
 
Description: Returns the modifier to healing (as a factor)
caused by buffs and debuffs. Examples:
 
UnitHealModifierGet("Kaki");
UnitHealModifierGet("Kaki-Emerald Dream");
UnitHealModifierGet("player", 3)
UnitHealModifierGet("raid10", 3)
UnitHealModifierGet("target", 3)
 
Input:
unit - The name or UnitID of the unit to retrieve information about.
 
Output:
factor - Always a fractional number - will be 1.0 if no buffs/debuffs
affect healing.
 
]]--
 
function lib:UnitHealModifierGet(unit)
if (type(unit) ~= "string") then return end
 
local targetName = unitFullName(unit);
return HealModifier[targetName] or calculateHealModifier(unit);
end
 
 
function lib:GetRaidOrPartyVersions()
local tab = {};
 
if (GetNumRaidMembers() > 0) then
for i = 1, GetNumRaidMembers() do
local name = unitFullName('raid' .. i);
if (not (name == playerName)) then
tab[name] = Versions[name] or false;
end
end
elseif (GetNumPartyMembers() > 0) then
for i = 1, GetNumPartyMembers() do
local name = unitFullName('party' .. i);
tab[name] = Versions[name] or false;
end
end
 
tab[playerName] = MINOR_VERSION;
 
return tab;
end
 
function lib:GetGuildVersions()
local tab = {};
 
if (IsInGuild()) then
GuildRoster();
 
for i = 1, GetNumGuildMembers(false) do
local name, rank, rankIndex, level, class, zone, note, officernote, online, status = GetGuildRosterInfo(i);
if (online and not (name == playerName)) then
tab[name] = Versions[name] or false;
end
end
end
 
tab[playerName] = MINOR_VERSION;
 
return tab;
end
 
function lib:GetUnitVersion(unit)
if (type(unit) ~= "string") then return end
 
local targetName = unitFullName(unit);
if (targetName == playerName) then return MINOR_VERSION end
return Versions[targetName] or false;
end
 
 
--------------------
-- Class Specific --
--------------------
 
local HealingSpells;
--local HotSpells;
local GetHealSize;
 
-- Druid --
 
-- TODO:
-- Talent: Empowered Rejuvenation. Increase effect of all HOTs by 4%-20%
-- Idol: Idol of Rejuvenation
 
if (playerClass == "DRUID") then
 
local tHealingTouch = GetSpellInfo(5185);
local tRegrowth = GetSpellInfo(8936);
local tNourish = GetSpellInfo(50464);
local tRejuvenation = GetSpellInfo(774);
local tLifebloom = GetSpellInfo(33763);
local tWildGrowth = GetSpellInfo(48438);
 
--[[HotSpells =
{
[tRegrowth] =
{
Level = {17, 23, 29, 35, 41, 47, 53, 59, 65, 70, 76, 80},
Duration = 21,
Ticks = 7,
Pattern = "(%d+)[^0-9]+%d+[^0-9]+$",
Type = "HoT",
},
[tRejuvenation] =
{
Level = {9, 15, 21, 27, 33, 39, 45, 51, 57, 59, 62, 68, 74, 79, 80},
Duration = 12,
Ticks = 4,
Pattern = "(%d+)",
Type = "HoT",
},
[tLifebloom] =
{
Level = {71, 79, 80},
Duration = 7,
Ticks = 7,
Pattern = "(%d+)"
Type = "Lifebloom",
},
}]]--
 
HealingSpells =
{
[tHealingTouch] =
{
Level = {1, 8, 14, 20, 26, 32, 38, 44, 50, 56, 60, 62, 69, 74, 79},
Type = "Direct",
},
[tRegrowth] =
{
Level = {12, 18, 24, 30, 36, 42, 48, 54, 60, 65, 71, 77},
Type = "Direct",
},
[tNourish] =
{
Level = {80};
Type = "Direct",
}
}
 
local idolsHealingTouch =
{
[28568] = 136, -- Idol of the Avian Heart
[22399] = 100, -- Idol of Health
}
 
GetHealSize = function(name, rank, target)
local i, effectiveHeal;
 
-- Get static spell info
local baseHealSize = getBaseHealSize(name)[rank];
local nBonus = 0;
local effectiveHealModifier = 1.0;
 
if (not baseHealSize) then
return nil;
end
 
-- Get +healing bonus
local bonus = GetSpellBonusHealing();
 
local spellTab = HealingSpells[name];
 
-- Gift of Nature Talent - Increases effective healing by 2% per rank on all spells
effectiveHealModifier = effectiveHealModifier * (2 * select(5, GetTalentInfo(3, 13)) / 100 + 1);
 
-- Process individual spells
if (name == tHealingTouch) then
local idolBonus = idolsHealingTouch[getEquippedRelicID()] or 0;
baseHealSize = baseHealSize + idolBonus;
 
-- Glyph of Healing Touch (decreases amount healed by 50%)
if (detectGlyph(54825)) then
effectiveHealModifier = effectiveHealModifier * 0.5
end
 
-- Empowered Touch Talent (increases bonus healing effects by 20% per rank)
local talentEmpoweredTouch = 20 * select(5, GetTalentInfo(3, 15)) / 100;
 
if (rank < 5) then
nBonus = bonus * (1.88 * (1.0 + rank * 0.5) / 3.5 + talentEmpoweredTouch);
else
nBonus = bonus * (1.88 + talentEmpoweredTouch);
end
elseif (name == tRegrowth) then
-- Glyph of Regrowth (increases effective healing by 20% if player's Regrowth is on target)
if (detectGlyph(54743) and detectBuff(target, tRegrowth, true)) then
effectiveHealModifier = effectiveHealModifier * 1.2;
end
nBonus = bonus * 1.88 * (2.0 / 3.5) * 0.5;
elseif (name == tNourish) then
-- Nourish heals for 20% more if player's HoT is on the target.
if (detectBuff(target, tRejuvenation, true) or detectBuff(target, tRegrowth, true) or detectBuff(target, tLifebloom, true) or detectBuff(target, tWildGrowth, true)) then
effectiveHealModifier = effectiveHealModifier * 1.2
end
nBonus = bonus * 1.88 * (1.5 / 3.5);
end
 
effectiveHeal = effectiveHealModifier * (baseHealSize + nBonus * getDownrankingFactor(spellTab.Level[rank], UnitLevel('player')));
return effectiveHeal;
end
 
end
 
-- Paladin --
-- TODO: Track Beacon of Light (GetSpellInfo(53563) for name).
if (playerClass == "PALADIN") then
 
local tHolyLight = GetSpellInfo(635);
local tFlashOfLight = GetSpellInfo(19750);
local tDivineFavor = GetSpellInfo(20216);
local tSealOfLight = GetSpellInfo(20167);
local tAvengingWrath = GetSpellInfo(31884);
local tDivinePlea = GetSpellInfo(54428);
 
HealingSpells =
{
[tHolyLight] =
{
Level = {1, 6, 14, 22, 30, 38, 46, 54, 60, 62, 70, 75, 80},
Type = "Direct",
},
[tFlashOfLight] =
{
Level = {20, 26, 34, 42, 50, 58, 66, 74, 79},
Type = "Direct",
},
}
 
local libramsFlashOfLight =
{
[42614] = 267, -- Deadly Gladiator's Libram of Justice
[42613] = 236, -- Hateful Gladiator's Libram of Justice
[42612] = 204, -- Savage Gladiator's Libram of Justice
[28592] = 89, -- Libram of Souls Redeemed (TODO: may be changed to affect Holy Light in 3.0.3)
[25644] = 79, -- Blessed Book of Nagrand
[23006] = 43, -- Libram of Light
[23201] = 28, -- Libram of Divinity
}
 
local libramsHolyLight =
{
[40268] = 141, -- Libram of Tolerance
[28296] = 47, -- Libram of the Lightbringer
}
 
GetHealSize = function(name, rank, target)
local i, effectiveHeal;
 
-- Get static spell info
local baseHealSize = getBaseHealSize(name)[rank];
local nBonus = 0;
local effectiveHealModifier = 1.0;
 
if (not baseHealSize) then
return nil;
end
 
-- Get +healing bonus
local bonus = GetSpellBonusHealing();
 
local spellTab = HealingSpells[name];
 
-- Divine Favor (100% crit chance on heal spell)
if (detectBuff('player', tDivineFavor)) then
effectiveHealModifier = effectiveHealModifier * 1.5;
end
 
-- Avenging Wrath (increase all healing by 20%)
if (detectBuff('player', tAvengingWrath)) then
effectiveHealModifier = effectiveHealModifier * 1.2;
end
 
-- Divine Plea (decrease all healing by 50%)
if (detectBuff('player', tDivinePlea)) then
effectiveHealModifier = effectiveHealModifier * 0.5;
end
 
-- Glyph of Seal of Light (increases healing by 5% if Seal of Light is active)
if (detectGlyph(54943) and detectBuff('player', tSealOfLight)) then
effectiveHealModifier = effectiveHealModifier * 1.05;
end
 
-- Healing Light - Increases healing by 4% per rank on all spells
effectiveHealModifier = effectiveHealModifier * (4 * select(5, GetTalentInfo(1, 3)) / 100 + 1);
 
-- Process individual spells
if (name == tFlashOfLight) then
local libramBonus = libramsFlashOfLight[getEquippedRelicID()] or 0;
nBonus = (bonus + libramBonus) * 1.88 * (1.5 / 3.5) * 1.25;
elseif (name == tHolyLight) then
local libramBonus = libramsHolyLight[getEquippedRelicID()] or 0;
nBonus = (bonus + libramBonus) * 1.88 * (2.5 / 3.5) * 1.25;
end
 
effectiveHeal = effectiveHealModifier * (baseHealSize + nBonus * getDownrankingFactor(spellTab.Level[rank], UnitLevel('player')));
return effectiveHeal;
end
 
end
 
-- Priest --
 
-- TODO: Talent: Improved Renew: increases renew by 5%-10%-15%
-- Healing_Done = (Renew_Base + (Healbonus * Downrankfactor) ) * Improved_Renew * Spiritual_Healing
if (playerClass == "PRIEST") then
 
local tLesserHeal = GetSpellInfo(2050);
local tHeal = GetSpellInfo(2054);
local tGreaterHeal = GetSpellInfo(2060);
local tFlashHeal = GetSpellInfo(2061);
local tBindingHeal = GetSpellInfo(32546);
local tPrayerOfHealing = GetSpellInfo(596);
local tPowerWordFortitude = GetSpellInfo(1243);
--local tRenew = GetSpellInfo(139);
local tGrace = GetSpellInfo(47930);
 
--[[HotSpells =
{
[tRenew] =
{
Level = {8, 14, 20, 26, 32, 38, 44, 50, 56, 60, 65, 74, 79, 80},
Duration = 15,
Ticks = 5,
Pattern = "(%d+)",
Type = "HoT",
},
}]]--
 
HealingSpells =
{
[tLesserHeal] =
{
Level = {1, 4, 10},
Type = "Direct"
},
[tHeal] =
{
Level = {16, 22, 28, 34},
Type = "Direct"
},
[tGreaterHeal] =
{
Level = {40, 46, 52, 58, 60, 63, 68, 73, 78},
Type = "Direct",
},
[tFlashHeal] =
{
Level = {20, 26, 32, 38, 44, 50, 56, 61, 67, 73, 79},
Type = "Direct",
},
[tBindingHeal] =
{
Level = {64, 72, 78},
Type = "Binding"
},
[tPrayerOfHealing] =
{
Level = {30, 40, 50, 60, 60, 68, 76},
Type = "Party",
InRange = function(unit) return IsSpellInRange(tPowerWordFortitude, unit) == 1 end
},
}
 
GetHealSize = function(name, rank, target)
local i, effectiveHeal;
 
-- Get static spell info
local baseHealSize = getBaseHealSize(name)[rank];
local nBonus = 0;
local effectiveHealModifier = 1.0;
 
if (not baseHealSize) then
return nil;
end
 
-- Get +healing bonus
local bonus = GetSpellBonusHealing();
 
local spellTab = HealingSpells[name];
 
-- Focused Power - Increases healing by 2% per rank on all spells
effectiveHealModifier = effectiveHealModifier * (2 * select(5, GetTalentInfo(1, 16)) / 100 + 1);
 
-- Spiritual Healing - Increases healing by 2% per rank on all spells
effectiveHealModifier = effectiveHealModifier * (2 * select(5, GetTalentInfo(2, 16)) / 100 + 1);
 
-- Grace (increases healing by 2% per application on target if buff was placed by the player)
if (target) then
local grace = detectBuff(target, tGrace, true);
if (grace) then
effectiveHealModifier = effectiveHealModifier * (1.0 + 0.02 * grace);
end
end
 
-- Process individual spells
if (name == tLesserHeal) then
nBonus = bonus * 1.88 * (1.0 + rank * 0.5) / 3.5;
elseif (name == tHeal) then
nBonus = bonus * 1.88 * (3.0 / 3.5);
elseif (name == tGreaterHeal) then
local empoweredHealing = 8 * select(5, GetTalentInfo(2, 20)) / 100;
nBonus = bonus * (1.88 * (3.0 / 3.5) + empoweredHealing);
elseif (name == tFlashHeal) then
local empoweredHealing = 4 * select(5, GetTalentInfo(2, 20)) / 100;
nBonus = bonus * (1.88 * (1.5 / 3.5) + empoweredHealing);
elseif (name == tBindingHeal) then
local empoweredHealing = 4 * select(5, GetTalentInfo(2, 20)) / 100;
nBonus = bonus * (1.88 * (1.5 / 3.5) + empoweredHealing);
elseif (name == tPrayerOfHealing) then
nBonus = bonus * 1.88 * (3.0 / 3.5) * 0.5;
end
 
effectiveHeal = effectiveHealModifier * (baseHealSize + nBonus * getDownrankingFactor(spellTab.Level[rank], UnitLevel('player')));
return effectiveHeal;
end
 
end
 
-- Shaman --
-- TODO: Nature's Blessing (GetTalentInfo(3, 21)) is probably not accounted for automatically anymore (or is it?)
-- TODO: Riptide 51point resto spell (instant cast regrowth (direct + hot))
-- TODO: Glyph of Healing Wave (binding heal, but self-heal is percentage of actual target healed)
if (playerClass == "SHAMAN") then
 
local tLesserHealingWave = GetSpellInfo(8004);
local tHealingWave = GetSpellInfo(331);
local tChainHeal = GetSpellInfo(1064);
local tHealingWay = GetSpellInfo(29206);
local tTidalWaves = GetSpellInfo(51562);
local tRiptide = GetSpellInfo(61295);
local tEarthShield = GetSpellInfo(974);
 
--[[HotSpells =
{
[tRiptide] =
{
Level = {60, 70, 75, 80},
Duration = 15,
Ticks = 5,
Pattern = "(%d+)",
Type = "HoT",
},
}]]--
 
HealingSpells =
{
[tLesserHealingWave] =
{
Level = {20, 28, 36, 44, 52, 60, 66, 72, 77},
Type = "Direct",
},
[tHealingWave] =
{
Level = {1, 6, 12, 18, 24, 32, 40, 48, 56, 60, 63, 70, 75, 80},
Type = "Direct",
},
[tChainHeal] =
{
Level = {40, 46, 54, 61, 68, 74, 80},
Type = "Direct",
},
}
 
local totemsLesserHealingWave =
{
[42597] = 267, -- Deadly Gladiator's Totem of the Third Wind
[42596] = 236, -- Hateful Gladiator's Totem of the Third Wind
[42595] = 204, -- Savage Gladiator's Totem of the Third Wind
[25645] = 79, -- Totem of The Plains
[22396] = 80, -- Totem of Life
[23200] = 53, -- Totem of Sustaining
}
 
local totemsHealingWave =
{
[27544] = 88, -- Totem of Spontaneous Regrowth
}
 
local totemsChainHeal =
{
[38368] = 102, -- Totem of the Bay
[28523] = 87, -- Totem of Healing Rains
}
 
GetHealSize = function(name, rank, target)
local i, effectiveHeal;
 
-- Get static spell info
local baseHealSize = getBaseHealSize(name)[rank];
local nBonus = 0;
local effectiveHealModifier = 1.0;
 
if (not baseHealSize) then
return nil;
end
 
-- Get +healing bonus
local bonus = GetSpellBonusHealing();
 
-- Purification Talent (increases healing by 2% per rank).
-- This is factored into effectiveHealModifier in the individual spell section below due to interaction with Improved Chain Heal.
local talentPurification = 2 * select(5, GetTalentInfo(3, 15)) / 100 + 1;
 
local spellTab = HealingSpells[name];
 
-- Process individual spells
if (name == tLesserHealingWave) then
local totemBonus = totemsLesserHealingWave[getEquippedRelicID()] or 0;
effectiveHealModifier = effectiveHealModifier * talentPurification;
 
-- Glyph of Lesser Healing Wave (increases effective healing by 20% if player's Earth Shield is on target)
if (detectGlyph(55438) and detectBuff(target, tEarthShield, true)) then
effectiveHealModifier = effectiveHealModifier * 1.2;
end
 
-- Tidal Waves Talent (increases bonus healing effects by 2% per rank)
local talentTidalWaves = 2 * select(5, GetTalentInfo(3, 25)) / 100;
 
nBonus = (bonus + totemBonus) * (1.88 * (1.5 / 3.5) + talentTidalWaves);
elseif (name == tHealingWave) then
local totemBonus = totemsHealingWave[getEquippedRelicID()] or 0;
effectiveHealModifier = effectiveHealModifier * talentPurification;
 
-- Healing Way Buff (target buff that increases effective healing by 18%)
if (detectBuff(target, tHealingWay)) then
effectiveHealModifier = effectiveHealModifier * 1.18;
end;
 
-- Tidal Waves Talent (increases bonus healing effects by 4% per rank)
local talentTidalWaves = 4 * select(5, GetTalentInfo(3, 25)) / 100;
 
-- Determine normalisation
if (rank < 4) then
nBonus = (bonus + totemBonus) * (1.88 * (1.0 + rank * 0.5) / 3.5 + talentTidalWaves);
else
nBonus = (bonus + totemBonus) * (1.88 * (3.0 / 3.5) + talentTidalWaves);
end
elseif (name == tChainHeal) then
local totemBonus = totemsChainHeal[getEquippedRelicID()] or 0;
baseHealSize = baseHealSize + totemBonus;
 
-- Improved Chain Heal Talent (increases healing by 10% per rank)
local talentImprovedChainHeal = 10 * select(5, GetTalentInfo(3, 20)) / 100;
 
effectiveHealModifier = effectiveHealModifier * (talentPurification + talentImprovedChainHeal);
 
-- Riptide Buff (target buff that increases effective healing by 25%)
if (detectBuff(target, tRiptide, true)) then
effectiveHealModifier = effectiveHealModifier * 1.25;
end
 
nBonus = bonus * 1.88 * (2.5 / 3.5);
end
 
effectiveHeal = effectiveHealModifier * (baseHealSize + nBonus * getDownrankingFactor(spellTab.Level[rank], UnitLevel('player')));
return effectiveHeal;
end
 
end
 
 
--------------------
-- Event Handlers --
--------------------
 
function lib:PLAYER_FOCUS_CHANGED()
if (UnitExists('focus')) then
self:UNIT_AURA('focus');
end
if (UnitExists('focustarget')) then
self:UNIT_AURA('focustarget');
end
end
 
function lib:PLAYER_TARGET_CHANGED()
if (UnitExists('target')) then
self:UNIT_AURA('target');
end
if (UnitExists('targettarget')) then
self:UNIT_AURA('targettarget');
end
end
 
function lib:UNIT_TARGET(unit)
if ((unit == 'target') or (unit == 'focus')) then
local unitTarget = unit .. "target";
if (UnitExists(unitTarget)) then
self:UNIT_AURA(unitTarget);
end
end
end
 
function lib:UNIT_AURA(unit)
local targetName = unitFullName(unit);
 
local oldModifier = HealModifier[targetName];
local newModifier = calculateHealModifier(unit);
if (oldModifier) then
if (newModifier == oldModifier) then
return
end
else
if (newModifier == 1.0) then
return
end
end
HealModifier[targetName] = newModifier;
 
self.Callbacks:Fire("HealComm_HealModifierUpdate", unit, targetName, newModifier);
end
 
function lib:LEARNED_SPELL_IN_TAB()
-- Invalidate cached spell data when learning new spells
SpellCache = {};
end
 
function lib:GLYPH_ADDED()
-- Invalidate cached glyph data when updating glyphs
GlyphCache = {};
end
 
function lib:GLYPH_REMOVED()
-- Invalidate cached glyph data when updating glyphs
GlyphCache = {};
end
 
function lib:GLYPH_UPDATED()
-- Invalidate cached glyph data when updating glyphs
GlyphCache = {};
end
 
function lib:UNIT_SPELLCAST_SENT(unit, spellName, spellRank, targetName)
if (unit ~= 'player') then return end
 
-- Latency measurement
SentTime = GetTime();
 
SentTargetName = targetName;
end
 
function lib:UNIT_SPELLCAST_START(unit, spellName, spellRank)
if (unit ~= 'player') then return end
 
-- Latency measurement
local currentLatency = GetTime() - SentTime;
if (currentLatency > 1) then -- Limit to 1 sec
currentLatency = 1;
end
Latency = 0.5 * Latency + 0.70 * currentLatency;
 
local spellInfo = HealingSpells[spellName];
 
-- Only process healing spells
if (spellInfo) then
if (spellInfo.Type == "Direct") then
CastInfoHealingTargetNames = SentTargetName;
CastInfoHealingSize = GetHealSize(spellName, tonumber(spellRank:match("(%d+)")), SentTargetName) or 0;
CastInfoIsCasting = true;
CastInfoEndTime = (select(6, UnitCastingInfo('player')) or 0) / 1000;
self.Callbacks:Fire("HealComm_DirectHealStart", playerName, CastInfoHealingSize, CastInfoEndTime, SentTargetName);
commSend(string.format("000%05d%s", math.min(CastInfoHealingSize, 99999), SentTargetName));
elseif (spellInfo.Type == "Binding") then
CastInfoHealingTargetNames = {playerName, SentTargetName};
CastInfoHealingSize = GetHealSize(spellName, tonumber(spellRank:match("(%d+)")), SentTargetName) or 0;
CastInfoIsCasting = true;
CastInfoEndTime = (select(6, UnitCastingInfo('player')) or 0) / 1000;
self.Callbacks:Fire("HealComm_DirectHealStart", playerName, CastInfoHealingSize, CastInfoEndTime, unpack(CastInfoHealingTargetNames));
commSend(string.format("002%05d%s", math.min(CastInfoHealingSize, 99999), SentTargetName));
elseif (spellInfo.Type == "Party") then
CastInfoHealingTargetNames = {};
if (spellInfo.InRange('party1')) then tinsert(CastInfoHealingTargetNames, unitFullName('party1')) end
if (spellInfo.InRange('party2')) then tinsert(CastInfoHealingTargetNames, unitFullName('party2')) end
if (spellInfo.InRange('party3')) then tinsert(CastInfoHealingTargetNames, unitFullName('party3')) end
if (spellInfo.InRange('party4')) then tinsert(CastInfoHealingTargetNames, unitFullName('party4')) end
CastInfoHealingSize = GetHealSize(spellName, tonumber(spellRank:match("(%d+)"))) or 0;
CastInfoIsCasting = true;
CastInfoEndTime = (select(6, UnitCastingInfo('player')) or 0) / 1000;
commSend(string.format("002%05d%s", math.min(CastInfoHealingSize, 99999), tconcat(CastInfoHealingTargetNames, ":")));
tinsert(CastInfoHealingTargetNames, 1, playerName);
self.Callbacks:Fire("HealComm_DirectHealStart", playerName, CastInfoHealingSize, CastInfoEndTime, unpack(CastInfoHealingTargetNames));
end
end
end
 
function lib:CHAT_MSG_ADDON(prefix, msg, distribution, sender)
if (prefix ~= "HealComm") then return end
if (sender == playerName) then return end
 
-- Workaround: Sometimes in battlegrounds the sender argument is not a
-- fully qualified name (the realm is missing), even though the sender is
-- from a different realm.
if (distribution == "BATTLEGROUND") then
sender = unitFullName(sender) or sender;
end
 
-- Get message type
local msgtype = tonumber(msg:sub(1, 3));
if (not msgtype) then return end
 
if (msgtype == 0) then -- DirectHealStart
local healSize = tonumber(msg:sub(4, 8));
local targetName = msg:sub(9, -1);
 
if (healSize and targetName) then
local endTime = select(6, UnitCastingInfo(sender));
 
if (endTime) then
if (distribution == "BATTLEGROUND") then
targetName = convertRealm(targetName, extractRealm(sender));
end
endTime = endTime / 1000;
entryUpdate(sender, targetName, healSize, endTime);
self.Callbacks:Fire("HealComm_DirectHealStart", sender, healSize, endTime, targetName);
end
end
elseif (msgtype == 1) then -- HealStop
local targetNames, healSize = entryRetrieve(sender);
entryDelete(sender);
if (type(targetNames) == "table") then
self.Callbacks:Fire("HealComm_DirectHealStop", sender, healSize, msg:sub(4, 4) == "S", unpack(targetNames));
elseif (targetNames) then
self.Callbacks:Fire("HealComm_DirectHealStop", sender, healSize, msg:sub(4, 4) == "S", targetNames);
end
elseif (msgtype == 2) then -- MultiTargetHealStart
local healSize = tonumber(msg:sub(4, 8));
local targetNames = {strsplit(":", msg:sub(9, -1))};
 
if (healSize) then
local endTime = select(6, UnitCastingInfo(sender));
 
if (endTime) then
if (distribution == "BATTLEGROUND") then
local senderRealm = extractRealm(sender);
for k, targetName in pairs(targetNames) do
targetNames[k] = convertRealm(targetName, senderRealm);
end
end
endTime = endTime / 1000;
tinsert(targetNames, 1, sender);
entryUpdate(sender, targetNames, healSize, endTime);
self.Callbacks:Fire("HealComm_DirectHealStart", sender, healSize, endTime, unpack(targetNames));
end
end
elseif (msgtype >= 998) then -- AnnounceVersion
local version = tonumber(msg:sub(4, -1));
if (version) then
Versions[sender] = version;
 
if (msgtype == 999) then -- RequestVersion
if (distribution ~= "BATTLEGROUND") then
-- Reply in whisper if possible
commSend("998" .. tostring(MINOR_VERSION), "WHISPER", sender);
else
-- Reply to inbound distribution channel
commSend("998" .. tostring(MINOR_VERSION), distribution);
end
end
end
end
end
 
function lib:UNIT_SPELLCAST_DELAYED(unit)
if (unit == 'player') then
if (CastInfoIsCasting) then
local endTime = select(6, UnitCastingInfo('player'));
if (endTime) then
CastInfoEndTime = endTime / 1000;
if (type(CastInfoHealingTargetNames) == "table") then
self.Callbacks:Fire("HealComm_DirectHealDelayed", playerName, CastInfoHealingSize, CastInfoEndTime, unpack(CastInfoHealingTargetNames));
elseif (CastInfoHealingTargetNames) then
self.Callbacks:Fire("HealComm_DirectHealDelayed", playerName, CastInfoHealingSize, CastInfoEndTime, CastInfoHealingTargetNames);
end
end
end
elseif (unit ~= 'target' and unit ~= 'focus') then
local healerName = unitFullName(unit);
local targetNames, healSize = entryRetrieve(healerName)
if (targetNames) then
local endTime = select(6, UnitCastingInfo(healerName));
if (endTime) then
endTime = endTime / 1000;
HealTime[healerName] = endTime;
if (type(targetNames) == "table") then
self.Callbacks:Fire("HealComm_DirectHealDelayed", healerName, healSize, endTime, unpack(targetNames));
elseif (targetNames) then
self.Callbacks:Fire("HealComm_DirectHealDelayed", healerName, healSize, endTime, targetNames);
end
end
end
end
end
 
function lib:UNIT_SPELLCAST_SUCCEEDED(unit, spellName, spellRank, spellCastIndex)
if (unit ~= 'player') then return end
 
if (CastInfoIsCasting) then
CastInfoIsCasting = false;
commSend("001S");
 
if (type(CastInfoHealingTargetNames) == "table") then
self.Callbacks:Fire("HealComm_DirectHealStop", playerName, CastInfoHealingSize, true, unpack(CastInfoHealingTargetNames));
elseif (CastInfoHealingTargetNames) then
self.Callbacks:Fire("HealComm_DirectHealStop", playerName, CastInfoHealingSize, true, CastInfoHealingTargetNames);
end
else
if (LastSpellCastIndex ~= spellCastIndex) then
-- Instant Cast Spells
end
end
end
 
function lib:UNIT_SPELLCAST_STOP(unit, spellName, spellRank, spellCastIndex)
if (unit == 'player' and CastInfoIsCasting) then
LastSpellCastIndex = spellCastIndex;
CastInfoIsCasting = false;
commSend("001F");
if (type(CastInfoHealingTargetNames) == "table") then
self.Callbacks:Fire("HealComm_DirectHealStop", playerName, CastInfoHealingSize, false, unpack(CastInfoHealingTargetNames));
elseif (CastInfoHealingTargetNames) then
self.Callbacks:Fire("HealComm_DirectHealStop", playerName, CastInfoHealingSize, false, CastInfoHealingTargetNames);
end
end
end
 
function lib:PLAYER_ALIVE()
-- This event is only fired at initial login, not at reloadui or load-on-demand loading.
-- The initialisation is triggered again, since none of the initialisation had any effect
-- prior to this event firing (no messages sent and InBattlegroundOrArena and InRaidOrParty
-- are probably not correctly initialised).
lib:Initialise();
 
-- Only receive once
self.EventFrame:UnregisterEvent("PLAYER_ALIVE");
end
 
function lib:PLAYER_ENTERING_WORLD()
HealTime = {};
HealTarget = {};
HealSize = {};
HealModifier = {};
end
 
function lib:PARTY_MEMBERS_CHANGED()
local wasInRaidOrParty = InRaidOrParty;
InRaidOrParty = (GetNumRaidMembers() > 0) or (GetNumPartyMembers() > 0);
 
-- Announce and request version when joining a group
if (not wasInRaidOrParty and InRaidOrParty) then
commSend("999" .. tostring(MINOR_VERSION));
end
end
 
function lib:RAID_ROSTER_UPDATE()
self:PARTY_MEMBERS_CHANGED();
end
 
function lib:Initialise()
local it = select(2, IsInInstance());
InBattlegroundOrArena = (it == "pvp") or (it == "arena");
 
InRaidOrParty = (GetNumRaidMembers() > 0) or (GetNumPartyMembers() > 0);
 
-- Announce and request version in group and in guild
commSend("999" .. tostring(MINOR_VERSION));
if (IsInGuild()) then
commSend("999" .. tostring(MINOR_VERSION), "GUILD");
end
end
 
lib:Initialise();
trunk/oUF_Smee2/oUF/ouf.lua New file
0,0 → 1,482
local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')
 
local _VERSION = GetAddOnMetadata(parent, 'version')
 
local function argcheck(value, num, ...)
assert(type(num) == 'number', "Bad argument #2 to 'argcheck' (number expected, got "..type(num)..")")
 
for i=1,select("#", ...) do
if type(value) == select(i, ...) then return end
end
 
local types = strjoin(", ", ...)
local name = string.match(debugstack(2,2,0), ": in function [`<](.-)['>]")
error(("Bad argument #%d to '%s' (%s expected, got %s"):format(num, name, types, type(value)), 3)
end
 
local print = function(a) ChatFrame1:AddMessage("|cff33ff99oUF:|r "..tostring(a)) end
local error = function(...) print("|cffff0000Error:|r "..string.format(...)) end
local dummy = function() end
 
 
local function SetManyAttributes(self, ...)
for i=1,select("#", ...),2 do
local att,val = select(i, ...)
if not att then return end
self:SetAttribute(att,val)
end
end
 
-- Colors
local colors = {
health = {49/255, 207/255, 37/255}, -- Health
happiness = {
[1] = {1, 0, 0}, -- need.... | unhappy
[2] = {1, 1, 0}, -- new..... | content
[3] = {0, 1, 0}, -- colors.. | happy
},
smooth = {
1, 0, 0,
1, 1, 0,
0, 1, 0
},
disconnected = {.6, .6, .6},
tapped = {.6,.6,.6},
class = {},
reaction = {},
power = {},
}
 
-- We do this because people edit the vars directly, and changing the default
-- globals makes SPICE FLOW!
for eclass, color in next, RAID_CLASS_COLORS do
colors.class[eclass] = {color.r, color.g, color.b}
end
 
for power, color in next, PowerBarColor do
if(type(power) == 'string') then
colors.power[power] = {color.r, color.g, color.b}
end
end
 
for eclass, color in next, FACTION_BAR_COLORS do
colors.reaction[eclass] = {color.r, color.g, color.b}
end
 
-- add-on object
local oUF = CreateFrame"Button"
local frame_metatable = {__index = oUF}
local event_metatable = {
__call = function(funcs, self, ...)
for _, func in ipairs(funcs) do
func(self, ...)
end
end,
}
 
local styles, style = {}
local callback, units, objects = {}, {}, {}
 
local _G, select, type, tostring, math_modf =
_G, select, type, tostring, math.modf
local UnitExists, UnitName =
UnitExists, UnitName
 
local conv = {
['playerpet'] = 'pet',
['playertarget'] = 'target',
}
local elements = {}
 
local enableTargetUpdate = function(object)
-- updating of "invalid" units.
local OnTargetUpdate
do
local timer = 0
OnTargetUpdate = function(self, elapsed)
if(not self.unit) then
return
elseif(timer >= .5) then
self:PLAYER_ENTERING_WORLD'OnTargetUpdate'
timer = 0
end
 
timer = timer + elapsed
end
end
 
object:SetScript("OnUpdate", OnTargetUpdate)
end
 
-- Events
local OnEvent = function(self, event, ...)
if(not self:IsShown() and not self.vehicleUnit) then return end
self[event](self, event, ...)
end
 
local OnAttributeChanged = function(self, name, value)
if(name == "unit" and value) then
units[value] = self
 
if(self.unit and self.unit == value) then
return
else
if(self.hasChildren) then
for _, object in next, objects do
local unit = SecureButton_GetModifiedUnit(object)
object.unit = conv[unit] or unit
object:PLAYER_ENTERING_WORLD()
end
end
 
self.unit = value
self.id = value:match"^.-(%d+)"
self:PLAYER_ENTERING_WORLD()
end
end
end
 
-- Gigantic function of doom
local HandleUnit = function(unit, object)
if(unit == "player") then
-- Hide the blizzard stuff
PlayerFrame:UnregisterAllEvents()
PlayerFrame.Show = dummy
PlayerFrame:Hide()
 
PlayerFrameHealthBar:UnregisterAllEvents()
PlayerFrameManaBar:UnregisterAllEvents()
elseif(unit == "pet")then
-- Hide the blizzard stuff
PetFrame:UnregisterAllEvents()
PetFrame.Show = dummy
PetFrame:Hide()
 
PetFrameHealthBar:UnregisterAllEvents()
PetFrameManaBar:UnregisterAllEvents()
elseif(unit == "target") then
-- Hide the blizzard stuff
TargetFrame:UnregisterAllEvents()
TargetFrame.Show = dummy
TargetFrame:Hide()
 
TargetFrameHealthBar:UnregisterAllEvents()
TargetFrameManaBar:UnregisterAllEvents()
TargetFrameSpellBar:UnregisterAllEvents()
 
ComboFrame:UnregisterAllEvents()
ComboFrame.Show = dummy
ComboFrame:Hide()
 
-- Enable our shit
object:RegisterEvent("PLAYER_TARGET_CHANGED", 'PLAYER_ENTERING_WORLD')
elseif(unit == "focus") then
FocusFrame:UnregisterAllEvents()
FocusFrame.Show = dummy
FocusFrame:Hide()
 
FocusFrameHealthBar:UnregisterAllEvents()
FocusFrameManaBar:UnregisterAllEvents()
FocusFrameSpellBar:UnregisterAllEvents()
 
object:RegisterEvent("PLAYER_FOCUS_CHANGED", 'PLAYER_ENTERING_WORLD')
elseif(unit == "mouseover") then
object:RegisterEvent("UPDATE_MOUSEOVER_UNIT", 'PLAYER_ENTERING_WORLD')
elseif(unit:match"target") then
-- Hide the blizzard stuff
if(unit == "targettarget") then
TargetofTargetFrame:UnregisterAllEvents()
TargetofTargetFrame.Show = dummy
TargetofTargetFrame:Hide()
 
TargetofTargetHealthBar:UnregisterAllEvents()
TargetofTargetManaBar:UnregisterAllEvents()
end
 
enableTargetUpdate(object)
elseif(unit == "party") then
for i=1,4 do
local party = "PartyMemberFrame"..i
local frame = _G[party]
 
frame:UnregisterAllEvents()
frame.Show = dummy
frame:Hide()
 
_G[party..'HealthBar']:UnregisterAllEvents()
_G[party..'ManaBar']:UnregisterAllEvents()
end
end
end
 
local initObject = function(unit, style, ...)
local num = select('#', ...)
for i=1, num do
local object = select(i, ...)
 
object.__elements = {}
 
object = setmetatable(object, frame_metatable)
style(object, unit)
 
local mt = type(style) == 'table'
local height = object:GetAttribute'initial-height' or (mt and style['initial-height'])
local width = object:GetAttribute'initial-width' or (mt and style['initial-width'])
local scale = object:GetAttribute'initial-scale' or (mt and style['initial-scale'])
local suffix = object:GetAttribute'unitsuffix'
 
if(height) then
object:SetAttribute('initial-height', height)
if(unit) then object:SetHeight(height) end
end
 
if(width) then
object:SetAttribute("initial-width", width)
if(unit) then object:SetWidth(width) end
end
 
if(scale) then
object:SetAttribute("initial-scale", scale)
if(unit) then object:SetScale(scale) end
end
 
if(suffix == 'target') then
enableTargetUpdate(object)
end
 
if(num > 1 and i == 1) then
object.hasChildren = true
end
 
object:SetAttribute("*type1", "target")
object:SetScript("OnEvent", OnEvent)
object:SetScript("OnAttributeChanged", OnAttributeChanged)
object:SetScript("OnShow", object.PLAYER_ENTERING_WORLD)
 
object:RegisterEvent"PLAYER_ENTERING_WORLD"
 
for element in next, elements do
object:EnableElement(element, unit)
end
 
for _, func in next, callback do
func(object)
end
 
-- We could use ClickCastFrames only, but it will probably contain frames that
-- we don't care about.
table.insert(objects, object)
_G.ClickCastFrames = ClickCastFrames or {}
ClickCastFrames[object] = true
end
end
 
local walkObject = function(object, unit)
local style = object:GetParent().style or styles[style]
 
initObject(unit, style, object, object:GetChildren())
end
 
function oUF:RegisterInitCallback(func)
table.insert(callback, func)
end
 
function oUF:RegisterStyle(name, func)
argcheck(name, 2, 'string')
argcheck(func, 3, 'function', 'table')
 
if(styles[name]) then return error("Style [%s] already registered.", name) end
if(not style) then style = name end
 
styles[name] = func
end
 
function oUF:SetActiveStyle(name)
argcheck(name, 2, 'string')
if(not styles[name]) then return error("Style [%s] does not exist.", name) end
 
style = name
end
 
function oUF:Spawn(unit, name, template, disableBlizz)
argcheck(unit, 2, 'string')
if(not style) then return error("Unable to create frame. No styles have been registered.") end
 
local style = styles[style]
local object
if(unit == "header") then
if(not template) then
template = "SecureGroupHeaderTemplate"
end
 
HandleUnit(disableBlizz or 'party')
 
local header = CreateFrame("Frame", name, UIParent, template)
header:SetAttribute("template", "SecureUnitButtonTemplate")
header.initialConfigFunction = walkObject
header.style = style
header.SetManyAttributes = SetManyAttributes
 
return header
else
object = CreateFrame("Button", name, UIParent, "SecureUnitButtonTemplate")
object:SetAttribute("unit", unit)
object.unit = unit
object.id = unit:match"^.-(%d+)"
 
units[unit] = object
walkObject(object, unit)
HandleUnit(unit, object)
RegisterUnitWatch(object)
end
 
return object
end
 
local RegisterEvent = oUF.RegisterEvent
function oUF:RegisterEvent(event, func)
argcheck(event, 2, 'string')
 
if(type(func) == 'string' and type(self[func]) == 'function') then
func = self[func]
end
 
local curev = self[event]
if(curev and func) then
if(type(curev) == 'function') then
self[event] = setmetatable({curev, func}, event_metatable)
else
for _, infunc in ipairs(curev) do
if(infunc == func) then return end
end
 
table.insert(curev, func)
end
elseif(self:IsEventRegistered(event)) then
return
else
if(func) then
self[event] = func
elseif(not self[event]) then
return error("Handler for event [%s] on unit [%s] does not exist.", event, self.unit or 'unknown')
end
 
RegisterEvent(self, event)
end
end
 
local UnregisterEvent = oUF.UnregisterEvent
function oUF:UnregisterEvent(event, func)
argcheck(event, 2, 'string')
 
local curev = self[event]
if(type(curev) == 'table' and func) then
for k, infunc in ipairs(curev) do
if(infunc == func) then
curev[k] = nil
 
if(#curev == 0) then
table.remove(curev, k)
UnregisterEvent(self, event)
end
end
end
else
self[event] = nil
UnregisterEvent(self, event)
end
end
 
function oUF:AddElement(name, update, enable, disable)
argcheck(name, 2, 'string')
argcheck(update, 3, 'function', 'nil')
argcheck(enable, 4, 'function', 'nil')
argcheck(disable, 5, 'function', 'nil')
 
if(elements[name]) then return error('Element [%s] is already registered.', name) end
elements[name] = {
update = update;
enable = enable;
disable = disable;
}
end
 
function oUF:EnableElement(name, unit)
argcheck(name, 2, 'string')
argcheck(unit, 3, 'string', 'nil')
 
local element = elements[name]
if(not element) then return end
 
if(element.enable(self, unit or self.unit)) then
table.insert(self.__elements, element.update)
end
end
 
function oUF:DisableElement(name)
argcheck(name, 2, 'string')
local element = elements[name]
if(not element) then return end
 
for k, update in ipairs(self.__elements) do
if(update == element.update) then
table.remove(self.__elements, k)
element.disable(self)
break
end
end
end
 
function oUF:UpdateElement(name)
argcheck(name, 2, 'string')
local element = elements[name]
if(not element) then return end
 
element.update(self, 'UpdateElement', self.unit)
end
 
oUF.Enable = RegisterUnitWatch
function oUF:Disable()
UnregisterUnitWatch(self)
self:Hide()
end
 
--[[
--:PLAYER_ENTERING_WORLD()
-- Notes:
-- - Does a full update of all elements on the object.
--]]
function oUF:PLAYER_ENTERING_WORLD(event)
local unit = self.unit
if(not UnitExists(unit)) then return end
 
for _, func in next, self.__elements do
func(self, event, unit)
end
end
 
-- http://www.wowwiki.com/ColorGradient
function oUF.ColorGradient(perc, ...)
if perc >= 1 then
local r, g, b = select(select('#', ...) - 2, ...)
return r, g, b
elseif perc <= 0 then
local r, g, b = ...
return r, g, b
end
 
local num = select('#', ...) / 3
 
local segment, relperc = math.modf(perc*(num-1))
local r1, g1, b1, r2, g2, b2 = select((segment*3)+1, ...)
 
return r1 + (r2-r1)*relperc, g1 + (g2-g1)*relperc, b1 + (b2-b1)*relperc
end
 
oUF.version = _VERSION
oUF.units = units
oUF.objects = objects
oUF.colors = colors
_G[global] = oUF
trunk/oUF_Smee2/oUF/elements/happiness.lua New file
0,0 → 1,50
local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')
local oUF = _G[global]
 
local Update = function(self, event, unit)
if(self.unit ~= unit) then return end
 
if(self.Happiness) then
local happiness = GetPetHappiness()
local hunterPet = select(2, HasPetUI())
 
if(not (happiness or hunterPet)) then
return self.Happiness:Hide()
end
 
self.Happiness:Show()
if(happiness == 1) then
self.Happiness:SetTexCoord(0.375, 0.5625, 0, 0.359375)
elseif(happiness == 2) then
self.Happiness:SetTexCoord(0.1875, 0.375, 0, 0.359375)
elseif(happiness == 3) then
self.Happiness:SetTexCoord(0, 0.1875, 0, 0.359375)
end
 
if(self.PostUpdateHappiness) then self:PostUpdateHappiness(event, unit, happiness) end
end
end
 
local Enable = function(self)
local happiness = self.Happiness
if(happiness) then
self:RegisterEvent("UNIT_HAPPINESS", Update)
 
if(happiness:IsObjectType"Texture" and not happiness:GetTexture()) then
happiness:SetTexture[[Interface\PetPaperDollFrame\UI-PetHappiness]]
end
 
return true
end
end
 
local Disable = function(self)
local happiness = self.Happiness
if(happiness) then
self:UnregisterEvent("UNIT_HAPPINESS", Update)
end
end
 
oUF:AddElement('Happiness', Update, Enable, Disable)
trunk/oUF_Smee2/oUF/elements/leader.lua New file
0,0 → 1,37
local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')
local oUF = _G[global]
 
local Update = function(self, event)
local unit = self.unit
if((UnitInParty(unit) or UnitInRaid(unit)) and UnitIsPartyLeader(unit)) then
self.Leader:Show()
else
self.Leader:Hide()
end
end
 
local Enable = function(self)
local leader = self.Leader
if(leader) then
self:RegisterEvent("PARTY_LEADER_CHANGED", Update)
self:RegisterEvent("PARTY_MEMBERS_CHANGED", Update)
 
if(leader:IsObjectType"Texture" and not leader:GetTexture()) then
leader:SetTexture[[Interface\GroupFrame\UI-Group-LeaderIcon]]
end
 
return true
end
end
 
local Disable = function(self)
local leader = self.Leader
if(leader) then
self:UnregisterEvent("PARTY_LEADER_CHANGED", Update)
self:UnregisterEvent("PARTY_MEMBERS_CHANGED", Update)
end
end
 
oUF:AddElement('Leader', Update, Enable, Disable)
trunk/oUF_Smee2/oUF/elements/power.lua New file
0,0 → 1,162
--[[
Elements handled: .Power
 
Shared:
The following settings are listed by priority:
- colorTapping
- colorDisconnected
- colorHappiness
- colorPower
- colorClass (Colors player units based on class)
- colorClassPet (Colors pet units based on class)
- colorClassNPC (Colors non-player units based on class)
- colorReaction
- colorSmooth - will use smoothGradient instead of the internal gradient if set.
 
Background:
- multiplier - number used to manipulate the power background. (default: 1)
This option will only enable for player and pet.
- frequentUpdates - do OnUpdate polling of power data.
 
Functions that can be overridden from within a layout:
- :PreUpdatePower(event, unit)
- :OverrideUpdatePower(event, unit, bar, min, max) - Setting this function
will disable the above color settings.
- :PostUpdatePower(event, unit, bar, min, max)
--]]
local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')
local oUF = _G[global]
 
local UnitManaMax = UnitManaMax
local UnitPowerType = UnitPowerType
local min, max, bar
 
local OnPowerUpdate
do
local UnitMana = UnitMana
OnPowerUpdate = function(self)
if(self.disconnected) then return end
local power = UnitMana(self.unit)
 
if(power ~= self.min) then
self.min = power
 
self:GetParent():UNIT_MAXMANA("OnPowerUpdate", self.unit)
end
end
end
 
local Update = function(self, event, unit)
if(self.unit ~= unit) then return end
if(self.PreUpdatePower) then self:PreUpdatePower(event, unit) end
 
min, max = UnitMana(unit), UnitManaMax(unit)
bar = self.Power
bar:SetMinMaxValues(0, max)
bar:SetValue(min)
 
bar.disconnected = not UnitIsConnected(unit)
bar.unit = unit
 
if(not self.OverrideUpdatePower) then
local r, g, b, t
if(bar.colorTapping and UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit)) then
t = self.colors.tapped
elseif(bar.colorDisconnected and not UnitIsConnected(unit)) then
t = self.colors.disconnected
elseif(bar.colorHappiness and unit == "pet" and GetPetHappiness()) then
t = self.colors.happiness[GetPetHappiness()]
elseif(bar.colorPower) then
local _, ptype = UnitPowerType(unit)
 
t = self.colors.power[ptype]
elseif(bar.colorClass and UnitIsPlayer(unit)) or
(bar.colorClassNPC and not UnitIsPlayer(unit)) or
(bar.colorClassPet and UnitPlayerControlled(unit) and not UnitIsPlayer(unit)) then
local _, class = UnitClass(unit)
t = self.colors.class[class]
elseif(bar.colorReaction) then
t = self.colors.reaction[UnitReaction(unit, "player")]
elseif(bar.colorSmooth) then
r, g, b = self.ColorGradient(min / max, unpack(bar.smoothGradient or self.colors.smooth))
end
 
if(t) then
r, g, b = t[1], t[2], t[3]
end
 
if(b) then
bar:SetStatusBarColor(r, g, b)
 
local bg = bar.bg
if(bg) then
local mu = bg.multiplier or 1
bg:SetVertexColor(r * mu, g * mu, b * mu)
end
end
else
self:OverrideUpdatePower(event, unit, bar, min, max)
end
 
if(self.PostUpdatePower) then self:PostUpdatePower(event, unit, bar, min, max) end
end
 
local Enable = function(self, unit)
local power = self.Power
if(power) then
if(power.frequentUpdates and (unit == 'player' or unit == 'pet')) then
power.disconnected = true
power:SetScript("OnUpdate", OnPowerUpdate)
else
self:RegisterEvent("UNIT_MANA", Update)
self:RegisterEvent("UNIT_RAGE", Update)
self:RegisterEvent("UNIT_FOCUS", Update)
self:RegisterEvent("UNIT_ENERGY", Update)
self:RegisterEvent("UNIT_RUNIC_POWER", Update)
end
self:RegisterEvent("UNIT_MAXMANA", Update)
self:RegisterEvent("UNIT_MAXRAGE", Update)
self:RegisterEvent("UNIT_MAXFOCUS", Update)
self:RegisterEvent("UNIT_MAXENERGY", Update)
self:RegisterEvent("UNIT_DISPLAYPOWER", Update)
self:RegisterEvent("UNIT_MAXRUNIC_POWER", Update)
 
self:RegisterEvent('UNIT_HAPPINESS', Update)
-- For tapping.
self:RegisterEvent('UNIT_FACTION', Update)
 
if(not power:GetStatusBarTexture()) then
power:SetStatusBarTexture[[Interface\TargetingFrame\UI-StatusBar]]
end
 
return true
end
end
 
local Disable = function(self)
local power = self.Power
if(power) then
if(power:GetScript'OnUpdate') then
power:SetScript("OnUpdate", nil)
else
self:UnregisterEvent("UNIT_MANA", Update)
self:UnregisterEvent("UNIT_RAGE", Update)
self:UnregisterEvent("UNIT_FOCUS", Update)
self:UnregisterEvent("UNIT_ENERGY", Update)
self:UnregisterEvent("UNIT_RUNIC_POWER", Update)
end
self:UnregisterEvent("UNIT_MAXMANA", Update)
self:UnregisterEvent("UNIT_MAXRAGE", Update)
self:UnregisterEvent("UNIT_MAXFOCUS", Update)
self:UnregisterEvent("UNIT_MAXENERGY", Update)
self:UnregisterEvent("UNIT_DISPLAYPOWER", Update)
self:UnregisterEvent("UNIT_MAXRUNIC_POWER", Update)
 
self:UnregisterEvent('UNIT_HAPPINESS', Update)
self:UnregisterEvent('UNIT_FACTION', Update)
end
end
 
oUF:AddElement('Power', Update, Enable, Disable)
trunk/oUF_Smee2/oUF/elements/range.lua New file
0,0 → 1,50
--[[
Elements handled: .Range
 
Settings:
- inRangeAlpha - A number for frame alpha when unit is within player range.
Required.
- outsideRangeAlpha - A number for frame alpha when unit is outside player
range. Required.
--]]
local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')
local oUF = _G[global]
 
local objects = oUF.objects
local OnRangeFrame
 
local UnitInRange, UnitIsConnected =
UnitInRange, UnitIsConnected
 
-- updating of range.
local timer = 0
local OnRangeUpdate = function(self, elapsed)
timer = timer + elapsed
 
if(timer >= .25) then
for _, object in ipairs(objects) do
if(object:IsShown() and object.Range) then
if(UnitIsConnected(object.unit) and not UnitInRange(object.unit)) then
if(object:GetAlpha() == object.inRangeAlpha) then
object:SetAlpha(object.outsideRangeAlpha)
end
elseif(object:GetAlpha() ~= object.inRangeAlpha) then
object:SetAlpha(object.inRangeAlpha)
end
end
end
 
timer = 0
end
end
 
local Enable = function(self)
if(self.Range and not OnRangeFrame) then
OnRangeFrame = CreateFrame"Frame"
OnRangeFrame:SetScript("OnUpdate", OnRangeUpdate)
end
end
 
oUF:AddElement('Range', nil, Enable)
trunk/oUF_Smee2/oUF/elements/ricons.lua New file
0,0 → 1,41
local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')
local oUF = _G[global]
 
local GetRaidTargetIndex = GetRaidTargetIndex
local SetRaidTargetIconTexture = SetRaidTargetIconTexture
 
local Update = function(self, event)
local index = GetRaidTargetIndex(self.unit)
local icon = self.RaidIcon
 
if(index) then
SetRaidTargetIconTexture(icon, index)
icon:Show()
else
icon:Hide()
end
end
 
local Enable = function(self)
local ricon = self.RaidIcon
if(ricon) then
self:RegisterEvent("RAID_TARGET_UPDATE", Update)
 
if(ricon:IsObjectType"Texture" and not ricon:GetTexture()) then
ricon:SetTexture[[Interface\TargetingFrame\UI-RaidTargetingIcons]]
end
 
return true
end
end
 
local Disable = function(self)
local ricon = self.RaidIcon
if(ricon) then
self:UnregisterEvent("RAID_TARGET_UPDATE", Update)
end
end
 
oUF:AddElement('RaidIcon', Update, Enable, Disable)
trunk/oUF_Smee2/oUF/elements/tags.lua New file
0,0 → 1,330
--[[
-- Experimental oUF tags
-- Status: Incomplete
--
-- Credits: Vika, Cladhaire, Tekkub
--
-- TODO:
-- - Tag and Untag should be able to handle more than one fontstring at a time.
]]
 
local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')
local oUF = _G[global]
 
local function Hex(r, g, b)
if type(r) == "table" then
if r.r then r, g, b = r.r, r.g, r.b else r, g, b = unpack(r) end
end
return string.format("|cff%02x%02x%02x", r*255, g*255, b*255)
end
 
local tags
tags = {
["[class]"] = function(u) return UnitClass(u) end,
["[creature]"] = function(u) return UnitCreatureFamily(u) or UnitCreatureType(u) end,
["[curhp]"] = UnitHealth,
["[curpp]"] = UnitPower,
["[dead]"] = function(u) return UnitIsDead(u) and "Dead" or UnitIsGhost(u) and "Ghost" end,
["[difficulty]"] = function(u) if UnitCanAttack("player", u) then local l = UnitLevel(u); return Hex(GetDifficultyColor((l > 0) and l or 99)) end end,
["[faction]"] = function(u) return UnitFactionGroup(u) end,
["[leader]"] = function(u) return UnitIsPartyLeader(u) and "(L)" end,
["[leaderlong]"] = function(u) return UnitIsPartyLeader(u) and "(Leader)" end,
["[level]"] = function(u) local l = UnitLevel(u) return (l > 0) and l or "??" end,
["[maxhp]"] = UnitHealthMax,
["[maxpp]"] = UnitPowerMax,
["[missinghp]"] = function(u) return UnitHealthMax(u) - UnitHealth(u) end,
["[missingpp]"] = function(u) return UnitPowerMax(u) - UnitPower(u) end,
["[name]"] = function(u, r) return UnitName(r or u) end,
["[offline]"] = function(u) return (not UnitIsConnected(u) and "Offline") end,
["[perhp]"] = function(u) local m = UnitHealthMax(u); return m == 0 and 0 or math.floor(UnitHealth(u)/m*100+0.5) end,
["[perpp]"] = function(u) local m = UnitPowerMax(u); return m == 0 and 0 or math.floor(UnitPower(u)/m*100+0.5) end,
["[plus]"] = function(u) local c = UnitClassification(u); return (c == "elite" or c == "rareelite") and "+" end,
["[pvp]"] = function(u) return UnitIsPVP(u) and "PvP" end,
["[race]"] = function(u) return UnitRace(u) end,
["[raidcolor]"] = function(u) local _, x = UnitClass(u); return x and Hex(RAID_CLASS_COLORS[x]) end,
["[rare]"] = function(u) local c = UnitClassification(u); return (c == "rare" or c == "rareelite") and "Rare" end,
["[resting]"] = function(u) return u == "player" and IsResting() and "zzz" end,
["[sex]"] = function(u) local s = UnitSex(u) return s == 2 and "Male" or s == 3 and "Female" end,
["[smartclass]"] = function(u) return UnitIsPlayer(u) and tags["[class]"](u) or tags["[creature]"](u) end,
["[status]"] = function(u) return UnitIsDead(u) and "Dead" or UnitIsGhost(u) and "Ghost" or not UnitIsConnected(u) and "Offline" or tags["[resting]"](u) end,
["[threat]"] = function(u) local s = UnitThreatSituation(u) return s == 1 and "++" or s == 2 and "--" or s == 3 and "Aggro" end,
["[threatcolor]"] = function(u) return Hex(GetThreatStatusColor(UnitThreatSituation(u))) end,
["[cpoints]"] = function(u) local cp = GetComboPoints(u, 'target') return (cp > 0) and cp end,
 
['[smartlevel]'] = function(u)
local c = UnitClassification(u)
if(c == 'worldboss') then
return 'Boss'
else
local plus = tags['[plus]'](u)
local level = tags['[level]'](u)
if(plus) then
return level .. plus
else
return level
end
end
end,
 
["[classification]"] = function(u)
local c = UnitClassification(u)
return c == "rare" and "Rare" or c == "eliterare" and "Rare Elite" or c == "elite" and "Elite" or c == "worldboss" and "Boss"
end,
 
["[shortclassification]"] = function(u)
local c = UnitClassification(u)
return c == "rare" and "R" or c == "eliterare" and "R+" or c == "elite" and "+" or c == "worldboss" and "B"
end,
}
local tagEvents = {
["[curhp]"] = "UNIT_HEALTH",
["[curpp]"] = "UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_RUNIC_POWER",
["[dead]"] = "UNIT_HEALTH",
["[leader]"] = "PARTY_LEADER_CHANGED",
["[leaderlong]"] = "PARTY_LEADER_CHANGED",
["[level]"] = "UNIT_LEVEL PLAYER_LEVEL_UP",
["[maxhp]"] = "UNIT_MAXHEALTH",
["[maxpp]"] = "UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_MAXRUNIC_POWER",
["[missinghp]"] = "UNIT_HEALTH UNIT_MAXHEALTH",
["[missingpp]"] = "UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_MAXRUNIC_POWER UNIT_RUNIC_POWER",
["[name]"] = "UNIT_NAME_UPDATE",
["[offline]"] = "UNIT_HEALTH",
["[perhp]"] = "UNIT_HEALTH UNIT_MAXHEALTH",
["[perpp]"] = "UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_MAXRUNIC_POWER UNIT_RUNIC_POWER",
["[pvp]"] = "UNIT_FACTION",
["[resting]"] = "PLAYER_UPDATE_RESTING",
["[status]"] = "UNIT_HEALTH PLAYER_UPDATE_RESTING",
["[smartlevel]"] = "UNIT_LEVEL PLAYER_LEVEL_UP UNIT_CLASSIFICATION_CHANGED",
["[threat]"] = "UNIT_THREAT_SITUATION_UPDATE",
["[threatcolor]"] = "UNIT_THREAT_SITUATION_UPDATE",
['[cpoints]'] = 'UNIT_COMBO_POINTS UNIT_TARGET',
['[rare]'] = 'UNIT_CLASSIFICATION_CHANGED',
['[classification]'] = 'UNIT_CLASSIFICATION_CHANGED',
['[shortclassification]'] = 'UNIT_CLASSIFICATION_CHANGED',
}
 
local unitlessEvents = {
PLAYER_TARGET_CHANGED = true,
PLAYER_FOCUS_CHANGED = true,
PLAYER_LEVEL_UP = true,
}
 
local events = {}
local frame = CreateFrame"Frame"
frame:SetScript('OnEvent', function(self, event, unit)
local strings = events[event]
if(strings) then
for k, fontstring in next, strings do
if(not unitlessEvents[event] and fontstring.parent.unit == unit and fontstring:IsVisible()) then
fontstring:UpdateTag()
end
end
end
end)
 
local eventlessUnits = {}
local timer = .5
local lowestTimer = .5
local OnUpdate = function(self, elapsed)
if(timer >= lowestTimer) then
for k, fs in next, eventlessUnits do
if(fs.parent:IsShown() and UnitExists(fs.parent.unit)) then
fs:UpdateTag()
end
end
 
timer = 0
end
 
timer = timer + elapsed
end
 
local OnShow = function(self)
for _, fs in next, self.__tags do
fs:UpdateTag()
end
end
 
local RegisterEvent = function(fontstr, event)
if(not events[event]) then events[event] = {} end
 
frame:RegisterEvent(event)
table.insert(events[event], fontstr)
end
 
local RegisterEvents = function(fontstr, tagstr)
-- Forcefully strip away any parentheses and the characters in them.
tagstr = tagstr:gsub('%b()', '')
for tag in tagstr:gmatch'[%[]%w+[%]]' do
local tagevents = tagEvents[tag]
if(tagevents) then
for event in tagevents:gmatch'%S+' do
RegisterEvent(fontstr, event)
end
end
end
end
 
local UnregisterEvents = function(fontstr)
for events, data in pairs(events) do
for k, tagfsstr in pairs(data) do
if(tagfsstr == fontstr) then
if(#data[k] == 1) then frame:UnregisterEvent(event) end
data[k] = nil
end
end
end
end
 
local tagPool = {}
local funcPool = {}
local tmp = {}
 
local Tag = function(self, fs, tagstr)
if(not fs or not tagstr or self == oUF) then return end
 
if(not self.__tags) then
self.__tags = {}
table.insert(self.__elements, OnShow)
else
-- Since people ignore everything that's good practice - unregister the tag
-- if it already exists.
for _, tag in pairs(self.__tags) do
if(fs == tag) then
-- We don't need to remove it from the __tags table as Untag handles
-- that for us.
self:Untag(fs)
end
end
end
 
fs.parent = self
 
local func = tagPool[tagstr]
if(not func) then
-- Using .- in the match prevents use from supporting [] as prepend/append
-- characters. Supporting these and having a single pattern here is a real
-- headache however.
local format = tagstr:gsub('%%', '%%%%'):gsub('[[].-[]]', '%%s')
local args = {}
 
for bracket in tagstr:gmatch'([[](.-)[]])' do
local tfunc = funcPool[bracket] or tags[bracket]
if(not tfunc) then
-- ...
local pre, tag, ap = bracket:match'[%[](%b())([%w]+)(%b())[%]]'
if(not pre) then pre, tag = bracket:match'[%[](%b())([%w]+)[%]]' end
if(not pre) then tag, ap = bracket:match'[%[]([%w]+)(%b())[%]]' end
tag = (tag and '['.. tag ..']')
tag = tags[tag]
 
if(tag) then
if(pre and ap) then
pre = pre:sub(2,-2)
ap = ap:sub(2,-2)
 
tfunc = function(u)
local str = tag(u)
if(str) then
return pre..str..ap
end
end
elseif(pre) then
pre = pre:sub(2,-2)
 
tfunc = function(u)
local str = tag(u)
if(str) then
return pre..str
end
end
elseif(ap) then
ap = ap:sub(2,-2)
 
tfunc = function(u)
local str = tag(u)
if(str) then
return str..ap
end
end
end
 
funcPool[bracket] = tfunc
end
end
 
if(tfunc) then
table.insert(args,tfunc)
else
return error(('Attempted to use invalid tag %s.'):format(bracket), 3)
end
end
 
func = function(self)
local unit = self.parent.unit
local __unit = self.parent.__unit
 
for i, func in next, args do
tmp[i] = func(unit, __unit) or ''
end
 
self:SetFormattedText(format, unpack(tmp))
end
 
tagPool[tagstr] = func
end
fs.UpdateTag = func
 
local unit = self.unit
if((unit and unit:match'%w+target') or fs.frequentUpdates) then
if(type(fs.frequentUpdates) == 'number') then
lowestTimer = math.min(fs.frequentUpdates, lowestTimer)
end
 
table.insert(eventlessUnits, fs)
 
if(not frame:GetScript'OnUpdate') then
frame:SetScript('OnUpdate', OnUpdate)
end
else
RegisterEvents(fs, tagstr)
 
if(unit == 'focus') then
RegisterEvent(fs, 'PLAYER_FOCUS_CHANGED')
elseif(unit == 'target') then
RegisterEvent(fs, 'PLAYER_TARGET_CHANGED')
elseif(unit == 'mouseover') then
RegisterEvent(fs, 'UPDATE_MOUSEOVER_UNIT')
end
end
 
table.insert(self.__tags, fs)
end
 
local Untag = function(self, fs)
if(not fs or self == oUF) then return end
 
UnregisterEvents(fs)
for k, fontstr in next, eventlessUnits do
if(fs == fontstr) then
table.remove(eventlessUnits, k)
end
end
 
for k, fontstr in next, self.__tags do
if(fontstr == fs) then
table.remove(self.__tags, k)
end
end
 
fs.UpdateTag = nil
end
 
oUF.Tags = tags
oUF.TagEvents = tagEvents
oUF.UnitlessTagEvents = unitlessEvents
 
oUF.Tag = Tag
oUF.Untag = Untag
trunk/oUF_Smee2/oUF/elements/health.lua New file
0,0 → 1,138
--[[
Elements handled: .Health
 
Shared:
The following settings are listed by priority:
- colorTapping
- colorDisconnected
- colorHappiness
- colorClass (Colors player units based on class)
- colorClassPet (Colors pet units based on class)
- colorClassNPC (Colors non-player units based on class)
- colorReaction
- colorSmooth - will use smoothGradient instead of the internal gradient if set.
- colorHealth
 
Background:
- multiplier - number used to manipulate the power background. (default: 1)
 
WotLK only:
- frequentUpdates - do OnUpdate polling of health data.
 
Functions that can be overridden from within a layout:
- :PreUpdateHealth(event, unit)
- :OverrideUpdateHealth(event, unit, bar, min, max) - Setting this function
will disable the above color settings.
- :PostUpdateHealth(event, unit, bar, min, max)
--]]
local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')
local oUF = _G[global]
 
local OnHealthUpdate
do
local UnitHealth = UnitHealth
OnHealthUpdate = function(self)
if(self.disconnected) then return end
local health = UnitHealth(self.unit)
 
if(health ~= self.min) then
self.min = health
 
self:GetParent():UNIT_MAXHEALTH("OnHealthUpdate", self.unit)
end
end
end
 
local Update = function(self, event, unit)
if(self.unit ~= unit) then return end
if(self.PreUpdateHealth) then self:PreUpdateHealth(event, unit) end
 
local min, max = UnitHealth(unit), UnitHealthMax(unit)
local bar = self.Health
bar:SetMinMaxValues(0, max)
bar:SetValue(min)
 
bar.disconnected = not UnitIsConnected(unit)
bar.unit = unit
 
if(not self.OverrideUpdateHealth) then
local r, g, b, t
if(bar.colorTapping and UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit)) then
t = self.colors.tapped
elseif(bar.colorDisconnected and not UnitIsConnected(unit)) then
t = self.colors.disconnected
elseif(bar.colorHappiness and unit == "pet" and GetPetHappiness()) then
t = self.colors.happiness[GetPetHappiness()]
elseif(bar.colorClass and UnitIsPlayer(unit)) or
(bar.colorClassNPC and not UnitIsPlayer(unit)) or
(bar.colorClassPet and UnitPlayerControlled(unit) and not UnitIsPlayer(unit)) then
local _, class = UnitClass(unit)
t = self.colors.class[class]
elseif(bar.colorReaction) then
t = self.colors.reaction[UnitReaction(unit, "player")]
elseif(bar.colorSmooth and max ~= 0) then
r, g, b = self.ColorGradient(min / max, unpack(bar.smoothGradient or self.colors.smooth))
elseif(bar.colorHealth) then
t = self.colors.health
end
 
if(t) then
r, g, b = t[1], t[2], t[3]
end
 
if(b) then
bar:SetStatusBarColor(r, g, b)
 
local bg = bar.bg
if(bg) then
local mu = bg.multiplier or 1
bg:SetVertexColor(r * mu, g * mu, b * mu)
end
end
else
self:OverrideUpdateHealth(event, unit, bar, min, max)
end
 
if(self.PostUpdateHealth) then self:PostUpdateHealth(event, unit, bar, min, max) end
end
 
local Enable = function(self)
local health = self.Health
if(health) then
if(health.frequentUpdates and (self.unit and not self.unit:match'%w+target$') or not self.unit) then
health.disconnected = true
health:SetScript('OnUpdate', OnHealthUpdate)
else
self:RegisterEvent("UNIT_HEALTH", Update)
end
self:RegisterEvent("UNIT_MAXHEALTH", Update)
self:RegisterEvent('UNIT_HAPPINESS', Update)
-- For tapping.
self:RegisterEvent('UNIT_FACTION', Update)
 
if(not health:GetStatusBarTexture()) then
health:SetStatusBarTexture[[Interface\TargetingFrame\UI-StatusBar]]
end
 
return true
end
end
 
local Disable = function(self)
local health = self.Health
if(health) then
if(self:GetScript'OnUpdate') then
health:SetScript('OnUpdate', nil)
else
self:UnregisterEvent('UNIT_HEALTH', Update)
end
 
self:UnregisterEvent('UNIT_MAXHEALTH', Update)
self:UnregisterEvent('UNIT_HAPPINESS', Update)
self:UnregisterEvent('UNIT_FACTION', Update)
end
end
 
oUF:AddElement('Health', Update, Enable, Disable)
trunk/oUF_Smee2/oUF/elements/pvp.lua New file
0,0 → 1,37
local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')
local oUF = _G[global]
 
local Update = function(self, event, unit)
if(unit ~= self.unit) then return end
 
if(self.PvP) then
local factionGroup = UnitFactionGroup(unit)
if(UnitIsPVPFreeForAll(unit)) then
self.PvP:SetTexture[[Interface\TargetingFrame\UI-PVP-FFA]]
self.PvP:Show()
elseif(factionGroup and UnitIsPVP(unit)) then
self.PvP:SetTexture([[Interface\TargetingFrame\UI-PVP-]]..factionGroup)
self.PvP:Show()
else
self.PvP:Hide()
end
end
end
 
local Enable = function(self)
if(self.PvP) then
self:RegisterEvent("UNIT_FACTION", Update)
 
return true
end
end
 
local Disable = function(self)
if(self.PvP) then
self:UnregisterEvent("UNIT_FACTION", Update)
end
end
 
oUF:AddElement('PvP', Update, Enable, Disable)
trunk/oUF_Smee2/oUF/elements/castbar.lua New file
0,0 → 1,359
--[[
Original codebase:
oUF_Castbar by starlon.
http://svn.wowace.com/wowace/trunk/oUF_Castbar/
 
Elements handled: .Castbar
Sub-elements: .Text, .Icon, .Time, .SafeZone, .Spark
Notes: This element will not work on units that require a OnUpdate.
(eventless units).
 
Functions that can be overridden from within a layout:
- :CustomDelayText(duration)
- :CustomTimeText(duration)
 
--]]
local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')
local oUF = _G[global]
 
local noop = function() end
local UnitName = UnitName
local GetTime = GetTime
local UnitCastingInfo = UnitCastingInfo
local UnitChannelInfo = UnitChannelInfo
 
local UNIT_SPELLCAST_START = function(self, event, unit, spell, spellrank)
if(self.unit ~= unit) then return end
 
local castbar = self.Castbar
local name, rank, text, texture, startTime, endTime, _, castid = UnitCastingInfo(unit)
if(not name) then
castbar:Hide()
return
end
 
endTime = endTime / 1e3
startTime = startTime / 1e3
local max = endTime - startTime
 
castbar.castid = castid
castbar.duration = GetTime() - startTime
castbar.max = max
castbar.delay = 0
castbar.casting = true
 
castbar:SetMinMaxValues(0, max)
castbar:SetValue(0)
 
if(castbar.Text) then castbar.Text:SetText(text) end
if(castbar.Icon) then castbar.Icon:SetTexture(texture) end
if(castbar.Time) then castbar.Time:SetText() end
 
local sf = castbar.SafeZone
if(sf) then
sf:ClearAllPoints()
sf:SetPoint'RIGHT'
sf:SetPoint'TOP'
sf:SetPoint'BOTTOM'
end
 
if(self.PostCastStart) then self:PostCastStart(event, unit, name, rank, text, castid) end
castbar:Show()
end
 
local UNIT_SPELLCAST_FAILED = function(self, event, unit, spellname, spellrank, castid)
if(self.unit ~= unit) then return end
 
local castbar = self.Castbar
if(castbar.castid ~= castid) then
return
end
 
castbar.casting = nil
castbar:SetValue(0)
castbar:Hide()
 
if(self.PostCastFailed) then self:PostCastFailed(event, unit, spellname, spellrank, castid) end
end
 
local UNIT_SPELLCAST_INTERRUPTED = function(self, event, unit, spellname, spellrank, castid)
if(self.unit ~= unit) then return end
 
local castbar = self.Castbar
if(castbar.castid ~= castid) then
return
end
castbar.casting = nil
castbar.channeling = nil
 
castbar:SetValue(0)
castbar:Hide()
 
if(self.PostCastInterrupted) then self:PostCastInterrupted(event, unit, spellname, spellrank, castid) end
end
 
local UNIT_SPELLCAST_DELAYED = function(self, event, unit, spellname, spellrank)
if(self.unit ~= unit) then return end
 
local name, rank, text, texture, startTime, endTime = UnitCastingInfo(unit)
if(not startTime) then return end
 
local castbar = self.Castbar
local duration = GetTime() - (startTime / 1000)
if(duration < 0) then duration = 0 end
 
castbar.delay = castbar.delay + castbar.duration - duration
castbar.duration = duration
 
castbar:SetValue(duration)
 
if(self.PostCastDelayed) then self:PostCastDelayed(event, unit, name, rank, text) end
end
 
local UNIT_SPELLCAST_STOP = function(self, event, unit, spellname, spellrank, castid)
if(self.unit ~= unit) then return end
 
local castbar = self.Castbar
if(castbar.castid ~= castid) then
return
end
 
castbar.casting = nil
castbar:SetValue(0)
castbar:Hide()
 
if(self.PostCastStop) then self:PostCastStop(event, unit, spellname, spellrank, castid) end
end
 
local UNIT_SPELLCAST_CHANNEL_START = function(self, event, unit, spellname, spellrank)
if(self.unit ~= unit) then return end
 
local castbar = self.Castbar
local name, rank, text, texture, startTime, endTime = UnitChannelInfo(unit)
if(not name) then
return
end
 
endTime = endTime / 1e3
startTime = startTime / 1e3
local max = (endTime - startTime)
local duration = endTime - GetTime()
 
castbar.duration = duration
castbar.max = max
castbar.delay = 0
castbar.channeling = true
 
castbar:SetMinMaxValues(0, max)
castbar:SetValue(duration)
 
if(castbar.Text) then castbar.Text:SetText(name) end
if(castbar.Icon) then castbar.Icon:SetTexture(texture) end
if(castbar.Time) then castbar.Time:SetText() end
 
local sf = castbar.SafeZone
if(sf) then
sf:ClearAllPoints()
sf:SetPoint'LEFT'
sf:SetPoint'TOP'
sf:SetPoint'BOTTOM'
end
 
if(self.PostChannelStart) then self:PostChannelStart(event, unit, name, rank, text) end
castbar:Show()
end
 
local UNIT_SPELLCAST_CHANNEL_UPDATE = function(self, event, unit, spellname, spellrank)
if(self.unit ~= unit) then return end
 
local name, rank, text, texture, startTime, endTime, oldStart = UnitChannelInfo(unit)
if(not name) then
return
end
 
local castbar = self.Castbar
local duration = (endTime / 1000) - GetTime()
 
castbar.delay = castbar.delay + castbar.duration - duration
castbar.duration = duration
castbar.max = (endTime - startTime) / 1000
 
castbar:SetMinMaxValues(0, castbar.max)
castbar:SetValue(duration)
 
if(self.PostChannelUpdate) then self:PostChannelUpdate(event, unit, name, rank, text) end
end
 
local UNIT_SPELLCAST_CHANNEL_STOP = function(self, event, unit, spellname, spellrank)
if(self.unit ~= unit) then return end
 
local castbar = self.Castbar
if(castbar:IsShown()) then
castbar.channeling = nil
 
castbar:SetValue(castbar.max)
castbar:Hide()
 
if(self.PostChannelStop) then self:PostChannelStop(event, unit, spellname, spellrank) end
end
end
 
local onUpdate = function(self, elapsed)
if self.casting then
local duration = self.duration + elapsed
if (duration >= self.max) then
self.casting = nil
self:Hide()
end
 
if self.SafeZone then
local width = self:GetWidth()
local _, _, ms = GetNetStats()
-- MADNESS!
local safeZonePercent = (width / self.max) * (ms / 1e5)
if(safeZonePercent > 1) then safeZonePercent = 1 end
self.SafeZone:SetWidth(width * safeZonePercent)
end
 
if self.Time then
if self.delay ~= 0 then
if(self.CustomDelayText) then
self:CustomDelayText(duration)
else
self.Time:SetFormattedText("%.1f|cffff0000-%.1f|r", duration, self.delay)
end
else
if(self.CustomTimeText) then
self:CustomTimeText(duration)
else
self.Time:SetFormattedText("%.1f", duration)
end
end
end
 
self.duration = duration
self:SetValue(duration)
 
if self.Spark then
self.Spark:SetPoint("CENTER", self, "LEFT", (duration / self.max) * self:GetWidth(), 0)
end
elseif self.channeling then
local duration = self.duration - elapsed
 
if(duration <= 0) then
self.channeling = nil
self:Hide()
return
end
 
if(self.SafeZone) then
local width = self:GetWidth()
local _, _, ms = GetNetStats()
-- MADNESS!
local safeZonePercent = (width / self.max) * (ms / 1e5)
if(safeZonePercent > 1) then safeZonePercent = 1 end
self.SafeZone:SetWidth(width * safeZonePercent)
end
 
 
if self.Time then
if self.delay ~= 0 then
if(self.CustomDelayText) then
self:CustomDelayText(duration)
else
self.Time:SetFormattedText("%.1f|cffff0000-%.1f|r", duration, self.delay)
end
else
if(self.CustomTimeText) then
self:CustomTimeText(duration)
else
self.Time:SetFormattedText("%.1f", duration)
end
end
end
 
self.duration = duration
self:SetValue(duration)
if self.Spark then
self.Spark:SetPoint("CENTER", self, "LEFT", (duration / self.max) * self:GetWidth(), 0)
end
else
self.unitName = nil
self.channeling = nil
self:SetValue(1)
self:Hide()
end
end
 
local Enable = function(object, unit)
local castbar = object.Castbar
 
if(castbar) then
if(not (unit and unit:match'%wtarget$')) then
object:RegisterEvent("UNIT_SPELLCAST_START", UNIT_SPELLCAST_START)
object:RegisterEvent("UNIT_SPELLCAST_FAILED", UNIT_SPELLCAST_FAILED)
object:RegisterEvent("UNIT_SPELLCAST_STOP", UNIT_SPELLCAST_STOP)
object:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED", UNIT_SPELLCAST_INTERRUPTED)
object:RegisterEvent("UNIT_SPELLCAST_DELAYED", UNIT_SPELLCAST_DELAYED)
object:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START", UNIT_SPELLCAST_CHANNEL_START)
object:RegisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE", UNIT_SPELLCAST_CHANNEL_UPDATE)
object:RegisterEvent("UNIT_SPELLCAST_CHANNEL_INTERRUPTED", 'UNIT_SPELLCAST_INTERRUPTED')
object:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP", UNIT_SPELLCAST_CHANNEL_STOP)
end
 
castbar:SetScript("OnUpdate", object.OnCastbarUpdate or onUpdate)
 
if object.unit == "player" then
CastingBarFrame:UnregisterAllEvents()
CastingBarFrame.Show = noop
CastingBarFrame:Hide()
elseif(object.unit == 'pet') then
PetCastingBarFrame:UnregisterAllEvents()
PetCastingBarFrame.Show = noop
PetCastingBarFrame:Hide()
end
 
if(not castbar:GetStatusBarTexture()) then
castbar:SetStatusBarTexture[[Interface\TargetingFrame\UI-StatusBar]]
end
 
local spark = castbar.Spark
if(spark and spark:IsObjectType'Texture' and not spark:GetTexture()) then
spark:SetTexture[[Interface\CastingBar\UI-CastingBar-Spark]]
end
 
local sz = castbar.SafeZone
if(sz and sz:IsObjectType'Texture' and not sz:GetTexture()) then
sz:SetTexture(1, 0, 0)
end
 
castbar:Hide()
 
return true
end
end
 
local Disable = function(object, unit)
local castbar = object.Castbar
 
if(castbar) then
object:UnregisterEvent("UNIT_SPELLCAST_START", UNIT_SPELLCAST_START)
object:UnregisterEvent("UNIT_SPELLCAST_FAILED", UNIT_SPELLCAST_FAILED)
object:UnregisterEvent("UNIT_SPELLCAST_STOP", UNIT_SPELLCAST_STOP)
object:UnregisterEvent("UNIT_SPELLCAST_INTERRUPTED", UNIT_SPELLCAST_INTERRUPTED)
object:UnregisterEvent("UNIT_SPELLCAST_DELAYED", UNIT_SPELLCAST_DELAYED)
object:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_START", UNIT_SPELLCAST_CHANNEL_START)
object:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE", UNIT_SPELLCAST_CHANNEL_UPDATE)
object:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_INTERRUPTED", UNIT_SPELLCAST_CHANNEL_INTERRUPTED)
object:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_STOP", UNIT_SPELLCAST_CHANNEL_STOP)
 
castbar:SetScript("OnUpdate", nil)
end
end
 
oUF:AddElement('Castbar', function(...)
UNIT_SPELLCAST_START(...)
UNIT_SPELLCAST_CHANNEL_START(...)
end, Enable, Disable)
trunk/oUF_Smee2/oUF/elements/cpoints.lua New file
0,0 → 1,41
local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')
local oUF = _G[global]
 
local GetComboPoints = GetComboPoints
local MAX_COMBO_POINTS = MAX_COMBO_POINTS
 
local Update = function(self, event, unit)
local cpoints = self.CPoints
if(self.unit ~= unit and (cpoints.unit and cpoints.unit ~= unit)) then return end
local cp = GetComboPoints(cpoints.unit or unit, 'target')
 
if(#cpoints == 0) then
cpoints:SetText((cp > 0) and cp)
else
for i=1, MAX_COMBO_POINTS do
if(i <= cp) then
cpoints[i]:Show()
else
cpoints[i]:Hide()
end
end
end
end
 
local Enable = function(self)
if(self.CPoints) then
self:RegisterEvent('UNIT_COMBO_POINTS', Update)
 
return true
end
end
 
local Disable = function(self)
if(self.CPoints) then
self:UnregisterEvent('UNIT_COMBO_POINTS', Update)
end
end
 
oUF:AddElement('CPoints', Update, Enable, Disable)
trunk/oUF_Smee2/oUF/elements/vehicle.lua New file
0,0 → 1,74
local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')
local oUF = _G[global]
 
local objects = oUF.objects
 
local VehicleDriverFrame
 
local UpdateVehicleSwitch = function(self, attr, value)
if attr == "unit" then
self.unit = value
 
if self:GetAttribute("normalUnit") == "player" then
PlayerFrame.unit = self.unit
BuffFrame_Update()
end
end
end
 
local Enable = function(self, unit)
if self.disallowVehicleSwap or (unit ~= "player" and unit ~= "pet") then return end
 
if not VehicleDriverFrame then
VehicleDriverFrame = CreateFrame("Frame", nil, UIParent, "SecureHandlerStateTemplate")
RegisterStateDriver(VehicleDriverFrame, "vehicle", "[target=vehicle,exists,bonusbar:5]vehicle;novehicle")
VehicleDriverFrame:SetAttribute("_onstate-vehicle", [[
if newstate == "vehicle" then
for idx, frame in pairs(VEHICLE_FRAMES) do
frame:SetAttribute("unit", frame:GetAttribute("vehicleUnit"))
end
else
for idx, frame in pairs(VEHICLE_FRAMES) do
frame:SetAttribute("unit", frame:GetAttribute("normalUnit"))
end
end
]])
VehicleDriverFrame:Execute([[
VEHICLE_FRAMES = newtable()
]])
end
 
self:SetAttribute("normalUnit", unit)
 
if unit == "player" then
self:SetAttribute("vehicleUnit", "pet")
elseif unit == "pet" then
self:SetAttribute("vehicleUnit", "player")
end
 
VehicleDriverFrame:SetFrameRef("vehicleFrame", self)
VehicleDriverFrame:Execute([[
local frame = self:GetFrameRef("vehicleFrame")
table.insert(VEHICLE_FRAMES, frame)
]])
 
self:HookScript("OnAttributeChanged", UpdateVehicleSwitch)
end
 
local Disable = function(self)
self:SetAttribute("unit", self:GetAttribute("normalUnit"))
VehicleDriverFrame:SetFrameRef("vehicleFrame", self)
VehicleDriverFrame:Execute([[
local frame = self:GetFrameRef("vehicleFrame")
for idx, value in pairs(VEHICLE_FRAMES) do
if value == frame then
table.remove(VEHICLE_FRAMES, idx)
return
end
end
]])
end
 
oUF:AddElement("VehicleSwitch", nil, Enable, Disable)
trunk/oUF_Smee2/oUF/elements/masterlooter.lua New file
0,0 → 1,51
local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')
local oUF = _G[global]
 
local function Update(self, event)
local unit
local method, pid, rid = GetLootMethod()
if(method == 'master') then
if(pid) then
if(pid == 0) then
unit = 'player'
else
unit = 'party'..pid
end
elseif(rid) then
unit = 'raid'..rid
end
 
if(UnitIsUnit(unit, self.unit)) then
self.MasterLooter:Show()
elseif(self.MasterLooter:IsShown()) then
self.MasterLooter:Hide()
end
elseif(self.MasterLooter:IsShown()) then
self.MasterLooter:Hide()
end
end
 
local function Enable(self, unit)
local masterlooter = self.MasterLooter
if(masterlooter) then
self:RegisterEvent('PARTY_LOOT_METHOD_CHANGED', Update)
self:RegisterEvent('PARTY_MEMBERS_CHANGED', Update)
 
if(masterlooter:IsObjectType('Texture') and not masterlooter:GetTexture()) then
masterlooter:SetTexture([[Interface\GroupFrame\UI-Group-MasterLooter]])
end
 
return true
end
end
 
local function Disable(self)
if(self.MasterLooter) then
self:UnregisterEvent('PARTY_LOOT_METHOD_CHANGED', Update)
self:UnregisterEvent('PARTY_MEMBERS_CHANGED', Update)
end
end
 
oUF:AddElement('MasterLooter', Update, Enable, Disable)
trunk/oUF_Smee2/oUF/elements/status.lua New file
0,0 → 1,68
local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')
local oUF = _G[global]
 
do
local Update = function(self, event)
if(IsResting()) then
self.Resting:Show()
else
self.Resting:Hide()
end
end
 
local Enable = function(self, unit)
if(self.Resting and unit == 'player') then
self:RegisterEvent("PLAYER_UPDATE_RESTING", Update)
 
if(self.Resting:IsObjectType"Texture" and not self.Resting:GetTexture()) then
self.Resting:SetTexture[[Interface\CharacterFrame\UI-StateIcon]]
self.Resting:SetTexCoord(0, .5, 0, .421875)
end
 
return true
end
end
 
local Disable = function(self)
if(self.Resting) then
self:UnregisterEvent("PLAYER_UPDATE_RESTING", Update)
end
end
 
oUF:AddElement('Resting', Update, Enable, Disable)
end
 
do
local Update = function(self, event)
if(UnitAffectingCombat"player") then
self.Combat:Show()
else
self.Combat:Hide()
end
end
 
local Enable = function(self, unit)
if(self.Combat and unit == 'player') then
self:RegisterEvent("PLAYER_REGEN_DISABLED", Update)
self:RegisterEvent("PLAYER_REGEN_ENABLED", Update)
 
if(self.Combat:IsObjectType"Texture" and not self.Combat:GetTexture()) then
self.Combat:SetTexture[[Interface\CharacterFrame\UI-StateIcon]]
self.Combat:SetTexCoord(.5, 1, 0, .5)
end
 
return true
end
end
 
local Disable = function(self)
if(self.Combat) then
self:UnregisterEvent("PLAYER_REGEN_DISABLED", Update)
self:UnregisterEvent("PLAYER_REGEN_ENABLED", Update)
end
end
 
oUF:AddElement('Combat', Update, Enable, Disable)
end
trunk/oUF_Smee2/oUF/elements/portraits.lua New file
0,0 → 1,45
local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')
local oUF = _G[global]
 
local Update = function(self, event, unit)
if(not UnitIsUnit(self.unit, unit)) then return end
 
local portrait = self.Portrait
if(portrait:IsObjectType'Model') then
local name = UnitName(unit)
if(not UnitExists(unit) or not UnitIsConnected(unit) or not UnitIsVisible(unit)) then
portrait:SetModelScale(4.25)
portrait:SetPosition(0, 0, -1.5)
portrait:SetModel"Interface\\Buttons\\talktomequestionmark.mdx"
elseif(portrait.name ~= name or event == 'UNIT_MODEL_CHANGED') then
portrait:SetUnit(unit)
portrait:SetCamera(0)
 
portrait.name = name
else
portrait:SetCamera(0)
end
else
SetPortraitTexture(portrait, unit)
end
end
 
local Enable = function(self)
if(self.Portrait) then
self:RegisterEvent("UNIT_PORTRAIT_UPDATE", Update)
self:RegisterEvent("UNIT_MODEL_CHANGED", Update)
 
return true
end
end
 
local Disable = function(self)
if(self.Portrait) then
self:UnregisterEvent("UNIT_PORTRAIT_UPDATE", Update)
self:UnregisterEvent("UNIT_MODEL_CHANGED", Update)
end
end
 
oUF:AddElement('Portrait', Update, Enable, Disable)
trunk/oUF_Smee2/oUF/elements/threat.lua New file
0,0 → 1,60
--[[
Elements handled: .Threat
 
Functions that can be overridden from within a layout:
- :PreUpdateThreat(event, unit)
- :OverrideUpdateThreat(event, unit, status)
- :PostUpdateThreat(event, unit, status)
--]]
if(select(4, GetBuildInfo()) < 3e4) then return end
local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')
local oUF = _G[global]
 
local Update = function(self, event, unit)
if(unit ~= self.unit) then return end
if(self.PreUpdateThreat) then self:PreUpdateThreat(event, unit) end
 
unit = unit or self.unit
local threat = self.Threat
local status = UnitThreatSituation(unit)
 
if(not self.OverrideUpdateThreat) then
if(status and status > 0) then
local r, g, b = GetThreatStatusColor(status)
threat:SetVertexColor(r, g, b)
threat:Show()
else
threat:Hide()
end
else
self:OverrideUpdateThreat(event, unit, status)
end
 
if(self.PostUpdateThreat) then self:PostUpdateThreat(event, unit, status) end
end
 
local Enable = function(self)
local threat = self.Threat
if(threat) then
self:RegisterEvent("UNIT_THREAT_SITUATION_UPDATE", Update)
threat:Hide()
 
if(threat:IsObjectType"Texture" and not threat:GetTexture()) then
threat:SetTexture[[Interface\Minimap\ObjectIcons]]
threat:SetTexCoord(6/8, 7/8, 1/2, 1)
end
 
return true
end
end
 
local Disable = function(self)
local threat = self.Threat
if(threat) then
self:UnregisterEvent("UNIT_THREAT_SITUATION_UPDATE", Update)
end
end
 
oUF:AddElement('Threat', Update, Enable, Disable)
trunk/oUF_Smee2/oUF/elements/aura.lua New file
0,0 → 1,296
--[[
Elements handled: .Auras, .Buffs, .Debuffs
 
Shared:
- spacing: Padding between aura icons. (Default: 0)
- size: Size of the aura icons. (Default: 16)
- initialAnchor: Initial anchor in the aura frame. (Default: "BOTTOMLEFT")
- onlyShowPlayer: Only display icons casted by the player. (Default: nil)
- growth-x: Growth direction, affected by initialAnchor. (Default: "UP")
- growth-y: Growth direction, affected by initialAnchor. (Default: "RIGHT")
- disableCooldown: Disable the Cooldown Spiral on the Aura Icons. (Default: nil)
- filter: Expects a string with filter. See the UnitAura[1] documentation for
more information.
 
.Auras only:
- gap: Adds a empty icon to separate buffs and debuffs. (Default: nil)
- numBuffs: The maximum number of buffs that should be shown. (Default: 32)
- numDebuffs: The maximum number of debuffs that should be shown. (Default: 40)
- buffFilter: See filter on Shared. (Default: "HELPFUL")
- debuffFilter: See filter on Shared. (Default: "HARMFUL")
- Variables set by .Auras:
- visibleBuffs: Number of currently visible buff icons.
- visibleDebuffs: Number of currently visible debuff icons.
- visibleAuras: Total number of currently visible buffs + debuffs.
 
.Buffs only:
- num: The maximum number of buffs that should be shown. (Default: 32)
- Variables set by .Buffs:
- visibleBuffs: Number of currently visible buff icons.
 
.Debuffs only:
- num: The maximum number of debuffs that should be shown. (Default: 40)
- Variables set by .Debuffs:
- visibleDebuffs: Number of currently visible debuff icons.
 
Functions that can be overridden from within a layout:
- :PostCreateAuraIcon(icon, icons, index, isDebuff)
- :CreateAuraIcon(icons, index, isDebuff)
- :PostUpdateAuraIcon(icons, unit, icon, index, offset, filter, isDebuff)
- :PreUpdateAura(event, unit)
- :SetAuraPosition(auras, max)
- :PostUpdateAura(event, unit)
 
[1] http://www.wowwiki.com/API_UnitAura
--]]
local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')
local oUF = _G[global]
 
local OnEnter = function(self)
if(not self:IsVisible()) then return end
 
GameTooltip:SetOwner(self, "ANCHOR_BOTTOMRIGHT")
GameTooltip:SetUnitAura(self.frame.unit, self:GetID(), self.filter)
end
 
local OnLeave = function()
GameTooltip:Hide()
end
 
local createAuraIcon = function(self, icons, index, debuff)
local button = CreateFrame("Frame", nil, icons)
button:EnableMouse(true)
 
button:SetWidth(icons.size or 16)
button:SetHeight(icons.size or 16)
 
local cd = CreateFrame("Cooldown", nil, button)
cd:SetAllPoints(button)
 
local icon = button:CreateTexture(nil, "BACKGROUND")
icon:SetAllPoints(button)
 
local count = button:CreateFontString(nil, "OVERLAY")
count:SetFontObject(NumberFontNormal)
count:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -1, 0)
 
local overlay = button:CreateTexture(nil, "OVERLAY")
overlay:SetTexture"Interface\\Buttons\\UI-Debuff-Overlays"
overlay:SetAllPoints(button)
overlay:SetTexCoord(.296875, .5703125, 0, .515625)
button.overlay = overlay
 
button:SetScript("OnEnter", OnEnter)
button:SetScript("OnLeave", OnLeave)
 
table.insert(icons, button)
 
button.parent = icons
button.frame = self
button.debuff = debuff
 
button.icon = icon
button.count = count
button.cd = cd
 
if(self.PostCreateAuraIcon) then self:PostCreateAuraIcon(button, icons, index, debuff) end
 
return button
end
 
local customFilter = function(icons, unit, icon, name, rank, texture, count, dtype, duration, timeLeft, caster)
local isPlayer
 
if(caster == 'player' or caster == 'vehicle') then
isPlayer = true
end
 
if((icons.onlyShowPlayer and isPlayer) or (not icons.onlyShowPlayer and name)) then
icon.isPlayer = isPlayer
icon.owner = caster
return true
end
end
 
local updateIcon = function(self, unit, icons, index, offset, filter, isDebuff, max)
if(index == 0) then index = max end
 
local icon = icons[index + offset]
if(not icon) then
icon = (self.CreateAuraIcon or createAuraIcon) (self, icons, index, isDebuff)
end
 
local name, rank, texture, count, dtype, duration, timeLeft, caster = UnitAura(unit, index, filter)
local show = (self.CustomAuraFilter or customFilter) (icons, unit, icon, name, rank, texture, count, dtype, duration, timeLeft, caster)
if(show) then
if(not icons.disableCooldown and duration and duration > 0) then
icon.cd:SetCooldown(timeLeft - duration, duration)
icon.duration = duration
icon.timeLeft = timeLeft
icon.cd:Show()
else
icon.cd:Hide()
end
 
if((isDebuff and icons.showDebuffType) or (not isDebuff and icons.showBuffType) or icons.showType) then
local color = DebuffTypeColor[dtype] or DebuffTypeColor.none
 
icon.overlay:SetVertexColor(color.r, color.g, color.b)
icon.overlay:Show()
else
icon.overlay:Hide()
end
 
icon.icon:SetTexture(texture)
icon.count:SetText((count > 1 and count))
 
icon.filter = filter
icon.debuff = isDebuff
 
icon:SetID(index)
icon:Show()
 
if(self.PostUpdateAuraIcon) then
self:PostUpdateAuraIcon(icons, unit, icon, index, offset, filter, isDebuff)
end
 
return true
else
icon:Hide()
end
end
 
local SetAuraPosition = function(self, icons, x)
if(icons and x > 0) then
local col = 0
local row = 0
local spacing = icons.spacing or 0
local gap = icons.gap
local size = (icons.size or 16) + spacing
local anchor = icons.initialAnchor or "BOTTOMLEFT"
local growthx = (icons["growth-x"] == "LEFT" and -1) or 1
local growthy = (icons["growth-y"] == "DOWN" and -1) or 1
local cols = math.floor(icons:GetWidth() / size + .5)
local rows = math.floor(icons:GetHeight() / size + .5)
 
for i = 1, x do
local button = icons[i]
if(button and button:IsShown()) then
if(gap and button.debuff) then
if(col > 0) then
col = col + 1
end
 
gap = false
end
 
if(col >= cols) then
col = 0
row = row + 1
end
button:ClearAllPoints()
button:SetPoint(anchor, icons, anchor, col * size * growthx, row * size * growthy)
 
col = col + 1
end
end
end
end
 
local Update = function(self, event, unit)
if(self.unit ~= unit) then return end
if(self.PreUpdateAura) then self:PreUpdateAura(event, unit) end
 
local auras, buffs, debuffs = self.Auras, self.Buffs, self.Debuffs
 
if(auras) then
local buffs = auras.numBuffs or 32
local debuffs = auras.numDebuffs or 40
local max = debuffs + buffs
 
local visibleBuffs, visibleDebuffs = 0, 0
for index = 1, max do
if(index > buffs) then
if(updateIcon(self, unit, auras, index % debuffs, visibleBuffs, auras.debuffFilter or auras.filter or 'HARMFUL', true, debuffs)) then
visibleDebuffs = visibleDebuffs + 1
end
else
if(updateIcon(self, unit, auras, index, 0, auras.buffFilter or auras.filter or 'HELPFUL')) then
visibleBuffs = visibleBuffs + 1
end
end
end
 
auras.visibleBuffs = visibleBuffs
auras.visibleDebuffs = visibleDebuffs
auras.visibleAuras = visibleBuffs + visibleDebuffs
 
self:SetAuraPosition(auras, max)
end
 
if(buffs) then
local filter = buffs.filter or 'HELPFUL'
local max = buffs.num or 32
local visibleBuffs = 0
for index = 1, max do
if(not updateIcon(self, unit, buffs, index, 0, filter)) then
max = index - 1
 
while(buffs[index]) do
buffs[index]:Hide()
index = index + 1
end
break
end
 
visibleBuffs = visibleBuffs + 1
end
 
buffs.visibleBuffs = visibleBuffs
self:SetAuraPosition(buffs, max)
end
 
if(debuffs) then
local filter = debuffs.filter or 'HARMFUL'
local max = debuffs.num or 40
local visibleDebuffs = 0
for index = 1, max do
if(not updateIcon(self, unit, debuffs, index, 0, filter, true)) then
max = index - 1
 
while(debuffs[index]) do
debuffs[index]:Hide()
index = index + 1
end
break
end
 
visibleDebuffs = visibleDebuffs + 1
end
debuffs.visibleDebuffs = visibleDebuffs
self:SetAuraPosition(debuffs, max)
end
 
if(self.PostUpdateAura) then self:PostUpdateAura(event, unit) end
end
 
local Enable = function(self)
if(self.Buffs or self.Debuffs or self.Auras) then
if(not self.SetAuraPosition) then
self.SetAuraPosition = SetAuraPosition
end
self:RegisterEvent("UNIT_AURA", Update)
 
return true
end
end
 
local Disable = function(self)
if(self.Buffs or self.Debuffs or self.Auras) then
self:UnregisterEvent("UNIT_AURA", Update)
end
end
 
oUF:AddElement('Aura', Update, Enable, Disable)
trunk/oUF_Smee2/oUF/oUF.toc New file
0,0 → 1,9
## Interface: 30100
## Title: oUF
## Author: Haste
## Version: 1.3.11
## X-eMail: troeks@gmail.com
## X-oUF: oUF
## Notes: Unit frame framework. Does nothing by itself.
 
oUF.xml
trunk/oUF_Smee2/oUF/LICENSE New file
0,0 → 1,22
Copyright (c) 2006-2009 Trond A Ekseth
 
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
 
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the 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 AUTHORS OR COPYRIGHT
HOLDERS 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.
trunk/oUF_Smee2/oUF/oUF.xml New file
0,0 → 1,39
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file='ouf.lua' />
 
<Script file='elements\power.lua' />
<Script file='elements\aura.lua' />
<Script file='elements\health.lua' />
<Script file='elements\cpoints.lua' />
<Script file='elements\ricons.lua' />
<Script file='elements\leader.lua' />
<Script file='elements\status.lua' />
<Script file='elements\pvp.lua' />
<Script file='elements\portraits.lua' />
<Script file='elements\range.lua' />
<Script file='elements\happiness.lua' />
<Script file='elements\castbar.lua' />
<Script file='elements\threat.lua' />
<Script file='elements\tags.lua' />
<Script file='elements\vehicle.lua' />
<Script file='elements\masterlooter.lua' />
 
<!--
This template requires the layout to set the anchoring positions from the
sub-frame(s). These are feed to the layouts style functions as any other unit
spawned by a header. The main difference is that they have the unitsuffix
attribute set (and they are parented to their respective owener).
-->
<Button name="oUF_HeaderTargetTemplate" inherits="SecureUnitButtonTemplate" hidden="true" virtual="true">
<Frames>
<Button name="$parentTarget" inherits="SecureUnitButtonTemplate">
<Attributes>
<Attribute name="unitsuffix" type="string" value="target"/>
<Attribute name="useparent-unit" type="boolean" value="true"/>
<Attribute name="type1" type="string" value="target"/>
<Attribute name="initial-unitWatch" type="boolean" value="true"/>
</Attributes>
</Button>
</Frames>
</Button>
</Ui>
trunk/oUF_Smee2/embeds.xml
7,5 → 7,6
<Include file="Libs\AceConsole-3.0\AceConsole-3.0.xml"/>
<Include file="Libs\AceDB-3.0\AceDB-3.0.xml"/>
<Include file="Libs\AceEvent-3.0\AceEvent-3.0.xml"/>
<Include file="Libs\LibSharedMedia-3.0\lib.xml"/>
<Include file="Libs\LibSharedMedia-3.0\lib.xml"/>
<Script file="Libs\ LibHealComm-3.0.lua"/>
</Ui>
trunk/oUF_Smee2/oUF_HealComm.lua New file
0,0 → 1,220
--==============================================================================
--
-- oUF_HealComm
--
-- Uses data from LibHealComm-3.0 to add incoming heal estimate bars onto units
-- health bars.
--
-- * currently won't update the frame if max HP is unknown (ie, restricted to
-- players/pets in your group that are in range), hides the bar for these
-- * can define frame.ignoreHealComm in layout to not have the bars appear on
-- that frame
--
--=============================================================================
 
local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
local oUF = _G[global] or oUF
assert(oUF, 'oUF not loaded')
 
local oUF_HealComm = {}
 
local healcomm = LibStub("LibHealComm-3.0")
 
local playerName = UnitName("player")
local playerIsCasting = false
local playerHeals = 0
local playerTarget = ""
oUF.debug=false
 
function round(num, idp)
if idp and idp>0 then
local mult = 10^idp
return math.floor(num * mult + 0.5) / mult
end
return math.floor(num + 0.5)
end
 
local numberize = function(val)
if(val >= 1e3) then
return ("%.1fk"):format(val / 1e3)
elseif (val >= 1e6) then
return ("%.1fm"):format(val / 1e6)
else
return round(val,1)
end
end
 
local function Hex(r, g, b)
if type(r) == "table" then
if r.r then r, g, b = r.r, r.g, r.b else r, g, b = unpack(r) end
end
return string.format("|cff%02x%02x%02x", r*255, g*255, b*255)
end
 
 
--set texture and color here
local color = {
r = 0,
g = 1,
b = 0,
a = .25,
}
 
 
--update a specific bar
local updateHealCommBar = function(frame, unit)
if not unit or unit == nil then return end
local curHP = UnitHealth(unit)
local maxHP = UnitHealthMax(unit)
local percHP = curHP / maxHP
local incHeals = select(2, healcomm:UnitIncomingHealGet(unit, GetTime())) or 0
local healCommBar = frame.HealCommBar
local _,parentBar,_,_,_ = healCommBar:GetPoint()
 
--add player's own heals if casting on this unit
if playerIsCasting then
for i = 1, select("#", playerTarget) do
local target = select(i, playerTarget)
if target == unit then
incHeals = incHeals + playerHeals
end
end
end
local percInc = incHeals / maxHP
 
--hide if unknown max hp or no heals inc
if maxHP == 100 or incHeals == 0 then
frame.HealCommBar:Hide()
return
else
frame.HealCommBar:Show()
end
 
h = parentBar:GetHeight()
w = frame:GetWidth()-2
orient = parentBar:GetOrientation()
healCommBar:ClearAllPoints()
healCommBar:SetFrameStrata("DIALOG")
 
if(orient=="VERTICAL")then
healCommBar:SetHeight(percInc * h)
healCommBar:SetWidth(w)
healCommBar:SetPoint("BOTTOM", parentBar, "BOTTOM", 0, h * percHP)
else
healCommBar:SetWidth(percInc * w)
healCommBar:SetHeight(h)
healCommBar:SetPoint("LEFT", parentBar, "LEFT", w * percHP,0)
end
if(healCommBar.Amount)then
healCommBar.Amount:SetText(numberize(incHeals))
end
 
end
 
--used by library callbacks, arguments should be list of units to update
local updateHealCommBars = function(...)
for i = 1, select("#", ...) do
local unit = select(i, ...)
 
--search current oUF frames for this unit
for frame in pairs(oUF.units) do
local name, server = UnitName(frame)
if server then name = strjoin("-",name,server) end
if name == unit and not oUF.units[frame].ignoreHealComm then
updateHealCommBar(oUF.units[frame],unit)
end
end
end
end
 
local function hook(frame)
if frame.ignoreHealComm then return end
 
local parentBar = frame.Health
--create heal bar here and set initial values
local hcb = CreateFrame"StatusBar"
if(parentBar:GetOrientation() =="VERTICAL")then
hcb:SetWidth(parentBar:GetWidth()) -- same height as health bar
hcb:SetHeight(4) --no initial width
hcb:SetStatusBarTexture(parentBar:GetStatusBarTexture():GetTexture())
hcb:SetStatusBarColor(color.r, color.g, color.b, color.a)
hcb:SetParent(frame)
hcb:SetPoint("BOTTOMLEFT", parentBar, "TOPLEFT",0,0) --attach to immediate right of health bar to start
hcb:Hide() --hide it for now
else
hcb:SetHeight(parentBar:GetHeight()) -- same height as health bar
hcb:SetWidth(4) --no initial width
hcb:SetStatusBarTexture(parentBar:GetStatusBarTexture():GetTexture())
hcb:SetStatusBarColor(color.r, color.g, color.b, color.a)
hcb:SetParent(frame)
hcb:SetPoint("LEFT", parentBar, "RIGHT",0,0) --attach to immediate right of health bar to start
hcb:Hide() --hide it for now
end
 
healthBarTextObj = parentBar.value or parentBar.text
if(healthBarTextObj)then
fontName, fontHeight, fontFlags = healthBarTextObj:GetFont()
else
fontName, fontHeight, fontFlags = font, fontSize, "outline"
end
 
hcb.Amount = hcb:CreateFontString(nil, "OVERLAY")
hcb.Amount:SetFont(fontName, fontHeight, fontFlags)
hcb.Amount:SetPoint('CENTER',hcb, 0, 0)
hcb.Amount:SetTextColor(1,1,1,.5)
hcb.Amount:SetJustifyH("CENTER")
 
if(frame.FontObjects ~= nil) then
frame.FontObjects["incomingHeals"] = {
name = "Incoming Heals",
object = hcb.Amount
}
end
 
frame.HealCommBar = hcb
 
local o = frame.PostUpdateHealth
frame.PostUpdateHealth = function(...)
if o then o(...) end
local name, server = UnitName(frame.unit)
if server then name = strjoin("-",name,server) end
updateHealCommBar(frame, name) --update the bar when unit's health is updated
end
end
 
--hook into all existing frames
for i, frame in ipairs(oUF.objects) do hook(frame) end
 
--hook into new frames as they're created
oUF:RegisterInitCallback(hook)
 
--set up LibHealComm callbacks
function oUF_HealComm:HealComm_DirectHealStart(event, healerName, healSize, endTime, ...)
if healerName == playerName then
playerIsCasting = true
playerTarget = ...
playerHeals = healSize
end
updateHealCommBars(...)
end
 
function oUF_HealComm:HealComm_DirectHealUpdate(event, healerName, healSize, endTime, ...)
updateHealCommBars(...)
end
 
function oUF_HealComm:HealComm_DirectHealStop(event, healerName, healSize, succeeded, ...)
if healerName == playerName then
playerIsCasting = false
end
updateHealCommBars(...)
end
 
function oUF_HealComm:HealComm_HealModifierUpdate(event, unit, targetName, healModifier)
updateHealCommBars(unit)
end
 
healcomm.RegisterCallback(oUF_HealComm, "HealComm_DirectHealStart")
healcomm.RegisterCallback(oUF_HealComm, "HealComm_DirectHealUpdate")
healcomm.RegisterCallback(oUF_HealComm, "HealComm_DirectHealStop")
healcomm.RegisterCallback(oUF_HealComm, "HealComm_HealModifierUpdate")
Property changes : Added: svn:executable + *
trunk/oUF_Smee2/oUF_SmeeRunes.lua New file
0,0 → 1,119
local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
local oUF = _G[global] or oUF
assert(oUF, 'oUF not loaded')
--[[
 
Elements handled:
.RuneBar [fontstring or table]
 
FontString only:
- space: The space between each "counter". (Default: " ")
- symbol: The symbol used when cooldowns are over. (Default: "*")
- interval: The time offset used for the update script. (Default: 0.5)
 
--]]
 
local localized, class = UnitClass('player')
local dummy = CreateFrame('Frame')
local colors = {
[1] = {0.77, 0.12, 0.23},
[2] = {0.3, 0.8, 0.1},
[3] = {0, 0.4, 0.7},
[4] = {0.8, 0.8, 0.8},
}
 
local OnUpdateBar, OnUpdateText
do
local total = 0
function OnUpdateText(self, elapsed)
total = total + elapsed
 
if(total >= (self.bars.RuneBar.interval or 0.5)) then
self:UpdateElement('RuneBar')
total = 0
end
end
 
function OnUpdateBar(self, rune)
local start, duration, ready = GetRuneCooldown(rune)
 
if(ready) then
self:SetValue(1)
self:SetScript('OnUpdate', nil)
else
self:SetValue((GetTime() - start) / duration)
end
end
end
 
local function UpdateStatusBar(self, event, rune, usable)
if(rune and not usable and GetRuneType(rune)) then
self.bars.RuneBar.bars[rune]:SetScript('OnUpdate', function(self) OnUpdateBar(self, rune) end)
end
end
 
local function Update(self, event, rune)
local runebar = self.bars.RuneBar
if(#runebar.bars == 0) then
local text = ''
for i = 1, 6 do
local start, duration, ready, temp = GetRuneCooldown(i)
local r, g, b = unpack(runebar.colors[GetRuneType(i)])
 
local temp = ready and (runebar.symbol or '*') or (duration - math.floor(GetTime() - start))
text = string.format('%s|cff%02x%02x%02x%s%s|r', text, r * 255, g * 255, b * 255, temp, runebar.space or ' ')
end
 
runebar:SetText(text)
else
for i = 1, 6 do
local runetype = GetRuneType(i)
if(runetype) then
runebar.bars[i]:SetStatusBarColor(unpack(runebar.colors[runetype]))
end
end
end
end
 
local function Enable(self, unit)
if not (unit == 'player' and class == 'DEATHKNIGHT') then return end
if(self.bars and self.bars.RuneBar)then
local runebar = self.bars.RuneBar
 
if(not runebar.colors) then
runebar.colors = self.colors.runes or colors
end
 
self:RegisterEvent('RUNE_TYPE_UPDATE', Update)
 
if(#runebar.bars == 0) then
self:RegisterEvent('RUNE_POWER_UPDATE', Update)
dummy:SetScript('OnUpdate', function(s, e) OnUpdateText(self, e) end)
else
self:RegisterEvent('RUNE_POWER_UPDATE', UpdateStatusBar)
end
 
RuneFrame:Hide()
 
return true
end
end
 
local function Disable(self)
local runebar = self.bars.RuneBar
if(runebar) then
self:RegisterEvent('RUNE_TYPE_UPDATE', Update)
 
if(#runebar == 0) then
self:UnregisterEvent('RUNE_POWER_UPDATE', Update)
dummy:SetScript('OnUpdate', nil)
else
self:UnregisterEvent('RUNE_POWER_UPDATE', UpdateStatusBar)
end
 
RuneFrame:Show()
end
end
 
oUF:AddElement('RuneBar', Update, Enable, Disable)
trunk/oUF_Smee2/tagEditor.lua New file
0,0 → 1,109
local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
local oUF = _G[global] or oUF
assert(oUF, 'oUF not loaded')
 
oUF.TagEvents["[status]"] = "UNIT_HEALTH PLAYER_UPDATE_RESTING PLAYER_FLAGS_CHANGED"
oUF.TagEvents["[afk]"] = "UNIT_HEALTH PLAYER_UPDATE_RESTING PLAYER_FLAGS_CHANGED"
oUF.TagEvents["[shortName]"] = "UNIT_NAME_UPDATE"
 
oUF.TagsLogicStrings = {
["[class]"] = [[function(u) return UnitClass(u) end]],
["[creature]"] = [[function(u) return UnitCreatureFamily(u) or UnitCreatureType(u) end]],
["[curhp]"] = [[UnitHealth]],
["[curpp]"] = [[UnitPower]],
["[dead]"] = [[function(u)
return UnitIsDead(u) and "Dead" or UnitIsGhost(u) and "Ghost"
end]],
["[difficulty]"] = [[function(u)
if UnitCanAttack("player", u) then
local l = UnitLevel(u);
return Hex(GetDifficultyColor((l > 0) and l or 99))
end
end]],
["[faction]"] = [[function(u) return UnitFactionGroup(u) end]],
["[leader]"] = [[function(u) return UnitIsPartyLeader(u) and "(L)" end]],
["[leaderlong]"] = [[function(u) return UnitIsPartyLeader(u) and "(Leader)" end]],
["[level]"] = [[function(u)
local l = UnitLevel(u);
return (l > 0) and l or "??"
end]],
["[maxhp]"] = [[UnitHealthMax]],
["[maxpp]"] = [[UnitPowerMax]],
["[missinghp]"] = [[function(u) m=UnitHealthMax(u) - UnitHealth(u); return m>0 and m.. " | " or "" end]],
["[missingpp]"] = [[function(u) m=UnitPowerMax(u) - UnitPower(u); return m>0 and m.. " | " or "" end]],
["[name]"] = [[function(u, r) return UnitName(r or u) end]],
["[shortname]"] = [[function(u) return string.sub(UnitName(u),1,4) or '' end]],
["[offline]"] = [[function(u) return (not UnitIsConnected(u) and "Offline") end]],
["[perhp]"] = [[function(u) local m = UnitHealthMax(u); return m == 0 and 0 or math.floor(UnitHealth(u)/m*100+0.5) end]],
["[perpp]"] = [[function(u) local m = UnitPowerMax(u); return m == 0 and 0 or math.floor(UnitPower(u)/m*100+0.5) end]],
["[plus]"] = [[function(u) return UnitIsPlusMob(u) and "+" end]],
["[pvp]"] = [[function(u) return UnitIsPVP(u) and "PvP" end]],
["[race]"] = [[function(u) return UnitRace(u) end]],
["[raidcolor]"] = [[function(u)
local _, x = UnitClass(u);
return x and Hex(RAID_CLASS_COLORS[x])
end]],
["[rare]"] = [[function(u)
local c = UnitClassification(u);
return (c == "rare" or c == "rareelite") and "Rare"
end]],
["[resting]"] = [[function(u) return u == "player" and IsResting() and "zzz" end]],
["[afk]"] = [[function(u) return UnitIsAFK(u) and "AFK" end]],
["[sex]"] = [[function(u) local s = UnitSex(u) return s == 2 and "Male" or s == 3 and "Female" end]],
["[smartclass]"] = [[function(u) return UnitIsPlayer(u) and oUF.Tags["[class]"](u) or oUF.Tags["[creature]"](u) end]],
["[status]"] = [[function(u) return UnitIsDead(u) and "Dead" or UnitIsGhost(u) and "Ghost" or not UnitIsConnected(u) and "Offline" or oUF.Tags["[resting]"](u) end]],
["[threat]"] = [[function(u) local s = UnitThreatSituation(u); return s == 1 and "++" or s == 2 and "--" or s == 3 and "Aggro" end]],
["[threatplus]"] = [[function(u)
local unitTarget = u.."target"
if(UnitExists(unitTarget))then
local_,_, threatpct, rawthreatpct, threatvalue = UnitDetailedThreatSituation(u, uTarget)
return rawthreatpct
else
return ''
end
end]],
["[threatcolor]"] = [[function(u) return Hex(GetThreatStatusColor(UnitThreatSituation(u))) end]],
["[cpoints]"] = [[function(u) local cp = GetComboPoints(u, 'target') return (cp > 0) and cp end]],
['[smartlevel]'] = [[function(u)
local c = UnitClassification(u)
if(c == "worldboss") then
return "Boss"
else
local plus = oUF.Tags["[plus]"](u)
local level = oUF.Tags["[level]"](u)
if(plus) then
return level .. plus
else
return level
end
end
end]],
["[classification]"] = [[function(u)
local c = UnitClassification(u)
return c == "rare" and "Rare" or c == "eliterare" and "Rare Elite" or c == "elite" and "Elite" or c == "worldboss" and "Boss"
end]],
["[shortclassification]"] = [[function(u)
local c = UnitClassification(u)
return c == "rare" and "R" or c == "eliterare" and "R+" or c == "elite" and "+" or c == "worldboss" and "B"
end]],
}
function oUF:ReWriteTag(tag,events,logic)
if logic then
builder = assert(loadstring("return " .. logic))
self.Tags[tag] = builder()
end
if events then
oUF.TagEvents[tag] = events
end
end
 
function oUF:CompileTagStringLogic()
for tag,logic in pairs(self.TagsLogicStrings)do
oUF:ReWriteTag(tag,oUF.TagEvents[tag],logic)
end
end