3bc290dcb1
- Added a new feature which allows syncing between multiple accounts (in beta) - Added new consumes to the itemlist - Added materials or objectives needed to make the consumes in the tooltips - Fixed some wrong ID's in the itemlist - Increased Performance in item scanning - Added class color codes to the preset lists and ordered the items better
4007 lines
154 KiB
Lua
4007 lines
154 KiB
Lua
-- Onload & Click Functionality -------------------------------------------------------------------------
|
|
WindowWidth = 350
|
|
|
|
function ConsumesManager_OnLoad(self)
|
|
self:RegisterForDrag("LeftButton")
|
|
self:SetScript("OnDragStart", function() ConsumesManager_OnDragStart(self) end)
|
|
self:SetScript("OnDragStop", function() ConsumesManager_OnDragStop(self) end)
|
|
end
|
|
|
|
function ConsumesManager_HandleClick(self, button)
|
|
if not self then return end
|
|
if button == "LeftButton" and not IsShiftKeyDown() then
|
|
if ConsumesManager_MainFrame and ConsumesManager_MainFrame:IsShown() then
|
|
ConsumesManager_MainFrame:Hide()
|
|
else
|
|
ConsumesManager_ShowMainWindow()
|
|
end
|
|
end
|
|
end
|
|
|
|
function ConsumesManager_OnDragStart(self)
|
|
if IsShiftKeyDown() then
|
|
self:StartMoving()
|
|
self.isMoving = true
|
|
end
|
|
end
|
|
|
|
function ConsumesManager_OnDragStop(self)
|
|
if self and self.isMoving then
|
|
self:StopMovingOrSizing()
|
|
self.isMoving = false
|
|
end
|
|
end
|
|
|
|
|
|
if not ConsumesManager_Options then
|
|
ConsumesManager_Options = {}
|
|
end
|
|
if not ConsumesManager_SelectedItems then
|
|
ConsumesManager_SelectedItems = {}
|
|
end
|
|
if not ConsumesManager_Data then
|
|
ConsumesManager_Data = {}
|
|
end
|
|
|
|
-- Event frame for updating data ------------------------------------------------------------------------
|
|
local ConsumesManager_EventFrame = CreateFrame("Frame")
|
|
ConsumesManager_EventFrame:RegisterEvent("PLAYER_LOGIN")
|
|
ConsumesManager_EventFrame:RegisterEvent("BAG_UPDATE")
|
|
ConsumesManager_EventFrame:RegisterEvent("BANKFRAME_OPENED")
|
|
ConsumesManager_EventFrame:RegisterEvent("PLAYERBANKSLOTS_CHANGED")
|
|
ConsumesManager_EventFrame:RegisterEvent("ITEM_LOCK_CHANGED")
|
|
ConsumesManager_EventFrame:RegisterEvent("MAIL_SHOW")
|
|
ConsumesManager_EventFrame:RegisterEvent("MAIL_INBOX_UPDATE")
|
|
ConsumesManager_EventFrame:RegisterEvent("MAIL_CLOSED")
|
|
|
|
ConsumesManager_EventFrame:SetScript("OnEvent", function()
|
|
if event == "PLAYER_LOGIN" then
|
|
if ConsumesManager_Options and ConsumesManager_Options.Channel and ConsumesManager_Options.Password then
|
|
local channelName = DecodeMessage(ConsumesManager_Options.Channel)
|
|
local channelPassword = DecodeMessage(ConsumesManager_Options.Password)
|
|
JoinChannelByName(channelName, channelPassword)
|
|
SetChannelPassword(channelName, channelPassword)
|
|
MultiAccountChannelAnnounce = "|cffffffff" .. GetAddOnMetadata("ConsumesManager", "Title") .. ":|r |cffffffffJoined|r |cffffc0c0[" .. channelName .. "]|r|cffffffff. Multi-account synchronization |cff00ff00enabled|r|cffffffff.|r"
|
|
ReadData("start")
|
|
else
|
|
MultiAccountChannelAnnounce = "|cffffffff" .. GetAddOnMetadata("ConsumesManager", "Title") .. ":|r Multi-account synchronization |cffff0000disabled|r|cffffffff. Check the addon options for setup.|r"
|
|
ReadData("stop")
|
|
end
|
|
|
|
local delayFrame = CreateFrame("Frame")
|
|
local elapsed = 0
|
|
local delay = 1
|
|
|
|
delayFrame:SetScript("OnUpdate", function()
|
|
elapsed = elapsed + arg1 -- arg1 provides the time since the last frame
|
|
if elapsed >= delay then
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cff00ff00" .. GetAddOnMetadata("ConsumesManager", "Title") .. "|r |cffaaaaaa(v" .. GetAddOnMetadata("ConsumesManager", "Version") .. ")|r |cffffffffLoaded!|r")
|
|
DEFAULT_CHAT_FRAME:AddMessage(MultiAccountChannelAnnounce)
|
|
delayFrame:SetScript("OnUpdate", nil) -- Stop the OnUpdate script
|
|
end
|
|
end)
|
|
|
|
ConsumesManager_ScanPlayerInventory()
|
|
ConsumesManager_ScanPlayerBank()
|
|
ConsumesManager_ScanPlayerMail()
|
|
elseif event == "BAG_UPDATE" then
|
|
ConsumesManager_ScanPlayerInventory()
|
|
if BankFrame and BankFrame:IsShown() then
|
|
ConsumesManager_ScanPlayerBank()
|
|
end
|
|
if MailFrame and MailFrame:IsShown() then
|
|
ConsumesManager_ScanPlayerMail()
|
|
end
|
|
elseif event == "BANKFRAME_OPENED" then
|
|
ConsumesManager_ScanPlayerBank()
|
|
elseif event == "PLAYERBANKSLOTS_CHANGED" then
|
|
ConsumesManager_ScanPlayerBank()
|
|
ConsumesManager_ScanPlayerInventory()
|
|
elseif event == "ITEM_LOCK_CHANGED" then
|
|
if BankFrame and BankFrame:IsShown() then
|
|
ConsumesManager_ScanPlayerInventory()
|
|
ConsumesManager_ScanPlayerBank()
|
|
end
|
|
if MailFrame and MailFrame:IsShown() then
|
|
ConsumesManager_ScanPlayerInventory()
|
|
ConsumesManager_ScanPlayerMail()
|
|
end
|
|
elseif event == "MAIL_SHOW" or event == "MAIL_INBOX_UPDATE" then
|
|
ConsumesManager_ScanPlayerMail()
|
|
end
|
|
end)
|
|
|
|
|
|
-- Main Windows Setup -----------------------------------------------------------------------------------
|
|
function ConsumesManager_CreateMainWindow()
|
|
-- Main Frame
|
|
ConsumesManager_MainFrame = CreateFrame("Frame", "ConsumesManager_MainFrame", UIParent)
|
|
ConsumesManager_MainFrame:SetWidth(WindowWidth)
|
|
ConsumesManager_MainFrame:SetHeight(512)
|
|
ConsumesManager_MainFrame:SetPoint("CENTER", UIParent, "CENTER")
|
|
ConsumesManager_MainFrame:SetFrameStrata("DIALOG")
|
|
ConsumesManager_MainFrame:SetMovable(true)
|
|
ConsumesManager_MainFrame:EnableMouse(true)
|
|
ConsumesManager_MainFrame:RegisterForDrag("LeftButton")
|
|
ConsumesManager_MainFrame:SetScript("OnDragStart", function()
|
|
this:StartMoving()
|
|
end)
|
|
ConsumesManager_MainFrame:SetScript("OnDragStop", function()
|
|
this:StopMovingOrSizing()
|
|
end)
|
|
|
|
table.insert(UISpecialFrames, "ConsumesManager_MainFrame")
|
|
|
|
-- Background Texture
|
|
local background = ConsumesManager_MainFrame:CreateTexture(nil, "BACKGROUND")
|
|
background:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Background")
|
|
background:SetPoint("TOPLEFT", ConsumesManager_MainFrame, "TOPLEFT", 12, -12)
|
|
background:SetPoint("BOTTOMRIGHT", ConsumesManager_MainFrame, "BOTTOMRIGHT", -12, 12)
|
|
|
|
-- Border
|
|
ConsumesManager_MainFrame:SetBackdrop({
|
|
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
|
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
|
|
tile = true, tileSize = 32, edgeSize = 32,
|
|
insets = { left = 11, right = 12, top = 12, bottom = 11 }
|
|
})
|
|
ConsumesManager_MainFrame:SetBackdropColor(0.1, 0.1, 0.1, 1)
|
|
|
|
-- Progress Bar for Syncing
|
|
ProgressBarFrame = CreateFrame("Frame", "ConsumesManager_ProgressBar", ConsumesManager_MainFrame, BackdropTemplateMixin and "BackdropTemplate")
|
|
ProgressBarFrame:SetWidth(20)
|
|
ProgressBarFrame:SetHeight(496)
|
|
ProgressBarFrame:SetPoint("TOPRIGHT", ConsumesManager_MainFrame, "TOPRIGHT", 10, -8)
|
|
ProgressBarFrame:SetBackdrop({
|
|
bgFile = "Interface\\Buttons\\WHITE8x8",
|
|
edgeFile = "Interface\\Buttons\\WHITE8x8",
|
|
edgeSize = 1,
|
|
})
|
|
ProgressBarFrame:SetBackdropColor(0,0,0,1)
|
|
ProgressBarFrame:SetBackdropBorderColor(0.5,0.5,0.5,1)
|
|
ProgressBarFrame:SetFrameLevel(ConsumesManager_MainFrame:GetFrameLevel() - 1)
|
|
ProgressBarFrame:Hide()
|
|
|
|
ProgressBarFrame_fill = CreateFrame("Frame", "ConsumesManager_ProgressBarFill", ProgressBarFrame, BackdropTemplateMixin and "BackdropTemplate")
|
|
ProgressBarFrame_fill:SetWidth(17)
|
|
ProgressBarFrame_fill:SetHeight(0)
|
|
ProgressBarFrame_fill:SetPoint("BOTTOMLEFT", ProgressBarFrame, "BOTTOMLEFT", 1, 2)
|
|
ProgressBarFrame_fill:SetBackdrop({
|
|
bgFile = "Interface\\Buttons\\WHITE8x8"
|
|
})
|
|
ProgressBarFrame_fill:SetBackdropColor(0,0.6,0,1)
|
|
ProgressBarFrame_fill:Hide()
|
|
ProgressBarFrame_fill:SetFrameLevel(ProgressBarFrame:GetFrameLevel() + 1)
|
|
|
|
|
|
ProgressBarFrame_Text = ProgressBarFrame_fill:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
|
|
ProgressBarFrame_Text:SetText("S\n\nY\n\nN\n\nC\n\nI\n\nN\n\nG")
|
|
ProgressBarFrame_Text:SetPoint("CENTER", ProgressBarFrame, "CENTER", 1, 0)
|
|
ProgressBarFrame_Text:SetTextColor(1,1,1)
|
|
ProgressBarFrame_Text:Hide()
|
|
|
|
|
|
-- Title Text
|
|
local titleText = ConsumesManager_MainFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
|
|
titleText:SetText("Consumes Manager")
|
|
titleText:SetPoint("TOP", ConsumesManager_MainFrame, "TOP", 0, -2)
|
|
|
|
-- Calculate the width of the title text and adjust the title background accordingly
|
|
local titleWidth = titleText:GetStringWidth() + 200
|
|
|
|
-- Title Background
|
|
local titleBg = ConsumesManager_MainFrame:CreateTexture(nil, "ARTWORK")
|
|
titleBg:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
|
|
titleBg:SetWidth(titleWidth)
|
|
titleBg:SetHeight(64)
|
|
titleBg:SetPoint("TOP", ConsumesManager_MainFrame, "TOP", 0, 12)
|
|
|
|
-- Close Button
|
|
local closeButton = CreateFrame("Button", nil, ConsumesManager_MainFrame, "UIPanelCloseButton")
|
|
closeButton:SetWidth(32)
|
|
closeButton:SetHeight(32)
|
|
closeButton:SetPoint("TOPRIGHT", ConsumesManager_MainFrame, "TOPRIGHT", -5, -5)
|
|
closeButton:SetScript("OnClick", function()
|
|
ConsumesManager_MainFrame:Hide()
|
|
end)
|
|
|
|
-- Create a custom tooltip frame
|
|
ConsumesManagerTooltip = CreateFrame("Frame", "ConsumesManagerTooltip", UIParent)
|
|
ConsumesManagerTooltip:SetWidth(100)
|
|
ConsumesManagerTooltip:SetHeight(40)
|
|
ConsumesManagerTooltip:SetFrameStrata("TOOLTIP")
|
|
ConsumesManagerTooltip:SetBackdrop({
|
|
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
|
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
|
tile = true, tileSize = 16, edgeSize = 16,
|
|
insets = { left = 4, right = 4, top = 4, bottom = 4 }
|
|
})
|
|
ConsumesManagerTooltip:SetBackdropColor(0, 0, 0, 1)
|
|
ConsumesManagerTooltip:Hide()
|
|
|
|
-- Tooltip text
|
|
local tooltipText = ConsumesManagerTooltip:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
tooltipText:SetPoint("CENTER", ConsumesManagerTooltip, "CENTER", 0, 0)
|
|
ConsumesManagerTooltip.text = tooltipText
|
|
|
|
-- Tabs
|
|
local tabs = {}
|
|
ConsumesManager_Tabs = {}
|
|
-- Adjusted CreateTab function
|
|
local function CreateTab(name, texture, xOffset, tooltipText, tabIndex)
|
|
local tab = CreateFrame("Button", name, ConsumesManager_MainFrame)
|
|
tab:SetWidth(36)
|
|
tab:SetHeight(36)
|
|
tab:SetPoint("TOPLEFT", ConsumesManager_MainFrame, "TOPLEFT", xOffset, -30)
|
|
|
|
-- Tab Icon
|
|
local icon = tab:CreateTexture(nil, "ARTWORK")
|
|
icon:SetTexture(texture)
|
|
icon:SetWidth(36)
|
|
icon:SetHeight(36)
|
|
icon:SetPoint("CENTER", tab, "CENTER", 0, 0)
|
|
tab.icon = icon
|
|
|
|
-- Hover Glow
|
|
local hoverTexture = tab:CreateTexture(nil, "HIGHLIGHT")
|
|
hoverTexture:SetTexture("Interface\\Buttons\\CheckButtonHilight")
|
|
hoverTexture:SetBlendMode("ADD")
|
|
hoverTexture:SetAllPoints(tab)
|
|
tab.hoverTexture = hoverTexture -- Store hoverTexture in tab
|
|
|
|
-- Active Highlight
|
|
local activeHighlight = tab:CreateTexture(nil, "OVERLAY")
|
|
activeHighlight:SetTexture("Interface\\Buttons\\CheckButtonHilight")
|
|
activeHighlight:SetBlendMode("ADD")
|
|
activeHighlight:SetAllPoints(tab)
|
|
activeHighlight:SetWidth(36)
|
|
activeHighlight:SetHeight(36)
|
|
activeHighlight:Hide()
|
|
tab.activeHighlight = activeHighlight
|
|
|
|
-- Store tooltip text
|
|
tab.tooltipText = tooltipText
|
|
|
|
-- Custom Tooltip Handlers
|
|
tab:SetScript("OnEnter", function()
|
|
ShowTooltip(tab, tab.tooltipText)
|
|
end)
|
|
tab:SetScript("OnLeave", HideTooltip)
|
|
|
|
-- Initialize as enabled
|
|
tab.isEnabled = true
|
|
|
|
-- Store tab in global table
|
|
ConsumesManager_Tabs[tabIndex] = tab
|
|
|
|
return tab
|
|
end
|
|
|
|
|
|
|
|
-- Manager Tab
|
|
local tab1 = CreateTab("ConsumesManager_MainFrameTab1", "Interface\\AddOns\\ConsumesManager\\images\\minimap_icon", 30, "Tracker", 1)
|
|
tab1.originalOnClick = function()
|
|
ConsumesManager_ShowTab(1)
|
|
end
|
|
tab1:SetScript("OnClick", tab1.originalOnClick)
|
|
|
|
-- Items Tab
|
|
local tab2 = CreateTab("ConsumesManager_MainFrameTab2", "Interface\\Icons\\Inv_misc_book_03", 80, "Items", 2)
|
|
tab2.originalOnClick = function()
|
|
ConsumesManager_ShowTab(2)
|
|
end
|
|
tab2:SetScript("OnClick", tab2.originalOnClick)
|
|
|
|
-- Presets Tab
|
|
local tab3 = CreateTab("ConsumesManager_MainFrameTab3", "Interface\\Icons\\inv_misc_note_06", 130, "Presets", 3)
|
|
tab3.originalOnClick = function()
|
|
ConsumesManager_ShowTab(3)
|
|
end
|
|
tab3:SetScript("OnClick", tab3.originalOnClick)
|
|
|
|
-- Settings Tab
|
|
local tab4 = CreateTab("ConsumesManager_MainFrameTab4", "Interface\\Icons\\INV_Misc_Gear_01", 180, "Settings", 4)
|
|
tab4.originalOnClick = function()
|
|
ConsumesManager_ShowTab(4)
|
|
end
|
|
tab4:SetScript("OnClick", tab4.originalOnClick)
|
|
|
|
|
|
-- Send Data Button
|
|
sendDataButton = CreateTab("ConsumesManager_sendDataButton", "Interface\\Icons\\inv_misc_punchcards_prismatic", 280, "Push Data", 5)
|
|
function updateSenDataButtonState()
|
|
if ConsumesManager_Options.Channel == nil or ConsumesManager_Options.Channel == "" or ConsumesManager_Options.Password == nil or ConsumesManager_Options.Password == "" then
|
|
sendDataButton:Hide()
|
|
ReadData("stop")
|
|
else
|
|
sendDataButton:Show()
|
|
ReadData("start")
|
|
end
|
|
end
|
|
updateSenDataButtonState()
|
|
sendDataButton.originalOnClick = function()
|
|
PushData()
|
|
end
|
|
sendDataButton:SetScript("OnClick", sendDataButton.originalOnClick)
|
|
|
|
|
|
-- Add Grey Line Under Tabs
|
|
local tabsLine = ConsumesManager_MainFrame:CreateTexture(nil, "ARTWORK")
|
|
tabsLine:SetHeight(1)
|
|
tabsLine:SetPoint("TOPLEFT", ConsumesManager_MainFrame, "TOPLEFT", 12, -72)
|
|
tabsLine:SetPoint("TOPRIGHT", ConsumesManager_MainFrame, "TOPRIGHT", -12, -72)
|
|
tabsLine:SetTexture("Interface\\Buttons\\WHITE8x8")
|
|
tabsLine:SetVertexColor(0.4, 0.4, 0.4, 1)
|
|
|
|
-- Tab Content
|
|
ConsumesManager_MainFrame.tabs = {}
|
|
local tab1Content = CreateFrame("Frame", nil, ConsumesManager_MainFrame)
|
|
tab1Content:SetWidth(WindowWidth - 50)
|
|
tab1Content:SetHeight(380)
|
|
tab1Content:SetPoint("TOPLEFT", ConsumesManager_MainFrame, "TOPLEFT", 30, -80)
|
|
ConsumesManager_MainFrame.tabs[1] = tab1Content
|
|
|
|
local tab2Content = CreateFrame("Frame", nil, ConsumesManager_MainFrame)
|
|
tab2Content:SetWidth(WindowWidth - 50)
|
|
tab2Content:SetHeight(380)
|
|
tab2Content:SetPoint("TOPLEFT", ConsumesManager_MainFrame, "TOPLEFT", 30, -80)
|
|
ConsumesManager_MainFrame.tabs[2] = tab2Content
|
|
|
|
local tab3Content = CreateFrame("Frame", nil, ConsumesManager_MainFrame)
|
|
tab3Content:SetWidth(WindowWidth - 50)
|
|
tab3Content:SetHeight(380)
|
|
tab3Content:SetPoint("TOPLEFT", ConsumesManager_MainFrame, "TOPLEFT", 30, -80)
|
|
ConsumesManager_MainFrame.tabs[3] = tab3Content
|
|
|
|
local tab4Content = CreateFrame("Frame", nil, ConsumesManager_MainFrame)
|
|
tab4Content:SetWidth(WindowWidth - 50)
|
|
tab4Content:SetHeight(380)
|
|
tab4Content:SetPoint("TOPLEFT", ConsumesManager_MainFrame, "TOPLEFT", 30, -80)
|
|
ConsumesManager_MainFrame.tabs[4] = tab4Content
|
|
|
|
-- Footer Button to Push Database
|
|
local footerText = ConsumesManager_MainFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
|
|
footerText:SetText("Made by Horyoshi (v" .. GetAddOnMetadata("ConsumesManager", "Version") .. ")")
|
|
footerText:SetTextColor(0.6, 0.6, 0.6)
|
|
footerText:SetPoint("BOTTOM", ConsumesManager_MainFrame, "BOTTOM", 0, 15)
|
|
|
|
|
|
-- Add Grey Line Above Footer
|
|
local footerLine = ConsumesManager_MainFrame:CreateTexture(nil, "ARTWORK")
|
|
footerLine:SetHeight(1)
|
|
footerLine:SetPoint("BOTTOMLEFT", ConsumesManager_MainFrame, "BOTTOMLEFT", 12, 30)
|
|
footerLine:SetPoint("BOTTOMRIGHT", ConsumesManager_MainFrame, "BOTTOMRIGHT", -12, 30)
|
|
footerLine:SetTexture("Interface\\Buttons\\WHITE8x8")
|
|
footerLine:SetVertexColor(0.4, 0.4, 0.4, 1)
|
|
|
|
-- Set Default Tab
|
|
ConsumesManager_ShowTab(1)
|
|
|
|
-- Add Custom Content for Tabs
|
|
ConsumesManager_CreateManagerContent(tab1Content)
|
|
ConsumesManager_CreateItemsContent(tab2Content)
|
|
ConsumesManager_CreatePresetsContent(tab3Content)
|
|
ConsumesManager_CreateSettingsContent(tab4Content)
|
|
|
|
ConsumesManager_UpdateTabStates()
|
|
end
|
|
|
|
function ConsumesManager_ShowMainWindow()
|
|
if not ConsumesManager_MainFrame then
|
|
ConsumesManager_CreateMainWindow()
|
|
end
|
|
ConsumesManager_MainFrame:Show()
|
|
-- Scan inventory when the window is opened
|
|
ConsumesManager_ScanPlayerInventory()
|
|
-- Only scan bank and mail if they are open
|
|
if BankFrame and BankFrame:IsShown() then
|
|
ConsumesManager_ScanPlayerBank()
|
|
end
|
|
if MailFrame and MailFrame:IsShown() then
|
|
ConsumesManager_ScanPlayerMail()
|
|
end
|
|
-- Update the tabs based on whether bank and mail have been scanned
|
|
ConsumesManager_UpdateTabStates()
|
|
-- Update the Manager content
|
|
ConsumesManager_UpdateManagerContent()
|
|
-- Update the Presets content
|
|
ConsumesManager_UpdatePresetsConsumables()
|
|
ConsumesManager_UpdateSettingsContent()
|
|
ConsumesManager_UpdateManagerContent()
|
|
end
|
|
|
|
|
|
function ConsumesManager_ShowTab(tabIndex)
|
|
if not ConsumesManager_MainFrame or not ConsumesManager_MainFrame.tabs then return end
|
|
|
|
-- Check if the tab is enabled
|
|
local tabButton = ConsumesManager_Tabs[tabIndex]
|
|
if tabButton and not tabButton.isEnabled then
|
|
return -- Do not switch to disabled tabs
|
|
end
|
|
|
|
for i, tabContent in pairs(ConsumesManager_MainFrame.tabs) do
|
|
if i == tabIndex then
|
|
tabContent:Show()
|
|
-- Set the tab button to active
|
|
local tabButton = ConsumesManager_Tabs[i]
|
|
if tabButton then
|
|
tabButton:SetNormalTexture("Interface\\ItemsFrame\\UI-ItemsFrame-ActiveTab")
|
|
tabButton.activeHighlight:Show()
|
|
end
|
|
else
|
|
tabContent:Hide()
|
|
-- Set the tab button to inactive
|
|
local tabButton = ConsumesManager_Tabs[i]
|
|
if tabButton then
|
|
tabButton:SetNormalTexture("Interface\\ItemsFrame\\UI-ItemsFrame-InActiveTab")
|
|
tabButton.activeHighlight:Hide()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
-- Tracker Window -----------------------------------------------------------------------------------
|
|
function ConsumesManager_CreateManagerContent(parentFrame)
|
|
-- Initialize sort order if not set
|
|
ConsumesManager_Options.sortOrder = ConsumesManager_Options.sortOrder or "name"
|
|
ConsumesManager_Options.sortDirection = ConsumesManager_Options.sortDirection or "asc"
|
|
|
|
|
|
-- Create buttons for sorting
|
|
local orderByNameButton = CreateFrame("Button", "ConsumesManager_OrderByNameButton", parentFrame, "UIPanelButtonTemplate")
|
|
orderByNameButton:SetWidth(100)
|
|
orderByNameButton:SetHeight(24)
|
|
orderByNameButton:SetText("Order by Name")
|
|
orderByNameButton:GetFontString():SetFont("Fonts\\FRIZQT__.TTF", 10, "NORMAL")
|
|
orderByNameButton:SetPoint("TOPLEFT", parentFrame, "TOPLEFT", 0, -5)
|
|
orderByNameButton:SetScript("OnClick", function()
|
|
if ConsumesManager_Options.sortOrder == "name" then
|
|
-- Toggle sort direction
|
|
if ConsumesManager_Options.sortDirection == "asc" then
|
|
ConsumesManager_Options.sortDirection = "desc"
|
|
else
|
|
ConsumesManager_Options.sortDirection = "asc"
|
|
end
|
|
else
|
|
ConsumesManager_Options.sortOrder = "name"
|
|
ConsumesManager_Options.sortDirection = "asc"
|
|
end
|
|
ConsumesManager_UpdateManagerContent()
|
|
end)
|
|
|
|
local orderByAmountButton = CreateFrame("Button", "ConsumesManager_OrderByAmountButton", parentFrame, "UIPanelButtonTemplate")
|
|
orderByAmountButton:SetWidth(100)
|
|
orderByAmountButton:SetHeight(24)
|
|
orderByAmountButton:SetText("Order by Amount")
|
|
orderByAmountButton:GetFontString():SetFont("Fonts\\FRIZQT__.TTF", 10, "NORMAL")
|
|
orderByAmountButton:SetPoint("LEFT", orderByNameButton, "RIGHT", 10, 0)
|
|
orderByAmountButton:SetScript("OnClick", function()
|
|
if ConsumesManager_Options.sortOrder == "amount" then
|
|
-- Toggle sort direction
|
|
if ConsumesManager_Options.sortDirection == "desc" then
|
|
ConsumesManager_Options.sortDirection = "asc"
|
|
else
|
|
ConsumesManager_Options.sortDirection = "desc"
|
|
end
|
|
else
|
|
ConsumesManager_Options.sortOrder = "amount"
|
|
ConsumesManager_Options.sortDirection = "desc"
|
|
end
|
|
ConsumesManager_UpdateManagerContent()
|
|
end)
|
|
|
|
parentFrame.orderByNameButton = orderByNameButton
|
|
parentFrame.orderByAmountButton = orderByAmountButton
|
|
|
|
-- Initially hide the order buttons
|
|
orderByNameButton:Hide()
|
|
orderByAmountButton:Hide()
|
|
|
|
-- Scroll Frame
|
|
local scrollFrame = CreateFrame("ScrollFrame", "ConsumesManager_ManagerScrollFrame", parentFrame)
|
|
scrollFrame:SetPoint("TOPLEFT", parentFrame, "TOPLEFT", 0, -35) -- Adjusted to be below the buttons
|
|
scrollFrame:SetPoint("BOTTOMRIGHT", parentFrame, "BOTTOMRIGHT", -20, 0)
|
|
scrollFrame:EnableMouseWheel(true)
|
|
scrollFrame:SetScript("OnMouseWheel", function()
|
|
local delta = arg1
|
|
local current = this:GetVerticalScroll()
|
|
local maxScroll = this.range or 0
|
|
local newScroll = math.max(0, math.min(current - (delta * 20), maxScroll))
|
|
this:SetVerticalScroll(newScroll)
|
|
parentFrame.scrollBar:SetValue(newScroll)
|
|
end)
|
|
|
|
-- Scroll Child Frame
|
|
local scrollChild = CreateFrame("Frame", nil, scrollFrame)
|
|
scrollChild:SetWidth(WindowWidth - 10)
|
|
scrollChild:SetHeight(1) -- Will adjust later
|
|
scrollFrame:SetScrollChild(scrollChild)
|
|
parentFrame.scrollChild = scrollChild
|
|
parentFrame.scrollFrame = scrollFrame
|
|
|
|
-- Initialize data structures
|
|
parentFrame.categoryInfo = {}
|
|
local index = 0 -- Position index
|
|
local lineHeight = 18
|
|
|
|
-- Sort categories alphabetically
|
|
local sortedCategories = {}
|
|
for categoryName, _ in pairs(consumablesCategories) do
|
|
table.insert(sortedCategories, categoryName)
|
|
end
|
|
table.sort(sortedCategories)
|
|
|
|
-- Iterate over sorted categories
|
|
for _, categoryName in ipairs(sortedCategories) do
|
|
local consumables = consumablesCategories[categoryName]
|
|
|
|
-- Create category label
|
|
local categoryLabel = scrollChild:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
|
|
categoryLabel:SetText(categoryName)
|
|
categoryLabel:SetTextColor(1, 1, 1)
|
|
categoryLabel:Show()
|
|
|
|
local categoryInfo = { name = categoryName, label = categoryLabel, Items = {} }
|
|
|
|
index = index + 1 -- Position for the category label
|
|
|
|
local numItemsInCategory = 0 -- Counter for items in this category
|
|
|
|
-- Sort the consumables by name
|
|
table.sort(consumables, function(a, b) return a.name < b.name end)
|
|
|
|
-- For each consumable in the category
|
|
for _, consumable in ipairs(consumables) do
|
|
local itemID = consumable.id
|
|
local itemName = consumable.name
|
|
|
|
-- Create a frame that encompasses the button and label
|
|
local itemFrame = CreateFrame("Frame", "ConsumesManager_ManagerItemFrame" .. index, scrollChild)
|
|
itemFrame:SetWidth(WindowWidth - 10)
|
|
itemFrame:SetHeight(lineHeight)
|
|
itemFrame:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, - (index) * lineHeight)
|
|
itemFrame:Hide()
|
|
itemFrame:EnableMouse(true) -- Enable mouse events for OnEnter and OnLeave
|
|
|
|
-- Create the 'Use' button inside the itemFrame
|
|
local useButton = CreateFrame("Button", "ConsumesManager_UseButton" .. index, itemFrame, "UIPanelButtonTemplate")
|
|
useButton:SetWidth(40)
|
|
useButton:SetHeight(16)
|
|
useButton:SetPoint("LEFT", itemFrame, "LEFT", 0, 0)
|
|
useButton:SetText("Use")
|
|
|
|
-- Initially show or hide the use button based on settings
|
|
if ConsumesManager_Options.showUseButton then
|
|
useButton:Show()
|
|
else
|
|
useButton:Hide()
|
|
end
|
|
|
|
-- Create FontString for label
|
|
local label = itemFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
if ConsumesManager_Options.showUseButton then
|
|
label:SetPoint("LEFT", useButton, "RIGHT", 4, 0)
|
|
else
|
|
label:SetPoint("LEFT", itemFrame, "LEFT", 0, 0)
|
|
end
|
|
label:SetText(itemName)
|
|
label:SetJustifyH("LEFT")
|
|
|
|
-- Set up the button OnClick handler
|
|
useButton:SetScript("OnClick", function()
|
|
local bag, slot = ConsumesManager_FindItemInBags(itemID)
|
|
if bag and slot then
|
|
UseContainerItem(bag, slot)
|
|
else
|
|
DEFAULT_CHAT_FRAME:AddMessage("Item not found in bags.")
|
|
end
|
|
end)
|
|
|
|
-- Initialize button state
|
|
useButton:Disable()
|
|
|
|
-- Mouseover Tooltip
|
|
itemFrame:SetScript("OnEnter", function()
|
|
ConsumesManager_ShowConsumableTooltip(itemID)
|
|
end)
|
|
itemFrame:SetScript("OnLeave", function()
|
|
if ConsumesManager_CustomTooltip then
|
|
ConsumesManager_CustomTooltip:Hide()
|
|
end
|
|
end)
|
|
|
|
-- Store item info
|
|
table.insert(categoryInfo.Items, {
|
|
frame = itemFrame,
|
|
label = label,
|
|
name = itemName,
|
|
itemID = itemID,
|
|
button = useButton
|
|
})
|
|
|
|
index = index + 1 -- Increment index after adding item
|
|
numItemsInCategory = numItemsInCategory + 1 -- Increment item count
|
|
end
|
|
|
|
-- Position the category label above its items
|
|
categoryLabel:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, - (index - numItemsInCategory - 1) * lineHeight)
|
|
|
|
-- Store category info
|
|
table.insert(parentFrame.categoryInfo, categoryInfo)
|
|
|
|
-- Add extra spacing after the category
|
|
index = index + 1 -- Add one extra line of spacing between categories
|
|
end
|
|
|
|
-- Adjust the scroll child height
|
|
scrollChild.contentHeight = (index - 1) * lineHeight
|
|
scrollChild:SetHeight(scrollChild.contentHeight)
|
|
|
|
-- Message Label (adjusted to be a child of parentFrame)
|
|
local messageLabel = parentFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
messageLabel:SetText("|cffff0000No consumables selected|r\n\n|cffffffffClick on |rItems|cffffffff to get started|r")
|
|
messageLabel:SetPoint("CENTER", parentFrame, "CENTER", 0, 0)
|
|
messageLabel:Hide() -- Initially hidden
|
|
parentFrame.messageLabel = messageLabel
|
|
|
|
-- Scroll Bar
|
|
local scrollBar = CreateFrame("Slider", "ConsumesManager_ManagerScrollBar", parentFrame)
|
|
scrollBar:SetPoint("TOPRIGHT", parentFrame, "TOPRIGHT", -2, -35) -- Adjusted to be below the buttons
|
|
scrollBar:SetPoint("BOTTOMRIGHT", parentFrame, "BOTTOMRIGHT", -2, 16)
|
|
scrollBar:SetWidth(16)
|
|
scrollBar:SetOrientation('VERTICAL')
|
|
scrollBar:SetThumbTexture("Interface\\Buttons\\UI-ScrollBar-Knob")
|
|
scrollBar:SetBackdrop({
|
|
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 }
|
|
})
|
|
scrollBar:SetScript("OnValueChanged", function()
|
|
local value = this:GetValue()
|
|
parentFrame.scrollFrame:SetVerticalScroll(value)
|
|
end)
|
|
parentFrame.scrollBar = scrollBar
|
|
|
|
-- Initially hide the scrollbar
|
|
scrollBar:Hide()
|
|
end
|
|
|
|
function ConsumesManager_UpdateManagerContent()
|
|
if not ConsumesManager_MainFrame or not ConsumesManager_MainFrame.tabs or not ConsumesManager_MainFrame.tabs[1] then
|
|
return
|
|
end
|
|
|
|
local ManagerFrame = ConsumesManager_MainFrame.tabs[1]
|
|
local realmName = GetRealmName()
|
|
local faction = UnitFactionGroup("player")
|
|
local playerName = UnitName("player")
|
|
|
|
-- Ensure data structure exists
|
|
ConsumesManager_Data[realmName] = ConsumesManager_Data[realmName] or {}
|
|
ConsumesManager_Data[realmName][faction] = ConsumesManager_Data[realmName][faction] or {}
|
|
local data = ConsumesManager_Data[realmName][faction]
|
|
|
|
-- Check if bank and mail have been scanned for current character
|
|
local currentCharData = data[playerName]
|
|
local bankScanned = currentCharData and currentCharData["bank"] ~= nil
|
|
local mailScanned = currentCharData and currentCharData["mail"] ~= nil
|
|
|
|
-- Hide the message label and order buttons by default
|
|
ManagerFrame.messageLabel:Hide()
|
|
ManagerFrame.orderByNameButton:Hide()
|
|
ManagerFrame.orderByAmountButton:Hide()
|
|
|
|
-- Hide all item frames and category labels
|
|
for _, categoryInfo in ipairs(ManagerFrame.categoryInfo) do
|
|
categoryInfo.label:Hide()
|
|
for _, itemInfo in ipairs(categoryInfo.Items) do
|
|
itemInfo.frame:Hide()
|
|
end
|
|
end
|
|
|
|
-- Reset the scrollChild height
|
|
ManagerFrame.scrollChild.contentHeight = 0
|
|
ManagerFrame.scrollChild:SetHeight(0)
|
|
|
|
if not bankScanned or not mailScanned then
|
|
-- Show message
|
|
ManagerFrame.messageLabel:SetText("|cffff0000This character is not scanned yet|r\n\n|cffffffffOpen your |rBank|cffffffff and |rMail|cffffffff to get started|r")
|
|
ManagerFrame.messageLabel:Show()
|
|
|
|
-- Update the Manager scrollbar
|
|
ConsumesManager_UpdateManagerScrollBar()
|
|
|
|
return
|
|
end
|
|
|
|
-- Proceed with normal content update
|
|
local index = 0 -- Positioning index for items
|
|
local hasAnyVisibleItems = false -- Track if any items are visible
|
|
local lineHeight = 18
|
|
|
|
-- Get the current sort order and direction
|
|
local sortOrder = ConsumesManager_Options.sortOrder or "name"
|
|
local sortDirection = ConsumesManager_Options.sortDirection or "asc"
|
|
|
|
local enableCategories = ConsumesManager_Options.enableCategories or false
|
|
local showUseButton = ConsumesManager_Options.showUseButton or false
|
|
|
|
-- Check if categories are enabled
|
|
if ConsumesManager_Options.enableCategories then
|
|
-- Iterate over categories
|
|
for _, categoryInfo in ipairs(ManagerFrame.categoryInfo) do
|
|
local anyItemVisible = false
|
|
|
|
-- First, collect the enabled items and their counts
|
|
local enabledItems = {}
|
|
|
|
for _, itemInfo in ipairs(categoryInfo.Items) do
|
|
local itemID = itemInfo.itemID
|
|
if ConsumesManager_SelectedItems[itemID] then
|
|
-- Sum counts across all selected characters
|
|
local totalCount = 0
|
|
for character, charData in pairs(data) do
|
|
if ConsumesManager_Options["Characters"][character] == true then
|
|
local inventory = charData["inventory"] and charData["inventory"][itemID] or 0
|
|
local bank = charData["bank"] and charData["bank"][itemID] or 0
|
|
local mail = charData["mail"] and charData["mail"][itemID] or 0
|
|
totalCount = totalCount + inventory + bank + mail
|
|
end
|
|
end
|
|
table.insert(enabledItems, {itemInfo = itemInfo, totalCount = totalCount})
|
|
anyItemVisible = true
|
|
else
|
|
itemInfo.frame:Hide()
|
|
end
|
|
end
|
|
|
|
-- If any items are visible, handle category label
|
|
if anyItemVisible then
|
|
categoryInfo.label:SetPoint("TOPLEFT", ManagerFrame.scrollChild, "TOPLEFT", 0, - (index) * lineHeight)
|
|
categoryInfo.label:Show()
|
|
index = index + 1
|
|
|
|
-- Sort enabled items based on sort order and direction
|
|
if sortOrder == "name" then
|
|
if sortDirection == "asc" then
|
|
table.sort(enabledItems, function(a, b) return a.itemInfo.name < b.itemInfo.name end)
|
|
else
|
|
table.sort(enabledItems, function(a, b) return a.itemInfo.name > b.itemInfo.name end)
|
|
end
|
|
elseif sortOrder == "amount" then
|
|
if sortDirection == "desc" then
|
|
table.sort(enabledItems, function(a, b) return a.totalCount > b.totalCount end)
|
|
else
|
|
table.sort(enabledItems, function(a, b) return a.totalCount < b.totalCount end)
|
|
end
|
|
end
|
|
|
|
-- Now, position and show the enabled items
|
|
for _, itemData in ipairs(enabledItems) do
|
|
local itemInfo = itemData.itemInfo
|
|
local itemID = itemInfo.itemID
|
|
local itemName = itemInfo.name
|
|
local label = itemInfo.label
|
|
local button = itemInfo.button
|
|
local frame = itemInfo.frame
|
|
local totalCount = itemData.totalCount
|
|
|
|
-- Update label text with counts
|
|
label:SetText(itemName .. " (" .. totalCount .. ")")
|
|
|
|
-- Adjust label color based on count
|
|
if totalCount == 0 then
|
|
label:SetTextColor(1, 0, 0) -- Red
|
|
elseif totalCount < 10 then
|
|
label:SetTextColor(1, 0.4, 0) -- Orange
|
|
elseif totalCount <= 20 then
|
|
label:SetTextColor(1, 0.85, 0) -- Yellow
|
|
else
|
|
label:SetTextColor(0, 1, 0) -- Green
|
|
end
|
|
|
|
-- Enable or disable the 'Use' button based on whether the item is in the player's inventory
|
|
local playerInventory = data[playerName]["inventory"] or {}
|
|
local countInInventory = playerInventory[itemID] or 0
|
|
|
|
if ConsumesManager_Options.showUseButton then
|
|
button:Show()
|
|
if countInInventory > 0 then
|
|
button:Enable()
|
|
else
|
|
button:Disable()
|
|
end
|
|
label:SetPoint("LEFT", button, "RIGHT", 4, 0)
|
|
else
|
|
button:Disable()
|
|
button:Hide()
|
|
label:SetPoint("LEFT", frame, "LEFT", 0, 0)
|
|
end
|
|
|
|
-- Show and position the item frame
|
|
frame:SetPoint("TOPLEFT", ManagerFrame.scrollChild, "TOPLEFT", 0, - (index) * lineHeight)
|
|
frame:Show()
|
|
index = index + 1
|
|
hasAnyVisibleItems = true
|
|
end
|
|
|
|
-- Add extra spacing after the category
|
|
index = index + 1 -- Add one extra line of spacing between categories
|
|
else
|
|
categoryInfo.label:Hide()
|
|
-- Hide all items under this category
|
|
for _, itemInfo in ipairs(categoryInfo.Items) do
|
|
itemInfo.frame:Hide()
|
|
end
|
|
end
|
|
end
|
|
else
|
|
-- Categories are disabled
|
|
-- Collect all enabled items into a single list with their counts
|
|
local allItems = {}
|
|
for _, categoryInfo in ipairs(ManagerFrame.categoryInfo) do
|
|
categoryInfo.label:Hide()
|
|
for _, itemInfo in ipairs(categoryInfo.Items) do
|
|
local itemID = itemInfo.itemID
|
|
if ConsumesManager_SelectedItems[itemID] then
|
|
-- Sum counts across all selected characters
|
|
local totalCount = 0
|
|
for character, charData in pairs(data) do
|
|
if ConsumesManager_Options["Characters"][character] == true then
|
|
local inventory = charData["inventory"] and charData["inventory"][itemID] or 0
|
|
local bank = charData["bank"] and charData["bank"][itemID] or 0
|
|
local mail = charData["mail"] and charData["mail"][itemID] or 0
|
|
totalCount = totalCount + inventory + bank + mail
|
|
end
|
|
end
|
|
table.insert(allItems, {itemInfo = itemInfo, totalCount = totalCount})
|
|
hasAnyVisibleItems = true
|
|
else
|
|
itemInfo.frame:Hide()
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Sort allItems based on sort order and direction
|
|
if sortOrder == "name" then
|
|
if sortDirection == "asc" then
|
|
table.sort(allItems, function(a, b) return a.itemInfo.name < b.itemInfo.name end)
|
|
else
|
|
table.sort(allItems, function(a, b) return a.itemInfo.name > b.itemInfo.name end)
|
|
end
|
|
elseif sortOrder == "amount" then
|
|
if sortDirection == "desc" then
|
|
table.sort(allItems, function(a, b) return a.totalCount > b.totalCount end)
|
|
else
|
|
table.sort(allItems, function(a, b) return a.totalCount < b.totalCount end)
|
|
end
|
|
end
|
|
|
|
-- Display all items
|
|
for _, itemData in ipairs(allItems) do
|
|
local itemInfo = itemData.itemInfo
|
|
local itemID = itemInfo.itemID
|
|
local itemName = itemInfo.name
|
|
local label = itemInfo.label
|
|
local button = itemInfo.button
|
|
local frame = itemInfo.frame
|
|
local totalCount = itemData.totalCount
|
|
|
|
-- Update label text with counts
|
|
label:SetText(itemName .. " (" .. totalCount .. ")")
|
|
|
|
-- Adjust label color based on count
|
|
if totalCount == 0 then
|
|
label:SetTextColor(1, 0, 0) -- Red
|
|
elseif totalCount < 10 then
|
|
label:SetTextColor(1, 0.4, 0) -- Orange
|
|
elseif totalCount <= 20 then
|
|
label:SetTextColor(1, 0.85, 0) -- Yellow
|
|
else
|
|
label:SetTextColor(0, 1, 0) -- Green
|
|
end
|
|
|
|
-- Enable or disable the 'Use' button based on whether the item is in the player's inventory
|
|
local playerInventory = data[playerName]["inventory"] or {}
|
|
local countInInventory = playerInventory[itemID] or 0
|
|
|
|
if showUseButton then
|
|
button:Show()
|
|
if countInInventory > 0 then
|
|
button:Enable()
|
|
else
|
|
button:Disable()
|
|
end
|
|
label:SetPoint("LEFT", button, "RIGHT", 4, 0)
|
|
else
|
|
button:Disable()
|
|
button:Hide()
|
|
label:SetPoint("LEFT", frame, "LEFT", 0, 0)
|
|
end
|
|
|
|
-- Show and position the item frame
|
|
frame:SetPoint("TOPLEFT", ManagerFrame.scrollChild, "TOPLEFT", 0, - (index) * lineHeight)
|
|
frame:Show()
|
|
index = index + 1
|
|
end
|
|
end
|
|
|
|
-- Adjust the scroll child height
|
|
ManagerFrame.scrollChild.contentHeight = index * lineHeight
|
|
ManagerFrame.scrollChild:SetHeight(ManagerFrame.scrollChild.contentHeight)
|
|
|
|
-- Update the scrollbar
|
|
ConsumesManager_UpdateManagerScrollBar()
|
|
|
|
if not hasAnyVisibleItems then
|
|
-- Hide the order buttons
|
|
ManagerFrame.orderByNameButton:Hide()
|
|
ManagerFrame.orderByAmountButton:Hide()
|
|
-- Show message when no items are selected
|
|
ManagerFrame.messageLabel:SetText("|cffff0000No consumables selected|r\n\n|cffffffffClick on |rItems|cffffffff to get started|r")
|
|
ManagerFrame.messageLabel:Show()
|
|
|
|
-- Reset the scrollChild height
|
|
ManagerFrame.scrollChild.contentHeight = 0
|
|
ManagerFrame.scrollChild:SetHeight(0)
|
|
|
|
-- Update the scrollbar
|
|
ConsumesManager_UpdateManagerScrollBar()
|
|
else
|
|
-- Show the order buttons
|
|
ManagerFrame.orderByNameButton:Show()
|
|
ManagerFrame.orderByAmountButton:Show()
|
|
-- Hide the message label as we have content to display
|
|
ManagerFrame.messageLabel:Hide()
|
|
end
|
|
end
|
|
|
|
function ConsumesManager_UpdateManagerScrollBar()
|
|
local ManagerFrame = ConsumesManager_MainFrame.tabs[1]
|
|
local scrollBar = ManagerFrame.scrollBar
|
|
local scrollFrame = ManagerFrame.scrollFrame
|
|
local scrollChild = ManagerFrame.scrollChild
|
|
|
|
local totalHeight = scrollChild:GetHeight()
|
|
local shownHeight = ManagerFrame:GetHeight() - 20 -- Account for padding/margins
|
|
|
|
if totalHeight > shownHeight then
|
|
local maxScroll = totalHeight - shownHeight
|
|
scrollFrame.range = maxScroll -- Set the scroll range
|
|
scrollBar:SetMinMaxValues(0, maxScroll)
|
|
scrollBar:SetValue(math.min(scrollBar:GetValue(), maxScroll))
|
|
scrollBar:Show()
|
|
else
|
|
scrollFrame.range = 0 -- Also handle this case
|
|
scrollBar:SetMinMaxValues(0, 0)
|
|
scrollBar:SetValue(0)
|
|
scrollBar:Hide()
|
|
end
|
|
end
|
|
|
|
|
|
|
|
-- Items Window -----------------------------------------------------------------------------------
|
|
function ConsumesManager_CreateItemsContent(parentFrame)
|
|
-- Create Search Input
|
|
local searchBox = CreateFrame("EditBox", "ConsumesManager_SearchBox", parentFrame, "InputBoxTemplate")
|
|
searchBox:SetWidth(WindowWidth - 50)
|
|
searchBox:SetHeight(25)
|
|
searchBox:SetPoint("TOPLEFT", parentFrame, "TOPLEFT", 0, -5)
|
|
searchBox:SetAutoFocus(false)
|
|
searchBox:SetText("Search...")
|
|
searchBox:SetTextColor(0.5, 0.5, 0.5) -- Placeholder text color
|
|
|
|
searchBox:SetScript("OnEditFocusGained", function()
|
|
if this:GetText() == "Search..." then
|
|
this:SetText("")
|
|
this:SetTextColor(1, 1, 1) -- User input text color
|
|
end
|
|
end)
|
|
|
|
searchBox:SetScript("OnEditFocusLost", function()
|
|
if this:GetText() == "" then
|
|
this:SetText("Search...")
|
|
this:SetTextColor(0.5, 0.5, 0.5) -- Placeholder text color
|
|
end
|
|
end)
|
|
|
|
-- Function to update the filter
|
|
local function UpdateFilter()
|
|
local filterText = string.lower(searchBox:GetText())
|
|
if filterText == "search..." then filterText = "" end
|
|
local index = 0 -- Position index
|
|
local lineHeight = 18
|
|
|
|
-- Iterate over categories
|
|
for _, categoryInfo in ipairs(parentFrame.categoryInfo) do
|
|
local categoryLabel = categoryInfo.label
|
|
local anyitemVisible = false
|
|
|
|
-- First, check if any Items in the category match the filter
|
|
for _, itemInfo in ipairs(categoryInfo.Items) do
|
|
local itemNameLower = string.lower(itemInfo.name)
|
|
|
|
if filterText == "" or string.find(itemNameLower, filterText, 1, true) then
|
|
anyitemVisible = true
|
|
break
|
|
end
|
|
end
|
|
|
|
-- If any Items are visible, show the category label
|
|
if anyitemVisible then
|
|
categoryLabel:SetPoint("TOPLEFT", parentFrame.scrollChild, "TOPLEFT", 0, - (index) * lineHeight)
|
|
categoryLabel:Show()
|
|
index = index + 1
|
|
|
|
-- Now, position and show the matching Items
|
|
for _, itemInfo in ipairs(categoryInfo.Items) do
|
|
local itemFrame = itemInfo.frame
|
|
local itemNameLower = string.lower(itemInfo.name)
|
|
|
|
if filterText == "" or string.find(itemNameLower, filterText, 1, true) then
|
|
-- Show the item
|
|
itemFrame:SetPoint("TOPLEFT", parentFrame.scrollChild, "TOPLEFT", 0, - (index) * lineHeight)
|
|
itemFrame:Show()
|
|
index = index + 1
|
|
else
|
|
itemFrame:Hide()
|
|
end
|
|
end
|
|
|
|
-- Add extra spacing after the category
|
|
index = index + 1 -- Add one extra line of spacing between categories
|
|
|
|
else
|
|
categoryLabel:Hide()
|
|
-- Hide all Items under this category
|
|
for _, itemInfo in ipairs(categoryInfo.Items) do
|
|
itemInfo.frame:Hide()
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Adjust the scroll child height
|
|
parentFrame.scrollChild.contentHeight = index * lineHeight
|
|
parentFrame.scrollChild:SetHeight(parentFrame.scrollChild.contentHeight)
|
|
|
|
-- Update the scrollbar
|
|
ConsumesManager_UpdateItemsScrollBar()
|
|
end
|
|
|
|
searchBox:SetScript("OnTextChanged", function()
|
|
UpdateFilter()
|
|
end)
|
|
|
|
-- Adjust the size of the scroll frame to make room for the search box and add extra spacing
|
|
local scrollFrame = CreateFrame("ScrollFrame", "ConsumesManager_ItemsScrollFrame", parentFrame)
|
|
scrollFrame:SetPoint("TOPLEFT", parentFrame, "TOPLEFT", 0, -40) -- Start below the search box
|
|
scrollFrame:SetPoint("BOTTOMRIGHT", parentFrame, "BOTTOMRIGHT", -20, 60) -- Leave space for buttons
|
|
scrollFrame:EnableMouseWheel(true)
|
|
scrollFrame:SetScript("OnMouseWheel", function()
|
|
local delta = arg1
|
|
local current = this:GetVerticalScroll()
|
|
local maxScroll = this.maxScroll or 0
|
|
local newScroll = math.max(0, math.min(current - (delta * 20), maxScroll))
|
|
this:SetVerticalScroll(newScroll)
|
|
parentFrame.scrollBar:SetValue(newScroll)
|
|
end)
|
|
|
|
-- Scroll Child Frame
|
|
local scrollChild = CreateFrame("Frame", nil, scrollFrame)
|
|
scrollChild:SetWidth(WindowWidth - 10)
|
|
scrollChild:SetHeight(1) -- Will adjust later
|
|
scrollFrame:SetScrollChild(scrollChild)
|
|
parentFrame.scrollChild = scrollChild
|
|
parentFrame.scrollFrame = scrollFrame
|
|
|
|
-- Sort categories alphabetically
|
|
local sortedCategories = {}
|
|
for categoryName, _ in pairs(consumablesCategories) do
|
|
table.insert(sortedCategories, categoryName)
|
|
end
|
|
table.sort(sortedCategories)
|
|
|
|
-- Checkboxes
|
|
parentFrame.checkboxes = {}
|
|
parentFrame.categoryInfo = {}
|
|
local index = 0 -- Position index
|
|
local lineHeight = 18
|
|
|
|
-- Iterate over sorted categories
|
|
for _, categoryName in ipairs(sortedCategories) do
|
|
local consumables = consumablesCategories[categoryName]
|
|
|
|
-- Create category label
|
|
local categoryLabel = scrollChild:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
|
|
categoryLabel:SetText(categoryName)
|
|
categoryLabel:SetTextColor(1, 1, 1)
|
|
categoryLabel:Show()
|
|
|
|
local categoryInfo = { name = categoryName, label = categoryLabel, Items = {} }
|
|
|
|
index = index + 1 -- Position for the category label
|
|
|
|
local numItemsInCategory = 0 -- Counter for Items in this category
|
|
|
|
-- Sort the consumables by name
|
|
table.sort(consumables, function(a, b) return a.name < b.name end)
|
|
|
|
-- For each consumable in the category
|
|
for _, consumable in ipairs(consumables) do
|
|
local currentItemID = consumable.id
|
|
local itemName = consumable.name
|
|
|
|
-- Create a frame that encompasses the checkbox and label
|
|
local itemFrame = CreateFrame("Frame", "ConsumesManager_ItemsFrame" .. index, scrollChild)
|
|
itemFrame:SetWidth(WindowWidth - 10)
|
|
itemFrame:SetHeight(lineHeight)
|
|
itemFrame:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, - (index) * lineHeight)
|
|
itemFrame:Show()
|
|
|
|
-- Create the checkbox inside the itemFrame
|
|
local checkbox = CreateFrame("CheckButton", "ConsumesManager_ItemsCheckbox" .. index, itemFrame)
|
|
checkbox:SetWidth(16)
|
|
checkbox:SetHeight(16)
|
|
checkbox:SetPoint("LEFT", itemFrame, "LEFT", 0, 0)
|
|
|
|
-- Create Textures for the checkbox
|
|
checkbox:SetNormalTexture("Interface\\Buttons\\UI-CheckBox-Up")
|
|
checkbox:SetPushedTexture("Interface\\Buttons\\UI-CheckBox-Down")
|
|
checkbox:SetHighlightTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
|
|
checkbox:SetCheckedTexture("Interface\\Buttons\\UI-CheckBox-Check")
|
|
|
|
-- Create FontString for label
|
|
local label = itemFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
label:SetPoint("LEFT", checkbox, "RIGHT", 4, 0)
|
|
label:SetText(itemName)
|
|
|
|
-- Set up the checkbox OnClick handler
|
|
checkbox:SetScript("OnClick", function()
|
|
ConsumesManager_SelectedItems[currentItemID] = checkbox:GetChecked()
|
|
ConsumesManager_UpdateManagerContent()
|
|
end)
|
|
-- Load saved setting
|
|
if ConsumesManager_SelectedItems[currentItemID] then
|
|
checkbox:SetChecked(true)
|
|
end
|
|
|
|
parentFrame.checkboxes[currentItemID] = checkbox
|
|
|
|
-- Make the itemFrame clickable
|
|
itemFrame:EnableMouse(true)
|
|
itemFrame:SetScript("OnMouseDown", function()
|
|
checkbox:Click()
|
|
end)
|
|
|
|
-- Mouseover Tooltip
|
|
itemFrame:SetScript("OnEnter", function()
|
|
ConsumesManager_ShowItemsTooltip(currentItemID)
|
|
end)
|
|
itemFrame:SetScript("OnLeave", function()
|
|
if ConsumesManager_ItemsTooltip then
|
|
ConsumesManager_ItemsTooltip:Hide()
|
|
end
|
|
end)
|
|
|
|
-- Store item info
|
|
table.insert(categoryInfo.Items, { frame = itemFrame, name = itemName })
|
|
|
|
index = index + 1 -- Increment index after adding item
|
|
numItemsInCategory = numItemsInCategory + 1 -- Increment Items count
|
|
end
|
|
|
|
-- Position the category label above its Items
|
|
categoryLabel:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, - (index - numItemsInCategory - 1) * lineHeight)
|
|
|
|
-- Store category info
|
|
table.insert(parentFrame.categoryInfo, categoryInfo)
|
|
|
|
-- Add extra spacing after the category
|
|
index = index + 1 -- Add one extra line of spacing between categories
|
|
end
|
|
|
|
-- Adjust the scroll child height
|
|
scrollChild.contentHeight = (index - 1) * lineHeight
|
|
scrollChild:SetHeight(scrollChild.contentHeight)
|
|
|
|
-- Scroll Bar
|
|
local scrollBar = CreateFrame("Slider", "ConsumesManager_ItemsScrollBar", parentFrame)
|
|
-- Corrected Y-offsets to prevent overlapping
|
|
scrollBar:SetPoint("TOPRIGHT", parentFrame, "TOPRIGHT", -2, -40) -- Start below the search box
|
|
scrollBar:SetPoint("BOTTOMRIGHT", parentFrame, "BOTTOMRIGHT", -2, 16) -- End above the buttons
|
|
scrollBar:SetWidth(16)
|
|
scrollBar:SetOrientation('VERTICAL')
|
|
scrollBar:SetThumbTexture("Interface\\Buttons\\UI-ScrollBar-Knob")
|
|
scrollBar:SetBackdrop({
|
|
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 }
|
|
})
|
|
scrollBar:SetScript("OnValueChanged", function()
|
|
local value = this:GetValue()
|
|
parentFrame.scrollFrame:SetVerticalScroll(value)
|
|
end)
|
|
parentFrame.scrollBar = scrollBar
|
|
|
|
-- Update the scrollbar
|
|
ConsumesManager_UpdateItemsScrollBar()
|
|
|
|
-- Create Select All Button
|
|
local selectAllButton = CreateFrame("Button", "ConsumesManager_SelectAllButton", parentFrame, "UIPanelButtonTemplate")
|
|
selectAllButton:SetWidth(100)
|
|
selectAllButton:SetHeight(24)
|
|
selectAllButton:SetText("Select All")
|
|
selectAllButton:SetPoint("BOTTOMLEFT", parentFrame, "BOTTOMLEFT", 20, 10)
|
|
selectAllButton:SetScript("OnClick", function()
|
|
for itemID, checkbox in pairs(parentFrame.checkboxes) do
|
|
checkbox:SetChecked(true)
|
|
ConsumesManager_SelectedItems[itemID] = true
|
|
end
|
|
ConsumesManager_UpdateManagerContent()
|
|
end)
|
|
|
|
-- Create Deselect All Button
|
|
local deselectAllButton = CreateFrame("Button", "ConsumesManager_DeselectAllButton", parentFrame, "UIPanelButtonTemplate")
|
|
deselectAllButton:SetWidth(100)
|
|
deselectAllButton:SetHeight(24)
|
|
deselectAllButton:SetText("Deselect All")
|
|
deselectAllButton:SetPoint("BOTTOMRIGHT", parentFrame, "BOTTOMRIGHT", -40, 10)
|
|
deselectAllButton:SetScript("OnClick", function()
|
|
for itemID, checkbox in pairs(parentFrame.checkboxes) do
|
|
checkbox:SetChecked(false)
|
|
ConsumesManager_SelectedItems[itemID] = false
|
|
end
|
|
ConsumesManager_UpdateManagerContent()
|
|
end)
|
|
end
|
|
|
|
function ConsumesManager_UpdateItemsScrollBar()
|
|
local ItemsFrame = ConsumesManager_MainFrame.tabs[2]
|
|
if not ItemsFrame then
|
|
print("Error: ItemsFrame (tabs[2]) is nil in UpdateItemsScrollBar")
|
|
return
|
|
end
|
|
local scrollBar = ItemsFrame.scrollBar
|
|
local scrollFrame = ItemsFrame.scrollFrame
|
|
local scrollChild = ItemsFrame.scrollChild
|
|
|
|
local totalHeight = scrollChild.contentHeight
|
|
local parentHeight = ItemsFrame:GetHeight()
|
|
local searchBoxHeight = 36 -- Adjusted height including padding
|
|
local buttonsHeight = 40 -- Space reserved for Select/Deselect buttons
|
|
local shownHeight = parentHeight - searchBoxHeight - buttonsHeight - 20 -- Additional padding
|
|
|
|
local maxScroll = math.max(0, totalHeight - shownHeight)
|
|
scrollFrame.maxScroll = maxScroll
|
|
|
|
if totalHeight > shownHeight then
|
|
scrollBar:SetMinMaxValues(0, maxScroll)
|
|
scrollBar:SetValue(math.min(scrollBar:GetValue(), maxScroll))
|
|
scrollBar:Show()
|
|
else
|
|
scrollBar:SetMinMaxValues(0, 0)
|
|
scrollBar:SetValue(0)
|
|
scrollBar:Hide()
|
|
end
|
|
end
|
|
|
|
|
|
|
|
-- Presets Window -----------------------------------------------------------------------------------
|
|
|
|
local classColors = {
|
|
["Rogue"] = "fff569",
|
|
["Mage"] = "69ccf0",
|
|
["Warrior"] = "c79c6e",
|
|
["Hunter"] = "abd473",
|
|
["Druid"] = "ff7d0a",
|
|
["Priest"] = "ffffff",
|
|
["Warlock"] = "9482c9",
|
|
["Shaman"] = "0070dd",
|
|
["Paladin"] = "f58cba"
|
|
}
|
|
|
|
-- Manually ordered raids (adjust as needed)
|
|
local orderedRaids = {
|
|
"Molten Core",
|
|
"Blackwing Lair",
|
|
"Emerald Sanctum",
|
|
"Temple of Ahn'Qiraj",
|
|
"Naxxramas",
|
|
"The Tower of Karazhan"
|
|
}
|
|
|
|
local function GetLastWord(str)
|
|
local spacePos = 0
|
|
while true do
|
|
local found = string.find(str, " ", spacePos + 1)
|
|
if found then
|
|
spacePos = found
|
|
else
|
|
break
|
|
end
|
|
end
|
|
if spacePos == 0 then
|
|
return str
|
|
else
|
|
return string.sub(str, spacePos + 1)
|
|
end
|
|
end
|
|
|
|
local function SortClassesByLastWord(t)
|
|
local n = table.getn(t)
|
|
local i = 1
|
|
while i < n do
|
|
local j = i + 1
|
|
while j <= n do
|
|
local lwA = GetLastWord(t[i])
|
|
local lwB = GetLastWord(t[j])
|
|
if lwA > lwB then
|
|
t[i], t[j] = t[j], t[i]
|
|
end
|
|
j = j + 1
|
|
end
|
|
i = i + 1
|
|
end
|
|
end
|
|
|
|
function ConsumesManager_CreatePresetsContent(parentFrame)
|
|
local lineHeight = 18
|
|
|
|
local raidDropdown = CreateFrame("Frame", "ConsumesManager_PresetsRaidDropdown", parentFrame, "UIDropDownMenuTemplate")
|
|
raidDropdown:SetPoint("TOPLEFT", parentFrame, "TOPLEFT", -20, 0)
|
|
UIDropDownMenu_SetWidth(120, raidDropdown)
|
|
UIDropDownMenu_SetText("Select |cffffff00Raid|r", raidDropdown)
|
|
|
|
local raidDropdownText = getglobal("ConsumesManager_PresetsRaidDropdownText")
|
|
if raidDropdownText then
|
|
raidDropdownText:SetJustifyH("LEFT")
|
|
end
|
|
|
|
local classDropdown = CreateFrame("Frame", "ConsumesManager_PresetsClassDropdown", parentFrame, "UIDropDownMenuTemplate")
|
|
classDropdown:SetPoint("LEFT", raidDropdown, "RIGHT", -20, 0)
|
|
UIDropDownMenu_SetWidth(120, classDropdown)
|
|
UIDropDownMenu_SetText("Select |cffffff00Class|r", classDropdown)
|
|
|
|
local classDropdownText = getglobal("ConsumesManager_PresetsClassDropdownText")
|
|
if classDropdownText then
|
|
classDropdownText:SetJustifyH("LEFT")
|
|
end
|
|
|
|
local classes = {}
|
|
for className, _ in pairs(classPresets) do
|
|
table.insert(classes, className)
|
|
end
|
|
|
|
SortClassesByLastWord(classes)
|
|
|
|
UIDropDownMenu_Initialize(classDropdown, function()
|
|
local idx = 1
|
|
while classes[idx] do
|
|
local cName = classes[idx]
|
|
local cIndex = idx
|
|
local info = {}
|
|
local lastWord = GetLastWord(cName)
|
|
local color = classColors[lastWord] or "ffffff"
|
|
info.text = "|cff" .. color .. cName .. "|r"
|
|
info.func = function()
|
|
UIDropDownMenu_SetSelectedID(classDropdown, cIndex)
|
|
ConsumesManager_SelectedClass = cName
|
|
ConsumesManager_UpdateRaidsDropdown()
|
|
ConsumesManager_UpdatePresetsConsumables()
|
|
end
|
|
UIDropDownMenu_AddButton(info)
|
|
idx = idx + 1
|
|
end
|
|
end)
|
|
|
|
-- Build initial raid list from the first class, but we won't sort them automatically
|
|
-- We rely on our manual "orderedRaids" list
|
|
local uniqueRaids, seen = {}, {}
|
|
local count = 0
|
|
local firstClass = next(classPresets)
|
|
if firstClass then
|
|
local classList = classPresets[firstClass]
|
|
local i = 1
|
|
while classList[i] do
|
|
local rName = classList[i].raid
|
|
if not seen[rName] then
|
|
count = count + 1
|
|
uniqueRaids[count] = rName
|
|
seen[rName] = true
|
|
end
|
|
i = i + 1
|
|
end
|
|
end
|
|
|
|
UIDropDownMenu_Initialize(raidDropdown, function()
|
|
if count == 0 then
|
|
local info = {}
|
|
info.text = "No Raids Available"
|
|
info.disabled = true
|
|
UIDropDownMenu_AddButton(info)
|
|
UIDropDownMenu_SetText("Select |cffffff00Raid|r", raidDropdown)
|
|
return
|
|
end
|
|
local i = 1
|
|
while orderedRaids[i] do
|
|
local orName = orderedRaids[i]
|
|
if seen[orName] then
|
|
local cIndex = i
|
|
local cRaidName = orName
|
|
local info = {}
|
|
info.text = orName
|
|
info.func = function()
|
|
UIDropDownMenu_SetSelectedID(raidDropdown, cIndex)
|
|
ConsumesManager_SelectedRaid = cRaidName
|
|
ConsumesManager_UpdatePresetsConsumables()
|
|
end
|
|
UIDropDownMenu_AddButton(info)
|
|
end
|
|
i = i + 1
|
|
end
|
|
UIDropDownMenu_SetText("Select |cffffff00Raid|r", raidDropdown)
|
|
end)
|
|
|
|
UIDropDownMenu_SetSelectedID(raidDropdown, 0)
|
|
|
|
local scrollFrame = CreateFrame("ScrollFrame", "ConsumesManager_PresetsScrollFrame", parentFrame)
|
|
scrollFrame:SetPoint("TOPLEFT", classDropdown, "BOTTOMLEFT", -135, -40)
|
|
scrollFrame:SetPoint("BOTTOMRIGHT", parentFrame, "BOTTOMRIGHT", -25, -5)
|
|
scrollFrame:EnableMouseWheel(true)
|
|
|
|
local scrollChild = CreateFrame("Frame", nil, scrollFrame)
|
|
scrollChild:SetWidth(parentFrame:GetWidth() - 40)
|
|
scrollChild:SetHeight(1)
|
|
scrollFrame:SetScrollChild(scrollChild)
|
|
parentFrame.scrollChild = scrollChild
|
|
parentFrame.scrollFrame = scrollFrame
|
|
|
|
local scrollBar = CreateFrame("Slider", "ConsumesManager_PresetsScrollBar", parentFrame)
|
|
scrollBar:SetPoint("TOPRIGHT", parentFrame, "TOPRIGHT", -2, -35)
|
|
scrollBar:SetPoint("BOTTOMRIGHT", parentFrame, "BOTTOMRIGHT", -2, 16)
|
|
scrollBar:SetWidth(16)
|
|
scrollBar:SetOrientation('VERTICAL')
|
|
scrollBar:SetThumbTexture("Interface\\Buttons\\UI-ScrollBar-Knob")
|
|
scrollBar:SetBackdrop({
|
|
bgFile = "Interface\\Buttons\\UI-SliderBar-Background",
|
|
edgeFile = "Interface\\Buttons\\UI-SliderBar-Border",
|
|
tile = 1, tileSize = 8, edgeSize = 8,
|
|
insets = { left = 3, right = 3, top = 3, bottom = 3 }
|
|
})
|
|
scrollBar:SetScript("OnValueChanged", function()
|
|
local val = this:GetValue()
|
|
parentFrame.scrollFrame:SetVerticalScroll(val)
|
|
end)
|
|
parentFrame.scrollBar = scrollBar
|
|
scrollBar:Hide()
|
|
|
|
scrollFrame:SetScript("OnMouseWheel", function()
|
|
local d = arg1
|
|
local cur = this:GetVerticalScroll()
|
|
local mx = this.range or 0
|
|
local new = 0
|
|
if d < 0 then
|
|
new = math.min(cur + 20, mx)
|
|
else
|
|
new = math.max(cur - 20, 0)
|
|
end
|
|
this:SetVerticalScroll(new)
|
|
parentFrame.scrollBar:SetValue(new)
|
|
end)
|
|
|
|
local orderByNameButton = CreateFrame("Button", "ConsumesManager_PresetsOrderByNameButton", parentFrame, "UIPanelButtonTemplate")
|
|
orderByNameButton:SetWidth(100)
|
|
orderByNameButton:SetHeight(24)
|
|
orderByNameButton:SetText("Order by Name")
|
|
orderByNameButton:GetFontString():SetFont("Fonts\\FRIZQT__.TTF", 10, "NORMAL")
|
|
orderByNameButton:SetPoint("TOPLEFT", ConsumesManager_MainFrame.tabs[3], "TOPLEFT", -4, -35)
|
|
orderByNameButton:SetScript("OnClick", function()
|
|
if ConsumesManager_Options.presetsSortOrder == "name" then
|
|
if ConsumesManager_Options.presetsSortDirection == "asc" then
|
|
ConsumesManager_Options.presetsSortDirection = "desc"
|
|
else
|
|
ConsumesManager_Options.presetsSortDirection = "asc"
|
|
end
|
|
else
|
|
ConsumesManager_Options.presetsSortOrder = "name"
|
|
ConsumesManager_Options.presetsSortDirection = "asc"
|
|
end
|
|
ConsumesManager_UpdatePresetsConsumables()
|
|
end)
|
|
|
|
local orderByAmountButton = CreateFrame("Button", "ConsumesManager_PresetsOrderByAmountButton", parentFrame, "UIPanelButtonTemplate")
|
|
orderByAmountButton:SetWidth(120)
|
|
orderByAmountButton:SetHeight(24)
|
|
orderByAmountButton:SetText("Order by Amount")
|
|
orderByAmountButton:GetFontString():SetFont("Fonts\\FRIZQT__.TTF", 10, "NORMAL")
|
|
orderByAmountButton:SetPoint("LEFT", orderByNameButton, "RIGHT", 10, 0)
|
|
orderByAmountButton:SetScript("OnClick", function()
|
|
if ConsumesManager_Options.presetsSortOrder == "amount" then
|
|
if ConsumesManager_Options.presetsSortDirection == "desc" then
|
|
ConsumesManager_Options.presetsSortDirection = "asc"
|
|
else
|
|
ConsumesManager_Options.presetsSortDirection = "desc"
|
|
end
|
|
else
|
|
ConsumesManager_Options.presetsSortOrder = "amount"
|
|
ConsumesManager_Options.presetsSortDirection = "desc"
|
|
end
|
|
ConsumesManager_UpdatePresetsConsumables()
|
|
end)
|
|
|
|
parentFrame.orderByNameButton = orderByNameButton
|
|
parentFrame.orderByAmountButton = orderByAmountButton
|
|
orderByNameButton:Hide()
|
|
orderByAmountButton:Hide()
|
|
|
|
parentFrame.presetsConsumables = {}
|
|
local messageLabel = parentFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
messageLabel:SetText("|cffff0000Please select both a Raid and a Class.|r")
|
|
messageLabel:SetPoint("CENTER", parentFrame, "CENTER", 0, 0)
|
|
messageLabel:Hide()
|
|
parentFrame.messageLabel = messageLabel
|
|
end
|
|
|
|
function ConsumesManager_UpdateRaidsDropdown()
|
|
local raidDropdown = getglobal("ConsumesManager_PresetsRaidDropdown")
|
|
if not raidDropdown then
|
|
return
|
|
end
|
|
local prevRaid = ConsumesManager_SelectedRaid
|
|
UIDropDownMenu_ClearAll(raidDropdown)
|
|
|
|
local uniqueRaids, seen = {}, {}
|
|
local c = 0
|
|
if ConsumesManager_SelectedClass and classPresets[ConsumesManager_SelectedClass] then
|
|
local clList = classPresets[ConsumesManager_SelectedClass]
|
|
local i = 1
|
|
while clList[i] do
|
|
local rName = clList[i].raid
|
|
if not seen[rName] then
|
|
c = c + 1
|
|
uniqueRaids[c] = rName
|
|
seen[rName] = true
|
|
end
|
|
i = i + 1
|
|
end
|
|
end
|
|
|
|
UIDropDownMenu_Initialize(raidDropdown, function()
|
|
if c == 0 then
|
|
local info = {}
|
|
info.text = "No Raids Available"
|
|
info.disabled = 1
|
|
UIDropDownMenu_AddButton(info)
|
|
UIDropDownMenu_SetText("Select |cffffff00Raid|r", raidDropdown)
|
|
return
|
|
end
|
|
local i = 1
|
|
local selectedIndex = 0
|
|
while orderedRaids[i] do
|
|
local raidName = orderedRaids[i]
|
|
if seen[raidName] then
|
|
local currentIndex = i
|
|
local currentRaidName = raidName
|
|
local info = {}
|
|
info.text = raidName
|
|
info.func = function()
|
|
UIDropDownMenu_SetSelectedID(raidDropdown, currentIndex)
|
|
ConsumesManager_SelectedRaid = currentRaidName
|
|
ConsumesManager_UpdatePresetsConsumables()
|
|
end
|
|
UIDropDownMenu_AddButton(info)
|
|
if raidName == prevRaid then
|
|
selectedIndex = i
|
|
end
|
|
end
|
|
i = i + 1
|
|
end
|
|
if selectedIndex > 0 then
|
|
UIDropDownMenu_SetSelectedID(raidDropdown, selectedIndex)
|
|
else
|
|
UIDropDownMenu_SetSelectedID(raidDropdown, 0)
|
|
UIDropDownMenu_SetText("Select |cffffff00Raid|r", raidDropdown)
|
|
ConsumesManager_SelectedRaid = nil
|
|
end
|
|
end)
|
|
end
|
|
|
|
|
|
function ConsumesManager_UpdatePresetsScrollBar()
|
|
local PresetsFrame = ConsumesManager_MainFrame.tabs[3]
|
|
if not PresetsFrame then
|
|
return
|
|
end
|
|
|
|
local scrollFrame = PresetsFrame.scrollFrame
|
|
local scrollChild = PresetsFrame.scrollChild
|
|
local scrollBar = PresetsFrame.scrollBar
|
|
|
|
if not scrollFrame or not scrollChild or not scrollBar then
|
|
return
|
|
end
|
|
|
|
local totalHeight = scrollChild:GetHeight()
|
|
local shownHeight = PresetsFrame:GetHeight() - 20 -- Account for padding/margins
|
|
|
|
if totalHeight > shownHeight then
|
|
local maxScroll = totalHeight - shownHeight
|
|
scrollFrame.range = maxScroll -- Set the scroll range
|
|
scrollBar:SetMinMaxValues(0, maxScroll)
|
|
scrollBar:SetValue(math.min(scrollBar:GetValue(), maxScroll))
|
|
scrollBar:Show()
|
|
else
|
|
scrollFrame.range = 0 -- Also handle this case
|
|
scrollBar:SetMinMaxValues(0, 0)
|
|
scrollBar:SetValue(0)
|
|
scrollBar:Hide()
|
|
end
|
|
end
|
|
|
|
function ConsumesManager_UpdatePresetsConsumables()
|
|
-- References to necessary frames
|
|
local parentFrame = ConsumesManager_MainFrame and ConsumesManager_MainFrame.tabs and ConsumesManager_MainFrame.tabs[3]
|
|
if not parentFrame then
|
|
-- Presets tab is not initialized yet
|
|
return
|
|
end
|
|
|
|
local scrollChild = parentFrame.scrollChild
|
|
local scrollFrame = parentFrame.scrollFrame
|
|
local scrollBar = parentFrame.scrollBar
|
|
|
|
-- Initialize presetsConsumables table if not already
|
|
if not parentFrame.presetsConsumables then
|
|
parentFrame.presetsConsumables = {}
|
|
end
|
|
|
|
-- Function to get the number of elements in a table
|
|
local function GetTableLength(t)
|
|
local count = 0
|
|
if type(t) == "table" then
|
|
for _ in pairs(t) do
|
|
count = count + 1
|
|
end
|
|
end
|
|
return count
|
|
end
|
|
|
|
-- Clear existing consumables
|
|
local consumablesCount = GetTableLength(parentFrame.presetsConsumables)
|
|
for i = 1, consumablesCount do
|
|
local consumable = parentFrame.presetsConsumables[i]
|
|
if consumable and consumable.frame and consumable.frame.Hide then
|
|
consumable.frame:Hide()
|
|
end
|
|
end
|
|
parentFrame.presetsConsumables = {}
|
|
|
|
-- Hide "No items" message if it exists
|
|
if parentFrame.noItemsMessage then
|
|
parentFrame.noItemsMessage:Hide()
|
|
end
|
|
|
|
-- Check if both Raid and Class are selected
|
|
if not ConsumesManager_SelectedRaid or not ConsumesManager_SelectedClass then
|
|
-- Show a message prompting the user to select both
|
|
parentFrame.messageLabel:SetText("|cffffffffSelect both a |rRaid|cffffffff and a |rClass|cffffffff.|r")
|
|
parentFrame.messageLabel:Show()
|
|
parentFrame.orderByNameButton:Hide()
|
|
parentFrame.orderByAmountButton:Hide()
|
|
return
|
|
else
|
|
parentFrame.messageLabel:Hide()
|
|
end
|
|
|
|
-- Retrieve the selected preset based on Class and Raid
|
|
local selectedPreset = nil
|
|
if classPresets and classPresets[ConsumesManager_SelectedClass] and type(classPresets[ConsumesManager_SelectedClass]) == "table" then
|
|
local presetListLength = GetTableLength(classPresets[ConsumesManager_SelectedClass])
|
|
for i = 1, presetListLength do
|
|
local preset = classPresets[ConsumesManager_SelectedClass][i]
|
|
if preset and preset.raid == ConsumesManager_SelectedRaid then
|
|
selectedPreset = preset
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Handle case where no preset is found
|
|
if not selectedPreset then
|
|
parentFrame.messageLabel:SetText("|cffff0000No presets found for this combination.|r")
|
|
parentFrame.messageLabel:Show()
|
|
parentFrame.orderByNameButton:Hide()
|
|
parentFrame.orderByAmountButton:Hide()
|
|
return
|
|
end
|
|
|
|
-- Get the consumable IDs from selectedPreset
|
|
local presetIDs = selectedPreset.id
|
|
if not presetIDs or type(presetIDs) ~= "table" then
|
|
parentFrame.messageLabel:SetText("|cffff0000Invalid preset data.|r")
|
|
parentFrame.messageLabel:Show()
|
|
parentFrame.orderByNameButton:Hide()
|
|
parentFrame.orderByAmountButton:Hide()
|
|
return
|
|
end
|
|
|
|
-- Ensure data structure exists
|
|
local realmName = GetRealmName()
|
|
local faction = UnitFactionGroup("player")
|
|
local playerName = UnitName("player")
|
|
|
|
|
|
local data = ConsumesManager_Data[realmName][faction]
|
|
|
|
-- Populate the consumables list based on presetIDs
|
|
-- Initialize tables
|
|
local consumablesList = {}
|
|
local consumablesNameToID = {}
|
|
local consumablesTexture = {}
|
|
local consumablesDescription = {}
|
|
|
|
-- Populate consumablesList and other lookup tables
|
|
for categoryName, consumables in pairs(consumablesCategories) do
|
|
for _, consumable in ipairs(consumables) do
|
|
consumablesList[consumable.id] = consumable.name
|
|
consumablesNameToID[consumable.name] = consumable.id
|
|
consumablesTexture[consumable.id] = consumable.texture
|
|
consumablesDescription[consumable.id] = consumable.description
|
|
end
|
|
end
|
|
|
|
-- Create a mapping from consumable ID to category name
|
|
local consumablesIDToCategory = {}
|
|
for categoryName, consumables in pairs(consumablesCategories) do
|
|
for _, consumable in ipairs(consumables) do
|
|
consumablesIDToCategory[consumable.id] = categoryName
|
|
end
|
|
end
|
|
|
|
-- Main loop to gather consumables to show
|
|
local consumablesToShow = {}
|
|
local presetIDsLength = GetTableLength(presetIDs)
|
|
for i = 1, presetIDsLength do
|
|
local id = presetIDs[i]
|
|
if id and consumablesList[id] then
|
|
-- Calculate total count across selected characters
|
|
local totalCount = 0
|
|
if data and ConsumesManager_SelectedItems and ConsumesManager_Options.Characters and type(ConsumesManager_Options.Characters) == "table" then
|
|
for character, isSelected in pairs(ConsumesManager_Options.Characters) do
|
|
if isSelected and data[character] and type(data[character]) == "table" then
|
|
local charInventory = data[character].inventory or {}
|
|
local charBank = data[character].bank or {}
|
|
local charMail = data[character].mail or {}
|
|
totalCount = totalCount + (charInventory[id] or 0) + (charBank[id] or 0) + (charMail[id] or 0)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Assign category using the mapping table
|
|
local category = consumablesIDToCategory[id] or "Uncategorized"
|
|
|
|
-- Insert consumable with additional data
|
|
table.insert(consumablesToShow, {
|
|
id = id,
|
|
name = consumablesList[id],
|
|
texture = consumablesTexture[id],
|
|
description = consumablesDescription[id],
|
|
totalCount = totalCount,
|
|
category = category
|
|
})
|
|
else
|
|
-- Optional: Handle the else case if needed
|
|
end
|
|
end
|
|
|
|
-- Apply sorting based on settings
|
|
local sortOrder = ConsumesManager_Options.presetsSortOrder or "name"
|
|
local sortDirection = ConsumesManager_Options.presetsSortDirection or "asc"
|
|
|
|
-- Sorting function
|
|
local function SortConsumables(a, b)
|
|
if sortOrder == "name" then
|
|
if sortDirection == "asc" then
|
|
return a.name < b.name
|
|
else
|
|
return a.name > b.name
|
|
end
|
|
elseif sortOrder == "amount" then
|
|
if sortDirection == "asc" then
|
|
return a.totalCount < b.totalCount
|
|
else
|
|
return a.totalCount > b.totalCount
|
|
end
|
|
else
|
|
-- Default to name ascending
|
|
return a.name < b.name
|
|
end
|
|
end
|
|
|
|
-- Sort consumablesToShow
|
|
if table and table.sort then
|
|
table.sort(consumablesToShow, SortConsumables)
|
|
else
|
|
-- Implement a simple bubble sort if table.sort is unavailable
|
|
local n = GetTableLength(consumablesToShow)
|
|
for i = 1, n - 1 do
|
|
for j = 1, n - i do
|
|
if not SortConsumables(consumablesToShow[j], consumablesToShow[j + 1]) then
|
|
-- Swap
|
|
consumablesToShow[j], consumablesToShow[j + 1] = consumablesToShow[j + 1], consumablesToShow[j]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Initialize variables for display
|
|
local index = 0
|
|
local lineHeight = 18
|
|
local hasAnyVisibleItems = false
|
|
|
|
-- Get settings
|
|
local enableCategories = ConsumesManager_Options.enableCategories or false
|
|
local showUseButton = ConsumesManager_Options.showUseButton or false
|
|
|
|
if enableCategories then
|
|
-- Group consumables by category
|
|
local categories = {}
|
|
local consumablesToShowLength = GetTableLength(consumablesToShow)
|
|
for i = 1, consumablesToShowLength do
|
|
local consumable = consumablesToShow[i]
|
|
local category = consumable.category or "Uncategorized"
|
|
if not categories[category] then
|
|
categories[category] = {}
|
|
end
|
|
table.insert(categories[category], consumable)
|
|
end
|
|
|
|
-- Sort category names alphabetically
|
|
local sortedCategoryNames = {}
|
|
for categoryName in pairs(categories) do
|
|
table.insert(sortedCategoryNames, categoryName)
|
|
end
|
|
if table and table.sort then
|
|
table.sort(sortedCategoryNames)
|
|
else
|
|
-- Simple bubble sort if table.sort is unavailable
|
|
local n = GetTableLength(sortedCategoryNames)
|
|
for i = 1, n - 1 do
|
|
for j = 1, n - i do
|
|
if sortedCategoryNames[j] > sortedCategoryNames[j + 1] then
|
|
sortedCategoryNames[j], sortedCategoryNames[j + 1] = sortedCategoryNames[j + 1], sortedCategoryNames[j]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Iterate over each category
|
|
local sortedCategoryNamesLength = GetTableLength(sortedCategoryNames)
|
|
for i = 1, sortedCategoryNamesLength do
|
|
local categoryName = sortedCategoryNames[i]
|
|
local items = categories[categoryName]
|
|
|
|
if items and GetTableLength(items) > 0 then
|
|
-- Create and display category label
|
|
index = index + 1
|
|
local categoryFrame = CreateFrame("Frame", "ConsumesManager_CategoryFrame" .. index, scrollChild)
|
|
categoryFrame:SetWidth(scrollChild:GetWidth() - 10)
|
|
categoryFrame:SetHeight(lineHeight)
|
|
categoryFrame:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, - ((index - 1) * lineHeight))
|
|
categoryFrame:Show()
|
|
|
|
local categoryLabel = categoryFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
|
|
categoryLabel:SetPoint("LEFT", categoryFrame, "LEFT", 0, 0)
|
|
categoryLabel:SetText(categoryName)
|
|
categoryLabel:SetJustifyH("LEFT")
|
|
categoryLabel:SetTextColor(1, 1, 1)
|
|
|
|
|
|
-- Store the category frame
|
|
table.insert(parentFrame.presetsConsumables, {
|
|
frame = categoryFrame,
|
|
label = categoryLabel,
|
|
isCategory = true
|
|
})
|
|
|
|
-- Increment index for items under the category
|
|
index = index + 1
|
|
|
|
-- Sort items within the category
|
|
if table and table.sort then
|
|
table.sort(items, SortConsumables)
|
|
else
|
|
-- Simple bubble sort if table.sort is unavailable
|
|
local m = GetTableLength(items)
|
|
for p = 1, m - 1 do
|
|
for q = 1, m - p do
|
|
if not SortConsumables(items[q], items[q + 1]) then
|
|
items[q], items[q + 1] = items[q + 1], items[q]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Iterate through each consumable in the category
|
|
local itemsLength = GetTableLength(items)
|
|
for j = 1, itemsLength do
|
|
local consumable = items[j]
|
|
if consumable then
|
|
-- Create consumable frame
|
|
local frame = CreateFrame("Frame", "ConsumesManager_PresetsConsumableFrame" .. index, scrollChild)
|
|
frame:SetWidth(scrollChild:GetWidth() - 10)
|
|
frame:SetHeight(lineHeight)
|
|
frame:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, - ((index - 1) * lineHeight))
|
|
frame:Show()
|
|
frame:EnableMouse(true) -- Enable mouse for tooltip
|
|
|
|
-- Create "Use" button if enabled
|
|
local useButton = nil
|
|
if showUseButton then
|
|
useButton = CreateFrame("Button", "ConsumesManager_PresetsUseButton" .. index, frame, "UIPanelButtonTemplate")
|
|
useButton:SetWidth(40)
|
|
useButton:SetHeight(16)
|
|
useButton:SetPoint("LEFT", frame, "LEFT", 0, 0)
|
|
useButton:SetText("Use")
|
|
useButton:SetScript("OnClick", function()
|
|
local bag, slot = ConsumesManager_FindItemInBags(consumable.id)
|
|
if bag and slot then
|
|
UseContainerItem(bag, slot)
|
|
else
|
|
DEFAULT_CHAT_FRAME:AddMessage("Item not found in bags.")
|
|
end
|
|
end)
|
|
end
|
|
|
|
-- Create label with count
|
|
local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
if showUseButton and useButton then
|
|
label:SetPoint("LEFT", useButton, "RIGHT", 4, 0)
|
|
else
|
|
label:SetPoint("LEFT", frame, "LEFT", 0, 0)
|
|
end
|
|
label:SetText(consumable.name .. " (" .. consumable.totalCount .. ")")
|
|
label:SetJustifyH("LEFT")
|
|
|
|
-- Adjust label color based on count
|
|
if consumable.totalCount == 0 then
|
|
label:SetTextColor(1, 0, 0) -- Red
|
|
elseif consumable.totalCount < 10 then
|
|
label:SetTextColor(1, 0.4, 0) -- Orange
|
|
elseif consumable.totalCount <= 20 then
|
|
label:SetTextColor(1, 0.85, 0) -- Yellow
|
|
else
|
|
label:SetTextColor(0, 1, 0) -- Green
|
|
end
|
|
|
|
-- Tooltip handling
|
|
frame:SetScript("OnEnter", function()
|
|
ConsumesManager_ShowConsumableTooltip(consumable.id)
|
|
end)
|
|
frame:SetScript("OnLeave", function()
|
|
if ConsumesManager_CustomTooltip and ConsumesManager_CustomTooltip.Hide then
|
|
ConsumesManager_CustomTooltip:Hide()
|
|
end
|
|
end)
|
|
|
|
-- Enable or disable "Use" button based on inventory
|
|
if useButton then
|
|
local playerInventory = (data and data[playerName] and data[playerName].inventory) or {}
|
|
local countInInventory = playerInventory[consumable.id] or 0
|
|
|
|
if countInInventory > 0 then
|
|
useButton:Enable()
|
|
else
|
|
useButton:Disable()
|
|
end
|
|
end
|
|
|
|
-- Store the consumable frame
|
|
table.insert(parentFrame.presetsConsumables, {
|
|
frame = frame,
|
|
label = label,
|
|
useButton = useButton,
|
|
id = consumable.id
|
|
})
|
|
|
|
index = index + 1
|
|
hasAnyVisibleItems = true
|
|
end
|
|
end
|
|
|
|
end
|
|
end
|
|
else
|
|
-- Categories are disabled; display all consumables in a single list
|
|
local consumablesToShowLength = GetTableLength(consumablesToShow)
|
|
for i = 1, consumablesToShowLength do
|
|
local consumable = consumablesToShow[i]
|
|
if consumable then
|
|
-- Create consumable frame
|
|
index = index + 1
|
|
|
|
local frame = CreateFrame("Frame", "ConsumesManager_PresetsConsumableFrame" .. index, scrollChild)
|
|
frame:SetWidth(scrollChild:GetWidth() - 10)
|
|
frame:SetHeight(lineHeight)
|
|
frame:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 5, - ((index - 1) * lineHeight))
|
|
frame:Show()
|
|
frame:EnableMouse(true) -- Enable mouse for tooltip
|
|
|
|
-- Create "Use" button if enabled
|
|
local useButton = nil
|
|
if showUseButton then
|
|
useButton = CreateFrame("Button", "ConsumesManager_PresetsUseButton" .. index, frame, "UIPanelButtonTemplate")
|
|
useButton:SetWidth(40)
|
|
useButton:SetHeight(16)
|
|
useButton:SetPoint("LEFT", frame, "LEFT", 0, 0)
|
|
useButton:SetText("Use")
|
|
useButton:SetScript("OnClick", function()
|
|
local bag, slot = ConsumesManager_FindItemInBags(consumable.id)
|
|
if bag and slot then
|
|
UseContainerItem(bag, slot)
|
|
else
|
|
DEFAULT_CHAT_FRAME:AddMessage("Item not found in bags.")
|
|
end
|
|
end)
|
|
end
|
|
|
|
-- Create label with count
|
|
local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
if showUseButton and useButton then
|
|
label:SetPoint("LEFT", useButton, "RIGHT", 4, 0)
|
|
else
|
|
label:SetPoint("LEFT", frame, "LEFT", 0, 0)
|
|
end
|
|
label:SetText(consumable.name .. " (" .. consumable.totalCount .. ")")
|
|
label:SetJustifyH("LEFT")
|
|
|
|
-- Adjust label color based on count
|
|
if consumable.totalCount == 0 then
|
|
label:SetTextColor(1, 0, 0) -- Red
|
|
elseif consumable.totalCount < 10 then
|
|
label:SetTextColor(1, 0.4, 0) -- Orange
|
|
elseif consumable.totalCount <= 20 then
|
|
label:SetTextColor(1, 0.85, 0) -- Yellow
|
|
else
|
|
label:SetTextColor(0, 1, 0) -- Green
|
|
end
|
|
|
|
-- Tooltip handling
|
|
frame:SetScript("OnEnter", function()
|
|
ConsumesManager_ShowConsumableTooltip(consumable.id)
|
|
end)
|
|
frame:SetScript("OnLeave", function()
|
|
if ConsumesManager_CustomTooltip and ConsumesManager_CustomTooltip.Hide then
|
|
ConsumesManager_CustomTooltip:Hide()
|
|
end
|
|
end)
|
|
|
|
-- Enable or disable "Use" button based on inventory
|
|
if useButton then
|
|
local playerInventory = (data and data[playerName] and data[playerName].inventory) or {}
|
|
local countInInventory = playerInventory[consumable.id] or 0
|
|
|
|
if countInInventory > 0 then
|
|
useButton:Enable()
|
|
else
|
|
useButton:Disable()
|
|
end
|
|
end
|
|
|
|
-- Store the consumable frame
|
|
table.insert(parentFrame.presetsConsumables, {
|
|
frame = frame,
|
|
label = label,
|
|
useButton = useButton,
|
|
id = consumable.id
|
|
})
|
|
|
|
|
|
hasAnyVisibleItems = true
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Adjust the scroll child height based on the number of items
|
|
scrollChild:SetHeight(index * lineHeight + 40)
|
|
|
|
-- Show sorting order buttons
|
|
parentFrame.orderByNameButton:Show()
|
|
parentFrame.orderByAmountButton:Show()
|
|
|
|
-- Update the scrollbar to reflect new content
|
|
ConsumesManager_UpdatePresetsScrollBar()
|
|
|
|
-- Handle the case where no consumables are visible
|
|
if not hasAnyVisibleItems then
|
|
-- Create and show a "No consumables available" message if it doesn't exist
|
|
if not parentFrame.noItemsMessage then
|
|
parentFrame.noItemsMessage = parentFrame.messageLabel
|
|
|
|
parentFrame.noItemsMessage:SetText("|cffff0000This preset is not available yet.|r")
|
|
|
|
parentFrame.orderByNameButton:Hide()
|
|
parentFrame.orderByAmountButton:Hide()
|
|
|
|
|
|
end
|
|
parentFrame.noItemsMessage:Show()
|
|
else
|
|
-- Hide the message if it exists
|
|
if parentFrame.noItemsMessage then
|
|
parentFrame.noItemsMessage:Hide()
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
function ConsumesManager_IsItemInPresets(itemID)
|
|
for className, presets in pairs(classPresets) do
|
|
for _, preset in ipairs(presets) do
|
|
for _, id in ipairs(preset.id) do
|
|
if id == itemID then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Settings Window -----------------------------------------------------------------------------------
|
|
function ConsumesManager_CreateSettingsContent(parentFrame)
|
|
-- Scroll Frame Setup
|
|
local scrollFrame = CreateFrame("ScrollFrame", "ConsumesManager_SettingsScrollFrame", parentFrame)
|
|
scrollFrame:SetPoint("TOPLEFT", parentFrame, "TOPLEFT", 0, 0)
|
|
scrollFrame:SetPoint("BOTTOMRIGHT", parentFrame, "BOTTOMRIGHT", -20, 0)
|
|
scrollFrame:EnableMouseWheel(true)
|
|
scrollFrame:SetScript("OnMouseWheel", function()
|
|
local delta = arg1
|
|
local current = this:GetVerticalScroll()
|
|
local maxScroll = this.maxScroll or 0
|
|
local newScroll = math.max(0, math.min(current - (delta * 20), maxScroll))
|
|
this:SetVerticalScroll(newScroll)
|
|
parentFrame.scrollBar:SetValue(newScroll)
|
|
end)
|
|
|
|
local scrollChild = CreateFrame("Frame", nil, scrollFrame)
|
|
scrollChild:SetWidth(WindowWidth - 10)
|
|
scrollChild:SetHeight(1)
|
|
scrollFrame:SetScrollChild(scrollChild)
|
|
parentFrame.scrollChild = scrollChild
|
|
parentFrame.scrollFrame = scrollFrame
|
|
|
|
parentFrame.checkboxes = {}
|
|
local index = 0
|
|
local lineHeight = 20
|
|
|
|
ConsumesManager_Options["Characters"] = ConsumesManager_Options["Characters"] or {}
|
|
ConsumesManager_Options.enableCategories = (ConsumesManager_Options.enableCategories == nil) and true or ConsumesManager_Options.enableCategories
|
|
ConsumesManager_Options.showUseButton = (ConsumesManager_Options.showUseButton == nil) and true or ConsumesManager_Options.showUseButton
|
|
|
|
local realmName = GetRealmName()
|
|
local faction = UnitFactionGroup("player")
|
|
local playerName = UnitName("player")
|
|
|
|
local characterList = {}
|
|
if ConsumesManager_Data[realmName] and ConsumesManager_Data[realmName][faction] then
|
|
for characterName, _ in pairs(ConsumesManager_Data[realmName][faction]) do
|
|
table.insert(characterList, characterName)
|
|
end
|
|
end
|
|
|
|
local playerInList = false
|
|
for _, name in ipairs(characterList) do
|
|
if name == playerName then
|
|
playerInList = true
|
|
break
|
|
end
|
|
end
|
|
if not playerInList then
|
|
table.insert(characterList, playerName)
|
|
end
|
|
|
|
table.sort(characterList)
|
|
|
|
-- Title
|
|
local title = scrollChild:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
|
|
title:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, 0)
|
|
title:SetText("Select Characters To Track")
|
|
title:SetTextColor(1, 1, 1)
|
|
|
|
local startYOffset = -20
|
|
|
|
-- Character Checkboxes
|
|
for _, characterName in ipairs(characterList) do
|
|
index = index + 1
|
|
local currentCharacterName = characterName
|
|
|
|
local itemFrame = CreateFrame("Frame", "ConsumesManager_CharacterFrame" .. index, scrollChild)
|
|
itemFrame:SetWidth(WindowWidth - 10)
|
|
itemFrame:SetHeight(18)
|
|
itemFrame:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, startYOffset - (index - 1) * lineHeight)
|
|
|
|
local checkbox = CreateFrame("CheckButton", "ConsumesManager_CharacterCheckbox" .. index, itemFrame)
|
|
checkbox:SetWidth(16)
|
|
checkbox:SetHeight(16)
|
|
checkbox:SetPoint("LEFT", itemFrame, "LEFT", 0, 0)
|
|
|
|
checkbox:SetNormalTexture("Interface\\Buttons\\UI-CheckBox-Up")
|
|
checkbox:SetPushedTexture("Interface\\Buttons\\UI-CheckBox-Down")
|
|
checkbox:SetHighlightTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
|
|
checkbox:SetCheckedTexture("Interface\\Buttons\\UI-CheckBox-Check")
|
|
|
|
local label = itemFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
label:SetPoint("LEFT", checkbox, "RIGHT", 4, 0)
|
|
label:SetText(currentCharacterName)
|
|
label:SetJustifyH("LEFT")
|
|
|
|
checkbox:SetScript("OnClick", function()
|
|
ConsumesManager_Options["Characters"][currentCharacterName] = (checkbox:GetChecked() == 1)
|
|
ConsumesManager_UpdateAllContent()
|
|
end)
|
|
|
|
if ConsumesManager_Options["Characters"][currentCharacterName] == nil then
|
|
checkbox:SetChecked(true)
|
|
ConsumesManager_Options["Characters"][currentCharacterName] = true
|
|
else
|
|
checkbox:SetChecked(ConsumesManager_Options["Characters"][currentCharacterName] == true)
|
|
end
|
|
|
|
parentFrame.checkboxes[currentCharacterName] = checkbox
|
|
itemFrame:EnableMouse(true)
|
|
itemFrame:SetScript("OnMouseDown", function()
|
|
checkbox:Click()
|
|
end)
|
|
end
|
|
|
|
index = index + 1
|
|
|
|
-- General Settings Title
|
|
local generalSettingsTitle = scrollChild:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
|
|
generalSettingsTitle:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, startYOffset - index * lineHeight)
|
|
generalSettingsTitle:SetText("General Settings")
|
|
generalSettingsTitle:SetTextColor(1, 1, 1)
|
|
|
|
index = index + 1
|
|
|
|
-- Enable Categories Checkbox
|
|
local enableCategoriesFrame = CreateFrame("Frame", "ConsumesManager_EnableCategoriesFrame", scrollChild)
|
|
enableCategoriesFrame:SetWidth(WindowWidth - 10)
|
|
enableCategoriesFrame:SetHeight(18)
|
|
enableCategoriesFrame:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, startYOffset - index * lineHeight)
|
|
enableCategoriesFrame:EnableMouse(true)
|
|
|
|
local enableCategoriesCheckbox = CreateFrame("CheckButton", "ConsumesManager_EnableCategoriesCheckbox", enableCategoriesFrame)
|
|
enableCategoriesCheckbox:SetWidth(16)
|
|
enableCategoriesCheckbox:SetHeight(16)
|
|
enableCategoriesCheckbox:SetPoint("LEFT", enableCategoriesFrame, "LEFT", 0, 0)
|
|
enableCategoriesCheckbox:SetNormalTexture("Interface\\Buttons\\UI-CheckBox-Up")
|
|
enableCategoriesCheckbox:SetPushedTexture("Interface\\Buttons\\UI-CheckBox-Down")
|
|
enableCategoriesCheckbox:SetHighlightTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
|
|
enableCategoriesCheckbox:SetCheckedTexture("Interface\\Buttons\\UI-CheckBox-Check")
|
|
enableCategoriesCheckbox:SetChecked(ConsumesManager_Options.enableCategories)
|
|
|
|
enableCategoriesCheckbox:SetScript("OnClick", function()
|
|
ConsumesManager_Options.enableCategories = enableCategoriesCheckbox:GetChecked()
|
|
ConsumesManager_UpdateAllContent()
|
|
end)
|
|
|
|
local enableCategoriesLabel = enableCategoriesFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
enableCategoriesLabel:SetPoint("LEFT", enableCategoriesCheckbox, "RIGHT", 4, 0)
|
|
enableCategoriesLabel:SetText("Enable Categories")
|
|
enableCategoriesLabel:SetJustifyH("LEFT")
|
|
enableCategoriesFrame:SetScript("OnMouseDown", function()
|
|
enableCategoriesCheckbox:Click()
|
|
end)
|
|
|
|
index = index + 1
|
|
|
|
-- Show Use Button Checkbox
|
|
local showUseButtonFrame = CreateFrame("Frame", "ConsumesManager_ShowUseButtonFrame", scrollChild)
|
|
showUseButtonFrame:SetWidth(WindowWidth - 10)
|
|
showUseButtonFrame:SetHeight(18)
|
|
showUseButtonFrame:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, startYOffset - index * lineHeight)
|
|
showUseButtonFrame:EnableMouse(true)
|
|
|
|
local showUseButtonCheckbox = CreateFrame("CheckButton", "ConsumesManager_ShowUseButtonCheckbox", showUseButtonFrame)
|
|
showUseButtonCheckbox:SetWidth(16)
|
|
showUseButtonCheckbox:SetHeight(16)
|
|
showUseButtonCheckbox:SetPoint("LEFT", showUseButtonFrame, "LEFT", 0, 0)
|
|
showUseButtonCheckbox:SetNormalTexture("Interface\\Buttons\\UI-CheckBox-Up")
|
|
showUseButtonCheckbox:SetPushedTexture("Interface\\Buttons\\UI-CheckBox-Down")
|
|
showUseButtonCheckbox:SetHighlightTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
|
|
showUseButtonCheckbox:SetCheckedTexture("Interface\\Buttons\\UI-CheckBox-Check")
|
|
showUseButtonCheckbox:SetChecked(ConsumesManager_Options.showUseButton)
|
|
|
|
showUseButtonCheckbox:SetScript("OnClick", function()
|
|
ConsumesManager_Options.showUseButton = showUseButtonCheckbox:GetChecked()
|
|
ConsumesManager_UpdateAllContent()
|
|
end)
|
|
|
|
local showUseButtonLabel = showUseButtonFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
showUseButtonLabel:SetPoint("LEFT", showUseButtonCheckbox, "RIGHT", 4, 0)
|
|
showUseButtonLabel:SetText("Show Use Button")
|
|
showUseButtonLabel:SetJustifyH("LEFT")
|
|
showUseButtonFrame:SetScript("OnMouseDown", function()
|
|
showUseButtonCheckbox:Click()
|
|
end)
|
|
|
|
index = index + 1
|
|
|
|
-- Multi-Account Setup
|
|
local multiAccountTitle = scrollChild:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
|
|
multiAccountTitle:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, startYOffset - index * lineHeight - 20)
|
|
multiAccountTitle:SetText("Multi-Account Setup |cffff0000(BETA!)|r")
|
|
multiAccountTitle:SetTextColor(1, 1, 1)
|
|
|
|
index = index + 1
|
|
|
|
local multiAccountInfo = scrollChild:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
multiAccountInfo:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, startYOffset - index * lineHeight - 20)
|
|
multiAccountInfo:SetText("Set a unique channel name and password. \nRepeat this setup for each of your alt-accounts.")
|
|
multiAccountInfo:SetJustifyH("LEFT")
|
|
|
|
index = index + 2
|
|
|
|
-- More Info Button
|
|
local popup = MultiAccountInfoPopup()
|
|
local MoreInfoBtn = CreateFrame("Button", "ConsumesManager_MoreInfoBtn", scrollChild, "UIPanelButtonTemplate")
|
|
MoreInfoBtn:SetWidth(70)
|
|
MoreInfoBtn:SetHeight(20)
|
|
MoreInfoBtn:SetText("More Info")
|
|
MoreInfoBtn:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, startYOffset - index * lineHeight - 10)
|
|
MoreInfoBtn:SetScript("OnClick", function()
|
|
if popup:IsShown() then
|
|
popup:Hide()
|
|
else
|
|
popup:Show()
|
|
end
|
|
end)
|
|
|
|
index = index + 1
|
|
|
|
-- Channel Input
|
|
local channelLabel = scrollChild:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
channelLabel:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, startYOffset - index * lineHeight - 20)
|
|
channelLabel:SetText("Channel:")
|
|
channelLabel:SetWidth(60)
|
|
channelLabel:SetJustifyH("LEFT")
|
|
channelLabel:SetTextColor(1, 1, 1)
|
|
|
|
-- Create a frame to hold the editbox so the sub-textures stay aligned
|
|
local channelFrame = CreateFrame("Frame", nil, scrollChild)
|
|
channelFrame:SetHeight(20)
|
|
channelFrame:SetWidth(140)
|
|
channelFrame:SetPoint("LEFT", channelLabel, "RIGHT", 10, 0)
|
|
|
|
local channelEditBox = CreateFrame("EditBox", "ConsumesManager_ChannelEditBox", channelFrame, "InputBoxTemplate")
|
|
channelEditBox:SetAutoFocus(false)
|
|
channelEditBox:SetMaxLetters(50)
|
|
channelEditBox:SetAllPoints(channelFrame) -- Fill the entire holding frame
|
|
|
|
local leftTex = getglobal(channelEditBox:GetName().."Left")
|
|
local midTex = getglobal(channelEditBox:GetName().."Middle")
|
|
local rightTex= getglobal(channelEditBox:GetName().."Right")
|
|
|
|
-- Anchor them so they move with the EditBox
|
|
if leftTex then
|
|
leftTex:ClearAllPoints()
|
|
leftTex:SetPoint("LEFT", channelEditBox, "LEFT", -5, 0)
|
|
end
|
|
if midTex then
|
|
midTex:ClearAllPoints()
|
|
midTex:SetPoint("LEFT", leftTex, "RIGHT", 0, 0)
|
|
midTex:SetPoint("RIGHT", rightTex, "LEFT", 0, 0)
|
|
end
|
|
if rightTex then
|
|
rightTex:ClearAllPoints()
|
|
rightTex:SetPoint("RIGHT", channelEditBox, "RIGHT", 5, 0)
|
|
end
|
|
|
|
-- Retrieve stored channel
|
|
local stored_channel = ""
|
|
if ConsumesManager_Options.Channel and ConsumesManager_Options.Channel ~= "" then
|
|
stored_channel = DecodeMessage(ConsumesManager_Options.Channel)
|
|
end
|
|
channelEditBox:SetText(stored_channel)
|
|
|
|
index = index + 1
|
|
|
|
-- Password Input
|
|
local passwordLabel = scrollChild:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
passwordLabel:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, startYOffset - index * lineHeight - 20)
|
|
passwordLabel:SetText("Password:")
|
|
passwordLabel:SetWidth(60)
|
|
passwordLabel:SetJustifyH("LEFT")
|
|
passwordLabel:SetTextColor(1, 1, 1)
|
|
|
|
-- Same holding frame approach
|
|
local passwordFrame = CreateFrame("Frame", nil, scrollChild)
|
|
passwordFrame:SetHeight(20)
|
|
passwordFrame:SetWidth(140)
|
|
passwordFrame:SetPoint("LEFT", passwordLabel, "RIGHT", 10, 0)
|
|
|
|
local passwordEditBox = CreateFrame("EditBox", "ConsumesManager_PasswordEditBox", passwordFrame, "InputBoxTemplate")
|
|
passwordEditBox:SetAutoFocus(false)
|
|
passwordEditBox:SetMaxLetters(50)
|
|
passwordEditBox:SetAllPoints(passwordFrame)
|
|
|
|
local pLeft = getglobal(passwordEditBox:GetName().."Left")
|
|
local pMid = getglobal(passwordEditBox:GetName().."Middle")
|
|
local pRight= getglobal(passwordEditBox:GetName().."Right")
|
|
|
|
if pLeft then
|
|
pLeft:ClearAllPoints()
|
|
pLeft:SetPoint("LEFT", passwordEditBox, "LEFT", -5, 0)
|
|
end
|
|
if pMid then
|
|
pMid:ClearAllPoints()
|
|
pMid:SetPoint("LEFT", pLeft, "RIGHT", 0, 0)
|
|
pMid:SetPoint("RIGHT", pRight, "LEFT", 0, 0)
|
|
end
|
|
if pRight then
|
|
pRight:ClearAllPoints()
|
|
pRight:SetPoint("RIGHT", passwordEditBox, "RIGHT", 5, 0)
|
|
end
|
|
|
|
local stored_password = ""
|
|
if ConsumesManager_Options.Password and ConsumesManager_Options.Password ~= "" then
|
|
stored_password = DecodeMessage(ConsumesManager_Options.Password)
|
|
end
|
|
passwordEditBox:SetText(stored_password)
|
|
|
|
index = index + 1
|
|
|
|
-- Join and Leave Channel Buttons
|
|
joinChannelButton = CreateFrame("Button", "ConsumesManager_JoinChannelButton", scrollChild, "UIPanelButtonTemplate")
|
|
joinChannelButton:SetWidth(140)
|
|
joinChannelButton:SetHeight(24)
|
|
joinChannelButton:SetText("Save & Join Channel")
|
|
joinChannelButton:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, startYOffset - index * lineHeight - 25)
|
|
|
|
LeaveChannelButton = CreateFrame("Button", "ConsumesManager_LeaveChannelButton", scrollChild, "UIPanelButtonTemplate")
|
|
LeaveChannelButton:SetWidth(140)
|
|
LeaveChannelButton:SetHeight(24)
|
|
LeaveChannelButton:SetText("Leave Channel")
|
|
LeaveChannelButton:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 140, startYOffset - index * lineHeight - 25)
|
|
|
|
-- Function to Update Leave Button State
|
|
local function UpdateLeaveButtonState()
|
|
if ConsumesManager_Options.Channel == "" or ConsumesManager_Options.Channel == nil then
|
|
LeaveChannelButton:Disable()
|
|
LeaveChannelButton:SetAlpha(0.5)
|
|
channelEditBox:SetText("")
|
|
passwordEditBox:SetText("")
|
|
else
|
|
LeaveChannelButton:Enable()
|
|
LeaveChannelButton:SetAlpha(1)
|
|
end
|
|
end
|
|
|
|
UpdateLeaveButtonState()
|
|
|
|
-- Leave Channel Button Script
|
|
LeaveChannelButton:SetScript("OnClick", function()
|
|
if ConsumesManager_Options.Channel == "" or ConsumesManager_Options.Channel == nil then
|
|
UpdateLeaveButtonState()
|
|
updateSenDataButtonState()
|
|
else
|
|
local decoded_channel = DecodeMessage(ConsumesManager_Options.Channel)
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffffffff" .. GetAddOnMetadata("ConsumesManager", "Title") .. ":|r |cffffffffYou left|r |cffffc0c0[" .. decoded_channel .. "]|r|cffffffff. Multi-account sync |cffff0000disabled|r|cffffffff.|r")
|
|
LeaveChannelByName(decoded_channel)
|
|
ConsumesManager_Options.Channel = nil
|
|
ConsumesManager_Options.Password = nil
|
|
UpdateLeaveButtonState()
|
|
updateSenDataButtonState()
|
|
channelErrorMessage:Hide()
|
|
end
|
|
end)
|
|
|
|
-- Channel Error Message
|
|
local channelErrorMessage = scrollChild:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
channelErrorMessage:SetPoint("TOPLEFT", joinChannelButton, "BOTTOMLEFT", 0, -5)
|
|
channelErrorMessage:SetTextColor(1, 0, 0)
|
|
channelErrorMessage:SetText("Failed to join channel. Read chat for more info.")
|
|
channelErrorMessage:Hide()
|
|
|
|
-- Function to Update Join Button State
|
|
local function UpdateJoinButtonState()
|
|
local ctext = channelEditBox:GetText()
|
|
local ptext = passwordEditBox:GetText()
|
|
if ctext ~= "" and ptext ~= "" then
|
|
joinChannelButton:Enable()
|
|
joinChannelButton:SetAlpha(1)
|
|
else
|
|
joinChannelButton:Disable()
|
|
joinChannelButton:SetAlpha(0.5)
|
|
end
|
|
end
|
|
|
|
channelEditBox:SetScript("OnTextChanged", UpdateJoinButtonState)
|
|
passwordEditBox:SetScript("OnTextChanged", UpdateJoinButtonState)
|
|
|
|
UpdateJoinButtonState()
|
|
|
|
-- Function to Handle Channel Join Failures
|
|
function ConsumesManager_ChannelJoinFailed(error_message)
|
|
ConsumesManager_Options.Channel = nil
|
|
ConsumesManager_Options.Password = nil
|
|
channelEditBox:SetText("")
|
|
passwordEditBox:SetText("")
|
|
UpdateJoinButtonState()
|
|
channelErrorMessage:Show()
|
|
channelErrorMessage:SetText(error_message)
|
|
end
|
|
|
|
index = index + 3
|
|
|
|
-- Danger Zone Title
|
|
local DangerZonTitle = scrollChild:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
|
|
DangerZonTitle:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, startYOffset - index * lineHeight - 30)
|
|
DangerZonTitle:SetText("Danger Zone")
|
|
DangerZonTitle:SetTextColor(1, 1, 1)
|
|
|
|
index = index + 2
|
|
|
|
-- Reset Addon Button
|
|
resetButton = CreateFrame("Button", "ConsumesManager_ResetButton", scrollChild, "UIPanelButtonTemplate")
|
|
resetButton:SetWidth(120)
|
|
resetButton:SetHeight(24)
|
|
resetButton:SetText("Reset Addon")
|
|
resetButton:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, startYOffset - index * lineHeight - 10)
|
|
resetButton:SetScript("OnClick", function()
|
|
if ConsumesManager_Options.Channel then
|
|
local decoded_channel = DecodeMessage(ConsumesManager_Options.Channel)
|
|
LeaveChannelByName(decoded_channel)
|
|
end
|
|
ConsumesManager_Options = {}
|
|
ConsumesManager_SelectedItems = {}
|
|
ConsumesManager_Data = {}
|
|
ReloadUI()
|
|
end)
|
|
|
|
scrollChild.contentHeight = math.abs(startYOffset) + index * lineHeight + 100
|
|
scrollChild:SetHeight(scrollChild.contentHeight)
|
|
|
|
-- Scroll Bar Setup
|
|
local scrollBar = CreateFrame("Slider", "ConsumesManager_SettingsScrollBar", parentFrame)
|
|
scrollBar:SetPoint("TOPRIGHT", parentFrame, "TOPRIGHT", -2, -16)
|
|
scrollBar:SetPoint("BOTTOMRIGHT", parentFrame, "BOTTOMRIGHT", -2, 16)
|
|
scrollBar:SetWidth(16)
|
|
scrollBar:SetOrientation('VERTICAL')
|
|
scrollBar:SetThumbTexture("Interface\\Buttons\\UI-ScrollBar-Knob")
|
|
scrollBar:SetBackdrop({
|
|
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 }
|
|
})
|
|
scrollBar:SetScript("OnValueChanged", function()
|
|
local value = this:GetValue()
|
|
scrollFrame:SetVerticalScroll(value)
|
|
end)
|
|
parentFrame.scrollBar = scrollBar
|
|
|
|
ConsumesManager_UpdateSettingsScrollBar()
|
|
|
|
|
|
if not ConsumesManager_ChannelFrame then
|
|
ConsumesManager_ChannelFrame = CreateFrame("Frame", "ConsumesManager_ChannelFrame")
|
|
end
|
|
|
|
local channelmsg = ""
|
|
|
|
joinChannelButton:SetScript("OnClick", function()
|
|
|
|
ConsumesManager_ChannelFrame:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE")
|
|
|
|
channelErrorMessage:Hide()
|
|
local ctext = channelEditBox:GetText()
|
|
local ptext = passwordEditBox:GetText()
|
|
local final_result = nil
|
|
local try_again = false
|
|
|
|
ConsumesManager_ChannelFrame:SetScript("OnEvent", function()
|
|
local noticeType = string.upper(arg1 or "")
|
|
local channelName = string.upper(arg9 or "")
|
|
local inputChannelName = string.upper(ctext or "")
|
|
|
|
if noticeType == "WRONG_PASSWORD" and channelName == inputChannelName then
|
|
channelmsg = "WRONG_PASSWORD"
|
|
DEFAULT_CHAT_FRAME:AddMessage(noticeType)
|
|
elseif noticeType == "NOT_MODERATOR" and channelName == inputChannelName then
|
|
channelmsg = "NOT_MODERATOR"
|
|
DEFAULT_CHAT_FRAME:AddMessage(noticeType)
|
|
elseif noticeType == "YOU_JOINED" and channelName == inputChannelName then
|
|
channelmsg = "YOU_JOINED"
|
|
DEFAULT_CHAT_FRAME:AddMessage(noticeType)
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
-- Don't join same channel
|
|
if ConsumesManager_Options.Channel then
|
|
if DecodeMessage(ConsumesManager_Options.Channel) == ctext then
|
|
channelErrorMessage:SetText("Already in this channel")
|
|
channelErrorMessage:Show()
|
|
return
|
|
end
|
|
end
|
|
|
|
-- Block attempts to join big system channels
|
|
local blocked = { "world", "general", "localdefense", "hardcore", "lft", "trade" }
|
|
local lowerChannel = string.lower(ctext)
|
|
for _, b in pairs(blocked) do
|
|
if lowerChannel == b then
|
|
ConsumesManager_ChannelJoinFailed("You cannot use a global channel")
|
|
return
|
|
end
|
|
end
|
|
|
|
JoinChannelByName(ctext, ptext)
|
|
|
|
joinChannelButton:SetText("Connecting... (4)")
|
|
joinChannelButton:Disable()
|
|
joinChannelButton:SetAlpha(0.5)
|
|
|
|
|
|
local delayFrame = CreateFrame("Frame")
|
|
delayFrame:Show()
|
|
local elapsed = 0
|
|
local delay = 5
|
|
local one_attempt = 0
|
|
|
|
delayFrame:SetScript("OnUpdate", function()
|
|
|
|
|
|
if elapsed > 1 and elapsed < 2 then
|
|
|
|
joinChannelButton:SetText("Connecting... (3)")
|
|
|
|
if one_attempt == 0 then
|
|
|
|
DEFAULT_CHAT_FRAME:AddMessage("message: " .. channelmsg)
|
|
|
|
if channelmsg == "WRONG_PASSWORD" then
|
|
final_result = "WRONG_PASSWORD"
|
|
elseif channelmsg == "YOU_JOINED" then
|
|
DEFAULT_CHAT_FRAME:AddMessage("setting password")
|
|
SetChannelPassword(ctext, ptext)
|
|
end
|
|
end
|
|
|
|
one_attempt = 1
|
|
|
|
|
|
elseif elapsed > 2 and elapsed < 3 then
|
|
joinChannelButton:SetText("Connecting... (2)")
|
|
|
|
|
|
if one_attempt == 1 then
|
|
|
|
DEFAULT_CHAT_FRAME:AddMessage("message: " .. channelmsg)
|
|
|
|
if channelmsg == "YOU_JOINED" then
|
|
final_result = "SUCCESS"
|
|
elseif channelmsg == "NOT_MODERATOR" then
|
|
LeaveChannelByName(ctext)
|
|
try_again = true
|
|
end
|
|
end
|
|
|
|
one_attempt = 2
|
|
|
|
|
|
|
|
elseif elapsed > 3 and elapsed < 4 then
|
|
joinChannelButton:SetText("Connecting... (1)")
|
|
|
|
if one_attempt == 2 then
|
|
|
|
DEFAULT_CHAT_FRAME:AddMessage("message: " .. channelmsg)
|
|
|
|
if try_again == true then
|
|
|
|
JoinChannelByName(ctext, ptext)
|
|
|
|
end
|
|
end
|
|
|
|
one_attempt = 3
|
|
|
|
elseif elapsed > 4 and elapsed < 5 then
|
|
joinChannelButton:SetText("Connecting... (0)")
|
|
|
|
if one_attempt == 3 then
|
|
|
|
DEFAULT_CHAT_FRAME:AddMessage("message: " .. channelmsg)
|
|
|
|
if try_again == true then
|
|
|
|
if channelmsg == "YOU_JOINED" then
|
|
final_result = "SUCCESS"
|
|
elseif channelmsg == "NOT_MODERATOR" then
|
|
final_result = "NOT_MODERATOR"
|
|
end
|
|
end
|
|
end
|
|
|
|
one_attempt = 4
|
|
|
|
end
|
|
|
|
|
|
|
|
elapsed = elapsed + arg1
|
|
|
|
if elapsed >= delay then
|
|
|
|
delayFrame:SetScript("OnUpdate", nil)
|
|
delayFrame:Hide()
|
|
|
|
|
|
-- ACTION AFTER 3 SECONDS
|
|
|
|
|
|
if final_result == "SUCCESS" then
|
|
|
|
ConsumesManager_Options.Channel = EncodeMessage(ctext)
|
|
ConsumesManager_Options.Password = EncodeMessage(ptext)
|
|
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffffffff" .. GetAddOnMetadata("ConsumesManager", "Title") ..
|
|
":|r |cffffffffYou joined|r |cffffc0c0[" .. ctext ..
|
|
"]|r|cffffffff. Multi-account sync |cff00ff00enabled|r|cffffffff.|r")
|
|
|
|
elseif final_result == "WRONG_PASSWORD" then
|
|
|
|
ConsumesManager_ChannelJoinFailed("Wrong password. Try again.")
|
|
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffffffff" .. GetAddOnMetadata("ConsumesManager", "Title") ..
|
|
":|r |cffffffffWrong password for|r |cffffc0c0[" .. ctext ..
|
|
"]|r|cffffffff. Multi-account sync |cffff0000disabled|r|cffffffff.|r")
|
|
|
|
elseif final_result == "NOT_MODERATOR" then
|
|
|
|
ConsumesManager_ChannelJoinFailed("This is not your channel.")
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffffffff" .. GetAddOnMetadata("ConsumesManager", "Title") ..
|
|
":|r |cffffffffYou don't own|r |cffffc0c0[" .. ctext ..
|
|
"]|r|cffffffff. Multi-account sync |cffff0000disabled|r|cffffffff.|r")
|
|
|
|
else
|
|
LeaveChannelByName(ctext)
|
|
ConsumesManager_ChannelJoinFailed("Unknown error")
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffffffff" .. GetAddOnMetadata("ConsumesManager", "Title") ..
|
|
":|r |cffffffffFailed to join|r |cffffc0c0[" .. ctext ..
|
|
"]|r|cffffffff. Multi-account sync |cffff0000disabled|r|cffffffff.|r")
|
|
end
|
|
|
|
joinChannelButton:SetText("Save & Join Channel")
|
|
joinChannelButton:Enable()
|
|
joinChannelButton:SetAlpha(1)
|
|
updateSenDataButtonState()
|
|
UpdateLeaveButtonState()
|
|
|
|
ConsumesManager_ChannelFrame:UnregisterEvent("CHAT_MSG_CHANNEL_NOTICE")
|
|
|
|
end
|
|
delayFrame:Show()
|
|
end)
|
|
end)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
function ConsumesManager_UpdateSettingsContent()
|
|
local parentFrame = ConsumesManager_MainFrame and ConsumesManager_MainFrame.tabs and ConsumesManager_MainFrame.tabs[4]
|
|
if not parentFrame or not parentFrame.scrollFrame then
|
|
return
|
|
end
|
|
|
|
-- Remove existing child
|
|
local oldChild = parentFrame.scrollFrame:GetScrollChild()
|
|
if oldChild then
|
|
oldChild:Hide()
|
|
oldChild:SetParent(nil)
|
|
parentFrame.scrollFrame:SetScrollChild(nil)
|
|
end
|
|
|
|
-- Remove old scrollbar
|
|
if parentFrame.scrollBar then
|
|
parentFrame.scrollBar:Hide()
|
|
parentFrame.scrollBar:SetParent(nil)
|
|
parentFrame.scrollBar = nil
|
|
end
|
|
|
|
-- New scroll child
|
|
local newScrollChild = CreateFrame("Frame", nil, parentFrame.scrollFrame)
|
|
newScrollChild:SetWidth(WindowWidth - 10)
|
|
newScrollChild:SetHeight(1)
|
|
newScrollChild.contentHeight = 0
|
|
parentFrame.scrollFrame:SetScrollChild(newScrollChild)
|
|
parentFrame.scrollChild = newScrollChild
|
|
|
|
-- Build content
|
|
ConsumesManager_CreateSettingsContent(parentFrame)
|
|
|
|
-- Reset scroll
|
|
if parentFrame.scrollBar then
|
|
parentFrame.scrollBar:SetValue(0)
|
|
end
|
|
end
|
|
|
|
|
|
function ConsumesManager_UpdateSettingsScrollBar()
|
|
local OptionsFrame = ConsumesManager_MainFrame and ConsumesManager_MainFrame.tabs and ConsumesManager_MainFrame.tabs[4]
|
|
if not OptionsFrame then
|
|
return
|
|
end
|
|
local scrollBar = OptionsFrame.scrollBar
|
|
local scrollFrame = OptionsFrame.scrollFrame
|
|
local scrollChild = OptionsFrame.scrollChild
|
|
|
|
local totalHeight = scrollChild.contentHeight
|
|
local shownHeight = 420
|
|
|
|
local maxScroll = math.max(0, totalHeight - shownHeight)
|
|
scrollFrame.maxScroll = maxScroll
|
|
|
|
if totalHeight > shownHeight then
|
|
scrollBar:SetMinMaxValues(0, maxScroll)
|
|
scrollBar:SetValue(math.min(scrollBar:GetValue(), maxScroll))
|
|
scrollBar:Show()
|
|
else
|
|
scrollFrame.maxScroll = 0
|
|
scrollBar:SetMinMaxValues(0, 0)
|
|
scrollBar:SetValue(0)
|
|
scrollBar:Hide()
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
-- Global Functions -----------------------------------------------------------------------------
|
|
function ConsumesManager_UpdateUseButtons()
|
|
if not ConsumesManager_MainFrame or not ConsumesManager_MainFrame.tabs or not ConsumesManager_MainFrame.tabs[1] then
|
|
return
|
|
end
|
|
|
|
local ManagerFrame = ConsumesManager_MainFrame.tabs[1]
|
|
local playerName = UnitName("player")
|
|
local realmName = GetRealmName()
|
|
local faction = UnitFactionGroup("player")
|
|
|
|
-- Ensure data structure exists
|
|
if not ConsumesManager_Data[realmName] or not ConsumesManager_Data[realmName][faction] then
|
|
return
|
|
end
|
|
local data = ConsumesManager_Data[realmName][faction]
|
|
local charData = data[playerName]
|
|
if not charData then return end
|
|
|
|
local inventory = charData["inventory"] or {}
|
|
|
|
-- Iterate over the Items to update the buttons
|
|
for _, categoryInfo in ipairs(ManagerFrame.categoryInfo) do
|
|
for _, itemInfo in ipairs(categoryInfo.Items) do
|
|
local itemID = itemInfo.itemID
|
|
local button = itemInfo.button
|
|
local label = itemInfo.label
|
|
local frame = itemInfo.frame
|
|
|
|
if ConsumesManager_SelectedItems[itemID] then
|
|
local count = inventory[itemID] or 0
|
|
if count > 0 then
|
|
if ConsumesManager_Options.showUseButton then
|
|
button:Enable()
|
|
button:Show()
|
|
label:SetPoint("LEFT", button, "RIGHT", 4, 0)
|
|
else
|
|
button:Disable()
|
|
button:Hide()
|
|
label:SetPoint("LEFT", frame, "LEFT", 0, 0)
|
|
end
|
|
else
|
|
button:Disable()
|
|
button:Hide()
|
|
label:SetPoint("LEFT", frame, "LEFT", 0, 0)
|
|
end
|
|
else
|
|
button:Disable()
|
|
button:Hide()
|
|
label:SetPoint("LEFT", frame, "LEFT", 0, 0)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function ConsumesManager_FindItemInBags(itemID)
|
|
for bag = 0, 4 do
|
|
local numSlots = GetContainerNumSlots(bag)
|
|
if numSlots then
|
|
for slot = 1, numSlots do
|
|
local link = GetContainerItemLink(bag, slot)
|
|
if link then
|
|
local _, _, linkItemID = string.find(link, "item:(%d+)")
|
|
if linkItemID then
|
|
linkItemID = tonumber(linkItemID)
|
|
if linkItemID == itemID then
|
|
return bag, slot
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return nil, nil
|
|
end
|
|
|
|
function ConsumesManager_GetConsumableCount(itemID)
|
|
local totalCount = 0
|
|
local realmName = GetRealmName()
|
|
local faction = UnitFactionGroup("player")
|
|
local data = ConsumesManager_Data[realmName] and ConsumesManager_Data[realmName][faction]
|
|
if not data then return 0 end
|
|
|
|
for character, charData in pairs(data) do
|
|
if ConsumesManager_Options["Characters"] and ConsumesManager_Options["Characters"][character] then
|
|
if charData["inventory"] and charData["inventory"][itemID] then
|
|
totalCount = totalCount + charData["inventory"][itemID]
|
|
end
|
|
if charData["bank"] and charData["bank"][itemID] then
|
|
totalCount = totalCount + charData["bank"][itemID]
|
|
end
|
|
if charData["mail"] and charData["mail"][itemID] then
|
|
totalCount = totalCount + charData["mail"][itemID]
|
|
end
|
|
end
|
|
end
|
|
return totalCount
|
|
end
|
|
|
|
function ConsumesManager_UpdateAllContent()
|
|
ConsumesManager_UpdateManagerContent()
|
|
ConsumesManager_UpdatePresetsConsumables()
|
|
ConsumesManager_UpdateSettingsContent()
|
|
end
|
|
|
|
function ConsumesManager_DisableTab(tab)
|
|
tab.isEnabled = false
|
|
tab:EnableMouse(true) -- Keep mouse enabled for tooltip
|
|
tab.icon:SetDesaturated(true) -- Grey out the icon
|
|
tab:SetScript("OnClick", nil) -- Remove OnClick handler
|
|
|
|
-- Hide highlight effect
|
|
if tab.hoverTexture then
|
|
tab.hoverTexture:SetAlpha(0)
|
|
end
|
|
|
|
-- Adjust OnEnter handler to show tooltip only
|
|
tab:SetScript("OnEnter", function()
|
|
ShowTooltip(tab, tab.tooltipText)
|
|
end)
|
|
tab:SetScript("OnLeave", HideTooltip)
|
|
end
|
|
|
|
function ConsumesManager_EnableTab(tab)
|
|
tab.isEnabled = true
|
|
tab:EnableMouse(true)
|
|
tab.icon:SetDesaturated(false)
|
|
tab:SetScript("OnClick", tab.originalOnClick) -- Restore OnClick handler
|
|
|
|
-- Show highlight effect
|
|
if tab.hoverTexture then
|
|
tab.hoverTexture:SetAlpha(1)
|
|
end
|
|
|
|
-- Restore original OnEnter and OnLeave handlers
|
|
tab:SetScript("OnEnter", function()
|
|
ShowTooltip(tab, tab.tooltipText)
|
|
end)
|
|
tab:SetScript("OnLeave", HideTooltip)
|
|
end
|
|
|
|
function ConsumesManager_CheckBankAndMailScanned()
|
|
local realmName = GetRealmName()
|
|
local faction = UnitFactionGroup("player")
|
|
local playerName = UnitName("player")
|
|
|
|
-- Ensure data structure exists
|
|
if not ConsumesManager_Data[realmName] or not ConsumesManager_Data[realmName][faction] then
|
|
return false, false
|
|
end
|
|
local data = ConsumesManager_Data[realmName][faction]
|
|
local currentCharData = data[playerName]
|
|
if not currentCharData then
|
|
return false, false
|
|
end
|
|
|
|
local bankScanned = currentCharData["bank"] ~= nil
|
|
local mailScanned = currentCharData["mail"] ~= nil
|
|
|
|
return bankScanned, mailScanned
|
|
end
|
|
|
|
function ConsumesManager_UpdateTabStates()
|
|
if not ConsumesManager_Tabs or not ConsumesManager_Tabs[2] or not ConsumesManager_Tabs[3] then
|
|
-- Tabs have not been created yet; exit the function
|
|
return
|
|
end
|
|
|
|
local bankScanned, mailScanned = ConsumesManager_CheckBankAndMailScanned()
|
|
if bankScanned and mailScanned then
|
|
ConsumesManager_EnableTab(ConsumesManager_Tabs[2]) -- Items Tab
|
|
ConsumesManager_EnableTab(ConsumesManager_Tabs[3]) -- Presets Tab
|
|
else
|
|
ConsumesManager_DisableTab(ConsumesManager_Tabs[2]) -- Items Tab
|
|
ConsumesManager_DisableTab(ConsumesManager_Tabs[3]) -- Presets Tab
|
|
end
|
|
end
|
|
|
|
function MultiAccountInfoPopup()
|
|
-- Create the frame
|
|
local popup = CreateFrame("Frame", "MyPopupFrame", UIParent)
|
|
popup:SetHeight(180)
|
|
popup:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
|
|
popup:SetBackdrop({
|
|
bgFile = "Interface\\ChatFrame\\ChatFrameBackground", -- Solid black background
|
|
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
|
|
tile = false,
|
|
tileSize = 0,
|
|
edgeSize = 32,
|
|
insets = { left = 8, right = 8, top = 8, bottom = 8 }
|
|
})
|
|
popup:SetBackdropColor(0, 0, 0, 1) -- Black background with full opacity
|
|
popup:SetBackdropBorderColor(1, 1, 1, 1) -- White border
|
|
popup:SetFrameStrata("DIALOG")
|
|
popup:SetFrameLevel(1000)
|
|
popup:SetMovable(true)
|
|
popup:EnableMouse(true)
|
|
popup:RegisterForDrag("LeftButton")
|
|
popup:SetScript("OnDragStart", function()
|
|
this:StartMoving()
|
|
end)
|
|
popup:SetScript("OnDragStop", function()
|
|
this:StopMovingOrSizing()
|
|
end)
|
|
|
|
-- Add a close button
|
|
local closeButton = CreateFrame("Button", nil, popup, "UIPanelCloseButton")
|
|
closeButton:SetPoint("TOPRIGHT", popup, "TOPRIGHT", -5, -5)
|
|
|
|
-- Add a title
|
|
local infotitle = popup:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
|
|
infotitle:SetPoint("TOPLEFT", popup, "TOPLEFT", 20, -20)
|
|
infotitle:SetText("How does it work?")
|
|
infotitle:SetTextColor(1,1,1)
|
|
|
|
-- Add the infotext
|
|
popup.infotext = popup:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
popup.infotext:SetPoint("TOPLEFT", popup, "TOPLEFT", 20, -35)
|
|
popup.infotext:SetJustifyH("LEFT")
|
|
popup.infotext:SetText(
|
|
"|cffff0000(Beta Feature! Might be glitchy!)|r\n\n" ..
|
|
"To sync accounts, follow these steps:\n\n" ..
|
|
"1. Join a private channel with a unique name and password.\n" ..
|
|
"2. The channel info is saved for all characters on your account.\n" ..
|
|
"3. Log into your alt account on a second client.\n" ..
|
|
"4. Join the same channel via this addon to link both accounts.\n" ..
|
|
"5. Keep one character from your main account online for syncing.\n" ..
|
|
"6. Click on 'Push Data' to send the database from one account to all the other that are online."
|
|
)
|
|
|
|
|
|
-- Function to adjust width dynamically after text is set
|
|
popup:SetScript("OnShow", function()
|
|
local textWidth = popup.infotext:GetStringWidth() + 40 -- Add padding
|
|
popup:SetWidth(textWidth)
|
|
end)
|
|
|
|
popup:Hide()
|
|
return popup
|
|
end
|
|
|
|
|
|
|
|
-- Tooltip Functions --------------------------------------------------------------------------------------
|
|
function ConsumesManager_ShowConsumableTooltip(itemID)
|
|
-- Ensure item is enabled in settings or part of presets
|
|
if not ConsumesManager_SelectedItems[itemID] and not ConsumesManager_IsItemInPresets(itemID) then
|
|
return
|
|
end
|
|
|
|
-- Create or reuse custom tooltip frame
|
|
if not ConsumesManager_CustomTooltip then
|
|
-- Create the frame
|
|
local tooltipFrame = CreateFrame("Frame", "ConsumesManager_CustomTooltip", UIParent)
|
|
tooltipFrame:SetFrameStrata("TOOLTIP")
|
|
tooltipFrame:SetWidth(200)
|
|
tooltipFrame:SetBackdrop({
|
|
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
|
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
|
tile = true, tileSize = 16, edgeSize = 16,
|
|
insets = { left = 4, right = 4, top = 4, bottom = 4 }
|
|
})
|
|
tooltipFrame:SetBackdropColor(0, 0, 0, 1)
|
|
|
|
-- Item icon
|
|
local icon = tooltipFrame:CreateTexture(nil, "ARTWORK")
|
|
icon:SetWidth(32)
|
|
icon:SetHeight(32)
|
|
icon:SetPoint("TOPLEFT", tooltipFrame, "TOPLEFT", 10, -10)
|
|
tooltipFrame.icon = icon
|
|
|
|
-- Item name
|
|
local title = tooltipFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
title:SetPoint("TOPLEFT", icon, "TOPRIGHT", 10, -2)
|
|
title:SetJustifyH("LEFT")
|
|
tooltipFrame.title = title
|
|
|
|
-- Item Total
|
|
local total = tooltipFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
total:SetPoint("TOPLEFT", icon, "TOPRIGHT", 10, -20)
|
|
total:SetJustifyH("LEFT")
|
|
tooltipFrame.total = total
|
|
|
|
-- Content text
|
|
local content = tooltipFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
content:SetPoint("TOPLEFT", icon, "BOTTOMLEFT", 0, -10)
|
|
content:SetJustifyH("LEFT")
|
|
tooltipFrame.content = content
|
|
|
|
-- Mats text
|
|
local mats = tooltipFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
|
|
mats:SetPoint("TOPLEFT", content, "BOTTOMLEFT", 0, -10)
|
|
mats:SetJustifyH("LEFT")
|
|
tooltipFrame.mats = mats
|
|
|
|
ConsumesManager_CustomTooltip = tooltipFrame
|
|
end
|
|
|
|
local tooltipFrame = ConsumesManager_CustomTooltip
|
|
|
|
-- Get item info
|
|
local itemName = consumablesList[itemID] or "Unknown Item"
|
|
local itemTexture = consumablesTexture[itemID] or "Interface\\Icons\\INV_Misc_QuestionMark"
|
|
|
|
|
|
-- Set icon and title
|
|
tooltipFrame.icon:SetTexture(itemTexture)
|
|
tooltipFrame.title:SetText(itemName)
|
|
|
|
local mats = consumablesMats[itemID] or {}
|
|
local matsText = ""
|
|
|
|
if type(mats) == "table" and next(mats) then
|
|
local index = 0
|
|
local divider = ""
|
|
for _, mat in ipairs(mats) do
|
|
index = index + 1
|
|
if index > 1 then
|
|
divider = " | "
|
|
else
|
|
divider = ""
|
|
end
|
|
|
|
matsText = matsText .. divider .. "|cff4ac9ff" .. mat .. "|r"
|
|
end
|
|
else
|
|
matsText = "|cff696969No materials specified for this item.|r"
|
|
end
|
|
|
|
tooltipFrame.mats:SetText(matsText)
|
|
|
|
|
|
|
|
-- Prepare content text
|
|
local contentText = ""
|
|
local matsText = ""
|
|
|
|
local realmName = GetRealmName()
|
|
local faction = UnitFactionGroup("player")
|
|
local playerName = UnitName("player")
|
|
|
|
-- Ensure data structure exists
|
|
ConsumesManager_Data[realmName] = ConsumesManager_Data[realmName] or {}
|
|
ConsumesManager_Data[realmName][faction] = ConsumesManager_Data[realmName][faction] or {}
|
|
|
|
local data = ConsumesManager_Data[realmName][faction]
|
|
|
|
-- Initialize totals
|
|
local totalInventory, totalBank, totalMail = 0, 0, 0
|
|
local hasItems = false
|
|
local characterList = {}
|
|
|
|
-- Ensure character settings exist
|
|
ConsumesManager_Options["Characters"] = ConsumesManager_Options["Characters"] or {}
|
|
|
|
-- Collect data for each character
|
|
for character, charData in pairs(data) do
|
|
if ConsumesManager_Options["Characters"][character] == true then
|
|
local inventory = charData["inventory"] and charData["inventory"][itemID] or 0
|
|
local bank = charData["bank"] and charData["bank"][itemID] or 0
|
|
local mail = charData["mail"] and charData["mail"][itemID] or 0
|
|
local total = inventory + bank + mail
|
|
|
|
if total > 0 then
|
|
hasItems = true
|
|
totalInventory = totalInventory + inventory
|
|
totalBank = totalBank + bank
|
|
totalMail = totalMail + mail
|
|
|
|
table.insert(characterList, {
|
|
name = character,
|
|
inventory = inventory,
|
|
bank = bank,
|
|
mail = mail,
|
|
total = total,
|
|
isPlayer = (character == playerName)
|
|
})
|
|
end
|
|
end
|
|
end
|
|
|
|
local totalItems = totalInventory + totalBank + totalMail
|
|
-- Adjust label color based on count
|
|
if totalItems == 0 then
|
|
tooltipFrame.total:SetTextColor(1, 0, 0) -- Red
|
|
elseif totalItems < 10 then
|
|
tooltipFrame.total:SetTextColor(1, 0.4, 0) -- Orange
|
|
elseif totalItems <= 20 then
|
|
tooltipFrame.total:SetTextColor(1, 0.85, 0) -- Yellow
|
|
else
|
|
tooltipFrame.total:SetTextColor(0, 1, 0) -- Green
|
|
end
|
|
|
|
tooltipFrame.total:SetText("Total: " .. totalItems)
|
|
|
|
if not hasItems then
|
|
contentText = contentText .. "|cffff0000No items found for this consumable.|r"
|
|
lineHeightAdjust = 10
|
|
else
|
|
lineHeightAdjust = 0
|
|
-- Sort characters alphabetically
|
|
table.sort(characterList, function(a, b) return a.name < b.name end)
|
|
|
|
-- Display data for each character
|
|
for _, charInfo in ipairs(characterList) do
|
|
local nameColor = charInfo.isPlayer and "|cff00ff00" or "|cffffffff" -- Green for player, grey for others
|
|
contentText = contentText .. nameColor .. charInfo.name .. " (" .. charInfo.total .. ")|r\n"
|
|
|
|
local detailText = ""
|
|
if charInfo.inventory > 0 then
|
|
detailText = detailText .. "|cffffffffInventory:|r " .. charInfo.inventory .. " "
|
|
end
|
|
if charInfo.bank > 0 then
|
|
detailText = detailText .. "|cffffffffBank:|r " .. charInfo.bank .. " "
|
|
end
|
|
if charInfo.mail > 0 then
|
|
detailText = detailText .. "|cffffffffMail:|r " .. charInfo.mail .. " "
|
|
end
|
|
|
|
contentText = contentText .. " " .. detailText .. "\n\n"
|
|
end
|
|
end
|
|
|
|
tooltipFrame.content:SetText(contentText)
|
|
|
|
-- Calculate the number of lines in contentText using string.gsub
|
|
local _, numLines = string.gsub(contentText, "\n", "")
|
|
numLines = numLines + 2 -- Add lines for title and padding
|
|
|
|
-- Adjust tooltip height based on the number of lines
|
|
local lineHeightTooltip = 12
|
|
local totalHeight = 60 + (numLines * lineHeightTooltip) + lineHeightAdjust
|
|
tooltipFrame:SetHeight(totalHeight)
|
|
|
|
-- Set the width based on content
|
|
local titleWidth = math.max(tooltipFrame.mats:GetStringWidth() + 20, tooltipFrame.title:GetStringWidth() + 60)
|
|
local maxWidth = math.max(titleWidth, tooltipFrame.content:GetStringWidth() + 20)
|
|
tooltipFrame:SetWidth(maxWidth)
|
|
|
|
-- Position the tooltip near the cursor
|
|
local x, y = GetCursorPosition()
|
|
local scale = UIParent:GetEffectiveScale()
|
|
tooltipFrame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", x / scale + 10, y / scale - 10)
|
|
|
|
tooltipFrame:Show()
|
|
end
|
|
|
|
function ConsumesManager_ShowItemsTooltip(itemID)
|
|
-- Set the maximum width for the description text
|
|
local maxDescriptionWidth = 200
|
|
|
|
-- Create or reuse the tooltip frame
|
|
if not ConsumesManager_ItemsTooltip then
|
|
-- Create the frame
|
|
local tooltipFrame = CreateFrame("Frame", "ConsumesManager_ItemsTooltip", UIParent)
|
|
tooltipFrame:SetFrameStrata("TOOLTIP")
|
|
tooltipFrame:SetBackdrop({
|
|
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
|
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
|
tile = true, tileSize = 16, edgeSize = 16,
|
|
insets = { left = 4, right = 4, top = 4, bottom = 4 }
|
|
})
|
|
tooltipFrame:SetBackdropColor(0, 0, 0, 1)
|
|
|
|
-- Item icon
|
|
local icon = tooltipFrame:CreateTexture(nil, "ARTWORK")
|
|
icon:SetWidth(32)
|
|
icon:SetHeight(32)
|
|
icon:SetPoint("TOPLEFT", tooltipFrame, "TOPLEFT", 10, -10)
|
|
tooltipFrame.icon = icon
|
|
|
|
-- Item name
|
|
local title = tooltipFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
title:SetPoint("TOPLEFT", icon, "TOPRIGHT", 10, -2)
|
|
title:SetJustifyH("LEFT")
|
|
tooltipFrame.title = title
|
|
|
|
-- Item description
|
|
local description = tooltipFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
description:SetPoint("TOPLEFT", icon, "BOTTOMLEFT", 0, -10)
|
|
description:SetWidth(maxDescriptionWidth)
|
|
description:SetJustifyH("LEFT")
|
|
description:SetTextColor(1, 1, 1)
|
|
tooltipFrame.description = description
|
|
|
|
-- Mats text
|
|
local mats = tooltipFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
|
|
mats:SetPoint("TOPLEFT", description, "BOTTOMLEFT", 0, -10)
|
|
mats:SetJustifyH("LEFT")
|
|
tooltipFrame.mats = mats
|
|
|
|
ConsumesManager_ItemsTooltip = tooltipFrame
|
|
end
|
|
|
|
local tooltipFrame = ConsumesManager_ItemsTooltip
|
|
|
|
-- Get item info
|
|
local itemName = consumablesList[itemID] or "Unknown Item"
|
|
local itemTexture = consumablesTexture[itemID] or "Interface\\Icons\\INV_Misc_QuestionMark"
|
|
local itemDescription = consumablesDescription[itemID] or ""
|
|
|
|
-- Set icon, title, and description
|
|
tooltipFrame.icon:SetTexture(itemTexture)
|
|
tooltipFrame.title:SetText(itemName)
|
|
tooltipFrame.description:SetText(itemDescription)
|
|
|
|
local mats = consumablesMats[itemID] or {}
|
|
local matsText = ""
|
|
|
|
if type(mats) == "table" and next(mats) then
|
|
local index = 0
|
|
local divider = ""
|
|
for _, mat in ipairs(mats) do
|
|
index = index + 1
|
|
if index > 1 then
|
|
divider = " | "
|
|
else
|
|
divider = ""
|
|
end
|
|
|
|
matsText = matsText .. divider .. "|cff4ac9ff" .. mat .. "|r"
|
|
end
|
|
else
|
|
matsText = "|cff696969No materials specified for this item.|r"
|
|
end
|
|
|
|
tooltipFrame.mats:SetText(matsText)
|
|
|
|
-- Adjust the height of the description based on its content
|
|
tooltipFrame.description:SetWidth(maxDescriptionWidth)
|
|
tooltipFrame.description:SetText(itemDescription)
|
|
local descriptionHeight = tooltipFrame.description:GetHeight()
|
|
|
|
-- Adjust tooltip height based on content
|
|
local totalHeight = 80 + descriptionHeight
|
|
tooltipFrame:SetHeight(totalHeight)
|
|
|
|
-- Set the width of the tooltip
|
|
local titleWidth = math.max(tooltipFrame.title:GetStringWidth() + 70, tooltipFrame.mats:GetStringWidth() + 20)
|
|
local maxWidth = math.max(titleWidth, maxDescriptionWidth + 20)
|
|
tooltipFrame:SetWidth(maxWidth)
|
|
|
|
-- Position the tooltip near the cursor
|
|
local x, y = GetCursorPosition()
|
|
local scale = UIParent:GetEffectiveScale()
|
|
tooltipFrame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", x / scale + 10, y / scale - 10)
|
|
|
|
tooltipFrame:Show()
|
|
end
|
|
|
|
function ShowTooltip(tab, text)
|
|
ConsumesManagerTooltip.text:SetText(text)
|
|
ConsumesManagerTooltip:SetPoint("BOTTOMLEFT", tab, "TOPLEFT", 0, 0)
|
|
ConsumesManagerTooltip:Show()
|
|
end
|
|
|
|
function HideTooltip()
|
|
ConsumesManagerTooltip:Hide()
|
|
end
|
|
|
|
|
|
|
|
-- Scan Functions ---------------------------------------------------------------------------------------
|
|
function ConsumesManager_ScanPlayerInventory()
|
|
local playerName = UnitName("player")
|
|
local realmName = GetRealmName()
|
|
local faction = UnitFactionGroup("player")
|
|
|
|
ConsumesManager_Data[realmName] = ConsumesManager_Data[realmName] or {}
|
|
ConsumesManager_Data[realmName][faction] = ConsumesManager_Data[realmName][faction] or {}
|
|
ConsumesManager_Data[realmName][faction][playerName] = ConsumesManager_Data[realmName][faction][playerName] or {}
|
|
local data = ConsumesManager_Data[realmName][faction][playerName]
|
|
data["inventory"] = {}
|
|
|
|
for bag = 0, 4 do
|
|
local numSlots = GetContainerNumSlots(bag)
|
|
if numSlots then
|
|
for slot = 1, numSlots do
|
|
local link = GetContainerItemLink(bag, slot)
|
|
if link then
|
|
local _, _, itemID = string.find(link, "item:(%d+)")
|
|
if itemID then
|
|
itemID = tonumber(itemID)
|
|
if consumablesList[itemID] then
|
|
local _, itemCount = GetContainerItemInfo(bag, slot)
|
|
if itemCount and itemCount > 0 then
|
|
data["inventory"][itemID] = (data["inventory"][itemID] or 0) + itemCount
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
ConsumesManager_UpdateUseButtons()
|
|
ConsumesManager_UpdateManagerContent()
|
|
ConsumesManager_UpdateTabStates()
|
|
end
|
|
|
|
function ConsumesManager_ScanPlayerBank()
|
|
if not BankFrame or not BankFrame:IsShown() then
|
|
return
|
|
end
|
|
|
|
local playerName = UnitName("player")
|
|
local realmName = GetRealmName()
|
|
local faction = UnitFactionGroup("player")
|
|
|
|
ConsumesManager_Data[realmName] = ConsumesManager_Data[realmName] or {}
|
|
ConsumesManager_Data[realmName][faction] = ConsumesManager_Data[realmName][faction] or {}
|
|
ConsumesManager_Data[realmName][faction][playerName] = ConsumesManager_Data[realmName][faction][playerName] or {}
|
|
local data = ConsumesManager_Data[realmName][faction][playerName]
|
|
data["bank"] = {}
|
|
|
|
for bag = -1, 10 do
|
|
if bag == -1 or (bag >= 5 and bag <= 10) then
|
|
local numSlots = GetContainerNumSlots(bag)
|
|
if numSlots then
|
|
for slot = 1, numSlots do
|
|
local link = GetContainerItemLink(bag, slot)
|
|
if link then
|
|
local _, _, itemID = string.find(link, "item:(%d+)")
|
|
if itemID then
|
|
itemID = tonumber(itemID)
|
|
if consumablesList[itemID] then
|
|
local _, itemCount = GetContainerItemInfo(bag, slot)
|
|
if itemCount and itemCount > 0 then
|
|
data["bank"][itemID] = (data["bank"][itemID] or 0) + itemCount
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
ConsumesManager_UpdateManagerContent()
|
|
ConsumesManager_UpdateTabStates()
|
|
end
|
|
|
|
function ConsumesManager_ScanPlayerMail()
|
|
if not MailFrame or not MailFrame:IsShown() then
|
|
return
|
|
end
|
|
|
|
local playerName = UnitName("player")
|
|
local realmName = GetRealmName()
|
|
local faction = UnitFactionGroup("player")
|
|
|
|
ConsumesManager_Data[realmName] = ConsumesManager_Data[realmName] or {}
|
|
ConsumesManager_Data[realmName][faction] = ConsumesManager_Data[realmName][faction] or {}
|
|
ConsumesManager_Data[realmName][faction][playerName] = ConsumesManager_Data[realmName][faction][playerName] or {}
|
|
local data = ConsumesManager_Data[realmName][faction][playerName]
|
|
data["mail"] = {}
|
|
|
|
local numInboxItems = GetInboxNumItems()
|
|
if numInboxItems and numInboxItems > 0 then
|
|
for mailIndex = 1, numInboxItems do
|
|
local itemName, _, itemCount = GetInboxItem(mailIndex)
|
|
if itemName and itemCount and itemCount > 0 then
|
|
local itemID = consumablesNameToID[itemName]
|
|
if itemID and consumablesList[itemID] then
|
|
data["mail"][itemID] = (data["mail"][itemID] or 0) + itemCount
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
ConsumesManager_UpdateManagerContent()
|
|
ConsumesManager_UpdateTabStates()
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Multi-Account Data Handling --------------------------------------------------------------------------
|
|
|
|
|
|
local Converter = LibStub("LibCompress", true)
|
|
|
|
|
|
-- SEND DATA
|
|
local countdownFrame = CreateFrame("Frame")
|
|
countdownFrame:Hide()
|
|
local countdownTimer = 0
|
|
local Syncing = false
|
|
local ProgressBar = 0
|
|
local total_time_stored = 0
|
|
local BarHeight = 0
|
|
|
|
local function SyncInProgress(syncing, totalTime)
|
|
if syncing then
|
|
sendDataButton:Disable()
|
|
sendDataButton.icon:SetDesaturated(true)
|
|
LeaveChannelButton:Disable()
|
|
LeaveChannelButton:SetAlpha(0.5)
|
|
joinChannelButton:Disable()
|
|
joinChannelButton:SetAlpha(0.5)
|
|
resetButton:Disable()
|
|
resetButton:SetAlpha(0.5)
|
|
|
|
ProgressBarFrame:Show()
|
|
ProgressBarFrame_fill:Show()
|
|
ProgressBarFrame_Text:Show()
|
|
|
|
ProgressBar = totalTime
|
|
if total_time_stored == 0 then
|
|
total_time_stored = totalTime
|
|
end
|
|
countdownTimer = 0
|
|
BarHeight = 0
|
|
ProgressBarFrame_fill:SetHeight(0)
|
|
|
|
countdownFrame:Show()
|
|
else
|
|
sendDataButton:Enable()
|
|
sendDataButton.icon:SetDesaturated(false)
|
|
LeaveChannelButton:Enable()
|
|
LeaveChannelButton:SetAlpha(1)
|
|
joinChannelButton:Enable()
|
|
joinChannelButton:SetAlpha(1)
|
|
resetButton:Enable()
|
|
resetButton:SetAlpha(1)
|
|
|
|
ProgressBarFrame:Hide()
|
|
ProgressBarFrame_Text:Hide()
|
|
ProgressBarFrame_fill:SetHeight(0)
|
|
ProgressBar = 0
|
|
total_time_stored = 0
|
|
BarHeight = 0
|
|
ProgressBarFrame_fill:Hide()
|
|
|
|
countdownFrame:Hide()
|
|
end
|
|
Syncing = syncing
|
|
end
|
|
|
|
countdownFrame:SetScript("OnUpdate", function()
|
|
if Syncing and ProgressBar > 0 then
|
|
countdownTimer = countdownTimer + arg1
|
|
if countdownTimer >= 1 then
|
|
ProgressBar = ProgressBar - 1
|
|
if BarHeight < 492 then
|
|
BarHeight = 492 - (492 / (total_time_stored - 1)) * (ProgressBar - 1)
|
|
if BarHeight > 492 then
|
|
BarHeight = 492
|
|
end
|
|
end
|
|
ProgressBarFrame_fill:SetHeight(BarHeight)
|
|
countdownTimer = 0
|
|
end
|
|
end
|
|
end)
|
|
|
|
function PushData()
|
|
if not ConsumesManager_Options.Channel or ConsumesManager_Options.Channel == "" or
|
|
not ConsumesManager_Options.Password or ConsumesManager_Options.Password == "" then
|
|
return
|
|
end
|
|
|
|
local realmName = GetRealmName()
|
|
local faction = UnitFactionGroup("player")
|
|
local dataTable = ConsumesManager_Data[realmName][faction]
|
|
local serialized = Converter:TableToString(dataTable)
|
|
local compressed = lzw:compress(serialized)
|
|
local data = EncodeMessage(compressed)
|
|
|
|
local channelName = DecodeMessage(ConsumesManager_Options.Channel)
|
|
local channelNumber = GetChannelName(channelName)
|
|
local length = string.len(data)
|
|
local chunkSize = 100
|
|
local pos = 1
|
|
local queue = {}
|
|
while pos <= length do
|
|
local chunk = string.sub(data, pos, pos + chunkSize - 1)
|
|
pos = pos + chunkSize
|
|
table.insert(queue, chunk)
|
|
end
|
|
|
|
local totalMessages = table.getn(queue)
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffffffff" .. GetAddOnMetadata("ConsumesManager", "Title") .. ":|r |cffffffffData pushing started in|r |cffffc0c0[" .. DecodeMessage(ConsumesManager_Options.Channel) .. "]|r|cffffffff. Please wait...|r")
|
|
SendChatMessage("CM_SYNC_STARTED", "CHANNEL", nil, channelNumber)
|
|
SyncInProgress(true, totalMessages)
|
|
|
|
local receivedChunks = {}
|
|
local sendFrame = CreateFrame("Frame")
|
|
local eventFrame = CreateFrame("Frame")
|
|
eventFrame:RegisterEvent("CHAT_MSG_CHANNEL")
|
|
|
|
local state = "IDLE"
|
|
local currentIndex = 0
|
|
local sendTimeout = 2
|
|
local lockoutDuration = 10
|
|
local lockedOutUntil = 0
|
|
local waitingForVerification = false
|
|
local verificationElapsed = 0
|
|
local verificationWaitTime = 1
|
|
local currentStartTime = 0
|
|
|
|
eventFrame:SetScript("OnEvent", function()
|
|
if event == "CHAT_MSG_CHANNEL" then
|
|
local msg = arg1
|
|
local iStart, iEnd, msgIndex, chunk = string.find(msg, "^CM_(%d+):(.+)$")
|
|
if msgIndex and chunk then
|
|
msgIndex = tonumber(msgIndex)
|
|
receivedChunks[msgIndex] = chunk
|
|
if state == "WAITING" and msgIndex == currentIndex + 1 then
|
|
table.remove(queue, 1)
|
|
currentIndex = currentIndex + 1
|
|
state = "IDLE"
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
local function verifyData()
|
|
for i=1, totalMessages do
|
|
if not receivedChunks[i] then
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffffffff" .. GetAddOnMetadata("ConsumesManager", "Title") .. ":|r Data validation |cffff0000failed|r|cffffffff!|r")
|
|
return
|
|
end
|
|
end
|
|
local reconstructed = table.concat(receivedChunks, "")
|
|
if reconstructed == data then
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffffffff" .. GetAddOnMetadata("ConsumesManager", "Title") .. ":|r Data validation |cff00ff00succeeded|r|cffffffff!|r")
|
|
else
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffffffff" .. GetAddOnMetadata("ConsumesManager", "Title") .. ":|r Data validation |cffff0000failed|r|cffffffff!|r")
|
|
end
|
|
end
|
|
|
|
sendFrame:SetScript("OnUpdate", function()
|
|
local now = GetTime()
|
|
|
|
if waitingForVerification then
|
|
verificationElapsed = verificationElapsed + arg1
|
|
if verificationElapsed >= verificationWaitTime then
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffffffff" .. GetAddOnMetadata("ConsumesManager", "Title") .. ":|r Data pushing |cff00ff00finished|r|cffffffff!|r")
|
|
verifyData()
|
|
SendChatMessage("CM_SYNC_STOPPED", "CHANNEL", nil, channelNumber)
|
|
SyncInProgress(false, 0)
|
|
eventFrame:UnregisterEvent("CHAT_MSG_CHANNEL")
|
|
sendFrame:SetScript("OnUpdate", nil)
|
|
sendFrame:Hide()
|
|
end
|
|
return
|
|
end
|
|
|
|
if table.getn(queue) == 0 then
|
|
waitingForVerification = true
|
|
verificationElapsed = 0
|
|
return
|
|
end
|
|
|
|
if state == "LOCKED" then
|
|
if now >= lockedOutUntil then
|
|
state = "IDLE"
|
|
else
|
|
return
|
|
end
|
|
end
|
|
|
|
if state == "IDLE" then
|
|
local nextMsg = queue[1]
|
|
if nextMsg then
|
|
SendChatMessage("CM_" .. (currentIndex + 1) .. ":" .. nextMsg, "CHANNEL", nil, channelNumber)
|
|
currentStartTime = now
|
|
state = "WAITING"
|
|
end
|
|
elseif state == "WAITING" then
|
|
if now - currentStartTime > sendTimeout then
|
|
state = "LOCKED"
|
|
lockedOutUntil = now + lockoutDuration
|
|
end
|
|
end
|
|
end)
|
|
|
|
sendFrame:Show()
|
|
end
|
|
|
|
-- READ DATA
|
|
|
|
|
|
local collecting = false
|
|
local collectedChunks = {}
|
|
local collectingFrom = ""
|
|
local collectingCount = 0
|
|
local dataComplete = false
|
|
local eventFrame = nil
|
|
local channelName = ""
|
|
|
|
local function ResetCollection()
|
|
collecting = false
|
|
collectingFrom = ""
|
|
collectedChunks = {}
|
|
collectingCount = 0
|
|
dataComplete = false
|
|
end
|
|
|
|
-- Adjusted to accept 'sender' as a parameter
|
|
local function StopCollecting(sender)
|
|
collecting = false
|
|
|
|
if sendDataButton then
|
|
sendDataButton:Enable()
|
|
sendDataButton.icon:SetDesaturated(false)
|
|
end
|
|
|
|
local total = table.getn(collectedChunks)
|
|
if total > 0 then
|
|
local i = 1
|
|
local finalString = ""
|
|
while i <= total do
|
|
if collectedChunks[i] then
|
|
finalString = finalString .. collectedChunks[i]
|
|
end
|
|
i = i + 1
|
|
end
|
|
DEFAULT_CHAT_FRAME:AddMessage(
|
|
"|cffffffff" .. GetAddOnMetadata("ConsumesManager", "Title") .. ":|r |cffffffffData |cff00ff00successfully|r retrieved from|r |cff00ccff"
|
|
.. sender .. "|r|cffffffff ("
|
|
.. total .. " chunks & " .. string.len(finalString) .. " data length)|r"
|
|
)
|
|
combineVariableTables(finalString)
|
|
else
|
|
DEFAULT_CHAT_FRAME:AddMessage(
|
|
"|cffffffff" .. GetAddOnMetadata("ConsumesManager", "Title") .. ":|r |cffffffffData transmission |cffff0000failed|r from|r |cff00ccff"
|
|
.. sender .. "|r"
|
|
)
|
|
end
|
|
end
|
|
|
|
local function StartCollecting(sender)
|
|
collecting = true
|
|
collectingFrom = sender
|
|
collectedChunks = {}
|
|
collectingCount = 0
|
|
dataComplete = false
|
|
|
|
if sendDataButton then
|
|
sendDataButton:Disable()
|
|
sendDataButton.icon:SetDesaturated(true)
|
|
end
|
|
|
|
DEFAULT_CHAT_FRAME:AddMessage(
|
|
"|cffffffff" .. GetAddOnMetadata("ConsumesManager", "Title")
|
|
.. ":|r |cffffffffReceiving data from|r |cff00ccff"
|
|
.. sender .. "|r|cffffffff...|r"
|
|
)
|
|
end
|
|
|
|
local function OnChatMessage()
|
|
if event == "CHAT_MSG_CHANNEL" then
|
|
local msg = arg1
|
|
local sender = arg2
|
|
local chName = arg9
|
|
|
|
if chName == channelName and channelName ~= "" then
|
|
if msg == "CM_SYNC_STARTED" then
|
|
if sender ~= UnitName("player") and not collecting then
|
|
StartCollecting(sender)
|
|
end
|
|
elseif msg == "CM_SYNC_STOPPED" then
|
|
if collecting and sender == collectingFrom then
|
|
StopCollecting(sender) -- Pass 'sender' here
|
|
ResetCollection()
|
|
end
|
|
else
|
|
if collecting and sender == collectingFrom then
|
|
local iStart, iEnd, msgIndex, chunk = string.find(msg, "^CM_(%d+):(.+)$")
|
|
if msgIndex and chunk then
|
|
msgIndex = tonumber(msgIndex)
|
|
collectedChunks[msgIndex] = chunk
|
|
collectingCount = collectingCount + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function ReadData(mode)
|
|
if not ConsumesManager_Options.Channel or ConsumesManager_Options.Channel == "" then
|
|
return
|
|
end
|
|
|
|
channelName = DecodeMessage(ConsumesManager_Options.Channel)
|
|
local channelNumber = GetChannelName(channelName)
|
|
|
|
if not channelNumber or channelNumber == 0 then
|
|
return
|
|
end
|
|
|
|
if mode == "start" then
|
|
if not eventFrame then
|
|
eventFrame = CreateFrame("Frame")
|
|
eventFrame:SetScript("OnEvent", OnChatMessage)
|
|
end
|
|
eventFrame:RegisterEvent("CHAT_MSG_CHANNEL")
|
|
elseif mode == "stop" then
|
|
if eventFrame then
|
|
eventFrame:UnregisterEvent("CHAT_MSG_CHANNEL")
|
|
if collecting then
|
|
StopCollecting(collectingFrom) -- Pass 'collectingFrom'
|
|
ResetCollection()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Register for PLAYER_LOGIN (or VARIABLES_LOADED in 1.12) to start listening automatically
|
|
local startupFrame = CreateFrame("Frame")
|
|
startupFrame:RegisterEvent("PLAYER_LOGIN")
|
|
startupFrame:SetScript("OnEvent", function()
|
|
if event == "PLAYER_LOGIN" then
|
|
ReadData("start")
|
|
end
|
|
end)
|
|
|
|
|
|
function combineVariableTables(compressed_message)
|
|
|
|
local receivedTable = {}
|
|
local realmName = GetRealmName()
|
|
local faction = UnitFactionGroup("player")
|
|
|
|
local decoded = DecodeMessage(compressed_message)
|
|
local uncompressed = lzw:decompress(decoded)
|
|
receivedTable = Converter:StringToTable(uncompressed)
|
|
|
|
local existingTable = ConsumesManager_Data[realmName][faction]
|
|
|
|
|
|
local function mergeTables(original, newData)
|
|
for key, value in newData do
|
|
if type(value) == "table" and type(original[key]) == "table" then
|
|
mergeTables(original[key], value)
|
|
else
|
|
original[key] = value
|
|
end
|
|
end
|
|
end
|
|
|
|
mergeTables(existingTable, receivedTable)
|
|
ConsumesManager_UpdateAllContent()
|
|
|
|
end
|
|
|
|
-- BASE64 ENCODE AND DECODE --------------------------------------------------------------------------------------------------
|
|
|
|
local b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
|
local d = {}
|
|
do
|
|
local i = 1
|
|
while i <= string.len(b) do
|
|
local c = string.sub(b, i, i)
|
|
d[c] = i - 1
|
|
i = i + 1
|
|
end
|
|
end
|
|
|
|
function EncodeMessage(data)
|
|
local encoded = {}
|
|
local length = string.len(data)
|
|
local i = 1
|
|
while i <= length do
|
|
local c1 = string.byte(data, i, i) i = i + 1
|
|
local c2 = (i <= length) and string.byte(data, i, i) or nil i = i + 1
|
|
local c3 = (i <= length) and string.byte(data, i, i) or nil i = i + 1
|
|
|
|
local o1 = bit.rshift(c1, 2)
|
|
local o2 = bit.bor(bit.lshift(bit.band(c1, 3),4), (c2 and bit.rshift(c2, 4) or 0))
|
|
local o3 = (c2 and bit.bor(bit.lshift(bit.band(c2,15),2), (c3 and bit.rshift(c3,6) or 0)) or 64)
|
|
local o4 = (c3 and bit.band(c3,63) or 64)
|
|
|
|
table.insert(encoded, string.sub(b, o1+1, o1+1))
|
|
table.insert(encoded, string.sub(b, o2+1, o2+1))
|
|
if o3 ~= 64 then
|
|
table.insert(encoded, string.sub(b, o3+1, o3+1))
|
|
else
|
|
table.insert(encoded, "=")
|
|
end
|
|
if o4 ~= 64 then
|
|
table.insert(encoded, string.sub(b, o4+1, o4+1))
|
|
else
|
|
table.insert(encoded, "=")
|
|
end
|
|
end
|
|
return table.concat(encoded, "")
|
|
end
|
|
|
|
function DecodeMessage(str)
|
|
local decoded = {}
|
|
local length = string.len(str)
|
|
local i = 1
|
|
while i <= length do
|
|
local c1 = string.sub(str, i, i) i = i + 1
|
|
local c2 = string.sub(str, i, i) i = i + 1
|
|
if (not c2) or (c1 == '=') or (c2 == '=') then
|
|
break
|
|
end
|
|
local c3 = string.sub(str, i, i) i = i + 1
|
|
local c4 = string.sub(str, i, i) i = i + 1
|
|
|
|
local dc1 = d[c1]
|
|
local dc2 = d[c2]
|
|
local dc3 = (c3 and c3 ~= '=' and d[c3]) or nil
|
|
local dc4 = (c4 and c4 ~= '=' and d[c4]) or nil
|
|
|
|
local o1 = bit.bor(bit.lshift(dc1, 2), bit.rshift(dc2, 4))
|
|
table.insert(decoded, string.char(o1))
|
|
|
|
if dc3 then
|
|
local o2 = bit.bor(bit.lshift(bit.band(dc2, 15),4), bit.rshift(dc3, 2))
|
|
table.insert(decoded, string.char(o2))
|
|
if dc4 then
|
|
local o3 = bit.bor(bit.lshift(bit.band(dc3, 3),6), dc4)
|
|
table.insert(decoded, string.char(o3))
|
|
end
|
|
end
|
|
end
|
|
return table.concat(decoded, "")
|
|
end
|
|
|