-- TODO: save/restore skill filters if window is opened |
|
local f = CreateFrame("Frame", "AraSkills", UIParent) |
local g = CreateFrame("Frame", nil, UIParent) |
local e = CreateFrame"Frame" |
local dropdown = CreateFrame("Frame", "AraSkillsDD", nil, "UIDropDownMenuTemplate") |
local dropdown_init, tipShown, nbEntries, Block_OnEnter |
|
local config, realm, options, c |
local playerName, realmName = GetUnitName"player", GetRealmName() |
local CDs, shortcuts, workingFrame, prevAltSkill |
|
local BUTTON_HEIGHT, ICON_SIZE, GAP, TEXT_OFFSET = 17, 15, 10, 4 |
local PANEL, PROFESSION, COMBAT_SKILL, LINK, SECONDARY, SPELL_ID = 1, 2, 4, 8, 16, 256 |
|
local L = setmetatable( _G.ABTS_T or {}, { __index = function(t,k) return k end, __call = function(t,k) return t[k] end } ) |
|
local bit_band, date, format, strmatch, tonumber, wipe, ipairs, tremove, GetSkillLineInfo, GetSpellInfo, GetTradeSkillInfo, GetTradeSkillRecipeLink, tip = |
bit.band, date, format, strmatch, tonumber, wipe, ipairs, tremove, GetSkillLineInfo, GetSpellInfo, GetTradeSkillInfo, GetTradeSkillRecipeLink |
|
local skills = { |
[L.Alchemy]= PROFESSION + 2259*SPELL_ID + PANEL + LINK, |
[L.Blacksmithing]= PROFESSION + 2018*SPELL_ID + PANEL + LINK, |
[L.Cooking]= PROFESSION + 2550*SPELL_ID + PANEL + LINK + SECONDARY, -- campfire |
[L.Enchanting]= PROFESSION + 7411*SPELL_ID + PANEL + LINK, -- d/e |
[L.Engineering]= PROFESSION + 4036*SPELL_ID + PANEL + LINK, |
[L"First Aid"]= PROFESSION + 3273*SPELL_ID + PANEL + LINK + SECONDARY, |
[L.Fishing]= PROFESSION + 7620*SPELL_ID + SECONDARY, |
[L.Herbalism]= PROFESSION + 2366*SPELL_ID, -- track herbs |
[L.Inscription]= PROFESSION + 45357*SPELL_ID + PANEL + LINK, -- mill |
[L.Jewelcrafting]= PROFESSION + 25229*SPELL_ID + PANEL + LINK, -- prospect |
[L.Leatherworking]= PROFESSION + 2108*SPELL_ID + PANEL + LINK, |
[L.Lockpicking]= PROFESSION + 1804*SPELL_ID + SECONDARY, |
[L.Runeforging]= PROFESSION + 53428*SPELL_ID + PANEL + SECONDARY, |
[L.Skinning]= PROFESSION + 8613*SPELL_ID, |
[L.Smelting]= PROFESSION + 2580*SPELL_ID + PANEL, -- track minerals (icons: 2575=mining, 2580=smelting) |
[L.Tailoring]= PROFESSION + 3908*SPELL_ID + PANEL + LINK, |
[L.Axes]= COMBAT_SKILL, |
[L.Bows]= COMBAT_SKILL, |
[L.Crossbows]= COMBAT_SKILL, |
[L.Daggers]= COMBAT_SKILL, |
[L.Defense]= COMBAT_SKILL, |
[L.Guns]= COMBAT_SKILL, |
[L.Maces]= COMBAT_SKILL, |
[L.Polearms]= COMBAT_SKILL, |
[L.Staves]= COMBAT_SKILL, |
[L.Swords]= COMBAT_SKILL, |
[L.Thrown]= COMBAT_SKILL, |
[L"Two-Handed Swords"]= COMBAT_SKILL, |
[L"Two-Handed Axes"]= COMBAT_SKILL, |
[L"Two-Handed Maces"]= COMBAT_SKILL, |
[L.Unarmed]= COMBAT_SKILL, |
[L.Wands]= COMBAT_SKILL, |
None = 0 |
} |
local altNames = { |
[L.Mining] = L.Smelting, |
[L.RuneforgingDN] = L.Runeforging, |
} |
local altIcons = { |
[L.Axes]= "Interface\\Icons\\INV_Axe_44", |
[L.Bows]= "Interface\\Icons\\INV_Weapon_Bow_05", |
[L.Crossbows]= "Interface\\Icons\\INV_Weapon_Crossbow_01", |
[L.Daggers]= "Interface\\Icons\\Ability_SteelMelee", |
[L.Defense]= "Interface\\Icons\\INV_Shield_09", |
[L.Guns]= "Interface\\Icons\\INV_Weapon_Rifle_01", |
[L.Maces]= "Interface\\Icons\\INV_Mace_04", |
[L.Polearms]= "Interface\\Icons\\INV_Spear_06", |
[L.Staves]= "Interface\\Icons\\INV_Staff_08", |
[L.Swords]= "Interface\\Icons\\INV_Sword_14", |
[L.Thrown]= "Interface\\Icons\\Ability_Throw", |
[L"Two-Handed Axes"]= "Interface\\Icons\\INV_Axe_09", |
[L"Two-Handed Maces"]= "Interface\\Icons\\INV_Hammer_16", |
[L"Two-Handed Swords"]= "Interface\\Icons\\INV_Sword_27", |
[L.Unarmed]= "Interface\\Icons\\Ability_Warrior_SecondWind", |
[L.Wands]= "Interface\\Icons\\INV_Wand_05", |
} |
local groupIcons = { |
["Transmutes"] = "Interface\\Icons\\Spell_Nature_ElementalPrecision_2" |
} |
|
local HOUR, DAY = 3600, 86400 |
local TRANSMUTE_G1 = { skill= L.Alchemy, CD=20*HOUR, group= "Transmutes" } |
|
local watchedCDs = { |
[11479]= TRANSMUTE_G1, -- Iron to Gold |
[11480]= TRANSMUTE_G1, -- Mithril to Truesilver |
[60350]= TRANSMUTE_G1, -- Titanium |
[17559]= TRANSMUTE_G1, -- Air to Fire |
[17566]= TRANSMUTE_G1, -- Earth to Life |
[17561]= TRANSMUTE_G1, -- Earth to Water |
[17560]= TRANSMUTE_G1, -- Fire to Earth |
[17565]= TRANSMUTE_G1, -- Life to Earth |
[17563]= TRANSMUTE_G1, -- Undeath to Earth |
[17562]= TRANSMUTE_G1, -- Water to Air |
[17564]= TRANSMUTE_G1, -- Water to Undeath |
[28566]= TRANSMUTE_G1, -- Primal Air to Fire |
[28585]= TRANSMUTE_G1, -- Primal Earth to Life |
[28567]= TRANSMUTE_G1, -- Primal Earth to Water |
[28568]= TRANSMUTE_G1, -- Primal Fire to Earth |
[28583]= TRANSMUTE_G1, -- Primal Fire to Mana |
[28584]= TRANSMUTE_G1, -- Primal Life to Earth |
[28582]= TRANSMUTE_G1, -- Primal Mana to Fire |
[28580]= TRANSMUTE_G1, -- Primal Shadow to Water |
[28569]= TRANSMUTE_G1, -- Primal Water to Air |
[28581]= TRANSMUTE_G1, -- Primal Water to Shadow |
[53777]= TRANSMUTE_G1, -- Eternal Air to Earth |
[52776]= TRANSMUTE_G1, -- Eternal Air to Water |
[53781]= TRANSMUTE_G1, -- Eternal Earth to Air |
[53782]= TRANSMUTE_G1, -- Eternal Earth to Shadow |
[53775]= TRANSMUTE_G1, -- Eternal Fire to Life |
[53774]= TRANSMUTE_G1, -- Eternal Fire to Water |
[53773]= TRANSMUTE_G1, -- Eternal Life to Fire |
[53771]= TRANSMUTE_G1, -- Eternal Life to Shadow |
[54020]= TRANSMUTE_G1, -- Eternal Might |
[53779]= TRANSMUTE_G1, -- Eternal Shadow to Earth |
[52780]= TRANSMUTE_G1, -- Eternal Shadow to Life |
[53783]= TRANSMUTE_G1, -- Eternal Water to Air |
[53784]= TRANSMUTE_G1, -- Eternal Water to Fire |
[28027]= { skill= L.Enchanting, CD= 2*DAY }, -- Prismatic Sphere |
[28028]= { skill= L.Enchanting, CD= 2*DAY }, -- Void Sphere |
[47280]= { skill= L.Jewelcrafting, CD= 20*HOUR }, -- Brilliant Glass |
[62242]= { skill= L.Jewelcrafting, CD= 20*HOUR }, -- Icy Prism -- NEW 3.0.8 |
[26751]= { skill= L.Tailoring, CD= 3*DAY+20*HOUR }, -- Primal Mooncloth |
[36686]= { skill= L.Tailoring, CD= 3*DAY+20*HOUR }, -- Shadowcloth |
[31373]= { skill= L.Tailoring, CD= 3*DAY+20*HOUR }, -- Spellcloth |
[56002]= { skill= L.Tailoring, CD= 3*DAY+20*HOUR }, -- Ebonweave |
[56003]= { skill= L.Tailoring, CD= 3*DAY+20*HOUR }, -- Spellweave |
[56001]= { skill= L.Tailoring, CD= 3*DAY+20*HOUR }, -- Moonshroud |
[61288]= { skill= L.Inscription, CD= 20*HOUR }, -- Minor Glyph RS |
[61177]= { skill= L.Inscription, CD= 20*HOUR }, -- Major Glyph RS |
[55208]= { skill= L.Smelting, CD= 20*HOUR }, -- Smelt Titansteel |
[60893]= { skill= L.Alchemy, CD= 2*DAY+20*HOUR }, -- Alchemy Research |
} |
|
local watchedIndex, watchedSpell, watchedID, watchedIcon |
local orgDoTradeSkill = _G.DoTradeSkill |
|
function DoTradeSkill(index, ...) |
watchedID = tonumber( strmatch( GetTradeSkillRecipeLink(index), "enchant:(%d+)" ) ) |
if watchedCDs[watchedID] then |
watchedIndex, watchedSpell, watchedIcon = index, GetTradeSkillInfo(index), GetTradeSkillIcon(index) |
f:RegisterEvent"UNIT_SPELLCAST_SUCCEEDED" |
f:RegisterEvent"UNIT_SPELLCAST_STOP" |
end |
return orgDoTradeSkill(index, ...) |
end |
|
function f:UNIT_SPELLCAST_STOP(event, unit, spell) |
if unit ~= "player" or spell ~= watchedSpell then return end |
self:UnregisterEvent"UNIT_SPELLCAST_SUCCEEDED" |
self:UnregisterEvent"UNIT_SPELLCAST_STOP" |
if event ~= "UNIT_SPELLCAST_SUCCEEDED" then return end |
local cd = watchedCDs[watchedID] |
char[watchedID] = time() + cd.CD |
if cd.group then config.names[cd.group] = watchedID end |
config.icons[cd.group or watchedID] = watchedIcon |
if config.displayCDs then e.timer = 0 end |
if tipShown then Block_OnEnter(tipShown) end |
end |
f.UNIT_SPELLCAST_SUCCEEDED = f.UNIT_SPELLCAST_STOP |
|
|
local tables = {} |
|
local function new(...) |
local t = tremove(tables) or {} |
for i = 1, select("#", ...), 2 do |
local k, v = select(i, ...) |
t[k] = v |
end |
return t |
end |
|
local function del(t) |
tables[#tables+1] = wipe(t) |
end |
|
|
local md, mx, xx, dd = 20*HOUR, 3*DAY+20*HOUR, { 86400, 3600, 60, 1 }, { L.d, L.h, L.m, L.s } |
local function SecondsToTime(s) |
local p = s<md and s/md*.5 or s<mx and (s-md)/(mx-md)*.5+.5 or 1 |
local i = s>=86400 and 1 or s>=3600 and 2 or 3 |
return format( "|cff%.2x%.2x40%i%s %.2i%s|r", |
p<.5 and 64+p*382 or 255, p<.5 and 255 or 446-p*382, |
floor(s/xx[i]), dd[i], floor((s%xx[i])/xx[i+1]), dd[i+1] ) |
end |
|
local function ColorCurMax(cur,max,isProfession) |
local pMax = isProfession and min(max/450,1) or 1 |
local pCur = isProfession and 1-min(sqrt(max-cur)/10,1) or 2/sqrt(max-cur+4) |
return format( "|cff%.2x%.2x00%.3i|r / |cff%.2x%.2x00%.3i|r", |
pCur<.5 and 255 or 510-pCur*510, pCur<.5 and pCur*510 or 255, cur, |
pMax<.5 and 255 or 510-pMax*510, pMax<.5 and pMax*510 or 255, max ) |
end |
|
local function SortSkills(a, b) |
if not a.isProfession == not b.isProfession then |
if a.primary == b.primary then |
return a.displayName < b.displayName |
else return a.primary |
end |
else return a.isProfession end |
end |
|
local function SortCooldowns(a, b) |
if a.group and a.group == b.group then |
return a.timeLeft > b.timeLeft |
else return a.name < b.name end |
end |
|
local function SortShortcuts(a, b) |
if a.skill == b.skill then |
return a.name < b.name |
else return a.skill < b.skill end |
end |
|
local function SortAltSkills(a, b) |
local primA = bit_band( skills[a], SECONDARY ) == 0 |
local primB = bit_band( skills[b], SECONDARY ) == 0 |
if primA == primB then |
return a < b |
else return primA end |
end |
|
local function SortAlts(a, b) |
return a.name < b.name |
end |
|
|
local function UpdateText() |
f.block.icon = select(3, GetSpellInfo(char.skill or 0)) or "Interface\\Icons\\Achievement_Halloween_Witch_01" |
if not config.displayCDs then f.block.text = " " .. (char.skill or _G.TRADESKILLS) end |
end |
|
local orgAbandonSkill = _G.AbandonSkill |
function AbandonSkill(...) |
if char.skill == GetSkillLineInfo(...) then char.skill=nil UpdateText() end |
return orgAbandonSkill(...) |
end |
|
local function CreateHL(frame) |
local hl = frame:CreateTexture() |
hl:SetTexture"Interface\\QuestFrame\\UI-QuestLogTitleHighlight" |
hl:SetBlendMode"ADD" |
hl:SetAlpha(0) |
return hl |
end |
local highlight = CreateHL(f) |
local altLight = CreateHL(g) |
|
|
local function Tradeskill_OnClick(button, click) |
if IsShiftKeyDown() and bit_band( skills[button.skill], LINK ) > 0 then |
f.getLink = true |
if TradeSkillFrame and TradeSkillFrame:IsShown() then |
f.keepOpen = true |
CloseTradeSkill() |
end |
f:RegisterEvent"TRADE_SKILL_SHOW" |
elseif click == "RightButton" then |
f.learnCD = true |
if TradeSkillFrame and TradeSkillFrame:IsShown() then |
f.keepOpen = true |
CloseTradeSkill() |
end |
f:RegisterEvent"TRADE_SKILL_SHOW" |
elseif click == "MiddleButton" then |
char.show[button.skill] = not char.show[button.skill] |
return Block_OnEnter(tipShown) |
elseif bit_band( skills[button.skill], PANEL ) > 0 then |
char.skill = button.skill |
UpdateText() |
button.fontLeft:SetTextColor(unpack(config.colors.selected)) |
if f.selected and f.selected ~= button then f.selected.fontLeft:SetTextColor(unpack(config.colors.activeName)) end |
f.selected = button |
else return end |
CastSpellByName(button.skill) |
end |
|
local function Cooldown_OnClick(button, click) |
local group = watchedCDs[button.spellID].group |
if click == "MiddleButton" then |
local char = realm[button.owner] |
if group then -- remove group |
for k, v in next, watchedCDs do |
if v.group == group then char[k] = nil end |
end |
else |
char[button.spellID] = nil |
end |
Block_OnEnter(tipShown) |
elseif click == "LeftButton" and IsControlKeyDown() then |
f.alias, f.aliasID = button.fontLeft:GetText(), group or button.spellID |
StaticPopup_Show("SET_ALIAS", config.names[button.spellID] or group) |
else |
f.doTradeSkill = click == "LeftButton" and not IsModifierKeyDown() |
f.searchedSpellID = button.spellID |
if TradeSkillFrame and TradeSkillFrame:IsShown() then CloseTradeSkill() end |
f:RegisterEvent"TRADE_SKILL_SHOW" |
CastSpellByName(button.skill) |
end |
end |
|
local function Shortcut_OnClick(button, click) |
if IsControlKeyDown() then |
f.alias, f.aliasID = button.fontLeft:GetText(), button.spellID |
StaticPopup_Show("SET_ALIAS", config.names[button.spellID]) |
elseif click == "MiddleButton" then |
char.shortcuts[button.spellID] = nil |
Block_OnEnter(tipshown) |
else |
f.doTradeSkill = click == "LeftButton" and not IsModifierKeyDown() |
f.searchedSpellID = button.spellID |
f.shortcut = true |
if TradeSkillFrame and TradeSkillFrame:IsShown() then CloseTradeSkill() end |
f:RegisterEvent"TRADE_SKILL_SHOW" |
CastSpellByName(button.skill) |
end |
end |
|
local function Link_OnClick(button, click) |
if not button.link then return end |
if IsModifierKeyDown() then |
if not ChatEdit_InsertLink(button.link) then |
ChatFrameEditBox:Show() |
ChatEdit_InsertLink(button.link) |
end |
elseif click == "LeftButton" then |
if button.skill == prevAltSkill and TradeSkillFrame and TradeSkillFrame:IsShown() then |
return CloseTradeSkill() |
end |
prevAltSkill = button.skill |
SetItemRef(button.link:match"|H([^|]+)") |
end |
end |
|
local function ProfessionsBook_OnClick() |
ProfessionsBook:ShowFrame() |
end |
|
|
local function Alt_OnEnter(self) |
if self and self.light then |
altLight:SetAllPoints(self) |
altLight:SetAlpha(1) |
|
if config.hideTips then return end |
local hasLink = bit_band( skills[self.skill], LINK ) > 0 |
if not( self.link or hasLink ) then return end |
|
tip:SetOwner(g, "ANCHOR_NONE") |
local showRight = f:GetCenter() > UIParent:GetWidth()/2 and "RIGHT" or "LEFT" |
local showBelow = select(2, g:GetCenter()) > UIParent:GetHeight()/2 and "TOP" or "BOTTOM" |
tip:SetPoint(showBelow..showRight, g, (showBelow == "TOP" and "BOTTOM" or "TOP")..showRight ) |
|
tip:AddLine(L.Hints) |
if self.link then |
tip:AddLine(L"|cffff8020Click|r to toggle panel.", .2,1,.2) |
tip:AddLine(L"|cffff8020Shift+Click|r to link in chat.", .2,1,.2) |
elseif hasLink then |
tip:AddLine(L"No link available. Open a character\ntradeskill panel to be able to access\nit from your other characters.", 1, .6, .2) |
end |
tip:Show() |
end |
end |
|
local function Alt_OnLeave(self) |
altLight:ClearAllPoints() |
if self and self.light then |
altLight:SetAlpha(0) |
tip:Hide() |
end |
if not MouseIsOver(f) and not MouseIsOver(g) then |
tipShown = nil |
f:Hide() g:Hide() tip:Hide() |
end |
end |
|
local function Menu_OnEnter(self) |
if self and self.light then |
highlight:SetAllPoints(self) |
highlight:SetAlpha(1) |
if config.hideTips or self.skill == "None" then return end |
tip:SetOwner(f, "ANCHOR_NONE") |
local showRight = f:GetCenter() > UIParent:GetWidth()/2 and "LEFT" or "RIGHT" |
local showBelow = select(2, f:GetCenter()) > UIParent:GetHeight()/2 and "TOP" or "BOTTOM" |
tip:SetPoint(showBelow..showRight, f, (showBelow == "TOP" and "BOTTOM" or "TOP")..showRight ) |
tip:AddLine(L.Hints) |
if self.shortcut then |
tip:AddLine(L"|cffff8020Click|r to craft.", .2,1,.2) |
tip:AddLine(L"|cffff8020Right-Click|r to show in panel.", .2,1,.2) |
tip:AddLine(L"|cffff8020Control+Click|r to set an alias.", .2, 1, .2) |
elseif self.spellID then |
tip:AddDoubleLine(L"Belongs to:", self.owner, 1,1,1,1,1,1) |
if self.owner == playerName and self.ready then |
tip:AddLine(L"|cffff8020Click|r to craft.", .2,1,.2) |
tip:AddLine(L"|cffff8020Right-Click|r to show CD in panel.", .2,1,.2) |
elseif char.show[watchedCDs[self.spellID].skill] ~= nil then |
tip:AddLine(L"|cffff8020Click|r to show CD in panel.", .2,1,.2) |
end |
tip:AddLine(L"|cffff8020Control+Click|r to set an alias.", .2, 1, .2) |
else |
local hasPanel = bit_band( skills[self.skill], PANEL ) > 0 |
local hasLink = bit_band( skills[self.skill], LINK ) > 0 |
if hasPanel then tip:AddLine(L"|cffff8020Click|r to toggle panel.", .2,1,.2) end |
if hasLink then tip:AddLine(L"|cffff8020Shift+Click|r to link in chat.", .2,1,.2) end |
if hasPanel then tip:AddLine(L"|cffff8020Right-Click|r to scan for CDs.", .2,1,.2) end |
end |
tip:AddLine(L"|cffff8020Middle-Click|r to remove from list.", .2, 1, .2) |
tip:Show() |
end |
end |
|
local function Menu_OnLeave(self) |
highlight:ClearAllPoints() |
if self and self.light then |
highlight:SetAlpha(0) |
tip:Hide() |
end |
if not MouseIsOver(f) and ( InCombatLockdown() or not MouseIsOver(g) ) then |
tipShown = nil |
f:Hide() g:Hide() tip:Hide() |
end |
end |
|
|
local metatable = { __index = function(table, key) |
local button = CreateFrame("Button", nil, workingFrame) |
rawset(table, key, button) |
button:RegisterForClicks"AnyUp" |
button:SetHeight(BUTTON_HEIGHT) |
button:SetPoint("TOPLEFT", workingFrame, "TOPLEFT", GAP, BUTTON_HEIGHT * (1-key) - GAP) |
button:SetScript("OnEnter", workingFrame == f and Menu_OnEnter or Alt_OnEnter) |
button:SetScript("OnLeave", workingFrame == f and Menu_OnLeave or Alt_OnLeave) |
button.icon = button:CreateTexture(nil, "OVERLAY") |
button.icon:SetWidth(ICON_SIZE) button.icon:SetHeight(ICON_SIZE) |
button.icon:SetPoint("LEFT", button, "LEFT") |
button.fontLeft = button:CreateFontString(nil, "OVERLAY", "SystemFont_Shadow_Med1") |
button.fontLeft:SetPoint("LEFT", button, "LEFT", ICON_SIZE + TEXT_OFFSET, 0) |
button.fontRight = button:CreateFontString(nil, "OVERLAY", "SystemFont_Shadow_Med1") |
button.fontRight:SetPoint("RIGHT", button, "RIGHT") |
return button |
end } |
|
local buttons = setmetatable( {}, metatable ) |
local altButtons = setmetatable( {}, metatable ) |
|
|
local function AddEntry( buttons, icon, leftText, leftTextColor, rightText, rightTextColor, highlight ) |
nbEntries = nbEntries + 1 |
local button = buttons[nbEntries] |
button.icon:SetTexture(icon or "") |
if icon then button.icon:SetTexCoord(0.075, 0.925, 0.075, 0.925) end |
button.fontLeft:SetText(leftText or "") |
if leftTextColor then button.fontLeft:SetTextColor(unpack(leftTextColor)) end |
button.fontRight:SetText(rightText or "") |
if rightTextColor then button.fontRight:SetTextColor(unpack(rightTextColor)) end |
button.light = highlight |
button:Show() |
return button, ICON_SIZE + TEXT_OFFSET + (leftText and button.fontLeft:GetStringWidth() or 0), rightText and button.fontRight:GetStringWidth() or 0 |
end |
|
|
local function UpdateCDs() |
local readyCDs = 0 |
local temp = new() |
local dups = new() |
local now = time() |
|
for i, v in next, CDs do |
del(v) |
CDs[i] = nil |
end |
|
for char, data in next, realm do |
for spellID, expireTime in next, data do |
if type(spellID)=="number" then |
local cd = watchedCDs[spellID] |
temp[#temp+1] = new( |
"name", cd.group and (config.aliases[cd.group] or cd.group) or config.aliases[spellID] or config.names[spellID] or GetSpellInfo(spellID), |
"timeLeft", expireTime-now, |
"char", char, |
"spellID", spellID, |
"skill", cd.skill, |
"group", cd.group) |
end |
end |
end |
sort(temp, SortCooldowns) |
|
for i=1, #temp do |
local cd = temp[i] |
if not dups[cd.group] then |
CDs[#CDs+1] = cd |
if cd.timeLeft <= 0 then readyCDs = readyCDs + 1 end |
end |
if cd.group then dups[cd.group] = true end |
end |
|
del(temp) |
del(dups) |
|
if config.displayCDs then |
-- local perc = readyCDs/totalCDs |
-- f.block.text = format(" |cff%.2x%.2x00%i/%i|r CD%s", perc<.5 and 255 or 510-perc*510, perc<.5 and perc*510 or 255, readyCDs, totalCDs, totalCDs>0 and "s" or "") |
f.block.text = format(" %i/%i CD%s", readyCDs, #CDs, #CDs>1 and "s" or "") |
end |
end |
|
local function SetMainPoint() |
|
end |
|
local function ShowAlts() |
workingFrame = g |
nbEntries = 0 |
altLight:SetVertexColor(unpack(config.colors.highlight)) |
local firstEntry, button = true |
local itemLeftWidth, itemRightWidth, colRightWidth, colLeftWidth = 0, 0, 0, 0 |
local list, subList = new(), new() |
|
for charName, charData in next, realm do |
if charName ~= playerName and charData.curSkills and next(charData.curSkills) then |
list[#list+1] = new("name",charName,"curSkills",charData.curSkills,"maxSkills",charData.maxSkills,"links",charData.links) |
end |
end |
sort(list,SortAlts) |
for _, char in ipairs(list) do |
if firstEntry then firstEntry = false else AddEntry(altButtons) end |
AddEntry( altButtons, "", char.name, config.colors.header ) |
for skill, value in next, char.maxSkills do |
if value > 1 then subList[#subList+1] = skill end |
end |
-- sort(subList) |
sort(subList, SortAltSkills) |
for _, skill in ipairs(subList) do |
local bitSkill = skills[skill] |
if not config.primaryOnly or bit_band(bitSkill, SECONDARY) == 0 then |
local hasLink = bit_band(bitSkill, LINK) > 0 |
local color = hasLink and config.colors.activeName or config.colors.infoName |
local icon = select(3,GetSpellInfo(floor(bitSkill/SPELL_ID))) |
local strValues = ColorCurMax( char.curSkills[skill], char.maxSkills[skill], true ) |
|
button, itemLeftWidth, itemRightWidth = AddEntry( altButtons, |
icon, skill, color, strValues, nil, hasLink) |
button:SetScript("OnClick", Link_OnClick) |
button.link = char.links and char.links[skill] |
button.skill = skill |
if itemLeftWidth > colLeftWidth then colLeftWidth = itemLeftWidth + GAP end |
if itemRightWidth > colRightWidth then colRightWidth = itemRightWidth end |
end |
end |
wipe(subList) |
end |
del(list) |
del(subList) |
g:Show() |
if _G.Skinner then _G.Skinner:applySkin(g) end |
if InCombatLockdown() then return end |
|
local maxWidth = colLeftWidth + colRightWidth |
for i=1, nbEntries do altButtons[i]:SetWidth(maxWidth) end |
g:SetWidth(maxWidth + GAP*2) |
g:SetHeight(BUTTON_HEIGHT * nbEntries + GAP*2) |
|
local horiz = f:GetCenter() > UIParent:GetWidth()/2 and "RIGHT" or "LEFT" |
local verti = select(2, f:GetCenter()) > UIParent:GetHeight()/2 and "TOP" or "BOTTOM" |
g:ClearAllPoints() |
g:SetPoint(verti..horiz, f, verti..(horiz=="LEFT"and"RIGHT"or"LEFT")) |
|
for i=nbEntries+1, #altButtons do altButtons[i]:Hide() end |
if nbEntries == 0 then g:Hide() end |
end |
|
|
Block_OnEnter = function(self) |
workingFrame = f |
highlight:SetVertexColor(unpack(config.colors.highlight)) |
f:Show() |
if InCombatLockdown() then return else CloseDropDownMenus() end |
tipShown = tipShown or self |
Menu_OnEnter(tipShown) |
nbEntries = 0 |
local char = realm[playerName] -- dirty fix |
|
local firstCombatSkill, button, selectedSkillExists = true |
local itemLeftWidth, itemRightWidth, colRightWidth, colLeftWidth, skillWidth, cdWidth = 0, 0, 0, 0 |
|
UpdateCDs() |
local showCDs, showProfessions, showCombatSkills, showShortcuts = min(#CDs,1), 0, 0, next(char.shortcuts) and 1 or 0 |
for k,v in next,f.skills do del(v) f.skills[k]=nil end |
|
ExpandSkillHeader(0) |
for i=1, GetNumSkillLines() do |
local displayName, skill, skillName, value, _, _, valueMax = GetSkillLineInfo(i) |
skillName = altNames[displayName] or displayName |
skill = skills[skillName] |
if skill then |
local hasPanel, isProfession = bit_band(skill,PANEL)>0, bit_band(skill,PROFESSION)>0 |
if char.show[skillName] == nil then char.show[skillName] = hasPanel end |
local show = (isProfession and not char.hideProfessions or not isProfession and not char.hideCombatSkills) and char.show[skillName] |
if show then if isProfession then showProfessions=1 else showCombatSkills=1 end end |
f.skills[#f.skills+1] = new( |
"displayName", displayName, |
"skillName", skillName, |
"isProfession", isProfession and floor(skill/SPELL_ID), |
"isCombatSkill",not isProfession, |
"hasPanel", hasPanel, |
"color", skillName==char.skill and config.colors.selected or hasPanel and config.colors.activeName or config.colors.infoName, |
"strValue", valueMax <= 1 and "" or ColorCurMax(value,valueMax,isProfession), |
"show", show, |
"primary", bit_band(skill,SECONDARY) == 0) |
if isProfession then char.curSkills[skillName], char.maxSkills[skillName] = value, valueMax end |
end |
end |
local nbHeaders = showProfessions + showCombatSkills + showCDs + showShortcuts |
|
sort(f.skills, SortSkills) |
for i, v in ipairs(f.skills) do |
if v.show then |
if nbEntries == 0 and showProfessions == 1 and nbHeaders > 1 then |
AddEntry(buttons, "", _G.TRADESKILLS, config.colors.header) |
end |
if v.isCombatSkill and firstCombatSkill and nbHeaders > 1 then |
firstCombatSkill = false |
if nbEntries > 0 then AddEntry(buttons) end |
AddEntry(buttons, "", L"Combat Skills", config.colors.header) |
end |
local texture = altIcons[v.skillName] or select(3,GetSpellInfo(v.isProfession)) or "" |
button, itemLeftWidth, itemRightWidth = AddEntry( buttons, |
texture, v.displayName, v.color, v.strValue, |
nil, true) |
button:SetScript("OnClick", Tradeskill_OnClick) |
button.skill, button.spellID, button.shortcut = v.skillName |
if v.color == config.colors.selected then f.selected = button end |
if itemLeftWidth > colLeftWidth then colLeftWidth = itemLeftWidth end |
if itemRightWidth > colRightWidth then colRightWidth = itemRightWidth end |
end |
end |
skillWidth = colLeftWidth + colRightWidth |
colRightWidth, colLeftWidth = 0, 0, 0, 0 |
|
-- Cooldowns |
local dups = new() |
for index, data in ipairs(CDs) do |
local group = data.group |
if not group or not dups[group] then |
if group then dups[group] = true end |
if index == 1 then |
if nbEntries>0 then AddEntry(buttons) end |
if nbHeaders>1 then AddEntry(buttons, "", L.Cooldowns, config.colors.header) end |
end |
button, itemLeftWidth, itemRightWidth = AddEntry( buttons, |
config.icons[group or data.spellID] or config.names[group] and select(3,GetSpellInfo(config.names[group])) or groupIcons[group], data.name, |
data.char == playerName and config.colors.ownCD or config.colors.foreignCD, |
data.timeLeft<=0 and L"|cff20ff20Ready!|r" or SecondsToTime(data.timeLeft), |
nil, true ) |
button:SetScript("OnClick", Cooldown_OnClick) |
button.skill, button.spellID, button.ready, button.owner, button.shortcut = data.skill, group and config.names[group] or data.spellID, data.timeLeft<=0, data.char |
if itemLeftWidth > colLeftWidth then colLeftWidth = itemLeftWidth end |
if itemRightWidth > colRightWidth then colRightWidth = itemRightWidth end |
end |
end |
del(dups) |
cdWidth = colLeftWidth + colRightWidth |
colLeftWidth = 0 |
|
-- Shortcuts |
local shortcuts = new() |
for spellID, skill in next, char.shortcuts do |
shortcuts[#shortcuts+1] = new( |
"skill", skill, |
"name", config.aliases[spellID] or config.names[spellID], |
"spellID", spellID) |
end |
sort(shortcuts, SortShortcuts) |
local firstShortcut = true |
for _, shortcut in ipairs(shortcuts) do |
if firstShortcut then |
firstShortcut = false |
if nbEntries>0 then AddEntry(buttons) end |
if nbHeaders>1 then AddEntry(buttons, "", L.Shortcuts, config.colors.header) end |
end |
button, itemLeftWidth = AddEntry( buttons, |
config.icons[shortcut.spellID], shortcut.name, config.colors.activeName, nil, nil, true ) |
if itemLeftWidth > colLeftWidth then colLeftWidth = itemLeftWidth end |
button:SetScript("OnClick", Shortcut_OnClick) |
button.skill, button.spellID, button.ready, button.shortcut = shortcut.skill, shortcut.spellID, true, true |
end |
del(shortcuts) |
|
-- ProfessionsBook |
if ProfessionsBook then |
if nbEntries>0 then AddEntry(buttons) end |
if nbHeaders>1 then AddEntry(buttons, "", L"Miscellaneous", config.colors.header) end |
button, itemLeftWidth = AddEntry( buttons, "Interface\\Spellbook\\Spellbook-Icon", "ProfessionsBook", config.colors.activeName, nil, nil, true ) |
button:SetScript("OnClick", ProfessionsBook_OnClick) |
button.skill, button.spellID, button.ready, button.shortcut = "None" |
end |
|
local maxWidth = math.max(skillWidth, cdWidth, colLeftWidth, itemLeftWidth) + GAP |
for i=1, nbEntries do buttons[i]:SetWidth(maxWidth) end |
f:SetWidth(maxWidth + GAP*2) |
f:SetHeight(BUTTON_HEIGHT * nbEntries + GAP*2) |
if _G.Skinner then _G.Skinner:applySkin(f) end |
|
local showBelow = select(2, tipShown:GetCenter()) > ( UIParent:GetHeight() / 2) |
f:ClearAllPoints() |
f:SetPoint(showBelow and "TOP" or "BOTTOM", tipShown, showBelow and "BOTTOM" or "TOP") |
|
for i=nbEntries+1, #buttons do buttons[i]:Hide() end |
if nbEntries == 0 then f:Hide() elseif not config.hideAlts then |
return InCombatLockdown() and g:Show() or ShowAlts() |
end |
end |
|
|
local function Block_OnClick(self, click) |
if click == "LeftButton" then |
if skills[char.skill] then CastSpellByName(char.skill) end |
elseif click == "RightButton" then |
f:Hide() tip:Hide() g:Hide() |
UIDropDownMenu_Initialize(dropdown, dropdown_init, "MENU") |
ToggleDropDownMenu(1, nil, dropdown, self, 0, 0) |
end |
end |
|
|
f.block = LibStub("LibDataBroker-1.1"):NewDataObject("|cFFFFB366Ara|r Tradeskills", { |
type = "data source", |
text = _G.TRADESKILLS, |
icon = "", |
OnEnter = Block_OnEnter, |
OnLeave = Menu_OnLeave, |
OnClick = Block_OnClick, |
} ) |
|
|
function f:TRADE_SKILL_SHOW() |
self:UnregisterEvent"TRADE_SKILL_SHOW" |
if self.getLink then |
self.getLink = nil |
local link = GetTradeSkillListLink() |
if not ChatEdit_InsertLink(link) then |
ChatFrameEditBox:Show() |
ChatEdit_InsertLink(link) |
end |
if self.keepOpen then self.keepOpen = nil else CloseTradeSkill() end |
return |
end |
ExpandTradeSkillSubClass(0) |
SetTradeSkillSubClassFilter(0,1,1) |
SetTradeSkillInvSlotFilter(0,1,1) |
TradeSkillOnlyShowMakeable(false) |
if TradeSkillFrameAvailableFilterCheckButton then |
TradeSkillFrameAvailableFilterCheckButton:SetChecked(false) |
end |
for i=1, GetNumTradeSkills() do |
local itemName, itemType = GetTradeSkillInfo(i) |
if itemType ~= "header" then |
local spellID = tonumber(strmatch(GetTradeSkillRecipeLink(i), "enchant:(%d+)")) |
local cd = watchedCDs[spellID] |
if spellID == self.searchedSpellID and (cd or self.shortcut) then |
SelectTradeSkill(i) |
TradeSkillFrame_SetSelection(i) |
if self.doTradeSkill and not GetTradeSkillCooldown(i) then |
DoTradeSkill(i) |
CloseTradeSkill() -- TODO: don't close if it was open |
else |
TradeSkillListScrollFrame:SetVerticalScroll(max(i-5,0)*TradeSkillSkill1:GetHeight()) |
end |
self.searchedSpellID, self.doTradeSkill, self.shortcut = nil |
break |
end |
if cd and self.learnCD then |
local timeLeft = GetTradeSkillCooldown(i) or 0 |
if timeLeft>0 or config.addReadyCD then |
char[spellID] = time() + timeLeft |
if not cd.group then |
config.icons[spellID] = GetTradeSkillIcon(i) |
config.names[spellID] = itemName |
end |
end |
end |
end |
end |
if self.learnCD then |
if self.keepOpen then self.keepOpen = nil else CloseTradeSkill() end |
self.learnCD = nil |
end |
if tipShown then Block_OnEnter(tipShown) end |
end |
|
|
function f:SetAlias(alias) |
config.aliases[self.aliasID] = alias ~= "" and alias or nil |
if tipShown then Block_OnEnter(tipShown)end |
end |
|
function f:PLAYER_LOGOUT() |
for i=1, GetNumSkillLines() do |
local displayName, skill, skillName, value, _, _, valueMax = GetSkillLineInfo(i) |
skillName = altNames[displayName] or displayName |
skill = skills[skillName] |
if skill then |
if bit_band(skill,PROFESSION) == 0 then break end |
char.curSkills[skillName], char.maxSkills[skillName] = value, valueMax |
end |
end |
end |
|
------------------------------[[ options ]]------------------------------ |
|
local function DisplayCD_OnUpdate(self, elapsed) |
self.timer = self.timer - elapsed |
if self.timer > 0 then return end |
self.timer = 60 |
UpdateCDs() |
end |
|
local function SetOption(self, t, v, c) t[v] = not t[v] end |
local function ColorPickerChange() c[1], c[2], c[3] = ColorPickerFrame:GetColorRGB() end |
local function ColorPickerCancel(prev) c[1], c[2], c[3] = unpack(prev) end |
local function OpenColorPicker(self, col) |
c = config.colors[col] |
ColorPickerFrame.func = ColorPickerChange |
ColorPickerFrame.cancelFunc = ColorPickerCancel |
ColorPickerFrame.previousValues = {unpack(c)} |
ColorPickerFrame:SetColorRGB( c[1], c[2], c[3] ) |
ColorPickerFrame:Show() |
end |
|
local function RemoveChar(self, char) |
realm[char] = nil |
print( "|cFFFFB366Ara|cffffff00BrokerTradeskills: "..format(L"|cff8080ff%s|r has been removed.",char) ) |
end |
|
function f:ADDON_LOADED(event, addon) |
if addon ~= "Ara_Broker_Tradeskills" then return end |
|
AraTradeskillsDB = AraTradeskillsDB or {icons={},names={},aliases={},colors={ header={1,1,1}, activeName={1,.82,0}, infoName={.6,.5,0}, selected={.9,0.45,.1}, highlight={1,.8,0}, ownCD={1,.82,0}, foreignCD={.6,.5,0} }} |
config = AraTradeskillsDB |
config.colors.activeVal, config.colors.infoVal = nil -- get rid of old config values |
if not config[realmName] then config[realmName] = {} end |
realm = config[realmName] |
if not realm[playerName] then realm[playerName] = {show={}} end |
char = realm[playerName] |
if not char.shortcuts then char.shortcuts = {} end -- r14 |
if not char.curSkills then char.curSkills, char.maxSkills = {}, {} end |
if not char.links then char.links = {} end -- r25 |
CDs = new() |
if config.displayCDs then |
e.timer = 0 |
e:SetScript("OnUpdate", DisplayCD_OnUpdate) |
end |
|
options = { |
{ text = format("|cFFFFB366Ara|r Broker Tradeskills (%s)", GetAddOnMetadata("Ara_Broker_Tradeskills", "Version")), isTitle = true }, |
{ text = _G.TRADE_SKILLS, submenu = "isProfession", scope=char, var="hideProfessions", inv=true }, |
{ text = L"Combat Skills", submenu = "isCombatSkill", scope=char, var="hideCombatSkills", inv=true }, |
{ text = L"Include |cff20ff20Ready!|r CDs when scanning", scope=config, var="addReadyCD" }, |
{ text = L"Show hints", scope=config, var="hideTips", inv=true }, |
{ text = L"Show alt. skills", scope=config, var="hideAlts", inv=true }, |
{ text = L"Show alt. primary skills only", scope=config, var="primaryOnly" }, |
{ text = L"Remove an alt.", submenu="alts" }, |
{ text = L"Display number of Ready CD", func= |
function() |
config.displayCDs = not config.displayCDs |
e.timer = 0 |
e:SetScript("OnUpdate", config.displayCDs and DisplayCD_OnUpdate or nil) |
UpdateText() |
end, checked=function() return config.displayCDs end }, |
{ text = L.Colors, submenu = { |
{ text = L"Header", colorPick = "header" }, |
{ text = L"Interactive skill name", colorPick = "activeName" }, |
{ text = L"Last selected skill", colorPick = "selected" }, |
{ text = L"Informative skill name", colorPick = "infoName" }, |
{ text = L"Player CD", colorPick = "ownCD" }, |
{ text = L"Other player CD", colorPick = "foreignCD" }, |
{ text = L"Highlight", colorPick = "highlight" }, }, |
}, |
} |
dropdown_init = function(self, level) |
level = level or 1 |
local options = level>1 and UIDROPDOWNMENU_MENU_VALUE or options |
if options == "alts" then |
for char in next, realm do |
if char ~= playerName then |
local info = UIDropDownMenu_CreateInfo() |
info.text, info.notCheckable = char, true |
info.func, info.arg1 = RemoveChar, char |
UIDropDownMenu_AddButton( info, level ) |
end |
end |
return |
end |
local custom = type(options)~="table" |
for i, v in ipairs(custom and f.skills or options) do |
if not custom or v[options] then |
local info = UIDropDownMenu_CreateInfo() |
info.text = custom and format("|cff%.2x%.2x%.2x%s|r", v.color[1]*255, v.color[2]*255, v.color[3]*255, v.displayName) or v.text |
info.isTitle, info.value, info.hasArrow = v.isTitle, v.submenu, v.submenu ~= nil |
if custom then |
info.checked = char.show[v.skillName] |
info.func, info.arg1, info.arg2 = SetOption, char.show, v.skillName |
elseif v.scope then |
info.checked = v.inv and not v.scope[v.var] or not v.inv and v.scope[v.var] |
info.func, info.arg1, info.arg2, info.tooltipText = SetOption, v.scope, v.var, v.inv |
elseif v.colorPick then |
info.hasColorSwatch, info.notCheckable = true, true |
info.r, info.g, info.b = unpack(config.colors[v.colorPick]) |
info.func, info.arg1 = OpenColorPicker, v.colorPick |
else |
info.func, info.checked = v.func, v.checked |
end |
info.keepShownOnClick = info.func |
UIDropDownMenu_AddButton( info, level ) |
end |
end |
end |
|
local popup = { |
text = L"Set an alias for \"%s\".\nLeave blank to reset.", |
OnAccept = function(self) AraSkills:SetAlias(self.wideEditBox:GetText()) end, |
OnShow = function(self) self.wideEditBox:SetText(AraSkills.alias) self.wideEditBox:SetFocus() end, |
EditBoxOnEnterPressed = function(self) |
local parent = self:GetParent() |
AraSkills:SetAlias(parent.wideEditBox:GetText()) |
parent:Hide() |
end, |
} |
for k, v in next, StaticPopupDialogs.SET_FRIENDNOTE do |
if not popup[k] then popup[k] = v end |
end |
StaticPopupDialogs.SET_ALIAS = popup |
tip = _G.GameTooltip |
|
self.skills = {} |
self:SetFrameStrata"TOOLTIP" |
self:SetClampedToScreen(true) |
self:EnableMouse(true) |
self:SetScript("OnEnter", Menu_OnEnter) |
self:SetScript("OnLeave", Menu_OnLeave) |
self:RegisterEvent"PLAYER_LOGOUT" |
|
g:SetFrameStrata"TOOLTIP" |
g:EnableMouse(true) |
g:SetScript("OnEnter", Alt_OnEnter) |
g:SetScript("OnLeave", Alt_OnLeave) |
|
if IsLoggedIn() then UpdateText() else |
f.PLAYER_ENTERING_WORLD = UpdateText |
f:RegisterEvent"PLAYER_ENTERING_WORLD" |
end |
self:UnregisterEvent(event) |
self.ADDON_LOADED = nil |
|
local backdrop = { bgFile="Interface\\Buttons\\WHITE8X8", edgeFile="Interface\\Tooltips\\UI-Tooltip-Border", |
tile=true, tileSize=12, edgeSize=12, insets = { left=2, right=2, top=2, bottom=2 } } |
self:SetBackdrop(backdrop) |
self:SetBackdropColor(0, 0, 0, .75) |
g:SetBackdrop(backdrop) |
g:SetBackdropColor(0, 0, 0, .75) |
end |
|
|
e:RegisterEvent"TRADE_SKILL_SHOW" |
|
e:SetScript("OnEvent", function() |
LoadAddOn"Blizzard_TradeSkillUI" |
|
local b = TradeSkillSkillIcon |
local TS_OnEnter = b:GetScript"OnEnter" |
local TS_OnLeave = b:GetScript"OnLeave" |
local TS_OnClick = b:GetScript"OnClick" |
|
local OrgSetItem = GameTooltip.SetTradeSkillItem |
local function NewSetItem(...) |
OrgSetItem(...) |
GameTooltip:AddLine("\n"..L"|cffff8040Click|r to create a shortcut.", .2, 1, .2) |
GameTooltip:Show() |
end |
|
b:SetScript("OnEnter", function(self, ...) |
GameTooltip.SetTradeSkillItem = NewSetItem |
TS_OnEnter(self, ...) |
end) |
b:SetScript("OnLeave", function(...) |
TS_OnLeave(...) |
GameTooltip.SetTradeSkillItem = OrgSetItem |
end) |
b:SetScript("OnClick", function(self,button,...) |
TS_OnClick(self,button,...) |
if not IsModifierKeyDown() and button == "LeftButton" then |
local index = TradeSkillFrame.selectedSkill |
local spellID = tonumber(strmatch(GetTradeSkillRecipeLink(index), "enchant:(%d+)")) |
local skill = GetTradeSkillLine() |
char.shortcuts[spellID] = altNames[skill] or skill |
config.names[spellID] = GetTradeSkillInfo(index) |
config.icons[spellID] = GetTradeSkillIcon(index) |
print("|cFFFFB366Ara|cffffff00BrokerTradeskills: "..format(L"|cff8080ff%s|r|cffffff00 added to shortcuts.",config.names[spellID])) |
end |
end) |
|
local function OnEvent() |
if not IsTradeSkillLinked() then |
local skill = GetTradeSkillLine() |
char.links[ altNames[skill] or skill ] = GetTradeSkillListLink() |
end |
end |
e:SetScript("OnEvent", OnEvent) |
OnEvent() |
end) |
|
f:SetScript("OnEvent", function(self, event, ...) return self[event](self, event, ...) end) |
f:RegisterEvent"ADDON_LOADED" |