mirror of
https://github.com/parnic/breakables.git
synced 2025-06-17 01:41:51 -05:00
Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
f93465037d | |||
f9971a7818 | |||
59fd3c320d | |||
4bc72649f2 | |||
4ad9afa103 | |||
958521c6d3 | |||
1401893e2d | |||
f55cd76606 | |||
6a89a7ca11 | |||
a5f5958c5e |
3
.pkgmeta
3
.pkgmeta
@ -28,6 +28,9 @@ externals:
|
||||
libs/AceEvent-3.0:
|
||||
url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceEvent-3.0
|
||||
tag: latest
|
||||
libs/AceLocale-3.0:
|
||||
url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceLocale-3.0
|
||||
tag: latest
|
||||
libs/LibBabble-Inventory-3.0:
|
||||
url: svn://svn.wowace.com/wow/libbabble-inventory-3-0/mainline/trunk
|
||||
tag: latest
|
||||
|
496
Breakables.lua
496
Breakables.lua
@ -1,3 +1,4 @@
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Breakables", false)
|
||||
Breakables = LibStub("AceAddon-3.0"):NewAddon("Breakables", "AceConsole-3.0", "AceEvent-3.0")
|
||||
local babbleInv = LibStub("LibBabble-Inventory-3.0"):GetLookupTable()
|
||||
|
||||
@ -13,6 +14,7 @@ local CanProspect = false
|
||||
local DisenchantId = 13262
|
||||
local DisenchantTypes = {babbleInv["Armor"], babbleInv["Weapon"]}
|
||||
local CanDisenchant = false
|
||||
|
||||
-- item rarity must meet or surpass this to be considered for disenchantability (is that a word?)
|
||||
local RARITY_UNCOMMON = 2
|
||||
|
||||
@ -31,23 +33,78 @@ local BREAKABLE_HERB = 1
|
||||
local BREAKABLE_ORE = 2
|
||||
local BREAKABLE_DE = 3
|
||||
|
||||
local BagUpdateCheckDelay = 1.5
|
||||
local nextCheck = {}
|
||||
for i=0,NUM_BAG_SLOTS do
|
||||
nextCheck[i] = -1
|
||||
end
|
||||
|
||||
local buttonSize = 28
|
||||
|
||||
local _G = _G
|
||||
|
||||
-- can be 1 or 2
|
||||
local numEligibleProfessions = 0
|
||||
|
||||
Breakables.optionsFrame = {}
|
||||
Breakables.justClicked = false
|
||||
|
||||
function Breakables:OnInitialize()
|
||||
self.defaults = {
|
||||
profile = {
|
||||
buttonFrameLeft = 100,
|
||||
buttonFrameTop = -100,
|
||||
buttonFrameLeft = {100, 100},
|
||||
buttonFrameTop = {-100, -150},
|
||||
hideIfNoBreakables = true,
|
||||
maxBreakablesToShow = 5,
|
||||
showSoulbound = false,
|
||||
hideEqManagerItems = true,
|
||||
hide = false,
|
||||
hideInCombat = false,
|
||||
buttonScale = 1,
|
||||
fontSize = 7,
|
||||
}
|
||||
}
|
||||
self.db = LibStub("AceDB-3.0"):New("BreakablesDB", self.defaults)
|
||||
self.settings = self.db.profile
|
||||
|
||||
self:RegisterChatCommand("brk", "OnSlashCommand")
|
||||
|
||||
if type(self.settings.buttonFrameLeft) ~= "table" then
|
||||
local old = self.settings.buttonFrameLeft
|
||||
self.settings.buttonFrameLeft = {}
|
||||
self.settings.buttonFrameLeft[1] = old
|
||||
self.settings.buttonFrameLeft[2] = self.defaults.profile.buttonFrameLeft[2]
|
||||
end
|
||||
if type(self.settings.buttonFrameTop) ~= "table" then
|
||||
local old = self.settings.buttonFrameTop
|
||||
self.settings.buttonFrameTop = {}
|
||||
self.settings.buttonFrameTop[1] = old
|
||||
self.settings.buttonFrameTop[2] = self.defaults.profile.buttonFrameTop[2]
|
||||
end
|
||||
|
||||
self:InitLDB()
|
||||
end
|
||||
|
||||
function Breakables:InitLDB()
|
||||
local LDB = LibStub and LibStub("LibDataBroker-1.1", true)
|
||||
|
||||
if (LDB) then
|
||||
local ldbButton = LDB:NewDataObject("Breakables", {
|
||||
type = "launcher",
|
||||
text = L["Breakables"],
|
||||
icon = "Interface\\Icons\\ability_warrior_sunder",
|
||||
OnClick = function(button, msg)
|
||||
self:OnSlashCommand()
|
||||
end,
|
||||
})
|
||||
|
||||
if ldbButton then
|
||||
function ldbButton:OnTooltipShow()
|
||||
self:AddLine(L["Breakables"] .. " @project-version@")
|
||||
self:AddLine(L["Click to open Breakables options."], 1, 1, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Breakables:OnEnable()
|
||||
@ -61,12 +118,44 @@ function Breakables:OnEnable()
|
||||
self:RegisterEvents()
|
||||
|
||||
if CanMill or CanProspect or CanDisenchant then
|
||||
if CanMill then
|
||||
numEligibleProfessions = numEligibleProfessions + 1
|
||||
end
|
||||
if CanProspect then
|
||||
numEligibleProfessions = numEligibleProfessions + 1
|
||||
end
|
||||
if CanDisenchant then
|
||||
numEligibleProfessions = numEligibleProfessions + 1
|
||||
end
|
||||
|
||||
self:CreateButtonFrame()
|
||||
if self.settings.hide then
|
||||
self:ToggleButtonFrameVisibility(false)
|
||||
else
|
||||
self:FindBreakables()
|
||||
end
|
||||
self.frame:SetScript("OnUpdate", function() self:CheckShouldFindBreakables() end)
|
||||
else
|
||||
self:UnregisterAllEvents()
|
||||
end
|
||||
end
|
||||
|
||||
function Breakables:ToggleButtonFrameVisibility(show)
|
||||
for i=1,numEligibleProfessions do
|
||||
if self.buttonFrame[i] then
|
||||
if show == nil then
|
||||
show = not self.buttonFrame[i]:IsVisible()
|
||||
end
|
||||
|
||||
if not show then
|
||||
self.buttonFrame[i]:Hide()
|
||||
else
|
||||
self.buttonFrame[i]:Show()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Breakables:RegisterEvents()
|
||||
-- would have used ITEM_PUSH here, but that seems to fire after looting and before the bag actually gets the item
|
||||
-- another alternative is to parse the chat msg, but that seems lame...however, that should only fire once as opposed to BAG_UPDATE's potential double-fire
|
||||
@ -82,24 +171,49 @@ end
|
||||
|
||||
function Breakables:OnDisable()
|
||||
self:UnregisterAllEvents()
|
||||
self.frame:SetScript("OnUpdate", nil)
|
||||
end
|
||||
|
||||
function Breakables:OnSlashCommand(input)
|
||||
InterfaceOptionsFrame_OpenToCategory(self.optionsFrame)
|
||||
end
|
||||
|
||||
function Breakables:OnItemReceived(bag)
|
||||
self:FindBreakables()
|
||||
function Breakables:OnItemReceived(event, bag)
|
||||
if self.justClicked then
|
||||
self:FindBreakables()
|
||||
self.justClicked = false
|
||||
elseif not bag or bag >= 0 then
|
||||
nextCheck[bag] = GetTime() + BagUpdateCheckDelay
|
||||
end
|
||||
end
|
||||
|
||||
function Breakables:CheckShouldFindBreakables()
|
||||
local latestTime = -1
|
||||
for i=0,#nextCheck do
|
||||
if nextCheck[i] > latestTime then
|
||||
latestTime = nextCheck[i]
|
||||
end
|
||||
end
|
||||
|
||||
if latestTime > 0 and latestTime <= GetTime() then
|
||||
self:FindBreakables()
|
||||
for i=0,#nextCheck do
|
||||
nextCheck[i] = -1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Breakables:OnEnterCombat()
|
||||
self.bCombat = true
|
||||
if self.settings.hideInCombat then
|
||||
self:ToggleButtonFrameVisibility(false)
|
||||
end
|
||||
end
|
||||
|
||||
function Breakables:OnLeaveCombat()
|
||||
self.bCombat = false
|
||||
|
||||
if self.bPendingUpdate then
|
||||
if self.bPendingUpdate or self.settings.hideInCombat then
|
||||
self.bPendingUpdate = false
|
||||
self:FindBreakables()
|
||||
end
|
||||
@ -120,27 +234,70 @@ end
|
||||
|
||||
function Breakables:GetOptions()
|
||||
local opts = {
|
||||
name = "Breakables",
|
||||
name = L["Breakables"],
|
||||
handler = Breakables,
|
||||
type = "group",
|
||||
args = {
|
||||
intro = {
|
||||
type = "description",
|
||||
fontSize = "small",
|
||||
name = L["Welcome"],
|
||||
order = 0,
|
||||
},
|
||||
hideAlways = {
|
||||
type = "toggle",
|
||||
name = L["Hide bar"],
|
||||
desc = L["This will completely hide the breakables bar whether you have anything to break down or not. Note that you can toggle this in a macro using the /breakables command as well."],
|
||||
get = function(info)
|
||||
return self.settings.hide
|
||||
end,
|
||||
set = function(info, v)
|
||||
self.settings.hide = v
|
||||
if info.uiType == "cmd" then
|
||||
print("|cff33ff99Breakables|r: set |cffffff78maxBreakables|r to " .. tostring(self.settings.hide))
|
||||
end
|
||||
self:ToggleButtonFrameVisibility(not v)
|
||||
if not v then
|
||||
self:FindBreakables()
|
||||
end
|
||||
end,
|
||||
order = 1
|
||||
},
|
||||
hideNoBreakables = {
|
||||
type = "toggle",
|
||||
name = "Hide if no breakables",
|
||||
desc = "Whether or not to hide the action bar if no breakables are present in your bags",
|
||||
name = L["Hide if no breakables"],
|
||||
desc = L["Whether or not to hide the action bar if no breakables are present in your bags"],
|
||||
get = function(info)
|
||||
return self.settings.hideIfNoBreakables
|
||||
end,
|
||||
set = function(info, v)
|
||||
self.settings.hideIfNoBreakables = v
|
||||
if info.uiType == "cmd" then
|
||||
print("|cff33ff99Breakables|r: set |cffffff78hideIfNoBreakables|r to " .. tostring(self.settings.hideIfNoBreakables))
|
||||
end
|
||||
self:FindBreakables()
|
||||
end,
|
||||
order = 1,
|
||||
order = 2,
|
||||
},
|
||||
hideInCombat = {
|
||||
type = "toggle",
|
||||
name = L["Hide during combat"],
|
||||
desc = L["Whether or not to hide the breakables bar when you enter combat and show it again when leaving combat."],
|
||||
get = function(info)
|
||||
return self.settings.hideInCombat
|
||||
end,
|
||||
set = function(info, v)
|
||||
self.settings.hideInCombat = v
|
||||
if info.uiType == "cmd" then
|
||||
print("|cff33ff99Breakables|r: set |cffffff78hideInCombat|r to " .. tostring(self.settings.hideInCombat))
|
||||
end
|
||||
end,
|
||||
order = 3,
|
||||
},
|
||||
maxBreakables = {
|
||||
type = 'range',
|
||||
name = 'Max number to display',
|
||||
desc = 'How many breakable buttons to display next to the profession button at maximum',
|
||||
name = L["Max number to display"],
|
||||
desc = L["How many breakable buttons to display next to the profession button at maximum"],
|
||||
min = 1,
|
||||
max = 50,
|
||||
step = 1,
|
||||
@ -149,9 +306,50 @@ function Breakables:GetOptions()
|
||||
end,
|
||||
set = function(info, v)
|
||||
self.settings.maxBreakablesToShow = v
|
||||
if info.uiType == "cmd" then
|
||||
print("|cff33ff99Breakables|r: set |cffffff78maxBreakables|r to " .. tostring(self.settings.maxBreakablesToShow))
|
||||
end
|
||||
self:FindBreakables()
|
||||
end,
|
||||
order = 2,
|
||||
order = 4,
|
||||
},
|
||||
buttonScale = {
|
||||
type = 'range',
|
||||
name = L["Button scale"],
|
||||
desc = L["This will scale the size of each button up or down."],
|
||||
min = 0.1,
|
||||
max = 2,
|
||||
step = 0.01,
|
||||
get = function(info)
|
||||
return self.settings.buttonScale
|
||||
end,
|
||||
set = function(info, v)
|
||||
self.settings.buttonScale = v
|
||||
Breakables:ApplyScale()
|
||||
if info.uiType == "cmd" then
|
||||
print("|cff33ff99Breakables|r: set |cffffff78buttonScale|r to " .. tostring(self.settings.buttonScale))
|
||||
end
|
||||
end,
|
||||
order = 5,
|
||||
},
|
||||
fontSize = {
|
||||
type = 'range',
|
||||
name = L["Font size"],
|
||||
desc = L["This sets the size of the text that shows how many items you have to break."],
|
||||
min = 4,
|
||||
max = 90,
|
||||
step = 1,
|
||||
get = function(info)
|
||||
return self.settings.fontSize
|
||||
end,
|
||||
set = function(info, v)
|
||||
self.settings.fontSize = v
|
||||
Breakables:ApplyScale()
|
||||
if info.uiType == "cmd" then
|
||||
print("|cff33ff99Breakables|r: set |cffffff78fontSize|r to " .. tostring(self.settings.fontSize))
|
||||
end
|
||||
end,
|
||||
order = 6,
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -159,87 +357,142 @@ function Breakables:GetOptions()
|
||||
if CanDisenchant then
|
||||
opts.args.showSoulbound = {
|
||||
type = "toggle",
|
||||
name = "Show soulbound items",
|
||||
desc = "Whether or not to display soulbound items as breakables.",
|
||||
name = L["Show soulbound items"],
|
||||
desc = L["Whether or not to display soulbound items as breakables."],
|
||||
get = function(info)
|
||||
return self.settings.showSoulbound
|
||||
end,
|
||||
set = function(info, v)
|
||||
self.settings.showSoulbound = v
|
||||
if info.uiType == "cmd" then
|
||||
print("|cff33ff99Breakables|r: set |cffffff78showSoulbound|r to " .. tostring(self.settings.showSoulbound))
|
||||
end
|
||||
self:FindBreakables()
|
||||
end,
|
||||
order = 3,
|
||||
order = 20,
|
||||
}
|
||||
opts.args.hideSoulboundIfInEquipmentManager = {
|
||||
opts.args.hideEqManagerItems = {
|
||||
type = "toggle",
|
||||
name = "Hide Eq. Mgr items",
|
||||
desc = "Whether or not to hide items that are part of an equipment set in the game's equipment manager.",
|
||||
name = L["Hide Eq. Mgr items"],
|
||||
desc = L["Whether or not to hide items that are part of an equipment set in the game's equipment manager."],
|
||||
get = function(info)
|
||||
return self.settings.hideEqManagerItems
|
||||
end,
|
||||
set = function(info, v)
|
||||
self.settings.hideEqManagerItems = v
|
||||
if info.uiType == "cmd" then
|
||||
print("|cff33ff99Breakables|r: set |cffffff78hideEqManagerItems|r to " .. tostring(self.settings.hideEqManagerItems))
|
||||
end
|
||||
self:FindBreakables()
|
||||
end,
|
||||
hidden = function()
|
||||
return not self.settings.showSoulbound
|
||||
end,
|
||||
order = 4,
|
||||
order = 21,
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
return opts
|
||||
end
|
||||
|
||||
function Breakables:CreateButtonFrame()
|
||||
if not self.frame then
|
||||
self.frame = CreateFrame("Frame")
|
||||
end
|
||||
if not self.buttonFrame then
|
||||
self.buttonFrame = CreateFrame("Button", "BreakablesButtonFrame1", UIParent, "SecureActionButtonTemplate")
|
||||
self.buttonFrame = {}
|
||||
end
|
||||
self.buttonFrame:SetPoint("TOPLEFT", UIParent, "TOPLEFT", self.settings.buttonFrameLeft, self.settings.buttonFrameTop)
|
||||
|
||||
if not self.buttonFrame.icon then
|
||||
self.buttonFrame.icon = self.buttonFrame:CreateTexture(nil, "BACKGROUND")
|
||||
end
|
||||
if CanMill or CanProspect or CanDisenchant then
|
||||
self.buttonFrame:SetWidth(40)
|
||||
self.buttonFrame:SetHeight(40)
|
||||
for i=1,numEligibleProfessions do
|
||||
if not self.buttonFrame[i] then
|
||||
self.buttonFrame[i] = CreateFrame("Button", "BreakablesButtonFrame1", self.frame, "SecureActionButtonTemplate")
|
||||
end
|
||||
self.buttonFrame[i]:SetPoint("TOPLEFT", UIParent, "TOPLEFT", self.settings.buttonFrameLeft[i], self.settings.buttonFrameTop[i])
|
||||
|
||||
self.buttonFrame:EnableMouse(true)
|
||||
self.buttonFrame:RegisterForClicks("LeftButtonUp")
|
||||
if CanMill and (i == 1 or self.buttonFrame[1].type ~= BREAKABLE_HERB) then
|
||||
self.buttonFrame[i].type = BREAKABLE_HERB
|
||||
elseif CanDisenchant and (i == 1 or self.buttonFrame[1].type ~= BREAKABLE_DE) then
|
||||
self.buttonFrame[i].type = BREAKABLE_DE
|
||||
elseif CanProspect and (i == 1 or self.buttonFrame[1].type ~= BREAKABLE_ORE) then
|
||||
self.buttonFrame[i].type = BREAKABLE_ORE
|
||||
end
|
||||
|
||||
self.buttonFrame:SetMovable(true)
|
||||
self.buttonFrame:RegisterForDrag("LeftButton")
|
||||
self.buttonFrame:SetScript("OnMouseDown", function() self:OnMouseDown() end)
|
||||
self.buttonFrame:SetScript("OnMouseUp", function() self:OnMouseUp() end)
|
||||
self.buttonFrame:SetClampedToScreen(true)
|
||||
if not self.buttonFrame[i].icon then
|
||||
self.buttonFrame[i].icon = self.buttonFrame[i]:CreateTexture(nil, "BACKGROUND")
|
||||
end
|
||||
if self.buttonFrame[i].type then
|
||||
self.buttonFrame[i]:SetWidth(buttonSize * self.settings.buttonScale)
|
||||
self.buttonFrame[i]:SetHeight(buttonSize * self.settings.buttonScale)
|
||||
|
||||
local spellName, _, texture = GetSpellInfo((CanMill and MillingId) or (CanProspect and ProspectingId) or DisenchantId)
|
||||
self.buttonFrame[i]:EnableMouse(true)
|
||||
self.buttonFrame[i]:RegisterForClicks("LeftButtonUp")
|
||||
|
||||
self.buttonFrame:SetAttribute("type1", "spell")
|
||||
self.buttonFrame:SetAttribute("spell1", spellName)
|
||||
self.buttonFrame[i]:SetMovable(true)
|
||||
self.buttonFrame[i]:RegisterForDrag("LeftButton")
|
||||
self.buttonFrame[i]:SetScript("OnMouseDown", function(frame) self:OnMouseDown(frame) end)
|
||||
self.buttonFrame[i]:SetScript("OnMouseUp", function(frame) self:OnMouseUp(frame) end)
|
||||
self.buttonFrame[i]:SetClampedToScreen(true)
|
||||
|
||||
self.buttonFrame.icon:SetTexture(texture)
|
||||
self.buttonFrame.icon:SetAllPoints(self.buttonFrame)
|
||||
else
|
||||
self.buttonFrame:SetTexture(nil)
|
||||
local spellName, _, texture = GetSpellInfo((self.buttonFrame[i].type == BREAKABLE_HERB and MillingId) or (self.buttonFrame[i].type == BREAKABLE_ORE and ProspectingId) or DisenchantId)
|
||||
|
||||
self.buttonFrame[i]:SetAttribute("type1", "spell")
|
||||
self.buttonFrame[i]:SetAttribute("spell1", spellName)
|
||||
|
||||
self.buttonFrame[i].icon:SetTexture(texture)
|
||||
self.buttonFrame[i].icon:SetAllPoints(self.buttonFrame[i])
|
||||
else
|
||||
self.buttonFrame[i]:SetTexture(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Breakables:OnMouseDown()
|
||||
function Breakables:ApplyScale()
|
||||
if not self.buttonFrame then
|
||||
return
|
||||
end
|
||||
|
||||
for i=1,numEligibleProfessions do
|
||||
-- yes, setscale exists...but it was scaling buttonFrame and breakableButtons differently for some reason. this works better.
|
||||
self.buttonFrame[i]:SetWidth(buttonSize * self.settings.buttonScale)
|
||||
self.buttonFrame[i]:SetHeight(buttonSize * self.settings.buttonScale)
|
||||
|
||||
if self.breakableButtons[i] then
|
||||
for j=1,#self.breakableButtons[i] do
|
||||
self.breakableButtons[i][j]:SetWidth(buttonSize * self.settings.buttonScale)
|
||||
self.breakableButtons[i][j]:SetHeight(buttonSize * self.settings.buttonScale)
|
||||
self.breakableButtons[i][j].text:SetFont(NumberFont_Outline_Med:GetFont(), self.settings.fontSize, "OUTLINE")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Breakables:OnMouseDown(frame)
|
||||
if IsShiftKeyDown() then
|
||||
self.buttonFrame:StartMoving()
|
||||
frame:StartMoving()
|
||||
end
|
||||
end
|
||||
|
||||
function Breakables:OnMouseUp()
|
||||
self.buttonFrame:StopMovingOrSizing()
|
||||
function Breakables:OnMouseUp(frame)
|
||||
frame:StopMovingOrSizing()
|
||||
|
||||
local _, _, _, xOff, yOff = self.buttonFrame:GetPoint(1)
|
||||
self.settings.buttonFrameLeft = xOff
|
||||
self.settings.buttonFrameTop = yOff
|
||||
local frameNum = 1
|
||||
for i=1,numEligibleProfessions do
|
||||
if self.buttonFrame[i] == frame then
|
||||
frameNum = i
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local _, _, _, xOff, yOff = frame:GetPoint(1)
|
||||
self.settings.buttonFrameLeft[frameNum] = xOff
|
||||
self.settings.buttonFrameTop[frameNum] = yOff
|
||||
end
|
||||
|
||||
function Breakables:FindBreakables()
|
||||
function Breakables:FindBreakables(bag)
|
||||
if self.settings.hide then
|
||||
return
|
||||
end
|
||||
|
||||
if self.bCombat then
|
||||
self.bPendingUpdate = true
|
||||
return
|
||||
@ -247,87 +500,110 @@ function Breakables:FindBreakables()
|
||||
|
||||
local foundBreakables = {}
|
||||
local i=1
|
||||
local numBreakableStacks = 0
|
||||
local numBreakableStacks = {}
|
||||
|
||||
for bagId=0,NUM_BAG_SLOTS do
|
||||
local found = self:FindBreakablesInBag(bagId)
|
||||
for n=1,#found do
|
||||
local addedToExisting = self:MergeBreakables(found[n], foundBreakables)
|
||||
-- this is where i tried to throttle updates...can't just yet since the full breakables list is rebuilt every time this function is called
|
||||
-- consider ways of caching off the last-known state of all breakables
|
||||
--if bag == nil or bag == bagId then
|
||||
local found = self:FindBreakablesInBag(bagId)
|
||||
for n=1,#found do
|
||||
local addedToExisting = self:MergeBreakables(found[n], foundBreakables)
|
||||
|
||||
if not addedToExisting then
|
||||
foundBreakables[i] = found[n]
|
||||
i = i + 1
|
||||
if not addedToExisting then
|
||||
foundBreakables[i] = found[n]
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
--end
|
||||
end
|
||||
|
||||
self:SortBreakables(foundBreakables)
|
||||
|
||||
if not self.breakableButtons then
|
||||
self.breakableButtons = {}
|
||||
end
|
||||
|
||||
for i=1,#foundBreakables do
|
||||
local isDisenchantable = self:BreakableIsDisenchantable(foundBreakables[i][IDX_TYPE], foundBreakables[i][IDX_LEVEL])
|
||||
if (CanDisenchant and isDisenchantable) or foundBreakables[i][IDX_COUNT] >= 5 then
|
||||
if not self.breakableButtons then
|
||||
self.breakableButtons = {}
|
||||
for j=1,numEligibleProfessions do
|
||||
if not self.breakableButtons[j] then
|
||||
self.breakableButtons[j] = {}
|
||||
end
|
||||
|
||||
numBreakableStacks = numBreakableStacks + 1
|
||||
|
||||
if not self.breakableButtons[numBreakableStacks] then
|
||||
self.breakableButtons[numBreakableStacks] = CreateFrame("Button", "BreakablesButtonStackFrame"..numBreakableStacks, self.buttonFrame, "SecureActionButtonTemplate")
|
||||
end
|
||||
local btn = self.breakableButtons[numBreakableStacks]
|
||||
btn:SetPoint("LEFT", numBreakableStacks == 1 and self.buttonFrame or self.breakableButtons[numBreakableStacks - 1], "RIGHT")
|
||||
btn:SetWidth(40)
|
||||
btn:SetHeight(40)
|
||||
btn:EnableMouse(true)
|
||||
btn:RegisterForClicks("AnyUp")
|
||||
|
||||
local BreakableAbilityName = GetSpellInfo((foundBreakables[i][IDX_BREAKABLETYPE] == BREAKABLE_HERB and MillingId) or (foundBreakables[i][IDX_BREAKABLETYPE] == BREAKABLE_ORE and ProspectingId) or DisenchantId)
|
||||
btn:SetAttribute("type", "macro")
|
||||
btn:SetAttribute("macrotext", "/cast "..BreakableAbilityName.."\n/use "..foundBreakables[i][IDX_BAG].." "..foundBreakables[i][IDX_SLOT])
|
||||
|
||||
-- btn:SetAttribute("type1", "item")
|
||||
-- btn:SetAttribute("bag1", foundBreakables[i][IDX_BAG])
|
||||
-- btn:SetAttribute("slot1", foundBreakables[i][IDX_SLOT])
|
||||
|
||||
if not btn.text then
|
||||
btn.text = btn:CreateFontString()
|
||||
btn.text:SetPoint("BOTTOM", btn, "BOTTOM", 0, 2)
|
||||
end
|
||||
btn.text:SetFont("Fonts\\FRIZQT__.TTF", 11, "OUTLINE")
|
||||
|
||||
if not isDisenchantable then
|
||||
btn.text:SetText(foundBreakables[i][IDX_COUNT].." ("..(floor(foundBreakables[i][IDX_COUNT]/5))..")")
|
||||
if not numBreakableStacks[j] then
|
||||
numBreakableStacks[j] = 0
|
||||
end
|
||||
|
||||
btn:SetScript("OnEnter", function(this) self:OnEnterBreakableButton(this, foundBreakables[i]) end)
|
||||
btn:SetScript("OnLeave", function() self:OnLeaveBreakableButton(foundBreakables[i]) end)
|
||||
if foundBreakables[i][IDX_BREAKABLETYPE] == self.buttonFrame[j].type and numBreakableStacks[j] < self.settings.maxBreakablesToShow then
|
||||
local isDisenchantable = self:BreakableIsDisenchantable(foundBreakables[i][IDX_TYPE], foundBreakables[i][IDX_LEVEL])
|
||||
if (CanDisenchant and isDisenchantable) or foundBreakables[i][IDX_COUNT] >= 5 then
|
||||
numBreakableStacks[j] = numBreakableStacks[j] + 1
|
||||
|
||||
if not btn.icon then
|
||||
btn.icon = btn:CreateTexture(nil, "BACKGROUND")
|
||||
end
|
||||
btn.icon:SetTexture(foundBreakables[i][IDX_TEXTURE])
|
||||
btn.icon:SetAllPoints(btn)
|
||||
local btn = self.breakableButtons[j][numBreakableStacks[j]]
|
||||
if not self.breakableButtons[j][numBreakableStacks[j]] then
|
||||
self.breakableButtons[j][numBreakableStacks[j]] = CreateFrame("Button", nil, self.buttonFrame[j], "SecureActionButtonTemplate")
|
||||
|
||||
if numBreakableStacks >= self.settings.maxBreakablesToShow then
|
||||
break
|
||||
btn = self.breakableButtons[j][numBreakableStacks[j]]
|
||||
|
||||
btn:SetPoint("LEFT", numBreakableStacks[j] == 1 and self.buttonFrame[j] or self.breakableButtons[j][numBreakableStacks[j] - 1], "RIGHT")
|
||||
btn:SetWidth(buttonSize * self.settings.buttonScale)
|
||||
btn:SetHeight(buttonSize * self.settings.buttonScale)
|
||||
btn:EnableMouse(true)
|
||||
btn:RegisterForClicks("AnyUp")
|
||||
|
||||
btn:SetAttribute("type", "macro")
|
||||
|
||||
-- btn:SetAttribute("type1", "item")
|
||||
-- btn:SetAttribute("bag1", foundBreakables[i][IDX_BAG])
|
||||
-- btn:SetAttribute("slot1", foundBreakables[i][IDX_SLOT])
|
||||
|
||||
if not btn.text then
|
||||
btn.text = btn:CreateFontString()
|
||||
btn.text:SetPoint("BOTTOM", btn, "BOTTOM", 0, 2)
|
||||
end
|
||||
btn.text:SetFont(NumberFont_Outline_Med:GetFont(), self.settings.fontSize, "OUTLINE")
|
||||
|
||||
if not btn.icon then
|
||||
btn.icon = btn:CreateTexture(nil, "BACKGROUND")
|
||||
end
|
||||
btn.icon:SetAllPoints(btn)
|
||||
end
|
||||
|
||||
if not isDisenchantable then
|
||||
btn.text:SetText(foundBreakables[i][IDX_COUNT].." ("..(floor(foundBreakables[i][IDX_COUNT]/5))..")")
|
||||
end
|
||||
|
||||
local BreakableAbilityName = GetSpellInfo((foundBreakables[i][IDX_BREAKABLETYPE] == BREAKABLE_HERB and MillingId) or (foundBreakables[i][IDX_BREAKABLETYPE] == BREAKABLE_ORE and ProspectingId) or DisenchantId)
|
||||
btn:SetAttribute("macrotext", "/cast "..BreakableAbilityName.."\n/use "..foundBreakables[i][IDX_BAG].." "..foundBreakables[i][IDX_SLOT].."\n/script Breakables.justClicked=true")
|
||||
btn.icon:SetTexture(foundBreakables[i][IDX_TEXTURE])
|
||||
|
||||
btn:SetScript("OnEnter", function(this) self:OnEnterBreakableButton(this, foundBreakables[i]) end)
|
||||
btn:SetScript("OnLeave", function() self:OnLeaveBreakableButton(foundBreakables[i]) end)
|
||||
|
||||
btn:Show()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self.breakableButtons and numBreakableStacks < #self.breakableButtons then
|
||||
for i=numBreakableStacks+1,#self.breakableButtons do
|
||||
self.breakableButtons[i].icon:SetTexture(nil)
|
||||
self.breakableButtons[i].text:SetText()
|
||||
self.breakableButtons[i]:EnableMouse(false)
|
||||
for i=1,numEligibleProfessions do
|
||||
if not numBreakableStacks[i] then
|
||||
numBreakableStacks[i] = 0
|
||||
end
|
||||
end
|
||||
|
||||
if self.buttonFrame then
|
||||
if numBreakableStacks == 0 and self.settings.hideIfNoBreakables then
|
||||
self.buttonFrame:Hide()
|
||||
else
|
||||
self.buttonFrame:Show()
|
||||
if self.breakableButtons[i] and numBreakableStacks[i] < #self.breakableButtons[i] then
|
||||
for j=numBreakableStacks[i]+1,#self.breakableButtons[i] do
|
||||
self.breakableButtons[i][j]:Hide()
|
||||
self.breakableButtons[i][j].icon:SetTexture(nil)
|
||||
end
|
||||
end
|
||||
|
||||
if self.buttonFrame[i] then
|
||||
if numBreakableStacks[i] == 0 and self.settings.hideIfNoBreakables then
|
||||
self.buttonFrame[i]:Hide()
|
||||
else
|
||||
self.buttonFrame[i]:Show()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,13 +1,17 @@
|
||||
## Interface: 30300
|
||||
## Interface: 40000
|
||||
## Author: Parnic
|
||||
## Name: Breakables
|
||||
## Title: Breakables |cff7fff7f -Ace3-|r
|
||||
## Title: Breakables |cff7fff7f-Ace3-|r
|
||||
## Notes: Tracks herbs/ore/items that can be broken into component pieces
|
||||
## Version: @project-version@ (Revision: @project-revision@)
|
||||
## SavedVariables: BreakablesDB
|
||||
## OptionalDeps: Ace3, LibBabble-Inventory-3.0
|
||||
## X-Compatible-With: 40000
|
||||
|
||||
#@no-lib-strip@
|
||||
embeds.xml
|
||||
#@end-no-lib-strip@
|
||||
# LDB is hard-embedded so don't skip it if packaging no-lib
|
||||
LibDataBroker-1.1.lua
|
||||
loc\loc.xml
|
||||
|
||||
Breakables.lua
|
90
LibDataBroker-1.1.lua
Normal file
90
LibDataBroker-1.1.lua
Normal file
@ -0,0 +1,90 @@
|
||||
|
||||
assert(LibStub, "LibDataBroker-1.1 requires LibStub")
|
||||
assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0")
|
||||
|
||||
local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 4)
|
||||
if not lib then return end
|
||||
oldminor = oldminor or 0
|
||||
|
||||
|
||||
lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib)
|
||||
lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {}
|
||||
local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks
|
||||
|
||||
if oldminor < 2 then
|
||||
lib.domt = {
|
||||
__metatable = "access denied",
|
||||
__index = function(self, key) return attributestorage[self] and attributestorage[self][key] end,
|
||||
}
|
||||
end
|
||||
|
||||
if oldminor < 3 then
|
||||
lib.domt.__newindex = function(self, key, value)
|
||||
if not attributestorage[self] then attributestorage[self] = {} end
|
||||
if attributestorage[self][key] == value then return end
|
||||
attributestorage[self][key] = value
|
||||
local name = namestorage[self]
|
||||
if not name then return end
|
||||
callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self)
|
||||
callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self)
|
||||
callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self)
|
||||
callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self)
|
||||
end
|
||||
end
|
||||
|
||||
if oldminor < 2 then
|
||||
function lib:NewDataObject(name, dataobj)
|
||||
if self.proxystorage[name] then return end
|
||||
|
||||
if dataobj then
|
||||
assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table")
|
||||
self.attributestorage[dataobj] = {}
|
||||
for i,v in pairs(dataobj) do
|
||||
self.attributestorage[dataobj][i] = v
|
||||
dataobj[i] = nil
|
||||
end
|
||||
end
|
||||
dataobj = setmetatable(dataobj or {}, self.domt)
|
||||
self.proxystorage[name], self.namestorage[dataobj] = dataobj, name
|
||||
self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj)
|
||||
return dataobj
|
||||
end
|
||||
end
|
||||
|
||||
if oldminor < 1 then
|
||||
function lib:DataObjectIterator()
|
||||
return pairs(self.proxystorage)
|
||||
end
|
||||
|
||||
function lib:GetDataObjectByName(dataobjectname)
|
||||
return self.proxystorage[dataobjectname]
|
||||
end
|
||||
|
||||
function lib:GetNameByDataObject(dataobject)
|
||||
return self.namestorage[dataobject]
|
||||
end
|
||||
end
|
||||
|
||||
if oldminor < 4 then
|
||||
local next = pairs(attributestorage)
|
||||
function lib:pairs(dataobject_or_name)
|
||||
local t = type(dataobject_or_name)
|
||||
assert(t == "string" or t == "table", "Usage: ldb:pairs('dataobjectname') or ldb:pairs(dataobject)")
|
||||
|
||||
local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
|
||||
assert(attributestorage[dataobj], "Data object not found")
|
||||
|
||||
return next, attributestorage[dataobj], nil
|
||||
end
|
||||
|
||||
local ipairs_iter = ipairs(attributestorage)
|
||||
function lib:ipairs(dataobject_or_name)
|
||||
local t = type(dataobject_or_name)
|
||||
assert(t == "string" or t == "table", "Usage: ldb:ipairs('dataobjectname') or ldb:ipairs(dataobject)")
|
||||
|
||||
local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
|
||||
assert(attributestorage[dataobj], "Data object not found")
|
||||
|
||||
return ipairs_iter, attributestorage[dataobj], 0
|
||||
end
|
||||
end
|
@ -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\AceLocale-3.0\AceLocale-3.0.xml"/>
|
||||
<Include file="libs\LibBabble-Inventory-3.0\lib.xml"/>
|
||||
</Ui>
|
4
loc/deDE.lua
Normal file
4
loc/deDE.lua
Normal file
@ -0,0 +1,4 @@
|
||||
local L = LibStub("AceLocale-3.0"):NewLocale("Breakables", "deDE")
|
||||
if not L then return end
|
||||
|
||||
--@localization(locale="deDE", format="lua_additive_table", handle-subnamespaces="concat", handle-unlocalized="english")@
|
13
loc/enUS.lua
Normal file
13
loc/enUS.lua
Normal file
@ -0,0 +1,13 @@
|
||||
local debug = false
|
||||
--@debug@
|
||||
debug = true
|
||||
--@end-debug@
|
||||
|
||||
local L = LibStub("AceLocale-3.0"):NewLocale("Breakables", "enUS", true, debug)
|
||||
|
||||
--@localization(locale="enUS", format="lua_additive_table", same-key-is-true=true, handle-subnamespaces="concat")@
|
||||
--@debug@
|
||||
L["Welcome"] = [[Thanks for using |cff33ff99Breakables|r! Use |cffffff78/brk|r to open this menu or |cffffff78/breakables|r to access the same options on the command line.
|
||||
|
||||
Hold shift and drag the profession button to move the breakables bar around. If you have any feature requests or problems, please email |cff33ff99breakables@parnic.com|r or visit the |cffffff78curse.com|r or |cffffff78wowinterface.com|r page and leave a comment.]]
|
||||
--@end-debug@
|
4
loc/esES.lua
Normal file
4
loc/esES.lua
Normal file
@ -0,0 +1,4 @@
|
||||
local L = LibStub("AceLocale-3.0"):NewLocale("Breakables", "esES")
|
||||
if not L then return end
|
||||
|
||||
--@localization(locale="esES", format="lua_additive_table", handle-subnamespaces="concat", handle-unlocalized="english")@
|
4
loc/esMX.lua
Normal file
4
loc/esMX.lua
Normal file
@ -0,0 +1,4 @@
|
||||
local L = LibStub("AceLocale-3.0"):NewLocale("Breakables", "esMX")
|
||||
if not L then return end
|
||||
|
||||
--@localization(locale="esMX", format="lua_additive_table", handle-subnamespaces="concat", handle-unlocalized="english")@
|
4
loc/frFR.lua
Normal file
4
loc/frFR.lua
Normal file
@ -0,0 +1,4 @@
|
||||
local L = LibStub("AceLocale-3.0"):NewLocale("Breakables", "frFR")
|
||||
if not L then return end
|
||||
|
||||
--@localization(locale="frFR", format="lua_additive_table", handle-subnamespaces="concat", handle-unlocalized="english")@
|
4
loc/koKR.lua
Normal file
4
loc/koKR.lua
Normal file
@ -0,0 +1,4 @@
|
||||
local L = LibStub("AceLocale-3.0"):NewLocale("Breakables", "koKR")
|
||||
if not L then return end
|
||||
|
||||
--@localization(locale="koKR", format="lua_additive_table", handle-subnamespaces="concat", handle-unlocalized="english")@
|
13
loc/loc.xml
Normal file
13
loc/loc.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/..\FrameXML\UI.xsd">
|
||||
|
||||
<Script file="enUS.lua"/>
|
||||
<Script file="deDE.lua"/>
|
||||
<Script file="esES.lua"/>
|
||||
<Script file="esMX.lua"/>
|
||||
<Script file="frFR.lua"/>
|
||||
<Script file="koKR.lua"/>
|
||||
<Script file="ruRU.lua"/>
|
||||
<Script file="zhCN.lua"/>
|
||||
<Script file="zhTW.lua"/>
|
||||
|
||||
</Ui>
|
4
loc/ruRU.lua
Normal file
4
loc/ruRU.lua
Normal file
@ -0,0 +1,4 @@
|
||||
local L = LibStub("AceLocale-3.0"):NewLocale("Breakables", "ruRU")
|
||||
if not L then return end
|
||||
|
||||
--@localization(locale="ruRU", format="lua_additive_table", handle-subnamespaces="concat", handle-unlocalized="english")@
|
4
loc/zhCN.lua
Normal file
4
loc/zhCN.lua
Normal file
@ -0,0 +1,4 @@
|
||||
local L = LibStub("AceLocale-3.0"):NewLocale("Breakables", "zhCN")
|
||||
if not L then return end
|
||||
|
||||
--@localization(locale="zhCN", format="lua_additive_table", handle-subnamespaces="concat", handle-unlocalized="english")@
|
4
loc/zhTW.lua
Normal file
4
loc/zhTW.lua
Normal file
@ -0,0 +1,4 @@
|
||||
local L = LibStub("AceLocale-3.0"):NewLocale("Breakables", "zhTW")
|
||||
if not L then return end
|
||||
|
||||
--@localization(locale="zhTW", format="lua_additive_table", handle-subnamespaces="concat", handle-unlocalized="english")@
|
Reference in New Issue
Block a user