From ae7a252a51b8f61f885b43c14f52cd33c2e0c173 Mon Sep 17 00:00:00 2001 From: Noshei <8866000+Noshei@users.noreply.github.com> Date: Wed, 4 Dec 2024 13:04:51 -0700 Subject: [PATCH] Merge Alerts into Master (#37) Added Alerts System Removed Notifications System (replaced by Alerts) Updated settings to use newer blizzard textures Switched completely to Bigwigs packager --- .github/workflows/release.yml | 6 +- .vscode/settings.json | 70 +- Alerts.lua | 580 ++++++++++ AlertsMenu.lua | 253 ++++ Bindings.lua | 18 +- Bindings.xml | 6 - Broker.lua | 5 + Config.lua | 924 ++++++++++----- Constants.lua | 1015 +++++++++-------- DisplayCreation.lua | 15 + FilterButton.lua | 31 +- GatheringTracker.lua | 53 +- GatheringTracker.toc | 9 +- .../CheckBox-Extended.lua | 48 +- .../DropDown-Extended.lua | 754 ++++++++++++ .../DropDown-Items-Extended.lua | 474 ++++++++ Libs/AceGUI-3.0-NosheiWidgets/FontWidget.lua | 246 ++++ .../HighlightWidget.lua | 250 ++++ .../Label-Extended.lua | 190 +++ .../Slider-Extended.lua | 283 +++++ Libs/AceGUI-3.0-NosheiWidgets/SoundWidget.lua | 293 +++++ Libs/AceGUI-3.0-NosheiWidgets/prototypes.lua | 284 +++++ Libs/AceGUI-3.0-NosheiWidgets/widget.xml | 8 + Media/ScreenFlash.tga | Bin 0 -> 58948 bytes Media/border1.tga | Bin 0 -> 10560 bytes Media/border2.tga | Bin 0 -> 4546 bytes Media/border3.tga | Bin 0 -> 105490 bytes Media/border4.tga | Bin 0 -> 12521 bytes NotificationHandler.lua | 174 --- Utilities.lua | 30 + embeds.xml | 2 +- 31 files changed, 5009 insertions(+), 1012 deletions(-) create mode 100644 Alerts.lua create mode 100644 AlertsMenu.lua create mode 100644 Libs/AceGUI-3.0-NosheiWidgets/DropDown-Extended.lua create mode 100644 Libs/AceGUI-3.0-NosheiWidgets/DropDown-Items-Extended.lua create mode 100644 Libs/AceGUI-3.0-NosheiWidgets/FontWidget.lua create mode 100644 Libs/AceGUI-3.0-NosheiWidgets/HighlightWidget.lua create mode 100644 Libs/AceGUI-3.0-NosheiWidgets/Label-Extended.lua create mode 100644 Libs/AceGUI-3.0-NosheiWidgets/Slider-Extended.lua create mode 100644 Libs/AceGUI-3.0-NosheiWidgets/SoundWidget.lua create mode 100644 Libs/AceGUI-3.0-NosheiWidgets/prototypes.lua create mode 100644 Media/ScreenFlash.tga create mode 100644 Media/border1.tga create mode 100644 Media/border2.tga create mode 100644 Media/border3.tga create mode 100644 Media/border4.tga delete mode 100644 NotificationHandler.lua diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 18b296a..f9fadbd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,11 +4,11 @@ name: Release AddOn # description of this workflow, can be anything you want on: push: tags: - - '**' + - "**" env: - #CF_API_KEY: ${{ secrets.CF_API_KEY }} - WOWI_API_TOKEN: ${{ secrets.WOWI_API_TOKEN }} + CF_API_KEY: ${{ secrets.CF_API_KEY }} + #WOWI_API_TOKEN: ${{ secrets.WOWI_API_TOKEN }} WAGO_API_TOKEN: ${{ secrets.WAGO_API_TOKEN }} # for github releases, this secret is automatically provided to the workflow GITHUB_OAUTH: ${{ secrets.GITHUB_TOKEN }} diff --git a/.vscode/settings.json b/.vscode/settings.json index 22911bf..31a4239 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -12,7 +12,7 @@ "utf8": "disable" }, "Lua.workspace.library": [ - "~\\.vscode\\extensions\\ketho.wow-api-0.17.6\\Annotations" + "~\\.vscode\\extensions\\ketho.wow-api-0.17.9\\Annotations" ], "Lua.diagnostics.globals": [ "RECrystallize_PriceCheckItemID", @@ -26,11 +26,75 @@ "SlashCmdList", "Settings", "SetDesaturation", + "C_Seasons", + "UNKNOWN", + "CALENDAR_STATUS_CONFIRMED", + "CALENDAR_STATUS_ACCEPTED", + "CALENDAR_STATUS_DECLINED", + "CALENDAR_STATUS_OUT", + "CALENDAR_STATUS_STANDBY", + "CALENDAR_STATUS_INVITED", + "CALENDAR_STATUS_SIGNEDUP", + "CALENDAR_STATUS_NOT_SIGNEDUP", + "CALENDAR_STATUS_TENTATIVE", + "STRING_SCHOOL_PHYSICAL", + "STRING_SCHOOL_HOLY", + "STRING_SCHOOL_FIRE", + "STRING_SCHOOL_NATURE", + "STRING_SCHOOL_FROST", + "STRING_SCHOOL_SHADOW", + "STRING_SCHOOL_ARCANE", + "WEEKDAY_SUNDAY", + "WEEKDAY_MONDAY", + "WEEKDAY_TUESDAY", + "WEEKDAY_WEDNESDAY", + "WEEKDAY_THURSDAY", + "WEEKDAY_FRIDAY", + "WEEKDAY_SATURDAY", + "FULLDATE_MONTH_JANUARY", + "FULLDATE_MONTH_FEBRUARY", + "FULLDATE_MONTH_MARCH", + "FULLDATE_MONTH_APRIL", + "FULLDATE_MONTH_MAY", + "FULLDATE_MONTH_JUNE", + "FULLDATE_MONTH_JULY", + "FULLDATE_MONTH_AUGUST", + "FULLDATE_MONTH_SEPTEMBER", + "FULLDATE_MONTH_OCTOBER", + "FULLDATE_MONTH_NOVEMBER", + "FULLDATE_MONTH_DECEMBER", + "LE_LFG_CATEGORY_LFD", + "LOOKING_FOR_DUNGEON", + "LE_LFG_CATEGORY_RF", + "RAID_FINDER", + "LE_LFG_CATEGORY_SCENARIO", + "SCENARIOS", + "LE_LFG_CATEGORY_LFR", + "LOOKING_FOR_RAID", + "LE_LFG_CATEGORY_FLEXRAID", + "FLEX_RAID", + "LE_LFG_CATEGORY_WORLDPVP", + "WORLD_PVP", + "LE_LFG_CATEGORY_BATTLEFIELD", + "LFG_CATEGORY_BATTLEFIELD", + "LE_EXPANSION_CLASSIC", + "DEFAULT_CHAT_FRAME", + "TablesAPIMixin", + "FunctionsAPIMixin", + "EventsAPIMixin", + "FieldsAPIMixin", + "SystemsAPIMixin", + "ChatFrame_OpenChat", + "ChatTypeInfo", + "OKAY", + "ACCEPT", + "CANCEL", "CLOSE", - "C_Seasons" + "ADD", + "LowHealthFrame" ], "Lua.diagnostics.disable": [ "assign-type-mismatch", - "cast-local-type" + "cast-local-type", ] } diff --git a/Alerts.lua b/Alerts.lua new file mode 100644 index 0000000..700294b --- /dev/null +++ b/Alerts.lua @@ -0,0 +1,580 @@ +---@class GT +local GT = LibStub("AceAddon-3.0"):GetAddon("GatheringTracker") +local media = LibStub:GetLibrary("LibSharedMedia-3.0") + +-- Localize global functions +local ipairs = ipairs +local math = math +local max = max +local next = next +local pairs = pairs +local select = select +local string = string +local table = table +local time = time +local tonumber = tonumber +local tostring = tostring +local type = type +local unpack = unpack + +GT.AlertSystem = {} +GT.AlertSystem.AllowAlertEffects = false +GT.Alerts = {} + +function GT:AllowAlertEffects(event) + GT.Debug("Allow Alert Effects", 1) + if event == "AllowAlertEffects" then + GT.AlertSystem.AllowAlertEffects = true + end +end + +function GT.AlertSystem:CreateAlertFrames() + GT.Display.Alerts = GT.Display.Alerts or {} + local flash = CreateFrame("Frame", "GT_Alerts_ScreenFlash", UIParent) + flash:SetAllPoints(UIParent) + flash:SetFrameStrata("TOOLTIP") + flash:Hide() + + flash.texture = flash:CreateTexture("GT_Alerts_ScreenFlash_Texture") + flash.texture:SetTexture("Interface\\Addons\\GatheringTracker\\Media\\ScreenFlash") + flash.texture:SetAllPoints(flash) + flash.texture:SetBlendMode("ADD") + + ---@class animGroup: AnimationGroup + local animGroup = flash:CreateAnimationGroup() + animGroup.FadeIn = animGroup:CreateAnimation("Alpha") + animGroup.FadeIn:SetParent(animGroup, 1) + animGroup.FadeOut = animGroup:CreateAnimation("Alpha") + animGroup.FadeOut:SetParent(animGroup, 2) + + animGroup.FadeIn:SetFromAlpha(0) + animGroup.FadeIn:SetToAlpha(1) + + animGroup.FadeOut:SetFromAlpha(1) + animGroup.FadeOut:SetToAlpha(0) + + flash.animGroup = animGroup + + function flash.SetDuration(self, duration) + animGroup.FadeIn:SetDuration(duration * (1 / 4)) + animGroup.FadeIn:SetStartDelay(0) + animGroup.FadeIn:SetEndDelay(0) + animGroup.FadeOut:SetDuration(duration * (3 / 4)) + animGroup.FadeOut:SetStartDelay(0) + animGroup.FadeOut:SetEndDelay(0, true) + end + + function flash.PlayAnimation() + flash:Show() + animGroup:Play() + animGroup:SetToFinalAlpha(true) + end + + GT.Display.Alerts.ScreenFlash = flash + + -- Commented this out as I'm not implmenting it right now, but will return to it in the future. + --[[local text = CreateFrame("Frame", "GT_Alerts_TextPopup", GT.baseFrame.frame) + text:SetPoint("CENTER") + text:SetFrameStrata("TOOLTIP") + + text.texture = text:CreateFontString("GT_Alerts_TextPopup_Texture") + text.texture:SetAllPoints(text) + text.texture:Hide() + + text.mover = CreateFrame("Frame", "GT_Alerts_TextPopup_Mover", text, BackdropTemplateMixin and "BackdropTemplate") + text.mover:SetWidth(300) + text.mover:SetHeight(300) + text.mover:SetAllPoints(text) + text.mover:SetBackdrop({ + bgFile = "Interface\\ChatFrame\\ChatFrameBackground", + edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", + tile = true, + tileSize = 16, + edgeSize = 16, + insets = { left = 3, right = 3, top = 5, bottom = 3 }, + }) + text.mover:SetBackdropColor(0.1, 0.1, 0.1, 0.5) + text.mover:SetBackdropBorderColor(0.4, 0.4, 0.4) + text.mover:SetFrameStrata("FULLSCREEN_DIALOG") + text.mover:SetClampedToScreen(true) + text.mover:SetMouseClickEnabled(false) + + GT.Display.Alerts.TextPopup = text]] +end + +---Entry point to the Alert System +---@param itemID number ID of the item to run the alert system for +---@param displayText table|number +---@param priceTotalItem? number +function GT.AlertSystem:Alerts(itemID, displayText, priceTotalItem) + if not GT.db.profile.General.alertsEnable then + return + end + local itemValue = GT.AlertSystem:GetItemValue(displayText) + GT.Debug("Alerts Initial", 3, itemID, itemValue, priceTotalItem) + + local item = GT.AlertSystem:GetItem(itemID, true) + local allItems = GT.AlertSystem:GetItem(1, true) + if not item and not allItems then + return + end + + local triggers = { itemValue, priceTotalItem } + local triggeredAlerts = GT.AlertSystem:GetTriggeredAlerts(itemID, item, allItems, triggers) + if #triggeredAlerts == 0 then + return + end + for _, alert in ipairs(triggeredAlerts) do + GT.AlertSystem:TriggerAlert(alert, triggers[alert:GetTriggerType()], itemID) + end +end + +---Simplifies the provided displayText to a single number instead of leaving it as a potential table +---@param displayText number|table +---@return number +function GT.AlertSystem:GetItemValue(displayText) + local itemValue = 0 + if type(displayText) == "table" then + itemValue = displayText[1] + else + itemValue = displayText + end + return itemValue +end + +---checks if the item (or all items) has been enabled for alerts +---@param itemID number +---@return number +function GT.AlertSystem:CheckItemAlert(itemID) + local trigger = 0 + if GT.db.profile.Alerts[itemID] and GT.db.profile.Alerts[itemID].enable then + trigger = 1 + end + if GT.db.profile.Alerts[1] and GT.db.profile.Alerts[1].enable then + trigger = trigger + 2 + end + GT.Debug("Check Item Alert", 4, itemID, trigger) + return trigger +end + +---checks the provided item and allItem objects for any alerts that should be triggered +---@param itemID number +---@param item AlertItem|nil +---@param allItems AlertItem|nil +---@param triggers table table of trigger values sorted by trigger type key +---@return table alertsToTrigger +function GT.AlertSystem:GetTriggeredAlerts(itemID, item, allItems, triggers) + GT.Debug("GetTriggeredAlerts Initial", 2, triggers[1], triggers[2]) + local triggeredAlerts = {} + + if item then + GT.Debug("GetTriggeredAlerts item", 4, item.itemID, #item.alerts, item.enable) + for _, alert in ipairs(item:GetAllAlerts()) do + if triggers[alert:GetTriggerType()] >= alert:GetTriggerValue() and alert:GetEnabled() and not alert:GetTriggered() then + table.insert(triggeredAlerts, alert) + end + if alert:GetTriggered() and alert:GetAlertType() == "Highlight" and triggers[alert:GetTriggerType()] < alert:GetTriggerValue() then + GT.AlertSystem:ClearAlert(alert) + end + end + end + + if allItems then + GT.Debug("GetTriggeredAlerts allItems", 4, allItems.itemID, #allItems.alerts, allItems.enable) + for _, alert in ipairs(allItems:GetAllAlerts()) do + local child = alert:GetChildAlert(itemID) or alert:AddChildAlert(itemID) + local itemAlertExists = false + if item and item:GetAlert(child:GetAlertType(), child:GetTypeCount()) then + itemAlertExists = true + end + if not itemAlertExists and triggers[child:GetTriggerType()] >= child:GetTriggerValue() and + child:GetEnabled() and not child:GetTriggered() then + local alertType = child:GetAlertType() + local triggerValue = child:GetTriggerValue() + if #triggeredAlerts > 0 then + local match = false + for _, alertObject in ipairs(triggeredAlerts) do + if alertType == alertObject:GetAlertType() and triggerValue == alertObject:GetTriggerValue() then + match = true + end + end + if not match then + table.insert(triggeredAlerts, child) + end + else + table.insert(triggeredAlerts, child) + end + end + if child:GetTriggered() and child:GetAlertType() == "Highlight" and triggers[child:GetTriggerType()] < child:GetTriggerValue() then + GT.AlertSystem:ClearAlert(child) + end + end + end + GT.Debug("GetTriggeredAlerts Final", 3, #triggeredAlerts) + return triggeredAlerts +end + +---comment +---@param alert Alert +---@param triggeredValue number +---@param itemID number +function GT.AlertSystem:TriggerAlert(alert, triggeredValue, itemID) + GT.Debug("Trigger Alert", 2, alert.itemID, itemID, alert:GetAlertType(), alert:GetTriggerValue()) + alert:SetTriggered(true) + + local alertSettings = alert:GetAlertSettings() + + GT.AlertSystem:TriggerEffects(alert, alertSettings, itemID) + + if alert:GetTriggerMultiple() then + GT.Debug("Trigger Alert: Trigger Multiple", 3, alert.itemID, alert:GetTriggerValue(), alert:GetTriggerMultiplier(), triggeredValue) + local baseTriggerValue = alert:GetTriggerMultiplier() + alert:SetTriggered(false) + alert:SetTriggerValue(((math.floor(triggeredValue / baseTriggerValue) + 1) * baseTriggerValue)) + end +end + +---@param alert Alert +---@param alertSettings table +---@param itemID number +function GT.AlertSystem:TriggerEffects(alert, alertSettings, itemID) + if not GT.AlertSystem.AllowAlertEffects then + return + end + if itemID == 2 then + itemID = 9999999998 + end + + if alert:GetAlertType() == "Audio" then + PlaySoundFile(tostring(media:Fetch("sound", alertSettings.tiggerSound)), "master") + elseif alert:GetAlertType() == "Highlight" then + GT.Display.Frames[itemID].highlight:SetTexture(GT.HighlightTextures[alertSettings.highlightBorder].atlas) + GT.Display.Frames[itemID].highlight:SetVertexColor(unpack(alertSettings.highlightColor)) + GT.Display.Frames[itemID].highlight:Show() + elseif alert:GetAlertType() == "Screen Flash" then + GT.Display.Alerts.ScreenFlash.texture:SetVertexColor(unpack(alertSettings.flashColor)) + GT.Display.Alerts.ScreenFlash:SetDuration(alertSettings.flashDuration or 3) + GT.Display.Alerts.ScreenFlash:PlayAnimation() + end +end + +---@param alert Alert +function GT.AlertSystem:ClearAlert(alert) + GT.Debug("Clear Alert", 1, alert.itemID, alert:GetAlertType(), alert:GetTriggerValue()) + local itemID = alert.itemID + if alert.itemID == 2 then + itemID = 9999999998 + end + GT.Display.Frames[itemID].highlight:Hide() +end + +function GT.AlertSystem:ResetAlerts() + GT.Debug("Reset Alerts", 1) + for itemID, Item in pairs(GT.Alerts) do + for _, Alert in ipairs(Item:GetAllAlerts(true)) do + Alert:SetTriggered(false) + if Alert:GetTriggerMultiple() then + Alert:SetTriggerValue(Alert:GetTriggerMultiplier()) + end + end + end +end + +---@param self Alert +---@param key boolean +local function SetEnabled(self, key) + self.enable = key +end + +---@param self Alert +---@return boolean enable +local function GetEnabled(self) + return self.enable +end + +---@param self Alert +---@param value number +local function SetTriggerValue(self, value) + if value == nil then + return + end + self.triggerValue = value +end + +---@param self Alert +---@param triggerType number +local function SetTriggerType(self, triggerType) + if triggerType == nil then + return + end + self.triggerType = triggerType +end + +---@param self Alert +---@param triggered boolean +local function SetTriggered(self, triggered) + if triggered == nil then + return + end + self.triggered = triggered +end + +---@param self Alert +---@param typeCount number +local function SetTypeCount(self, typeCount) + if typeCount == nil then + return + end + self.typeCount = typeCount +end + +---@param self Alert +---@param triggerMultiple boolean +local function SetTriggerMultiple(self, triggerMultiple) + if triggerMultiple == nil then + return + end + self.triggerMultiple = triggerMultiple +end + +---@param self Alert +---@param triggerMultiplier number +local function SetTriggerMultiplier(self, triggerMultiplier) + if triggerMultiplier == nil then + return + end + self.triggerMultiplier = triggerMultiplier +end + +---@param self Alert +---@param settings table +local function SetAlertSettings(self, settings) + if settings == nil then + return + end + self.alertSettings = settings +end + +---@param self Alert +---@return number triggerValue +local function GetTriggerValue(self) + return self.triggerValue +end + +---@param self Alert +---@return number triggerType +local function GetTriggerType(self) + return self.triggerType +end + +---@param self Alert +---@return boolean triggered +local function GetTriggered(self) + return self.triggered +end + +---@param self Alert +---@return string alertType +local function GetAlertType(self) + return self.alertType +end + +---@param self Alert +---@return number typeCount +local function GetTypeCount(self) + return self.typeCount +end + +---@param self Alert +---@return boolean triggerMultiple +local function GetTriggerMultiple(self) + return self.triggerMultiple +end + +---@param self Alert +---@return number triggerMultiplier +local function GetTriggerMultiplier(self) + return self.triggerMultiplier +end + +---@param self Alert +---@return boolean enable +local function GetAlertSettings(self) + return self.alertSettings +end + +local function AddChildAlert(self, itemID) + local child = { + triggered = false, + triggerValue = self:GetTriggerValue(), + triggerMultiplier = self:GetTriggerMultiplier(), + itemID = itemID, + + GetTriggered = GetTriggered, + GetTriggerValue = GetTriggerValue, + GetTriggerMultiplier = GetTriggerMultiplier, + SetTriggered = SetTriggered, + SetTriggerValue = SetTriggerValue + } + local metatable = { + __index = { + alertType = self.alertType, + typeCount = self.typeCount, + triggerMultiple = self.triggerMultiple, + enable = self.enable, + triggerType = self.triggerType, + alertSettings = self.alertSettings, + + GetEnabled = self.GetEnabled, + GetTriggerType = self.GetTriggerType, + GetAlertType = self.GetAlertType, + GetTypeCount = self.GetTypeCount, + GetTriggerMultiple = self.GetTriggerMultiple, + GetAlertSettings = self.GetAlertSettings, + }, + } + setmetatable(child, metatable) + self.child[itemID] = child + + return child +end + +local function GetChildAlert(self, itemID) + return self.child[itemID] +end + +---@alias Alert table +---@param self Alert +---@param alertType string +---@param typeCount number +---@param triggerValue number +---@return Alert +local function AddAlert(self, alertType, typeCount, triggerValue) + local alert = {} + alert.alertType = alertType + alert.typeCount = typeCount + alert.triggerValue = triggerValue + alert.triggered = false + alert.triggerMultiple = false + alert.triggerMultiplier = 0 + alert.itemID = self.itemID + alert.enable = false + alert.triggerType = 1 + alert.alertSettings = {} + alert.child = {} + + -- Methods + alert.SetEnabled = SetEnabled + alert.GetEnabled = GetEnabled + alert.SetTriggerValue = SetTriggerValue + alert.SetTriggerType = SetTriggerType + alert.SetTriggered = SetTriggered + alert.SetTypeCount = SetTypeCount + alert.SetTriggerMultiple = SetTriggerMultiple + alert.SetTriggerMultiplier = SetTriggerMultiplier + alert.SetAlertSettings = SetAlertSettings + alert.GetTriggerValue = GetTriggerValue + alert.GetTriggerType = GetTriggerType + alert.GetTriggered = GetTriggered + alert.GetAlertType = GetAlertType + alert.GetTypeCount = GetTypeCount + alert.GetTriggerMultiple = GetTriggerMultiple + alert.GetTriggerMultiplier = GetTriggerMultiplier + alert.GetAlertSettings = GetAlertSettings + + alert.AddChildAlert = AddChildAlert + alert.GetChildAlert = GetChildAlert + + table.insert(self.alerts, alert) + return alert +end + +local function RemoveAlert(self, alert) + for index, alertObject in ipairs(self.alerts) do + if alert == alertObject then + alertObject = nil + table.remove(self.alerts, index) + end + end +end + +---@param self Alert +---@param alertType string +---@param typeCount number +---@return table|nil +local function GetAlert(self, alertType, typeCount) + for _, alert in ipairs(self.alerts) do + if alert.alertType == alertType and alert.typeCount == typeCount then + return alert + end + end +end + +---@param self AlertItem +---@param includeChildAlerts boolean +---@return table|nil +local function GetAllAlerts(self, includeChildAlerts) + if includeChildAlerts then + local alerts = {} + for _, alert in ipairs(self.alerts) do + table.insert(alerts, alert) + if next(alert.child) ~= nil then + for itemID, child in pairs(alert.child) do + table.insert(alerts, child) + end + end + end + return alerts + end + return self.alerts +end + +---@alias AlertItem table +---@param itemID number +---@return AlertItem +function GT.AlertSystem:AddItem(itemID) + local item = {} + item.alerts = {} + item.itemID = itemID + item.enable = true + + -- Methods + item.SetEnabled = SetEnabled + item.GetEnabled = GetEnabled + item.AddAlert = AddAlert + item.RemoveAlert = RemoveAlert + item.GetAlert = GetAlert + item.GetAllAlerts = GetAllAlerts + + GT.Alerts[itemID] = item + + return item +end + +---@param itemID number +---@param returnEnabledOnly? boolean +---@return AlertItem|nil +function GT.AlertSystem:GetItem(itemID, returnEnabledOnly) + if not GT.Alerts[itemID] then + return + end + if returnEnabledOnly and not GT.Alerts[itemID]:GetEnabled() then + return + end + return GT.Alerts[itemID] +end + +---@param itemID number +function GT.AlertSystem:RemoveItem(itemID) + if not GT.Alerts[itemID] then + return + end + GT.Alerts[itemID] = nil +end + +function GT.AlertSystem:RemoveAllItems(event) + if event ~= "Refresh Config" then + return + end + GT.Alerts = {} +end diff --git a/AlertsMenu.lua b/AlertsMenu.lua new file mode 100644 index 0000000..9e168b6 --- /dev/null +++ b/AlertsMenu.lua @@ -0,0 +1,253 @@ +---@class GT +local GT = LibStub("AceAddon-3.0"):GetAddon("GatheringTracker") + +-- Localize global functions +local ipairs = ipairs +local math = math +local max = max +local next = next +local pairs = pairs +local select = select +local string = string +local table = table +local time = time +local tonumber = tonumber +local tostring = tostring +local type = type +local unpack = unpack + +GT.AlertSystem.Menu = {} + +function GT:GenerateAlertsMenu(frame) + local function AlertsMenu(frame, rootDescription) + rootDescription:SetTag("GatheringTracker_Alerts_Menu") + for expansionIndex, expansion in ipairs(GT.expansionsOrder) do + if GT.ItemData[expansion] and expansion ~= "Other" then + frame[expansion] = rootDescription:CreateButton(expansion, function() end) + for categoryIndex, category in ipairs(GT.categoriesOrder) do + if GT.ItemData[expansion][category] then + frame[expansion][category] = frame[expansion]:CreateButton(category, function() end) + frame[expansion][category]:SetScrollMode(GetScreenHeight() * 0.75) + for _, itemData in ipairs(GT.ItemData[expansion][category]) do + local function IsSelected_Item() + if GT.db.profile.Alerts[itemData.id] then + return true + else + return false + end + end + local function SetSelected_Item() + GT.Debug("Item Button Clicked", 2, expansion, category, itemData.name) + local key = not IsSelected_Item() + if key then + local alertItemData = { + id = itemData.id, + name = itemData.name, + icon = itemData.icon or C_Item.GetItemIconByID(itemData.id), + rarity = C_Item.GetItemQualityByID(itemData.id) or 1, + } + if GT.gameVersion == "retail" then + alertItemData.quality = C_TradeSkillUI.GetItemReagentQualityByItemInfo(itemData.id) + end + + GT.AlertSystem:AddItem(alertItemData.id) + GT.db.profile.Alerts[alertItemData.id] = {} + GT.db.profile.Alerts[alertItemData.id].enable = true + GT.db.profile.Alerts[alertItemData.id].alerts = {} + GT.db.profile.Alerts[itemData.id].itemData = alertItemData + GT:CreateAlertOptions(alertItemData) + else + GT.db.profile.Alerts[itemData.id] = nil + GT:RemoveItemAlerts(itemData.id) + end + end + + if itemData.id == -1 then + local divider = frame[expansion][category]:CreateTitle(itemData.name) + else + local name = itemData.name + + if itemData.quality then + if itemData.quality == 1 then + name = "|cff784335" .. name .. "*" + elseif itemData.quality == 2 then + name = "|cff96979E" .. name .. "**" + elseif itemData.quality == 3 then + name = "|cffDCC15F" .. name .. "***" + end + end + + frame[expansion][category][itemData.name] = frame[expansion][category]:CreateCheckbox(name, IsSelected_Item, SetSelected_Item) + frame[expansion][category][itemData.name]:AddInitializer(function(text, description, menu) + local leftTexture = text:AttachTexture() + + leftTexture:SetDrawLayer("BACKGROUND", 0) + leftTexture:SetPoint("LEFT", text.leftTexture1, "RIGHT", 7, 1) + + text:SetHeight(26) + leftTexture:SetSize(24, 24) + + if itemData.icon then + leftTexture:SetTexture(itemData.icon) + else + leftTexture:SetTexture(C_Item.GetItemIconByID(itemData.id)) + end + + text.fontString:SetPoint("LEFT", leftTexture, "RIGHT", 7, 1) + + local leftTextureRarity = text:AttachTexture() + leftTextureRarity:SetDrawLayer("BACKGROUND", 1) + local rarity = C_Item.GetItemQualityByID(itemData.id) or 1 + if rarity <= 1 then + leftTextureRarity:SetTexture("Interface\\Common\\WhiteIconFrame") + else + leftTextureRarity:SetAtlas("bags-glow-white") + end + local R, G, B = C_Item.GetItemQualityColor(rarity) + leftTextureRarity:SetVertexColor(R, G, B, 0.8) + leftTextureRarity:SetAllPoints(leftTexture) + + if itemData.quality then + local leftTextureQuality = text:AttachTexture() + leftTextureQuality:SetDrawLayer("BACKGROUND", 2) + if itemData.quality == 1 then + leftTextureQuality:SetAtlas("professions-icon-quality-tier1-inv", true) + elseif itemData.quality == 2 then + leftTextureQuality:SetAtlas("professions-icon-quality-tier2-inv", true) + elseif itemData.quality == 3 then + leftTextureQuality:SetAtlas("professions-icon-quality-tier3-inv", true) + end + leftTextureQuality:SetAllPoints(leftTexture) + end + end) + end + end + end + end + end + end + --add Custom Filters to filterMenu + GT:CreateCustomFiltersAlertsList(frame, rootDescription) + + local special = { + { + id = 1, + name = "All Items", + }, + { + id = 2, + name = "Total Items", + icon = 133647, + }, + } + + for _, itemData in ipairs(special) do + local function IsSelected_Item() + if GT.db.profile.Alerts[itemData.id] then + return true + else + return false + end + end + local function SetSelected_Item() + GT.Debug("Item Button Clicked", 2, itemData.name) + local key = not IsSelected_Item() + if key then + GT.AlertSystem:AddItem(itemData.id) + GT.db.profile.Alerts[itemData.id] = {} + GT.db.profile.Alerts[itemData.id].enable = true + GT.db.profile.Alerts[itemData.id].alerts = {} + GT.db.profile.Alerts[itemData.id].itemData = itemData + GT:CreateAlertOptions(itemData) + else + GT.db.profile.Alerts[itemData.id] = nil + GT:RemoveItemAlerts(itemData.id) + end + end + + frame[itemData.name] = rootDescription:CreateCheckbox(itemData.name, IsSelected_Item, SetSelected_Item) + end + + GT.AlertSystem.Menu.rootDescription = rootDescription + end + + ---@class GT.AlertSystem.menu: MenuProxy + GT.AlertSystem.Menu = MenuUtil.CreateContextMenu(frame, AlertsMenu) +end + +function GT:CreateCustomFiltersAlertsList(frame, rootDescription) + local customFiltersList = {} + for id, data in pairs(GT.db.profile.CustomFiltersTable) do + local itemID = tonumber(id) or 1 + local item = Item:CreateFromItemID(itemID) + --Waits for the data to be returned from the server + item:ContinueOnItemLoad(function() + local itemInfo = { C_Item.GetItemInfo(id) } + local itemData = { + id = id, + name = itemInfo[1], + icon = itemInfo[10], + rarity = itemInfo[3], + } + if GT.gameVersion == "retail" then + itemData.quality = C_TradeSkillUI.GetItemReagentQualityByItemInfo(id) + end + table.insert(customFiltersList, itemData) + end) + end + + table.sort(customFiltersList, function(a, b) + return a.name < b.name + end) + + frame["Custom Filters"] = rootDescription:CreateButton("Custom Filters", function() end) + + for itemIndex, itemData in ipairs(customFiltersList) do + local function IsSelected_CustomFilterItem() + if GT.db.profile.Alerts[itemData.id] then + return true + else + return false + end + end + local function SetSelected_CustomFilterItem() + GT.Debug("Item Button Clicked", 2, itemData.name) + local key = not IsSelected_CustomFilterItem() + if key then + GT.AlertSystem:AddItem(itemData.id) + GT.db.profile.Alerts[itemData.id] = {} + GT.db.profile.Alerts[itemData.id].enable = true + GT.db.profile.Alerts[itemData.id].alerts = {} + GT.db.profile.Alerts[itemData.id].itemData = itemData + GT:CreateAlertOptions(itemData) + else + GT.db.profile.Alerts[itemData.id] = nil + GT:RemoveItemAlerts(itemData.id) + end + end + + frame["Custom Filters"][itemData.name] = frame["Custom Filters"]:CreateCheckbox(itemData.name, IsSelected_CustomFilterItem, SetSelected_CustomFilterItem) + frame["Custom Filters"][itemData.name]:AddInitializer(function(text, description, menu) + local leftTexture = text:AttachTexture() + leftTexture:SetDrawLayer("BACKGROUND", 0) + text:SetHeight(26) + leftTexture:SetSize(24, 24) + leftTexture:SetPoint("LEFT", text.leftTexture1, "RIGHT", 7, 1) + leftTexture:SetTexture(tonumber(itemData.icon)) + + text.fontString:SetPoint("LEFT", leftTexture, "RIGHT", 7, 1) + + local leftTextureRarity = text:AttachTexture() + leftTextureRarity:SetDrawLayer("BACKGROUND", 1) + local rarity = C_Item.GetItemQualityByID(itemData.id) or 1 + if rarity <= 1 then + leftTextureRarity:SetTexture("Interface\\Common\\WhiteIconFrame") + else + leftTextureRarity:SetAtlas("bags-glow-white") + end + local R, G, B = C_Item.GetItemQualityColor(rarity) + leftTextureRarity:SetVertexColor(R, G, B, 0.8) + leftTextureRarity:SetAllPoints(leftTexture) + end) + end +end diff --git a/Bindings.lua b/Bindings.lua index 66108b6..7ef9c59 100644 --- a/Bindings.lua +++ b/Bindings.lua @@ -32,18 +32,6 @@ function GT:ToggleGatheringTracker() end end -function GT:ToggleCountNotifications() - GT.Debug("Toggle Count Notifications", 1, GT.db.profile.Notifications.Count.enable) - local key = not GT.db.profile.Notifications.Count.enable - GT.db.profile.Notifications.Count.enable = key -end - -function GT:ToggleGoldNotifications() - GT.Debug("Toggle Gold Notifications", 1, GT.db.profile.Notifications.Gold.enable) - local key = not GT.db.profile.Notifications.Gold.enable - GT.db.profile.Notifications.Gold.enable = key -end - function GT:ClearFilters() --disables all enabled filters GT.Debug("Clear Filters", 1) @@ -61,7 +49,7 @@ end function GT:ResetSession() --resets the per hour displays to current time and values - GT.Debug("Reset Per Hour", 1) + GT.Debug("Reset Session", 1) GT.GlobalStartTime = time() for itemID, itemData in pairs(GT.InventoryData) do @@ -70,6 +58,10 @@ function GT:ResetSession() itemData.sessionCount = 0 end + if GT.db.profile.General.sessionOnly then + GT.AlertSystem:ResetAlerts() + end + GT:RefreshPerHourDisplay(false, true) GT:RebuildDisplay("Reset Session") end diff --git a/Bindings.xml b/Bindings.xml index 77b8fbf..51a94f8 100644 --- a/Bindings.xml +++ b/Bindings.xml @@ -2,12 +2,6 @@ GatheringTracker:ToggleGatheringTracker() - - GatheringTracker:ToggleCountNotifications() - - - GatheringTracker:ToggleGoldNotifications() - GatheringTracker:ClearFilters() diff --git a/Broker.lua b/Broker.lua index 85854b2..f236aee 100644 --- a/Broker.lua +++ b/Broker.lua @@ -29,6 +29,8 @@ function GT:InitializeBroker() GT:ResetSession() elseif button == "LeftButton" then GT:GenerateFiltersMenu(frame) + elseif button == "RightButton" and IsShiftKeyDown() then + GT.AlertSystem:ResetAlerts() elseif button == "RightButton" then Settings.OpenToCategory(GT.metaData.name, true) end @@ -37,12 +39,15 @@ function GT:InitializeBroker() tooltip:AddLine(GT.metaData.name .. " |cffff6f00v" .. GT.metaData.version .. "|r") tooltip:AddLine(" ") tooltip:AddLine("|cff8080ffLeft-Click|r to open the Filter Menu") + tooltip:AddLine("|cff8080ffShift + Left-Click|r to reset Session") tooltip:AddLine("|cff8080ffRight-Click|r to open the addon options") + tooltip:AddLine("|cff8080ffShift + Right-Click|r to reset Alert Triggers") end, }) -- Register with LibDBIcon LibDBIcon:Register(GT.metaData.name, dataObj, GT.db.profile.miniMap) + LibDBIcon:Hide(GT.metaData.name) end function GT:MinimapHandler(key) diff --git a/Config.lua b/Config.lua index f0385b4..1e5ce8b 100644 --- a/Config.lua +++ b/Config.lua @@ -65,22 +65,9 @@ GT.defaults = { sessionItems = false, sessionOnly = false, itemTooltip = false, + alertsEnable = false, }, - Notifications = { - Count = { - enable = false, - threshold = "100", - itemAll = 1, - interval = 1, - sound = "Auction Window Close" - }, - Gold = { - enable = false, - threshold = "1000", - itemAll = 1, - interval = 1, - sound = "Auction Window Open" - }, + Alerts = { }, Filters = { }, @@ -88,7 +75,7 @@ GT.defaults = { CustomFiltersTable = { }, miniMap = { - hide = true, + enable = false, }, }, } @@ -104,6 +91,7 @@ local generalOptions = { args = { enable = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Enabled", desc = "Uncheck to disable the addon, this will effectively turn off the addon.", width = 1.70, @@ -115,6 +103,7 @@ local generalOptions = { }, unlock = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Unlock Frame", width = 1.70, get = function() return GT.db.profile.General.unlock end, @@ -126,15 +115,17 @@ local generalOptions = { }, miniMap = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Minimap Button", desc = "Enable this to show the minimap button.\n" .. - "Left Click shows filters menu.\n" .. - "Right Click opens the addon options.\n" .. - "Shift + Left Click resets Session Data.", + "|cff8080ffLeft Click|r shows filters menu.\n" .. + "|cff8080ffRight Click|r opens the addon options.\n" .. + "|cff8080ffShift + Left Click|r resets Session Data.\n" .. + "|cff8080ffShift + Right-Click|r to reset Alert Triggers", width = 1.70, - get = function() return not GT.db.profile.miniMap.hide end, + get = function() return GT.db.profile.miniMap.enable end, set = function(_, key) - GT.db.profile.miniMap.hide = not key + GT.db.profile.miniMap.enable = key GT:MinimapHandler(key) end, order = 3 @@ -146,6 +137,7 @@ local generalOptions = { }, filtersButton = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Filters Button", desc = "Left Click shows filters menu.\n" .. "Right Click clears all filters.\n" .. @@ -160,6 +152,7 @@ local generalOptions = { }, buttonFade = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Fade Out", desc = "When Enabled the Filter Button will fade out, but will show up again on mouse over.", width = 1.70, @@ -183,6 +176,7 @@ local generalOptions = { }, buttonAlpha = { type = "range", + dialogControl = "NW_Slider", name = "Fade Out Alpha", desc = "0% is not visible, 100% is fully visible.\nDefault is 0", min = 0, @@ -215,6 +209,7 @@ local generalOptions = { }, buttonDelay = { type = "range", + dialogControl = "NW_Slider", name = "Fade Out Delay", desc = "This configures how long after the mouse leaves the button before it fades out.\n" .. "Default is 0.5.", @@ -244,6 +239,7 @@ local generalOptions = { }, groupHide = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Hide in Group", desc = "When selected the display will be hidden when you are in a group.\n" .. "Delves and Follower Dungeons count as groups.", @@ -257,6 +253,7 @@ local generalOptions = { }, instanceHide = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Hide in Instance Content", desc = "When selected the display will be hidden in instance content.", width = 1.70, @@ -269,6 +266,7 @@ local generalOptions = { }, showDelve = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Show In Delves", desc = "When selected the display will be shown in Delves regardless of how Hide in Instance Content and Hide in Group are configured.", width = 1.70, @@ -295,6 +293,7 @@ local generalOptions = { }, showFollower = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Show in Follower Dungeons", desc = "When selected the display will be shown in Follower Dungeons regardless of how Hide in Instance Content and Hide in Group are configured.", width = 1.70, @@ -321,6 +320,7 @@ local generalOptions = { }, combatHide = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Hide in Combat", desc = "When selected the display will be hidden when you enter combat.\n" .. "This overrides the options for Show in Delves and Show in Follower Dungeons.", @@ -342,6 +342,7 @@ local generalOptions = { }, collapseDisplay = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Collapse Display", desc = "When selected the display will be collapsed to only display the total rows.", width = 1.70, @@ -354,6 +355,7 @@ local generalOptions = { }, collapseTime = { type = "range", + dialogControl = "NW_Slider", name = "Collapse Delay", desc = "This configures how long after the mouse leaves the display area before it clopases to the total rows.\nDefault is 2.", min = 0, @@ -378,6 +380,7 @@ local generalOptions = { }, allFiltered = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Display All Filtered Items", desc = "When selected all selected filtered items will be displayed, including those with 0 count.\n\n" .. @@ -400,6 +403,7 @@ local generalOptions = { }, itemTooltip = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Display Item Tooltip", desc = "When selected the item tooltip will be displayed when mousing over an items icon.\n\n" .. @@ -426,6 +430,7 @@ local generalOptions = { }, tsmPrice = { type = "select", + dialogControl = "NW_Dropdown", name = "Price Source", desc = "Select the desired price source, or none to disable price information.\n" .. "|cffff0000Supported addon required.|r\n\n" .. @@ -476,6 +481,7 @@ local generalOptions = { }, perItemPrice = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Display Per Item Price", desc = "If selected the price for 1 of each item will be displayed.\n" .. "Price Source is required for this option to be enabled.", @@ -496,6 +502,7 @@ local generalOptions = { }, ignoreAmount = { type = "range", + dialogControl = "NW_Slider", name = "Ignore Amount", desc = "Use this option to ignore a specific amount, this value will be subtracted from the totals.", min = 0, @@ -511,6 +518,7 @@ local generalOptions = { }, includeBank = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Include Bank", desc = "If selected displayed values will include items in your bank.", width = 1.70, @@ -523,6 +531,7 @@ local generalOptions = { }, includeReagent = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Include Reagent Bank", desc = "If selected displayed values will include items in your reagent bank.", width = 1.70, @@ -542,6 +551,7 @@ local generalOptions = { }, includeWarband = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Include Warband Bank", desc = "If selected displayed values will include items in your Warband bank.", width = 1.70, @@ -566,6 +576,7 @@ local generalOptions = { }, sessionItems = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Display Session Item Counts", desc = "If selected session item counts will be displayed in the column to the right of the item count.\n" .. "Price data (if enabled) is not displayed for session data.\n\n" .. @@ -583,6 +594,7 @@ local generalOptions = { }, sessionOnly = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Only Display Session Data", desc = "If selected only the session data will be displayed and selected items will only display if collected during the session.\n" .. "Price data (if enabled) is displayed for the session data.", @@ -603,6 +615,7 @@ local generalOptions = { }, itemsPerHour = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Display Items Per Hour", desc = "If selected an estimated items gathered per hour will be displayed.", width = 1.70, @@ -615,6 +628,7 @@ local generalOptions = { }, goldPerHour = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Display Gold Per Hour", desc = "If selected an estimated gold per hour will be displayed based on the value of items gathered.\n" .. "Price Source is required for this option to be enabled.", @@ -658,6 +672,7 @@ local generalOptions = { }, multiColumn = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Multiple Columns", desc = "Enables the display to use multiple columns.", width = 1.70, @@ -671,6 +686,7 @@ local generalOptions = { }, numRows = { type = "range", + dialogControl = "NW_Slider", name = "Max Rows Per Column", desc = "Set the maximum number of rows to be displayed per column.", min = 1, @@ -701,6 +717,7 @@ local generalOptions = { }, iconWidth = { type = "range", + dialogControl = "NW_Slider", name = "Icon Width", min = 10, max = 100, @@ -718,6 +735,7 @@ local generalOptions = { }, iconHeight = { type = "range", + dialogControl = "NW_Slider", name = "Icon Height", min = 10, max = 100, @@ -742,6 +760,7 @@ local generalOptions = { }, rarityBorder = { type = "toggle", + dialogControl = "NW_CheckBox", name = "Show Rarity Border", desc = "Will display a colored border based on item rarity.", width = 1.70, @@ -795,6 +814,7 @@ local generalOptions = { }, textSize = { type = "range", + dialogControl = "NW_Slider", name = "Text Size", min = 10, max = 70, @@ -827,9 +847,9 @@ local generalOptions = { }, textFont = { type = "select", + dialogControl = 'NW_Font', name = "Text Font", width = 1.20, - dialogControl = 'LSM30_Font', values = media:HashTable("font"), get = function() return GT.db.profile.General.textFont end, set = function(_, key) @@ -873,6 +893,7 @@ local generalOptions = { }, totalSize = { type = "range", + dialogControl = "NW_Slider", name = "Total Size", min = 10, max = 70, @@ -905,9 +926,9 @@ local generalOptions = { }, totalFont = { type = "select", + dialogControl = 'NW_Font', name = "Total Font", width = 1.20, - dialogControl = 'LSM30_Font', values = media:HashTable("font"), get = function() return GT.db.profile.General.totalFont end, set = function(_, key) @@ -931,246 +952,47 @@ local generalOptions = { }, }, }, - Notifications = { + Alerts = { type = "group", - name = "Notifications", - order = 3, + name = "Alerts", + childGroups = "tree", + order = 4, args = { - header1 = { - type = "header", - name = "Count Notification", - order = 1 - }, - countEnable = { + alertsEnable = { type = "toggle", - name = "Enable Count Notification", - desc = "Check to enable Count notification.", - width = "full", - get = function() return GT.db.profile.Notifications.Count.enable end, - set = function(_, key) - GT:ToggleCountNotifications() - end, - order = 2 - }, - countSound = { - type = "select", - name = "Alert Sound", - desc = "The sound that plays when the notification is triggered.\nDefault: Auction Window Close", - width = 1.40, - dialogControl = "LSM30_Sound", - values = media:HashTable("sound"), - get = function() return GT.db.profile.Notifications.Count.sound end, - set = function(_, key) GT.db.profile.Notifications.Count.sound = key end, - disabled = function() return not GT.db.profile.Notifications.Count.enable end, - order = 3 - }, - spacer1 = { - type = "description", - name = " ", - width = 0.3, - order = 4 - }, - countThreshold = { - type = "input", - name = "Count Threshold", - width = "Normal", - usage = "Enter threshold for alert\n\nDefault: 100", - validate = function(_, key) - if not (string.match(key, "[%d]+") or key == '') then - return false - end - return true - end, - get = function() return GT.db.profile.Notifications.Count.threshold end, + dialogControl = "NW_CheckBox", + name = "Enable Alerts", + desc = "Check to enable Alerts", + width = 1.7, + get = function() return GT.db.profile.General.alertsEnable end, set = function(_, key) - if key == '' or key == nil then - key = '0' - end - GT.db.profile.Notifications.Count.threshold = key + GT.db.profile.General.alertsEnable = key end, - disabled = function() return not GT.db.profile.Notifications.Count.enable end, - order = 5 - }, - countItemAll = { - type = "select", - name = "Notify for each item, all items, or both", - desc = "This controls if the notification triggers when each filtered item hits the threshold" .. - ", when all items hits the threshold, or both.\n\n" .. - "Default: All Items", - width = 1.40, - values = { [0] = "Each Item", [1] = "All Items", [2] = "Both" }, - get = function() return GT.db.profile.Notifications.Count.itemAll end, - set = function(_, key) GT.db.profile.Notifications.Count.itemAll = key end, - disabled = function() return not GT.db.profile.Notifications.Count.enable end, - order = 6 - }, - spacer2 = { - type = "description", - name = " ", - width = 0.3, - order = 7 + order = 101, }, - countInterval = { - type = "select", - name = "Exact or Interval", - desc = "This controls if the notification only triggers when exceeding the exact threshold" .. - ", an interval of the threshold, or both.\n" .. - "For an Example, if the threshold is 100:\n" .. - "Exact: only triggers once after exceeding 100\n" .. - "Interval: Triggers after exceeding 100, 200, 300, etc\n\n" .. - "Default: Exact", - width = 1.40, - values = { [0] = "Exact", [1] = "Interval" }, - get = function() return GT.db.profile.Notifications.Count.interval end, - set = function(_, key) GT.db.profile.Notifications.Count.interval = key end, - disabled = function() return not GT.db.profile.Notifications.Count.enable end, - order = 8 - }, - - --Gold Notification Settings - header2 = { - type = "header", - name = "Gold Notification", - order = 101 - }, - goldEnable = { - type = "toggle", - name = "Enable Gold Notification", - desc = "Check to enable gold notification.\n\nRequires TSM.", - width = "full", - get = function() return GT.db.profile.Notifications.Gold.enable end, - set = function(_, key) - GT:ToggleGoldNotifications() - end, - disabled = function() - if not GT.priceSources or GT.db.profile.General.tsmPrice == 0 then - return true - else - return false - end + addItem = { + type = "execute", + name = "Select Item for Alerts", + desc = "Click to select what item to enable for Alerts.", + width = 1.7, + func = function() + GT:GenerateAlertsMenu() end, - order = 102 - }, - goldSound = { - type = "select", - name = "Alert Sound", - desc = "The sound that plays when the notification is triggered.\nDefault: Auction Window Open", - width = 1.40, - dialogControl = "LSM30_Sound", - values = media:HashTable("sound"), - get = function() return GT.db.profile.Notifications.Gold.sound end, - set = function(_, key) GT.db.profile.Notifications.Gold.sound = key end, disabled = function() - if GT.db.profile.Notifications.Gold.enable then - if not GT.priceSources or GT.db.profile.General.tsmPrice == 0 then - return true - else - return false - end - else - return true - end - end, - order = 103 - }, - spacer3 = { - type = "description", - name = " ", - width = 0.3, - order = 104 - }, - goldThreshold = { - type = "input", - name = "Gold Threshold", - width = "Normal", - usage = "Enter threshold for alert in gold value\n\nDefault: 1000", - validate = function(_, key) - if not (string.match(key, "[%d]+") or key == '') then + if GT.db.profile.General.alertsEnable then return false - end - return true - end, - get = function() return GT.db.profile.Notifications.Gold.threshold end, - set = function(_, key) - if key == '' or key == nil then - key = '0' - end - GT.db.profile.Notifications.Gold.threshold = key - end, - disabled = function() - if GT.db.profile.Notifications.Gold.enable then - if not GT.priceSources or GT.db.profile.General.tsmPrice == 0 then - return true - else - return false - end - else - return true - end - end, - order = 105 - }, - goldItemAll = { - type = "select", - name = "Notify for each item, all items, or both", - desc = "This controls if the notification triggers when each filtered item hits the threshold" .. - ", when all items hits the threshold, or both.\n\n" .. - "Default: All Items", - width = 1.40, - values = { [0] = "Each Item", [1] = "All Items", [2] = "Both" }, - get = function() return GT.db.profile.Notifications.Gold.itemAll end, - set = function(_, key) GT.db.profile.Notifications.Gold.itemAll = key end, - disabled = function() - if GT.db.profile.Notifications.Gold.enable then - if not GT.priceSources or GT.db.profile.General.tsmPrice == 0 then - return true - else - return false - end - else - return true - end - end, - order = 106 - }, - spacer4 = { - type = "description", - name = " ", - width = 0.3, - order = 107 - }, - goldInterval = { - type = "select", - name = "Exact or Interval", - desc = "This controls if the notification only triggers when exceeding the exact threshold" .. - ", an interval of the threshold, or both.\n" .. - "For an Example, if the threshold is 100:\n" .. - "Exact: only triggers once after exceeding 100\n" .. - "Interval: Triggers after exceeding 100, 200, 300, etc\n\n" .. - "Default: Exact", - width = 1.40, - values = { [0] = "Exact", [1] = "Interval" }, - get = function() return GT.db.profile.Notifications.Gold.interval end, - set = function(_, key) GT.db.profile.Notifications.Gold.interval = key end, - disabled = function() - if GT.db.profile.Notifications.Gold.enable then - if not GT.priceSources or GT.db.profile.General.tsmPrice == 0 then - return true - else - return false - end else return true end end, - order = 108 + order = 102, }, - } + }, }, Debug = { type = "group", name = "Debug", - order = 4, + order = 5, args = { header5 = { type = "header", @@ -1179,6 +1001,7 @@ local generalOptions = { }, debugOption = { type = "select", + dialogControl = "NW_Dropdown", name = "Debug", desc = "This is for debugging the addon, do NOT enable, it is spammy.", width = 1.70, @@ -1205,6 +1028,563 @@ local generalOptions = { } } +local function InitializeAlert(Item, alertType, typeCount, DB) + local Alert = Item:AddAlert(alertType, typeCount, DB.triggerValue) + Alert:SetEnabled(DB.enable) + Alert:SetTriggerType(DB.triggerType) + Alert:SetTriggerMultiple(DB.triggerMultiple) + Alert:SetTriggerMultiplier(DB.triggerValue) + if alertType == "Audio" then + Alert:SetAlertSettings({ tiggerSound = DB.tiggerSound or "Auction Window Open" }) + elseif alertType == "Highlight" then + Alert:SetAlertSettings({ highlightBorder = DB.highlightBorder, highlightColor = DB.highlightColor }) + elseif alertType == "Screen Flash" then + Alert:SetAlertSettings({ flashDuration = DB.flashDuration, flashColor = DB.flashColor }) + end + + return Alert +end + +local function GetAlertOptionsTable(itemData, alertType, typeCount, Item, Alert) + local DB = GT.db.profile.Alerts[itemData.id].alerts[alertType][typeCount] + local typeName = alertType .. "_" .. typeCount + + local options = { + type = "group", + name = alertType .. " Alert " .. typeCount, + order = DB.order + typeCount, + inline = true, + disabled = function() + if not GT.db.profile.General.alertsEnable then + return true + end + if not GT.db.profile.Alerts[itemData.id].enable then + return true + end + if not DB.enable then + return true + end + return false + end, + args = { + enableAlert = { + type = "toggle", + dialogControl = "NW_CheckBox", + name = "Enable " .. alertType .. " Alert", + desc = "Check to enable " .. alertType .. " alert for " .. itemData.name, + width = "normal", + get = function() + if DB.enable then + return DB.enable + end + return false + end, + set = function(_, key) + DB.enable = key + Alert:SetEnabled(key) + end, + disabled = function() + if not GT.db.profile.General.alertsEnable then + return true + end + if not GT.db.profile.Alerts[itemData.id].enable then + return true + end + return false + end, + order = 1 + }, + removeAlert = { + type = "execute", + name = "Delete Alert", + desc = "Click to delete " .. alertType .. " Alert " .. typeCount, + width = "normal", + confirm = true, + func = function() + local alertOptions = generalOptions.args.Alerts.args[tostring(itemData.id)].args + local alertTypeCount = #GT.db.profile.Alerts[itemData.id].alerts[alertType] + alertOptions[typeName] = nil + table.remove(GT.db.profile.Alerts[itemData.id].alerts[alertType], typeCount) + if #GT.db.profile.Alerts[itemData.id].alerts[alertType] == 0 then + GT.db.profile.Alerts[itemData.id].alerts[alertType] = nil + end + + Item:RemoveAlert(Alert) + + if typeCount < alertTypeCount then + for index = typeCount + 1, alertTypeCount do + local alertToUpdate = Item:GetAlert(alertType, index) + alertToUpdate:SetTypeCount(index - 1) + alertOptions[alertType .. "_" .. index] = nil + alertOptions[alertType .. "_" .. (index - 1)] = GetAlertOptionsTable(itemData, alertType, (index - 1), Item, Alert) + end + end + AceConfigRegistry:NotifyChange(GT.metaData.name) + end, + disabled = function() + if not GT.db.profile.General.alertsEnable then + return true + end + if not GT.db.profile.Alerts[itemData.id].enable then + return true + end + return false + end, + order = 2, + }, + triggerValue = { + type = "input", + name = "Trigger Value", + width = "Normal", + desc = "Enter value the alert should trigger at.\n\n" .. + "Uses session value when |cffffd100Only Display Session Data|r is enabled.\n\n", + usage = "Must be a whole number", + validate = function(_, key) + if (string.match(key, "[^%d]") or key == '') then + return false + end + return true + end, + get = function() return tostring(DB.triggerValue) end, + set = function(_, key) + if key == '' or key == nil then + key = 0 + end + DB.triggerValue = tonumber(key) + Alert:SetTriggerValue(tonumber(key)) + end, + order = 3 + }, + triggerType = { + type = "select", + dialogControl = "NW_Dropdown", + name = "Trigger Type", + width = "Normal", + desc = "Select which type of value should be triggered off of.", + values = function() + local values = {} + values[1] = "Item Count" + if GT.priceSources and GT.db.profile.General.tsmPrice > 0 then + values[2] = "Gold Value" + end + return values + end, + get = function() return DB.triggerType end, + set = function(_, key) + DB.triggerType = key + Alert:SetTriggerType(key) + end, + order = 4 + }, + triggerMultiple = { + type = "toggle", + dialogControl = "NW_CheckBox", + name = "Trigger on Multiplier", + desc = "When enabled the alert will trigger on multiples of the Trigger Value.\n\n" .. + "Example: If Trigger Value is 100, this option will cause the alert to trigger on 100, 200, 300, etc.", + width = "Normal", + get = function() return DB.triggerMultiple end, + set = function(_, key) + DB.triggerMultiple = key + Alert:SetTriggerMultiple(key) + Alert:SetTriggerMultiplier(DB.triggerValue) + end, + order = 5 + }, + }, + } + if alertType == "Audio" then + options.args.tiggerSound = { + type = "select", + dialogControl = "NW_Sound", + name = "Alert Sound", + desc = "The sound that plays when the alert is triggered.\n\n" .. + "Default: Auction Window Open", + width = "Normal", + values = media:HashTable("sound"), + get = function() + local sound = "Auction Window Open" + if media:IsValid("sound", DB.tiggerSound) then + sound = DB.tiggerSound + end + return sound + end, + set = function(_, key) + DB.tiggerSound = key + Alert:SetAlertSettings({ tiggerSound = DB.tiggerSound }) + end, + order = 100 + } + elseif alertType == "Highlight" then + options.args.highlightBorder = { + type = "select", + dialogControl = "NW_Highlight", + name = "Highlight Texture", + desc = "The highlight texture that is displayed when an the alert is triggered.", + width = "Normal", + values = { + ["Border 1"] = "Interface\\Addons\\GatheringTracker\\Media\\border1", + ["Border 2"] = "Interface\\Addons\\GatheringTracker\\Media\\border2", + ["Top/Bottom 1"] = "Interface\\Addons\\GatheringTracker\\Media\\border3", + ["Top/Bottom 2"] = "Interface\\Addons\\GatheringTracker\\Media\\border4", + }, + get = function() return DB.highlightBorder end, + set = function(_, key) + DB.highlightBorder = key + Alert:SetAlertSettings({ highlightBorder = DB.highlightBorder, highlightColor = DB.highlightColor }) + end, + order = 101 + } + options.args.highlightColor = { + type = "color", + name = "Highlight Color", + width = "Normal", + hasAlpha = true, + get = function() + local c = DB.highlightColor + return c[1], c[2], c[3], c[4] + end, + set = function(_, r, g, b, a) + DB.highlightColor = { r, g, b, a } + Alert:SetAlertSettings({ highlightBorder = DB.highlightBorder, highlightColor = DB.highlightColor }) + AceConfigRegistry:NotifyChange(GT.metaData.name) + end, + order = 102 + } + options.args.highlightPreview = { + type = "description", + dialogControl = "NW_Label", + name = "", + width = "Normal", + image = function() + local atlas = GT.HighlightTextures[DB.highlightBorder].atlas + return atlas, 108, 27 + end, + imageCoords = function() + local data = {} + table.insert(data, "texture") + table.insert(data, DB.highlightColor) + return data + end, + order = 103 + } + elseif alertType == "Screen Flash" then + options.args.flashDuration = { + type = "range", + dialogControl = "NW_Slider", + name = "Screen Flash Duration", + min = 0.5, + max = 20, + softMax = 10, + step = 0.1, + width = "Normal", + get = function() return DB.flashDuration end, + set = function(_, key) + DB.flashDuration = key + Alert:SetAlertSettings({ flashDuration = DB.flashDuration, flashColor = DB.flashColor }) + end, + order = 100 + } + options.args.flashColor = { + type = "color", + name = "Screen Flash Color", + width = "Normal", + hasAlpha = true, + get = function() + local c = DB.flashColor + return unpack(c) + end, + set = function(_, r, g, b, a) + DB.flashColor = { r, g, b, a } + Alert:SetAlertSettings({ flashDuration = DB.flashDuration, flashColor = DB.flashColor }) + AceConfigRegistry:NotifyChange(GT.metaData.name) + end, + order = 101 + } + options.args.flashPreview = { + type = "description", + dialogControl = "NW_Label", + name = "", + width = "Normal", + image = function() + local texture = "Interface\\Addons\\GatheringTracker\\Media\\ScreenFlash" + return texture, 128, 128 + end, + imageCoords = function() + local data = {} + table.insert(data, "texture") + table.insert(data, DB.flashColor) + return data + end, + order = 102 + } + --removing text option for now, may revisit after Alerts is released + --[[elseif alertType == "Text" then + options.args.textDuration = { + type = "range", + dialogControl = "NW_Slider", + name = "Display Text Duration", + min = 0.5, + max = 20, + softMax = 10, + step = 0.1, + width = "Normal", + get = function() return DB.textDuration or 1 end, + set = function(_, key) + DB.textDuration = key + end, + order = 100 + } + options.args.textColor = { + type = "color", + name = "Display Text Color", + width = "Normal", + get = function() + local c = DB.textColor or { 1, 1, 1 } + return unpack(c) + end, + set = function(_, r, g, b) + DB.textColor = { r, g, b } + AceConfigRegistry:NotifyChange(GT.metaData.name) + end, + order = 101 + } + options.args.textString = { + type = "input", + name = "Display Text", + width = "full", + multiline = 2, + desc = "Enter what text will be displayed on screen.\n\n" .. + "#item# - will display the Item Name.\n" .. + "#value# - will display the current value for the item based on the trigger type." .. + "#trigger# - will display the trigger value for the alert.", + get = function() return DB.textString or "#item# exceeded #trigger# items" end, + set = function(_, key) + DB.textString = key + end, + order = 103 + } + options.args.textPreview = { + type = "description", + dialogControl = "NW_Label", + name = function() + local text = DB.textString or "#item# exceeded #trigger# items" + text = string.gsub(text, "#item#", itemData.name) + text = string.gsub(text, "#value#", function() + if GT.InventoryData[itemData.id] then + return GT.InventoryData[itemData.id].count + end + return 0 + end) + text = string.gsub(text, "#trigger#", DB.triggerValue or 0) + local data = { + text, + DB.textColor or { 1, 1, 1 } + } + return data + end, + width = "full", + fontSize = "medium", + order = 104 + }]] + end + + return options +end + +local function AddAlertConfig(itemData, Item, alertType, alertIndex) + GT.Debug("AddAlertConfig", 4, itemData.id, itemData.name, alertType, alertIndex) + local alertOptions = generalOptions.args.Alerts.args[tostring(itemData.id)].args + local typeCount = alertIndex or #GT.db.profile.Alerts[itemData.id].alerts[alertType] + local DB = GT.db.profile.Alerts[itemData.id].alerts[alertType][typeCount] + local typeName = alertType .. "_" .. typeCount + + local Alert = InitializeAlert(Item, alertType, typeCount, DB) + + alertOptions[typeName] = GetAlertOptionsTable(itemData, alertType, typeCount, Item, Alert) + AceConfigRegistry:NotifyChange(GT.metaData.name) +end + +local function SetupAlertDefaults(itemData, data) + GT.db.profile.Alerts[itemData.id].alerts[data[1]] = GT.db.profile.Alerts[itemData.id].alerts[data[1]] or {} + local typeCount = #GT.db.profile.Alerts[itemData.id].alerts[data[1]] + 1 + GT.db.profile.Alerts[itemData.id].alerts[data[1]][typeCount] = { + enable = true, + order = data[2], + triggerValue = 0, + triggerType = 1, + triggerMultiple = false, + } + local DB = GT.db.profile.Alerts[itemData.id].alerts[data[1]][typeCount] + + if data[1] == "Audio" then + DB.tiggerSound = "Auction Window Open" + elseif data[1] == "Highlight" then + DB.highlightBorder = "Border 1" + DB.highlightColor = { 1, 1, 1, 1 } + elseif data[1] == "Screen Flash" then + DB.flashDuration = 3 + DB.flashColor = { 1, 0, 0, 1 } + end +end + +local function AlertMenu(frame, itemData, Item) + MenuUtil.CreateContextMenu(frame, function(ownerRegion, rootDescription) + local function OnClick(data) + SetupAlertDefaults(itemData, data) + AddAlertConfig(itemData, Item, data[1]) + end + rootDescription:CreateButton("Audio", OnClick, { "Audio", 10 }) + rootDescription:CreateButton("Highlight", OnClick, { "Highlight", 20 }) + rootDescription:CreateButton("Screen Flash", OnClick, { "Screen Flash", 30 }) + end) +end + +local function AddAlertsFromDB(itemData) + if not GT.db.profile.Alerts[itemData.id].alerts then + return + end + + for type, alerts in pairs(GT.db.profile.Alerts[itemData.id].alerts) do + local Item = GT.AlertSystem:GetItem(itemData.id) + for index, alertData in ipairs(alerts) do + AddAlertConfig(itemData, Item, type, index) + end + end +end + +function GT:InitializeAlertOptions(event, itemData) + GT.Debug("Initialize Alert Options", 1, event, itemData) + if event == "Refresh Config" then + for name, data in pairs(generalOptions.args.Alerts.args) do + if name ~= "addItem" and name ~= "alertsEnable" then + generalOptions.args.Alerts.args[name] = nil + end + end + end + + for id, data in pairs(GT.db.profile.Alerts) do + local itemData = {} + if id > 2 then + GT.Debug("Create Alerts Table", 2, "Normal Item", id) + local item = Item:CreateFromItemID(id) + item:ContinueOnItemLoad(function() + local itemInfo = { C_Item.GetItemInfo(id) } + itemData = { + id = id, + name = itemInfo[1], + icon = itemInfo[10], + rarity = itemInfo[3], + } + if GT.gameVersion == "retail" then + itemData.quality = C_TradeSkillUI.GetItemReagentQualityByItemInfo(id) + end + GT:CreateAlertOptions(itemData) + AddAlertsFromDB(itemData) + end) + else + GT.Debug("Create Alerts Table", 2, "Special Item", id) + itemData = { + id = id, + name = data.itemData.name, + icon = data.itemData.icon, + } + GT:CreateAlertOptions(itemData) + AddAlertsFromDB(itemData) + end + end + AceConfigRegistry:NotifyChange(GT.metaData.name) +end + +function GT:CreateAlertOptions(itemData) + GT.Debug("Create Alert Options", 3, itemData.id, itemData.name) + local alertOptions = generalOptions.args.Alerts.args + local Item = GT.AlertSystem:GetItem(itemData.id) or GT.AlertSystem:AddItem(itemData.id) + Item:SetEnabled(GT.db.profile.Alerts[itemData.id].enable) + + alertOptions[tostring(itemData.id)] = { + type = "group", + name = itemData.name, + order = itemData.id, + icon = function() + if itemData.icon then + return itemData.icon + end + end, + args = { + enableAlert = { + type = "toggle", + dialogControl = "NW_CheckBox", + name = "Enable " .. itemData.name .. " Alert(s)", + desc = "Check to enable alert(s) for " .. itemData.name, + width = 1.4, + get = function() + if GT.db.profile.Alerts[itemData.id].enable then + return GT.db.profile.Alerts[itemData.id].enable + end + return false + end, + set = function(_, key) + GT.db.profile.Alerts[itemData.id].enable = key + Item:SetEnabled(key) + end, + disabled = function() + if GT.db.profile.General.alertsEnable then + return false + end + return true + end, + order = 1 + }, + addAlert = { + type = "execute", + name = "Add Alert", + desc = "Click to select what type of alert to add.", + width = "normal", + func = function() + AlertMenu(GT.Options.Main, itemData, Item) + end, + disabled = function() + if not GT.db.profile.General.alertsEnable then + return true + end + if not GT.db.profile.Alerts[itemData.id].enable then + return true + end + return false + end, + order = 2, + }, + removeItem = { + type = "execute", + name = "Remove Item", + desc = "Click to remove " .. itemData.name, + width = "normal", + confirm = true, + func = function() + alertOptions[tostring(itemData.id)] = nil + GT.db.profile.Alerts[itemData.id] = nil + GT.AlertSystem:RemoveItem(itemData.id) + AceConfigRegistry:NotifyChange(GT.metaData.name) + end, + disabled = function() + if GT.db.profile.General.alertsEnable then + return false + end + return true + end, + order = 3, + }, + }, + } + AceConfigRegistry:NotifyChange(GT.metaData.name) +end + +function GT:RemoveItemAlerts(id) + generalOptions.args.Alerts.args[tostring(id)] = nil + AceConfigRegistry:NotifyChange(GT.metaData.name) +end + local filterOptions = { type = "group", name = "Filters", @@ -1454,8 +1834,8 @@ end local function UpdateChangedorRemovedSavedVariables() -- Increment when adding anything to function - local fixConstant = 1 - if GT.db.profile.General.fixSettings < fixConstant then + local fixConstant = 2 + if GT.db.profile.General.fixSettings < fixConstant and GT.db.profile.General.fixSettings == 1 then --Change debug to int instead of bool if type(GT.db.profile.General.debugOption) == "boolean" then GT.db.profile.General.debugOption = 0 @@ -1484,6 +1864,10 @@ local function UpdateChangedorRemovedSavedVariables() GT.db.profile.CustomFiltersTable = tempFilterTable GT.db.profile.General.fixSettings = fixConstant + elseif GT.db.profile.General.fixSettings < fixConstant and GT.db.profile.General.fixSettings == 2 then + if GT.db.profile.Notifications then + GT.db.profile.Notifications = nil + end end end @@ -1509,12 +1893,18 @@ function GT:RefreshConfig(event, db, profile) GT.db.profile.General.xPos, GT.db.profile.General.yPos ) + GT.AlertSystem.AllowAlertEffects = false + GT.AlertSystem:RemoveAllItems("Refresh Config") GT:RebuildIDTables() GT:ClearDisplay() - GT:FiltersButton(true) + GT:FiltersButton() GT:InventoryUpdate("Refresh Config", true) GT:CreateCustomFilterOptions() + GT:InitializeAlertOptions("Refresh Config") + GT:MinimapHandler(GT.db.profile.miniMap.enable) + + GT:wait(2, "AllowAlertEffects", "AllowAlertEffects") end local function InitializePriceSource() @@ -1538,6 +1928,7 @@ end function GT:OnInitialize() --have to check if tsm is loaded before we create the options so that we can use that variable in the options. GT.priceSources = InitializePriceSource() + GT.GeneralOptions = generalOptions GT.db = LibStub("AceDB-3.0"):New("GatheringTrackerDB", GT.defaults, true) GT.db.RegisterCallback(GT, "OnProfileChanged", "RefreshConfig") @@ -1558,6 +1949,7 @@ function GT:OnInitialize() UpdateChangedorRemovedSavedVariables() + AceConfigRegistry:RegisterOptionsTable(GT.metaData.name, generalOptions) GT.Options.Main = AceConfigDialog:AddToBlizOptions(GT.metaData.name, GT.metaData.name) GT.Options.Main:SetScript("OnHide", GT.OptionsHide) @@ -1584,18 +1976,19 @@ function GT:OnInitialize() --register font and sound with LSM media:Register("font", "Fira Mono Medium", "Interface\\Addons\\GatheringTracker\\Media\\Fonts\\FiraMono-Medium.ttf", media.LOCALE_BIT_western + media.LOCALE_BIT_ruRU) - media:Register("sound", "Auction Window Open", "567482") - media:Register("sound", "Auction Window Close", "567499") - media:Register("sound", "Auto Quest Complete", "567476") - media:Register("sound", "Level Up", "567431") - media:Register("sound", "Player Invite", "567451") - media:Register("sound", "Raid Warning", "567397") - media:Register("sound", "Ready Check", "567409") - media:Register("sound", "Murloc Aggro", "556000") - media:Register("sound", "Map Ping", "567416") - media:Register("sound", "Bonk 1", "568956") - media:Register("sound", "Bonk 2", "569179") - media:Register("sound", "Bonk 3", "569569") + media:Register("sound", "Auction Window Open", 567482) + media:Register("sound", "Auction Window Close", 567499) + media:Register("sound", "Auto Quest Complete", 567476) + media:Register("sound", "Level Up", 567431) + media:Register("sound", "Player Invite", 567451) + media:Register("sound", "Raid Warning", 567397) + media:Register("sound", "Ready Check", 567409) + media:Register("sound", "Murloc Aggro", 556000) + media:Register("sound", "Map Ping", 567416) + media:Register("sound", "Bonk 1", 568956) + media:Register("sound", "Bonk 2", 569179) + media:Register("sound", "Bonk 3", 569569) + media:Register("sound", "Turtle Water", 109068) GT.Enabled = GT.db.profile.General.enable if not GT.Enabled then @@ -1603,10 +1996,13 @@ function GT:OnInitialize() end GT:InitializeBroker() - - --Pause Notifications to prevent spam after reloading the UI - GT.NotificationPause = true - GT:RebuildIDTables() GT:CreateBaseFrame() + GT:FiltersButton() + GT:InitializePools() + + GT.AlertSystem:CreateAlertFrames() + GT:InitializeAlertOptions("OnInitialize") + + GT.temp = generalOptions end diff --git a/Constants.lua b/Constants.lua index 79b21be..458008f 100644 --- a/Constants.lua +++ b/Constants.lua @@ -1,6 +1,29 @@ ---@class GT local GT = LibStub("AceAddon-3.0"):GetAddon("GatheringTracker") +GT.HighlightTextures = { + ["Border 1"] = { + atlas = "Interface\\Addons\\GatheringTracker\\Media\\border1", + texture = "interface\\lootframe\\lootframe", + textureCoords = { 0.001953125, 0.583984375, 0.5224609375, 0.5966796875 }, + }, + ["Border 2"] = { + atlas = "Interface\\Addons\\GatheringTracker\\Media\\border2", + texture = "interface\\buttons\\listbuttons", + textureCoords = { 0.001953125, 0.76953125, 0.095703125, 0.185546875 }, + }, + ["Top/Bottom 1"] = { + atlas = "Interface\\Addons\\GatheringTracker\\Media\\border3", + texture = "interface\\garrison\\adventuremissionslist", + textureCoords = { 0.0009765625, 0.82421875, 0.1875, 0.369140625 }, + }, + ["Top/Bottom 2"] = { + atlas = "Interface\\Addons\\GatheringTracker\\Media\\border4", + texture = "interface\\common\\search", + textureCoords = { 0.001953125, 0.501953125, 0.234375, 0.6015625 }, + }, +} + local expansionsOrder = { "Classic", "BC", @@ -52,531 +75,531 @@ end local ItemData = { -- Classic - { id = 2447, name = "Peacebloom", order = 1, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 765, name = "Silverleaf", order = 2, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 2449, name = "Earthroot", order = 3, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 785, name = "Mageroyal", order = 4, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 2450, name = "Briarthorn", order = 5, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 2452, name = "Swiftthistle", order = 6, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 3820, name = "Stranglekelp", order = 7, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 2453, name = "Bruiseweed", order = 8, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 3369, name = "Grave Moss", order = 9, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 3355, name = "Wild Steelbloom", order = 10, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 3356, name = "Kingsblood", order = 11, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 3357, name = "Liferoot", order = 12, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 3818, name = "Fadeleaf", order = 13, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 3821, name = "Goldthorn", order = 14, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 3358, name = "Khadgars Whisker", order = 15, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 3819, name = "Dragons Teeth", order = 16, retail = true, classic = true, expansion = "Classic", category = "Herb" }, - { id = 3819, name = "Wintersbite", order = 17, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 4625, name = "Firebloom", order = 18, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 5056, name = "Root Sample", order = 19, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 8831, name = "Purple Lotus", order = 20, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 8153, name = "Wildvine", order = 21, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 2447, name = "Peacebloom", order = 1, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 765, name = "Silverleaf", order = 2, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 2449, name = "Earthroot", order = 3, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 785, name = "Mageroyal", order = 4, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 2450, name = "Briarthorn", order = 5, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 2452, name = "Swiftthistle", order = 6, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 3820, name = "Stranglekelp", order = 7, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 2453, name = "Bruiseweed", order = 8, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 3369, name = "Grave Moss", order = 9, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 3355, name = "Wild Steelbloom", order = 10, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 3356, name = "Kingsblood", order = 11, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 3357, name = "Liferoot", order = 12, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 3818, name = "Fadeleaf", order = 13, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 3821, name = "Goldthorn", order = 14, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 3358, name = "Khadgars Whisker", order = 15, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 3819, name = "Dragons Teeth", order = 16, retail = true, cata = true, wrath = true, bc = true, expansion = "Classic", category = "Herb" }, + { id = 3819, name = "Wintersbite", order = 17, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 4625, name = "Firebloom", order = 18, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 5056, name = "Root Sample", order = 19, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 8831, name = "Purple Lotus", order = 20, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 8153, name = "Wildvine", order = 21, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, { id = 8836, name = "Arthas Tears", order = 22, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 8838, name = "Sungrass", order = 23, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 8839, name = "Blindweed", order = 24, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 8845, name = "Ghost Mushroom", order = 25, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 8846, name = "Gromsblood", order = 26, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 8838, name = "Sungrass", order = 23, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 8839, name = "Blindweed", order = 24, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 8845, name = "Ghost Mushroom", order = 25, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 8846, name = "Gromsblood", order = 26, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, { id = 11514, name = "Fel Creep", order = 27, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 13464, name = "Golden Sansam", order = 28, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 13463, name = "Dreamfoil", order = 29, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 13465, name = "Mountain Silversage", order = 30, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 13466, name = "Sorrowmoss", order = 31, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 13467, name = "Icecap", order = 32, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 13468, name = "Black Lotus", order = 33, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 13464, name = "Golden Sansam", order = 28, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 13463, name = "Dreamfoil", order = 29, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 13465, name = "Mountain Silversage", order = 30, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 13466, name = "Sorrowmoss", order = 31, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 13467, name = "Icecap", order = 32, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, + { id = 13468, name = "Black Lotus", order = 33, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Herb" }, { id = 19726, name = "Bloodvine", order = 34, era = true, season = true, expansion = "Classic", category = "Herb" }, - { id = 2770, name = "Copper Ore", order = 1, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Ore" }, - { id = 2771, name = "Tin Ore", order = 2, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Ore" }, - { id = 2775, name = "Silver Ore", order = 3, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Ore" }, - { id = 2772, name = "Iron Ore", order = 4, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Ore" }, - { id = 2776, name = "Gold Ore", order = 5, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Ore" }, - { id = 3858, name = "Mithril Ore", order = 6, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Ore" }, - { id = 7911, name = "Truesilver Ore", order = 7, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Ore" }, - { id = 10620, name = "Thorium Ore", order = 8, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Ore" }, - { id = 11370, name = "Dark Iron Ore", order = 9, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Ore" }, - { id = -1, name = "Stone", order = 10, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Ore" }, - { id = 2835, name = "Rough Stone", order = 11, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Ore" }, - { id = 2836, name = "Coarse Stone", order = 12, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Ore" }, - { id = 2838, name = "Heavy Stone", order = 13, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Ore" }, - { id = 7912, name = "Solid Stone", order = 14, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Ore" }, - { id = 12365, name = "Dense Stone", order = 15, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Ore" }, - { id = -1, name = "Other", order = 16, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Ore" }, - { id = 22202, name = "Small Obsidian Shard", order = 17, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Ore" }, - { id = 22203, name = "Large Obsidian Shard", order = 18, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Ore" }, + { id = 2770, name = "Copper Ore", order = 1, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Ore" }, + { id = 2771, name = "Tin Ore", order = 2, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Ore" }, + { id = 2775, name = "Silver Ore", order = 3, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Ore" }, + { id = 2772, name = "Iron Ore", order = 4, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Ore" }, + { id = 2776, name = "Gold Ore", order = 5, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Ore" }, + { id = 3858, name = "Mithril Ore", order = 6, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Ore" }, + { id = 7911, name = "Truesilver Ore", order = 7, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Ore" }, + { id = 10620, name = "Thorium Ore", order = 8, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Ore" }, + { id = 11370, name = "Dark Iron Ore", order = 9, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Ore" }, + { id = -1, name = "Stone", order = 10, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Ore" }, + { id = 2835, name = "Rough Stone", order = 11, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Ore" }, + { id = 2836, name = "Coarse Stone", order = 12, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Ore" }, + { id = 2838, name = "Heavy Stone", order = 13, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Ore" }, + { id = 7912, name = "Solid Stone", order = 14, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Ore" }, + { id = 12365, name = "Dense Stone", order = 15, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Ore" }, + { id = -1, name = "Other", order = 16, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Ore" }, + { id = 22202, name = "Small Obsidian Shard", order = 17, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Ore" }, + { id = 22203, name = "Large Obsidian Shard", order = 18, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Ore" }, { id = 3340, name = "Incendicite Ore", order = 19, era = true, season = true, expansion = "Classic", category = "Ore" }, { id = 5833, name = "Indurium Ore", order = 20, era = true, season = true, expansion = "Classic", category = "Ore" }, { id = 4278, name = "Lesser Bloodstone Ore", order = 21, era = true, season = true, expansion = "Classic", category = "Ore" }, { id = 2798, name = "Rethban Ore", order = 22, era = true, season = true, expansion = "Classic", category = "Ore" }, { id = 11513, name = "Tainted Vitriol", order = 23, era = true, season = true, expansion = "Classic", category = "Ore" }, - { id = 2589, name = "Linen Cloth", order = 1, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, - { id = 2592, name = "Wool Cloth", order = 2, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, - { id = 4306, name = "Silk Cloth", order = 3, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, - { id = 4338, name = "Mageweave Cloth", order = 4, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, - { id = 14047, name = "Runecloth", order = 5, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, - { id = 14256, name = "Felcloth", order = 6, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, - { id = -1, name = "Silk", order = 7, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, - { id = 3182, name = "Spiders Silk", order = 8, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, - { id = 4337, name = "Thick Spiders Silk", order = 9, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, - { id = 10285, name = "Shadow Silk", order = 10, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, - { id = 14227, name = "Ironweb Spider Silk", order = 11, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, - { id = 2318, name = "Light Leather", order = 1, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 2319, name = "Medium Leather", order = 2, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 4234, name = "Heavy Leather", order = 3, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 4304, name = "Thick Leather", order = 4, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 8170, name = "Rugged Leather", order = 5, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 15417, name = "Devilsaur Leather", order = 6, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 15419, name = "Warbear Leather", order = 7, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 2589, name = "Linen Cloth", order = 1, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, + { id = 2592, name = "Wool Cloth", order = 2, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, + { id = 4306, name = "Silk Cloth", order = 3, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, + { id = 4338, name = "Mageweave Cloth", order = 4, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, + { id = 14047, name = "Runecloth", order = 5, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, + { id = 14256, name = "Felcloth", order = 6, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, + { id = -1, name = "Silk", order = 7, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, + { id = 3182, name = "Spiders Silk", order = 8, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, + { id = 4337, name = "Thick Spiders Silk", order = 9, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, + { id = 10285, name = "Shadow Silk", order = 10, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, + { id = 14227, name = "Ironweb Spider Silk", order = 11, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Cloth" }, + { id = 2318, name = "Light Leather", order = 1, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 2319, name = "Medium Leather", order = 2, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 4234, name = "Heavy Leather", order = 3, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 4304, name = "Thick Leather", order = 4, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 8170, name = "Rugged Leather", order = 5, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 15417, name = "Devilsaur Leather", order = 6, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 15419, name = "Warbear Leather", order = 7, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, { id = 15422, name = "Frostsaber Leather", order = 8, era = true, season = true, expansion = "Classic", category = "Leather" }, { id = 15423, name = "Chimera Leather", order = 9, era = true, season = true, expansion = "Classic", category = "Leather" }, { id = 17012, name = "Core Leather", order = 10, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 19767, name = "Primal Bat Leather", order = 11, retail = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 19768, name = "Primal Tiger Leather", order = 12, retail = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = -1, name = "Hide", order = 13, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 783, name = "Light Hide", order = 14, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 4232, name = "Medium Hide", order = 15, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 4235, name = "Heavy Hide", order = 16, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 8169, name = "Thick Hide", order = 17, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 8171, name = "Rugged Hide", order = 18, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 19767, name = "Primal Bat Leather", order = 11, retail = true, cata = true, wrath = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 19768, name = "Primal Tiger Leather", order = 12, retail = true, cata = true, wrath = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = -1, name = "Hide", order = 13, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 783, name = "Light Hide", order = 14, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 4232, name = "Medium Hide", order = 15, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 4235, name = "Heavy Hide", order = 16, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 8169, name = "Thick Hide", order = 17, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 8171, name = "Rugged Hide", order = 18, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, { id = 7428, name = "Shadowcat Hide", order = 19, era = true, season = true, expansion = "Classic", category = "Leather" }, { id = 8368, name = "Thick Wolfhide", order = 20, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = -1, name = "Scales", order = 21, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 6470, name = "Deviate Scale", order = 22, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 6471, name = "Perfect Deviate Scale", order = 23, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 8165, name = "Worn Dragonscale", order = 24, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 15412, name = "Green Dragonscale", order = 25, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 15414, name = "Red Dragonscale", order = 26, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = -1, name = "Scales", order = 21, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 6470, name = "Deviate Scale", order = 22, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 6471, name = "Perfect Deviate Scale", order = 23, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 8165, name = "Worn Dragonscale", order = 24, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 15412, name = "Green Dragonscale", order = 25, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 15414, name = "Red Dragonscale", order = 26, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, { id = 15415, name = "Blue Dragonscale", order = 27, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 15416, name = "Black Dragonscale", order = 28, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 7286, name = "Black Whelp Scale", order = 29, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 15416, name = "Black Dragonscale", order = 28, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 7286, name = "Black Whelp Scale", order = 29, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, { id = 7287, name = "Red Whelp Scale", order = 30, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 7392, name = "Green Whelp Scale", order = 31, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 8167, name = "Turtle Scale", order = 32, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 8154, name = "Scorpid Scale", order = 33, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 15408, name = "Heavy Scorpid Scale", order = 34, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 15410, name = "Scale of Onyxia", order = 35, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 20381, name = "Dreamscale", order = 36, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 7392, name = "Green Whelp Scale", order = 31, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 8167, name = "Turtle Scale", order = 32, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 8154, name = "Scorpid Scale", order = 33, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 15408, name = "Heavy Scorpid Scale", order = 34, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 15410, name = "Scale of Onyxia", order = 35, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 20381, name = "Dreamscale", order = 36, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, { id = 20500, name = "Light Silithid Carapace", order = 37, era = true, season = true, expansion = "Classic", category = "Leather" }, { id = 20501, name = "Heavy Silithid Carapace", order = 38, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = -1, name = "Other", order = 39, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 8973, name = "Thick Yeti Hide", order = 40, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 17057, name = "Shiny Fish Scales", order = 41, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = -1, name = "Other", order = 39, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 8973, name = "Thick Yeti Hide", order = 40, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 17057, name = "Shiny Fish Scales", order = 41, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, { id = 11512, name = "Patch of Tainted Skin", order = 42, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 18947, name = "Rage Scar Yeti Hide", order = 43, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Leather" }, + { id = 18947, name = "Rage Scar Yeti Hide", order = 43, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Leather" }, { id = 20498, name = "Silithid Chitin", order = 44, era = true, season = true, expansion = "Classic", category = "Leather" }, - { id = 3173, name = "Bear Meat", order = 1, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 3730, name = "Big Bear Meat", order = 2, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 3173, name = "Bear Meat", order = 1, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 3730, name = "Big Bear Meat", order = 2, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, { id = 3172, name = "Boar Intestines", order = 3, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 2677, name = "Boar Ribs", order = 4, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 3404, name = "Buzzard Wing", order = 5, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 21024, name = "Chimaerok Tenderloin", order = 6, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 769, name = "Chunk of Boar Meat", order = 7, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 5503, name = "Clam Meat", order = 8, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 2673, name = "Coyote Meat", order = 9, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 2886, name = "Crag Boar Rib", order = 10, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 2675, name = "Crawler Claw", order = 11, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 2674, name = "Crawler Meat", order = 12, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 2924, name = "Crocolisk Meat", order = 13, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 12207, name = "Giant Egg", order = 14, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 2251, name = "Gooey Spider Leg", order = 15, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 723, name = "Goretusk Liver", order = 16, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 2677, name = "Boar Ribs", order = 4, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 3404, name = "Buzzard Wing", order = 5, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 21024, name = "Chimaerok Tenderloin", order = 6, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 769, name = "Chunk of Boar Meat", order = 7, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 5503, name = "Clam Meat", order = 8, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 2673, name = "Coyote Meat", order = 9, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 2886, name = "Crag Boar Rib", order = 10, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 2675, name = "Crawler Claw", order = 11, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 2674, name = "Crawler Meat", order = 12, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 2924, name = "Crocolisk Meat", order = 13, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 12207, name = "Giant Egg", order = 14, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 2251, name = "Gooey Spider Leg", order = 15, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 723, name = "Goretusk Liver", order = 16, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, { id = 731, name = "Goretusk Snout", order = 17, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 12204, name = "Heavy Kodo Meat", order = 18, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 5467, name = "Kodo Meat", order = 19, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 1015, name = "Lean Wolf Flank", order = 20, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 3731, name = "Lion Meat", order = 21, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 12223, name = "Meaty Bat Wing", order = 22, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 12204, name = "Heavy Kodo Meat", order = 18, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 5467, name = "Kodo Meat", order = 19, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 1015, name = "Lean Wolf Flank", order = 20, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 3731, name = "Lion Meat", order = 21, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 12223, name = "Meaty Bat Wing", order = 22, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, { id = 730, name = "Murloc Eye", order = 23, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 1468, name = "Murloc Fin", order = 24, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 12037, name = "Mystery Meat", order = 25, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 3685, name = "Raptor Egg", order = 26, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 12184, name = "Raptor Flesh", order = 27, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 12203, name = "Red Wolf Meat", order = 28, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 20424, name = "Sandworm Meat", order = 29, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 5466, name = "Scorpid Stinger", order = 30, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 6889, name = "Small Egg", order = 31, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 5465, name = "Small Spider Leg", order = 32, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 5468, name = "Soft Frenzy Flesh", order = 33, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 1468, name = "Murloc Fin", order = 24, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 12037, name = "Mystery Meat", order = 25, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 3685, name = "Raptor Egg", order = 26, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 12184, name = "Raptor Flesh", order = 27, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 12203, name = "Red Wolf Meat", order = 28, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 20424, name = "Sandworm Meat", order = 29, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 5466, name = "Scorpid Stinger", order = 30, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 6889, name = "Small Egg", order = 31, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 5465, name = "Small Spider Leg", order = 32, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 5468, name = "Soft Frenzy Flesh", order = 33, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, { id = 3174, name = "Spider Ichor", order = 34, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 5471, name = "Stag Meat", order = 35, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 5469, name = "Strider Meat", order = 36, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 5471, name = "Stag Meat", order = 35, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 5469, name = "Strider Meat", order = 36, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, { id = 729, name = "Stringy Vulture Meat", order = 37, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 2672, name = "Stringy Wolf Meat", order = 38, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 5504, name = "Tangy Clam Meat", order = 39, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 12206, name = "Tender Crab Meat", order = 40, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 3667, name = "Tender Crocolisk Meat", order = 41, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 12208, name = "Tender Wolf Meat", order = 42, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 5470, name = "Thunder Lizard Tail", order = 43, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 12202, name = "Tiger Meat", order = 44, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 1080, name = "Tough Condor Meat", order = 45, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 3712, name = "Turtle Meat", order = 46, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 12205, name = "White Spider Meat", order = 47, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 7974, name = "Zesty Clam Meat", order = 48, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Meat" }, - { id = 6303, name = "Raw Slitherskin Mackerel", order = 1, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Fish" }, - { id = 6291, name = "Raw Brilliant Smallfish", order = 2, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Fish" }, - { id = 6289, name = "Raw Longjaw Mud Snapper", order = 3, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Fish" }, - { id = 6361, name = "Raw Rainbow Fin Albacore", order = 4, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Fish" }, - { id = 6317, name = "Raw Loch Frenzy", order = 5, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Fish" }, - { id = 21071, name = "Raw Sagefish", order = 6, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Fish" }, - { id = 6308, name = "Raw Bristle Whisker Catfish", order = 7, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Fish" }, - { id = 8365, name = "Raw Mithril Head Trout", order = 8, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Fish" }, - { id = 6362, name = "Raw Rockscale Cod", order = 9, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Fish" }, - { id = 21153, name = "Raw Greater Sagefish", order = 10, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Fish" }, - { id = 13759, name = "Raw Nightfin Snapper", order = 11, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Fish" }, - { id = 4603, name = "Raw Spotted Yellowtail", order = 12, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Fish" }, - { id = 13754, name = "Raw Glossy Mightfish", order = 13, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Fish" }, - { id = 13888, name = "Darkclaw Lobster", order = 14, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Fish" }, - { id = 13760, name = "Raw Sunscale Salmon", order = 15, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Fish" }, - { id = 13758, name = "Raw Redgill", order = 16, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Fish" }, - { id = 13756, name = "Raw Summer Bass", order = 17, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Fish" }, - { id = 13889, name = "Raw Whitescale Salmon", order = 18, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Fish" }, - { id = 6522, name = "Deviate Fish", order = 19, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Fish" }, + { id = 2672, name = "Stringy Wolf Meat", order = 38, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 5504, name = "Tangy Clam Meat", order = 39, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 12206, name = "Tender Crab Meat", order = 40, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 3667, name = "Tender Crocolisk Meat", order = 41, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 12208, name = "Tender Wolf Meat", order = 42, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 5470, name = "Thunder Lizard Tail", order = 43, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 12202, name = "Tiger Meat", order = 44, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 1080, name = "Tough Condor Meat", order = 45, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 3712, name = "Turtle Meat", order = 46, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 12205, name = "White Spider Meat", order = 47, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 7974, name = "Zesty Clam Meat", order = 48, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Meat" }, + { id = 6303, name = "Raw Slitherskin Mackerel", order = 1, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Fish" }, + { id = 6291, name = "Raw Brilliant Smallfish", order = 2, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Fish" }, + { id = 6289, name = "Raw Longjaw Mud Snapper", order = 3, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Fish" }, + { id = 6361, name = "Raw Rainbow Fin Albacore", order = 4, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Fish" }, + { id = 6317, name = "Raw Loch Frenzy", order = 5, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Fish" }, + { id = 21071, name = "Raw Sagefish", order = 6, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Fish" }, + { id = 6308, name = "Raw Bristle Whisker Catfish", order = 7, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Fish" }, + { id = 8365, name = "Raw Mithril Head Trout", order = 8, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Fish" }, + { id = 6362, name = "Raw Rockscale Cod", order = 9, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Fish" }, + { id = 21153, name = "Raw Greater Sagefish", order = 10, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Fish" }, + { id = 13759, name = "Raw Nightfin Snapper", order = 11, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Fish" }, + { id = 4603, name = "Raw Spotted Yellowtail", order = 12, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Fish" }, + { id = 13754, name = "Raw Glossy Mightfish", order = 13, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Fish" }, + { id = 13888, name = "Darkclaw Lobster", order = 14, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Fish" }, + { id = 13760, name = "Raw Sunscale Salmon", order = 15, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Fish" }, + { id = 13758, name = "Raw Redgill", order = 16, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Fish" }, + { id = 13756, name = "Raw Summer Bass", order = 17, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Fish" }, + { id = 13889, name = "Raw Whitescale Salmon", order = 18, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Fish" }, + { id = 6522, name = "Deviate Fish", order = 19, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Fish" }, { id = 124669, name = "Darkmoon Daggermaw", order = 20, retail = true, expansion = "Classic", category = "Fish" }, - { id = 7081, name = "Breath of Wind", order = 1, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, - { id = 7075, name = "Core of Earth", order = 2, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, - { id = 7069, name = "Elemental Air", order = 3, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, - { id = 7067, name = "Elemental Earth", order = 4, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, - { id = 7068, name = "Elemental Fire", order = 5, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, - { id = 7070, name = "Elemental Water", order = 6, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, - { id = 7082, name = "Essence of Air", order = 7, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, - { id = 7076, name = "Essence of Earth", order = 8, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, - { id = 7078, name = "Essence of Fire", order = 9, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, - { id = 12808, name = "Essence of Undeath", order = 10, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, - { id = 7080, name = "Essence of Water", order = 11, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, - { id = 7079, name = "Globe of Water", order = 12, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, - { id = 7077, name = "Heart of Fire", order = 13, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, - { id = 10286, name = "Heart of The Wild", order = 14, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, - { id = 7972, name = "Ichor of Undeath", order = 15, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, - { id = 12803, name = "Living Essence", order = 16, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, - { id = 774, name = "Malachite", order = 1, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Gem" }, - { id = 818, name = "Tigerseye", order = 2, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Gem" }, - { id = 1206, name = "Moss Agate", order = 3, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Gem" }, - { id = 1210, name = "Shadowgem", order = 4, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Gem" }, - { id = 1529, name = "Jade", order = 5, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Gem" }, - { id = 1705, name = "Lesser Moonstone", order = 6, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Gem" }, - { id = 3864, name = "Citrine", order = 7, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Gem" }, - { id = 7910, name = "Star Ruby", order = 8, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Gem" }, - { id = 7909, name = "Aquamarine", order = 9, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Gem" }, - { id = 12799, name = "Large Opal", order = 10, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Gem" }, - { id = 12361, name = "Blue Sapphire", order = 11, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Gem" }, - { id = 12364, name = "Huge Emerald", order = 12, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Gem" }, - { id = 12363, name = "Arcane Crystal", order = 13, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Gem" }, - { id = 12800, name = "Azerothian Diamond", order = 14, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Gem" }, - { id = 11754, name = "Black Diamond", order = 15, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Gem" }, - { id = 18335, name = "Pristine Black Diamond", order = 16, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Gem" }, + { id = 7081, name = "Breath of Wind", order = 1, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, + { id = 7075, name = "Core of Earth", order = 2, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, + { id = 7069, name = "Elemental Air", order = 3, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, + { id = 7067, name = "Elemental Earth", order = 4, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, + { id = 7068, name = "Elemental Fire", order = 5, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, + { id = 7070, name = "Elemental Water", order = 6, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, + { id = 7082, name = "Essence of Air", order = 7, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, + { id = 7076, name = "Essence of Earth", order = 8, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, + { id = 7078, name = "Essence of Fire", order = 9, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, + { id = 12808, name = "Essence of Undeath", order = 10, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, + { id = 7080, name = "Essence of Water", order = 11, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, + { id = 7079, name = "Globe of Water", order = 12, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, + { id = 7077, name = "Heart of Fire", order = 13, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, + { id = 10286, name = "Heart of The Wild", order = 14, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, + { id = 7972, name = "Ichor of Undeath", order = 15, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, + { id = 12803, name = "Living Essence", order = 16, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Elemental" }, + { id = 774, name = "Malachite", order = 1, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Gem" }, + { id = 818, name = "Tigerseye", order = 2, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Gem" }, + { id = 1206, name = "Moss Agate", order = 3, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Gem" }, + { id = 1210, name = "Shadowgem", order = 4, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Gem" }, + { id = 1529, name = "Jade", order = 5, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Gem" }, + { id = 1705, name = "Lesser Moonstone", order = 6, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Gem" }, + { id = 3864, name = "Citrine", order = 7, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Gem" }, + { id = 7910, name = "Star Ruby", order = 8, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Gem" }, + { id = 7909, name = "Aquamarine", order = 9, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Gem" }, + { id = 12799, name = "Large Opal", order = 10, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Gem" }, + { id = 12361, name = "Blue Sapphire", order = 11, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Gem" }, + { id = 12364, name = "Huge Emerald", order = 12, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Gem" }, + { id = 12363, name = "Arcane Crystal", order = 13, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Gem" }, + { id = 12800, name = "Azerothian Diamond", order = 14, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Gem" }, + { id = 11754, name = "Black Diamond", order = 15, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Gem" }, + { id = 18335, name = "Pristine Black Diamond", order = 16, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Gem" }, { id = 19774, name = "Souldarite", order = 17, era = true, season = true, expansion = "Classic", category = "Gem" }, - { id = 10940, name = "Strange Dust", order = 1, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 11083, name = "Soul Dust", order = 2, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 11137, name = "Vision Dust", order = 3, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 11176, name = "Dream Dust", order = 4, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 16204, name = "Illusion Dust", order = 5, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 10940, name = "Strange Dust", order = 1, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 11083, name = "Soul Dust", order = 2, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 11137, name = "Vision Dust", order = 3, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 11176, name = "Dream Dust", order = 4, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 16204, name = "Illusion Dust", order = 5, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, { id = 16204, name = "Light Illusion Dust", order = 6, retail = true, expansion = "Classic", category = "Enchanting" }, { id = 156930, name = "Rich Illusion Dust", order = 7, retail = true, expansion = "Classic", category = "Enchanting" }, - { id = 10938, name = "Lesser Magic Essence", order = 8, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 10939, name = "Greater Magic Essence", order = 9, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 10998, name = "Lesser Astral Essence", order = 10, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 11082, name = "Greater Astral Essence", order = 11, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 11134, name = "Lesser Mystic Essence", order = 12, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 11135, name = "Greater Mystic Essence", order = 13, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 11174, name = "Lesser Nether Essence", order = 14, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 11175, name = "Greater Nether Essence", order = 15, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 16202, name = "Lesser Eternal Essence", order = 16, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 16203, name = "Greater Eternal Essence", order = 17, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 10978, name = "Small Glimmering Shard", order = 18, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 11084, name = "Large Glimmering Shard", order = 19, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 11138, name = "Small Glowing Shard", order = 20, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 11139, name = "Large Glowing Shard", order = 21, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 11177, name = "Small Radiant Shard", order = 22, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 11178, name = "Large Radiant Shard", order = 23, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 14343, name = "Small Brilliant Shard", order = 24, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 14344, name = "Large Brilliant Shard", order = 25, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 20725, name = "Nexus Crystal", order = 26, classic = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, - { id = 39151, name = "Alabaster Pigment", order = 1, retail = true, classic = true, expansion = "Classic", category = "Pigment" }, - { id = 39334, name = "Dusky Pigment", order = 2, retail = true, classic = true, expansion = "Classic", category = "Pigment" }, - { id = 43103, name = "Verdant Pigment", order = 3, retail = true, classic = true, expansion = "Classic", category = "Pigment" }, - { id = 39338, name = "Golden Pigment", order = 4, retail = true, classic = true, expansion = "Classic", category = "Pigment" }, - { id = 39339, name = "Emerald Pigment", order = 5, retail = true, classic = true, expansion = "Classic", category = "Pigment" }, - { id = 39340, name = "Violet Pigment", order = 6, retail = true, classic = true, expansion = "Classic", category = "Pigment" }, - { id = 39341, name = "Silvery Pigment", order = 7, retail = true, classic = true, expansion = "Classic", category = "Pigment" }, - { id = -1, name = "Uncommon Pigment", order = 8, retail = true, classic = true, expansion = "Classic", category = "Pigment" }, - { id = 43104, name = "Burnt Pigment", order = 9, retail = true, classic = true, expansion = "Classic", category = "Pigment" }, - { id = 43105, name = "Indigo Pigment", order = 10, retail = true, classic = true, expansion = "Classic", category = "Pigment" }, - { id = 43106, name = "Ruby Pigment", order = 11, retail = true, classic = true, expansion = "Classic", category = "Pigment" }, - { id = 43107, name = "Sapphire Pigment", order = 12, retail = true, classic = true, expansion = "Classic", category = "Pigment" }, - { id = 5498, name = "Small Lustrous Pearl", order = 1, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Other" }, - { id = 7971, name = "Black Pearl", order = 2, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Other" }, - { id = 9262, name = "Black Vitriol", order = 7, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Other" }, + { id = 10938, name = "Lesser Magic Essence", order = 8, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 10939, name = "Greater Magic Essence", order = 9, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 10998, name = "Lesser Astral Essence", order = 10, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 11082, name = "Greater Astral Essence", order = 11, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 11134, name = "Lesser Mystic Essence", order = 12, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 11135, name = "Greater Mystic Essence", order = 13, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 11174, name = "Lesser Nether Essence", order = 14, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 11175, name = "Greater Nether Essence", order = 15, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 16202, name = "Lesser Eternal Essence", order = 16, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 16203, name = "Greater Eternal Essence", order = 17, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 10978, name = "Small Glimmering Shard", order = 18, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 11084, name = "Large Glimmering Shard", order = 19, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 11138, name = "Small Glowing Shard", order = 20, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 11139, name = "Large Glowing Shard", order = 21, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 11177, name = "Small Radiant Shard", order = 22, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 11178, name = "Large Radiant Shard", order = 23, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 14343, name = "Small Brilliant Shard", order = 24, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 14344, name = "Large Brilliant Shard", order = 25, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 20725, name = "Nexus Crystal", order = 26, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Enchanting" }, + { id = 39151, name = "Alabaster Pigment", order = 1, retail = true, cata = true, wrath = true, bc = true, expansion = "Classic", category = "Pigment" }, + { id = 39334, name = "Dusky Pigment", order = 2, retail = true, cata = true, wrath = true, bc = true, expansion = "Classic", category = "Pigment" }, + { id = 43103, name = "Verdant Pigment", order = 3, retail = true, cata = true, wrath = true, bc = true, expansion = "Classic", category = "Pigment" }, + { id = 39338, name = "Golden Pigment", order = 4, retail = true, cata = true, wrath = true, bc = true, expansion = "Classic", category = "Pigment" }, + { id = 39339, name = "Emerald Pigment", order = 5, retail = true, cata = true, wrath = true, bc = true, expansion = "Classic", category = "Pigment" }, + { id = 39340, name = "Violet Pigment", order = 6, retail = true, cata = true, wrath = true, bc = true, expansion = "Classic", category = "Pigment" }, + { id = 39341, name = "Silvery Pigment", order = 7, retail = true, cata = true, wrath = true, bc = true, expansion = "Classic", category = "Pigment" }, + { id = -1, name = "Uncommon Pigment", order = 8, retail = true, cata = true, wrath = true, bc = true, expansion = "Classic", category = "Pigment" }, + { id = 43104, name = "Burnt Pigment", order = 9, retail = true, cata = true, wrath = true, bc = true, expansion = "Classic", category = "Pigment" }, + { id = 43105, name = "Indigo Pigment", order = 10, retail = true, cata = true, wrath = true, bc = true, expansion = "Classic", category = "Pigment" }, + { id = 43106, name = "Ruby Pigment", order = 11, retail = true, cata = true, wrath = true, bc = true, expansion = "Classic", category = "Pigment" }, + { id = 43107, name = "Sapphire Pigment", order = 12, retail = true, cata = true, wrath = true, bc = true, expansion = "Classic", category = "Pigment" }, + { id = 5498, name = "Small Lustrous Pearl", order = 1, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Other" }, + { id = 7971, name = "Black Pearl", order = 2, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Other" }, + { id = 9262, name = "Black Vitriol", order = 7, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Other" }, { id = 7191, name = "Fused Wiring", order = 8, era = true, season = true, expansion = "Classic", category = "Other" }, - { id = 5637, name = "Large Fang", order = 10, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Other" }, - { id = 5635, name = "Sharp Claw", order = 11, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Other" }, - { id = 4402, name = "Small Flame Sac", order = 9, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Other" }, - { id = 1475, name = "Small Venom Sac", order = 12, classic = true, era = true, season = true, expansion = "Classic", category = "Other" }, - { id = 1288, name = "Large Venom Sac", order = 13, classic = true, era = true, season = true, expansion = "Classic", category = "Other" }, - { id = 19441, name = "Huge Venom Sac", order = 14, classic = true, era = true, season = true, expansion = "Classic", category = "Other" }, - { id = 12804, name = "Powerful Mojo", order = 3, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Other" }, - { id = 13926, name = "Golden Pearl", order = 4, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Other" }, - { id = 12811, name = "Righteous Orb", order = 5, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Other" }, - { id = 12809, name = "Guardian Stone", order = 6, retail = true, classic = true, era = true, season = true, expansion = "Classic", category = "Other" }, + { id = 5637, name = "Large Fang", order = 10, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Other" }, + { id = 5635, name = "Sharp Claw", order = 11, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Other" }, + { id = 4402, name = "Small Flame Sac", order = 9, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Other" }, + { id = 1475, name = "Small Venom Sac", order = 12, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Other" }, + { id = 1288, name = "Large Venom Sac", order = 13, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Other" }, + { id = 19441, name = "Huge Venom Sac", order = 14, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Other" }, + { id = 12804, name = "Powerful Mojo", order = 3, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Other" }, + { id = 13926, name = "Golden Pearl", order = 4, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Other" }, + { id = 12811, name = "Righteous Orb", order = 5, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Other" }, + { id = 12809, name = "Guardian Stone", order = 6, retail = true, cata = true, wrath = true, bc = true, era = true, season = true, expansion = "Classic", category = "Other" }, -- BC - { id = 22710, name = "Bloodthistle", order = 1, retail = true, classic = true, expansion = "BC", category = "Herb" }, - { id = 22785, name = "Felweed", order = 2, retail = true, classic = true, expansion = "BC", category = "Herb" }, - { id = 22786, name = "Dreaming Glory", order = 3, retail = true, classic = true, expansion = "BC", category = "Herb" }, - { id = 22787, name = "Ragveil", order = 4, retail = true, classic = true, expansion = "BC", category = "Herb" }, - { id = 22788, name = "Flame Cap", order = 5, retail = true, classic = true, expansion = "BC", category = "Herb" }, - { id = 22789, name = "Terocone", order = 6, retail = true, classic = true, expansion = "BC", category = "Herb" }, - { id = 22790, name = "Ancient Lichen", order = 7, retail = true, classic = true, expansion = "BC", category = "Herb" }, - { id = 22791, name = "Netherbloom", order = 8, retail = true, classic = true, expansion = "BC", category = "Herb" }, - { id = 22792, name = "Nightmare Vine", order = 9, retail = true, classic = true, expansion = "BC", category = "Herb" }, - { id = 22793, name = "Mana Thistle", order = 10, retail = true, classic = true, expansion = "BC", category = "Herb" }, - { id = 22794, name = "Fel Lotus", order = 11, retail = true, classic = true, expansion = "BC", category = "Herb" }, - { id = 23425, name = "Adamantite Ore", order = 1, retail = true, classic = true, expansion = "BC", category = "Ore" }, - { id = 23427, name = "Eternium Ore", order = 2, retail = true, classic = true, expansion = "BC", category = "Ore" }, - { id = 23424, name = "Fel Iron Ore", order = 2, retail = true, classic = true, expansion = "BC", category = "Ore" }, - { id = 23426, name = "Khorium Ore", order = 4, retail = true, classic = true, expansion = "BC", category = "Ore" }, - { id = 21877, name = "Netherweave Cloth", order = 1, retail = true, classic = true, expansion = "BC", category = "Cloth" }, - { id = 21881, name = "Netherweb Spider Silk", order = 2, retail = true, classic = true, expansion = "BC", category = "Cloth" }, - { id = 21887, name = "Knothide Leather", order = 1, retail = true, classic = true, expansion = "BC", category = "Leather" }, - { id = 25699, name = "Crystal Infused Leather", order = 2, retail = true, classic = true, expansion = "BC", category = "Leather" }, - { id = 25707, name = "Fel Hide", order = 3, retail = true, classic = true, expansion = "BC", category = "Leather" }, - { id = -1, name = "Scales", order = 4, retail = true, classic = true, expansion = "BC", category = "Leather" }, - { id = 29539, name = "Cobra Scales", order = 5, retail = true, classic = true, expansion = "BC", category = "Leather" }, - { id = 25700, name = "Fel Scales", order = 6, retail = true, classic = true, expansion = "BC", category = "Leather" }, - { id = 29547, name = "Wind Scales", order = 7, retail = true, classic = true, expansion = "BC", category = "Leather" }, - { id = 29548, name = "Nether Dragonscales", order = 8, retail = true, classic = true, expansion = "BC", category = "Leather" }, - { id = 27669, name = "Bat Flesh", order = 1, retail = true, classic = true, expansion = "BC", category = "Meat" }, - { id = 35562, name = "Bear Flank", order = 2, retail = true, classic = true, expansion = "BC", category = "Meat" }, - { id = 27671, name = "Buzzard Meat", order = 3, retail = true, classic = true, expansion = "BC", category = "Meat" }, - { id = 27677, name = "Chunk O Basilisk", order = 4, retail = true, classic = true, expansion = "BC", category = "Meat" }, - { id = 27678, name = "Clefthoof Meat", order = 5, retail = true, classic = true, expansion = "BC", category = "Meat" }, - { id = 22644, name = "Crunchy Spider Leg", order = 6, retail = true, classic = true, expansion = "BC", category = "Meat" }, - { id = 24477, name = "Jaggal Clam Meat", order = 7, retail = true, classic = true, expansion = "BC", category = "Meat" }, - { id = 27668, name = "Lynx Meat", order = 8, retail = true, classic = true, expansion = "BC", category = "Meat" }, - { id = 23676, name = "Moongraze Stag Tenderloin", order = 9, retail = true, classic = true, expansion = "BC", category = "Meat" }, - { id = 31670, name = "Raptor Ribs", order = 10, retail = true, classic = true, expansion = "BC", category = "Meat" }, - { id = 27674, name = "Ravager Flesh", order = 11, retail = true, classic = true, expansion = "BC", category = "Meat" }, - { id = 31671, name = "Serpent Flesh", order = 12, retail = true, classic = true, expansion = "BC", category = "Meat" }, - { id = 27682, name = "Talbuk Venison", order = 13, retail = true, classic = true, expansion = "BC", category = "Meat" }, - { id = 27681, name = "Warped Flesh", order = 14, retail = true, classic = true, expansion = "BC", category = "Meat" }, - { id = 27422, name = "Barbed Gill Trout", order = 1, retail = true, classic = true, expansion = "BC", category = "Fish" }, - { id = 33823, name = "Bloodfin Catfish", order = 2, retail = true, classic = true, expansion = "BC", category = "Fish" }, - { id = 33824, name = "Crescent Tail Skullfish", order = 3, retail = true, classic = true, expansion = "BC", category = "Fish" }, - { id = 27435, name = "Figlusters Mudfish", order = 4, retail = true, classic = true, expansion = "BC", category = "Fish" }, - { id = 27439, name = "Furious Crawdad", order = 5, retail = true, classic = true, expansion = "BC", category = "Fish" }, - { id = 35285, name = "Giant Sunfish", order = 6, retail = true, classic = true, expansion = "BC", category = "Fish" }, - { id = 27438, name = "Golden Darter", order = 7, retail = true, classic = true, expansion = "BC", category = "Fish" }, - { id = 27437, name = "Icefin Bluefish", order = 8, retail = true, classic = true, expansion = "BC", category = "Fish" }, - { id = 27425, name = "Spotted Feltail", order = 9, retail = true, classic = true, expansion = "BC", category = "Fish" }, - { id = 27429, name = "Zangarian Spore Fish", order = 10, retail = true, classic = true, expansion = "BC", category = "Fish" }, - { id = 22572, name = "Mote of Air", order = 1, retail = true, classic = true, expansion = "BC", category = "Elemental" }, - { id = 22573, name = "Mote of Earth", order = 2, retail = true, classic = true, expansion = "BC", category = "Elemental" }, - { id = 22574, name = "Mote of Fire", order = 3, retail = true, classic = true, expansion = "BC", category = "Elemental" }, - { id = 22575, name = "Mote of Life", order = 4, retail = true, classic = true, expansion = "BC", category = "Elemental" }, - { id = 22576, name = "Mote of Mana", order = 5, retail = true, classic = true, expansion = "BC", category = "Elemental" }, - { id = 22577, name = "Mote of Shadow", order = 6, retail = true, classic = true, expansion = "BC", category = "Elemental" }, - { id = 22578, name = "Mote of Water", order = 7, retail = true, classic = true, expansion = "BC", category = "Elemental" }, - { id = 22451, name = "Primal Air", order = 8, retail = true, classic = true, expansion = "BC", category = "Elemental" }, - { id = 22452, name = "Primal Earth", order = 9, retail = true, classic = true, expansion = "BC", category = "Elemental" }, - { id = 21884, name = "Primal Fire", order = 10, retail = true, classic = true, expansion = "BC", category = "Elemental" }, - { id = 21886, name = "Primal Life", order = 11, retail = true, classic = true, expansion = "BC", category = "Elemental" }, - { id = 22457, name = "Primal Mana", order = 12, retail = true, classic = true, expansion = "BC", category = "Elemental" }, - { id = 22456, name = "Primal Shadow", order = 13, retail = true, classic = true, expansion = "BC", category = "Elemental" }, - { id = 21885, name = "Primal Water", order = 14, retail = true, classic = true, expansion = "BC", category = "Elemental" }, - { id = -1, name = "Other", order = 15, retail = true, classic = true, expansion = "BC", category = "Elemental" }, - { id = 23572, name = "Primal Nether", order = 16, retail = true, classic = true, expansion = "BC", category = "Elemental" }, - { id = 32428, name = "Heart of Darkness", order = 17, retail = true, classic = true, expansion = "BC", category = "Elemental" }, - { id = 34664, name = "Sunmote", order = 18, retail = true, classic = true, expansion = "BC", category = "Elemental" }, - { id = 23077, name = "Blood Garnet", order = 1, retail = true, classic = true, expansion = "BC", category = "Gem" }, - { id = 21929, name = "Flame Spessarite", order = 2, retail = true, classic = true, expansion = "BC", category = "Gem" }, - { id = 23112, name = "Golden Draenite", order = 3, retail = true, classic = true, expansion = "BC", category = "Gem" }, - { id = 23079, name = "Deep Peridot", order = 4, retail = true, classic = true, expansion = "BC", category = "Gem" }, - { id = 23117, name = "Azure Moonstone", order = 5, retail = true, classic = true, expansion = "BC", category = "Gem" }, - { id = 23107, name = "Shadow Draenite", order = 6, retail = true, classic = true, expansion = "BC", category = "Gem" }, - { id = -1, name = "Rare Gems", order = 7, retail = true, classic = true, expansion = "BC", category = "Gem" }, - { id = 23436, name = "Living Ruby", order = 8, retail = true, classic = true, expansion = "BC", category = "Gem" }, - { id = 23439, name = "Noble Topaz", order = 9, retail = true, classic = true, expansion = "BC", category = "Gem" }, - { id = 23440, name = "Dawnstone", order = 10, retail = true, classic = true, expansion = "BC", category = "Gem" }, - { id = 23437, name = "Talasite", order = 11, retail = true, classic = true, expansion = "BC", category = "Gem" }, - { id = 23438, name = "Star of Elune", order = 12, retail = true, classic = true, expansion = "BC", category = "Gem" }, - { id = 23441, name = "Nightseye", order = 13, retail = true, classic = true, expansion = "BC", category = "Gem" }, - { id = -1, name = "Epic Gems", order = 14, retail = true, classic = true, expansion = "BC", category = "Gem" }, - { id = 32227, name = "Crimson Spinel", order = 15, retail = true, classic = true, expansion = "BC", category = "Gem" }, - { id = 32231, name = "Pyrestone", order = 16, retail = true, classic = true, expansion = "BC", category = "Gem" }, - { id = 32229, name = "Lionseye", order = 17, retail = true, classic = true, expansion = "BC", category = "Gem" }, - { id = 32249, name = "Seaspray Emerald", order = 18, retail = true, classic = true, expansion = "BC", category = "Gem" }, - { id = 32228, name = "Empyrean Sapphire", order = 19, retail = true, classic = true, expansion = "BC", category = "Gem" }, - { id = 32230, name = "Shadowsong Amethyst", order = 20, retail = true, classic = true, expansion = "BC", category = "Gem" }, - { id = 22445, name = "Arcane Dust", order = 1, retail = true, classic = true, expansion = "BC", category = "Enchanting" }, - { id = 22447, name = "Lesser Planar Essence", order = 2, retail = true, classic = true, expansion = "BC", category = "Enchanting" }, - { id = 22446, name = "Greater Planar Essence", order = 3, retail = true, classic = true, expansion = "BC", category = "Enchanting" }, - { id = 22448, name = "Small Prismatic Shard", order = 4, retail = true, classic = true, expansion = "BC", category = "Enchanting" }, - { id = 22449, name = "Large Prismatic Shard", order = 5, retail = true, classic = true, expansion = "BC", category = "Enchanting" }, - { id = 22450, name = "Void Crystal", order = 6, retail = true, classic = true, expansion = "BC", category = "Enchanting" }, - { id = 39342, name = "Nether Pigment", order = 1, retail = true, classic = true, expansion = "BC", category = "Pigment" }, - { id = 43108, name = "Ebon Pigment", order = 2, retail = true, classic = true, expansion = "BC", category = "Pigment" }, + { id = 22710, name = "Bloodthistle", order = 1, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Herb" }, + { id = 22785, name = "Felweed", order = 2, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Herb" }, + { id = 22786, name = "Dreaming Glory", order = 3, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Herb" }, + { id = 22787, name = "Ragveil", order = 4, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Herb" }, + { id = 22788, name = "Flame Cap", order = 5, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Herb" }, + { id = 22789, name = "Terocone", order = 6, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Herb" }, + { id = 22790, name = "Ancient Lichen", order = 7, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Herb" }, + { id = 22791, name = "Netherbloom", order = 8, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Herb" }, + { id = 22792, name = "Nightmare Vine", order = 9, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Herb" }, + { id = 22793, name = "Mana Thistle", order = 10, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Herb" }, + { id = 22794, name = "Fel Lotus", order = 11, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Herb" }, + { id = 23425, name = "Adamantite Ore", order = 1, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Ore" }, + { id = 23427, name = "Eternium Ore", order = 2, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Ore" }, + { id = 23424, name = "Fel Iron Ore", order = 2, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Ore" }, + { id = 23426, name = "Khorium Ore", order = 4, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Ore" }, + { id = 21877, name = "Netherweave Cloth", order = 1, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Cloth" }, + { id = 21881, name = "Netherweb Spider Silk", order = 2, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Cloth" }, + { id = 21887, name = "Knothide Leather", order = 1, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Leather" }, + { id = 25699, name = "Crystal Infused Leather", order = 2, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Leather" }, + { id = 25707, name = "Fel Hide", order = 3, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Leather" }, + { id = -1, name = "Scales", order = 4, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Leather" }, + { id = 29539, name = "Cobra Scales", order = 5, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Leather" }, + { id = 25700, name = "Fel Scales", order = 6, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Leather" }, + { id = 29547, name = "Wind Scales", order = 7, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Leather" }, + { id = 29548, name = "Nether Dragonscales", order = 8, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Leather" }, + { id = 27669, name = "Bat Flesh", order = 1, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Meat" }, + { id = 35562, name = "Bear Flank", order = 2, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Meat" }, + { id = 27671, name = "Buzzard Meat", order = 3, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Meat" }, + { id = 27677, name = "Chunk O Basilisk", order = 4, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Meat" }, + { id = 27678, name = "Clefthoof Meat", order = 5, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Meat" }, + { id = 22644, name = "Crunchy Spider Leg", order = 6, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Meat" }, + { id = 24477, name = "Jaggal Clam Meat", order = 7, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Meat" }, + { id = 27668, name = "Lynx Meat", order = 8, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Meat" }, + { id = 23676, name = "Moongraze Stag Tenderloin", order = 9, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Meat" }, + { id = 31670, name = "Raptor Ribs", order = 10, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Meat" }, + { id = 27674, name = "Ravager Flesh", order = 11, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Meat" }, + { id = 31671, name = "Serpent Flesh", order = 12, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Meat" }, + { id = 27682, name = "Talbuk Venison", order = 13, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Meat" }, + { id = 27681, name = "Warped Flesh", order = 14, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Meat" }, + { id = 27422, name = "Barbed Gill Trout", order = 1, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Fish" }, + { id = 33823, name = "Bloodfin Catfish", order = 2, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Fish" }, + { id = 33824, name = "Crescent Tail Skullfish", order = 3, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Fish" }, + { id = 27435, name = "Figlusters Mudfish", order = 4, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Fish" }, + { id = 27439, name = "Furious Crawdad", order = 5, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Fish" }, + { id = 35285, name = "Giant Sunfish", order = 6, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Fish" }, + { id = 27438, name = "Golden Darter", order = 7, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Fish" }, + { id = 27437, name = "Icefin Bluefish", order = 8, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Fish" }, + { id = 27425, name = "Spotted Feltail", order = 9, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Fish" }, + { id = 27429, name = "Zangarian Spore Fish", order = 10, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Fish" }, + { id = 22572, name = "Mote of Air", order = 1, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Elemental" }, + { id = 22573, name = "Mote of Earth", order = 2, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Elemental" }, + { id = 22574, name = "Mote of Fire", order = 3, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Elemental" }, + { id = 22575, name = "Mote of Life", order = 4, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Elemental" }, + { id = 22576, name = "Mote of Mana", order = 5, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Elemental" }, + { id = 22577, name = "Mote of Shadow", order = 6, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Elemental" }, + { id = 22578, name = "Mote of Water", order = 7, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Elemental" }, + { id = 22451, name = "Primal Air", order = 8, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Elemental" }, + { id = 22452, name = "Primal Earth", order = 9, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Elemental" }, + { id = 21884, name = "Primal Fire", order = 10, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Elemental" }, + { id = 21886, name = "Primal Life", order = 11, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Elemental" }, + { id = 22457, name = "Primal Mana", order = 12, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Elemental" }, + { id = 22456, name = "Primal Shadow", order = 13, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Elemental" }, + { id = 21885, name = "Primal Water", order = 14, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Elemental" }, + { id = -1, name = "Other", order = 15, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Elemental" }, + { id = 23572, name = "Primal Nether", order = 16, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Elemental" }, + { id = 32428, name = "Heart of Darkness", order = 17, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Elemental" }, + { id = 34664, name = "Sunmote", order = 18, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Elemental" }, + { id = 23077, name = "Blood Garnet", order = 1, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Gem" }, + { id = 21929, name = "Flame Spessarite", order = 2, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Gem" }, + { id = 23112, name = "Golden Draenite", order = 3, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Gem" }, + { id = 23079, name = "Deep Peridot", order = 4, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Gem" }, + { id = 23117, name = "Azure Moonstone", order = 5, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Gem" }, + { id = 23107, name = "Shadow Draenite", order = 6, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Gem" }, + { id = -1, name = "Rare Gems", order = 7, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Gem" }, + { id = 23436, name = "Living Ruby", order = 8, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Gem" }, + { id = 23439, name = "Noble Topaz", order = 9, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Gem" }, + { id = 23440, name = "Dawnstone", order = 10, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Gem" }, + { id = 23437, name = "Talasite", order = 11, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Gem" }, + { id = 23438, name = "Star of Elune", order = 12, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Gem" }, + { id = 23441, name = "Nightseye", order = 13, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Gem" }, + { id = -1, name = "Epic Gems", order = 14, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Gem" }, + { id = 32227, name = "Crimson Spinel", order = 15, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Gem" }, + { id = 32231, name = "Pyrestone", order = 16, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Gem" }, + { id = 32229, name = "Lionseye", order = 17, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Gem" }, + { id = 32249, name = "Seaspray Emerald", order = 18, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Gem" }, + { id = 32228, name = "Empyrean Sapphire", order = 19, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Gem" }, + { id = 32230, name = "Shadowsong Amethyst", order = 20, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Gem" }, + { id = 22445, name = "Arcane Dust", order = 1, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Enchanting" }, + { id = 22447, name = "Lesser Planar Essence", order = 2, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Enchanting" }, + { id = 22446, name = "Greater Planar Essence", order = 3, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Enchanting" }, + { id = 22448, name = "Small Prismatic Shard", order = 4, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Enchanting" }, + { id = 22449, name = "Large Prismatic Shard", order = 5, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Enchanting" }, + { id = 22450, name = "Void Crystal", order = 6, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Enchanting" }, + { id = 39342, name = "Nether Pigment", order = 1, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Pigment" }, + { id = 43108, name = "Ebon Pigment", order = 2, retail = true, cata = true, wrath = true, bc = true, expansion = "BC", category = "Pigment" }, -- Wrath - { id = 36901, name = "Goldclover", order = 1, retail = true, classic = true, expansion = "Wrath", category = "Herb" }, - { id = 39970, name = "Fire Leaf", order = 2, retail = true, classic = true, expansion = "Wrath", category = "Herb" }, - { id = 36904, name = "Tiger Lily", order = 3, retail = true, classic = true, expansion = "Wrath", category = "Herb" }, - { id = 36907, name = "Talandras Rose", order = 4, retail = true, classic = true, expansion = "Wrath", category = "Herb" }, - { id = 36903, name = "Adders Tongue", order = 5, retail = true, classic = true, expansion = "Wrath", category = "Herb" }, - { id = 37921, name = "Deadnettle", order = 6, retail = true, classic = true, expansion = "Wrath", category = "Herb" }, - { id = 36905, name = "Lichbloom", order = 7, retail = true, classic = true, expansion = "Wrath", category = "Herb" }, - { id = 36906, name = "Icethorn", order = 8, retail = true, classic = true, expansion = "Wrath", category = "Herb" }, - { id = 36908, name = "Frost Lotus", order = 9, retail = true, classic = true, expansion = "Wrath", category = "Herb" }, - { id = 36909, name = "Cobalt Ore", order = 1, retail = true, classic = true, expansion = "Wrath", category = "Ore" }, - { id = 36912, name = "Saronite Ore", order = 2, retail = true, classic = true, expansion = "Wrath", category = "Ore" }, - { id = 36910, name = "Titanium Ore", order = 3, retail = true, classic = true, expansion = "Wrath", category = "Ore" }, - { id = 33470, name = "Frostweave Cloth", order = 1, retail = true, classic = true, expansion = "Wrath", category = "Cloth" }, - { id = 42253, name = "Iceweb Spider Silk", order = 2, retail = true, classic = true, expansion = "Wrath", category = "Cloth" }, - { id = 33568, name = "Borean Leather", order = 1, retail = true, classic = true, expansion = "Wrath", category = "Leather" }, - { id = 44128, name = "Arctic Fur", order = 2, retail = true, classic = true, expansion = "Wrath", category = "Leather" }, - { id = -1, name = "Scales", order = 3, retail = true, classic = true, expansion = "Wrath", category = "Leather" }, - { id = 38557, name = "Icy Dragonscale", order = 4, retail = true, classic = true, expansion = "Wrath", category = "Leather" }, - { id = 38561, name = "Jormungar Scale", order = 5, retail = true, classic = true, expansion = "Wrath", category = "Leather" }, - { id = 38558, name = "Nerubian Chitin", order = 6, retail = true, classic = true, expansion = "Wrath", category = "Leather" }, - { id = 43013, name = "Chilled Meat", order = 1, retail = true, classic = true, expansion = "Wrath", category = "Meat" }, - { id = 34736, name = "Chunk O Mammoth", order = 2, retail = true, classic = true, expansion = "Wrath", category = "Meat" }, - { id = 43501, name = "Northern Egg", order = 3, retail = true, classic = true, expansion = "Wrath", category = "Meat" }, - { id = 43012, name = "Rhino Meat", order = 4, retail = true, classic = true, expansion = "Wrath", category = "Meat" }, - { id = 43009, name = "Shoveltusk Flank", order = 5, retail = true, classic = true, expansion = "Wrath", category = "Meat" }, - { id = 43011, name = "Worg Haunch", order = 6, retail = true, classic = true, expansion = "Wrath", category = "Meat" }, - { id = 43010, name = "Worm Meat", order = 7, retail = true, classic = true, expansion = "Wrath", category = "Meat" }, - { id = 41812, name = "Barrelhead Goby", order = 1, retail = true, classic = true, expansion = "Wrath", category = "Fish" }, - { id = 41808, name = "Bonescale Snapper", order = 2, retail = true, classic = true, expansion = "Wrath", category = "Fish" }, - { id = 41805, name = "Borean Man O War", order = 3, retail = true, classic = true, expansion = "Wrath", category = "Fish" }, - { id = 41800, name = "Deep Sea Monsterbelly", order = 4, retail = true, classic = true, expansion = "Wrath", category = "Fish" }, - { id = 41807, name = "Dragonfin Angelfish", order = 5, retail = true, classic = true, expansion = "Wrath", category = "Fish" }, - { id = 41810, name = "Fangtooth Herring", order = 6, retail = true, classic = true, expansion = "Wrath", category = "Fish" }, - { id = 43646, name = "Fountain Goldfish", order = 7, retail = true, classic = true, expansion = "Wrath", category = "Fish" }, - { id = 41809, name = "Glacial Salmon", order = 8, retail = true, classic = true, expansion = "Wrath", category = "Fish" }, - { id = 41814, name = "Glassfin Minnow", order = 9, retail = true, classic = true, expansion = "Wrath", category = "Fish" }, - { id = 41802, name = "Imperial Manta Ray", order = 10, retail = true, classic = true, expansion = "Wrath", category = "Fish" }, - { id = 43572, name = "Magic Eater", order = 11, retail = true, classic = true, expansion = "Wrath", category = "Fish" }, - { id = 41801, name = "Moonglow Cuttlefish", order = 12, retail = true, classic = true, expansion = "Wrath", category = "Fish" }, - { id = 41806, name = "Musselback Sculpin", order = 13, retail = true, classic = true, expansion = "Wrath", category = "Fish" }, - { id = 41813, name = "Nettlefish", order = 14, retail = true, classic = true, expansion = "Wrath", category = "Fish" }, - { id = 41803, name = "Rockfin Grouper", order = 15, retail = true, classic = true, expansion = "Wrath", category = "Fish" }, - { id = 43571, name = "Sewer Carp", order = 16, retail = true, classic = true, expansion = "Wrath", category = "Fish" }, - { id = 43647, name = "Shimmering Minnow", order = 17, retail = true, classic = true, expansion = "Wrath", category = "Fish" }, - { id = 43652, name = "Slippery Eel", order = 18, retail = true, classic = true, expansion = "Wrath", category = "Fish" }, - { id = 37700, name = "Crystallized Air", order = 1, retail = true, classic = true, expansion = "Wrath", category = "Elemental" }, - { id = 37701, name = "Crystallized Earth", order = 2, retail = true, classic = true, expansion = "Wrath", category = "Elemental" }, - { id = 37702, name = "Crystallized Fire", order = 3, retail = true, classic = true, expansion = "Wrath", category = "Elemental" }, - { id = 37704, name = "Crystallized Life", order = 4, retail = true, classic = true, expansion = "Wrath", category = "Elemental" }, - { id = 37703, name = "Crystallized Shadow", order = 5, retail = true, classic = true, expansion = "Wrath", category = "Elemental" }, - { id = 37705, name = "Crystallized Water", order = 6, retail = true, classic = true, expansion = "Wrath", category = "Elemental" }, - { id = 35623, name = "Eternal Air", order = 7, retail = true, classic = true, expansion = "Wrath", category = "Elemental" }, - { id = 35624, name = "Eternal Earth", order = 8, retail = true, classic = true, expansion = "Wrath", category = "Elemental" }, - { id = 36860, name = "Eternal Fire", order = 9, retail = true, classic = true, expansion = "Wrath", category = "Elemental" }, - { id = 35625, name = "Eternal Life", order = 10, retail = true, classic = true, expansion = "Wrath", category = "Elemental" }, - { id = 35627, name = "Eternal Shadow", order = 11, retail = true, classic = true, expansion = "Wrath", category = "Elemental" }, - { id = 35622, name = "Eternal Water", order = 12, retail = true, classic = true, expansion = "Wrath", category = "Elemental" }, - { id = -1, name = "Other", order = 13, retail = true, classic = true, expansion = "Wrath", category = "Elemental" }, - { id = 43102, name = "Frozen Orb", order = 14, retail = true, classic = true, expansion = "Wrath", category = "Elemental" }, - { id = 45087, name = "Runed Orb", order = 15, retail = true, classic = true, expansion = "Wrath", category = "Elemental" }, - { id = 47556, name = "Crusader Orb", order = 16, retail = true, classic = true, expansion = "Wrath", category = "Elemental" }, - { id = 49908, name = "Primordial Saronite", order = 17, retail = true, classic = true, expansion = "Wrath", category = "Elemental" }, - { id = 36917, name = "Bloodstone", order = 1, retail = true, classic = true, expansion = "Wrath", category = "Gem" }, - { id = 36929, name = "Huge Citrine", order = 2, retail = true, classic = true, expansion = "Wrath", category = "Gem" }, - { id = 36920, name = "Sun Crystal", order = 3, retail = true, classic = true, expansion = "Wrath", category = "Gem" }, - { id = 36932, name = "Dark Jade", order = 4, retail = true, classic = true, expansion = "Wrath", category = "Gem" }, - { id = 36923, name = "Chalcedony", order = 5, retail = true, classic = true, expansion = "Wrath", category = "Gem" }, - { id = 36926, name = "Shadow Crystal", order = 6, retail = true, classic = true, expansion = "Wrath", category = "Gem" }, - { id = -1, name = "Rare Gems", order = 7, retail = true, classic = true, expansion = "Wrath", category = "Gem" }, - { id = 36918, name = "Scarlet Ruby", order = 8, retail = true, classic = true, expansion = "Wrath", category = "Gem" }, - { id = 36930, name = "Monarch Topaz", order = 9, retail = true, classic = true, expansion = "Wrath", category = "Gem" }, - { id = 36921, name = "Autumns Glow", order = 10, retail = true, classic = true, expansion = "Wrath", category = "Gem" }, - { id = 36933, name = "Forest Emerald", order = 11, retail = true, classic = true, expansion = "Wrath", category = "Gem" }, - { id = 36924, name = "Sky Sapphire", order = 12, retail = true, classic = true, expansion = "Wrath", category = "Gem" }, - { id = 36927, name = "Twilight Opal", order = 13, retail = true, classic = true, expansion = "Wrath", category = "Gem" }, - { id = -1, name = "Epic Gems", order = 14, retail = true, classic = true, expansion = "Wrath", category = "Gem" }, - { id = 36919, name = "Cardinal Ruby", order = 15, retail = true, classic = true, expansion = "Wrath", category = "Gem" }, - { id = 36931, name = "Ametrine", order = 16, retail = true, classic = true, expansion = "Wrath", category = "Gem" }, - { id = 36922, name = "Kings Amber", order = 17, retail = true, classic = true, expansion = "Wrath", category = "Gem" }, - { id = 36934, name = "Eye of Zul", order = 18, retail = true, classic = true, expansion = "Wrath", category = "Gem" }, - { id = 36925, name = "Majestic Zircon", order = 19, retail = true, classic = true, expansion = "Wrath", category = "Gem" }, - { id = 36928, name = "Dreadstone", order = 20, retail = true, classic = true, expansion = "Wrath", category = "Gem" }, - { id = 34054, name = "Infinite Dust", order = 1, retail = true, classic = true, expansion = "Wrath", category = "Enchanting" }, - { id = 34056, name = "Lesser Cosmic Essence", order = 2, retail = true, classic = true, expansion = "Wrath", category = "Enchanting" }, - { id = 34055, name = "Greater Cosmic Essence", order = 3, retail = true, classic = true, expansion = "Wrath", category = "Enchanting" }, - { id = 34053, name = "Small Dream Shard", order = 4, retail = true, classic = true, expansion = "Wrath", category = "Enchanting" }, - { id = 34052, name = "Dream Shard", order = 5, retail = true, classic = true, expansion = "Wrath", category = "Enchanting" }, - { id = 34057, name = "Abyss Crystal", order = 6, retail = true, classic = true, expansion = "Wrath", category = "Enchanting" }, - { id = 39343, name = "Azure Pigment", order = 1, retail = true, classic = true, expansion = "Wrath", category = "Pigment" }, - { id = 43109, name = "Icy Pigment", order = 2, retail = true, classic = true, expansion = "Wrath", category = "Pigment" }, + { id = 36901, name = "Goldclover", order = 1, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Herb" }, + { id = 39970, name = "Fire Leaf", order = 2, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Herb" }, + { id = 36904, name = "Tiger Lily", order = 3, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Herb" }, + { id = 36907, name = "Talandras Rose", order = 4, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Herb" }, + { id = 36903, name = "Adders Tongue", order = 5, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Herb" }, + { id = 37921, name = "Deadnettle", order = 6, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Herb" }, + { id = 36905, name = "Lichbloom", order = 7, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Herb" }, + { id = 36906, name = "Icethorn", order = 8, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Herb" }, + { id = 36908, name = "Frost Lotus", order = 9, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Herb" }, + { id = 36909, name = "Cobalt Ore", order = 1, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Ore" }, + { id = 36912, name = "Saronite Ore", order = 2, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Ore" }, + { id = 36910, name = "Titanium Ore", order = 3, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Ore" }, + { id = 33470, name = "Frostweave Cloth", order = 1, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Cloth" }, + { id = 42253, name = "Iceweb Spider Silk", order = 2, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Cloth" }, + { id = 33568, name = "Borean Leather", order = 1, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Leather" }, + { id = 44128, name = "Arctic Fur", order = 2, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Leather" }, + { id = -1, name = "Scales", order = 3, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Leather" }, + { id = 38557, name = "Icy Dragonscale", order = 4, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Leather" }, + { id = 38561, name = "Jormungar Scale", order = 5, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Leather" }, + { id = 38558, name = "Nerubian Chitin", order = 6, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Leather" }, + { id = 43013, name = "Chilled Meat", order = 1, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Meat" }, + { id = 34736, name = "Chunk O Mammoth", order = 2, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Meat" }, + { id = 43501, name = "Northern Egg", order = 3, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Meat" }, + { id = 43012, name = "Rhino Meat", order = 4, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Meat" }, + { id = 43009, name = "Shoveltusk Flank", order = 5, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Meat" }, + { id = 43011, name = "Worg Haunch", order = 6, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Meat" }, + { id = 43010, name = "Worm Meat", order = 7, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Meat" }, + { id = 41812, name = "Barrelhead Goby", order = 1, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Fish" }, + { id = 41808, name = "Bonescale Snapper", order = 2, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Fish" }, + { id = 41805, name = "Borean Man O War", order = 3, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Fish" }, + { id = 41800, name = "Deep Sea Monsterbelly", order = 4, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Fish" }, + { id = 41807, name = "Dragonfin Angelfish", order = 5, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Fish" }, + { id = 41810, name = "Fangtooth Herring", order = 6, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Fish" }, + { id = 43646, name = "Fountain Goldfish", order = 7, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Fish" }, + { id = 41809, name = "Glacial Salmon", order = 8, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Fish" }, + { id = 41814, name = "Glassfin Minnow", order = 9, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Fish" }, + { id = 41802, name = "Imperial Manta Ray", order = 10, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Fish" }, + { id = 43572, name = "Magic Eater", order = 11, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Fish" }, + { id = 41801, name = "Moonglow Cuttlefish", order = 12, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Fish" }, + { id = 41806, name = "Musselback Sculpin", order = 13, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Fish" }, + { id = 41813, name = "Nettlefish", order = 14, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Fish" }, + { id = 41803, name = "Rockfin Grouper", order = 15, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Fish" }, + { id = 43571, name = "Sewer Carp", order = 16, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Fish" }, + { id = 43647, name = "Shimmering Minnow", order = 17, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Fish" }, + { id = 43652, name = "Slippery Eel", order = 18, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Fish" }, + { id = 37700, name = "Crystallized Air", order = 1, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Elemental" }, + { id = 37701, name = "Crystallized Earth", order = 2, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Elemental" }, + { id = 37702, name = "Crystallized Fire", order = 3, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Elemental" }, + { id = 37704, name = "Crystallized Life", order = 4, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Elemental" }, + { id = 37703, name = "Crystallized Shadow", order = 5, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Elemental" }, + { id = 37705, name = "Crystallized Water", order = 6, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Elemental" }, + { id = 35623, name = "Eternal Air", order = 7, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Elemental" }, + { id = 35624, name = "Eternal Earth", order = 8, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Elemental" }, + { id = 36860, name = "Eternal Fire", order = 9, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Elemental" }, + { id = 35625, name = "Eternal Life", order = 10, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Elemental" }, + { id = 35627, name = "Eternal Shadow", order = 11, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Elemental" }, + { id = 35622, name = "Eternal Water", order = 12, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Elemental" }, + { id = -1, name = "Other", order = 13, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Elemental" }, + { id = 43102, name = "Frozen Orb", order = 14, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Elemental" }, + { id = 45087, name = "Runed Orb", order = 15, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Elemental" }, + { id = 47556, name = "Crusader Orb", order = 16, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Elemental" }, + { id = 49908, name = "Primordial Saronite", order = 17, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Elemental" }, + { id = 36917, name = "Bloodstone", order = 1, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Gem" }, + { id = 36929, name = "Huge Citrine", order = 2, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Gem" }, + { id = 36920, name = "Sun Crystal", order = 3, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Gem" }, + { id = 36932, name = "Dark Jade", order = 4, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Gem" }, + { id = 36923, name = "Chalcedony", order = 5, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Gem" }, + { id = 36926, name = "Shadow Crystal", order = 6, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Gem" }, + { id = -1, name = "Rare Gems", order = 7, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Gem" }, + { id = 36918, name = "Scarlet Ruby", order = 8, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Gem" }, + { id = 36930, name = "Monarch Topaz", order = 9, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Gem" }, + { id = 36921, name = "Autumns Glow", order = 10, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Gem" }, + { id = 36933, name = "Forest Emerald", order = 11, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Gem" }, + { id = 36924, name = "Sky Sapphire", order = 12, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Gem" }, + { id = 36927, name = "Twilight Opal", order = 13, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Gem" }, + { id = -1, name = "Epic Gems", order = 14, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Gem" }, + { id = 36919, name = "Cardinal Ruby", order = 15, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Gem" }, + { id = 36931, name = "Ametrine", order = 16, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Gem" }, + { id = 36922, name = "Kings Amber", order = 17, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Gem" }, + { id = 36934, name = "Eye of Zul", order = 18, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Gem" }, + { id = 36925, name = "Majestic Zircon", order = 19, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Gem" }, + { id = 36928, name = "Dreadstone", order = 20, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Gem" }, + { id = 34054, name = "Infinite Dust", order = 1, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Enchanting" }, + { id = 34056, name = "Lesser Cosmic Essence", order = 2, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Enchanting" }, + { id = 34055, name = "Greater Cosmic Essence", order = 3, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Enchanting" }, + { id = 34053, name = "Small Dream Shard", order = 4, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Enchanting" }, + { id = 34052, name = "Dream Shard", order = 5, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Enchanting" }, + { id = 34057, name = "Abyss Crystal", order = 6, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Enchanting" }, + { id = 39343, name = "Azure Pigment", order = 1, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Pigment" }, + { id = 43109, name = "Icy Pigment", order = 2, retail = true, cata = true, wrath = true, expansion = "Wrath", category = "Pigment" }, -- Cata - { id = 52983, name = "Cinderbloom", order = 1, retail = true, classic = true, expansion = "Cata", category = "Herb" }, - { id = 52985, name = "Azsharas Veil", order = 2, retail = true, classic = true, expansion = "Cata", category = "Herb" }, - { id = 52984, name = "Stormvine", order = 3, retail = true, classic = true, expansion = "Cata", category = "Herb" }, - { id = 52986, name = "Heartblossom", order = 4, retail = true, classic = true, expansion = "Cata", category = "Herb" }, - { id = 52988, name = "Whiptail", order = 5, retail = true, classic = true, expansion = "Cata", category = "Herb" }, - { id = 52987, name = "Twilight Jasmine", order = 6, retail = true, classic = true, expansion = "Cata", category = "Herb" }, - { id = 53038, name = "Obsidium Ore", order = 1, retail = true, classic = true, expansion = "Cata", category = "Ore" }, - { id = 52185, name = "Elementium Ore", order = 2, retail = true, classic = true, expansion = "Cata", category = "Ore" }, - { id = 52183, name = "Pyrite Ore", order = 3, retail = true, classic = true, expansion = "Cata", category = "Ore" }, - { id = 53010, name = "Embersilk Cloth", order = 1, retail = true, classic = true, expansion = "Cata", category = "Cloth" }, - { id = 52976, name = "Savage Leather", order = 1, retail = true, classic = true, expansion = "Cata", category = "Leather" }, - { id = 52980, name = "Pristine Hide", order = 2, retail = true, classic = true, expansion = "Cata", category = "Leather" }, - { id = -1, name = "Scales", order = 3, retail = true, classic = true, expansion = "Cata", category = "Leather" }, - { id = 52979, name = "Blackened Dragonscale", order = 4, retail = true, classic = true, expansion = "Cata", category = "Leather" }, - { id = 52982, name = "Deepsea Scale", order = 5, retail = true, classic = true, expansion = "Cata", category = "Leather" }, - { id = 62783, name = "Basilisk Liver", order = 1, retail = true, classic = true, expansion = "Cata", category = "Meat" }, - { id = 62784, name = "Crocolisk Tail", order = 2, retail = true, classic = true, expansion = "Cata", category = "Meat" }, - { id = 62785, name = "Delicate Wing", order = 3, retail = true, classic = true, expansion = "Cata", category = "Meat" }, - { id = 62782, name = "Dragon Flank", order = 4, retail = true, classic = true, expansion = "Cata", category = "Meat" }, - { id = 62781, name = "Giant Turtle Tongue", order = 5, retail = true, classic = true, expansion = "Cata", category = "Meat" }, - { id = 62779, name = "Monstrous Claw", order = 6, retail = true, classic = true, expansion = "Cata", category = "Meat" }, - { id = 62780, name = "Snake Eye", order = 7, retail = true, classic = true, expansion = "Cata", category = "Meat" }, - { id = 67229, name = "Stag Flank", order = 8, retail = true, classic = true, expansion = "Cata", category = "Meat" }, - { id = 62778, name = "Toughened Flesh", order = 9, retail = true, classic = true, expansion = "Cata", category = "Meat" }, - { id = 53065, name = "Albino Cavefish", order = 1, retail = true, classic = true, expansion = "Cata", category = "Fish" }, - { id = 53071, name = "Algaefin Rockffish", order = 2, retail = true, classic = true, expansion = "Cata", category = "Fish" }, - { id = 53066, name = "Blackbelly Mudfish", order = 3, retail = true, classic = true, expansion = "Cata", category = "Fish" }, - { id = 62791, name = "Blood Shrimp", order = 4, retail = true, classic = true, expansion = "Cata", category = "Fish" }, - { id = 53072, name = "Deepsea Sagefish", order = 5, retail = true, classic = true, expansion = "Cata", category = "Fish" }, - { id = 53070, name = "Fathom Eel", order = 6, retail = true, classic = true, expansion = "Cata", category = "Fish" }, - { id = 53064, name = "Highland Guppy", order = 7, retail = true, classic = true, expansion = "Cata", category = "Fish" }, - { id = 53068, name = "Lavascale Catfish", order = 8, retail = true, classic = true, expansion = "Cata", category = "Fish" }, - { id = 53063, name = "Mountain Trout", order = 9, retail = true, classic = true, expansion = "Cata", category = "Fish" }, - { id = 53069, name = "Murglesnout", order = 10, retail = true, classic = true, expansion = "Cata", category = "Fish" }, - { id = 53062, name = "Sharptooth", order = 11, retail = true, classic = true, expansion = "Cata", category = "Fish" }, - { id = 53067, name = "Striped Lurker", order = 12, retail = true, classic = true, expansion = "Cata", category = "Fish" }, - { id = 52328, name = "Volatile Air", order = 1, retail = true, classic = true, expansion = "Cata", category = "Elemental" }, - { id = 52327, name = "Volatile Earth", order = 2, retail = true, classic = true, expansion = "Cata", category = "Elemental" }, - { id = 52325, name = "Volatile Fire", order = 3, retail = true, classic = true, expansion = "Cata", category = "Elemental" }, - { id = 52329, name = "Volatile Life", order = 4, retail = true, classic = true, expansion = "Cata", category = "Elemental" }, - { id = 52326, name = "Volatile Water", order = 5, retail = true, classic = true, expansion = "Cata", category = "Elemental" }, - { id = -1, name = "Other", order = 6, retail = true, classic = true, expansion = "Cata", category = "Elemental" }, - { id = 52078, name = "Chaos Orb", order = 7, retail = true, classic = true, expansion = "Cata", category = "Elemental" }, - { id = 69237, name = "Living Ember", order = 8, retail = true, classic = true, expansion = "Cata", category = "Elemental" }, - { id = 71998, name = "Essence of Destruction", order = 9, retail = true, classic = true, expansion = "Cata", category = "Elemental" }, - { id = 52177, name = "Carnelian", order = 1, retail = true, classic = true, expansion = "Cata", category = "Gem" }, - { id = 52181, name = "Hessonite", order = 2, retail = true, classic = true, expansion = "Cata", category = "Gem" }, - { id = 52179, name = "Alicite", order = 3, retail = true, classic = true, expansion = "Cata", category = "Gem" }, - { id = 52182, name = "Jasper", order = 4, retail = true, classic = true, expansion = "Cata", category = "Gem" }, - { id = 52178, name = "Zephyrite", order = 5, retail = true, classic = true, expansion = "Cata", category = "Gem" }, - { id = 52180, name = "Nightstone", order = 6, retail = true, classic = true, expansion = "Cata", category = "Gem" }, - { id = -1, name = "Rare Gems", order = 7, retail = true, classic = true, expansion = "Cata", category = "Gem" }, - { id = 52190, name = "Inferno Ruby", order = 8, retail = true, classic = true, expansion = "Cata", category = "Gem" }, - { id = 52193, name = "Ember Topaz", order = 9, retail = true, classic = true, expansion = "Cata", category = "Gem" }, - { id = 52195, name = "Amberjewel", order = 10, retail = true, classic = true, expansion = "Cata", category = "Gem" }, - { id = 52192, name = "Dream Emerald", order = 11, retail = true, classic = true, expansion = "Cata", category = "Gem" }, - { id = 52191, name = "Ocean Sapphire", order = 12, retail = true, classic = true, expansion = "Cata", category = "Gem" }, - { id = 52194, name = "Demonseye", order = 13, retail = true, classic = true, expansion = "Cata", category = "Gem" }, - { id = -1, name = "Epic Gems", order = 14, retail = true, classic = true, expansion = "Cata", category = "Gem" }, - { id = 71808, name = "Lava Coral", order = 15, retail = true, classic = true, expansion = "Cata", category = "Gem" }, - { id = 71806, name = "Lightstone", order = 16, retail = true, classic = true, expansion = "Cata", category = "Gem" }, - { id = 71810, name = "Elven Peridot", order = 17, retail = true, classic = true, expansion = "Cata", category = "Gem" }, - { id = 71807, name = "Deepholm Iolite", order = 18, retail = true, classic = true, expansion = "Cata", category = "Gem" }, - { id = 71809, name = "Shadow Spinel", order = 19, retail = true, classic = true, expansion = "Cata", category = "Gem" }, - { id = 52555, name = "Hypnotic Dust", order = 1, retail = true, classic = true, expansion = "Cata", category = "Enchanting" }, - { id = 52718, name = "Lesser Celestial Essence", order = 2, retail = true, classic = true, expansion = "Cata", category = "Enchanting" }, - { id = 52719, name = "Greater Celestial Essence", order = 3, retail = true, classic = true, expansion = "Cata", category = "Enchanting" }, - { id = 52720, name = "Small Heavenly Shard", order = 4, retail = true, classic = true, expansion = "Cata", category = "Enchanting" }, - { id = 52721, name = "Heavenly Shard", order = 5, retail = true, classic = true, expansion = "Cata", category = "Enchanting" }, - { id = 52722, name = "Maelstrom Crystal", order = 6, retail = true, classic = true, expansion = "Cata", category = "Enchanting" }, - { id = 61979, name = "Ashen Pigment", order = 1, retail = true, classic = true, expansion = "Cata", category = "Pigment" }, - { id = 61980, name = "Burning Embers", order = 2, retail = true, classic = true, expansion = "Cata", category = "Pigment" }, + { id = 52983, name = "Cinderbloom", order = 1, retail = true, cata = true, expansion = "Cata", category = "Herb" }, + { id = 52985, name = "Azsharas Veil", order = 2, retail = true, cata = true, expansion = "Cata", category = "Herb" }, + { id = 52984, name = "Stormvine", order = 3, retail = true, cata = true, expansion = "Cata", category = "Herb" }, + { id = 52986, name = "Heartblossom", order = 4, retail = true, cata = true, expansion = "Cata", category = "Herb" }, + { id = 52988, name = "Whiptail", order = 5, retail = true, cata = true, expansion = "Cata", category = "Herb" }, + { id = 52987, name = "Twilight Jasmine", order = 6, retail = true, cata = true, expansion = "Cata", category = "Herb" }, + { id = 53038, name = "Obsidium Ore", order = 1, retail = true, cata = true, expansion = "Cata", category = "Ore" }, + { id = 52185, name = "Elementium Ore", order = 2, retail = true, cata = true, expansion = "Cata", category = "Ore" }, + { id = 52183, name = "Pyrite Ore", order = 3, retail = true, cata = true, expansion = "Cata", category = "Ore" }, + { id = 53010, name = "Embersilk Cloth", order = 1, retail = true, cata = true, expansion = "Cata", category = "Cloth" }, + { id = 52976, name = "Savage Leather", order = 1, retail = true, cata = true, expansion = "Cata", category = "Leather" }, + { id = 52980, name = "Pristine Hide", order = 2, retail = true, cata = true, expansion = "Cata", category = "Leather" }, + { id = -1, name = "Scales", order = 3, retail = true, cata = true, expansion = "Cata", category = "Leather" }, + { id = 52979, name = "Blackened Dragonscale", order = 4, retail = true, cata = true, expansion = "Cata", category = "Leather" }, + { id = 52982, name = "Deepsea Scale", order = 5, retail = true, cata = true, expansion = "Cata", category = "Leather" }, + { id = 62783, name = "Basilisk Liver", order = 1, retail = true, cata = true, expansion = "Cata", category = "Meat" }, + { id = 62784, name = "Crocolisk Tail", order = 2, retail = true, cata = true, expansion = "Cata", category = "Meat" }, + { id = 62785, name = "Delicate Wing", order = 3, retail = true, cata = true, expansion = "Cata", category = "Meat" }, + { id = 62782, name = "Dragon Flank", order = 4, retail = true, cata = true, expansion = "Cata", category = "Meat" }, + { id = 62781, name = "Giant Turtle Tongue", order = 5, retail = true, cata = true, expansion = "Cata", category = "Meat" }, + { id = 62779, name = "Monstrous Claw", order = 6, retail = true, cata = true, expansion = "Cata", category = "Meat" }, + { id = 62780, name = "Snake Eye", order = 7, retail = true, cata = true, expansion = "Cata", category = "Meat" }, + { id = 67229, name = "Stag Flank", order = 8, retail = true, cata = true, expansion = "Cata", category = "Meat" }, + { id = 62778, name = "Toughened Flesh", order = 9, retail = true, cata = true, expansion = "Cata", category = "Meat" }, + { id = 53065, name = "Albino Cavefish", order = 1, retail = true, cata = true, expansion = "Cata", category = "Fish" }, + { id = 53071, name = "Algaefin Rockffish", order = 2, retail = true, cata = true, expansion = "Cata", category = "Fish" }, + { id = 53066, name = "Blackbelly Mudfish", order = 3, retail = true, cata = true, expansion = "Cata", category = "Fish" }, + { id = 62791, name = "Blood Shrimp", order = 4, retail = true, cata = true, expansion = "Cata", category = "Fish" }, + { id = 53072, name = "Deepsea Sagefish", order = 5, retail = true, cata = true, expansion = "Cata", category = "Fish" }, + { id = 53070, name = "Fathom Eel", order = 6, retail = true, cata = true, expansion = "Cata", category = "Fish" }, + { id = 53064, name = "Highland Guppy", order = 7, retail = true, cata = true, expansion = "Cata", category = "Fish" }, + { id = 53068, name = "Lavascale Catfish", order = 8, retail = true, cata = true, expansion = "Cata", category = "Fish" }, + { id = 53063, name = "Mountain Trout", order = 9, retail = true, cata = true, expansion = "Cata", category = "Fish" }, + { id = 53069, name = "Murglesnout", order = 10, retail = true, cata = true, expansion = "Cata", category = "Fish" }, + { id = 53062, name = "Sharptooth", order = 11, retail = true, cata = true, expansion = "Cata", category = "Fish" }, + { id = 53067, name = "Striped Lurker", order = 12, retail = true, cata = true, expansion = "Cata", category = "Fish" }, + { id = 52328, name = "Volatile Air", order = 1, retail = true, cata = true, expansion = "Cata", category = "Elemental" }, + { id = 52327, name = "Volatile Earth", order = 2, retail = true, cata = true, expansion = "Cata", category = "Elemental" }, + { id = 52325, name = "Volatile Fire", order = 3, retail = true, cata = true, expansion = "Cata", category = "Elemental" }, + { id = 52329, name = "Volatile Life", order = 4, retail = true, cata = true, expansion = "Cata", category = "Elemental" }, + { id = 52326, name = "Volatile Water", order = 5, retail = true, cata = true, expansion = "Cata", category = "Elemental" }, + { id = -1, name = "Other", order = 6, retail = true, cata = true, expansion = "Cata", category = "Elemental" }, + { id = 52078, name = "Chaos Orb", order = 7, retail = true, cata = true, expansion = "Cata", category = "Elemental" }, + { id = 69237, name = "Living Ember", order = 8, retail = true, cata = true, expansion = "Cata", category = "Elemental" }, + { id = 71998, name = "Essence of Destruction", order = 9, retail = true, cata = true, expansion = "Cata", category = "Elemental" }, + { id = 52177, name = "Carnelian", order = 1, retail = true, cata = true, expansion = "Cata", category = "Gem" }, + { id = 52181, name = "Hessonite", order = 2, retail = true, cata = true, expansion = "Cata", category = "Gem" }, + { id = 52179, name = "Alicite", order = 3, retail = true, cata = true, expansion = "Cata", category = "Gem" }, + { id = 52182, name = "Jasper", order = 4, retail = true, cata = true, expansion = "Cata", category = "Gem" }, + { id = 52178, name = "Zephyrite", order = 5, retail = true, cata = true, expansion = "Cata", category = "Gem" }, + { id = 52180, name = "Nightstone", order = 6, retail = true, cata = true, expansion = "Cata", category = "Gem" }, + { id = -1, name = "Rare Gems", order = 7, retail = true, cata = true, expansion = "Cata", category = "Gem" }, + { id = 52190, name = "Inferno Ruby", order = 8, retail = true, cata = true, expansion = "Cata", category = "Gem" }, + { id = 52193, name = "Ember Topaz", order = 9, retail = true, cata = true, expansion = "Cata", category = "Gem" }, + { id = 52195, name = "Amberjewel", order = 10, retail = true, cata = true, expansion = "Cata", category = "Gem" }, + { id = 52192, name = "Dream Emerald", order = 11, retail = true, cata = true, expansion = "Cata", category = "Gem" }, + { id = 52191, name = "Ocean Sapphire", order = 12, retail = true, cata = true, expansion = "Cata", category = "Gem" }, + { id = 52194, name = "Demonseye", order = 13, retail = true, cata = true, expansion = "Cata", category = "Gem" }, + { id = -1, name = "Epic Gems", order = 14, retail = true, cata = true, expansion = "Cata", category = "Gem" }, + { id = 71808, name = "Lava Coral", order = 15, retail = true, cata = true, expansion = "Cata", category = "Gem" }, + { id = 71806, name = "Lightstone", order = 16, retail = true, cata = true, expansion = "Cata", category = "Gem" }, + { id = 71810, name = "Elven Peridot", order = 17, retail = true, cata = true, expansion = "Cata", category = "Gem" }, + { id = 71807, name = "Deepholm Iolite", order = 18, retail = true, cata = true, expansion = "Cata", category = "Gem" }, + { id = 71809, name = "Shadow Spinel", order = 19, retail = true, cata = true, expansion = "Cata", category = "Gem" }, + { id = 52555, name = "Hypnotic Dust", order = 1, retail = true, cata = true, expansion = "Cata", category = "Enchanting" }, + { id = 52718, name = "Lesser Celestial Essence", order = 2, retail = true, cata = true, expansion = "Cata", category = "Enchanting" }, + { id = 52719, name = "Greater Celestial Essence", order = 3, retail = true, cata = true, expansion = "Cata", category = "Enchanting" }, + { id = 52720, name = "Small Heavenly Shard", order = 4, retail = true, cata = true, expansion = "Cata", category = "Enchanting" }, + { id = 52721, name = "Heavenly Shard", order = 5, retail = true, cata = true, expansion = "Cata", category = "Enchanting" }, + { id = 52722, name = "Maelstrom Crystal", order = 6, retail = true, cata = true, expansion = "Cata", category = "Enchanting" }, + { id = 61979, name = "Ashen Pigment", order = 1, retail = true, cata = true, expansion = "Cata", category = "Pigment" }, + { id = 61980, name = "Burning Embers", order = 2, retail = true, cata = true, expansion = "Cata", category = "Pigment" }, -- MoP { id = 72234, name = "Green Tea Leaf", order = 1, retail = true, expansion = "MoP", category = "Herb" }, { id = 72237, name = "Rain Poppy", order = 2, retail = true, expansion = "MoP", category = "Herb" }, @@ -1337,9 +1360,9 @@ local ItemData = { { id = -1, name = "Other", order = 16, season = true, expansion = "SoD", category = "Phase 3" }, { id = 221021, name = "Nightmare Seed", order = 17, season = true, expansion = "SoD", category = "Phase 3" }, -- Other - { id = 1, name = "Current Gold", order = 1, icon = "Interface\\Addons\\GatheringTracker\\Media\\Ability_Racial_PackHobgoblin", desc = "Displays the current Gold on the character, rounded to the nearest whole number.", retail = true, classic = true, era = true, season = true, expansion = "Other", category = "Other" }, - { id = 2, name = "Open Bag Space", order = 2, icon = "Interface\\Addons\\GatheringTracker\\Media\\Garrison_Building_Storehouse", desc = "Displays the number of open bag space.", retail = true, classic = true, era = true, season = true, expansion = "Other", category = "Other" }, - { id = 3, name = "Session Timer", order = 3, icon = 134377, desc = "Displays a timer starting from the first gather after being enabled.", retail = true, classic = true, era = true, season = true, expansion = "Other", category = "Other" }, + { id = 1, name = "Current Gold", order = 1, icon = "Interface\\Addons\\GatheringTracker\\Media\\Ability_Racial_PackHobgoblin", desc = "Displays the current Gold on the character, rounded to the nearest whole number.", retail = true, cata = true, era = true, season = true, expansion = "Other", category = "Other" }, + { id = 2, name = "Open Bag Space", order = 2, icon = "Interface\\Addons\\GatheringTracker\\Media\\Garrison_Building_Storehouse", desc = "Displays the number of open bag space.", retail = true, cata = true, era = true, season = true, expansion = "Other", category = "Other" }, + { id = 3, name = "Session Timer", order = 3, icon = 134377, desc = "Displays a timer starting from the first gather after being enabled.", retail = true, cata = true, era = true, season = true, expansion = "Other", category = "Other" }, } GT.ItemData = {} diff --git a/DisplayCreation.lua b/DisplayCreation.lua index 32c6b48..12b76d6 100644 --- a/DisplayCreation.lua +++ b/DisplayCreation.lua @@ -37,6 +37,11 @@ local function FramePool_Resetter(framePool, frame) GT.Pools.texturePool:Release(frame.iconRarity) frame.iconRarity = nil end + if frame.highlight then + frame.highlight:SetVertexColor(1, 1, 1, 1) + GT.Pools.texturePool:Release(frame.highlight) + frame.highlight = nil + end if frame.text == nil then return end @@ -113,6 +118,8 @@ function GT:CreateDisplayFrame(id, iconId, iconQuality, iconRarity, displayText, GT.Display.Frames[id] = frame + GT:DisplayFrameHighlight(frame) + GT:DisplayFrameIcon(frame, iconId, id) if iconQuality then @@ -240,6 +247,14 @@ function GT:DisplayFrameRarity(frame, iconRarity) frame.iconRarity:Show() end +function GT:DisplayFrameHighlight(frame) + frame.highlight = GT.Pools.texturePool:Acquire() + frame.highlight:SetParent(frame) + frame.highlight:SetDrawLayer("BACKGROUND", 7) + frame.highlight:SetAllPoints(frame) + frame.highlight:Hide() +end + function GT:DisplayFrameCounts(frame, id, text, index) index = index or 1 local anchor = frame.icon diff --git a/FilterButton.lua b/FilterButton.lua index 01ff3d3..38ff37c 100644 --- a/FilterButton.lua +++ b/FilterButton.lua @@ -39,7 +39,7 @@ function GT:ToggleFilterButton(show) end end -function GT:FiltersButton(profileChanged) +function GT:FiltersButton() if not GT.db.profile.General.filtersButton then GT:ToggleFilterButton(false) return @@ -70,6 +70,8 @@ function GT:FiltersButton(profileChanged) GT:ResetSession() elseif button == "LeftButton" then GT:GenerateFiltersMenu(self) + elseif button == "RightButton" and IsShiftKeyDown() then + GT.AlertSystem:ResetAlerts() elseif button == "RightButton" then GT:ClearFilters() end @@ -175,9 +177,6 @@ function GT:GenerateFiltersMenu(frame) end frame[expansion][category] = frame[expansion]:CreateCheckbox(category, IsSelected_Category, SetSelected_Category) - if category == "Knowledge" then - local columns = 3 - end frame[expansion][category]:SetScrollMode(GetScreenHeight() * 0.75) for _, itemData in ipairs(GT.ItemData[expansion][category]) do local function IsSelected_Item() @@ -267,10 +266,12 @@ function GT:GenerateFiltersMenu(frame) --add Profiles to filterMenu GT:CreateProfilesList(frame, rootDescription) - GT.baseFrame.button.rootDescription = rootDescription + GT.baseFrame.menu.rootDescription = rootDescription end - MenuUtil.CreateContextMenu(frame, FiltersMenu) + ---@class GT.baseFrame.menu: MenuProxy + GT.baseFrame.menu = GT.baseFrame.menu or {} + GT.baseFrame.menu = MenuUtil.CreateContextMenu(frame, FiltersMenu) end function GT:FiltersButtonFade(alpha) @@ -396,11 +397,26 @@ function GT:CreateCustomFiltersList(frame, rootDescription) frame["Custom Filters"][itemData.text] = frame["Custom Filters"]:CreateCheckbox(itemData.text, IsSelected_CustomFilterItem, SetSelected_CustomFilterItem) frame["Custom Filters"][itemData.text]:AddInitializer(function(text, description, menu) local leftTexture = text:AttachTexture() - leftTexture:SetSize(18, 18) + + leftTexture:SetDrawLayer("BACKGROUND", 0) leftTexture:SetPoint("LEFT", text.leftTexture1, "RIGHT", 7, 1) + text:SetHeight(26) + leftTexture:SetSize(24, 24) leftTexture:SetTexture(tonumber(itemData.icon)) text.fontString:SetPoint("LEFT", leftTexture, "RIGHT", 7, 1) + + local leftTextureRarity = text:AttachTexture() + leftTextureRarity:SetDrawLayer("BACKGROUND", 1) + local rarity = C_Item.GetItemQualityByID(itemData.id) or 1 + if rarity <= 1 then + leftTextureRarity:SetTexture("Interface\\Common\\WhiteIconFrame") + else + leftTextureRarity:SetAtlas("bags-glow-white") + end + local R, G, B = C_Item.GetItemQualityColor(rarity) + leftTextureRarity:SetVertexColor(R, G, B, 0.8) + leftTextureRarity:SetAllPoints(leftTexture) end) end end @@ -429,6 +445,7 @@ function GT:CreateProfilesList(frame, rootDescription) local function SetSelected_Profile() GT.Debug("Profile Button Clicked", 2, name) GT.db:SetProfile(name) + GT.baseFrame.menu:Close() end frame["Profiles"][name] = frame["Profiles"]:CreateCheckbox(name, IsSelected_Profile, SetSelected_Profile) diff --git a/GatheringTracker.lua b/GatheringTracker.lua index 2339cf8..904177b 100644 --- a/GatheringTracker.lua +++ b/GatheringTracker.lua @@ -9,8 +9,6 @@ GT.Pools = {} GT.PlayerEnteringWorld = true GT.DebugCount = 0 GT.Options = {} -GT.Notifications = {} -GT.NotificationPause = true GT.GlobalStartTime = 0 -- Localize global functions @@ -34,15 +32,16 @@ GT.metaData = { notes = C_AddOns.GetAddOnMetadata("GatheringTracker", "Notes"), } -GT.gameVersion = "retail" -if WOW_PROJECT_ID == WOW_PROJECT_CATACLYSM_CLASSIC then - GT.gameVersion = "classic" -elseif WOW_PROJECT_ID == WOW_PROJECT_CLASSIC and (C_Seasons.GetActiveSeason() == 2) then +local gameVersions = { + [WOW_PROJECT_MAINLINE or 1] = "retail", + [WOW_PROJECT_CLASSIC or 2] = "era", + [WOW_PROJECT_BURNING_CRUSADE_CLASSIC or 5] = "bc", + [WOW_PROJECT_WRATH_CLASSIC or 11] = "wrath", + [WOW_PROJECT_CATACLYSM_CLASSIC or 14] = "cata" +} +GT.gameVersion = gameVersions[WOW_PROJECT_ID] or "retail" +if WOW_PROJECT_ID == WOW_PROJECT_CLASSIC and (C_Seasons.GetActiveSeason() == 2) then GT.gameVersion = "season" -elseif WOW_PROJECT_ID == WOW_PROJECT_CLASSIC then - GT.gameVersion = "era" -else - GT.gameVersion = "retail" end BINDING_HEADER_GATHERINGTRACKER = GT.metaData.name .. " v" .. GT.metaData.version @@ -61,6 +60,8 @@ function GT:OnEnable() GT:RegisterEvent("PLAYER_REGEN_DISABLED") GT:RegisterEvent("PLAYER_REGEN_ENABLED") end + + GT:MinimapHandler(GT.db.profile.miniMap.enable) else GT:OnDisable() end @@ -96,8 +97,8 @@ function GT:PLAYER_ENTERING_WORLD() end GT:wait(6, "InventoryUpdate", "PLAYER_ENTERING_WORLD", false) - GT:wait(7, "NotificationHandler", "PLAYER_ENTERING_WORLD") GT:wait(7, "AnchorFilterButton", "PLAYER_ENTERING_WORLD") + GT:wait(8, "AllowAlertEffects", "AllowAlertEffects") end function GT:GROUP_ROSTER_UPDATE(event) @@ -170,9 +171,6 @@ function GT:CreateBaseFrame() backdrop = backdrop, } GT.baseFrame = baseFrame - - GT:FiltersButton() - GT:InitializePools() end function GT:UpdateBaseFrameSize() @@ -211,6 +209,7 @@ function GT:ToggleBaseLock(key) frame:SetMovable(true) frame:EnableMouse(true) frame:SetMouseClickEnabled(true) + frame:SetSize(GT.baseFrame.frame:GetSize()) frame:SetScript("OnMouseDown", function(self, button) if button == "LeftButton" and not self.isMoving then self:StartMoving() @@ -248,9 +247,6 @@ function GT:OptionsHide() GT:ToggleBaseLock(false) end - --Pause Notifications to prevent spam after closing the settings - GT.NotificationPause = true - --Do an inventory update if we dont have any information if #GT.InventoryData == 0 and GT.Enabled then GT:InventoryUpdate("InterfaceOptionsFrame:OnHide", false) @@ -549,12 +545,6 @@ function GT:PrepareDataForDisplay(event, wait) GT:SetTSMPriceSource() - if not GT.NotificationPause then - GT.Debug("Trigger Notification Handler for all", 6) - local count, value = GT:CalculatePlayerTotal(true, GT.db.profile.General.sessionOnly) - GT:NotificationHandler("all", "all", count, value) - end - GT:SetupItemRows() GT:SetupTotalsRow() @@ -591,6 +581,7 @@ function GT:SetupItemRows() local pricePerItem = nil local itemsPerHour = nil local goldPerHour = nil + local displayText = GT:GetItemRowData(itemID) if GT.priceSources then pricePerItem = GT:GetItemPrice(itemID) end @@ -607,16 +598,18 @@ function GT:SetupItemRows() end GT:InitiateFrameProcess( - tonumber(itemID), + itemID, C_Item.GetItemIconByID(itemID), iconQuality, C_Item.GetItemQualityByID(itemID), - GT:GetItemRowData(itemID), + displayText, pricePerItem, priceTotalItem, itemsPerHour, goldPerHour ) + + GT.AlertSystem:Alerts(itemID, displayText, priceTotalItem) elseif GT.Display.Frames[itemID] then GT:RemoveDiaplayRow(itemID) end @@ -624,6 +617,9 @@ function GT:SetupItemRows() end end +---generates the count data that will be displayed for a given item +---@param itemID number +---@return table|number displayText table if both session and total count are enabled, otherwise number function GT:GetItemRowData(itemID) GT.Debug("GetItemRowData", 2, itemID) @@ -720,6 +716,7 @@ function GT:SetupTotalsRow() itemsPerHour, goldPerHour ) + GT.AlertSystem:Alerts(2, playerTotals, priceTotal) elseif GT.Display.Frames[9999999998] then GT:RemoveDiaplayRow(9999999998) end @@ -831,12 +828,6 @@ function GT:ProcessData(event) ) end - if event and (event == "InventoryUpdate" or event == "BAG_UPDATE") and itemCount > 0 then - GT.Debug("Trigger Notification Handler for each", 5) - GT.NotificationPause = false - GT:NotificationHandler("each", data.id, itemCount) - end - GT.InventoryData[data.id] = GT.InventoryData[data.id] or GT:ItemDataConstructor(data.id) GT.InventoryData[data.id].count = itemCount diff --git a/GatheringTracker.toc b/GatheringTracker.toc index adb47fc..ed22f7f 100644 --- a/GatheringTracker.toc +++ b/GatheringTracker.toc @@ -1,12 +1,14 @@ -## Interface: 11504, 40401, 110005 +## Interface: 11505, 40401, 110005 ## Title: Gathering Tracker ## Notes: Addon for tracking gathered items, supports solo players and groups ## Author: Noshei -## Version: 3.0.4 +## Version: 3.1.0 ## OptionalDeps: TradeSkillMaster, RECrystallize, Auctionator ## SavedVariables: GatheringTrackerDB ## AddonCompartmentFunc: GatheringTracker_OnAddonCompartmentClick ## IconTexture: Interface\Addons\GatheringTracker\Media\GT_Icon +## X-Curse-Project-ID: 406104 +## X-Wago-ID: Xb6XQbKp embeds.xml GatheringTracker.lua @@ -14,7 +16,8 @@ DisplayCreation.lua DisplayCollapse.lua Utilities.lua FilterButton.lua -NotificationHandler.lua +Alerts.lua +AlertsMenu.lua Constants.lua Config.lua Broker.lua diff --git a/Libs/AceGUI-3.0-NosheiWidgets/CheckBox-Extended.lua b/Libs/AceGUI-3.0-NosheiWidgets/CheckBox-Extended.lua index d332341..1359a44 100644 --- a/Libs/AceGUI-3.0-NosheiWidgets/CheckBox-Extended.lua +++ b/Libs/AceGUI-3.0-NosheiWidgets/CheckBox-Extended.lua @@ -1,6 +1,7 @@ --[[----------------------------------------------------------------------------- Checkbox Extended Widget Widget is an extension of the Checkbox Widget from AceGUI-3.0 +Updated to use newer checkbox atlas files instead of old textures We've hijacked ImageCoords from AceConfDisplay to be able to extend the new functions to AceConfig This Lib is not for general use outside of my own addons. Adds additional image options: @@ -11,7 +12,7 @@ Adds additional image options: -------------------------------------------------------------------------------]] local AGNW = LibStub:NewLibrary("AceGUINosheiWidgets-1.0", 110002) -local Type, Version = "NW_CheckBox", 1 +local Type, Version = "NW_CheckBox", 2 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end @@ -41,10 +42,14 @@ end Scripts -------------------------------------------------------------------------------]] local function Control_OnEnter(frame) + local self = frame.obj + self.background:SetVertexColor(0.35, 0.35, 0.35, 1) frame.obj:Fire("OnEnter") end local function Control_OnLeave(frame) + local self = frame.obj + self.background:SetVertexColor(0, 0, 0, 0) frame.obj:Fire("OnLeave") end @@ -91,7 +96,16 @@ local methods = { self:SetDescription(nil) end, - -- ["OnRelease"] = nil, + ["OnRelease"] = function(self) + if self.border then + self.border:SetTexture(nil) + self.border:SetAtlas(nil) + end + if self.overlay then + self.overlay:SetTexture(nil) + self.overlay:SetAtlas(nil) + end + end, ["OnWidthSet"] = function(self, width) if self.desc then @@ -170,13 +184,16 @@ local methods = { highlight:SetTexCoord(0.5, 0.75, 0, 1) else size = 24 - checkbg:SetTexture(130755) -- Interface\\Buttons\\UI-CheckBox-Up - checkbg:SetTexCoord(0, 1, 0, 1) - check:SetTexture(130751) -- Interface\\Buttons\\UI-CheckBox-Check - check:SetTexCoord(0, 1, 0, 1) + --checkbg:SetTexture(130755) -- Interface\\Buttons\\UI-CheckBox-Up + --checkbg:SetTexCoord(0, 1, 0, 1) + checkbg:SetAtlas("checkbox-minimal", true) + check:SetAtlas("checkmark-minimal", true) + --check:SetTexture(130751) -- Interface\\Buttons\\UI-CheckBox-Check + --check:SetTexCoord(0, 1, 0, 1) check:SetBlendMode("BLEND") - highlight:SetTexture(130753) -- Interface\\Buttons\\UI-CheckBox-Highlight - highlight:SetTexCoord(0, 1, 0, 1) + highlight:SetAtlas("checkbox-minimal", true) + --highlight:SetTexture(130753) -- Interface\\Buttons\\UI-CheckBox-Highlight + --highlight:SetTexCoord(0, 1, 0, 1) end checkbg:SetHeight(size) checkbg:SetWidth(size) @@ -291,15 +308,22 @@ local function Constructor() frame:SetScript("OnMouseDown", CheckBox_OnMouseDown) frame:SetScript("OnMouseUp", CheckBox_OnMouseUp) + local background = frame:CreateTexture(nil, "BACKGROUND") + background:SetAllPoints(frame) + background:SetTexture("Interface/Tooltips/UI-Tooltip-Background") + background:SetVertexColor(0, 0, 0, 0) + local checkbg = frame:CreateTexture(nil, "ARTWORK") checkbg:SetWidth(24) checkbg:SetHeight(24) checkbg:SetPoint("TOPLEFT") - checkbg:SetTexture(130755) -- Interface\\Buttons\\UI-CheckBox-Up + checkbg:SetAtlas("checkbox-minimal", true) + --checkbg:SetTexture(130755) -- Interface\\Buttons\\UI-CheckBox-Up local check = frame:CreateTexture(nil, "OVERLAY") check:SetAllPoints(checkbg) - check:SetTexture(130751) -- Interface\\Buttons\\UI-CheckBox-Check + check:SetAtlas("checkmark-minimal", true) + --check:SetTexture(130751) -- Interface\\Buttons\\UI-CheckBox-Check local text = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlight") text:SetJustifyH("LEFT") @@ -308,7 +332,8 @@ local function Constructor() text:SetPoint("RIGHT") local highlight = frame:CreateTexture(nil, "HIGHLIGHT") - highlight:SetTexture(130753) -- Interface\\Buttons\\UI-CheckBox-Highlight + highlight:SetAtlas("checkbox-minimal", true) + --highlight:SetTexture(130753) -- Interface\\Buttons\\UI-CheckBox-Highlight highlight:SetBlendMode("ADD") highlight:SetAllPoints(checkbg) @@ -325,6 +350,7 @@ local function Constructor() local widget = { checkbg = checkbg, + background = background, check = check, text = text, highlight = highlight, diff --git a/Libs/AceGUI-3.0-NosheiWidgets/DropDown-Extended.lua b/Libs/AceGUI-3.0-NosheiWidgets/DropDown-Extended.lua new file mode 100644 index 0000000..5972057 --- /dev/null +++ b/Libs/AceGUI-3.0-NosheiWidgets/DropDown-Extended.lua @@ -0,0 +1,754 @@ +--[[ $Id: AceGUIWidget-DropDown.lua 1284 2022-09-25 09:15:30Z nevcairiel $ ]] -- +local AceGUI = LibStub("AceGUI-3.0") + +-- Lua APIs +local min, max, floor = math.min, math.max, math.floor +local select, pairs, ipairs, type, tostring = select, pairs, ipairs, type, tostring +local tsort = table.sort + +-- WoW APIs +local PlaySound = PlaySound +local UIParent, CreateFrame = UIParent, CreateFrame +local _G = _G + +local function fixlevels(parent, ...) + local i = 1 + local child = select(i, ...) + while child do + child:SetFrameLevel(parent:GetFrameLevel() + 1) + fixlevels(child, child:GetChildren()) + i = i + 1 + child = select(i, ...) + end +end + +local function fixstrata(strata, parent, ...) + local i = 1 + local child = select(i, ...) + parent:SetFrameStrata(strata) + while child do + fixstrata(strata, child, child:GetChildren()) + i = i + 1 + child = select(i, ...) + end +end + +do + local widgetType = "NW_Dropdown-Pullout" + local widgetVersion = 5 + + --[[ Static data ]] -- + + local backdrop = { + bgFile = "Interface\\ChatFrame\\ChatFrameBackground", + --edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", + edgeFile = "interface\\glues\\charactercreate\\charactercreatedropdown", + edgeSize = 32, + tileSize = 32, + tile = true, + insets = { left = 20, right = 20, top = 20, bottom = 20 }, + } + local sliderBackdrop = { + bgFile = "Interface\\Buttons\\UI-SliderBar-Background", + edgeFile = "Interface\\Buttons\\UI-SliderBar-Border", + tile = true, + tileSize = 8, + edgeSize = 8, + insets = { left = 3, right = 3, top = 3, bottom = 3 } + } + + local defaultWidth = 200 + local defaultMaxHeight = 600 + + --[[ UI Event Handlers ]] -- + + -- HACK: This should be no part of the pullout, but there + -- is no other 'clean' way to response to any item-OnEnter + -- Used to close Submenus when an other item is entered + local function OnEnter(item) + local self = item.pullout + for k, v in ipairs(self.items) do + if v.CloseMenu and v ~= item then + v:CloseMenu() + end + end + end + + -- See the note in Constructor() for each scroll related function + local function OnMouseWheel(this, value) + this.obj:MoveScroll(value) + end + + local function OnScrollValueChanged(this, value) + this.obj:SetScroll(value) + end + + local function OnSizeChanged(this) + this.obj:FixScroll() + end + + --[[ Exported methods ]] -- + + -- exported + local function SetScroll(self, value) + local status = self.scrollStatus + local frame, child = self.scrollFrame, self.itemFrame + local height, viewheight = frame:GetHeight(), child:GetHeight() + + local offset + if height > viewheight then + offset = 0 + else + offset = floor((viewheight - height) / 1000 * value) + end + child:ClearAllPoints() + child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset) + child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", self.slider:IsShown() and -12 or 0, offset) + status.offset = offset + status.scrollvalue = value + end + + -- exported + local function MoveScroll(self, value) + local status = self.scrollStatus + local frame, child = self.scrollFrame, self.itemFrame + local height, viewheight = frame:GetHeight(), child:GetHeight() + + if height > viewheight then + self.slider:Hide() + else + self.slider:Show() + local diff = height - viewheight + local delta = 1 + if value < 0 then + delta = -1 + end + self.slider:SetValue(min(max(status.scrollvalue + delta * (1000 / (diff / 45)), 0), 1000)) + end + end + + -- exported + local function FixScroll(self) + local status = self.scrollStatus + local frame, child = self.scrollFrame, self.itemFrame + local height, viewheight = frame:GetHeight(), child:GetHeight() + local offset = status.offset or 0 + + if viewheight < height then + self.slider:Hide() + child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, offset) + self.slider:SetValue(0) + else + self.slider:Show() + local value = (offset / (viewheight - height) * 1000) + if value > 1000 then value = 1000 end + self.slider:SetValue(value) + self:SetScroll(value) + if value < 1000 then + child:ClearAllPoints() + child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset) + child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -12, offset) + status.offset = offset + end + end + end + + -- exported, AceGUI callback + local function OnAcquire(self) + self.frame:SetParent(UIParent) + --self.itemFrame:SetToplevel(true) + end + + -- exported, AceGUI callback + local function OnRelease(self) + self:Clear() + self.frame:ClearAllPoints() + self.frame:Hide() + end + + -- exported + local function AddItem(self, item) + self.items[#self.items + 1] = item + + local h = #self.items * 16 + self.itemFrame:SetHeight(h) + self.frame:SetHeight(min(h + 34, self.maxHeight)) -- +34: 20 for scrollFrame placement (10 offset) and +14 for item placement + + item.frame:SetPoint("LEFT", self.itemFrame, "LEFT") + item.frame:SetPoint("RIGHT", self.itemFrame, "RIGHT") + + item:SetPullout(self) + item:SetOnEnter(OnEnter) + end + + -- exported + local function Open(self, point, relFrame, relPoint, x, y) + local items = self.items + local frame = self.frame + local itemFrame = self.itemFrame + + frame:SetPoint(point, relFrame, relPoint, x, y) + + + local height = 8 + for i, item in pairs(items) do + item:SetPoint("TOP", itemFrame, "TOP", 0, -2 + (i - 1) * -16) + item:Show() + + height = height + 16 + end + itemFrame:SetHeight(height) + fixstrata("TOOLTIP", frame, frame:GetChildren()) + frame:Show() + self:Fire("OnOpen") + end + + -- exported + local function Close(self) + self.frame:Hide() + self:Fire("OnClose") + end + + -- exported + local function Clear(self) + local items = self.items + for i, item in pairs(items) do + AceGUI:Release(item) + items[i] = nil + end + end + + -- exported + local function IterateItems(self) + return ipairs(self.items) + end + + -- exported + local function SetHideOnLeave(self, val) + self.hideOnLeave = val + end + + -- exported + local function SetMaxHeight(self, height) + self.maxHeight = height or defaultMaxHeight + if self.frame:GetHeight() > height then + self.frame:SetHeight(height) + elseif (self.itemFrame:GetHeight() + 34) < height then + self.frame:SetHeight(self.itemFrame:GetHeight() + 34) -- see :AddItem + end + end + + -- exported + local function GetRightBorderWidth(self) + return 6 + (self.slider:IsShown() and 12 or 0) + end + + -- exported + local function GetLeftBorderWidth(self) + return 6 + end + + --[[ Constructor ]] -- + + local function Constructor() + local count = AceGUI:GetNextWidgetNum(widgetType) + local frame = CreateFrame("Frame", "AceGUI30Pullout" .. count, UIParent) --, "BackdropTemplate") + local backdrop = frame:CreateTexture(nil, "BACKGROUND") + local self = {} + self.count = count + self.type = widgetType + self.frame = frame + self.backdrop = backdrop + frame.obj = self + + self.OnAcquire = OnAcquire + self.OnRelease = OnRelease + + self.AddItem = AddItem + self.Open = Open + self.Close = Close + self.Clear = Clear + self.IterateItems = IterateItems + self.SetHideOnLeave = SetHideOnLeave + + self.SetScroll = SetScroll + self.MoveScroll = MoveScroll + self.FixScroll = FixScroll + + self.SetMaxHeight = SetMaxHeight + self.GetRightBorderWidth = GetRightBorderWidth + self.GetLeftBorderWidth = GetLeftBorderWidth + + self.items = {} + + self.scrollStatus = { + scrollvalue = 0, + } + + self.maxHeight = defaultMaxHeight + + --frame:SetBackdrop(backdrop) + --frame:SetBackdropColor(0, 0, 0) + frame:SetFrameStrata("FULLSCREEN_DIALOG") + frame:SetClampedToScreen(true) + frame:SetWidth(defaultWidth) + frame:SetHeight(self.maxHeight) + --frame:SetToplevel(true) + + backdrop:SetAtlas("common-dropdown-bg") + backdrop:SetAllPoints(frame) + + -- NOTE: The whole scroll frame code is copied from the AceGUI-3.0 widget ScrollFrame + local scrollFrame = CreateFrame("ScrollFrame", nil, frame) + local itemFrame = CreateFrame("Frame", nil, scrollFrame) + + self.scrollFrame = scrollFrame + self.itemFrame = itemFrame + + scrollFrame.obj = self + itemFrame.obj = self + + local slider = CreateFrame("Slider", "AceGUI30PulloutScrollbar" .. count, scrollFrame, "BackdropTemplate") + slider:SetOrientation("VERTICAL") + slider:SetHitRectInsets(0, 0, -10, 0) + slider:SetBackdrop(sliderBackdrop) + slider:SetWidth(8) + slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical") + slider:SetFrameStrata("FULLSCREEN_DIALOG") + self.slider = slider + slider.obj = self + + scrollFrame:SetScrollChild(itemFrame) + scrollFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", 6, -12) + scrollFrame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -6, 12) + scrollFrame:EnableMouseWheel(true) + scrollFrame:SetScript("OnMouseWheel", OnMouseWheel) + scrollFrame:SetScript("OnSizeChanged", OnSizeChanged) + scrollFrame:SetToplevel(true) + scrollFrame:SetFrameStrata("FULLSCREEN_DIALOG") + + itemFrame:SetPoint("TOPLEFT", scrollFrame, "TOPLEFT", 0, 0) + itemFrame:SetPoint("TOPRIGHT", scrollFrame, "TOPRIGHT", -12, 0) + itemFrame:SetHeight(400) + itemFrame:SetToplevel(true) + itemFrame:SetFrameStrata("FULLSCREEN_DIALOG") + + slider:SetPoint("TOPLEFT", scrollFrame, "TOPRIGHT", -16, 0) + slider:SetPoint("BOTTOMLEFT", scrollFrame, "BOTTOMRIGHT", -16, 0) + slider:SetScript("OnValueChanged", OnScrollValueChanged) + slider:SetMinMaxValues(0, 1000) + slider:SetValueStep(1) + slider:SetValue(0) + + scrollFrame:Show() + itemFrame:Show() + slider:Hide() + + self:FixScroll() + + AceGUI:RegisterAsWidget(self) + return self + end + + AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion) +end + +do + local widgetType = "NW_Dropdown" + local widgetVersion = 1 + + --[[ Static data ]] -- + + --[[ UI event handler ]] -- + + local function Control_OnEnter(this) + if this.obj.dropdown:IsEnabled() then + this.obj.dropdown.over = true; + this.obj.dropdown:OnButtonStateChanged(); + end + --this.obj.button:LockHighlight() + this.obj:Fire("OnEnter") + end + + local function Control_OnLeave(this) + if this.obj.dropdown:IsEnabled() then + this.obj.dropdown.over = nil; + this.obj.dropdown:OnButtonStateChanged(); + end + --this.obj.button:UnlockHighlight() + this.obj:Fire("OnLeave") + end + + local function Dropdown_OnHide(this) + local self = this.obj + if self.open then + self.pullout:Close() + end + end + + local function Dropdown_TogglePullout(this) + local self = this.obj + if self.open then + self.open = nil + self.pullout:Close() + AceGUI:ClearFocus() + else + self.open = true + self.pullout:SetWidth(self.pulloutWidth or self.frame:GetWidth()) + self.pullout:Open("TOPLEFT", self.frame, "BOTTOMLEFT", 0, self.label:IsShown() and -2 or 0) + AceGUI:SetFocus(self) + end + end + + local function OnPulloutOpen(this) + local self = this.userdata.obj + local value = self.value + + if not self.multiselect then + for i, item in this:IterateItems() do + item:SetValue(item.userdata.value == value) + end + end + + self.open = true + self:Fire("OnOpened") + end + + local function OnPulloutClose(this) + local self = this.userdata.obj + self.open = nil + self:Fire("OnClosed") + end + + local function ShowMultiText(self) + local text + for i, widget in self.pullout:IterateItems() do + if widget.type == "NW_Dropdown-Item-Toggle" then + if widget:GetValue() then + if text then + text = text .. ", " .. widget:GetText() + else + text = widget:GetText() + end + end + end + end + self:SetText(text) + end + + local function OnItemValueChanged(this, event, checked) + local self = this.userdata.obj + + if self.multiselect then + self:Fire("OnValueChanged", this.userdata.value, checked) + ShowMultiText(self) + else + if checked then + self:SetValue(this.userdata.value) + self:Fire("OnValueChanged", this.userdata.value) + else + this:SetValue(true) + end + if self.open then + self.pullout:Close() + end + end + end + + --[[ Exported methods ]] -- + + -- exported, AceGUI callback + local function OnAcquire(self) + local pullout = AceGUI:Create("NW_Dropdown-Pullout") + self.pullout = pullout + pullout.userdata.obj = self + pullout:SetCallback("OnClose", OnPulloutClose) + pullout:SetCallback("OnOpen", OnPulloutOpen) + self.pullout.frame:SetFrameLevel(self.frame:GetFrameLevel() + 1) + fixlevels(self.pullout.frame, self.pullout.frame:GetChildren()) + + self:SetHeight(44) + self:SetWidth(200) + self:SetLabel() + self:SetPulloutWidth(nil) + self.list = {} + end + + -- exported, AceGUI callback + local function OnRelease(self) + if self.open then + self.pullout:Close() + end + AceGUI:Release(self.pullout) + self.pullout = nil + + self:SetText("") + self:SetDisabled(false) + self:SetMultiselect(false) + + self.value = nil + self.list = nil + self.open = nil + self.hasClose = nil + + self.frame:ClearAllPoints() + self.frame:Hide() + end + + -- exported + local function SetDisabled(self, disabled) + self.disabled = disabled + if disabled then + --[[self.text:SetTextColor(0.5, 0.5, 0.5) + self.button:Disable() + self.button_cover:Disable()]] + self.label:SetTextColor(0.5, 0.5, 0.5) + self.dropdown:Disable() + else + --[[self.button:Enable() + self.button_cover:Enable() + self.text:SetTextColor(1, 1, 1)]] + self.label:SetTextColor(1, .82, 0) + self.dropdown:Enable() + end + end + + -- exported + local function ClearFocus(self) + if self.open then + self.pullout:Close() + end + end + + -- exported + local function SetText(self, text) + --self.text:SetText(text or "") + self.dropdown.Text:SetText(text or "") + end + + -- exported + local function SetLabel(self, text) + if text and text ~= "" then + self.label:SetText(text) + self.label:Show() + self.dropdown:SetPoint("TOPLEFT", self.frame, "TOPLEFT", 3, -16) + self:SetHeight(44) + self.alignoffset = 26 + else + self.label:SetText("") + self.label:Hide() + self.dropdown:SetPoint("TOPLEFT", self.frame, "TOPLEFT", 3, 0) + self:SetHeight(44) + self.alignoffset = 12 + end + end + + -- exported + local function SetValue(self, value) + self:SetText(self.list[value] or "") + self.value = value + end + + -- exported + local function GetValue(self) + return self.value + end + + -- exported + local function SetItemValue(self, item, value) + if not self.multiselect then return end + for i, widget in self.pullout:IterateItems() do + if widget.userdata.value == item then + if widget.SetValue then + widget:SetValue(value) + end + end + end + ShowMultiText(self) + end + + -- exported + local function SetItemDisabled(self, item, disabled) + for i, widget in self.pullout:IterateItems() do + if widget.userdata.value == item then + widget:SetDisabled(disabled) + end + end + end + + local function AddListItem(self, value, text, itemType) + if not itemType then itemType = "NW_Dropdown-Item-Toggle" end + local exists = AceGUI:GetWidgetVersion(itemType) + if not exists then error(("The given item type, %q, does not exist within AceGUI-3.0"):format(tostring(itemType)), 2) end + + local item = AceGUI:Create(itemType) + item:SetText(text) + item.userdata.obj = self + item.userdata.value = value + item:SetCallback("OnValueChanged", OnItemValueChanged) + self.pullout:AddItem(item) + end + + local function AddCloseButton(self) + if not self.hasClose then + local close = AceGUI:Create("NW_Dropdown-Item-Execute") + close:SetText(CLOSE) + self.pullout:AddItem(close) + self.hasClose = true + end + end + + -- exported + local sortlist = {} + local function sortTbl(x, y) + local num1, num2 = tonumber(x), tonumber(y) + if num1 and num2 then -- numeric comparison, either two numbers or numeric strings + return num1 < num2 + else -- compare everything else tostring'ed + return tostring(x) < tostring(y) + end + end + local function SetList(self, list, order, itemType) + self.list = list or {} + self.pullout:Clear() + self.hasClose = nil + if not list then return end + + if type(order) ~= "table" then + for v in pairs(list) do + sortlist[#sortlist + 1] = v + end + tsort(sortlist, sortTbl) + + for i, key in ipairs(sortlist) do + AddListItem(self, key, list[key], itemType) + sortlist[i] = nil + end + else + for i, key in ipairs(order) do + AddListItem(self, key, list[key], itemType) + end + end + if self.multiselect then + ShowMultiText(self) + AddCloseButton(self) + end + end + + -- exported + local function AddItem(self, value, text, itemType) + self.list[value] = text + AddListItem(self, value, text, itemType) + end + + -- exported + local function SetMultiselect(self, multi) + self.multiselect = multi + if multi then + ShowMultiText(self) + AddCloseButton(self) + end + end + + -- exported + local function GetMultiselect(self) + return self.multiselect + end + + local function SetPulloutWidth(self, width) + self.pulloutWidth = width + end + + --[[ Constructor ]] -- + + local function Constructor() + local count = AceGUI:GetNextWidgetNum(widgetType) + local frame = CreateFrame("Frame", nil, UIParent) + local dropdown = CreateFrame("DropdownButton", "AceGUI30DropDown" .. count, frame, "WowStyle2DropdownTemplate") + + local self = {} + self.type = widgetType + self.frame = frame + self.dropdown = dropdown + self.count = count + frame.obj = self + dropdown.obj = self + + self.OnRelease = OnRelease + self.OnAcquire = OnAcquire + + self.ClearFocus = ClearFocus + + self.SetText = SetText + self.SetValue = SetValue + self.GetValue = GetValue + self.SetList = SetList + self.SetLabel = SetLabel + self.SetDisabled = SetDisabled + self.AddItem = AddItem + self.SetMultiselect = SetMultiselect + self.GetMultiselect = GetMultiselect + self.SetItemValue = SetItemValue + self.SetItemDisabled = SetItemDisabled + self.SetPulloutWidth = SetPulloutWidth + + self.alignoffset = 26 + + frame:SetScript("OnHide", Dropdown_OnHide) + + dropdown:ClearAllPoints() + dropdown:SetPoint("TOPLEFT", frame, "TOPLEFT", 3, 0) + dropdown:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -5, 0) + dropdown:SetScript("OnHide", nil) + dropdown:SetScript("OnEnter", Control_OnEnter) + dropdown:SetScript("OnLeave", Control_OnLeave) + dropdown:SetScript("OnClick", Dropdown_TogglePullout) + + --[[local left = _G[dropdown:GetName() .. "Left"] + local middle = _G[dropdown:GetName() .. "Middle"] + local right = _G[dropdown:GetName() .. "Right"] + + middle:ClearAllPoints() + right:ClearAllPoints() + + middle:SetPoint("LEFT", left, "RIGHT", 0, 0) + middle:SetPoint("RIGHT", right, "LEFT", 0, 0) + right:SetPoint("TOPRIGHT", dropdown, "TOPRIGHT", 0, 17) + + local button = _G[dropdown:GetName() .. "Button"] + self.button = button + button.obj = self + button:SetScript("OnEnter", Control_OnEnter) + button:SetScript("OnLeave", Control_OnLeave) + button:SetScript("OnClick", Dropdown_TogglePullout) + + local button_cover = CreateFrame("BUTTON", nil, self.frame) + self.button_cover = button_cover + button_cover.obj = self + button_cover:SetPoint("TOPLEFT", self.frame, "BOTTOMLEFT", 0, 25) + button_cover:SetPoint("BOTTOMRIGHT", self.frame, "BOTTOMRIGHT") + button_cover:SetScript("OnEnter", Control_OnEnter) + button_cover:SetScript("OnLeave", Control_OnLeave) + button_cover:SetScript("OnClick", Dropdown_TogglePullout) + + local text = _G[dropdown:GetName() .. "Text"] + self.text = text + text.obj = self + text:ClearAllPoints() + text:SetPoint("RIGHT", right, "RIGHT", -43, 2) + text:SetPoint("LEFT", left, "LEFT", 25, 2)]] + + local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + label:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, 0) + label:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, 0) + label:SetJustifyH("LEFT") + label:SetHeight(18) + label:Hide() + self.label = label + + AceGUI:RegisterAsWidget(self) + return self + end + + AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion) +end diff --git a/Libs/AceGUI-3.0-NosheiWidgets/DropDown-Items-Extended.lua b/Libs/AceGUI-3.0-NosheiWidgets/DropDown-Items-Extended.lua new file mode 100644 index 0000000..0e7bddd --- /dev/null +++ b/Libs/AceGUI-3.0-NosheiWidgets/DropDown-Items-Extended.lua @@ -0,0 +1,474 @@ +--[[ $Id: AceGUIWidget-DropDown-Items.lua 1272 2022-08-29 15:56:35Z nevcairiel $ ]] -- + +local AceGUI = LibStub("AceGUI-3.0") + +-- Lua APIs +local select, assert = select, assert + +-- WoW APIs +local PlaySound = PlaySound +local CreateFrame = CreateFrame + +local function fixlevels(parent, ...) + local i = 1 + local child = select(i, ...) + while child do + child:SetFrameLevel(parent:GetFrameLevel() + 1) + fixlevels(child, child:GetChildren()) + i = i + 1 + child = select(i, ...) + end +end + +local function fixstrata(strata, parent, ...) + local i = 1 + local child = select(i, ...) + parent:SetFrameStrata(strata) + while child do + fixstrata(strata, child, child:GetChildren()) + i = i + 1 + child = select(i, ...) + end +end + +-- ItemBase is the base "class" for all dropdown items. +-- Each item has to use ItemBase.Create(widgetType) to +-- create an initial 'self' value. +-- ItemBase will add common functions and ui event handlers. +-- Be sure to keep basic usage when you override functions. + +local ItemBase = { + -- NOTE: The ItemBase version is added to each item's version number + -- to ensure proper updates on ItemBase changes. + -- Use at least 1000er steps. + version = 2000, + counter = 0, +} + +function ItemBase.Frame_OnEnter(this) + local self = this.obj + + if self.useHighlight then + self.highlight:SetAlpha(0.25) + end + self:Fire("OnEnter") + + if self.specialOnEnter then + self.specialOnEnter(self) + end +end + +function ItemBase.Frame_OnLeave(this) + local self = this.obj + + self.highlight:SetAlpha(0) + self:Fire("OnLeave") + + if self.specialOnLeave then + self.specialOnLeave(self) + end +end + +-- exported, AceGUI callback +function ItemBase.OnAcquire(self) + self.frame:SetToplevel(true) + self.frame:SetFrameStrata("FULLSCREEN_DIALOG") +end + +-- exported, AceGUI callback +function ItemBase.OnRelease(self) + self:SetDisabled(false) + self.pullout = nil + self.frame:SetParent(nil) + self.frame:ClearAllPoints() + self.frame:Hide() +end + +-- exported +-- NOTE: this is called by a Dropdown-Pullout. +-- Do not call this method directly +function ItemBase.SetPullout(self, pullout) + self.pullout = pullout + + self.frame:SetParent(nil) + self.frame:SetParent(pullout.itemFrame) + self.parent = pullout.itemFrame + fixlevels(pullout.itemFrame, pullout.itemFrame:GetChildren()) +end + +-- exported +function ItemBase.SetText(self, text) + self.text:SetText(text or "") +end + +-- exported +function ItemBase.GetText(self) + return self.text:GetText() +end + +-- exported +function ItemBase.SetPoint(self, ...) + self.frame:SetPoint(...) +end + +-- exported +function ItemBase.Show(self) + self.frame:Show() +end + +-- exported +function ItemBase.Hide(self) + self.frame:Hide() +end + +-- exported +function ItemBase.SetDisabled(self, disabled) + self.disabled = disabled + if disabled then + self.useHighlight = false + self.text:SetTextColor(.5, .5, .5) + else + self.useHighlight = true + self.text:SetTextColor(1, 1, 1) + end +end + +-- exported +-- NOTE: this is called by a Dropdown-Pullout. +-- Do not call this method directly +function ItemBase.SetOnLeave(self, func) + self.specialOnLeave = func +end + +-- exported +-- NOTE: this is called by a Dropdown-Pullout. +-- Do not call this method directly +function ItemBase.SetOnEnter(self, func) + self.specialOnEnter = func +end + +function ItemBase.Create(type) + -- NOTE: Most of the following code is copied from AceGUI-3.0/Dropdown widget + local count = AceGUI:GetNextWidgetNum(type) + local frame = CreateFrame("Button", "AceGUI30DropDownItem" .. count) + local self = {} + self.frame = frame + frame.obj = self + self.type = type + + self.useHighlight = true + + frame:SetHeight(17) + frame:SetFrameStrata("FULLSCREEN_DIALOG") + + local text = frame:CreateFontString(nil, "OVERLAY", "GameFontWhite") + text:SetTextColor(1, 1, 1) + text:SetJustifyH("LEFT") + text:SetPoint("TOPLEFT", frame, "TOPLEFT", 18, 0) + text:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -8, 0) + self.text = text + + local highlight = frame:CreateTexture(nil, "OVERLAY") + highlight:SetAtlas("common-dropdown-customize-mouseover", true) + --highlight:SetTexture(136810) -- Interface\\QuestFrame\\UI-QuestTitleHighlight + --highlight:SetBlendMode("ADD") + highlight:SetHeight(17) + highlight:ClearAllPoints() + highlight:SetPoint("RIGHT", frame, "RIGHT", -10, 0) + highlight:SetPoint("LEFT", frame, "LEFT", 10, 0) + highlight:SetAlpha(0) + self.highlight = highlight + + --[[local check = frame:CreateTexture(nil, "OVERLAY") + check:SetWidth(16) + check:SetHeight(16) + check:SetPoint("LEFT", frame, "LEFT", 3, -1) + check:SetTexture(130751) -- Interface\\Buttons\\UI-CheckBox-Check + check:Hide() + self.check = check]] + + local sub = frame:CreateTexture(nil, "OVERLAY") + sub:SetWidth(16) + sub:SetHeight(16) + sub:SetPoint("RIGHT", frame, "RIGHT", -3, -1) + sub:SetTexture(130940) -- Interface\\ChatFrame\\ChatFrameExpandArrow + sub:Hide() + self.sub = sub + + frame:SetScript("OnEnter", ItemBase.Frame_OnEnter) + frame:SetScript("OnLeave", ItemBase.Frame_OnLeave) + + self.OnAcquire = ItemBase.OnAcquire + self.OnRelease = ItemBase.OnRelease + + self.SetPullout = ItemBase.SetPullout + self.GetText = ItemBase.GetText + self.SetText = ItemBase.SetText + self.SetDisabled = ItemBase.SetDisabled + + self.SetPoint = ItemBase.SetPoint + self.Show = ItemBase.Show + self.Hide = ItemBase.Hide + + self.SetOnLeave = ItemBase.SetOnLeave + self.SetOnEnter = ItemBase.SetOnEnter + + return self +end + +-- Register a dummy LibStub library to retrieve the ItemBase, so other addons can use it. +local IBLib = LibStub:NewLibrary("NW_Dropdown-ItemBase", ItemBase.version) +if IBLib then + IBLib.GetItemBase = function() return ItemBase end +end + +--[[ + Template for items: + +-- Item: +-- +do + local widgetType = "Dropdown-Item-" + local widgetVersion = 1 + + local function Constructor() + local self = ItemBase.Create(widgetType) + + AceGUI:RegisterAsWidget(self) + return self + end + + AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version) +end +--]] + +-- Item: Header +-- A single text entry. +-- Special: Different text color and no highlight +do + local widgetType = "NW_Dropdown-Item-Header" + local widgetVersion = 1 + + local function OnEnter(this) + local self = this.obj + self:Fire("OnEnter") + + if self.specialOnEnter then + self.specialOnEnter(self) + end + end + + local function OnLeave(this) + local self = this.obj + self:Fire("OnLeave") + + if self.specialOnLeave then + self.specialOnLeave(self) + end + end + + -- exported, override + local function SetDisabled(self, disabled) + ItemBase.SetDisabled(self, disabled) + if not disabled then + self.text:SetTextColor(1, 1, 0) + end + end + + local function Constructor() + local self = ItemBase.Create(widgetType) + + self.SetDisabled = SetDisabled + + self.frame:SetScript("OnEnter", OnEnter) + self.frame:SetScript("OnLeave", OnLeave) + + self.text:SetTextColor(1, 1, 0) + + AceGUI:RegisterAsWidget(self) + return self + end + + AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version) +end + +-- Item: Execute +-- A simple button +do + local widgetType = "NW_Dropdown-Item-Execute" + local widgetVersion = 1 + + local function Frame_OnClick(this, button) + local self = this.obj + if self.disabled then return end + self:Fire("OnClick") + if self.pullout then + self.pullout:Close() + end + end + + local function Constructor() + local self = ItemBase.Create(widgetType) + + self.frame:SetScript("OnClick", Frame_OnClick) + + AceGUI:RegisterAsWidget(self) + return self + end + + AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version) +end + +-- Item: Toggle +-- Some sort of checkbox for dropdown menus. +-- Does not close the pullout on click. +do + local widgetType = "NW_Dropdown-Item-Toggle" + local widgetVersion = 4 + + local function UpdateToggle(self) + if self.value then + self.text:SetTextColor(1, 0.82, 0) + --self.check:Show() + else + self.text:SetTextColor(1, 1, 1) + --self.check:Hide() + end + end + + local function OnRelease(self) + ItemBase.OnRelease(self) + self:SetValue(nil) + end + + local function Frame_OnClick(this, button) + local self = this.obj + if self.disabled then return end + self.value = not self.value + if self.value then + PlaySound(856) -- SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON + else + PlaySound(857) -- SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_OFF + end + UpdateToggle(self) + self:Fire("OnValueChanged", self.value) + end + + -- exported + local function SetValue(self, value) + self.value = value + UpdateToggle(self) + end + + -- exported + local function GetValue(self) + return self.value + end + + local function Constructor() + local self = ItemBase.Create(widgetType) + + self.frame:SetScript("OnClick", Frame_OnClick) + + self.SetValue = SetValue + self.GetValue = GetValue + self.OnRelease = OnRelease + + AceGUI:RegisterAsWidget(self) + return self + end + + AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version) +end + +-- Item: Menu +-- Shows a submenu on mouse over +-- Does not close the pullout on click +do + local widgetType = "NW_Dropdown-Item-Menu" + local widgetVersion = 2 + + local function OnEnter(this) + local self = this.obj + self:Fire("OnEnter") + + if self.specialOnEnter then + self.specialOnEnter(self) + end + + self.highlight:SetAlpha(0.15) + + if not self.disabled and self.submenu then + self.submenu:Open("TOPLEFT", self.frame, "TOPRIGHT", self.pullout:GetRightBorderWidth(), 0, self.frame:GetFrameLevel() + 100) + end + end + + local function OnHide(this) + local self = this.obj + if self.submenu then + self.submenu:Close() + end + end + + -- exported + local function SetMenu(self, menu) + assert(menu.type == "NW_Dropdown-Pullout") + self.submenu = menu + end + + -- exported + local function CloseMenu(self) + self.submenu:Close() + end + + local function Constructor() + local self = ItemBase.Create(widgetType) + + self.sub:Show() + + self.frame:SetScript("OnEnter", OnEnter) + self.frame:SetScript("OnHide", OnHide) + + self.SetMenu = SetMenu + self.CloseMenu = CloseMenu + + AceGUI:RegisterAsWidget(self) + return self + end + + AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version) +end + +-- Item: Separator +-- A single line to separate items +do + local widgetType = "NW_Dropdown-Item-Separator" + local widgetVersion = 2 + + -- exported, override + local function SetDisabled(self, disabled) + ItemBase.SetDisabled(self, disabled) + self.useHighlight = false + end + + local function Constructor() + local self = ItemBase.Create(widgetType) + + self.SetDisabled = SetDisabled + + local line = self.frame:CreateTexture(nil, "OVERLAY") + line:SetHeight(1) + line:SetColorTexture(.5, .5, .5) + line:SetPoint("LEFT", self.frame, "LEFT", 10, 0) + line:SetPoint("RIGHT", self.frame, "RIGHT", -10, 0) + + self.text:Hide() + + self.useHighlight = false + + AceGUI:RegisterAsWidget(self) + return self + end + + AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version) +end diff --git a/Libs/AceGUI-3.0-NosheiWidgets/FontWidget.lua b/Libs/AceGUI-3.0-NosheiWidgets/FontWidget.lua new file mode 100644 index 0000000..b90345e --- /dev/null +++ b/Libs/AceGUI-3.0-NosheiWidgets/FontWidget.lua @@ -0,0 +1,246 @@ +-- Widget is based on the AceGUIWidget-DropDown.lua supplied with AceGUI-3.0 +-- Widget created by Yssaril +-- Forked from AceGUISharedMediaWidgets-1.0 to modify for my own use by Noshei + +local AceGUI = LibStub("AceGUI-3.0") +local Media = LibStub("LibSharedMedia-3.0") + +local AGNW = LibStub("AceGUI-3.0-NosheiWidgets-1.0") + +do + local widgetType = "NW_Font" + local widgetVersion = 1 + + local contentFrameCache = {} + local function ReturnSelf(self) + self:ClearAllPoints() + self:Hide() + --self.check:Hide() + table.insert(contentFrameCache, self) + end + + local function ContentOnClick(this, button) + local self = this.obj + self:Fire("OnValueChanged", this.text:GetText()) + if self.dropdown then + self.dropdown = AGNW:ReturnDropDownFrame(self.dropdown) + end + end + + local function GetContentLine() + local frame + if next(contentFrameCache) then + frame = table.remove(contentFrameCache) + else + frame = CreateFrame("Button", nil, UIParent) + --frame:SetWidth(200) + frame:SetHeight(18) + --frame:SetHighlightTexture([[Interface\QuestFrame\UI-QuestTitleHighlight]], "ADD") + frame:SetScript("OnClick", ContentOnClick) + --[[local check = frame:CreateTexture("OVERLAY") + check:SetWidth(16) + check:SetHeight(16) + check:SetPoint("LEFT", frame, "LEFT", 1, -1) + check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") + check:Hide() + frame.check = check]] + + local highlight = frame:CreateTexture(nil, "OVERLAY") + highlight:SetAtlas("common-dropdown-customize-mouseover", true) + highlight:SetHeight(18) + highlight:ClearAllPoints() + highlight:SetPoint("RIGHT", frame, "RIGHT", -1, 0) + highlight:SetPoint("LEFT", frame, "LEFT", 1, 0) + highlight:SetAlpha(0) + frame.highlight = highlight + + local text = frame:CreateFontString(nil, "OVERLAY", "GameFontWhite") + text:SetPoint("TOPLEFT", frame, "TOPLEFT", 8, 0) + text:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -8, 0) + text:SetJustifyH("LEFT") + text:SetText("Test Test Test Test Test Test Test") + frame.text = text + frame.ReturnSelf = ReturnSelf + + frame:SetScript("OnEnter", function(self) + self.highlight:SetAlpha(0.25) + end) + frame:SetScript("OnLeave", function(self) + self.highlight:SetAlpha(0) + end) + end + frame:Show() + return frame + end + + local function OnAcquire(self) + self:SetHeight(44) + self:SetWidth(200) + end + + local function OnRelease(self) + self:SetText("") + self:SetLabel("") + self:SetDisabled(false) + + self.value = nil + self.list = nil + self.open = nil + self.hasClose = nil + + self.frame:ClearAllPoints() + self.frame:Hide() + end + + local function SetValue(self, value) -- Set the value to an item in the List. + if self.list then + self:SetText(value or "") + end + self.value = value + end + + local function GetValue(self) + return self.value + end + + local function SetList(self, list) -- Set the list of values for the dropdown (key => value pairs) + self.list = list or Media:HashTable("font") + end + + local function SetText(self, text) -- Set the text displayed in the box. + --self.frame.text:SetText(text or "") + self.frame.dropButton.Text:SetText(text or "") + local font = self.list[text] ~= text and self.list[text] or Media:Fetch('font', text) + local _, size, outline = self.frame.dropButton.Text:GetFont() + --self.frame.text:SetFont(font, size, outline) + self.frame.dropButton.Text:SetFont(font, size, outline) + end + + local function SetLabel(self, text) -- Set the text for the label. + self.frame.label:SetText(text or "") + end + + local function AddItem(self, key, value) -- Add an item to the list. + self.list = self.list or {} + self.list[key] = value + end + local SetItemValue = AddItem -- Set the value of a item in the list. <> + + local function SetMultiselect(self, flag) end -- Toggle multi-selecting. <> + local function GetMultiselect() return false end -- Query the multi-select flag. <> + local function SetItemDisabled(self, key) end -- Disable one item in the list. <> + + local function SetDisabled(self, disabled) -- Disable the widget. + self.disabled = disabled + if disabled then + self.frame:Disable() + else + self.frame:Enable() + end + end + + local function textSort(a, b) + return string.upper(a) < string.upper(b) + end + + local sortedlist = {} + local function ToggleDrop(this) + local self = this.obj + if self.dropdown then + self.dropdown = AGNW:ReturnDropDownFrame(self.dropdown) + AceGUI:ClearFocus() + else + AceGUI:SetFocus(self) + self.dropdown = AGNW:GetDropDownFrame() + local width = self.frame:GetWidth() + self.dropdown:SetPoint("TOPLEFT", self.frame, "BOTTOMLEFT") + self.dropdown:SetPoint("TOPRIGHT", self.frame, "BOTTOMRIGHT", width < 160 and (160 - width) or 0, 0) + for k, v in pairs(self.list) do + sortedlist[#sortedlist + 1] = k + end + table.sort(sortedlist, textSort) + for i, k in ipairs(sortedlist) do + local f = GetContentLine() + local _, size, outline = f.text:GetFont() + local font = self.list[k] ~= k and self.list[k] or Media:Fetch('font', k) + f.text:SetFont(font, size, outline) + f.text:SetText(k) + if k == self.value then + --f.check:Show() + f.text:SetTextColor(1, .82, 0) + else + f.text:SetTextColor(1, 1, 1) + end + f.obj = self + self.dropdown:AddFrame(f) + end + wipe(sortedlist) + end + end + + local function ClearFocus(self) + if self.dropdown then + self.dropdown = AGNW:ReturnDropDownFrame(self.dropdown) + end + end + + local function OnHide(this) + local self = this.obj + if self.dropdown then + self.dropdown = AGNW:ReturnDropDownFrame(self.dropdown) + end + end + + local function Drop_OnEnter(this) + if this.obj.frame.dropButton:IsEnabled() then + this.obj.frame.dropButton.over = true; + this.obj.frame.dropButton:OnButtonStateChanged(); + end + this.obj:Fire("OnEnter") + end + + local function Drop_OnLeave(this) + if this.obj.frame.dropButton:IsEnabled() then + this.obj.frame.dropButton.over = nil; + this.obj.frame.dropButton:OnButtonStateChanged(); + end + this.obj:Fire("OnLeave") + end + + local function Constructor() + local frame = AGNW:GetBaseFrame() + local self = {} + + self.type = widgetType + self.frame = frame + frame.obj = self + frame.dropButton.obj = self + frame.dropButton:SetScript("OnEnter", Drop_OnEnter) + frame.dropButton:SetScript("OnLeave", Drop_OnLeave) + frame.dropButton:SetScript("OnClick", ToggleDrop) + frame:SetScript("OnHide", OnHide) + + self.alignoffset = 31 + + self.OnRelease = OnRelease + self.OnAcquire = OnAcquire + self.ClearFocus = ClearFocus + self.SetText = SetText + self.SetValue = SetValue + self.GetValue = GetValue + self.SetList = SetList + self.SetLabel = SetLabel + self.SetDisabled = SetDisabled + self.AddItem = AddItem + self.SetMultiselect = SetMultiselect + self.GetMultiselect = GetMultiselect + self.SetItemValue = SetItemValue + self.SetItemDisabled = SetItemDisabled + self.ToggleDrop = ToggleDrop + + AceGUI:RegisterAsWidget(self) + return self + end + + AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion) +end diff --git a/Libs/AceGUI-3.0-NosheiWidgets/HighlightWidget.lua b/Libs/AceGUI-3.0-NosheiWidgets/HighlightWidget.lua new file mode 100644 index 0000000..3f976a0 --- /dev/null +++ b/Libs/AceGUI-3.0-NosheiWidgets/HighlightWidget.lua @@ -0,0 +1,250 @@ +-- Widget is based on the AceGUIWidget-DropDown.lua supplied with AceGUI-3.0 +-- Modified from AceGUISharedMediaWidgets-1.0 StatusbarWidget +-- Widget created by Yssaril + +local AceGUI = LibStub("AceGUI-3.0") + +local AGNW = LibStub("AceGUI-3.0-NosheiWidgets-1.0") + +do + local widgetType = "NW_Highlight" + local widgetVersion = 2 + + local contentFrameCache = {} + local function ReturnSelf(self) + self:ClearAllPoints() + self:Hide() + --self.check:Hide() + table.insert(contentFrameCache, self) + end + + local function ContentOnClick(this, button) + local self = this.obj + self:Fire("OnValueChanged", this.text:GetText()) + if self.dropdown then + self.dropdown = AGNW:ReturnDropDownFrame(self.dropdown) + end + end + + local function GetContentLine() + local frame + if next(contentFrameCache) then + frame = table.remove(contentFrameCache) + else + frame = CreateFrame("Button", nil, UIParent) + --frame:SetWidth(200) + frame:SetHeight(26) + --frame:SetHighlightTexture([[Interface\QuestFrame\UI-QuestTitleHighlight]], "ADD") + frame:SetScript("OnClick", ContentOnClick) + --[[local check = frame:CreateTexture("OVERLAY") + check:SetWidth(16) + check:SetHeight(16) + check:SetPoint("LEFT", frame, "LEFT", 1, -1) + check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") + check:Hide() + frame.check = check]] + local highlight = frame:CreateTexture(nil, "OVERLAY") + highlight:SetAtlas("common-dropdown-customize-mouseover", true) + highlight:SetHeight(24) + highlight:ClearAllPoints() + highlight:SetPoint("RIGHT", frame, "RIGHT", -1, 0) + highlight:SetPoint("LEFT", frame, "LEFT", 1, 0) + highlight:SetAlpha(0) + frame.highlight = highlight + local bar = frame:CreateTexture("ARTWORK") + bar:SetHeight(22) + bar:SetPoint("LEFT", frame, "LEFT", 10, 0) + bar:SetPoint("RIGHT", frame, "RIGHT", -10, 0) + frame.bar = bar + local text = frame:CreateFontString(nil, "OVERLAY", "GameFontWhite") + + local font, size = text:GetFont() + text:SetFont(font, size, "OUTLINE") + + text:SetPoint("TOPLEFT", frame, "TOPLEFT", 13, 0) + text:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -2, 0) + text:SetJustifyH("LEFT") + text:SetText("Test Test Test Test Test Test Test") + frame.text = text + frame.ReturnSelf = ReturnSelf + + frame:SetScript("OnEnter", function(self) + self.highlight:SetAlpha(0.25) + end) + frame:SetScript("OnLeave", function(self) + self.highlight:SetAlpha(0) + end) + end + frame:Show() + return frame + end + + local function OnAcquire(self) + self:SetHeight(44) + self:SetWidth(200) + end + + local function OnRelease(self) + self:SetText("") + self:SetLabel("") + self:SetDisabled(false) + + self.value = nil + self.list = nil + self.open = nil + self.hasClose = nil + + self.frame:ClearAllPoints() + self.frame:Hide() + end + + local function SetValue(self, value) -- Set the value to an item in the List. + if self.list then + self:SetText(value or "") + end + self.value = value + end + + local function GetValue(self) + return self.value + end + + local function SetList(self, list) -- Set the list of values for the dropdown (key => value pairs) + self.list = list + end + + + local function SetText(self, text) -- Set the text displayed in the box. + self.frame.dropButton.Text:SetText(text or "") + end + + local function SetLabel(self, text) -- Set the text for the label. + self.frame.label:SetText(text or "") + end + + local function AddItem(self, key, value) -- Add an item to the list. + self.list = self.list or {} + self.list[key] = value + end + local SetItemValue = AddItem -- Set the value of a item in the list. <> + + local function SetMultiselect(self, flag) end -- Toggle multi-selecting. <> + local function GetMultiselect() return false end -- Query the multi-select flag. <> + local function SetItemDisabled(self, key) end -- Disable one item in the list. <> + + local function SetDisabled(self, disabled) -- Disable the widget. + self.disabled = disabled + if disabled then + self.frame:Disable() + else + self.frame:Enable() + end + end + + local function textSort(a, b) + return string.upper(a) < string.upper(b) + end + + local sortedlist = {} + local function ToggleDrop(this) + local self = this.obj + if self.dropdown then + self.dropdown = AGNW:ReturnDropDownFrame(self.dropdown) + AceGUI:ClearFocus() + else + AceGUI:SetFocus(self) + self.dropdown = AGNW:GetDropDownFrame() + local width = self.frame:GetWidth() + self.dropdown:SetPoint("TOPLEFT", self.frame, "BOTTOMLEFT") + self.dropdown:SetPoint("TOPRIGHT", self.frame, "BOTTOMRIGHT", width < 160 and (160 - width) or 0, 0) + for k, v in pairs(self.list) do + sortedlist[#sortedlist + 1] = k + end + table.sort(sortedlist, textSort) + for i, k in ipairs(sortedlist) do + local f = GetContentLine() + f.text:SetText(k) + --print(k) + if k == self.value then + --f.check:Show() + f.text:SetTextColor(1, .82, 0) + else + f.text:SetTextColor(1, 1, 1) + end + + local statusbar = self.list[k] ~= k and self.list[k] + f.bar:SetTexture(statusbar) + f.obj = self + f.dropdown = self.dropdown + self.dropdown:AddFrame(f) + end + wipe(sortedlist) + end + end + + local function ClearFocus(self) + if self.dropdown then + self.dropdown = AGNW:ReturnDropDownFrame(self.dropdown) + end + end + + local function OnHide(this) + local self = this.obj + if self.dropdown then + self.dropdown = AGNW:ReturnDropDownFrame(self.dropdown) + end + end + + local function Drop_OnEnter(this) + if this.obj.frame.dropButton:IsEnabled() then + this.obj.frame.dropButton.over = true; + this.obj.frame.dropButton:OnButtonStateChanged(); + end + this.obj:Fire("OnEnter") + end + + local function Drop_OnLeave(this) + if this.obj.frame.dropButton:IsEnabled() then + this.obj.frame.dropButton.over = nil; + this.obj.frame.dropButton:OnButtonStateChanged(); + end + this.obj:Fire("OnLeave") + end + + local function Constructor() + local frame = AGNW:GetBaseFrame() + local self = {} + + self.type = widgetType + self.frame = frame + frame.obj = self + frame.dropButton.obj = self + frame.dropButton:SetScript("OnEnter", Drop_OnEnter) + frame.dropButton:SetScript("OnLeave", Drop_OnLeave) + frame.dropButton:SetScript("OnClick", ToggleDrop) + frame:SetScript("OnHide", OnHide) + + self.alignoffset = 31 + + self.OnRelease = OnRelease + self.OnAcquire = OnAcquire + self.ClearFocus = ClearFocus + self.SetText = SetText + self.SetValue = SetValue + self.GetValue = GetValue + self.SetList = SetList + self.SetLabel = SetLabel + self.SetDisabled = SetDisabled + self.AddItem = AddItem + self.SetMultiselect = SetMultiselect + self.GetMultiselect = GetMultiselect + self.SetItemValue = SetItemValue + self.SetItemDisabled = SetItemDisabled + self.ToggleDrop = ToggleDrop + + AceGUI:RegisterAsWidget(self) + return self + end + + AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion) +end diff --git a/Libs/AceGUI-3.0-NosheiWidgets/Label-Extended.lua b/Libs/AceGUI-3.0-NosheiWidgets/Label-Extended.lua new file mode 100644 index 0000000..b0f4324 --- /dev/null +++ b/Libs/AceGUI-3.0-NosheiWidgets/Label-Extended.lua @@ -0,0 +1,190 @@ +--[[----------------------------------------------------------------------------- +Label Widget +Displays text and optionally an icon. +Widget is an extension of the Label Widget from AceGUI-3.0 +We've hijacked ImageCoords from AceConfDisplay to be able to extend the new functions to AceConfig + SetImage has been updated to only support SetAtlas + the ImageCoords table has been repurposed to be used for SetVertexColor on the image +This Lib is not for general use outside of my own addons. +-------------------------------------------------------------------------------]] +local Type, Version = "NW_Label", 1 +local AceGUI = LibStub and LibStub("AceGUI-3.0", true) +if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end + +-- Lua APIs +local max, select, pairs = math.max, select, pairs + +-- WoW APIs +local CreateFrame, UIParent = CreateFrame, UIParent + +--[[----------------------------------------------------------------------------- +Support functions +-------------------------------------------------------------------------------]] + +local function UpdateImageAnchor(self) + if self.resizing then return end + local frame = self.frame + local width = frame.width or frame:GetWidth() or 0 + local image = self.image + local label = self.label + local height + + label:ClearAllPoints() + image:ClearAllPoints() + + if self.imageshown then + local imagewidth = image:GetWidth() + if (width - imagewidth) < 200 or (label:GetText() or "") == "" then + -- image goes on top centered when less than 200 width for the text, or if there is no text + image:SetPoint("TOP") + label:SetPoint("TOP", image, "BOTTOM") + label:SetPoint("LEFT") + label:SetWidth(width) + height = image:GetHeight() + label:GetStringHeight() + else + -- image on the left + image:SetPoint("TOPLEFT") + if image:GetHeight() > label:GetStringHeight() then + label:SetPoint("LEFT", image, "RIGHT", 4, 0) + else + label:SetPoint("TOPLEFT", image, "TOPRIGHT", 4, 0) + end + label:SetWidth(width - imagewidth - 4) + height = max(image:GetHeight(), label:GetStringHeight()) + end + else + -- no image shown + label:SetPoint("TOPLEFT") + label:SetWidth(width) + height = label:GetStringHeight() + end + + -- avoid zero-height labels, since they can used as spacers + if not height or height == 0 then + height = 1 + end + + self.resizing = true + frame:SetHeight(height) + frame.height = height + self.resizing = nil +end + +--[[----------------------------------------------------------------------------- +Methods +-------------------------------------------------------------------------------]] +local methods = { + ["OnAcquire"] = function(self) + -- set the flag to stop constant size updates + self.resizing = true + -- height is set dynamically by the text and image size + self:SetWidth(200) + self:SetText() + self:SetImage(nil) + self:SetImageSize(16, 16) + self:SetColor() + self:SetFontObject() + self:SetJustifyH("LEFT") + self:SetJustifyV("TOP") + + -- reset the flag + self.resizing = nil + -- run the update explicitly + UpdateImageAnchor(self) + end, + + -- ["OnRelease"] = nil, + + ["OnWidthSet"] = function(self, width) + UpdateImageAnchor(self) + end, + + ["SetText"] = function(self, text) + if type(text) == "table" then + self:SetColor(unpack(text[2])) + self.label:SetText(text[1]) + else + self.label:SetText(text) + end + UpdateImageAnchor(self) + end, + + ["SetColor"] = function(self, r, g, b) + if not (r and g and b) then + r, g, b = 1, 1, 1 + end + self.label:SetVertexColor(r, g, b) + end, + + ["SetImage"] = function(self, path, imageType, color) + local image = self.image + if imageType == "texture" then + image:SetTexture(path) + else + image:SetAtlas(path, false) + end + + if image:GetTexture() then + self.imageshown = true + if color then + image:SetVertexColor(unpack(color)) + end + else + self.imageshown = nil + end + UpdateImageAnchor(self) + end, + + ["SetFont"] = function(self, font, height, flags) + if not self.fontObject then + self.fontObject = CreateFont("AceGUI30LabelFont" .. AceGUI:GetNextWidgetNum(Type)) + end + self.fontObject:SetFont(font, height, flags) + self:SetFontObject(self.fontObject) + end, + + ["SetFontObject"] = function(self, font) + self.label:SetFontObject(font or GameFontHighlightSmall) + UpdateImageAnchor(self) + end, + + ["SetImageSize"] = function(self, width, height) + self.image:SetWidth(width) + self.image:SetHeight(height) + UpdateImageAnchor(self) + end, + + ["SetJustifyH"] = function(self, justifyH) + self.label:SetJustifyH(justifyH) + end, + + ["SetJustifyV"] = function(self, justifyV) + self.label:SetJustifyV(justifyV) + end, +} + +--[[----------------------------------------------------------------------------- +Constructor +-------------------------------------------------------------------------------]] +local function Constructor() + local frame = CreateFrame("Frame", nil, UIParent) + frame:Hide() + + local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontHighlightSmall") + local image = frame:CreateTexture(nil, "BACKGROUND") + + -- create widget + local widget = { + label = label, + image = image, + frame = frame, + type = Type + } + for method, func in pairs(methods) do + widget[method] = func + end + + return AceGUI:RegisterAsWidget(widget) +end + +AceGUI:RegisterWidgetType(Type, Constructor, Version) diff --git a/Libs/AceGUI-3.0-NosheiWidgets/Slider-Extended.lua b/Libs/AceGUI-3.0-NosheiWidgets/Slider-Extended.lua new file mode 100644 index 0000000..ba8b426 --- /dev/null +++ b/Libs/AceGUI-3.0-NosheiWidgets/Slider-Extended.lua @@ -0,0 +1,283 @@ +--[[----------------------------------------------------------------------------- +Slider Widget +Graphical Slider, like, for Range values. +Widget is an extension of the Slider Widget from AceGUI-3.0 +Updated to use newer atlas files instead of old textures +-------------------------------------------------------------------------------]] +local Type, Version = "NW_Slider", 1 +local AceGUI = LibStub and LibStub("AceGUI-3.0", true) +if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end + +-- Lua APIs +local min, max, floor = math.min, math.max, math.floor +local tonumber, pairs = tonumber, pairs + +-- WoW APIs +local PlaySound = PlaySound +local CreateFrame, UIParent = CreateFrame, UIParent + +--[[----------------------------------------------------------------------------- +Support functions +-------------------------------------------------------------------------------]] +local function UpdateText(self) + local value = self.value or 0 + if self.ispercent then + self.editbox:SetText(("%s%%"):format(floor(value * 1000 + 0.5) / 10)) + else + self.editbox:SetText(floor(value * 100 + 0.5) / 100) + end +end + +local function UpdateLabels(self) + local min_value, max_value = (self.min or 0), (self.max or 100) + if self.ispercent then + self.lowtext:SetFormattedText("%s%%", (min_value * 100)) + self.hightext:SetFormattedText("%s%%", (max_value * 100)) + else + self.lowtext:SetText(min_value) + self.hightext:SetText(max_value) + end +end + +--[[----------------------------------------------------------------------------- +Scripts +-------------------------------------------------------------------------------]] +local function Control_OnEnter(frame) + frame.obj:Fire("OnEnter") +end + +local function Control_OnLeave(frame) + frame.obj:Fire("OnLeave") +end + +local function Frame_OnMouseDown(frame) + frame.obj.slider:EnableMouseWheel(true) + AceGUI:ClearFocus() +end + +local function Slider_OnValueChanged(frame, newvalue) + local self = frame.obj + if not frame.setup then + if self.step and self.step > 0 then + local min_value = self.min or 0 + newvalue = floor((newvalue - min_value) / self.step + 0.5) * self.step + min_value + end + if newvalue ~= self.value and not self.disabled then + self.value = newvalue + self:Fire("OnValueChanged", newvalue) + end + if self.value then + UpdateText(self) + end + end +end + +local function Slider_OnMouseUp(frame) + local self = frame.obj + self:Fire("OnMouseUp", self.value) +end + +local function Slider_OnMouseWheel(frame, v) + local self = frame.obj + if not self.disabled then + local value = self.value + if v > 0 then + value = min(value + (self.step or 1), self.max) + else + value = max(value - (self.step or 1), self.min) + end + self.slider:SetValue(value) + end +end + +local function EditBox_OnEscapePressed(frame) + frame:ClearFocus() +end + +local function EditBox_OnEnterPressed(frame) + local self = frame.obj + local value = frame:GetText() + if self.ispercent then + value = value:gsub('%%', '') + value = tonumber(value) / 100 + else + value = tonumber(value) + end + + if value then + PlaySound(856) -- SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON + self.slider:SetValue(value) + self:Fire("OnMouseUp", value) + end +end + +local function EditBox_OnEnter(frame) + frame:SetBackdropBorderColor(0.5, 0.5, 0.5, 1) +end + +local function EditBox_OnLeave(frame) + frame:SetBackdropBorderColor(0.3, 0.3, 0.3, 0.8) +end + +--[[----------------------------------------------------------------------------- +Methods +-------------------------------------------------------------------------------]] +local methods = { + ["OnAcquire"] = function(self) + self:SetWidth(200) + self:SetHeight(44) + self:SetDisabled(false) + self:SetIsPercent(nil) + self:SetSliderValues(0, 100, 1) + self:SetValue(0) + self.slider:EnableMouseWheel(false) + end, + + -- ["OnRelease"] = nil, + + ["SetDisabled"] = function(self, disabled) + self.disabled = disabled + if disabled then + self.slider:EnableMouse(false) + self.label:SetTextColor(.5, .5, .5) + self.hightext:SetTextColor(.5, .5, .5) + self.lowtext:SetTextColor(.5, .5, .5) + --self.valuetext:SetTextColor(.5, .5, .5) + self.editbox:SetTextColor(.5, .5, .5) + self.editbox:EnableMouse(false) + self.editbox:ClearFocus() + else + self.slider:EnableMouse(true) + self.label:SetTextColor(1, .82, 0) + self.hightext:SetTextColor(1, 1, 1) + self.lowtext:SetTextColor(1, 1, 1) + --self.valuetext:SetTextColor(1, 1, 1) + self.editbox:SetTextColor(1, 1, 1) + self.editbox:EnableMouse(true) + end + end, + + ["SetValue"] = function(self, value) + self.slider.setup = true + self.slider:SetValue(value) + self.value = value + UpdateText(self) + self.slider.setup = nil + end, + + ["GetValue"] = function(self) + return self.value + end, + + ["SetLabel"] = function(self, text) + self.label:SetText(text) + end, + + ["SetSliderValues"] = function(self, min_value, max_value, step) + local frame = self.slider + frame.setup = true + self.min = min_value + self.max = max_value + self.step = step + frame:SetMinMaxValues(min_value or 0, max_value or 100) + UpdateLabels(self) + frame:SetValueStep(step or 1) + if self.value then + frame:SetValue(self.value) + end + frame.setup = nil + end, + + ["SetIsPercent"] = function(self, value) + self.ispercent = value + UpdateLabels(self) + UpdateText(self) + end +} + +--[[----------------------------------------------------------------------------- +Constructor +-------------------------------------------------------------------------------]] +local SliderBackdrop = { + bgFile = "Interface\\Buttons\\UI-SliderBar-Background", + edgeFile = "Interface\\Buttons\\UI-SliderBar-Border", + tile = true, + tileSize = 8, + edgeSize = 8, + insets = { left = 3, right = 3, top = 6, bottom = 6 } +} + +local ManualBackdrop = { + bgFile = "Interface\\ChatFrame\\ChatFrameBackground", + edgeFile = "Interface\\ChatFrame\\ChatFrameBackground", + tile = true, + edgeSize = 1, + tileSize = 5, +} + +local function Constructor() + local frame = CreateFrame("Frame", nil, UIParent) + + frame:EnableMouse(true) + frame:SetScript("OnMouseDown", Frame_OnMouseDown) + + local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal") + label:SetPoint("TOPLEFT") + label:SetPoint("TOPRIGHT") + label:SetJustifyH("CENTER") + label:SetHeight(15) + + local slider = CreateFrame("Slider", nil, frame, "MinimalSliderTemplate") + slider:SetPoint("TOP", label, "BOTTOM") + slider:SetPoint("LEFT", 3, 0) + slider:SetPoint("RIGHT", -3, 0) + slider:SetMinMaxValues(0, 100) + slider:SetValueStep(1) + slider:SetValue(0) + slider:SetScript("OnValueChanged", Slider_OnValueChanged) + slider:SetScript("OnEnter", Control_OnEnter) + slider:SetScript("OnLeave", Control_OnLeave) + slider:SetScript("OnMouseUp", Slider_OnMouseUp) + slider:SetScript("OnMouseWheel", Slider_OnMouseWheel) + + local lowtext = slider:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall") + lowtext:SetPoint("TOPLEFT", slider, "BOTTOMLEFT", 2, 2) + + local hightext = slider:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall") + hightext:SetPoint("TOPRIGHT", slider, "BOTTOMRIGHT", -2, 2) + + local editbox = CreateFrame("EditBox", nil, frame, "BackdropTemplate") + editbox:SetAutoFocus(false) + editbox:SetFontObject(GameFontHighlightSmall) + editbox:SetPoint("TOP", slider, "BOTTOM") + editbox:SetHeight(14) + editbox:SetWidth(70) + editbox:SetJustifyH("CENTER") + editbox:EnableMouse(true) + editbox:SetBackdrop(ManualBackdrop) + editbox:SetBackdropColor(0, 0, 0, 0.5) + editbox:SetBackdropBorderColor(0.3, 0.3, 0.30, 0.80) + editbox:SetScript("OnEnter", EditBox_OnEnter) + editbox:SetScript("OnLeave", EditBox_OnLeave) + editbox:SetScript("OnEnterPressed", EditBox_OnEnterPressed) + editbox:SetScript("OnEscapePressed", EditBox_OnEscapePressed) + + local widget = { + label = label, + slider = slider, + lowtext = lowtext, + hightext = hightext, + editbox = editbox, + alignoffset = 25, + frame = frame, + type = Type + } + for method, func in pairs(methods) do + widget[method] = func + end + slider.obj, editbox.obj = widget, widget + + return AceGUI:RegisterAsWidget(widget) +end + +AceGUI:RegisterWidgetType(Type, Constructor, Version) diff --git a/Libs/AceGUI-3.0-NosheiWidgets/SoundWidget.lua b/Libs/AceGUI-3.0-NosheiWidgets/SoundWidget.lua new file mode 100644 index 0000000..9f7f189 --- /dev/null +++ b/Libs/AceGUI-3.0-NosheiWidgets/SoundWidget.lua @@ -0,0 +1,293 @@ +-- Widget is based on the AceGUIWidget-DropDown.lua supplied with AceGUI-3.0 +-- Widget created by Yssaril +-- Forked from AceGUISharedMediaWidgets-1.0 to modify for my own use by Noshei + +local AceGUI = LibStub("AceGUI-3.0") +local Media = LibStub("LibSharedMedia-3.0") + +local AGNW = LibStub("AceGUI-3.0-NosheiWidgets-1.0") + +do + local widgetType = "NW_Sound" + local widgetVersion = 1 + + local contentFrameCache = {} + local function ReturnSelf(self) + self:ClearAllPoints() + self:Hide() + --self.check:Hide() + table.insert(contentFrameCache, self) + end + + local function ContentOnClick(this, button) + local self = this.obj + self:Fire("OnValueChanged", this.text:GetText()) + if self.dropdown then + self.dropdown = AGNW:ReturnDropDownFrame(self.dropdown) + end + end + + local function ContentSpeakerOnClick(this, button) + local self = this.frame.obj + local sound = this.frame.text:GetText() + PlaySoundFile(self.list[sound] ~= sound and self.list[sound] or Media:Fetch('sound', sound), "Master") + end + + local function GetContentLine() + local frame + if next(contentFrameCache) then + frame = table.remove(contentFrameCache) + else + frame = CreateFrame("Button", nil, UIParent) + --frame:SetWidth(200) + frame:SetHeight(18) + --frame:SetHighlightTexture([[Interface\QuestFrame\UI-QuestTitleHighlight]], "ADD") + frame:SetScript("OnClick", ContentOnClick) + --[[local check = frame:CreateTexture("OVERLAY") + check:SetWidth(16) + check:SetHeight(16) + check:SetPoint("LEFT", frame, "LEFT", 1, -1) + check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") + check:Hide() + frame.check = check]] + + local highlight = frame:CreateTexture(nil, "OVERLAY") + highlight:SetAtlas("common-dropdown-customize-mouseover", true) + highlight:SetHeight(18) + highlight:ClearAllPoints() + highlight:SetPoint("RIGHT", frame, "RIGHT", -1, 0) + highlight:SetPoint("LEFT", frame, "LEFT", 1, 0) + highlight:SetAlpha(0) + frame.highlight = highlight + + local soundbutton = CreateFrame("Button", nil, frame) + soundbutton:SetWidth(16) + soundbutton:SetHeight(16) + soundbutton:SetPoint("RIGHT", frame, "RIGHT", -3, 0) + soundbutton.frame = frame + soundbutton:SetScript("OnClick", ContentSpeakerOnClick) + frame.soundbutton = soundbutton + + local speaker = soundbutton:CreateTexture(nil, "BACKGROUND") + speaker:SetTexture("Interface\\Common\\VoiceChat-Speaker") + speaker:SetAllPoints(soundbutton) + frame.speaker = speaker + local speakeron = soundbutton:CreateTexture(nil, "HIGHLIGHT") + speakeron:SetTexture("Interface\\Common\\VoiceChat-On") + speakeron:SetAllPoints(soundbutton) + frame.speakeron = speakeron + + local text = frame:CreateFontString(nil, "OVERLAY", "GameFontWhite") + text:SetPoint("TOPLEFT", frame, "TOPLEFT", 8, 0) + text:SetPoint("BOTTOMRIGHT", soundbutton, "BOTTOMLEFT", -2, 0) + text:SetJustifyH("LEFT") + text:SetText("Test Test Test Test Test Test Test") + frame.text = text + frame.ReturnSelf = ReturnSelf + + frame:SetScript("OnEnter", function(self) + self.highlight:SetAlpha(0.25) + end) + frame:SetScript("OnLeave", function(self) + self.highlight:SetAlpha(0) + end) + end + frame:Show() + return frame + end + + local function OnAcquire(self) + self:SetHeight(44) + self:SetWidth(200) + end + + local function OnRelease(self) + self:SetText("") + self:SetLabel("") + self:SetDisabled(false) + + self.value = nil + self.list = nil + self.open = nil + self.hasClose = nil + + self.frame:ClearAllPoints() + self.frame:Hide() + end + + local function SetValue(self, value) -- Set the value to an item in the List. + if self.list then + self:SetText(value or "") + end + self.value = value + end + + local function GetValue(self) + return self.value + end + + local function SetList(self, list) -- Set the list of values for the dropdown (key => value pairs) + self.list = list or Media:HashTable("sound") + end + + local function SetText(self, text) -- Set the text displayed in the box. + --self.frame.text:SetText(text or "") + self.frame.dropButton.Text:SetText(text or "") + end + + local function SetLabel(self, text) -- Set the text for the label. + self.frame.label:SetText(text or "") + end + + local function AddItem(self, key, value) -- Add an item to the list. + self.list = self.list or {} + self.list[key] = value + end + local SetItemValue = AddItem -- Set the value of a item in the list. <> + + local function SetMultiselect(self, flag) end -- Toggle multi-selecting. <> + local function GetMultiselect() return false end -- Query the multi-select flag. <> + local function SetItemDisabled(self, key) end -- Disable one item in the list. <> + + local function SetDisabled(self, disabled) -- Disable the widget. + self.disabled = disabled + if disabled then + self.frame:Disable() + self.speaker:SetDesaturated(true) + self.speakeron:SetDesaturated(true) + else + self.frame:Enable() + self.speaker:SetDesaturated(false) + self.speakeron:SetDesaturated(false) + end + end + + local function textSort(a, b) + return string.upper(a) < string.upper(b) + end + + local sortedlist = {} + local function ToggleDrop(this) + local self = this.obj + if self.dropdown then + self.dropdown = AGNW:ReturnDropDownFrame(self.dropdown) + AceGUI:ClearFocus() + else + AceGUI:SetFocus(self) + self.dropdown = AGNW:GetDropDownFrame() + local width = self.frame:GetWidth() + self.dropdown:SetPoint("TOPLEFT", self.frame, "BOTTOMLEFT") + self.dropdown:SetPoint("TOPRIGHT", self.frame, "BOTTOMRIGHT", width < 160 and (160 - width) or 0, 0) + for k, v in pairs(self.list) do + sortedlist[#sortedlist + 1] = k + end + table.sort(sortedlist, textSort) + for i, k in ipairs(sortedlist) do + local f = GetContentLine() + f.text:SetText(k) + if k == self.value then + --f.check:Show() + f.text:SetTextColor(1, .82, 0) + else + f.text:SetTextColor(1, 1, 1) + end + f.obj = self + self.dropdown:AddFrame(f) + end + wipe(sortedlist) + end + end + + local function ClearFocus(self) + if self.dropdown then + self.dropdown = AGNW:ReturnDropDownFrame(self.dropdown) + end + end + + local function OnHide(this) + local self = this.obj + if self.dropdown then + self.dropdown = AGNW:ReturnDropDownFrame(self.dropdown) + end + end + + local function Drop_OnEnter(this) + if this.obj.frame.dropButton:IsEnabled() then + this.obj.frame.dropButton.over = true; + this.obj.frame.dropButton:OnButtonStateChanged(); + end + this.obj:Fire("OnEnter") + end + + local function Drop_OnLeave(this) + if this.obj.frame.dropButton:IsEnabled() then + this.obj.frame.dropButton.over = nil; + this.obj.frame.dropButton:OnButtonStateChanged(); + end + this.obj:Fire("OnLeave") + end + + local function WidgetPlaySound(this) + local self = this.obj + local sound = self.frame.dropButton.Text:GetText() + PlaySoundFile(self.list[sound] ~= sound and self.list[sound] or Media:Fetch('sound', sound), "Master") + end + + local function Constructor() + local frame = AGNW:GetBaseFrame() + local self = {} + + self.type = widgetType + self.frame = frame + frame.obj = self + frame.dropButton.obj = self + frame.dropButton:SetScript("OnEnter", Drop_OnEnter) + frame.dropButton:SetScript("OnLeave", Drop_OnLeave) + frame.dropButton:SetScript("OnClick", ToggleDrop) + frame:SetScript("OnHide", OnHide) + + + local soundbutton = CreateFrame("Button", nil, frame) + soundbutton:SetWidth(16) + soundbutton:SetHeight(16) + soundbutton:SetFrameStrata("HIGH") + soundbutton:SetPoint("LEFT", frame.dropButton, "LEFT", 10, 0) + soundbutton:SetScript("OnClick", WidgetPlaySound) + soundbutton.obj = self + self.soundbutton = soundbutton + frame.dropButton.Text:SetPoint("LEFT", soundbutton, "RIGHT", 2, 0) + + + local speaker = soundbutton:CreateTexture(nil, "BACKGROUND") + speaker:SetTexture("Interface\\Common\\VoiceChat-Speaker") + speaker:SetAllPoints(soundbutton) + self.speaker = speaker + local speakeron = soundbutton:CreateTexture(nil, "HIGHLIGHT") + speakeron:SetTexture("Interface\\Common\\VoiceChat-On") + speakeron:SetAllPoints(soundbutton) + self.speakeron = speakeron + + self.alignoffset = 31 + + self.OnRelease = OnRelease + self.OnAcquire = OnAcquire + self.ClearFocus = ClearFocus + self.SetText = SetText + self.SetValue = SetValue + self.GetValue = GetValue + self.SetList = SetList + self.SetLabel = SetLabel + self.SetDisabled = SetDisabled + self.AddItem = AddItem + self.SetMultiselect = SetMultiselect + self.GetMultiselect = GetMultiselect + self.SetItemValue = SetItemValue + self.SetItemDisabled = SetItemDisabled + self.ToggleDrop = ToggleDrop + + AceGUI:RegisterAsWidget(self) + return self + end + + AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion) +end diff --git a/Libs/AceGUI-3.0-NosheiWidgets/prototypes.lua b/Libs/AceGUI-3.0-NosheiWidgets/prototypes.lua new file mode 100644 index 0000000..0a3c54b --- /dev/null +++ b/Libs/AceGUI-3.0-NosheiWidgets/prototypes.lua @@ -0,0 +1,284 @@ +-- Widget created by Yssaril +local DataVersion = 9004 +local AGNW = LibStub:NewLibrary("AceGUI-3.0-NosheiWidgets-1.0", DataVersion) + +if not AGNW then + return -- already loaded and no upgrade necessary +end + +local AceGUI = LibStub("AceGUI-3.0") +local Media = LibStub("LibSharedMedia-3.0") + +AGNW = AGNW or {} + +AceGUIWidgetLSMlists = { + ['font'] = Media:HashTable("font"), + ['sound'] = Media:HashTable("sound"), + ['statusbar'] = Media:HashTable("statusbar"), + ['border'] = Media:HashTable("border"), + ['background'] = Media:HashTable("background"), +} + +do + local function disable(frame) + frame.label:SetTextColor(.5, .5, .5) + frame.dropButton.Text:SetTextColor(.5, .5, .5) + frame.dropButton:Disable() + if frame.displayButtonFont then + frame.displayButtonFont:SetTextColor(.5, .5, .5) + frame.displayButton:Disable() + end + end + + local function enable(frame) + frame.label:SetTextColor(1, .82, 0) + frame.dropButton.Text:SetTextColor(1, .82, 0) + frame.dropButton:Enable() + if frame.displayButtonFont then + frame.displayButtonFont:SetTextColor(1, 1, 1) + frame.displayButton:Enable() + end + end + + local displayButtonBackdrop = { + edgeFile = "Interface/Tooltips/UI-Tooltip-Border", + tile = true, + tileSize = 16, + edgeSize = 16, + insets = { left = 4, right = 4, top = 4, bottom = 4 }, + } + + -- create or retrieve BaseFrame + function AGNW:GetBaseFrame() + local frame = CreateFrame("Frame", nil, UIParent) + frame:SetHeight(44) + frame:SetWidth(200) + + local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + label:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, 0) + label:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, 0) + label:SetJustifyH("LEFT") + label:SetHeight(18) + label:SetText("") + frame.label = label + + local dropButton = CreateFrame("DropdownButton", nil, frame, "WowStyle2DropdownTemplate") + dropButton:ClearAllPoints() + dropButton:SetPoint("TOPLEFT", frame, "TOPLEFT", 3, -16) + dropButton:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -5, 0) + frame.dropButton = dropButton + --[[dropdown:SetScript("OnHide", nil) + dropdown:SetScript("OnEnter", Control_OnEnter) + dropdown:SetScript("OnLeave", Control_OnLeave) + dropdown:SetScript("OnClick", Dropdown_TogglePullout)]] + + --[[local DLeft = frame:CreateTexture(nil, "ARTWORK") + DLeft:SetWidth(25) + DLeft:SetHeight(64) + DLeft:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", -17, -21) + DLeft:SetTexture("Interface\\Glues\\CharacterCreate\\CharacterCreate-LabelFrame") + DLeft:SetTexCoord(0, 0.1953125, 0, 1) + frame.DLeft = DLeft + + local DRight = frame:CreateTexture(nil, "ARTWORK") + DRight:SetWidth(25) + DRight:SetHeight(64) + DRight:SetPoint("TOP", DLeft, "TOP") + DRight:SetPoint("RIGHT", frame, "RIGHT", 17, 0) + DRight:SetTexture("Interface\\Glues\\CharacterCreate\\CharacterCreate-LabelFrame") + DRight:SetTexCoord(0.8046875, 1, 0, 1) + frame.DRight = DRight + + local DMiddle = frame:CreateTexture(nil, "ARTWORK") + DMiddle:SetHeight(64) + DMiddle:SetPoint("TOP", DLeft, "TOP") + DMiddle:SetPoint("LEFT", DLeft, "RIGHT") + DMiddle:SetPoint("RIGHT", DRight, "LEFT") + DMiddle:SetTexture("Interface\\Glues\\CharacterCreate\\CharacterCreate-LabelFrame") + DMiddle:SetTexCoord(0.1953125, 0.8046875, 0, 1) + frame.DMiddle = DMiddle + + local text = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall") + text:SetPoint("RIGHT", DRight, "RIGHT", -43, 1) + text:SetPoint("LEFT", DLeft, "LEFT", 26, 1) + text:SetJustifyH("RIGHT") + text:SetHeight(18) + text:SetText("") + frame.text = text + + local dropButton = CreateFrame("Button", nil, frame) + dropButton:SetWidth(24) + dropButton:SetHeight(24) + dropButton:SetPoint("TOPRIGHT", DRight, "TOPRIGHT", -16, -18) + dropButton:SetNormalTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Up") + dropButton:SetPushedTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Down") + dropButton:SetDisabledTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Disabled") + dropButton:SetHighlightTexture("Interface\\Buttons\\UI-Common-MouseHilight", "ADD") + frame.dropButton = dropButton]] + + frame.Disable = disable + frame.Enable = enable + return frame + end + + function AGNW:GetBaseFrameWithWindow() + local frame = self:GetBaseFrame() + + local displayButton = CreateFrame("Button", nil, frame, BackdropTemplateMixin and "BackdropTemplate") + displayButton:SetHeight(42) + displayButton:SetWidth(42) + displayButton:SetPoint("TOPLEFT", frame, "TOPLEFT", 1, -2) + displayButton:SetBackdrop(displayButtonBackdrop) + displayButton:SetBackdropBorderColor(.5, .5, .5) + frame.displayButton = displayButton + + frame.label:SetPoint("TOPLEFT", displayButton, "TOPRIGHT", 1, 2) + + --frame.DLeft:SetPoint("BOTTOMLEFT", displayButton, "BOTTOMRIGHT", -17, -20) + + return frame + end +end + +do + local sliderBackdrop = { + ["bgFile"] = "Interface\\Buttons\\UI-SliderBar-Background", + ["edgeFile"] = "Interface\\Buttons\\UI-SliderBar-Border", + ["tile"] = true, + ["edgeSize"] = 8, + ["tileSize"] = 8, + ["insets"] = { + ["left"] = 3, + ["right"] = 3, + ["top"] = 3, + ["bottom"] = 3, + }, + } + local frameBackdrop = { + bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background-Dark", + edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", + tile = true, + tileSize = 32, + edgeSize = 32, + insets = { left = 11, right = 12, top = 12, bottom = 9 }, + } + + local function OnMouseWheel(self, dir) + self.slider:SetValue(self.slider:GetValue() + (15 * dir * -1)) + end + + local function AddFrame(self, frame) + frame:SetParent(self.contentframe) + frame:SetFrameStrata(self:GetFrameStrata()) + frame:SetFrameLevel(self:GetFrameLevel() + 100) + + if next(self.contentRepo) then + frame:SetPoint("TOPLEFT", self.contentRepo[#self.contentRepo], "BOTTOMLEFT", 0, 0) + frame:SetPoint("RIGHT", self.contentframe, "RIGHT", 0, 0) + self.contentframe:SetHeight(self.contentframe:GetHeight() + frame:GetHeight()) + self.contentRepo[#self.contentRepo + 1] = frame + else + self.contentframe:SetHeight(frame:GetHeight()) + frame:SetPoint("TOPLEFT", self.contentframe, "TOPLEFT", 0, 0) + frame:SetPoint("RIGHT", self.contentframe, "RIGHT", 0, 0) + self.contentRepo[1] = frame + end + + if self.contentframe:GetHeight() > UIParent:GetHeight() * 2 / 5 - 20 then + self.scrollframe:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -28, 12) + self:SetHeight(UIParent:GetHeight() * 2 / 5) + self.slider:Show() + self:SetScript("OnMouseWheel", OnMouseWheel) + self.slider:SetMinMaxValues(0, self.contentframe:GetHeight() - self.scrollframe:GetHeight()) + else + self.scrollframe:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -14, 12) + self:SetHeight(self.contentframe:GetHeight() + 25) + self.slider:Hide() + self:SetScript("OnMouseWheel", nil) + self.slider:SetMinMaxValues(0, 0) + end + self.contentframe:SetWidth(self.scrollframe:GetWidth()) + end + + local function ClearFrames(self) + for i, frame in ipairs(self.contentRepo) do + frame:ReturnSelf() + self.contentRepo[i] = nil + end + end + + local function slider_OnValueChanged(self, value) + self.frame.scrollframe:SetVerticalScroll(value) + end + + local DropDownCache = {} + function AGNW:GetDropDownFrame() + local frame + if next(DropDownCache) then + frame = table.remove(DropDownCache) + else + frame = CreateFrame("Frame", nil, UIParent) --, BackdropTemplateMixin and "BackdropTemplate") + frame:SetClampedToScreen(true) + frame:SetWidth(188) + --frame:SetBackdrop(frameBackdrop) + frame:SetFrameStrata("TOOLTIP") + frame:EnableMouseWheel(true) + + + local backdrop = frame:CreateTexture(nil, "BACKGROUND") + backdrop:SetAtlas("common-dropdown-bg") + backdrop:SetAllPoints(frame) + frame.backdrop = backdrop + + local contentframe = CreateFrame("Frame", nil, frame) + contentframe:SetWidth(160) + contentframe:SetHeight(0) + frame.contentframe = contentframe + + local scrollframe = CreateFrame("ScrollFrame", nil, frame) + scrollframe:SetWidth(160) + scrollframe:SetPoint("TOPLEFT", frame, "TOPLEFT", 14, -13) + scrollframe:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -14, 12) + scrollframe:SetScrollChild(contentframe) + frame.scrollframe = scrollframe + + contentframe:SetPoint("TOPLEFT", scrollframe) + contentframe:SetPoint("TOPRIGHT", scrollframe) + + local bgTex = frame:CreateTexture(nil, "ARTWORK") + bgTex:SetAllPoints(scrollframe) + frame.bgTex = bgTex + + frame.AddFrame = AddFrame + frame.ClearFrames = ClearFrames + frame.contentRepo = {} -- store all our frames in here so we can get rid of them later + + local slider = CreateFrame("Slider", nil, scrollframe, BackdropTemplateMixin and "BackdropTemplate") + slider:SetOrientation("VERTICAL") + slider:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -14, -10) + slider:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -14, 10) + slider:SetBackdrop(sliderBackdrop) + slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical") + slider:SetMinMaxValues(0, 1) + --slider:SetValueStep(1) + slider:SetWidth(12) + slider.frame = frame + slider:SetScript("OnValueChanged", slider_OnValueChanged) + frame.slider = slider + end + frame:SetHeight(UIParent:GetHeight() * 2 / 5) + frame.slider:SetValue(0) + frame:Show() + return frame + end + + function AGNW:ReturnDropDownFrame(frame) + ClearFrames(frame) + frame:ClearAllPoints() + frame:Hide() + frame.backdrop:SetAtlas("common-dropdown-bg") + frame.bgTex:SetTexture(nil) + table.insert(DropDownCache, frame) + return nil + end +end diff --git a/Libs/AceGUI-3.0-NosheiWidgets/widget.xml b/Libs/AceGUI-3.0-NosheiWidgets/widget.xml index bb1088a..4043f1f 100644 --- a/Libs/AceGUI-3.0-NosheiWidgets/widget.xml +++ b/Libs/AceGUI-3.0-NosheiWidgets/widget.xml @@ -1,4 +1,12 @@ +