780 lines
28 KiB
Lua
780 lines
28 KiB
Lua
-- Guda Quest Item Bar
|
|
-- Displays usable quest items in a separate bar
|
|
|
|
local addon = Guda
|
|
local QuestItemBar = addon.Modules.QuestItemBar
|
|
if not QuestItemBar then
|
|
-- Fallback if Init.lua changed
|
|
QuestItemBar = {}
|
|
addon.Modules.QuestItemBar = QuestItemBar
|
|
end
|
|
|
|
local buttons = {}
|
|
local questItems = {}
|
|
local flyoutButtons = {}
|
|
local flyoutFrame
|
|
|
|
--=====================================================
|
|
-- Quest Item Detection (using centralized ItemDetection)
|
|
--=====================================================
|
|
|
|
-- Combined function to check if an item is a quest item AND usable
|
|
-- Uses centralized ItemDetection module for consistent detection
|
|
function QuestItemBar:CheckQuestItemUsable(bagID, slotID)
|
|
if not bagID or not slotID then return false, false, false end
|
|
|
|
-- Get item data for ItemDetection
|
|
local itemData = nil
|
|
if addon.Modules.BagScanner then
|
|
itemData = addon.Modules.BagScanner:ScanSlot(bagID, slotID)
|
|
end
|
|
|
|
-- Use centralized ItemDetection
|
|
if addon.Modules.ItemDetection and itemData then
|
|
local props = addon.Modules.ItemDetection:GetItemProperties(itemData, bagID, slotID)
|
|
return props.isQuestItem, props.isQuestStarter, props.isQuestUsable
|
|
end
|
|
|
|
-- Fallback to Utils if ItemDetection not available
|
|
if addon.Modules.Utils and addon.Modules.Utils.IsQuestItem then
|
|
local isQuestItem, isQuestStarter = addon.Modules.Utils:IsQuestItem(bagID, slotID, nil, false, false)
|
|
-- For usability fallback, check if it's a quest item (assume usable)
|
|
return isQuestItem, isQuestStarter, isQuestItem
|
|
end
|
|
|
|
return false, false, false
|
|
end
|
|
|
|
-- Scan bags for quest items (optimized: single tooltip scan per item)
|
|
function QuestItemBar:ScanForQuestItems()
|
|
questItems = {}
|
|
|
|
-- Scan backpack and 4 bags
|
|
for bagID = 0, 4 do
|
|
local numSlots = GetContainerNumSlots(bagID)
|
|
for slotID = 1, numSlots do
|
|
local texture, count = GetContainerItemInfo(bagID, slotID)
|
|
if texture then
|
|
-- Single combined check instead of two separate tooltip scans
|
|
local isQuest, isStarter, isUsable = self:CheckQuestItemUsable(bagID, slotID)
|
|
if isQuest and isUsable and not isStarter then
|
|
table.insert(questItems, {
|
|
bagID = bagID,
|
|
slotID = slotID,
|
|
texture = texture,
|
|
count = count
|
|
})
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Legacy function kept for compatibility (now calls combined function)
|
|
function QuestItemBar:IsQuestItem(bagID, slotID)
|
|
local isQuestItem, isQuestStarter, _ = self:CheckQuestItemUsable(bagID, slotID)
|
|
return isQuestItem, isQuestStarter
|
|
end
|
|
|
|
function QuestItemBar:PinItem(itemID, slot)
|
|
if not itemID then return end
|
|
local pins = addon.Modules.DB:GetSetting("questBarPinnedItems") or {}
|
|
|
|
local targetSlot = slot or 1
|
|
if not slot then
|
|
-- Original logic: Find first empty slot or replace first
|
|
for i = 1, 2 do
|
|
if pins[i] == itemID then return end
|
|
end
|
|
|
|
for i = 1, 2 do
|
|
if not pins[i] then
|
|
targetSlot = i
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
pins[targetSlot] = itemID
|
|
addon.Modules.DB:SetSetting("questBarPinnedItems", pins)
|
|
self:Update()
|
|
return true
|
|
end
|
|
|
|
-- Update the bar buttons
|
|
function QuestItemBar:Update()
|
|
local showQuestBar = addon.Modules.DB:GetSetting("showQuestBar")
|
|
local frame = Guda_QuestItemBar
|
|
|
|
if not frame then return end
|
|
|
|
if showQuestBar == false then
|
|
frame:Hide()
|
|
return
|
|
end
|
|
|
|
self:ScanForQuestItems()
|
|
|
|
-- If no quest items found, hide the bar
|
|
if table.getn(questItems or {}) == 0 then
|
|
frame:Hide()
|
|
return
|
|
end
|
|
|
|
frame:Show()
|
|
|
|
local pinnedItems = addon.Modules.DB:GetSetting("questBarPinnedItems") or {}
|
|
local buttonSize = addon.Modules.DB:GetSetting("questBarSize") or 36
|
|
local spacing = 2
|
|
local xOffset = 5
|
|
|
|
-- Update frame height based on button size
|
|
frame:SetHeight(buttonSize + 8)
|
|
|
|
-- Used to keep track of which bag items are already displayed
|
|
local usedBagSlots = {}
|
|
|
|
local slots = math.min(2, table.getn(questItems or {}))
|
|
for i = 1, slots do
|
|
local index = i
|
|
local button = buttons[i]
|
|
if not button then
|
|
button = CreateFrame("Button", "Guda_QuestItemBarButton" .. i, frame, "Guda_ItemButtonTemplate")
|
|
table.insert(buttons, button)
|
|
|
|
-- Set up the button once
|
|
button:RegisterForDrag("LeftButton")
|
|
button:SetScript("OnDragStart", function() end)
|
|
button:SetScript("OnReceiveDrag", function() end)
|
|
button:SetScript("OnMouseDown", function()
|
|
if arg1 == "LeftButton" then
|
|
if IsShiftKeyDown() and not (CursorHasItem and CursorHasItem()) then
|
|
this:GetParent():StartMoving()
|
|
this:GetParent().isMoving = true
|
|
end
|
|
end
|
|
end)
|
|
button:SetScript("OnMouseUp", function()
|
|
if arg1 == "LeftButton" then
|
|
local parent = this:GetParent()
|
|
if parent.isMoving then
|
|
parent:StopMovingOrSizing()
|
|
parent.isMoving = false
|
|
local point, _, relativePoint, x, y = parent:GetPoint()
|
|
addon.Modules.DB:SetSetting("questBarPosition", {point = point, relativePoint = relativePoint, x = x, y = y})
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
local itemToDisplay = nil
|
|
|
|
-- 1. Try to find the pinned item for this slot
|
|
local pinnedID = pinnedItems[i]
|
|
if pinnedID then
|
|
-- Find this item in bags
|
|
for _, item in ipairs(questItems) do
|
|
local itemID = addon.Modules.Utils:ExtractItemID(GetContainerItemLink(item.bagID, item.slotID))
|
|
if itemID == pinnedID and not usedBagSlots[item.bagID .. ":" .. item.slotID] then
|
|
itemToDisplay = item
|
|
usedBagSlots[item.bagID .. ":" .. item.slotID] = true
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
-- 2. If no pinned item or pinned item not found, auto-fill
|
|
if not itemToDisplay then
|
|
for _, item in ipairs(questItems) do
|
|
if not usedBagSlots[item.bagID .. ":" .. item.slotID] then
|
|
itemToDisplay = item
|
|
usedBagSlots[item.bagID .. ":" .. item.slotID] = true
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
if itemToDisplay then
|
|
button.bagID = itemToDisplay.bagID
|
|
button.slotID = itemToDisplay.slotID
|
|
button.hasItem = true
|
|
button.fromDB = itemToDisplay.fromDB
|
|
|
|
local link = itemToDisplay.link
|
|
if not link and itemToDisplay.bagID and itemToDisplay.slotID then
|
|
link = GetContainerItemLink(itemToDisplay.bagID, itemToDisplay.slotID)
|
|
end
|
|
button.itemData = { link = link }
|
|
|
|
local icon = getglobal(button:GetName() .. "IconTexture")
|
|
icon:SetTexture(itemToDisplay.texture)
|
|
icon:SetVertexColor(1.0, 1.0, 1.0, 1.0)
|
|
|
|
local countText = getglobal(button:GetName() .. "Count")
|
|
if itemToDisplay.count > 1 then
|
|
countText:SetText(itemToDisplay.count)
|
|
countText:Show()
|
|
else
|
|
countText:Hide()
|
|
end
|
|
|
|
button:SetScript("OnClick", function()
|
|
if this.fromDB then
|
|
addon:Print("Item is not currently in your bags (loading from database).")
|
|
return
|
|
end
|
|
|
|
if arg1 == "LeftButton" then
|
|
if CursorHasItem() then
|
|
-- Try to pin item on cursor
|
|
local tooltip = addon.Modules.Utils:GetScanTooltip()
|
|
tooltip:SetOwner(WorldFrame, "ANCHOR_NONE")
|
|
tooltip:SetCursorItem()
|
|
local link = nil
|
|
-- In 1.12, getting link from cursor is hard.
|
|
-- We'll rely on Alt-Click from bags for pinning.
|
|
end
|
|
|
|
if not IsShiftKeyDown() then
|
|
UseContainerItem(this.bagID, this.slotID)
|
|
end
|
|
elseif arg1 == "RightButton" then
|
|
if IsAltKeyDown() then
|
|
-- Clear pin for this slot
|
|
local pins = addon.Modules.DB:GetSetting("questBarPinnedItems") or {}
|
|
pins[index] = nil
|
|
addon.Modules.DB:SetSetting("questBarPinnedItems", pins)
|
|
QuestItemBar:Update()
|
|
elseif not IsShiftKeyDown() then
|
|
UseContainerItem(this.bagID, this.slotID)
|
|
end
|
|
end
|
|
end)
|
|
|
|
button:Show()
|
|
else
|
|
-- Empty slot
|
|
button.hasItem = false
|
|
button.bagID = nil
|
|
button.slotID = nil
|
|
|
|
local icon = getglobal(button:GetName() .. "IconTexture")
|
|
local slotStyle = "rounded"
|
|
if addon.Modules and addon.Modules.Theme then
|
|
slotStyle = addon.Modules.Theme:GetSlotStyle()
|
|
end
|
|
if slotStyle == "square" then
|
|
icon:SetTexture("Interface\\Buttons\\WHITE8x8")
|
|
icon:SetVertexColor(0.05, 0.05, 0.05, 0.5)
|
|
else
|
|
icon:SetTexture("Interface\\Buttons\\UI-EmptySlot")
|
|
icon:SetVertexColor(0.5, 0.5, 0.5, 0.5)
|
|
end
|
|
|
|
local countText = getglobal(button:GetName() .. "Count")
|
|
countText:Hide()
|
|
|
|
button:SetScript("OnClick", function()
|
|
if arg1 == "LeftButton" then
|
|
if CursorHasItem() then
|
|
-- Pinning from cursor is hard in 1.12 without hooks.
|
|
end
|
|
elseif arg1 == "RightButton" then
|
|
if IsAltKeyDown() then
|
|
-- Clear pin for this slot
|
|
local pins = addon.Modules.DB:GetSetting("questBarPinnedItems") or {}
|
|
pins[index] = nil
|
|
addon.Modules.DB:SetSetting("questBarPinnedItems", pins)
|
|
QuestItemBar:Update()
|
|
end
|
|
end
|
|
end)
|
|
|
|
button:Show()
|
|
end
|
|
|
|
button:SetScript("OnEnter", function()
|
|
if this.hasItem then
|
|
Guda_ItemButton_OnEnter(this)
|
|
else
|
|
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
|
|
GameTooltip:SetText("Quest Slot " .. index)
|
|
GameTooltip:AddLine("Auto-fills with usable quest items.", 1, 1, 1)
|
|
GameTooltip:AddLine("Alt-Click an item in bags to pin it.", 0, 1, 0)
|
|
GameTooltip:AddLine("Alt-Right-Click to unpin.", 0.5, 0.5, 0.5)
|
|
GameTooltip:Show()
|
|
end
|
|
|
|
-- Only show flyout if there are more quest items to show
|
|
if QuestItemBar:HasExtraQuestItems() then
|
|
QuestItemBar:ShowFlyout(this)
|
|
end
|
|
end)
|
|
|
|
button:SetScript("OnLeave", function()
|
|
if this.hasItem then
|
|
Guda_ItemButton_OnLeave(this)
|
|
else
|
|
GameTooltip:Hide()
|
|
end
|
|
QuestItemBar:HideFlyout()
|
|
end)
|
|
|
|
button:ClearAllPoints()
|
|
button:SetPoint("LEFT", frame, "LEFT", xOffset + (i-1) * (buttonSize + spacing), 0)
|
|
button:SetWidth(buttonSize)
|
|
button:SetHeight(buttonSize)
|
|
|
|
-- Resize all button textures to match button size
|
|
local icon = getglobal(button:GetName() .. "IconTexture")
|
|
if icon then
|
|
icon:SetWidth(buttonSize)
|
|
icon:SetHeight(buttonSize)
|
|
end
|
|
|
|
-- Scale border proportionally (64/37 is the standard ratio for WoW item buttons)
|
|
local slotStyle = "rounded"
|
|
if addon.Modules and addon.Modules.Theme then
|
|
slotStyle = addon.Modules.Theme:GetSlotStyle()
|
|
end
|
|
|
|
local normalTex = getglobal(button:GetName() .. "NormalTexture")
|
|
if slotStyle == "square" then
|
|
-- Hide rounded border in pfUI mode
|
|
button:SetNormalTexture("")
|
|
if normalTex then
|
|
normalTex:SetTexture(nil)
|
|
normalTex:Hide()
|
|
end
|
|
-- Crop icon for pfUI style
|
|
if icon then
|
|
icon:SetTexCoord(.08, .92, .08, .92)
|
|
end
|
|
else
|
|
local borderSize = buttonSize * 64 / 37
|
|
if normalTex then
|
|
normalTex:SetWidth(borderSize)
|
|
normalTex:SetHeight(borderSize)
|
|
end
|
|
end
|
|
|
|
-- Resize empty slot background
|
|
local emptyBg = getglobal(button:GetName() .. "_EmptySlotBg")
|
|
if emptyBg then
|
|
if slotStyle == "square" then
|
|
emptyBg:SetTexture("Interface\\Buttons\\WHITE8x8")
|
|
emptyBg:SetVertexColor(0.05, 0.05, 0.05, 1)
|
|
emptyBg:ClearAllPoints()
|
|
emptyBg:SetPoint("TOPLEFT", button, "TOPLEFT", 0, 0)
|
|
emptyBg:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", 0, 0)
|
|
else
|
|
emptyBg:SetWidth(buttonSize)
|
|
emptyBg:SetHeight(buttonSize)
|
|
end
|
|
end
|
|
|
|
-- Update visual overlays (cooldown, etc)
|
|
if Guda_ItemButton_UpdateCooldown then
|
|
Guda_ItemButton_UpdateCooldown(button)
|
|
end
|
|
end
|
|
|
|
-- Hide any extra buttons beyond current slots
|
|
for j = slots + 1, table.getn(buttons) do
|
|
local extra = buttons[j]
|
|
if extra then
|
|
extra:Hide()
|
|
extra.hasItem = false
|
|
end
|
|
end
|
|
|
|
-- Fixed width for current number of slots
|
|
local newWidth = xOffset * 2 + slots * (buttonSize + spacing) - spacing
|
|
frame:SetWidth(newWidth)
|
|
end
|
|
|
|
function QuestItemBar:UpdateCooldowns()
|
|
for _, button in ipairs(buttons) do
|
|
if button:IsShown() and Guda_ItemButton_UpdateCooldown then
|
|
Guda_ItemButton_UpdateCooldown(button)
|
|
end
|
|
end
|
|
for _, button in ipairs(flyoutButtons) do
|
|
if button:IsShown() and Guda_ItemButton_UpdateCooldown then
|
|
Guda_ItemButton_UpdateCooldown(button)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Check if there are more quest items than shown in the main slots
|
|
function QuestItemBar:HasExtraQuestItems()
|
|
local mainItemIDs = {}
|
|
for i = 1, 2 do
|
|
local btn = buttons[i]
|
|
if btn and btn.hasItem and btn.itemData and btn.itemData.link then
|
|
local id = addon.Modules.Utils:ExtractItemID(btn.itemData.link)
|
|
if id then mainItemIDs[id] = true end
|
|
end
|
|
end
|
|
|
|
for _, item in ipairs(questItems or {}) do
|
|
local link = item.link
|
|
if not link and item.bagID and item.slotID then
|
|
link = GetContainerItemLink(item.bagID, item.slotID)
|
|
end
|
|
|
|
if link then
|
|
local id = addon.Modules.Utils:ExtractItemID(link)
|
|
if id and not mainItemIDs[id] then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
function QuestItemBar:ShowFlyout(parent)
|
|
if not flyoutFrame then return end
|
|
|
|
self:UpdateFlyout(parent)
|
|
flyoutFrame:Show()
|
|
end
|
|
|
|
function QuestItemBar:HideFlyout(immediate)
|
|
if not flyoutFrame then return end
|
|
|
|
if immediate then
|
|
flyoutFrame:Hide()
|
|
flyoutFrame:SetScript("OnUpdate", nil)
|
|
return
|
|
end
|
|
|
|
-- Delay hiding to allow moving mouse to the flyout
|
|
flyoutFrame.hideTime = GetTime() + 0.1
|
|
flyoutFrame:SetScript("OnUpdate", function()
|
|
if GetTime() > this.hideTime then
|
|
if not MouseIsOver(this) and (not this.parent or not MouseIsOver(this.parent)) then
|
|
this:Hide()
|
|
end
|
|
this:SetScript("OnUpdate", nil)
|
|
end
|
|
end)
|
|
end
|
|
|
|
function QuestItemBar:UpdateFlyout(parent)
|
|
if not flyoutFrame then return end
|
|
flyoutFrame.parent = parent
|
|
|
|
local buttonSize = addon.Modules.DB:GetSetting("questBarSize") or 36
|
|
local spacing = 2
|
|
|
|
-- Collect items not in main buttons
|
|
local displayItems = {}
|
|
local mainItemIDs = {}
|
|
for _, btn in ipairs(buttons) do
|
|
if btn and btn.hasItem and btn.itemData and btn.itemData.link then
|
|
local id = addon.Modules.Utils:ExtractItemID(btn.itemData.link)
|
|
if id then mainItemIDs[id] = true end
|
|
end
|
|
end
|
|
|
|
for _, item in ipairs(questItems) do
|
|
local link = GetContainerItemLink(item.bagID, item.slotID)
|
|
local id = addon.Modules.Utils:ExtractItemID(link)
|
|
if id and not mainItemIDs[id] then
|
|
-- Avoid duplicates in flyout if multiple stacks exist (optional, but TrinketMenu does it)
|
|
local alreadyInFlyout = false
|
|
for _, existing in ipairs(displayItems) do
|
|
if existing.itemID == id then
|
|
alreadyInFlyout = true
|
|
break
|
|
end
|
|
end
|
|
|
|
if not alreadyInFlyout then
|
|
table.insert(displayItems, {
|
|
bagID = item.bagID,
|
|
slotID = item.slotID,
|
|
texture = item.texture,
|
|
count = item.count,
|
|
itemID = id,
|
|
link = link
|
|
})
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Hide all flyout buttons first
|
|
for _, btn in ipairs(flyoutButtons) do
|
|
btn:Hide()
|
|
end
|
|
|
|
if table.getn(displayItems) == 0 then
|
|
flyoutFrame:Hide()
|
|
return
|
|
end
|
|
|
|
-- Position flyout above the parent button
|
|
flyoutFrame:ClearAllPoints()
|
|
flyoutFrame:SetPoint("BOTTOM", parent, "TOP", 0, 5)
|
|
|
|
for i, item in ipairs(displayItems) do
|
|
local btn = flyoutButtons[i]
|
|
if not btn then
|
|
btn = CreateFrame("Button", "Guda_QuestItemFlyoutButton" .. i, flyoutFrame, "Guda_ItemButtonTemplate")
|
|
table.insert(flyoutButtons, btn)
|
|
|
|
btn:SetScript("OnDragStart", function() end)
|
|
btn:SetScript("OnReceiveDrag", function() end)
|
|
btn:SetScript("OnMouseDown", function() end)
|
|
|
|
btn:SetScript("OnEnter", function()
|
|
Guda_ItemButton_OnEnter(this)
|
|
if flyoutFrame then flyoutFrame.hideTime = GetTime() + 5 end -- Keep open
|
|
end)
|
|
btn:SetScript("OnLeave", function()
|
|
Guda_ItemButton_OnLeave(this)
|
|
QuestItemBar:HideFlyout()
|
|
end)
|
|
end
|
|
|
|
btn.bagID = item.bagID
|
|
btn.slotID = item.slotID
|
|
btn.hasItem = true
|
|
btn.fromDB = item.fromDB
|
|
btn.itemData = { link = item.link }
|
|
btn.itemID = item.itemID
|
|
|
|
local icon = getglobal(btn:GetName() .. "IconTexture")
|
|
icon:SetTexture(item.texture)
|
|
|
|
local countText = getglobal(btn:GetName() .. "Count")
|
|
if item.count > 1 then
|
|
countText:SetText(item.count)
|
|
countText:Show()
|
|
else
|
|
countText:Hide()
|
|
end
|
|
|
|
btn:SetScript("OnClick", function()
|
|
if this.fromDB then
|
|
addon:Print("Item is not currently in your bags (loading from database).")
|
|
return
|
|
end
|
|
|
|
local targetSlot = 1
|
|
if flyoutFrame.parent then
|
|
-- Check if parent is Guda_QuestItemBarButton2
|
|
if flyoutFrame.parent:GetName() == "Guda_QuestItemBarButton2" then
|
|
targetSlot = 2
|
|
end
|
|
end
|
|
|
|
if arg1 == "LeftButton" then
|
|
QuestItemBar:PinItem(this.itemID, targetSlot)
|
|
elseif arg1 == "RightButton" then
|
|
-- Both clicks now work on targetSlot based on context,
|
|
-- but we'll keep RightButton for slot 2 as a fallback/original behavior
|
|
-- or just make it also use targetSlot if we want "both clicks work on mouse 1".
|
|
-- The requirement says "make both clicks work on mouse 1 instead of mouse 2 and mouse 1 clicks to separate bars"
|
|
-- This phrasing is a bit ambiguous, but contextually it means
|
|
-- Mouse 1 on flyout button should replace the bar that was hovered.
|
|
QuestItemBar:PinItem(this.itemID, targetSlot)
|
|
end
|
|
QuestItemBar:HideFlyout(true)
|
|
end)
|
|
|
|
btn:ClearAllPoints()
|
|
btn:SetPoint("BOTTOM", flyoutFrame, "BOTTOM", 0, (i-1) * (buttonSize + spacing) + 5)
|
|
btn:SetWidth(buttonSize)
|
|
btn:SetHeight(buttonSize)
|
|
|
|
-- Resize all button textures to match button size
|
|
local btnIcon = getglobal(btn:GetName() .. "IconTexture")
|
|
if btnIcon then
|
|
btnIcon:SetWidth(buttonSize)
|
|
btnIcon:SetHeight(buttonSize)
|
|
end
|
|
|
|
-- Scale or hide border based on theme
|
|
local btnNormalTex = getglobal(btn:GetName() .. "NormalTexture")
|
|
local flyoutSlotStyle = "rounded"
|
|
if addon.Modules and addon.Modules.Theme then
|
|
flyoutSlotStyle = addon.Modules.Theme:GetSlotStyle()
|
|
end
|
|
if flyoutSlotStyle == "square" then
|
|
btn:SetNormalTexture("")
|
|
if btnNormalTex then
|
|
btnNormalTex:SetTexture(nil)
|
|
btnNormalTex:Hide()
|
|
end
|
|
if btnIcon then
|
|
btnIcon:SetTexCoord(.08, .92, .08, .92)
|
|
end
|
|
else
|
|
local borderSize = buttonSize * 64 / 37
|
|
if btnNormalTex then
|
|
btnNormalTex:SetWidth(borderSize)
|
|
btnNormalTex:SetHeight(borderSize)
|
|
end
|
|
end
|
|
|
|
-- Resize empty slot background
|
|
local btnEmptyBg = getglobal(btn:GetName() .. "_EmptySlotBg")
|
|
if btnEmptyBg then
|
|
btnEmptyBg:SetWidth(buttonSize)
|
|
btnEmptyBg:SetHeight(buttonSize)
|
|
end
|
|
|
|
btn:Show()
|
|
|
|
if Guda_ItemButton_UpdateCooldown then
|
|
Guda_ItemButton_UpdateCooldown(btn)
|
|
end
|
|
end
|
|
|
|
flyoutFrame:SetWidth(buttonSize + 10)
|
|
flyoutFrame:SetHeight(table.getn(displayItems) * (buttonSize + spacing) + 10)
|
|
end
|
|
|
|
-- Global wrappers for keybindings
|
|
function Guda_UseQuestItem1()
|
|
local button = getglobal("Guda_QuestItemBarButton1")
|
|
if button and button:IsShown() and button.hasItem and button.bagID and button.slotID then
|
|
UseContainerItem(button.bagID, button.slotID)
|
|
end
|
|
end
|
|
|
|
function Guda_UseQuestItem2()
|
|
local button = getglobal("Guda_QuestItemBarButton2")
|
|
if button and button:IsShown() and button.hasItem and button.bagID and button.slotID then
|
|
UseContainerItem(button.bagID, button.slotID)
|
|
end
|
|
end
|
|
|
|
function QuestItemBar:Initialize()
|
|
local frame = CreateFrame("Frame", "Guda_QuestItemBar", UIParent)
|
|
frame:SetWidth(40)
|
|
frame:SetHeight(45)
|
|
frame:SetPoint("BOTTOM", UIParent, "BOTTOM", 0, 150)
|
|
frame:EnableMouse(true)
|
|
frame:SetMovable(true)
|
|
frame:SetClampedToScreen(true)
|
|
|
|
--addon:ApplyBackdrop(frame, "DEFAULT_FRAME")
|
|
|
|
-- Create flyout frame
|
|
flyoutFrame = CreateFrame("Frame", "Guda_QuestItemFlyout", UIParent)
|
|
flyoutFrame:SetFrameStrata("TOOLTIP")
|
|
flyoutFrame:Hide()
|
|
addon:ApplyBackdrop(flyoutFrame, "DEFAULT_FRAME")
|
|
|
|
-- Handle dragging
|
|
frame:RegisterForDrag("LeftButton")
|
|
frame:SetScript("OnMouseDown", function()
|
|
if arg1 == "LeftButton" then
|
|
this:StartMoving()
|
|
this.isMoving = true
|
|
end
|
|
end)
|
|
frame:SetScript("OnMouseUp", function()
|
|
if arg1 == "LeftButton" and this.isMoving then
|
|
this:StopMovingOrSizing()
|
|
this.isMoving = false
|
|
local point, _, relativePoint, x, y = this:GetPoint()
|
|
addon.Modules.DB:SetSetting("questBarPosition", {point = point, relativePoint = relativePoint, x = x, y = y})
|
|
end
|
|
end)
|
|
|
|
-- Restore position
|
|
local pos = addon.Modules.DB:GetSetting("questBarPosition")
|
|
if pos and pos.point then
|
|
frame:ClearAllPoints()
|
|
frame:SetPoint(pos.point, UIParent, pos.relativePoint or pos.point, pos.x, pos.y)
|
|
end
|
|
|
|
-- Register for events with debouncing to prevent lag on rapid bag updates
|
|
local bagUpdatePending = false
|
|
addon.Modules.Events:Register("BAG_UPDATE", function()
|
|
-- Skip updates while sorting is in progress (sort completion will trigger update)
|
|
if addon.Modules.SortEngine and addon.Modules.SortEngine.sortingInProgress then return end
|
|
if bagUpdatePending then return end
|
|
bagUpdatePending = true
|
|
-- Debounce: wait 0.15 seconds before updating (uses pooled timer)
|
|
Guda_ScheduleTimer(0.15, function()
|
|
bagUpdatePending = false
|
|
QuestItemBar:Update()
|
|
end)
|
|
end, "QuestItemBar")
|
|
|
|
addon.Modules.Events:Register("BAG_UPDATE_COOLDOWN", function()
|
|
QuestItemBar:UpdateCooldowns()
|
|
end, "QuestItemBar")
|
|
|
|
addon.Modules.Events:Register("PLAYER_ENTERING_WORLD", function()
|
|
QuestItemBar:Update()
|
|
end, "QuestItemBar")
|
|
|
|
QuestItemBar:Update()
|
|
addon:Debug("QuestItemBar initialized")
|
|
end
|
|
|
|
-- Debug function to diagnose QuestItemBar issues
|
|
-- Usage: /script Guda.Modules.QuestItemBar:Debug()
|
|
function QuestItemBar:Debug()
|
|
addon:Print("=== QuestItemBar Debug ===")
|
|
|
|
-- Check setting
|
|
local showQuestBar = addon.Modules.DB:GetSetting("showQuestBar")
|
|
addon:Print("showQuestBar setting: " .. tostring(showQuestBar))
|
|
|
|
-- Check frame
|
|
local frame = Guda_QuestItemBar
|
|
addon:Print("Frame exists: " .. tostring(frame ~= nil))
|
|
if frame then
|
|
addon:Print("Frame shown: " .. tostring(frame:IsShown()))
|
|
end
|
|
|
|
-- Scan all bags for potential quest items
|
|
addon:Print("--- Scanning bags ---")
|
|
local foundCount = 0
|
|
for bagID = 0, 4 do
|
|
local numSlots = GetContainerNumSlots(bagID)
|
|
for slotID = 1, numSlots do
|
|
local texture, count = GetContainerItemInfo(bagID, slotID)
|
|
if texture then
|
|
local itemLink = GetContainerItemLink(bagID, slotID)
|
|
local itemData = addon.Modules.BagScanner:ScanSlot(bagID, slotID)
|
|
|
|
if itemData then
|
|
local props = addon.Modules.ItemDetection:GetItemProperties(itemData, bagID, slotID)
|
|
|
|
-- Show items that are quest-related OR have Quest class
|
|
if props.isQuestItem or props.isQuestUsable or (itemData.class and itemData.class == "Quest") then
|
|
foundCount = foundCount + 1
|
|
addon:Print(string.format("[%d:%d] %s", bagID, slotID, itemData.name or "Unknown"))
|
|
addon:Print(string.format(" class=%s, isQuest=%s, isUsable=%s, isStarter=%s",
|
|
tostring(itemData.class),
|
|
tostring(props.isQuestItem),
|
|
tostring(props.isQuestUsable),
|
|
tostring(props.isQuestStarter)))
|
|
|
|
-- Check if it would show in bar
|
|
local wouldShow = props.isQuestItem and props.isQuestUsable and not props.isQuestStarter
|
|
addon:Print(" Would show in bar: " .. tostring(wouldShow))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if foundCount == 0 then
|
|
addon:Print("No quest-related items found in bags")
|
|
end
|
|
|
|
addon:Print("=== End Debug ===")
|
|
end
|
|
|
|
QuestItemBar.isLoaded = true
|