You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

499 lines
19 KiB

--lua
local unpack, select, strsplit, tonumber, pairs, wipe, tinsert, tconcat
= unpack, select, strsplit, tonumber, pairs, wipe, table.insert, table.concat
-- WoW APi
local GetItemInfoFromHyperlink, GetItemInfo, CreateFrame, GetItemUniqueness
= GetItemInfoFromHyperlink, GetItemInfo, CreateFrame, GetItemUniqueness
local BestInSlot, L, AceGUI = unpack(select(2, ...))
local CustomItems = BestInSlot:GetMenuPrototype(L["Custom Items"])
CustomItems.Width = 500
CustomItems.Height = 400
local minimumIlvl = 100
local failtimer
local upgradeStages = {
[525] = "Stage 1",
[526] = "Stage 2",
[527] = "Stage 3",
[593] = "Stage 4",
[617] = "Stage 5",
[618] = "Stage 6"
}
local upgradeTypes = {
427, --of the Auger
150, --of the Aurora
129, --of the Deft
385, --of the Diviner
343, --of the Fanatic
108, --of the Feverflare
19, --of the Fireflash
238, --of the Guileful
196, --of the Harmonious
406, --of the Herald
175, --of the Merciless
280, --of the Noble
45, --of the Peerless
87, --of the Quickblade
66, --of the Savage
322, --of the Stalwart
301, --of the Stormbreaker
217, --of the Strategist
259, --of the Windshaper
364, --of the Zealot
}
local upgradeNames = {}
local function onEnterPreviewLabel(widget)
local link = widget:GetUserData("link")
if not link then return end
GameTooltip:SetOwner(CustomItems.frame.frame)
GameTooltip:SetAnchorType("ANCHOR_CURSOR")
GameTooltip:SetHyperlink(link)
GameTooltip:Show()
end
local function onLeavePreviewLabel(widget)
GameTooltip:Hide()
end
local function editBoxOnEnterPressed(widget, _,value)
if #value > 0 then
CustomItems:TryGenerateCustomItem(value)
else
CustomItems:ResetCustomItem("")
end
end
local function OnItemInfoReceived(event, itemid)
CustomItems:TryGenerateCustomItem(itemid)
end
local function timerFailedQuery()
CustomItems:FailedItemQuery()
end
function CustomItems:EnablePreviewLabel(text, success)
local label = self.successlabel
if not label then return end
label:SetText(("\n%s\n"):format(text))
label:SetCallback("OnEnter", onEnterPreviewLabel)
label:SetCallback("OnLeave", onLeavePreviewLabel)
if GetItemInfoFromHyperlink(text) ~= nil then
label:SetUserData("link", text)
end
if success then
self.verifytext:SetText(L["Please verify that this is the item you would like to add:"])
end
self.container:DoLayout()
end
function CustomItems:ResetCustomItem(text)
local label = self.successlabel
if not label then return end
label:SetText(text)
label:SetCallback("OnEnter", nil)
label:SetCallback("OnLeave", nil)
self.verifytext:SetText("")
self.notallowedlabel:SetText("")
self.suffixDropdown:SetDisabled(true)
self.stageDropdown:SetDisabled(true)
self.dungeonDropdown:SetDisabled(true)
self.submitButton:SetDisabled(true)
self.cancelButton:SetDisabled(true)
self.stageDropdown:SetValue()
self.suffixDropdown:SetValue()
self:DisableInput(false)
self.customItemDropdown:SetValue()
self:DisableInput(false)
self.deleteButton:SetDisabled(true)
self.container:DoLayout()
end
function CustomItems:IsItemAllowed(itemid)
local name, link, quality, iLevel, reqLevel, class, subclass, maxStack, equipSlot, texture, vendorPrice = GetItemInfo(itemid)
local errors = {}
local label = self.notallowedlabel
if quality < 3 then
tinsert(errors, ("- "..L["You can only add items of %ssuperior%s quality or higher!"]):format(ITEM_QUALITY_COLORS[3].hex, RED_FONT_COLOR_CODE))
end
if #equipSlot == 0 and not IsArtifactRelicItem(itemid) then --empty string means no equipment slot?
tinsert(errors, "- "..L["You must be able to equip the item!"])
elseif equipSlot == "INVTYPE_TABARD" or equipSlot == "INVTYPE_BODY" then
tinsert(errors, "- "..(L["You cannot add items of type: %s!"]):format(_G[equipSlot]))
elseif equipSlot == "INVTYPE_BODY" then
tinsert(errors, "- "..(L["You cannot add items of type: %s!"]):format(_G[equipSlot]))
end
if self:ItemExists(itemid) then
local item = self:GetItem(itemid)
if item.customitem then
self.customItemDropdown:SetValue(itemid)
label:SetText(L["Warning! Editing this item will overwrite the previous item set on this itemid!"])
return self:LoadCustomItem(itemid)
else
local raidtier = self:GetRaidTiers(self.INSTANCE, item.dungeon)
tinsert(errors, ("- "..L["This item already exists in the database! It is registered to %s"]):format(self:GetDescription(self.RAIDTIER, raidtier)))
end
end
if iLevel < minimumIlvl then
tinsert(errors, "- "..(L["The minimum item level of custom items is %d!"]):format(minimumIlvl))
end
if #errors > 0 then
tinsert(errors, 1, L["Failed to add item because of the following reasons:"])
label:SetText("|cffff0000"..tconcat(errors, "\n"))
end
return #errors == 0
end
function BestInSlot:GetWarlordsCraftedLink(itemid, stage, upgradeType)
return ("item:%d:0:0:0:0:0:0:0:0:0:0:0:2:%d:%d"):format(itemid, stage, upgradeType)
end
function CustomItems:DisableInput(disable)
self.inputbox:SetDisabled(disable)
local customItemCount = self.customItemDropdown:GetUserData("count")
self.customItemDropdown:SetDisabled(customItemCount == 0 or disable)
end
function CustomItems:LoadCustomItem(itemid)
local item = self:GetItem(itemid)
if item then
self.itemid = itemid
self.itemstr = item.customitem
self:DisableInput(true)
self:EnablePreviewLabel(item.link, true)
self.dungeonDropdown:SetValue(item.dungeon)
self.container:DoLayout()
self:EnableImportOptions(itemid, item.link)
self.deleteButton:SetDisabled(false)
end
return false
end
function CustomItems:GenerateUpgradeNames(itemid)
local spirit = "SPIRIT"
local stats = {
[427] = {spirit, "VERSATILITY"}, --of the Auger
[150] = {"HASTE", "VERSATILITY"}, --of the Aurora
[129]= {"HASTE", "MULTISTRIKE"}, --of the Deft
[385] = {spirit, "MASTERY"}, --of the Diviner
[343] = {spirit, "CRITICAL_STRIKE"},
[108] = {"HASTE", "MASTERY"}, --of the Feverflare
[19] = {"HASTE", "CRITICAL_STRIKE"}, --of the Fireflash
[238] = {"BONUS_ARMOR", "CRITICAL_STRIKE"}, --of the Guileful
[196] = {"MASTERY", "VERSATILITY"}, --of the Harmonious
[406] = {spirit, "MULTISTRIKE"}, --of the Herald
[175] = {"MASTERY", "MULTISTRIKE"}, --of the Merciless
[280] = {"BONUS_ARMOR", "MASTERY"}, --of the Noble
[45] = {"CRITICAL_STRIKE", "MASTERY"}, --of the Peerless
[87] = {"CRITICAL_STRIKE", "VERSATILITY"}, --of the Quickblade
[66] = {"CRITICAL_STRIKE", "MULTISTRIKE"}, --of the Savage
[322] = {"BONUS_ARMOR", "VERSATILITY"}, --of the Stalwart
[301] = {"BONUS_ARMOR", "MULTISTRIKE"}, --of the Stormbreaker
[217] = {"MULTISTRIKE", "VERSATILITY"}, --of the Strategist
[259] = {"BONUS_ARMOR", "HASTE"}, --of the Windshaper
[364] = {spirit, "HASTE"}, --of the Zealot
}
local name = GetItemInfo(itemid) --original name to compare with other results
local tooltip = CreateFrame("GAMETOOLTIP", "BestInSlotScanTooltip", UIParent, "GameTooltipTemplate")
local stage = 525
for i=1,#upgradeTypes do
local upgradeType = upgradeTypes[i]
tooltip:SetOwner(UIParent, "ANCHOR_NONE")
tooltip:ClearLines()
tooltip:SetHyperlink(self:GetWarlordsCraftedLink(itemid, stage, upgradeType))
tooltip:Show()
local typeName = BestInSlotScanTooltipTextLeft1:GetText()
tooltip:Hide()
if stats[upgradeType][1] == spirit then
upgradeNames[upgradeType] = typeName:sub(#name + 1)..(" (%s + %s)"):format(ITEM_MOD_SPIRIT_SHORT, _G["STAT_"..stats[upgradeType][2]])
else
upgradeNames[upgradeType] = typeName:sub(#name + 1)..(" (%s + %s)"):format(_G["STAT_"..stats[upgradeType][1]], _G["STAT_"..stats[upgradeType][2]])
end
end
tooltip:Hide()
end
local function warlordsCraftedDropdownChanged()
if not CustomItems.itemid then error("The itemid is not known!") end
local isTrinket = select(9,GetItemInfo(CustomItems.itemid)) == "INVTYPE_TRINKET"
local stage = CustomItems.stageDropdown:GetValue() or 525
local suffix = CustomItems.suffixDropdown:GetValue() or not isTrinket and 150
local hyperlink = CustomItems:GetWarlordsCraftedLink(CustomItems.itemid, stage, suffix)
local link = select(2, GetItemInfo(hyperlink))
if isTrinket then
CustomItems.submitButton:SetDisabled(CustomItems.stageDropdown:GetValue() == nil)
else
CustomItems.submitButton:SetDisabled(CustomItems.stageDropdown:GetValue() == nil or CustomItems.suffixDropdown:GetValue() == nil)
end
CustomItems.successlabel:SetText("\n"..link.."\n")
CustomItems.successlabel:SetUserData("link", link)
end
function CustomItems:GenerateWarlordsCraftedOptions(itemlink)
local _,_, _, _, _, _, _, _, _, _, _, _, _, numBonusID, bonusId1, bonusId2 = strsplit(":", (itemlink):sub(1,(itemlink):find("|h") - 1), 15)
numBonusID, bonusId1, bonusId2 = tonumber(numBonusID), tonumber(bonusId1), tonumber(bonusId2)
for _,bonusId in pairs({bonusId1, bonusId2}) do
if upgradeNames[bonusId] then
self.suffixDropdown:SetValue(bonusId)
elseif upgradeStages[bonusId] then
self.stageDropdown:SetValue(bonusId)
end
end
end
function CustomItems:EnableImportOptions(itemid, link)
local container = self.container
if not container then return end
local isWarlordsCraftedItem = GetItemUniqueness(itemid) == 341
self.suffixDropdown:SetDisabled(not isWarlordsCraftedItem or select(9, GetItemInfo(itemid)) == "INVTYPE_TRINKET")
self.stageDropdown:SetDisabled(not isWarlordsCraftedItem)
self.cancelButton:SetDisabled(false)
if isWarlordsCraftedItem then --warlords crafted
if not upgradeNames[upgradeTypes[1]] then
self:GenerateUpgradeNames(itemid)
self.suffixDropdown:SetList(upgradeNames)
end
self:GenerateWarlordsCraftedOptions(link)
self:ShowTutorial(L["Custom Items"], 3)
end
self.submitButton:SetDisabled(isWarlordsCraftedItem and (self.suffixDropdown:GetValue() == nil or self.stageDropdown:GetValue() == nil))
self.dungeonDropdown:SetDisabled(false)
end
function CustomItems:TryGenerateCustomItem(input)
self:ResetCustomItem(self.colorNormal..L["Looking up item"].."...".."|r")
self:DisableInput(true)
local name, link, quality, iLevel, reqLevel, class, subclass, maxStack, equipSlot, texture, vendorPrice = GetItemInfo(input)
if name then
local itemStr = link:match("|H(item.-)|h")
local itemid = GetItemInfoFromHyperlink(link)
self.itemid = itemid
self.itemstr = itemStr
if failtimer then
failtimer:Cancel()
self:UnregisterEvent("GET_ITEM_INFO_RECEIVED", OnItemInfoReceived)
end
local success = self:IsItemAllowed(itemid)
self.successlabel:SetUserData("link", link)
self:EnablePreviewLabel(link, success)
self:DisableInput(success)
if success then
self:EnableImportOptions(itemid, link)
end
else
self.itemid = nil
failtimer = C_Timer.NewTimer(1.5, timerFailedQuery)
self:RegisterEvent("GET_ITEM_INFO_RECEIVED", OnItemInfoReceived)
end
end
function CustomItems:FailedItemQuery()
self:UnregisterEvent("GET_ITEM_INFO_RECEIVED", OnItemInfoReceived)
failtimer = nil
self:ResetCustomItem((RED_FONT_COLOR_CODE.."%s\n%s: %s"):format(L["Couldn't find item!"], LABEL_NOTE, L["You can only use the item name if you have the item in your inventory!"]))
self:DisableInput(false)
end
local function onDungeonChanged(dropdown, _, value)
CustomItems:SetSelected(CustomItems.INSTANCE, value)
end
function CustomItems:SubmitCustomItem()
local itemid = self.itemid
local itemStr = self.itemstr
local updatePrevious = self.customItemDropdown:GetValue() ~= nil
local warlordsCrafted = not self.stageDropdown.disabled
local suffixType = self.suffixDropdown:GetValue()
local stageType = self.stageDropdown:GetValue()
local dungeon = self:GetSelected(self.INSTANCE)
self:AddCustomItem(itemid, itemStr, dungeon, updatePrevious)
self.inputbox:SetText("")
local link = select(2, GetItemInfo(itemStr))
self:ResetCustomItem("|cff00ff00"..(L["Successfully added %s to the custom items of %s!"]):format(link.."|cff00ff00", self:GetDescription(self.INSTANCE, dungeon)))
self:SetCustomItemDropdown()
end
function CustomItems:SetCustomItemDropdown()
local dropdown = self.customItemDropdown
local customItems, count = self:GetCustomItems()
if count > 0 then
dropdown:SetList({})
for dungeon, list in pairs(customItems) do
for i=1,#list do
local itemid = list[i]
dropdown:AddItem(itemid, self:GetItem(itemid).link)
end
end
end
local disabled = count == 0
dropdown:SetDisabled(disabled)
dropdown:SetText(disabled and L["There are no custom items present"] or "")
dropdown:SetUserData("count", count)
end
local function customItemDropdownValueChanged(widget, _, value)
CustomItems:LoadCustomItem(value)
end
function CustomItems:Draw(container, dungeon)
local editBox = AceGUI:Create("EditBox")
editBox:SetFullWidth(true)
editBox:SetLabel(L["Insert item ID, item link or item name"])
editBox:SetCallback("OnEnterPressed", editBoxOnEnterPressed)
container:SetUserData("input", editBox)
container:AddChild(editBox)
local customItemDropdown = AceGUI:Create("Dropdown")
customItemDropdown:SetFullWidth(true)
customItemDropdown:SetLabel(L["Pick a previously created custom item"])
customItemDropdown:SetCallback("OnValueChanged", customItemDropdownValueChanged)
container:AddChild(customItemDropdown)
container:SetUserData("customitem", customItemDropdown)
local verifytext = AceGUI:Create("Label")
verifytext:SetFullWidth(true)
container:AddChild(verifytext)
local successlabel = AceGUI:Create("InteractiveLabel")
successlabel:SetFullWidth(true)
successlabel:SetText("")
container:AddChild(successlabel)
local notallowedlabel = AceGUI:Create("Label")
notallowedlabel:SetFullWidth(true)
notallowedlabel:SetText("")
container:AddChild(notallowedlabel)
local suffixDropdown = AceGUI:Create("Dropdown")
suffixDropdown:SetList(upgradeNames)
suffixDropdown:SetFullWidth(true)
suffixDropdown:SetLabel(L["Warlords crafted options:"])
suffixDropdown:SetCallback("OnValueChanged", warlordsCraftedDropdownChanged)
suffixDropdown:SetDisabled(true)
--container:AddChild(suffixDropdown)
local stageDropdown = AceGUI:Create("Dropdown")
stageDropdown:SetList(upgradeStages)
stageDropdown:SetFullWidth(true)
stageDropdown:SetCallback("OnValueChanged", warlordsCraftedDropdownChanged)
stageDropdown:SetDisabled(true)
--container:AddChild(stageDropdown)
container:SetUserData("stage", stageDropdown)
local dungeonDropdown = AceGUI:Create("Dropdown")
dungeonDropdown:SetLabel(L["Select the instance that you would like to add this item to."])
local raidTiers = self:GetRaidTiers()
dungeonDropdown:SetList({})
for _,raidtier in pairs(raidTiers) do
local raidtierDungeons = self:GetInstances(self.RAIDTIER, raidtier)
dungeonDropdown:AddItem(raidtier, " "..self:GetDescription(self.RAIDTIER, raidtier))
dungeonDropdown:SetItemDisabled(raidtier, true)
for _, dungeon in pairs(raidtierDungeons) do
dungeonDropdown:AddItem(dungeon, self:GetDescription(self.INSTANCE, dungeon))
end
end
dungeonDropdown:SetFullWidth(true)
dungeonDropdown:SetDisabled(true)
dungeonDropdown:SetCallback("OnValueChanged", onDungeonChanged)
dungeonDropdown:SetValue(dungeon or self:GetSelected(self.INSTANCE))
container:AddChild(dungeonDropdown)
local submitButton = AceGUI:Create("Button")
submitButton:SetText(SUBMIT)
submitButton:SetRelativeWidth(0.33)
submitButton:SetDisabled(true)
submitButton:SetCallback("OnClick", function() CustomItems:SubmitCustomItem() end)
container:AddChild(submitButton)
local cancelButton = AceGUI:Create("Button")
cancelButton:SetText(CANCEL)
cancelButton:SetRelativeWidth(0.33)
cancelButton:SetDisabled(true)
cancelButton:SetCallback("OnClick", function() CustomItems:ResetCustomItem() end)
container:AddChild(cancelButton)
local deleteButton = AceGUI:Create("Button")
deleteButton:SetText(DELETE)
deleteButton:SetRelativeWidth(0.33)
deleteButton:SetDisabled(true)
deleteButton:SetCallback("OnClick", function() CustomItems:DeleteCustomItem() end)
container:AddChild(deleteButton)
self.inputbox = editBox
self.customItemDropdown = customItemDropdown
self.verifytext = verifytext
self.successlabel = successlabel
self.notallowedlabel = notallowedlabel
self.container = container
self.suffixDropdown = suffixDropdown
self.stageDropdown = stageDropdown
self.dungeonDropdown = dungeonDropdown
self.submitButton = submitButton
self.cancelButton = cancelButton
self.deleteButton = deleteButton
self:SetCustomItemDropdown()
end
function CustomItems:DeleteCustomItem(doDelete)
local item = self:GetItem(self.itemid)
local isBiS = false
for difficulty, difficTable in pairs(item.isBiS) do
for specId, bis in pairs(difficTable) do
if bis then
isBiS = true
break
end
end
end
if not doDelete and isBiS then
local popup = StaticPopup_Show("BESTINSLOT_CONFIRMDELETECUSTOMITEM", self:GetItem(self.itemid).link)
popup:SetFrameStrata("TOOLTIP")
return
end
self:UnregisterCustomItem(self.itemid)
self:ResetCustomItem("|cff00ff00"..(L["Successfully deleted %s%s from the custom items!"]):format(item.link, "|cff00ff00"))
self:SetCustomItemDropdown()
end
function CustomItems:Close()
self.successlabel = nil
self.inputbox = nil
self.container = nil
self.notallowedlabel = nil
self.itemid = nil
self.itemstr = nil
self.stageDropdown = nil
self.suffixDropdown = nil
self.dungeonDropdown = nil
self.submitButton = nil
self.cancelButton = nil
self.deleteButton = nil
self.customItemDropdown = nil
if failtimer then failtimer:Cancel() failtimer = nil end
wipe(upgradeNames) --memory saving, user should barely ever use this screen
end
StaticPopupDialogs["BESTINSLOT_CONFIRMDELETECUSTOMITEM"] = {
text = L["Are you sure you want to delete %s? This item is on your Best In Slot list!"],
button1 = YES,
button2 = NO,
OnAccept = function() CustomItems:DeleteCustomItem(true) end,
whileDead = true,
hideOnEscape = true,
preferredIndex = 3,
exclusive = 1,
}
CustomItems:RegisterTutorials(L["Custom Items"],{
[1] = {text = L["In this menu you can add custom items. Use this edit box to submit your item."], text2 = L["You can only use the item name if you have the item in your inventory!"], xOffset = 0, yOffset = -20, container = "content", UpArrow = true, element = "input"},
[2] = {text = L["You can edit previously made custom items by selecting them with this dropdown box."], xOffset = 0, yOffset = -20, container = "content", UpArrow = true, element = "customitem"},
--[3] = {text = L["When adding crafted items, you can select the random stats and the stage of the item with these dropdown boxes."], xOffset = 0, yOffset = -20, container = "content", Uparrow = true, element = "stage", UpArrow = true, onRequest = true}
})