/trunk
local _G = getfenv(0) |
local LibStub = _G.LibStub |
local Heatsink = LibStub("AceAddon-3.0"):GetAddon("Heatsink") |
local L = LibStub:GetLibrary("AceLocale-3.0"):GetLocale("Heatsink") |
local AceGUIWidgetLSMlists = _G.AceGUIWidgetLSMlists |
local STRING_SCHOOL_ARCANE = _G.STRING_SCHOOL_ARCANE |
local STRING_SCHOOL_FIRE = _G.STRING_SCHOOL_FIRE |
local STRING_SCHOOL_FROST = _G.STRING_SCHOOL_FROST |
local STRING_SCHOOL_HOLY = _G.STRING_SCHOOL_HOLY |
local STRING_SCHOOL_NATURE = _G.STRING_SCHOOL_NATURE |
local STRING_SCHOOL_PHYSICAL = _G.STRING_SCHOOL_PHYSICAL |
local STRING_SCHOOL_SHADOW = _G.STRING_SCHOOL_SHADOW |
local tostring = _G.tostring |
local tonumber = _G.tonumber |
local unpack = _G.unpack |
local options = { |
type = "group", |
args = { |
toggle = { |
type = "execute", |
name = L["Toggle anchor"], |
desc = L["Toggle the bar anchor frame"], |
func = function() |
Heatsink:ToggleAnchor() |
end, |
order = 10, |
}, |
test = { |
type = "execute", |
name = L["Test"], |
desc = L["Test bars"], |
func = function() |
Heatsink:RunTest() |
end, |
order = 20, |
}, |
duration = { |
name = "Duration settings", |
desc = "Duration settings", |
type = "group", |
args = { |
min = { |
type = "input", |
name = L["Minimum duration"], |
desc = L["Minimum cooldown duration to display"], |
pattern = "%d+", |
get = function() return tostring(Heatsink.db.profile.min) end, |
set = function(info, v) Heatsink.db.profile.min = tonumber(v) end, |
order = 1, |
}, |
max = { |
type = "input", |
name = L["Maximum duration"], |
desc = L["Maximum cooldown duration to display"], |
pattern = "%d+", |
get = function() return tostring(Heatsink.db.profile.max) end, |
set = function(info, v) Heatsink.db.profile.max = tonumber(v) end, |
order = 2, |
}, |
}, |
}, |
bars = { |
order = 10, |
type = "group", |
name = L["Bar settings"], |
desc = L["Bar settings"], |
args = { |
growup = { |
type = "toggle", |
order = 10, |
name = L["Grow upwards"], |
desc = L["Toggle bars grow upwards/downwards from anchor"], |
get = function () return Heatsink.db.profile.growup end, |
set = function (info, v) |
Heatsink.db.profile.growup = v |
Heatsink:UpdateAnchor() |
end, |
}, |
scale = { |
type = "range", |
order = 20, |
name = L["Scale"], |
desc = L["Set the scale of the bars"], |
get = function() return Heatsink.db.profile.scale end, |
set = function(info, v) |
Heatsink.db.profile.scale = v |
Heatsink:UpdateAnchor() |
end, |
min = 0.1, |
max = 5, |
step = 0.01, |
isPercent = true, |
}, |
texture = { |
type = "select", |
dialogControl = "LSM30_Statusbar", |
order = 30, |
name = L["Texture"], |
desc = L["Set the texture for the timer bars"], |
values = AceGUIWidgetLSMlists.statusbar, |
get = function() return Heatsink.db.profile.texture end, |
set = function(i,v) |
Heatsink.db.profile.texture = v |
Heatsink:UpdateAnchor() |
end, |
}, |
barcolor = { |
type = "color", |
hasAlpha = true, |
order = 40, |
name = L["Bar Color"], |
desc = L["Set the bar color"], |
get = function() return unpack(Heatsink.db.profile.color.bar) end, |
set = function(i,r,g,b,a) |
Heatsink.db.profile.color.bar = { r, g, b, a } |
Heatsink:UpdateAnchor() |
end, |
}, |
bgcolor = { |
type = "color", |
hasAlpha = true, |
order = 50, |
name = L["Background Color"], |
desc = L["Set the background color"], |
get = function() return unpack(Heatsink.db.profile.color.bg) end, |
set = function(i,r,g,b,a) |
Heatsink.db.profile.color.bg = { r, g, b, a } |
Heatsink:UpdateAnchor() |
end, |
}, |
font = { |
type = "select", |
dialogControl = "LSM30_Font", |
order = 60, |
name = L["Font"], |
desc = L["Set the font"], |
values = AceGUIWidgetLSMlists.font, |
get = function() return Heatsink.db.profile.font end, |
set = function(i,v) |
Heatsink.db.profile.font = v |
Heatsink:UpdateAnchor() |
end, |
}, |
fontsize = { |
type = "range", |
order = 70, |
name = L["Font Size"], |
desc = L["Set the font size"], |
min = 8, |
max = 24, |
step = 1, |
get = function() return Heatsink.db.profile.fontsize end, |
set = function(i,v) |
Heatsink.db.profile.fontsize = v |
Heatsink:UpdateAnchor() |
end, |
}, |
justify = { |
type = "select", |
order = 80, |
name = L["Justify"], |
desc = L["Set the text position"], |
values = {["left"]="LEFT", ["center"]="CENTER"}, |
get = function() return Heatsink.db.profile.justify end, |
set = function(i,v) |
Heatsink.db.profile.justify = v |
Heatsink:UpdateAnchor() |
end, |
}, |
textcolor = { |
type = "color", |
order = 90, |
name = L["Text Color"], |
desc = L["Set the text color"], |
get = function() return unpack(Heatsink.db.profile.color.text) end, |
set = function(i,r,g,b,a) |
Heatsink.db.profile.color.text = { r, g, b, a } |
Heatsink:UpdateAnchor() |
end, |
}, |
}, |
}, |
show = { |
type = "group", |
name = L["Show cooldowns"], |
desc = L["Toggle showing cooldown types"], |
args = { |
spells = { |
type = "group", |
name = L["Spells"], |
desc = L["Player spells cooldown options"], |
args = { |
enable = { |
type = "toggle", |
name = L["Enable player spells"], |
desc = L["Toggle showing player spells cooldowns"], |
get = function () return Heatsink.db.profile.show.spells end, |
set = function (info, v) |
Heatsink.db.profile.show.spells = v |
Heatsink:SPELL_UPDATE_COOLDOWN() |
end, |
order = 10, |
}, |
school = { |
type = "toggle", |
name = L["Show school"], |
desc = L["Spawns single bar if a school is locked out"], |
get = function () return Heatsink.db.profile.show.school end, |
set = function (info, v) |
Heatsink.db.profile.show.school = v |
end, |
disabled = function () |
return not Heatsink.db.profile.show.school |
end, |
order = 100, |
}, |
}, |
order = 10, |
}, |
petspells = { |
type = "toggle", |
name = L["Pet spells"], |
desc = L["Toggle showing pet cooldowns"], |
get = function () return Heatsink.db.profile.show.pet end, |
set = function (info, v) |
Heatsink.db.profile.show.pet = v |
Heatsink:PET_BAR_UPDATE_COOLDOWN() |
end, |
order = 20, |
}, |
equipped = { |
type = "toggle", |
name = L["Equipped items"], |
desc = L["Toggle showing equipped items cooldowns"], |
get = function () return Heatsink.db.profile.show.items end, |
set = function (info, v) |
Heatsink.db.profile.show.items = v |
Heatsink:ScanItems() |
end, |
order = 30, |
}, |
bags = { |
type = "toggle", |
name = L["Inventory items"], |
desc = L["Toggle showing inventory items cooldowns"], |
get = function () return Heatsink.db.profile.show.inventory end, |
set = function (info, v) |
Heatsink.db.profile.show.inventory = v |
Heatsink:ScanItems() |
end, |
order = 40, |
}, |
proc = { |
type = "toggle", |
name = L["Internal Cooldowns"], |
desc = L["Toggle showing item internal proc cooldowns"], |
get = function () return Heatsink.db.profile.show.proc end, |
set = function (info, v) |
Heatsink.db.profile.show.proc = v |
end, |
order = 50, |
}, |
}, |
}, |
}, |
} |
function Heatsink:SetupOptions() |
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Heatsink", options) |
options.args.profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(Heatsink.db) |
local optFrame = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("Heatsink") |
LibStub("AceConsole-3.0"):RegisterChatCommand( "heatsink", function() InterfaceOptionsFrame_OpenToCategory("Heatsink") end ) |
end |
package-as: Heatsink |
externals: |
libs/LibStub: |
url: svn://svn.wowace.com/wow/libstub/mainline/trunk |
tag: latest |
libs/CallbackHandler-1.0: |
url: svn://svn.wowace.com/wow/callbackhandler/mainline/trunk/CallbackHandler-1.0 |
tag: latest |
libs/AceAddon-3.0: |
url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceAddon-3.0 |
libs/AceGUI-3.0: |
url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceGUI-3.0 |
libs/AceConfig-3.0: |
url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceConfig-3.0 |
libs/AceDB-3.0: |
url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceDB-3.0 |
libs/AceDBOptions-3.0: |
url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceDBOptions-3.0 |
libs/AceConsole-3.0: |
url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceConsole-3.0 |
libs/AceEvent-3.0: |
url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceEvent-3.0 |
libs/AceBucket-3.0: |
url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceBucket-3.0 |
libs/AceLocale-3.0: |
url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceLocale-3.0 |
libs/AceGUI-3.0-SharedMediaWidgets: |
url: svn://svn.wowace.com/wow/ace-gui-3-0-shared-media-widgets/mainline/trunk/AceGUI-3.0-SharedMediaWidgets |
tag: latest |
libs/LibCandyBar-3.0: |
url: svn://svn.wowace.com/wow/libcandybar-3-0/mainline/trunk |
tag: latest |
libs/LibSharedMedia-3.0: |
url: svn://svn.wowace.com/wow/libsharedmedia-3-0/mainline/trunk/LibSharedMedia-3.0 |
tag: latest |
libs/LibInternalCooldowns-1.0: |
url: svn://svn.wowace.com/wow/libinternalcooldowns-1-0/mainline/trunk/LibInternalCooldowns-1.0 |
tag: latest |
local _G = getfenv(0) |
local LibStub = _G.LibStub |
local Heatsink = LibStub("AceAddon-3.0"):NewAddon("Heatsink", "AceConsole-3.0", "AceEvent-3.0", "AceBucket-3.0") |
_G.Heatsink = Heatsink |
local L = LibStub:GetLibrary("AceLocale-3.0"):GetLocale("Heatsink") |
local candy = LibStub("LibCandyBar-3.0") |
local icd = LibStub("LibInternalCooldowns-1.0") |
local media = LibStub("LibSharedMedia-3.0") |
local anchor, db, class |
local RUNE_COOLDOWN = 10 |
local GCD = 1.5 |
local BOOKTYPE_PET = _G.BOOKTYPE_PET |
local BOOKTYPE_SPELL = _G.BOOKTYPE_SPELL |
local CreateFrame = _G.CreateFrame |
local GameFontNormal = _G.GameFontNormal |
local GetContainerItemCooldown = _G.GetContainerItemCooldown |
local GetContainerItemInfo = _G.GetContainerItemInfo |
local GetContainerItemLink = _G.GetContainerItemLink |
local GetContainerNumSlots = _G.GetContainerNumSlots |
local GetInventoryItemCooldown = _G.GetInventoryItemCooldown |
local GetInventoryItemLink = _G.GetInventoryItemLink |
local GetInventoryItemTexture = _G.GetInventoryItemTexture |
local GetInventorySlotInfo = _G.GetInventorySlotInfo |
local GetItemInfo = _G.GetItemInfo |
local GetNumSpellTabs = _G.GetNumSpellTabs |
local GetRealZoneText = _G.GetRealZoneText |
local GetSpellCooldown = _G.GetSpellCooldown |
local GetSpellInfo = _G.GetSpellInfo |
local GetSpellName = _G.GetSpellName |
local GetSpellTabInfo = _G.GetSpellTabInfo |
local GetTime = _G.GetTime |
local UnitClass = _G.UnitClass |
local UnitGUID = _G.UnitGUID |
local ipairs = _G.ipairs |
local pairs = _G.pairs |
local unpack = _G.unpack |
local wipe = _G.wipe |
local format = _G.string.format |
local find = _G.string.find |
local random = _G.math.random |
local tinsert = _G.table.insert |
local tsort = _G.table.sort |
local defaults = { |
profile = { |
min = 3, |
max = 3600, |
growup = true, |
texture = "Blizzard", |
font = "ABF", |
fontsize = 10, |
justify = "CENTER", |
width = 250, |
height = 14, |
scale = 1, |
pos = { |
p = "CENTER", |
rp = "CENTER", |
x = 0, |
y = 0, |
}, |
color = { |
bg = { 0.5, 0.5, 0.5, 0.3 }, |
text = { 1, 1, 1 }, |
bar = { 0.25, 0.33, 0.68, 1 }, |
}, |
show = { |
school = true, |
spells = true, |
pet = true, |
items = true, |
inventory = true, |
proc = true, |
}, |
}, |
} |
-- Credit to the BigWigs team (Rabbit, Ammo, et al) for the anchor code |
local createAnchor, toggleAnchor, updateAnchor, runTest, startBar, stopBar |
do |
local GameTooltip = _G.GameTooltip |
local function sortBars(a, b) |
return (a.remaining > b.remaining and db.growup) and true or false |
end |
local function rearrangeBars(anchor) |
local tmp = {} |
for bar in pairs(anchor.active) do |
tinsert(tmp, bar) |
end |
tsort(tmp, sortBars) |
local lastBar = nil |
for i, bar in ipairs(tmp) do |
bar:ClearAllPoints() |
if db.growup then |
bar:SetPoint("BOTTOMLEFT", lastBar or anchor, "TOPLEFT") |
bar:SetPoint("BOTTOMRIGHT", lastBar or anchor, "TOPRIGHT") |
else |
bar:SetPoint("TOPLEFT", lastBar or anchor, "BOTTOMLEFT") |
bar:SetPoint("TOPRIGHT", lastBar or anchor, "BOTTOMRIGHT") |
end |
lastBar = bar |
end |
wipe(tmp) |
end |
local function onDragHandleMouseDown(self) |
self:GetParent():StartSizing("BOTTOMRIGHT") |
end |
local function onDragHandleMouseUp(self, button) |
self:GetParent():StopMovingOrSizing() |
end |
local function onResize(self, width) |
db.width = width |
rearrangeBars(self) |
end |
local function onDragStart(self) |
self:StartMoving() |
end |
local function onDragStop(self) |
self:StopMovingOrSizing() |
local p, _, rp, x, y = self:GetPoint() |
db.pos.p = p |
db.pos.rp = rp |
db.pos.x = x |
db.pos.y = y |
end |
local function onControlEnter(self) |
GameTooltip:ClearLines() |
GameTooltip:SetOwner(self, "ANCHOR_TOPLEFT") |
GameTooltip:AddLine(self.tooltipHeader) |
GameTooltip:AddLine(self.tooltipText, 1, 1, 1, 1) |
GameTooltip:Show() |
end |
local function onControlLeave() |
GameTooltip:Hide() |
end |
local function getBar(text) |
local bar |
for k in pairs(anchor.active) do |
if k.candyBarLabel:GetText() == text then |
bar = true |
break |
end |
end |
return bar |
end |
function stopBar(text) |
local bar |
for k in pairs(anchor.active) do |
if (not text or k.candyBarLabel:GetText() == text) then |
k:Stop() |
bar = true |
end |
end |
if bar then rearrangeBars(anchor) end |
return bar |
end |
function startBar(text, start, duration, icon, update) |
if getBar(text) and not update then |
return |
elseif duration >= db.min and duration <= db.max then |
stopBar(text) |
local bar = candy:New(media:Fetch("statusbar", db.texture), db.width, db.height) |
bar:Set("anchor", anchor) |
anchor.active[bar] = true |
bar.candyBarBackground:SetVertexColor(unpack(db.color.bg)) |
bar:SetColor(unpack(db.color.bar)) |
bar.candyBarLabel:SetJustifyH(db.justify) |
bar.candyBarLabel:SetTextColor(unpack(db.color.text)) |
bar.candyBarLabel:SetFont(media:Fetch("font", db.font), db.fontsize) |
bar.candyBarDuration:SetFont(media:Fetch("font", db.font), db.fontsize) |
bar:SetLabel(text) |
bar:SetDuration(start and (duration-(GetTime()-start)) or duration) |
bar:SetTimeVisibility(true) |
bar:SetIcon(icon) |
bar:SetScale(db.scale) |
bar:Start() |
rearrangeBars(anchor) |
end |
end |
function runTest(anchor) |
local tmp = {} |
for i = 2, GetNumSpellTabs() do |
local name, texture, offset, numSpells = GetSpellTabInfo(i) |
if offset then |
for s = offset + 1, offset + numSpells do |
tinsert(tmp, (GetSpellName(s, BOOKTYPE_SPELL))) |
end |
end |
end |
local spell = tmp[random(1, #tmp)] |
local name, rank, icon = GetSpellInfo(spell) |
local duration = random(10, 30) |
startBar(name, nil, duration, icon) |
wipe(tmp) |
end |
function toggleAnchor(anchor) |
if anchor:IsShown() then |
anchor:Hide() |
else |
anchor:Show() |
end |
end |
function createAnchor(frameName, title) |
local display = CreateFrame("Frame", frameName, _G.UIParent) |
display:EnableMouse(true) |
display:SetMovable(true) |
display:SetResizable(true) |
display:RegisterForDrag("LeftButton") |
display:SetWidth(db.width) |
display:SetHeight(20) |
display:SetMinResize(80, 20) |
display:SetMaxResize(1920, 20) |
display:ClearAllPoints() |
display:SetPoint(db.pos.p, _G.UIParent, db.pos.rp, db.pos.x, db.pos.y) |
local bg = display:CreateTexture(nil, "PARENT") |
bg:SetAllPoints(display) |
bg:SetBlendMode("BLEND") |
bg:SetTexture(0, 0, 0, 0.3) |
local header = display:CreateFontString(nil, "OVERLAY") |
header:SetFontObject(GameFontNormal) |
header:SetText(title) |
header:SetAllPoints(display) |
header:SetJustifyH("CENTER") |
header:SetJustifyV("MIDDLE") |
local drag = CreateFrame("Frame", nil, display) |
drag:SetFrameLevel(display:GetFrameLevel() + 10) |
drag:SetWidth(16) |
drag:SetHeight(16) |
drag:SetPoint("BOTTOMRIGHT", display, -1, 1) |
drag:EnableMouse(true) |
drag:SetScript("OnMouseDown", onDragHandleMouseDown) |
drag:SetScript("OnMouseUp", onDragHandleMouseUp) |
drag:SetAlpha(0.5) |
local tex = drag:CreateTexture(nil, "BACKGROUND") |
tex:SetTexture("Interface\\AddOns\\Heatsink\\Textures\\draghandle") |
tex:SetWidth(16) |
tex:SetHeight(16) |
tex:SetBlendMode("ADD") |
tex:SetPoint("CENTER", drag) |
local test = CreateFrame("Button", nil, display) |
test:SetPoint("BOTTOMLEFT", display, "BOTTOMLEFT", 3, 3) |
test:SetHeight(14) |
test:SetWidth(14) |
test.tooltipHeader = L["Test"] |
test.tooltipText = L["Creates a new test bar"] |
test:SetScript("OnEnter", onControlEnter) |
test:SetScript("OnLeave", onControlLeave) |
test:SetScript("OnClick", function() runTest() end) |
test:SetNormalTexture("Interface\\AddOns\\Heatsink\\Textures\\test") |
local close = CreateFrame("Button", nil, display) |
close:SetPoint("BOTTOMLEFT", test, "BOTTOMRIGHT", 4, 0) |
close:SetHeight(14) |
close:SetWidth(14) |
close.tooltipHeader = L["Hide"] |
close.tooltipText = L["Hides the anchor"] |
close:SetScript("OnEnter", onControlEnter) |
close:SetScript("OnLeave", onControlLeave) |
close:SetScript("OnClick", function() toggleAnchor(anchor) end) |
close:SetNormalTexture("Interface\\AddOns\\Heatsink\\Textures\\close") |
display:SetScript("OnSizeChanged", onResize) |
display:SetScript("OnDragStart", onDragStart) |
display:SetScript("OnDragStop", onDragStop) |
display.active = {} |
display:Hide() |
return display |
end |
function updateAnchor(anchor) |
anchor:SetWidth(db.width) |
for bar in pairs(anchor.active) do |
bar.candyBarBar:SetStatusBarTexture(media:Fetch("statusbar", db.texture)) |
bar.candyBarBackground:SetTexture(media:Fetch("statusbar", db.texture)) |
bar.candyBarBackground:SetVertexColor(unpack(db.color.bg)) |
bar.candyBarBar:SetStatusBarColor(unpack(db.color.bar)) |
bar.candyBarLabel:SetJustifyH(db.justify) |
bar.candyBarLabel:SetTextColor(unpack(db.color.text)) |
bar.candyBarLabel:SetFont(media:Fetch("font", db.font), 10) |
bar.candyBarDuration:SetFont(media:Fetch("font", db.font), 10) |
bar:SetScale(db.scale) |
bar:SetWidth(db.width) |
bar:SetHeight(db.height) |
end |
rearrangeBars(anchor) |
end |
end |
function Heatsink:OnInitialize() |
self.db = LibStub("AceDB-3.0"):New("HeatsinkDB", defaults, "Default") |
db = self.db.profile |
self.db.RegisterCallback(self, "OnProfileChanged", "UpdateProfile") |
self.db.RegisterCallback(self, "OnProfileCopied", "UpdateProfile") |
self.db.RegisterCallback(self, "OnProfileReset", "UpdateProfile") |
self:SetupOptions() |
anchor = createAnchor("HeatsinkAnchor", "Heatsink") |
end |
function Heatsink:OnEnable() |
local _, english = UnitClass("player") |
class = english |
self:RegisterEvent("SPELLS_CHANGED") |
self:RegisterBucketEvent("PET_BAR_UPDATE_COOLDOWN", 0.1) |
self:RegisterBucketEvent("SPELL_UPDATE_COOLDOWN", 1.0) |
self:RegisterBucketEvent("UNIT_INVENTORY_CHANGED", 0.1, "ScanItems") |
self:RegisterBucketEvent("BAG_UPDATE_COOLDOWN", 0.1,"ScanItems") |
icd.RegisterCallback(self, "InternalCooldowns_Proc") |
candy.RegisterCallback(self, "LibCandyBar_Stop") |
self:ScanPlayer() |
self:ScanPet() |
self:ScanItems() |
end |
function Heatsink:OnDisable() |
self:UnregisterAllEvents() |
icd.UnregisterCallback(self, "InternalCooldowns_Proc") |
candy.UnregisterCallback(self, "LibCandyBar_Stop") |
end |
function Heatsink:UpdateProfile() |
db = self.db.profile |
updateAnchor(anchor) |
end |
function Heatsink:RunTest() |
runTest(anchor) |
end |
function Heatsink:ToggleAnchor() |
toggleAnchor(anchor) |
end |
function Heatsink:UpdateAnchor() |
updateAnchor(anchor) |
end |
function Heatsink:LibCandyBar_Stop(callback, bar) |
local a = bar:Get("anchor") |
if a == anchor and anchor.active and anchor.active[bar] then |
anchor.active[bar] = nil |
end |
end |
function Heatsink:InternalCooldowns_Proc(callback, item, spell, start, duration, source) |
if db.show.proc then |
local name, icon, _ |
if source == "ENCHANT" then |
name, _, icon = GetSpellInfo(spell) |
else |
name, _, _, _, _, _, _, _, _, icon = GetItemInfo(item) |
end |
startBar(name, start, duration, icon) |
end |
end |
function Heatsink:SPELLS_CHANGED() |
self:ScanPlayer() |
self:ScanPet() |
end |
function Heatsink:SPELL_UPDATE_COOLDOWN() |
if db.show.spells then |
if db.show.school and self.schoolspell[class] then |
for school,id in pairs(self.schoolspell[class]) do |
local name, rank, icon = GetSpellInfo(id) |
local start, duration = GetSpellCooldown(name) |
if duration and duration > GCD then |
startBar(school, start, duration, icon) |
self.lockout[school] = true |
else |
self.lockout[school] = false |
end |
end |
end |
for spell, data in pairs(self.player) do |
local start, duration, active = GetSpellCooldown(data.id, BOOKTYPE_SPELL) |
if class == "DEATHKNIGHT" and duration == RUNE_COOLDOWN and not self.whitelist[spell] then |
duration = -1 |
end |
if db.show.school and data.schoolname and self.lockout[data.schoolname] then |
duration = -1 |
end |
if active ==1 and duration > GCD then |
startBar(self.spellsub[spell] or spell, start, duration, data.icon) |
elseif start == 0 and duration == 0 then |
stopBar(spell) |
end |
end |
end |
end |
function Heatsink:PET_BAR_UPDATE_COOLDOWN() |
if db.show.pet then |
for spell, data in pairs(self.pet) do |
local start, duration = GetSpellCooldown(data.id, BOOKTYPE_PET) |
if duration > 0 then |
startBar(spell, start, duration, data.icon) |
elseif duration == 0 then |
stopBar(spell) |
end |
end |
end |
end |
function Heatsink:ScanItems() |
if db.show.inventory then |
for bag = 0,4 do |
local slots = GetContainerNumSlots(bag) |
for slot = 1,slots do |
local start, duration, enabled = GetContainerItemCooldown(bag,slot) |
if enabled == 1 and duration > 0 then |
local link = GetContainerItemLink(bag, slot) |
local _,_,name = link:find("%|h%[(.-)%]%|h") |
local icon = GetContainerItemInfo(bag, slot) |
for k,v in pairs(self.itemsub) do |
if name:find(k) then |
name = v |
end |
end |
startBar(name, start, duration, icon) |
end |
end |
end |
end |
if db.show.items then |
for _, slotName in pairs(Heatsink.slots) do |
local slot = GetInventorySlotInfo(slotName) |
local start, duration, enabled = GetInventoryItemCooldown("player", slot) |
if enabled == 1 and duration > 0 then |
local _,_,name = GetInventoryItemLink("player", slot):find("%|h%[(.-)%]%|h") |
if duration > db.min and duration <= db.max then |
local icon = GetInventoryItemTexture("player", slot) |
startBar(name, start, duration, icon, true) |
end |
end |
end |
end |
end |
function Heatsink:ScanPlayer() |
self.player = self.player or {} |
wipe(self.player) |
local id |
for i = 1, GetNumSpellTabs() do |
local tab, texture, offset, numSpells = GetSpellTabInfo(i) |
for j = 1, numSpells do |
id = j + offset |
local name, rank, icon = GetSpellInfo(id, BOOKTYPE_SPELL) |
for f in pairs(self.notooltip) do |
if name == f then |
self.player[name] = { |
id = id, |
icon = icon, |
} |
end |
end |
if not self.player[name] then |
self.tooltip:SetSpell(id, BOOKTYPE_SPELL) |
for i = 1, Heatsink.tooltip:NumLines() do |
local line = Heatsink.tooltip.R[i] |
if line and line:find(L["cooldown$"]) then |
self.player[name] = { |
id = id, |
icon = icon, |
} |
if self.school[class] and self.player[name] then |
local school = self.school[class][name] |
if school then |
self.player[name].schoolname = school |
end |
end |
end |
end |
end |
end |
end |
self:SPELL_UPDATE_COOLDOWN() |
end |
function Heatsink:ScanPet() |
self.pet = self.pet or {} |
wipe(self.pet) |
local id = 1 |
local previous |
local name, rank, icon = GetSpellInfo(id, BOOKTYPE_PET) |
while name do |
if name ~= previous then |
self.tooltip:SetSpell(id, BOOKTYPE_PET) |
for i = 1, self.tooltip:NumLines() do |
local line = self.tooltip.R[i] or "" |
if line:find(L["cooldown$"]) then |
self.pet[name] = { |
id = id, |
icon = icon, |
} |
break |
end |
end |
end |
id = id + 1 |
previous = name |
name, rank, icon = GetSpellInfo(id, BOOKTYPE_PET) |
end |
self:PET_BAR_UPDATE_COOLDOWN() |
end |
local _G = getfenv(0) |
local LibStub = _G.LibStub |
local debug = false |
--@debug@ |
debug = true |
--@end-debug@ |
local L = LibStub("AceLocale-3.0"):NewLocale("Heatsink", "enUS", true, debug) |
--@localization(locale="enUS", format="lua_additive_table", same-key-is-true=true, handle-unlocalized="english")@ |
local _G = getfenv(0) |
local LibStub = _G.LibStub |
local Heatsink = LibStub("AceAddon-3.0"):GetAddon("Heatsink", "AceEvent-3.0", "AceTimer-3.0") |
local L = LibStub:GetLibrary("AceLocale-3.0"):GetLocale("Heatsink") |
local GetSpellInfo = _G.GetSpellInfo |
local pairs = _G.pairs |
local FIRE = L["%s School"]:format(_G.STRING_SCHOOL_FIRE) |
local SHADOW = L["%s School"]:format(_G.STRING_SCHOOL_SHADOW) |
local FROST = L["%s School"]:format(_G.STRING_SCHOOL_FROST) |
local HOLY = L["%s School"]:format(_G.STRING_SCHOOL_HOLY) |
local NATURE = L["%s School"]:format(_G.STRING_SCHOOL_NATURE) |
local ARCANE = L["%s School"]:format(_G.STRING_SCHOOL_ARCANE) |
local PHYSICAL = L["%s School"]:format(_G.STRING_SCHOOL_PHYSICAL) |
local slots = { "Trinket0Slot", |
"Trinket1Slot", |
"Finger0Slot", |
"Finger1Slot", |
"HeadSlot" |
} |
local spellsub = { |
[(GetSpellInfo(1499))] = L["Traps"], -- 1499 Freezing Trap |
[(GetSpellInfo(13795))] = L["Traps"], -- 13795 Immolation Trap |
[(GetSpellInfo(13809))] = L["Traps"], -- 13909 Immolation Trap |
[(GetSpellInfo(13813))] = L["Traps"], -- 13813 Explosive Trap |
[(GetSpellInfo(34600))] = L["Traps"], -- 34600 Snake Trap |
[(GetSpellInfo(8042))] = L["Shocks"], -- 8042 Earth Shock |
[(GetSpellInfo(8056))] = L["Shocks"], -- 8056 Frost Shock |
[(GetSpellInfo(8050))] = L["Shocks"], -- 8050 Flame Shock |
[(GetSpellInfo(53408))] = L["Judgement"], -- Judgement of Wisdom |
[(GetSpellInfo(20271))] = L["Judgement"], -- Judgement of Light |
[(GetSpellInfo(53407))] = L["Judgement"], -- Judgement of Justice |
[(GetSpellInfo(16979))] = (GetSpellInfo(49377)), -- 16979 Feral Charge - Bear, 49377 Feral Charge (Talent) |
[(GetSpellInfo(49376))] = (GetSpellInfo(49377)), -- 16979 Feral Charge - Cat, 49377 Feral Charge (Talent) |
} |
local itemsub = { |
-- items |
[L["Mana Jade"]] = L["Stones"], |
[L["Mana Ruby"]] = L["Stones"], |
[L["Mana Citrine"]] = L["Stones"], |
[L["Mana Agate"]] = L["Stones"], |
[L["Mana Emerald"]] = L["Stones"], |
[L["Healthstone$"]] = L["Stones"], |
[L["Potion"]] = L["Potions"], |
[L["Injector"]] = L["Potions"], |
[L["Blue Ogre Brew Special"]]= L["Potions"], --Ogri'la |
[L["Red Ogre Brew Special"]] = L["Potions"], --Ogri'la |
[L["Blue Ogre Brew"]]= L["Potions"], --Ogri'la |
[L["Red Ogre Brew"]] = L["Potions"], --Ogri'la |
[L["Bottled Nethergon Energy"]] = L["Potions"], --Tempest Keep |
[L["Bottled Nethergon Vapor"]] = L["Potions"], --Tempest Keep |
[L["Cenarion Mana Salve"]] = L["Potions"], --Cenarion Expedition |
[L["Cenarion Healing Salve"]] = L["Potions"], --enarion Expedition |
[L["Major Healing Draught"]] = L["Potions"], --PvP |
[L["Major Mana Draught"]] = L["Potions"], --PvP |
[L["Superior Mana Draught"]] = L["Potions"], --PvP |
[L["Superior Healing Draught"]] = L["Potions"], --PvP |
[L["Noth's Special Brew"]] = L["Potions"], -- Deathknight Starting Area |
} |
local schoolspell = { |
["WARLOCK"] = { |
[SHADOW] = 686, -- 686 Shadow Bolt |
[FIRE] = 5676, -- 5676 Searing Pain |
}, |
["MAGE"] = { |
[ARCANE] = 5143, -- 5343 Arcane Missiles |
[FIRE] = 133, -- 133 Fireball |
[FROST] = 116, -- 116 Frostbolt |
}, |
["DRUID"] = { |
[NATURE] = 5185, -- 5185 Healing Touch |
}, |
["SHAMAN"] = { |
[NATURE] = 403, -- 403 Lightning Bolt |
[FIRE] = 8024, -- 8024 Flametongue Weapon |
[FROST] = 8033, -- 8033 Frostbrand Weapon |
[PHYSICAL] = 8071, -- 8071 Stoneskin Totem |
}, |
["PRIEST"] = { |
[HOLY] = 585, --585 Smite |
[SHADOW] = 589, -- 589 Shadow Word: Pain |
}, |
["PALADIN"] = { |
[HOLY] = 635, -- 635 Holy Light |
}, |
} |
local school = { |
["WARLOCK"] = { |
[(GetSpellInfo(603))] = SHADOW, -- 603 Curse of Doom |
[(GetSpellInfo(698))] = SHADOW, -- 698 Ritual of Summoning |
[(GetSpellInfo(1122))] = SHADOW, -- 1122 Inferno |
[(GetSpellInfo(5484))] = SHADOW, -- 5484 Howl of Terror |
[(GetSpellInfo(6229))] = SHADOW, -- 6229 Shadow Ward |
[(GetSpellInfo(6789))] = SHADOW, -- 6789 Death Coil |
[(GetSpellInfo(17877))] = SHADOW, -- 17877 Shadowburn |
[(GetSpellInfo(18708))] = SHADOW, -- 18708 Fel Domination |
[(GetSpellInfo(18540))] = SHADOW, -- 18540 Ritual of Doom |
[(GetSpellInfo(29858))] = SHADOW, -- 29858 Soulshatter |
[(GetSpellInfo(29893))] = SHADOW, -- 29893 Ritual of Souls |
[(GetSpellInfo(47897))] = SHADOW, -- 47897 Shadowflame |
[(GetSpellInfo(48020))] = SHADOW, -- 48020 Demonic Circle: Teleport |
[(GetSpellInfo(48181))] = SHADOW, -- 48181 Haunt |
[(GetSpellInfo(50796))] = FIRE, -- 50796 Chaos Bolt |
[(GetSpellInfo(17962))] = FIRE, -- 17962 Conflagrate |
}, |
["MAGE"] = { |
[(GetSpellInfo(66))] = ARCANE, -- 66 Invisibility |
[(GetSpellInfo(1953))] = ARCANE, -- 1953 Blink |
[(GetSpellInfo(2139))] = ARCANE, -- 2139 Counterspell |
[(GetSpellInfo(10059))] = ARCANE, -- 10059 Portal: Stormwind |
[(GetSpellInfo(11416))] = ARCANE, -- 11416 Portal: Ironforge |
[(GetSpellInfo(11417))] = ARCANE, -- 11417 Portal: Orgrimmar |
[(GetSpellInfo(11418))] = ARCANE, -- 11418 Portal: Undercity |
[(GetSpellInfo(11419))] = ARCANE, -- 11419 Portal: Darnassus |
[(GetSpellInfo(11420))] = ARCANE, -- 11420 Portal: Thunder Bluff |
[(GetSpellInfo(12042))] = ARCANE, -- 12042 Arcane Power |
[(GetSpellInfo(12043))] = ARCANE, -- 12043 Presence of Mind |
[(GetSpellInfo(12051))] = ARCANE, -- 12051 Evocation |
[(GetSpellInfo(32266))] = ARCANE, -- 32266 Portal: Exodar |
[(GetSpellInfo(32267))] = ARCANE, -- 32267 Portal: Silvermoon |
[(GetSpellInfo(33691))] = ARCANE, -- 33691 Portal: Shattrath |
[(GetSpellInfo(543))] = FIRE, -- 543 Fire Ward |
[(GetSpellInfo(1831))] = FIRE, -- 1831 Blast Wave |
[(GetSpellInfo(2136))] = FIRE, -- 2136 Fire Blast |
[(GetSpellInfo(31661))] = FIRE, -- 31661 Dragon's Breath |
[(GetSpellInfo(120))] = FROST, -- 120 Cone of Cold |
[(GetSpellInfo(122))] = FROST, -- 122 Frost Nova |
[(GetSpellInfo(6143))] = FROST, -- 6143 Frost Ward |
[(GetSpellInfo(11426))] = FROST, -- 11426 Ice Barrier |
[(GetSpellInfo(11958))] = FROST, -- 11958 Cold Snap |
[(GetSpellInfo(12472))] = FROST, -- 12472 Icy Veins |
[(GetSpellInfo(31687))] = FROST, -- 31687 Summon Water Elemental |
[(GetSpellInfo(45438))] = FROST, -- 45438 Ice Block |
[(GetSpellInfo(44572))] = FROST, -- 44572 Deep Freeze |
}, |
["DRUID"] = { |
[(GetSpellInfo(740))] = NATURE, -- 740 Tranquility |
[(GetSpellInfo(29166))] = NATURE, -- 29166 Innervate |
[(GetSpellInfo(20484))] = NATURE, -- 20484 Rebirth |
[(GetSpellInfo(16857))] = NATURE, -- 16857 Faerie Fire (Feral) |
[(GetSpellInfo(22812))] = NATURE, -- 22812 Barkskin |
[(GetSpellInfo(16689))] = NATURE, -- 16689 Nature's Grasp |
[(GetSpellInfo(16914))] = NATURE, -- 16914 Hurricane |
}, |
["SHAMAN"] = { |
[(GetSpellInfo(421))] = NATURE, -- 421 Chain Lightning |
[(GetSpellInfo(556))] = NATURE, -- 556 Astral Recall |
[(GetSpellInfo(2062))] = NATURE, -- 2062 Earth Elemental Totem |
[(GetSpellInfo(2484))] = NATURE, -- 2484 Earthbind Totem |
[(GetSpellInfo(2825))] = NATURE, -- 2825 Bloodlust |
[(GetSpellInfo(5730))] = NATURE, -- 5730 Stoneclaw Totem |
[(GetSpellInfo(8042))] = NATURE, -- 8042 Earth Shock |
[(GetSpellInfo(8177))] = NATURE, -- 8177 Grounding Totem |
[(GetSpellInfo(16166))] = NATURE, -- 16166 Elemental Mastery |
[(GetSpellInfo(32182))] = NATURE, -- 32182 Heroism |
[(GetSpellInfo(2894))] = FIRE, -- 2894 Fire Elemental Totem |
[(GetSpellInfo(1535))] = FIRE, -- 1535 Fire Nova Totem |
[(GetSpellInfo(8050))] = FIRE, -- 8050 Flame Shock |
[(GetSpellInfo(8056))] = FROST, -- 8056 Frost Shock |
[(GetSpellInfo(16190))] = FROST, -- 16190 Mana Tide Totem |
[(GetSpellInfo(16188))] = PHYSICAL, -- 16188 Nature's Swiftness |
[(GetSpellInfo(17364))] = PHYSICAL, -- 17364 Stormstrike |
}, |
["PRIEST"] = { |
[(GetSpellInfo(586))] = SHADOW, -- 586 Fade |
[(GetSpellInfo(8092))] = SHADOW, -- 8092 Mind Blast |
[(GetSpellInfo(32379))] = SHADOW, -- 32379 Shadow Word: Death |
[(GetSpellInfo(15407))] = SHADOW, -- 15407 Mind Flay |
[(GetSpellInfo(34433))] = SHADOW, -- 34433 Shadowfiend |
[(GetSpellInfo(19238))] = HOLY, -- 19238 Desperate Prayer |
[(GetSpellInfo(15263))] = HOLY, -- 15263 Holy Fire |
[(GetSpellInfo(27870))] = HOLY, -- 27870 Lightwell |
[(GetSpellInfo(33076))] = HOLY, -- 33076 Prayer of Mending |
[(GetSpellInfo(34863))] = HOLY, -- 34863 Circle of Healing |
[(GetSpellInfo(47540))] = HOLY, -- 47540 Penance |
[(GetSpellInfo(64843))] = HOLY, -- 64843 Divine Hymn |
[(GetSpellInfo(64901))] = HOLY, -- 64901 Hymn of Hope |
}, |
["PALADIN"] = { |
[(GetSpellInfo(498))] = HOLY, -- 498 Divine Protection |
[(GetSpellInfo(633))] = HOLY, -- 633 Lay on Hands |
[(GetSpellInfo(642))] = HOLY, -- 642 Divine Shield |
[(GetSpellInfo(853))] = HOLY, -- 853 Hammer of Justice |
[(GetSpellInfo(879))] = HOLY, -- 879 Exorcism |
[(GetSpellInfo(2812))] = HOLY, -- 2812 Holy Wrath |
[(GetSpellInfo(10326))] = HOLY, -- 10326 Turn Evil |
[(GetSpellInfo(19752))] = HOLY, -- 19752 Divine Intervention |
[(GetSpellInfo(20216))] = HOLY, -- 20216 Divine Favor |
[(GetSpellInfo(20473))] = HOLY, -- 20473 Holy Shock |
[(GetSpellInfo(20271))] = HOLY, -- 20271 Judgement of Light |
[(GetSpellInfo(24275))] = HOLY, -- 24275 Hammer of Wrath |
[(GetSpellInfo(26573))] = HOLY, -- 26573 Consecration |
[(GetSpellInfo(31789))] = HOLY, -- 31789 Righteous Defense |
[(GetSpellInfo(31842))] = HOLY, -- 31842 Divine Illumination |
[(GetSpellInfo(31884))] = HOLY, -- 31884 Avenging Wrath |
}, |
} |
local whitelist = { |
[(GetSpellInfo(47528))] = true, |
} |
local notooltip = { |
[(GetSpellInfo(20608))] = true, |
} |
Heatsink.slots = Heatsink.slots or {} |
for k,v in pairs(slots) do |
Heatsink.slots[k] = v |
end |
Heatsink.spellsub = Heatsink.spellsub or {} |
for k,v in pairs(spellsub) do |
Heatsink.spellsub[k] = v |
end |
Heatsink.itemsub = Heatsink.itemsub or {} |
for k,v in pairs(itemsub) do |
Heatsink.itemsub[k] = v |
end |
Heatsink.schoolspell = Heatsink.schoolspell or {} |
Heatsink.lockout = Heatsink.lockout or {} |
for k,v in pairs(schoolspell) do |
Heatsink.schoolspell[k] = v |
for i in pairs(v) do |
Heatsink.lockout[i] = false |
end |
end |
Heatsink.school = Heatsink.school or {} |
for k,v in pairs(school) do |
Heatsink.school[k] = v |
end |
Heatsink.whitelist = Heatsink.whitelist or {} |
for k,v in pairs(whitelist) do |
Heatsink.whitelist[k] = v |
end |
Heatsink.notooltip = Heatsink.notooltip or {} |
for k,v in pairs(notooltip) do |
Heatsink.notooltip[k] = v |
end |
## Interface: 30300 |
## Title: Heatsink |
## Notes: Cooldown tracker with bar display |
## Author: durcyn |
## X-Credits: Evl for the original Hourglass, Nirek & Mist for their enhancements, Rabbit and Ammo for LCB-3, Antiarc for LibICD. |
## SavedVariables: HeatsinkDB |
## OptionalDeps: Ace3, AceGUI-3.0-SharedMediaWidgets, LibCandyBar-3.0, LibSharedMedia-3.0, LibInternalCooldowns-1.0 |
#@no-lib-strip@ |
libs\LibStub\LibStub.lua |
libs\CallbackHandler-1.0\CallbackHandler-1.0.xml |
libs\AceAddon-3.0\AceAddon-3.0.xml |
libs\AceGUI-3.0\AceGUI-3.0.xml |
libs\AceConfig-3.0\AceConfig-3.0.xml |
libs\AceDB-3.0\AceDB-3.0.xml |
libs\AceDBOptions-3.0\AceDBOptions-3.0.xml |
libs\AceConsole-3.0\AceConsole-3.0.xml |
libs\AceEvent-3.0\AceEvent-3.0.xml |
libs\AceBucket-3.0\AceBucket-3.0.xml |
libs\AceLocale-3.0\AceLocale-3.0.xml |
libs\LibSharedMedia-3.0\lib.xml |
libs\AceGUI-3.0-SharedMediaWidgets\widget.xml |
libs\LibCandyBar-3.0\bars.lua |
libs\LibInternalCooldowns-1.0\lib.xml |
#@end-no-lib-strip@ |
locale-enUS.lua |
Heatsink.lua |
Config.lua |
Data.lua |
TinyGratuity.lua |
local _G = getfenv(0) |
local LibStub = _G.LibStub |
local pairs = _G.pairs |
local setmetatable = _G.setmetatable |
local Heatsink = LibStub("AceAddon-3.0"):GetAddon("Heatsink") |
Heatsink.tooltip = _G.CreateFrame("GameTooltip") |
Heatsink.tooltip:SetOwner(_G.WorldFrame, "ANCHOR_NONE") |
local tooltip = Heatsink.tooltip |
local lcache, rcache = {}, {} |
for i=1,30 do |
lcache[i] = tooltip:CreateFontString() |
rcache[i] = tooltip:CreateFontString() |
lcache[i]:SetFontObject(_G.GameFontNormal) |
rcache[i]:SetFontObject(_G.GameFontNormal) |
tooltip:AddFontStrings(lcache[i], rcache[i]) |
end |
-- GetText cache tables, provide fast access to the tooltip's text |
tooltip.R = setmetatable({}, { |
__index = function(t, key) |
if tooltip:NumLines() >= key and rcache[key] then |
local v = rcache[key]:GetText() |
t[key] = v |
return v |
end |
return nil |
end, |
}) |
local orig = tooltip.SetSpell |
tooltip.SetSpell = function(self, ...) |
self:ClearLines() -- Ensures tooltip's NumLines is reset |
for i in pairs(self.R) do self.R[i] = nil end -- Flush the metatable cache |
if not self:IsOwned(_G.WorldFrame) then self:SetOwner(_G.WorldFrame, "ANCHOR_NONE") end |
return orig(self, ...) |
end |