mirror of
https://github.com/parnic/breakables.git
synced 2025-06-17 01:41:51 -05:00
Compare commits
73 Commits
Author | SHA1 | Date | |
---|---|---|---|
bb3316cad3
|
|||
b2c12901f6
|
|||
3c7f556780
|
|||
33679a0e57 | |||
ab8c9eb427
|
|||
98a73a1872
|
|||
85280456af | |||
e388f5243e | |||
d24498372b
|
|||
89191ad299
|
|||
96cac06743
|
|||
10da683630
|
|||
2a0ad73b5f
|
|||
71ee74a273
|
|||
76fa35ef02
|
|||
dd746f2800
|
|||
1792dac5e5
|
|||
aebaa54dc6
|
|||
a7213689f4
|
|||
26156517ec
|
|||
402c88b82d
|
|||
e559af59ec
|
|||
4d6efe8842
|
|||
0322faf629
|
|||
4c816fc5ed
|
|||
bc3632d177
|
|||
713fbf5f16
|
|||
902adfa2c8
|
|||
e0a5f0b97d
|
|||
4d93c119a2
|
|||
c7a8cf4838
|
|||
ba61a08f05
|
|||
7396b7189a
|
|||
d5a1f01749
|
|||
9ac6b125a3
|
|||
6f78aeb7fa
|
|||
450527d1bd
|
|||
de6924ee14
|
|||
b517fbf9f6
|
|||
b08c8c49d2
|
|||
cd34b60c36
|
|||
4fc455150f
|
|||
fb982f7f9d
|
|||
cba6773d1c
|
|||
5286afb4cd
|
|||
d69da1a7d5
|
|||
55c73b3505
|
|||
fcd5d6d1f9
|
|||
c39996022e
|
|||
6c3f3e93e6
|
|||
e84b834139
|
|||
a6d396e88d
|
|||
89dd251093
|
|||
1d6883b1f5
|
|||
cb0cd8749d
|
|||
a98b02e7cb
|
|||
d299ed3d3f
|
|||
4a1d004502
|
|||
a775f7af33
|
|||
3a9db4082a
|
|||
59b1cafee3
|
|||
a27b2a7301
|
|||
8abe349758
|
|||
4cb1d01204
|
|||
016cc6f226
|
|||
f71b527f71
|
|||
a65674510e
|
|||
41592a7c76
|
|||
62c8db483e
|
|||
abf769bf9d
|
|||
9bd5541f81
|
|||
80e495f707
|
|||
3257ce5645
|
22
.github/workflows/release.yml
vendored
22
.github/workflows/release.yml
vendored
@ -23,6 +23,7 @@ jobs:
|
||||
env:
|
||||
CF_API_KEY: ${{ secrets.CF_API_KEY }}
|
||||
WOWI_API_TOKEN: ${{ secrets.WOWI_API_TOKEN }}
|
||||
WAGO_API_TOKEN: ${{ secrets.WAGO_API_TOKEN }}
|
||||
GITHUB_OAUTH: ${{ secrets.GITHUB_TOKEN }} # "GITHUB_TOKEN" is a secret always provided to the workflow
|
||||
# for your own token, the name cannot start with "GITHUB_"
|
||||
|
||||
@ -31,20 +32,33 @@ jobs:
|
||||
|
||||
# we first have to clone the AddOn project, this is a required step
|
||||
- name: Clone project
|
||||
uses: actions/checkout@v1
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # gets git history for changelogs
|
||||
|
||||
# once cloned, we just run the GitHub Action for the packager project
|
||||
- name: Package and release
|
||||
uses: BigWigsMods/packager@master
|
||||
uses: BigWigsMods/packager@v2
|
||||
|
||||
# another example where we supply additional arguments, this example is specifically to release
|
||||
# for the Classic version of the game
|
||||
- name: Package and release for Classic
|
||||
uses: BigWigsMods/packager@master
|
||||
uses: BigWigsMods/packager@v2
|
||||
with:
|
||||
args: -g classic -w 0
|
||||
|
||||
- name: Package and release for TBC
|
||||
uses: BigWigsMods/packager@master
|
||||
uses: BigWigsMods/packager@v2
|
||||
with:
|
||||
args: -g bcc -w 0
|
||||
|
||||
- name: Package and release for Wrath
|
||||
uses: BigWigsMods/packager@v2
|
||||
with:
|
||||
args: -g wrath -w 0
|
||||
|
||||
- name: Package and release for Cataclysm
|
||||
uses: BigWigsMods/packager@v2
|
||||
with:
|
||||
args: -g cata -w 0
|
||||
|
1
.pkgmeta
1
.pkgmeta
@ -37,6 +37,7 @@ externals:
|
||||
|
||||
ignore:
|
||||
- readme.md
|
||||
- FUNDING.yml
|
||||
|
||||
manual-changelog: changelog.txt
|
||||
|
||||
|
540
Breakables.lua
540
Breakables.lua
@ -5,16 +5,91 @@ local LBF = LibStub("Masque", true)
|
||||
|
||||
local lbfGroup
|
||||
|
||||
local IsArtifactRelicItem = IsArtifactRelicItem
|
||||
local IsArtifactRelicItem, GetBagName, GetContainerNumSlots, GetContainerItemInfo, GetContainerItemLink =
|
||||
IsArtifactRelicItem, GetBagName, GetContainerNumSlots, GetContainerItemInfo, GetContainerItemLink
|
||||
if not IsArtifactRelicItem then
|
||||
IsArtifactRelicItem = function()
|
||||
return false
|
||||
end
|
||||
end
|
||||
if C_Container then
|
||||
if C_Container.GetBagName then
|
||||
GetBagName = C_Container.GetBagName
|
||||
end
|
||||
if C_Container.GetContainerNumSlots then
|
||||
GetContainerNumSlots = C_Container.GetContainerNumSlots
|
||||
end
|
||||
if C_Container.GetContainerItemInfo then
|
||||
GetContainerItemInfo = function(bagId, slotId)
|
||||
local info = C_Container.GetContainerItemInfo(bagId, slotId)
|
||||
if not info then
|
||||
return nil
|
||||
end
|
||||
|
||||
return info.iconFileID, info.stackCount
|
||||
end
|
||||
end
|
||||
if C_Container.GetContainerItemLink then
|
||||
GetContainerItemLink = C_Container.GetContainerItemLink
|
||||
end
|
||||
end
|
||||
|
||||
local GetSpellInfo = GetSpellInfo
|
||||
if not GetSpellInfo and C_Spell and C_Spell.GetSpellInfo then
|
||||
GetSpellInfo = function(id)
|
||||
if not id then
|
||||
return nil
|
||||
end
|
||||
|
||||
local info = C_Spell.GetSpellInfo(id)
|
||||
if info then
|
||||
return info.name, nil, info.iconID
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local IsUsableSpell = IsUsableSpell
|
||||
if not IsUsableSpell and C_Spell and C_Spell.IsSpellUsable then
|
||||
IsUsableSpell = C_Spell.IsSpellUsable
|
||||
end
|
||||
|
||||
local EQUIPPED_LAST = EQUIPPED_LAST
|
||||
if not EQUIPPED_LAST then
|
||||
EQUIPPED_LAST = INVSLOT_LAST_EQUIPPED
|
||||
end
|
||||
|
||||
local WowVer = select(4, GetBuildInfo())
|
||||
local IsClassic = WOW_PROJECT_ID and WOW_PROJECT_ID == WOW_PROJECT_CLASSIC
|
||||
local IsClassicBC = WOW_PROJECT_ID and WOW_PROJECT_ID == WOW_PROJECT_BURNING_CRUSADE_CLASSIC
|
||||
local IsClassic = false
|
||||
local IsClassicBC = false
|
||||
local IsClassicWrath = false
|
||||
local IsClassicCataclysm = false
|
||||
if GetClassicExpansionLevel then
|
||||
IsClassic = GetClassicExpansionLevel() == 0
|
||||
IsClassicBC = GetClassicExpansionLevel() == 1
|
||||
IsClassicWrath = GetClassicExpansionLevel() == 2
|
||||
IsClassicCataclysm = GetClassicExpansionLevel() == 3
|
||||
else
|
||||
IsClassic = WOW_PROJECT_ID and WOW_PROJECT_ID == WOW_PROJECT_CLASSIC
|
||||
IsClassicBC = false
|
||||
IsClassicWrath = false
|
||||
IsClassicCataclysm = false
|
||||
if WOW_PROJECT_ID and WOW_PROJECT_ID == WOW_PROJECT_BURNING_CRUSADE_CLASSIC then
|
||||
if not LE_EXPANSION_LEVEL_CURRENT or LE_EXPANSION_LEVEL_CURRENT == LE_EXPANSION_BURNING_CRUSADE then
|
||||
IsClassicBC = true
|
||||
elseif LE_EXPANSION_LEVEL_CURRENT == LE_EXPANSION_WRATH_OF_THE_LICH_KING then
|
||||
IsClassicWrath = true
|
||||
end
|
||||
elseif WOW_PROJECT_WRATH_CLASSIC and WOW_PROJECT_ID == WOW_PROJECT_WRATH_CLASSIC then
|
||||
IsClassicWrath = true
|
||||
elseif WOW_PROJECT_CATACLYSM_CLASSIC and WOW_PROJECT_ID == WOW_PROJECT_CATACLYSM_CLASSIC then
|
||||
IsClassicCataclysm = true
|
||||
end
|
||||
end
|
||||
|
||||
local ShouldHookTradeskillUpdate = WowVer < 80000
|
||||
local ShouldShowTabardControls = WowVer >= 80000
|
||||
local UseNonNativeEqManagerChecks = WowVer < 80000
|
||||
local IgnoreEnchantingSkillLevelForDisenchant = WowVer >= 80000
|
||||
|
||||
local MillingId = 51005
|
||||
local MillingItemSubType = babbleInv["Herb"]
|
||||
@ -148,11 +223,22 @@ local OreCombineItems = {
|
||||
|
||||
local DisenchantId = 13262
|
||||
local DisenchantTypes = {babbleInv["Armor"], babbleInv["Weapon"]}
|
||||
local DisenchantEquipSlots = {"INVTYPE_PROFESSION_GEAR", "INVTYPE_PROFESSION_TOOL"}
|
||||
local CanDisenchant = false
|
||||
local EnchantingProfessionId = 333
|
||||
|
||||
local AdditionalDisenchantableItems = {
|
||||
137195, -- highmountain armor
|
||||
-- dragonflight
|
||||
-- specialization items (Mystics)
|
||||
200939, -- Chromatic Pocketwatch
|
||||
200940, -- Everflowing Inkwell
|
||||
200941, -- Seal of Order
|
||||
200942, -- Vibrant Emulsion
|
||||
200943, -- Whispering Band
|
||||
200945, -- Valiant Hammer
|
||||
200946, -- Thunderous Blade
|
||||
200947, -- Carving of Awakening
|
||||
}
|
||||
|
||||
local PickLockId = 1804
|
||||
@ -190,6 +276,8 @@ local PickableItems = {
|
||||
180533, -- kyrian
|
||||
180522, -- night fae
|
||||
186161, -- stygian lockbox, 9.1.0
|
||||
-- dragonflight
|
||||
190954, -- serevite lockbox
|
||||
}
|
||||
local CanPickLock = false
|
||||
|
||||
@ -211,6 +299,7 @@ local IDX_BREAKABLETYPE = 9
|
||||
local IDX_SOULBOUND = 10
|
||||
local IDX_NAME = 11
|
||||
local IDX_RARITY = 12
|
||||
local IDX_EQUIPSLOT = 13
|
||||
|
||||
local BREAKABLE_HERB = 1
|
||||
local BREAKABLE_ORE = 2
|
||||
@ -219,6 +308,7 @@ local BREAKABLE_PICK = 4
|
||||
local BREAKABLE_COMBINE = 5
|
||||
|
||||
local BagUpdateCheckDelay = 0.1
|
||||
local PickLockFinishedDelay = 1
|
||||
local nextCheck = {}
|
||||
for i=0,NUM_BAG_SLOTS do
|
||||
nextCheck[i] = -1
|
||||
@ -237,6 +327,10 @@ local showingTooltip = nil
|
||||
|
||||
Breakables.optionsFrame = {}
|
||||
Breakables.justClicked = false
|
||||
Breakables.justClickedBag = -1
|
||||
Breakables.justClickedSlot = -1
|
||||
Breakables.justPickedBag = -1
|
||||
Breakables.justPickedSlot = -1
|
||||
|
||||
function Breakables:OnInitialize()
|
||||
self.defaults = {
|
||||
@ -310,11 +404,27 @@ function Breakables:InitLDB()
|
||||
end
|
||||
end
|
||||
|
||||
function Breakables:OnEnable()
|
||||
function Breakables:SetCapabilities()
|
||||
CanMill = IsUsableSpell(GetSpellInfo(MillingId))
|
||||
CanProspect = IsUsableSpell(GetSpellInfo(ProspectingId))
|
||||
CanDisenchant = IsUsableSpell(GetSpellInfo(DisenchantId))
|
||||
CanPickLock = IsUsableSpell(GetSpellInfo(PickLockId))
|
||||
end
|
||||
|
||||
function Breakables:OnSpellsChanged()
|
||||
local couldMill = CanMill
|
||||
local couldProspect = CanProspect
|
||||
local couldDisenchant = CanDisenchant
|
||||
local couldPick = CanPickLock
|
||||
self:SetCapabilities()
|
||||
|
||||
if couldMill ~= CanMill or couldProspect ~= CanProspect or couldDisenchant ~= CanDisenchant or couldPick ~= CanPickLock then
|
||||
self:SetupButtons()
|
||||
end
|
||||
end
|
||||
|
||||
function Breakables:OnEnable()
|
||||
self:SetCapabilities()
|
||||
|
||||
self.EnchantingLevel = 0
|
||||
|
||||
@ -332,7 +442,16 @@ function Breakables:OnEnable()
|
||||
|
||||
self:RegisterEvents()
|
||||
|
||||
if CanMill or CanProspect or CanDisenchant or CanPickLock then
|
||||
self:SetupButtons()
|
||||
end
|
||||
|
||||
local canBreakSomething = function()
|
||||
return CanMill or CanProspect or CanDisenchant or CanPickLock
|
||||
end
|
||||
|
||||
function Breakables:SetupButtons()
|
||||
numEligibleProfessions = 0
|
||||
if canBreakSomething() then
|
||||
if CanMill then
|
||||
numEligibleProfessions = numEligibleProfessions + 1
|
||||
end
|
||||
@ -358,7 +477,7 @@ function Breakables:OnEnable()
|
||||
end
|
||||
self.frame:SetScript("OnUpdate", self.frame.OnUpdateFunc)
|
||||
else
|
||||
self:UnregisterAllEvents()
|
||||
self:CreateButtonFrame()
|
||||
end
|
||||
end
|
||||
|
||||
@ -386,15 +505,15 @@ function Breakables:RegisterEvents()
|
||||
self:RegisterEvent("PLAYER_REGEN_DISABLED", "OnEnterCombat")
|
||||
self:RegisterEvent("PLAYER_REGEN_ENABLED", "OnLeaveCombat")
|
||||
|
||||
self:RegisterEvent("MODIFIER_STATE_CHANGED", "FindBreakables")
|
||||
self:RegisterEvent("SPELLS_CHANGED", "OnSpellsChanged")
|
||||
-- this will show lockboxes if the player gains a level that then enables opening that box
|
||||
self:RegisterEvent("PLAYER_LEVEL_UP", "FindBreakables")
|
||||
|
||||
if CanDisenchant and WowVer < 80000 then
|
||||
if ShouldHookTradeskillUpdate then
|
||||
self:RegisterEvent("TRADE_SKILL_UPDATE", "OnTradeSkillUpdate")
|
||||
end
|
||||
|
||||
if CanPickLock then
|
||||
self:RegisterEvent("CHAT_MSG_OPENING", "OnBagItemLockPicked")
|
||||
end
|
||||
self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED", "OnSpellCastSucceeded")
|
||||
|
||||
if UnitCanPetBattle then
|
||||
self:RegisterEvent("PET_BATTLE_OPENING_START", "PetBattleStarted")
|
||||
@ -402,19 +521,17 @@ function Breakables:RegisterEvents()
|
||||
end
|
||||
end
|
||||
|
||||
function Breakables:OnModifierChanged()
|
||||
if showingTooltip ~= nil and not self.bCombat then
|
||||
self:OnEnterBreakableButton(showingTooltip)
|
||||
end
|
||||
end
|
||||
|
||||
function Breakables:OnDisable()
|
||||
self:UnregisterAllEvents()
|
||||
self.frame:SetScript("OnUpdate", nil)
|
||||
end
|
||||
|
||||
function Breakables:OnSlashCommand(input)
|
||||
if InterfaceOptionsFrame_OpenToCategory then
|
||||
InterfaceOptionsFrame_OpenToCategory(self.optionsFrame)
|
||||
else
|
||||
Settings.OpenToCategory("Breakables")
|
||||
end
|
||||
end
|
||||
|
||||
function Breakables:OnItemReceived(event, bag)
|
||||
@ -427,7 +544,14 @@ function Breakables:OnItemReceived(event, bag)
|
||||
end
|
||||
end
|
||||
|
||||
local STATE_IDLE, STATE_SCANNING = 0, 1
|
||||
local currState = STATE_IDLE
|
||||
function Breakables:CheckShouldFindBreakables()
|
||||
if currState == STATE_SCANNING then
|
||||
self:FindBreakables()
|
||||
return
|
||||
end
|
||||
|
||||
local latestTime = -1
|
||||
for i=0,#nextCheck do
|
||||
if nextCheck[i] and nextCheck[i] > latestTime then
|
||||
@ -436,10 +560,10 @@ function Breakables:CheckShouldFindBreakables()
|
||||
end
|
||||
|
||||
if latestTime > 0 and latestTime <= GetTime() then
|
||||
self:FindBreakables()
|
||||
for i=0,#nextCheck do
|
||||
nextCheck[i] = -1
|
||||
end
|
||||
self:FindBreakables()
|
||||
end
|
||||
end
|
||||
|
||||
@ -460,12 +584,24 @@ function Breakables:OnLeaveCombat()
|
||||
end
|
||||
|
||||
function Breakables:OnTradeSkillUpdate()
|
||||
if not CanDisenchant then
|
||||
return
|
||||
end
|
||||
|
||||
self:GetEnchantingLevel()
|
||||
self:FindBreakables()
|
||||
end
|
||||
|
||||
function Breakables:OnBagItemLockPicked()
|
||||
function Breakables:OnSpellCastSucceeded(evt, unit, guid, spell)
|
||||
if spell ~= PickLockId or not CanPickLock then
|
||||
return
|
||||
end
|
||||
|
||||
self.justPickedBag = self.justClickedBag
|
||||
self.justPickedSlot = self.justClickedSlot
|
||||
|
||||
self:FindBreakables()
|
||||
nextCheck[0] = GetTime() + PickLockFinishedDelay
|
||||
end
|
||||
|
||||
function Breakables:PetBattleStarted()
|
||||
@ -498,6 +634,14 @@ function Breakables:GetEnchantingLevel()
|
||||
self.EnchantingLevel = rank
|
||||
end
|
||||
end
|
||||
elseif GetSkillLineInfo then
|
||||
for i=1,100 do
|
||||
local skillName, header, isExpanded, skillRank, numTempPoints, skillModifier, skillMaxRank, isAbandonable, stepCost, rankCost, minLevel, skillCostType = GetSkillLineInfo(i)
|
||||
if skillName == babbleInv["Enchanting"] then
|
||||
self.EnchantingLevel = skillRank
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -536,6 +680,11 @@ function Breakables:GetOptions()
|
||||
name = L["Welcome"],
|
||||
order = 0,
|
||||
},
|
||||
mainSettings = {
|
||||
name = L["Settings"],
|
||||
type = "group",
|
||||
order = 1,
|
||||
args = {
|
||||
hideAlways = {
|
||||
type = "toggle",
|
||||
name = L["Hide bar"],
|
||||
@ -546,7 +695,7 @@ function Breakables:GetOptions()
|
||||
set = function(info, v)
|
||||
self.settings.hide = v
|
||||
if info.uiType == "cmd" then
|
||||
print("|cff33ff99Breakables|r: set |cffffff78maxBreakables|r to " .. tostring(self.settings.hide))
|
||||
print("|cff33ff99Breakables|r: set |cffffff78hideAlways|r to " .. tostring(self.settings.hide))
|
||||
end
|
||||
self:ToggleButtonFrameVisibility(not v)
|
||||
if not v then
|
||||
@ -565,7 +714,7 @@ function Breakables:GetOptions()
|
||||
set = function(info, v)
|
||||
self.settings.hideIfNoBreakables = v
|
||||
if info.uiType == "cmd" then
|
||||
print("|cff33ff99Breakables|r: set |cffffff78hideIfNoBreakables|r to " .. tostring(self.settings.hideIfNoBreakables))
|
||||
print("|cff33ff99Breakables|r: set |cffffff78hideNoBreakables|r to " .. tostring(self.settings.hideIfNoBreakables))
|
||||
end
|
||||
self:FindBreakables()
|
||||
end,
|
||||
@ -654,6 +803,9 @@ function Breakables:GetOptions()
|
||||
set = function(info, v)
|
||||
self.settings.growDirection = v
|
||||
self:FindBreakables()
|
||||
if info.uiType == "cmd" then
|
||||
print("|cff33ff99Breakables|r: set |cffffff78growDirection|r to " .. tostring(self.settings.growDirection))
|
||||
end
|
||||
end,
|
||||
order = 7,
|
||||
},
|
||||
@ -687,6 +839,25 @@ function Breakables:GetOptions()
|
||||
end,
|
||||
order = 9,
|
||||
},
|
||||
showNonUnlockableItems = {
|
||||
type = 'toggle',
|
||||
name = L['Show high-level lockboxes'],
|
||||
desc = L['If checked, a lockbox that is too high level for the player to pick will still be shown in the list, otherwise it will be hidden.'],
|
||||
get = function(info)
|
||||
return self.settings.showNonUnlockableItems
|
||||
end,
|
||||
set = function(info, v)
|
||||
self.settings.showNonUnlockableItems = v
|
||||
self:FindBreakables()
|
||||
if info.uiType == "cmd" then
|
||||
print("|cff33ff99Breakables|r: set |cffffff78showNonUnlockableItems|r to " .. tostring(self.settings.showNonUnlockableItems))
|
||||
end
|
||||
end,
|
||||
hidden = function()
|
||||
return not CanPickLock or not C_TooltipInfo
|
||||
end,
|
||||
order = 10,
|
||||
},
|
||||
ignoreList = {
|
||||
type = 'multiselect',
|
||||
name = L["Ignore list"],
|
||||
@ -720,11 +891,7 @@ function Breakables:GetOptions()
|
||||
hidden = function() return not IsIgnoringAnything() end,
|
||||
order = 31,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if CanDisenchant then
|
||||
opts.args.showSoulbound = {
|
||||
showSoulbound = {
|
||||
type = "toggle",
|
||||
name = L["Show soulbound items"],
|
||||
desc = L["Whether or not to display soulbound items as breakables."],
|
||||
@ -738,10 +905,39 @@ function Breakables:GetOptions()
|
||||
end
|
||||
self:FindBreakables()
|
||||
end,
|
||||
hidden = function()
|
||||
return not CanDisenchant
|
||||
end,
|
||||
order = 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
reset = {
|
||||
name = L["Reset"],
|
||||
type = "group",
|
||||
order = 2,
|
||||
args = {
|
||||
resetPlacement = {
|
||||
type = "execute",
|
||||
name = L["Reset placement"],
|
||||
desc = L["Resets where the buttons are placed on the screen to the default location."],
|
||||
func = function(info)
|
||||
self.settings.buttonFrameLeft = self.defaults.profile.buttonFrameLeft
|
||||
self.settings.buttonFrameTop = self.defaults.profile.buttonFrameTop
|
||||
self:CreateButtonFrame()
|
||||
if info.uiType == "cmd" then
|
||||
print("|cff33ff99Breakables|r: reset placement of button")
|
||||
end
|
||||
end,
|
||||
order = 30,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if GetNumEquipmentSets or C_EquipmentSet then
|
||||
opts.args.hideEqManagerItems = {
|
||||
opts.args.mainSettings.args.hideEqManagerItems = {
|
||||
type = "toggle",
|
||||
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."],
|
||||
@ -756,13 +952,14 @@ function Breakables:GetOptions()
|
||||
self:FindBreakables()
|
||||
end,
|
||||
hidden = function()
|
||||
return not self.settings.showSoulbound
|
||||
return not CanDisenchant and not self.settings.showSoulbound
|
||||
end,
|
||||
order = 21,
|
||||
}
|
||||
end
|
||||
if WowVer >= 80000 then
|
||||
opts.args.hideTabards = {
|
||||
|
||||
if ShouldShowTabardControls then
|
||||
opts.args.mainSettings.args.hideTabards = {
|
||||
type = "toggle",
|
||||
name = L["Hide Tabards"],
|
||||
desc = L["Whether or not to hide tabards from the disenchantable items list."],
|
||||
@ -779,10 +976,28 @@ function Breakables:GetOptions()
|
||||
order = 22,
|
||||
}
|
||||
end
|
||||
|
||||
if not IgnoreEnchantingSkillLevelForDisenchant then
|
||||
opts.args.mainSettings.args.ignoreEnchantingSkillLevel = {
|
||||
type = "toggle",
|
||||
name = L["Ignore Enchanting skill level"],
|
||||
desc = L["Whether or not items should be shown when Breakables thinks you don't have the appropriate skill level to disenchant it."],
|
||||
get = function(info)
|
||||
return self.settings.ignoreEnchantingSkillLevel
|
||||
end,
|
||||
set = function(info, v)
|
||||
self.settings.ignoreEnchantingSkillLevel = v
|
||||
self:FindBreakables()
|
||||
if info.uiType == "cmd" then
|
||||
print("|cff33ff99Breakables|r: set |cffffff78ignoreEnchantingSkillLevel|r to " .. tostring(self.settings.ignoreEnchantingSkillLevel))
|
||||
end
|
||||
end,
|
||||
order = 10,
|
||||
}
|
||||
end
|
||||
|
||||
if UnitCanPetBattle then
|
||||
opts.args.hideInPetBattle = {
|
||||
opts.args.mainSettings.args.hideInPetBattle = {
|
||||
type = "toggle",
|
||||
name = L["Hide during pet battles"],
|
||||
desc = L["Whether or not to hide the breakables bar when you enter a pet battle."],
|
||||
@ -811,6 +1026,11 @@ function Breakables:CreateButtonFrame()
|
||||
self.buttonFrame = {}
|
||||
end
|
||||
|
||||
for i=numEligibleProfessions+1,#self.buttonFrame do
|
||||
self.buttonFrame[i]:ClearAllPoints()
|
||||
self.buttonFrame[i]:Hide()
|
||||
end
|
||||
|
||||
for i=1,numEligibleProfessions do
|
||||
if not self.buttonFrame[i] then
|
||||
self.buttonFrame[i] = CreateFrame("Button", "BREAKABLES_BUTTON_FRAME"..i, self.frame, "SecureActionButtonTemplate")
|
||||
@ -833,7 +1053,7 @@ function Breakables:CreateButtonFrame()
|
||||
frame:SetHeight(buttonSize)
|
||||
|
||||
frame:EnableMouse(true)
|
||||
frame:RegisterForClicks("LeftButtonUp")
|
||||
frame:RegisterForClicks("LeftButtonUp", "LeftButtonDown")
|
||||
|
||||
if not frame.OnMouseDownFunc then
|
||||
frame.OnMouseDownFunc = function(frame) self:OnMouseDown(frame) end
|
||||
@ -928,32 +1148,65 @@ function Breakables:OnMouseUp(frame)
|
||||
self.settings.buttonFrameTop[frameNum] = frame:GetTop()
|
||||
end
|
||||
|
||||
local function IgnoreFunc(self, button)
|
||||
if button == "RightButton" and not InCombatLockdown() then
|
||||
Breakables.settings.ignoreList[self.itemId] = true
|
||||
StaticPopupDialogs["BREAKABLES_CONFIRM_IGNORE"] = {
|
||||
text = L["This will add the chosen item to the ignore list so it no longer appears as breakable. Items can be removed from the ignore list in the Breakables settings.\n\nWould you like to ignore this item?"],
|
||||
button1 = YES,
|
||||
OnShow = function(self)
|
||||
self:SetFrameStrata("TOOLTIP")
|
||||
end,
|
||||
OnHide = function(self)
|
||||
self:SetFrameStrata("DIALOG")
|
||||
end,
|
||||
OnAccept = function(self, data)
|
||||
Breakables.settings.ignoreList[data] = true
|
||||
Breakables:FindBreakables()
|
||||
LibStub("AceConfigRegistry-3.0"):NotifyChange("Breakables")
|
||||
end,
|
||||
button2 = NO,
|
||||
timeout = 0,
|
||||
whileDead = 1,
|
||||
hideOnEscape = 0
|
||||
}
|
||||
|
||||
local function IgnoreFunc(self, button, isDown)
|
||||
if button == "RightButton" and isDown and not InCombatLockdown() then
|
||||
local dlg = StaticPopup_Show("BREAKABLES_CONFIRM_IGNORE")
|
||||
if dlg then
|
||||
dlg.data = self.itemId
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Breakables:FindBreakables(bag)
|
||||
do
|
||||
local bagId = 0
|
||||
local updatefunc
|
||||
local foundBreakables = {}
|
||||
function Breakables:FindBreakables()
|
||||
if self.settings.hide then
|
||||
return
|
||||
end
|
||||
|
||||
if not canBreakSomething() then
|
||||
return
|
||||
end
|
||||
|
||||
if self.bCombat then
|
||||
self.bPendingUpdate = true
|
||||
return
|
||||
end
|
||||
|
||||
local foundBreakables = {}
|
||||
local i=1
|
||||
if currState ~= STATE_SCANNING then
|
||||
local count = #foundBreakables
|
||||
for i=0, count do
|
||||
foundBreakables[i]=nil
|
||||
end
|
||||
end
|
||||
currState = STATE_SCANNING
|
||||
local i=#foundBreakables + 1
|
||||
local numBreakableStacks = {}
|
||||
|
||||
for bagId=0,NUM_BAG_SLOTS do
|
||||
-- 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 maxTime = GetTimePreciseSec() + 0.01
|
||||
while bagId <= NUM_BAG_SLOTS do
|
||||
local found = self:FindBreakablesInBag(bagId)
|
||||
for n=1,#found do
|
||||
local addedToExisting = self:MergeBreakables(found[n], foundBreakables)
|
||||
@ -963,8 +1216,16 @@ function Breakables:FindBreakables(bag)
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
--end
|
||||
|
||||
bagId = bagId + 1
|
||||
|
||||
if maxTime < GetTimePreciseSec() then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
bagId = 0
|
||||
currState = STATE_IDLE
|
||||
|
||||
self:SortBreakables(foundBreakables)
|
||||
|
||||
@ -983,7 +1244,7 @@ function Breakables:FindBreakables(bag)
|
||||
end
|
||||
|
||||
if (foundBreakables[i][IDX_BREAKABLETYPE] == self.buttonFrame[j].type or (foundBreakables[i][IDX_BREAKABLETYPE] == BREAKABLE_COMBINE and foundBreakables[i][IDX_COUNT] >= 10)) and numBreakableStacks[j] < self.settings.maxBreakablesToShow then
|
||||
local isDisenchantable = self:BreakableIsDisenchantable(foundBreakables[i][IDX_TYPE], foundBreakables[i][IDX_LEVEL], foundBreakables[i][IDX_RARITY], foundBreakables[i][IDX_LINK])
|
||||
local isDisenchantable = self:BreakableIsDisenchantable(foundBreakables[i][IDX_TYPE], foundBreakables[i][IDX_LEVEL], foundBreakables[i][IDX_RARITY], foundBreakables[i][IDX_LINK], nil, foundBreakables[i][IDX_EQUIPSLOT])
|
||||
local isLockedItem = foundBreakables[i][IDX_BREAKABLETYPE] == BREAKABLE_PICK
|
||||
|
||||
if (CanDisenchant and isDisenchantable) or (CanPickLock and isLockedItem) or (foundBreakables[i][IDX_COUNT] >= 5) then
|
||||
@ -1003,7 +1264,7 @@ function Breakables:FindBreakables(bag)
|
||||
btn:SetWidth(buttonSize)
|
||||
btn:SetHeight(buttonSize)
|
||||
btn:EnableMouse(true)
|
||||
btn:RegisterForClicks("AnyUp")
|
||||
btn:RegisterForClicks("AnyUp", "AnyDown")
|
||||
|
||||
btn:SetAttribute("type1", "spell")
|
||||
|
||||
@ -1122,6 +1383,7 @@ function Breakables:FindBreakables(bag)
|
||||
self:OnEnterBreakableButton(showingTooltip)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Breakables:OnEnterProfessionButton(btn)
|
||||
local spellId = self:GetSpellIdFromProfessionButton(btn.type)
|
||||
@ -1161,6 +1423,9 @@ function Breakables:OnLeaveBreakableButton()
|
||||
end
|
||||
|
||||
function Breakables:PostClickedBreakableButton(this)
|
||||
self.justClickedBag = this.bag
|
||||
self.justClickedSlot = this.slot
|
||||
|
||||
if this.type == BREAKABLE_HERB or this.type == BREAKABLE_ORE or this.type == BREAKABLE_DE or this.type == BREAKABLE_COMBINE then
|
||||
self.justClicked = true
|
||||
end
|
||||
@ -1174,6 +1439,7 @@ function Breakables:FindBreakablesInBag(bagId)
|
||||
for slotId=1,GetContainerNumSlots(bagId) do
|
||||
local found = self:FindBreakablesInSlot(bagId, slotId)
|
||||
if found then
|
||||
if bagId ~= self.justPickedBag or slotId ~= self.justPickedSlot then
|
||||
local addedToExisting = self:MergeBreakables(found, foundBreakables)
|
||||
|
||||
if not addedToExisting then
|
||||
@ -1181,19 +1447,60 @@ function Breakables:FindBreakablesInBag(bagId)
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
elseif bagId == self.justPickedBag and slotId == self.justPickedSlot then
|
||||
self.justPickedBag = -1
|
||||
self.justPickedSlot = -1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return foundBreakables
|
||||
end
|
||||
|
||||
function Breakables:ScanForTooltipLine(tooltipData, ...)
|
||||
if tooltipData then
|
||||
for _, line in ipairs(tooltipData.lines) do
|
||||
if not line then
|
||||
return false
|
||||
end
|
||||
if not line.leftText then
|
||||
return false
|
||||
end
|
||||
|
||||
for j=1,select('#', ...) do
|
||||
if line.leftText == select(j, ...) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
for i=1,15 do
|
||||
local leftText = _G["BreakablesTooltipTextLeft"..i]
|
||||
local textLine = leftText and leftText:GetText() or nil
|
||||
if not textLine then
|
||||
return false
|
||||
end
|
||||
|
||||
for j=1,select('#', ...) do
|
||||
if textLine == select(j, ...) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function Breakables:FindBreakablesInSlot(bagId, slotId)
|
||||
if not self.myTooltip then
|
||||
if not C_TooltipInfo and not self.myTooltip then
|
||||
self.myTooltip = CreateFrame("GameTooltip", "BreakablesTooltip", nil, "GameTooltipTemplate")
|
||||
self.myTooltip:SetOwner(WorldFrame, "ANCHOR_NONE")
|
||||
end
|
||||
|
||||
local texture, itemCount, locked, quality, readable = GetContainerItemInfo(bagId, slotId)
|
||||
local texture, itemCount = GetContainerItemInfo(bagId, slotId)
|
||||
if texture then
|
||||
local itemLink = GetContainerItemLink(bagId, slotId)
|
||||
local itemId = self:GetItemIdFromLink(itemLink)
|
||||
@ -1203,21 +1510,22 @@ function Breakables:FindBreakablesInSlot(bagId, slotId)
|
||||
|
||||
local itemName, _, itemRarity, itemLevel, _, itemType, itemSubType, _, equipSlot, itemTexture, vendorPrice = GetItemInfo(itemLink)
|
||||
|
||||
local tooltipData
|
||||
if C_TooltipInfo then
|
||||
tooltipData = C_TooltipInfo.GetBagItem(bagId, slotId)
|
||||
if TooltipUtil and TooltipUtil.SurfaceArgs then
|
||||
TooltipUtil.SurfaceArgs(tooltipData)
|
||||
for _, line in ipairs(tooltipData.lines) do
|
||||
TooltipUtil.SurfaceArgs(line)
|
||||
end
|
||||
end
|
||||
else
|
||||
self.myTooltip:SetBagItem(bagId, slotId)
|
||||
end
|
||||
|
||||
if CanDisenchant and itemRarity and itemRarity >= RARITY_UNCOMMON and itemRarity < RARITY_HEIRLOOM
|
||||
and self:BreakableIsDisenchantable(itemType, itemLevel, itemRarity, itemLink, itemId) then
|
||||
local i = 1
|
||||
local soulbound = false
|
||||
for i=1,15 do
|
||||
if _G["BreakablesTooltipTextLeft"..i] then
|
||||
local textLine = _G["BreakablesTooltipTextLeft"..i]:GetText()
|
||||
if textLine == ITEM_SOULBOUND or textLine == ITEM_ACCOUNTBOUND or textLine == ITEM_BNETACCOUNTBOUND then
|
||||
soulbound = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
and self:BreakableIsDisenchantable(itemType, itemLevel, itemRarity, itemLink, itemId, equipSlot) then
|
||||
local soulbound = self:ScanForTooltipLine(tooltipData, ITEM_SOULBOUND, ITEM_ACCOUNTBOUND, ITEM_BNETACCOUNTBOUND)
|
||||
|
||||
local isInEquipmentSet = false
|
||||
if self.settings.hideEqManagerItems then
|
||||
@ -1232,27 +1540,14 @@ function Breakables:FindBreakablesInSlot(bagId, slotId)
|
||||
local shouldHideThisItem = (self.settings.hideEqManagerItems and isInEquipmentSet) or (self.settings.hideTabards and isTabard)
|
||||
or equipSlot == nil or (equipSlot == "" and not IsArtifactRelicItem(itemLink))
|
||||
|
||||
if (not soulbound or self.settings.showSoulbound) and not shouldHideThisItem then
|
||||
return {itemLink, itemCount, itemType, itemTexture, bagId, slotId, itemSubType, itemLevel, BREAKABLE_DE, soulbound, itemName, itemRarity}
|
||||
if self:IsForcedDisenchantable(itemId) or ((not soulbound or self.settings.showSoulbound) and not shouldHideThisItem) then
|
||||
return {itemLink, itemCount, itemType, itemTexture, bagId, slotId, itemSubType, itemLevel, BREAKABLE_DE, soulbound, itemName, itemRarity, equipSlot}
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
local idx = 1
|
||||
local millable = false
|
||||
local prospectable = false
|
||||
for idx=1,5 do
|
||||
if _G["BreakablesTooltipTextLeft"..idx] then
|
||||
if _G["BreakablesTooltipTextLeft"..idx]:GetText() == ITEM_MILLABLE then
|
||||
millable = true
|
||||
break
|
||||
elseif _G["BreakablesTooltipTextLeft"..idx]:GetText() == ITEM_PROSPECTABLE then
|
||||
prospectable = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
local millable = self:ScanForTooltipLine(tooltipData, ITEM_MILLABLE)
|
||||
|
||||
if CanMill and not millable then
|
||||
for i=1,#AdditionalMillableItems do
|
||||
@ -1262,7 +1557,9 @@ function Breakables:FindBreakablesInSlot(bagId, slotId)
|
||||
end
|
||||
end
|
||||
|
||||
local prospectable
|
||||
if CanProspect then
|
||||
prospectable = self:ScanForTooltipLine(tooltipData, ITEM_PROSPECTABLE)
|
||||
if not prospectable then
|
||||
for i=1,#AdditionalProspectableItems do
|
||||
if AdditionalProspectableItems[i] == itemId then
|
||||
@ -1281,11 +1578,11 @@ function Breakables:FindBreakablesInSlot(bagId, slotId)
|
||||
|
||||
if CanMill --[[and (itemSubType == MillingItemSubType or itemSubType == MillingItemSecondarySubType)]] then
|
||||
if millable then
|
||||
return {itemLink, itemCount, itemType, itemTexture, bagId, slotId, itemSubType, itemLevel, BREAKABLE_HERB, false, itemName, itemRarity}
|
||||
return {itemLink, itemCount, itemType, itemTexture, bagId, slotId, itemSubType, itemLevel, BREAKABLE_HERB, false, itemName, itemRarity, equipSlot}
|
||||
else
|
||||
for i=1,#HerbCombineItems do
|
||||
if HerbCombineItems[i] == itemId then
|
||||
return {itemLink, itemCount, itemType, itemTexture, bagId, slotId, itemSubType, itemLevel, BREAKABLE_COMBINE, false, itemName, itemRarity}
|
||||
return {itemLink, itemCount, itemType, itemTexture, bagId, slotId, itemSubType, itemLevel, BREAKABLE_COMBINE, false, itemName, itemRarity, equipSlot}
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1293,24 +1590,49 @@ function Breakables:FindBreakablesInSlot(bagId, slotId)
|
||||
|
||||
if CanProspect --[[and itemSubType == ProspectingItemSubType]] then
|
||||
if prospectable then
|
||||
return {itemLink, itemCount, itemType, itemTexture, bagId, slotId, itemSubType, itemLevel, BREAKABLE_ORE, false, itemName, itemRarity}
|
||||
return {itemLink, itemCount, itemType, itemTexture, bagId, slotId, itemSubType, itemLevel, BREAKABLE_ORE, false, itemName, itemRarity, equipSlot}
|
||||
else
|
||||
for i=1,#OreCombineItems do
|
||||
if OreCombineItems[i] == itemId then
|
||||
return {itemLink, itemCount, itemType, itemTexture, bagId, slotId, itemSubType, itemLevel, BREAKABLE_COMBINE, false, itemName, itemRarity}
|
||||
return {itemLink, itemCount, itemType, itemTexture, bagId, slotId, itemSubType, itemLevel, BREAKABLE_COMBINE, false, itemName, itemRarity, equipSlot}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if CanPickLock and self:ItemIsPickable(itemId) and self:ItemIsLocked(bagId, slotId) then
|
||||
return {itemLink, itemCount, itemType, itemTexture, bagId, slotId, itemSubType, itemLevel, BREAKABLE_PICK, false, itemName, itemRarity}
|
||||
if CanPickLock and self:ItemIsPickable(itemId) and self:ItemIsLocked(bagId, slotId) and self:PlayerHasSkillToPickItem(bagId, slotId) then
|
||||
return {itemLink, itemCount, itemType, itemTexture, bagId, slotId, itemSubType, itemLevel, BREAKABLE_PICK, false, itemName, itemRarity, equipSlot}
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function Breakables:PlayerHasSkillToPickItem(bagId, slotId)
|
||||
if not C_TooltipInfo or self.settings.showNonUnlockableItems then
|
||||
return true
|
||||
end
|
||||
|
||||
local tooltipData = C_TooltipInfo.GetBagItem(bagId, slotId)
|
||||
if not tooltipData then
|
||||
return true
|
||||
end
|
||||
|
||||
if TooltipUtil and TooltipUtil.SurfaceArgs then
|
||||
TooltipUtil.SurfaceArgs(tooltipData)
|
||||
end
|
||||
for _, line in ipairs(tooltipData.lines) do
|
||||
if TooltipUtil and TooltipUtil.SurfaceArgs then
|
||||
TooltipUtil.SurfaceArgs(line)
|
||||
end
|
||||
if line.leftText == LOCKED then
|
||||
return not (line.leftColor and line.leftColor.r == 1 and line.leftColor.g < 0.2 and line.leftColor.b < 0.2)
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function Breakables:ItemIsPickable(itemId)
|
||||
for i=1,#PickableItems do
|
||||
if PickableItems[i] == itemId then
|
||||
@ -1355,7 +1677,7 @@ do
|
||||
end
|
||||
|
||||
function Breakables:IsInEquipmentSet(itemId)
|
||||
if WowVer < 80000 and GetNumEquipmentSets then
|
||||
if UseNonNativeEqManagerChecks and GetNumEquipmentSets then
|
||||
for setIdx=1, GetNumEquipmentSets() do
|
||||
local set = GetEquipmentSetInfo(setIdx)
|
||||
local itemArray = GetEquipmentSetItemIDs(set)
|
||||
@ -1383,7 +1705,12 @@ function Breakables:IsInEquipmentSet(itemId)
|
||||
end
|
||||
|
||||
function Breakables:GetItemIdFromLink(itemLink)
|
||||
local _, foundItemId = strsplit(":", itemLink)
|
||||
local _, num1, num2 = strsplit(":", itemLink)
|
||||
local foundItemId = num1
|
||||
-- support new item link format that adds a new : section in front
|
||||
if not tonumber(foundItemId) then
|
||||
foundItemId = num2
|
||||
end
|
||||
return tonumber(foundItemId)
|
||||
end
|
||||
|
||||
@ -1408,7 +1735,7 @@ function Breakables:SortBreakables(foundBreakables)
|
||||
local iId = self:GetItemIdFromLink(foundBreakables[i][IDX_LINK])
|
||||
for j=i,#foundBreakables do
|
||||
local jId = self:GetItemIdFromLink(foundBreakables[j][IDX_LINK])
|
||||
if iId < jId then
|
||||
if iId > jId then
|
||||
local temp = foundBreakables[i]
|
||||
foundBreakables[i] = foundBreakables[j]
|
||||
foundBreakables[j] = temp
|
||||
@ -1417,11 +1744,23 @@ function Breakables:SortBreakables(foundBreakables)
|
||||
end
|
||||
end
|
||||
|
||||
function Breakables:BreakableIsDisenchantable(itemType, itemLevel, itemRarity, itemLink, itemId)
|
||||
for i=1,#DisenchantTypes do
|
||||
if DisenchantTypes[i] == itemType or IsArtifactRelicItem(itemLink) then
|
||||
-- temp hack for bfa until disenchant item level scales are identified. and for classic until finding the profession level api
|
||||
if WowVer >= 80000 or IsClassic or IsClassicBC then
|
||||
function Breakables:BreakableIsDisenchantable(itemType, itemLevel, itemRarity, itemLink, itemId, equipSlot)
|
||||
if not itemId and itemLink then
|
||||
itemId = self:GetItemIdFromLink(itemLink)
|
||||
end
|
||||
|
||||
if self:IsDisenchantableItemType(itemType) or IsArtifactRelicItem(itemLink) or self:IsDisenchantableEquipSlot(equipSlot) then
|
||||
-- bfa+ no longer has skill level requirements for disenchanting
|
||||
if IgnoreEnchantingSkillLevelForDisenchant then
|
||||
return true
|
||||
end
|
||||
|
||||
if self.settings.ignoreEnchantingSkillLevel then
|
||||
return true
|
||||
end
|
||||
|
||||
-- if we couldn't figure out the player's enchanting skill level, err on the side of showing stuff
|
||||
if self.EnchantingLevel == 0 then
|
||||
return true
|
||||
end
|
||||
|
||||
@ -1518,8 +1857,11 @@ function Breakables:BreakableIsDisenchantable(itemType, itemLevel, itemRarity, i
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
return self:IsForcedDisenchantable(itemId)
|
||||
end
|
||||
|
||||
function Breakables:IsForcedDisenchantable(itemId)
|
||||
for i=1,#AdditionalDisenchantableItems do
|
||||
if AdditionalDisenchantableItems[i] == itemId then
|
||||
return true
|
||||
@ -1528,3 +1870,23 @@ function Breakables:BreakableIsDisenchantable(itemType, itemLevel, itemRarity, i
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function Breakables:IsDisenchantableItemType(itemType)
|
||||
for i=1,#DisenchantTypes do
|
||||
if DisenchantTypes[i] == itemType then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function Breakables:IsDisenchantableEquipSlot(equipSlot)
|
||||
for i=1,#DisenchantEquipSlots do
|
||||
if DisenchantEquipSlots[i] == equipSlot then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
@ -1,7 +1,9 @@
|
||||
## Interface: 90205
|
||||
## Interface-Retail: 90205
|
||||
## Interface-Classic: 11403
|
||||
## Interface: 110105
|
||||
## Interface-Retail: 110105
|
||||
## Interface-Classic: 11507
|
||||
## Interface-BCC: 20504
|
||||
## Interface-Wrath: 30403
|
||||
## Interface-Cata: 40402
|
||||
## Author: Parnic
|
||||
## Name: Breakables
|
||||
## Title: Breakables |cff7fff7f-Ace3-|r
|
||||
@ -13,9 +15,22 @@
|
||||
# ## Version: @project-version@
|
||||
#@end-non-debug@
|
||||
## SavedVariables: BreakablesDB
|
||||
## IconTexture: Interface\Icons\ability_warrior_sunder
|
||||
## OptionalDeps: Ace3, LibBabble-Inventory-3.0, Masque
|
||||
## X-Curse-Project-ID: 16629
|
||||
## X-WoWI-ID: 17929
|
||||
## X-Wago-ID: rkGrlA6y
|
||||
## Category-enUS: Professions
|
||||
## Category-deDE: Berufe
|
||||
## Category-esES: Profesiones
|
||||
## Category-esMX: Profesiones
|
||||
## Category-frFR: Métiers
|
||||
## Category-itIT: Professioni
|
||||
## Category-koKR: 전문 기술
|
||||
## Category-ptBR: Profissões
|
||||
## Category-ruRU: Профессии
|
||||
## Category-zhCN: 专业
|
||||
## Category-zhTW: 專業技能
|
||||
|
||||
#@no-lib-strip@
|
||||
embeds.xml
|
||||
|
3
FUNDING.yml
Normal file
3
FUNDING.yml
Normal file
@ -0,0 +1,3 @@
|
||||
github: parnic
|
||||
ko_fi: parnic
|
||||
custom: "https://www.paypal.me/parnic"
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 parnic
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
170
changelog.txt
170
changelog.txt
@ -1,3 +1,173 @@
|
||||
v1.10.8:
|
||||
|
||||
- Support WoW 11.1.5 (fixes #15)
|
||||
- Update TOC
|
||||
|
||||
v1.10.7:
|
||||
|
||||
- Update TOCs
|
||||
|
||||
v1.10.6:
|
||||
|
||||
- Update TOCs
|
||||
|
||||
v1.10.5:
|
||||
|
||||
- Update TOCs
|
||||
|
||||
v1.10.4:
|
||||
|
||||
- Update Cataclysm Classic TOC to 4.4.1
|
||||
- Update Classic-era TOC for 1.15.4
|
||||
- Update TWW TOC for 11.0.5
|
||||
|
||||
v1.10.3:
|
||||
|
||||
- Fix another error from 11.0.2
|
||||
|
||||
v1.10.2:
|
||||
|
||||
- Fix error from 11.0.2
|
||||
|
||||
v1.10.1:
|
||||
|
||||
- Update Classic-era TOC for 1.15.3
|
||||
- Update TOC for TWW
|
||||
|
||||
v1.10.0:
|
||||
|
||||
- Support The War Within/11.0
|
||||
|
||||
v1.9.26:
|
||||
|
||||
- Update Dragonflight TOC for 10.2.7
|
||||
|
||||
v1.9.25:
|
||||
|
||||
- Support Cataclysm Classic 4.4.0
|
||||
|
||||
v1.9.24:
|
||||
|
||||
- Update TOCs
|
||||
|
||||
v1.9.23:
|
||||
|
||||
- Update Dragonflight TOC for 10.2.5
|
||||
|
||||
v1.9.22:
|
||||
|
||||
- Update Classic-era TOC for 1.15.0
|
||||
|
||||
v1.9.21:
|
||||
|
||||
- Update Dragonflight TOC for 10.2.0
|
||||
|
||||
v1.9.20:
|
||||
|
||||
- Update Wrath-Classic TOC for 3.4.3
|
||||
|
||||
v1.9.19:
|
||||
|
||||
- Update Dragonflight TOC for 10.1.7
|
||||
- Update Classic-era TOC for 1.14.4
|
||||
|
||||
v1.9.18:
|
||||
|
||||
- Added a confirmation dialog when ignoring breakables, and updated the description to mention the ignore feature.
|
||||
|
||||
v1.9.17:
|
||||
|
||||
- Update Dragonflight TOC for 10.1.5
|
||||
|
||||
v1.9.16:
|
||||
|
||||
- Update TOC for Wrath Classic 3.4.2
|
||||
|
||||
v1.9.15:
|
||||
|
||||
- Updated TOCs for 10.1.0
|
||||
- Added icon for 10.1.0
|
||||
|
||||
v1.9.14:
|
||||
|
||||
- Updated TOCs for 10.0.7
|
||||
|
||||
v1.9.13:
|
||||
|
||||
- Updated TOCs for 10.0.5
|
||||
|
||||
v1.9.12:
|
||||
|
||||
- Add detection of Dragonflight profession tools as disenchantable.
|
||||
|
||||
v1.9.11:
|
||||
|
||||
- Add detection of Dragonflight profession gear as disenchantable.
|
||||
|
||||
v1.9.10:
|
||||
|
||||
- Add Dragonflight Mystic disenchantable items. (Fixed)
|
||||
|
||||
v1.9.9
|
||||
|
||||
- Fix issue with not updating or showing items in some cases.
|
||||
|
||||
v1.9.8:
|
||||
|
||||
- Fix microstutter every time a modifier key, such as Alt, was pressed.
|
||||
- Improve performance when scanning for new breakables (such as when items enter/leave bags, a lockbox is clicked, etc.).
|
||||
|
||||
v1.9.7:
|
||||
|
||||
- Add Dragonflight lockboxes.
|
||||
- Hide lockboxes that can't be picked because the player's level is too low, where we can detect it (10.0+, toggleable with an option).
|
||||
|
||||
v1.9.6:
|
||||
|
||||
- Fix lockboxes in 10.0.2
|
||||
|
||||
v1.9.5:
|
||||
|
||||
- Fix another error from 10.0.2
|
||||
|
||||
v1.9.4:
|
||||
|
||||
- Update TOC for 10.0.2
|
||||
|
||||
v1.9.3:
|
||||
|
||||
- Fix error on 10.0.0
|
||||
|
||||
v1.9.2:
|
||||
|
||||
- Dragonflight/10.0.2 compatibility
|
||||
- Add ability to reset placement of the bar in case it gets lost somehow.
|
||||
- Shuffled settings into their own categories to make accidental resets unlikely.
|
||||
- Fix items being added to the ignore list both on press and release. This would frequently mean that two items would get ignored instead of just the one you wanted to click on.
|
||||
|
||||
v1.9.1:
|
||||
|
||||
- Fix right-click ignore functionality after the upgrade to 10.0.
|
||||
|
||||
v1.9.0:
|
||||
|
||||
- Handle gaining and losing a Breakable skill without requiring a UI reload
|
||||
- Update TOC, fix button clicking bug for 10.0
|
||||
|
||||
v1.8.7:
|
||||
|
||||
- Improve reliability of UI updates after picking lockboxes. There's no good game event for "locked item opened", so this uses some best-guess heuristics to make it function as expected in most cases.
|
||||
|
||||
v1.8.6:
|
||||
|
||||
- Improve enchanting level detection for Wrath Classic
|
||||
- Add option to ignore enchanting skill level for showing disenchantable items
|
||||
|
||||
v1.8.5:
|
||||
|
||||
- Wrath Classic compatibility
|
||||
- Updated TOCs
|
||||
|
||||
v1.8.4:
|
||||
|
||||
- Updated TOCs
|
||||
|
@ -9,7 +9,7 @@ local L = LibStub("AceLocale-3.0"):NewLocale("Breakables", "enUS", true, debug)
|
||||
--@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. You can also click directly on any breakable item button to break it without having to click the profession button first.
|
||||
Hold shift and drag the profession button to move the breakables bar around. You can also click directly on any breakable item button to break it without having to click the profession button first. Right-clicking a breakable button will add that item to the ignore list so it won't show up again. The ignore list can be managed from the configuration panel.
|
||||
|
||||
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@
|
12
readme.md
12
readme.md
@ -1,12 +1,14 @@
|
||||
### **Description**
|
||||
# Breakables
|
||||
|
||||
## **Description**
|
||||
|
||||
Displays a bar on screen that allows quick access to enchanting, jewelcrafting, and inscription professions by presenting a Disenchant/Prospect/Mill button and all of the breakable items you have for that profession next to it. Also displays a bar for any locked junkboxes in your inventory if you're a Rogue. This allows one-click access for breaking down items instead of finding the item in your bag, clicking the appropriate profession/skill button, and clicking the item for each and every item you want to break. For prospecting and milling, you will see the number of items you have alongside the number of times you can break it. In the prospecting screenshot on the right, the player has 169 total Saronite Ore in his bags which will allow for 33 total prospects.
|
||||
|
||||
### **Usage**
|
||||
## **Usage**
|
||||
|
||||
By default, if you have the appropriate profession and items in your inventory, a bar will appear with the profession ability followed by any items that are eligible for breaking. You can hold shift to drag the bar around if you want to move it. Clicking the profession button will activate that ability (disenchant/prospect/mill) and clicking an item will break it. You don't have to click the profession button first as simply clicking the item will automatically break it down.
|
||||
By default, if you have the appropriate profession and items in your inventory, a bar will appear with the profession ability followed by any items that are eligible for breaking. You can hold shift to drag the bar around if you want to move it. Clicking the profession button will activate that ability (disenchant/prospect/mill) and clicking an item will break it. You don't have to click the profession button first as simply clicking the item will automatically break it down. Right-clicking an item will place that item on the ignore list so it won't show up in the list again. The ignore list can be managed in the addon's configuration panel.
|
||||
|
||||
### **Configuration**
|
||||
## **Configuration**
|
||||
|
||||
Typing */brk* will open the configuration settings (or you can get to it from Blizzard's Interface options) which consist of:
|
||||
|
||||
@ -14,6 +16,6 @@ Typing */brk* will open the configuration settings (or you can get to it from Bl
|
||||
* **Max number to display**: this controls the highest number of items that you will see next to your profession button. If this is 5 but you have 10 breakable items in your bags, you will only see 5 at a time.
|
||||
* **Show soulbound items**: aimed at enchanters, this controls whether or not you will see items that are soulbound as breakable items or not.
|
||||
|
||||
### **Known issues**
|
||||
## **Known issues**
|
||||
|
||||
* If you have more than 5 of a breakable item but split into stacks all smaller than 5, the game will say you do not have enough items to break. The default UI now has a built-in button to compress stacks that should solve this issue.
|
||||
|
Reference in New Issue
Block a user