Files
MetaHunt/api/options-autobuy.lua
T
DuvelCorp ccf9d8b0b6 Unify all option panels through MTH_Layout engine
Add reusable MTH_Layout box/column layout engine (api/options-layout.lua) and route every option panel through it (shell, general, zButtons per-button config, zBar, chronometer, auto buy, profiles, credits, etc.) for consistent, auto-sizing layout. Restore realm gate. README note.
2026-09-10 23:59:37 +02:00

834 lines
26 KiB
Lua

local MTH_AB_READY = MTH_OptionsRequire and MTH_OptionsRequire("options-autobuy", {
"MTH_GetFrame",
"MTH_ClearContainer",
"MTH_CreateCheckbox",
})
local MTH_AB_LAYOUT = {
LEFT_SECTION_X = 0,
RIGHT_SECTION_X = 290,
ROW_CHECK_X = 0,
ROW_CHECK_LABEL_X = 27,
ROW_DROPDOWN_X = 33,
ROW_DROPDOWN_WIDTH = 100,
ROW_QTY_GAP = 6,
ROW_SUFFIX_GAP = 6,
ROW_STEP = 40,
SECTION_TITLE_Y = -110,
SECTION_ROWS_Y0 = -138,
}
local MTH_AB_STATE = {
container = nil,
built = false,
syncing = false,
controls = {
moduleEnabled = nil,
projectilesEnabled = nil,
petFoodEnabled = nil,
petFoodQty = nil,
petFoodQtyLabel = nil,
petFoodQtySuffix = nil,
petFoodScopeCurrent = nil,
petFoodScopeAll = nil,
petFoodTitle = nil,
petFoodPetLines = {},
title = nil,
body = nil,
sectionArrowTitle = nil,
sectionBulletTitle = nil,
rows = {
arrow = {},
bullet = {},
},
},
}
local MTH_AB_TRANSIENT_STORE = {}
local function MTH_AB_SetCheckedNoClick(check, checked)
if not check then return end
MTH_AB_STATE.syncing = true
check:SetChecked(checked and true or false)
MTH_AB_STATE.syncing = false
end
local function MTH_AB_IsChecked(control)
if not control or type(control.GetChecked) ~= "function" then
return false
end
local checked = control:GetChecked()
return checked == 1 or checked == true
end
local function MTH_AB_GetEngine()
return MTH_AutoBuyEngine
end
local function MTH_AB_GetStore()
local engine = MTH_AB_GetEngine()
if engine and engine.EnsureDefaults then
return engine:EnsureDefaults()
end
return MTH_AB_TRANSIENT_STORE
end
local function MTH_AB_NormalizeRule(rule)
if type(rule) ~= "table" then
rule = {}
end
if rule.enabled == nil then
rule.enabled = false
end
rule.enabled = rule.enabled and true or false
rule.itemId = rule.itemId and (tonumber(rule.itemId) or rule.itemId) or nil
local stacks = tonumber(rule.stacks)
if not stacks then
stacks = rule.enabled and 1 or 0
end
stacks = math.floor(stacks)
if stacks < 0 then
stacks = 0
end
if rule.enabled and stacks < 1 then
stacks = 1
end
rule.stacks = stacks
return rule
end
local function MTH_AB_EnsureConfig()
local store = MTH_AB_GetStore()
if store.enabled == nil then store.enabled = false end
if type(store.projectiles) ~= "table" then store.projectiles = {} end
if type(store.petFood) ~= "table" then store.petFood = {} end
if store.projectiles.enabled == nil then store.projectiles.enabled = false end
if store.petFood.enabled == nil then store.petFood.enabled = false end
if store.petFood.stacks == nil then store.petFood.stacks = 1 end
if store.petFood.scope == nil then store.petFood.scope = "current" end
store.petFood.stacks = math.floor(tonumber(store.petFood.stacks) or 1)
if store.petFood.stacks < 1 then store.petFood.stacks = 1 end
if store.petFood.scope ~= "current" and store.petFood.scope ~= "all" then
store.petFood.scope = "current"
end
if type(store.projectiles.arrows) ~= "table" then store.projectiles.arrows = {} end
if type(store.projectiles.bullets) ~= "table" then store.projectiles.bullets = {} end
if type(store.projectiles.arrows.rules) ~= "table" then store.projectiles.arrows.rules = {} end
if type(store.projectiles.bullets.rules) ~= "table" then store.projectiles.bullets.rules = {} end
for i = 1, 3 do
store.projectiles.arrows.rules[i] = MTH_AB_NormalizeRule(store.projectiles.arrows.rules[i])
store.projectiles.bullets.rules[i] = MTH_AB_NormalizeRule(store.projectiles.bullets.rules[i])
end
return store
end
local function MTH_AB_SetPetFoodStacks(store, value)
if type(store) ~= "table" or type(store.petFood) ~= "table" then
return
end
local stacks = math.floor(tonumber(value) or 1)
if stacks < 1 then stacks = 1 end
store.petFood.stacks = stacks
end
local function MTH_AB_TitleCase(text)
local source = tostring(text or "")
if source == "" then return "" end
return string.upper(string.sub(source, 1, 1)) .. string.lower(string.sub(source, 2))
end
local function MTH_AB_NormalizeFamilyToken(text)
local value = string.lower(tostring(text or ""))
value = string.gsub(value, "%b()", " ")
value = string.gsub(value, "[^%a]", "")
return value
end
local function MTH_AB_SingularizeFamilyToken(token)
local value = tostring(token or "")
if string.len(value) <= 3 then
return value
end
if string.sub(value, -3) == "ves" and string.len(value) > 4 then
return string.sub(value, 1, -4) .. "f"
end
if string.sub(value, -3) == "ies" and string.len(value) > 4 then
return string.sub(value, 1, -4) .. "y"
end
if string.sub(value, -3) == "xes" and string.len(value) > 4 then
return string.sub(value, 1, -3)
end
if string.sub(value, -4) == "ches" and string.len(value) > 5 then
return string.sub(value, 1, -3)
end
if string.sub(value, -4) == "shes" and string.len(value) > 5 then
return string.sub(value, 1, -3)
end
if string.sub(value, -3) == "zes" and string.len(value) > 4 then
return string.sub(value, 1, -3)
end
if string.sub(value, -3) == "ses" then
return string.sub(value, 1, -3)
end
if string.sub(value, -1) == "s" then
return string.sub(value, 1, -2)
end
return value
end
local function MTH_AB_FindFamilyDietRow(familyName)
if type(MTH_DS_Families) ~= "table" then
return nil
end
local needle = MTH_AB_NormalizeFamilyToken(familyName)
if needle == "" then
return nil
end
local needleSingular = MTH_AB_SingularizeFamilyToken(needle)
for key, row in pairs(MTH_DS_Families) do
local candidate = MTH_AB_NormalizeFamilyToken(key)
if candidate ~= "" then
if candidate == needle or candidate == needleSingular then
return row
end
local candidateSingular = MTH_AB_SingularizeFamilyToken(candidate)
if candidateSingular == needle or candidateSingular == needleSingular then
return row
end
end
end
return nil
end
local function MTH_AB_GetPetDietText(familyName)
local family = tostring(familyName or "")
if family == "" then
return "unknown diet"
end
local row = MTH_AB_FindFamilyDietRow(family)
if type(row) ~= "table" or type(row.food) ~= "table" then
return "unknown diet"
end
local diets = {}
for i = 1, table.getn(row.food) do
local diet = tostring(row.food[i] or "")
if diet ~= "" then
table.insert(diets, MTH_AB_TitleCase(diet))
end
end
if table.getn(diets) == 0 then
return "unknown diet"
end
return table.concat(diets, ", ")
end
local function MTH_AB_GetPetFoodEntries()
if type(MTH_PETS_RefreshCurrentPet) == "function" then
pcall(MTH_PETS_RefreshCurrentPet)
end
local entries = {}
local defaultIcon = "Interface\\Icons\\INV_Misc_QuestionMark"
local function buildEntryFromRow(row)
if type(row) ~= "table" then
return nil
end
local name = tostring(row.name or "")
if name == "" then
return nil
end
local family = tostring(row.family or "")
local icon = tostring((type(row.stableInfo) == "table" and row.stableInfo.icon) or row.icon or "")
if icon == "" and type(row.stableRaw) == "table" then
icon = tostring(row.stableRaw[1] or "")
end
if icon == "" then icon = defaultIcon end
return {
icon = icon,
name = name,
family = family,
diets = MTH_AB_GetPetDietText(family),
}
end
local function setSlot(slot, data)
entries[slot + 1] = data
end
for slot = 0, 4 do
setSlot(slot, {
icon = defaultIcon,
name = "",
diets = "",
placeholder = (slot == 0) and "NO CURRENT PET !" or "Free slot",
})
end
local petsRoot = type(MTH_PETS_GetRootStore) == "function" and MTH_PETS_GetRootStore() or nil
local petStore = petsRoot and petsRoot.petStore or nil
local activeById = petStore and petStore.activeById or nil
local stableSlotIndex = petStore and petStore.stableSlotIndex or nil
local currentInfo = type(MTH_GetCurrentPetInfo) == "function" and MTH_GetCurrentPetInfo() or nil
if currentInfo and currentInfo.liveExists then
local currentName = tostring(currentInfo.name or "")
if currentName ~= "" then
local currentFamily = tostring(currentInfo.family or "")
local currentIcon = defaultIcon
local currentId = currentInfo.id
if currentId and type(activeById) == "table" and type(activeById[currentId]) == "table" then
local currentRow = activeById[currentId]
local iconFromRow = tostring((type(currentRow.stableInfo) == "table" and currentRow.stableInfo.icon) or currentRow.icon or "")
if iconFromRow == "" and type(currentRow.stableRaw) == "table" then
iconFromRow = tostring(currentRow.stableRaw[1] or "")
end
if iconFromRow ~= "" then
currentIcon = iconFromRow
end
end
setSlot(0, {
icon = currentIcon,
name = currentName,
family = currentFamily,
diets = MTH_AB_GetPetDietText(currentFamily),
})
end
end
for slot = 1, 4 do
local petId = nil
if type(stableSlotIndex) == "table" then
petId = stableSlotIndex[slot]
end
local row = (petId and type(activeById) == "table") and activeById[petId] or nil
if type(row) ~= "table" and type(activeById) == "table" then
for _, candidate in pairs(activeById) do
if type(candidate) == "table" and tonumber(candidate.stableSlot) == slot then
row = candidate
break
end
end
end
local entry = buildEntryFromRow(row)
if entry then
setSlot(slot, entry)
end
end
return entries
end
local function MTH_AB_RefreshPetFoodListUI()
local lines = MTH_AB_STATE.controls.petFoodPetLines or {}
if table.getn(lines) == 0 then
return
end
local entries = MTH_AB_GetPetFoodEntries()
for i = 1, table.getn(lines) do
local line = lines[i]
local entry = entries[i]
if line and line.text and line.icon then
if entry then
line.icon:Show()
line.icon:SetTexture(tostring(entry.icon or "Interface\\Icons\\INV_Misc_QuestionMark"))
line.text:Show()
if tostring(entry.name or "") ~= "" then
line.text:SetText(tostring(entry.name) .. " likes " .. tostring(entry.diets or "unknown diet"))
else
line.text:SetText(tostring(entry.placeholder or ""))
end
else
line.icon:Hide()
line.text:SetText("")
end
end
end
end
local function MTH_AB_GetBuyableItems(subtype)
if type(MTH_AutoBuy_GetProjectileItems) == "function" then
local result = MTH_AutoBuy_GetProjectileItems(subtype)
if type(result) == "table" then
for i = 1, table.getn(result) do
local row = result[i]
if type(row) == "table" then
local itemId = tonumber(row.itemId)
if itemId and MTH and MTH.GetLocalizedItemName then
row.name = MTH:GetLocalizedItemName(itemId, row.name)
end
end
end
return result
end
end
local wanted = string.lower(tostring(subtype or ""))
local result = {}
local source = MTH_DS_AmmoItems or {}
for itemId, row in pairs(source) do
if type(row) == "table" and string.lower(tostring(row.subtype or "")) == wanted and type(row.vendors) == "table" then
for _ in pairs(row.vendors) do
local defaultName = tostring(row.name or ("Item " .. tostring(itemId)))
local localizedName = (MTH and MTH.GetLocalizedItemName)
and MTH:GetLocalizedItemName(itemId, defaultName)
or defaultName
table.insert(result, {
itemId = tonumber(itemId) or itemId,
name = tostring(localizedName),
level = tonumber(row.level) or 0,
reqlevel = tonumber(row.reqlevel) or 0,
})
break
end
end
end
table.sort(result, function(a, b)
if (a.level or 0) ~= (b.level or 0) then
return (a.level or 0) < (b.level or 0)
end
if tostring(a.name or "") ~= tostring(b.name or "") then
return tostring(a.name or "") < tostring(b.name or "")
end
return tonumber(a.itemId or 0) < tonumber(b.itemId or 0)
end)
return result
end
local function MTH_AB_GetItemLabel(item)
if type(item) ~= "table" then return "Unknown" end
return tostring(item.name or ("Item " .. tostring(item.itemId or "")))
end
local function MTH_AB_DropdownSetText(frame, text)
if UIDropDownMenu_SetText then
UIDropDownMenu_SetText(tostring(text or ""), frame)
return
end
if not frame then return end
local textRegion = getglobal(frame:GetName() .. "Text")
if textRegion and textRegion.SetText then
textRegion:SetText(tostring(text or ""))
end
end
local function MTH_AB_FindItemById(list, itemId)
itemId = tonumber(itemId)
if not itemId or type(list) ~= "table" then return nil end
for i = 1, table.getn(list) do
if tonumber(list[i].itemId) == itemId then
return list[i]
end
end
return nil
end
local function MTH_AB_GetRule(store, subtype, index)
local bucket = subtype == "arrow" and store.projectiles.arrows or store.projectiles.bullets
if type(bucket.rules[index]) ~= "table" then
bucket.rules[index] = MTH_AB_NormalizeRule(nil)
end
bucket.rules[index] = MTH_AB_NormalizeRule(bucket.rules[index])
return bucket.rules[index]
end
local function MTH_AB_SetRuleEnabled(store, subtype, index, enabled)
local rule = MTH_AB_GetRule(store, subtype, index)
rule.enabled = enabled and true or false
if not rule.enabled then
rule.itemId = nil
rule.stacks = 0
elseif rule.stacks < 1 then
rule.stacks = 1
end
end
local function MTH_AB_SetRuleItem(store, subtype, index, itemId)
local rule = MTH_AB_GetRule(store, subtype, index)
rule.itemId = itemId and (tonumber(itemId) or itemId) or nil
end
local function MTH_AB_SetRuleStacks(store, subtype, index, value)
local rule = MTH_AB_GetRule(store, subtype, index)
local stacks = math.floor(tonumber(value) or 0)
if stacks < 0 then stacks = 0 end
if rule.enabled and stacks < 1 then stacks = 1 end
rule.stacks = stacks
end
local function MTH_AB_RefreshRowUI(row, store, moduleEnabled, projectilesEnabled)
local rule = MTH_AB_GetRule(store, row.subtype, row.index)
local rowEnabled = moduleEnabled and projectilesEnabled and rule.enabled
local rowInteractive = moduleEnabled and projectilesEnabled
local muted = rowInteractive and 1 or 0.5
MTH_AB_SetCheckedNoClick(row.check, rule.enabled)
if rowInteractive then
if row.check.Enable then row.check:Enable() end
else
if row.check.Disable then row.check:Disable() end
end
if UIDropDownMenu_EnableDropDown and UIDropDownMenu_DisableDropDown then
if rowEnabled then
UIDropDownMenu_EnableDropDown(row.dropdown)
else
UIDropDownMenu_DisableDropDown(row.dropdown)
end
end
local selectedItem = MTH_AB_FindItemById(row.items, rule.itemId)
if selectedItem then
MTH_AB_DropdownSetText(row.dropdown, MTH_AB_GetItemLabel(selectedItem))
else
MTH_AB_DropdownSetText(row.dropdown, "Select item...")
end
if row.qty then
if rowEnabled then
if row.qty.Enable then row.qty:Enable() end
if row.qty.EnableMouse then row.qty:EnableMouse(true) end
if row.qty.SetTextColor then row.qty:SetTextColor(1, 1, 1) end
else
if row.qty.Disable then row.qty:Disable() end
if row.qty.EnableMouse then row.qty:EnableMouse(false) end
if row.qty.ClearFocus then row.qty:ClearFocus() end
if row.qty.SetTextColor then row.qty:SetTextColor(0.6, 0.6, 0.6) end
end
row.qty:SetText(tostring(rule.stacks or 0))
end
if row.label and row.label.SetTextColor then
row.label:SetTextColor(muted, muted, muted)
end
if row.suffix and row.suffix.SetTextColor then
row.suffix:SetTextColor(muted, muted, muted)
end
end
local function MTH_AB_RefreshOptionsUI()
if not MTH_AB_STATE.built then return end
local store = MTH_AB_EnsureConfig()
local moduleEnabled = true
if MTH and MTH.IsModuleEnabled then
moduleEnabled = MTH:IsModuleEnabled("autobuy", false) and true or false
end
MTH_AB_SetCheckedNoClick(MTH_AB_STATE.controls.moduleEnabled, moduleEnabled)
MTH_AB_SetCheckedNoClick(MTH_AB_STATE.controls.projectilesEnabled, store.projectiles.enabled and true or false)
if MTH_AB_STATE.controls.projectilesEnabled then
local proj = MTH_AB_STATE.controls.projectilesEnabled
if moduleEnabled then
if proj.Enable then
proj:Enable()
end
else
if proj.Disable then
proj:Disable()
end
end
end
if MTH_AB_STATE.controls.petFoodEnabled then
local pf = MTH_AB_STATE.controls.petFoodEnabled
MTH_AB_SetCheckedNoClick(pf, store.petFood.enabled and true or false)
if moduleEnabled then
if pf.Enable then pf:Enable() end
else
if pf.Disable then pf:Disable() end
end
end
local petFoodInteractive = moduleEnabled and store.petFood.enabled
if MTH_AB_STATE.controls.petFoodQty then
local qty = MTH_AB_STATE.controls.petFoodQty
qty:SetText(tostring(store.petFood.stacks or 1))
if petFoodInteractive then
if qty.Enable then qty:Enable() end
if qty.EnableMouse then qty:EnableMouse(true) end
if qty.SetTextColor then qty:SetTextColor(1, 1, 1) end
else
if qty.Disable then qty:Disable() end
if qty.EnableMouse then qty:EnableMouse(false) end
if qty.ClearFocus then qty:ClearFocus() end
if qty.SetTextColor then qty:SetTextColor(0.6, 0.6, 0.6) end
end
end
if MTH_AB_STATE.controls.petFoodScopeCurrent then
MTH_AB_SetCheckedNoClick(MTH_AB_STATE.controls.petFoodScopeCurrent, store.petFood.scope == "current")
if petFoodInteractive then
if MTH_AB_STATE.controls.petFoodScopeCurrent.Enable then MTH_AB_STATE.controls.petFoodScopeCurrent:Enable() end
else
if MTH_AB_STATE.controls.petFoodScopeCurrent.Disable then MTH_AB_STATE.controls.petFoodScopeCurrent:Disable() end
end
end
if MTH_AB_STATE.controls.petFoodScopeAll then
MTH_AB_SetCheckedNoClick(MTH_AB_STATE.controls.petFoodScopeAll, store.petFood.scope == "all")
if petFoodInteractive then
if MTH_AB_STATE.controls.petFoodScopeAll.Enable then MTH_AB_STATE.controls.petFoodScopeAll:Enable() end
else
if MTH_AB_STATE.controls.petFoodScopeAll.Disable then MTH_AB_STATE.controls.petFoodScopeAll:Disable() end
end
end
MTH_AB_RefreshPetFoodListUI()
for i = 1, 3 do
MTH_AB_RefreshRowUI(MTH_AB_STATE.controls.rows.arrow[i], store, moduleEnabled, store.projectiles.enabled)
MTH_AB_RefreshRowUI(MTH_AB_STATE.controls.rows.bullet[i], store, moduleEnabled, store.projectiles.enabled)
end
end
local function MTH_AB_CreateRow(box, subtype, index)
local f, y = box:Row(38)
local padX = box:PadX()
local row = {
subtype = subtype,
index = index,
items = MTH_AB_GetBuyableItems(subtype),
}
local nameBase = "MetaHuntOptionsAutoBuy_" .. subtype .. "_" .. tostring(index)
row.check = MTH_CreateCheckbox(f, nameBase .. "Check", "", y, padX)
row.label = getglobal(nameBase .. "Label") or f:CreateFontString(nameBase .. "Label", "ARTWORK", "GameFontNormalSmall")
row.label:ClearAllPoints()
row.label:SetPoint("TOPLEFT", f, "TOPLEFT", padX + 27, y - 5)
row.label:SetText("On?")
row.dropdown = getglobal(nameBase .. "Drop") or CreateFrame("Frame", nameBase .. "Drop", f, "UIDropDownMenuTemplate")
row.dropdown:ClearAllPoints()
row.dropdown:SetPoint("TOPLEFT", f, "TOPLEFT", padX + 33, y + 3)
if UIDropDownMenu_SetWidth then
UIDropDownMenu_SetWidth(MTH_AB_LAYOUT.ROW_DROPDOWN_WIDTH, row.dropdown)
end
if UIDropDownMenu_JustifyText then
UIDropDownMenu_JustifyText("LEFT", row.dropdown)
end
if UIDropDownMenu_Initialize then
UIDropDownMenu_Initialize(row.dropdown, function()
local infoFactory = UIDropDownMenu_CreateInfo
local info = type(infoFactory) == "function" and infoFactory() or {}
info.text = "Select item..."
info.func = function()
local store = MTH_AB_EnsureConfig()
MTH_AB_SetRuleItem(store, subtype, index, nil)
MTH_AB_RefreshOptionsUI()
end
if UIDropDownMenu_AddButton then UIDropDownMenu_AddButton(info) end
for j = 1, table.getn(row.items) do
local item = row.items[j]
local label = MTH_AB_GetItemLabel(item)
local itemId = item.itemId
local entry = type(infoFactory) == "function" and infoFactory() or {}
entry.text = label
entry.func = function()
local store = MTH_AB_EnsureConfig()
MTH_AB_SetRuleItem(store, subtype, index, itemId)
MTH_AB_RefreshOptionsUI()
end
if UIDropDownMenu_AddButton then UIDropDownMenu_AddButton(entry) end
end
end)
end
row.qty = getglobal(nameBase .. "Qty") or CreateFrame("EditBox", nameBase .. "Qty", f, "InputBoxTemplate")
row.qty:ClearAllPoints()
local dropButton = getglobal(nameBase .. "DropButton")
if dropButton then
row.qty:SetPoint("LEFT", dropButton, "RIGHT", MTH_AB_LAYOUT.ROW_QTY_GAP, -1)
else
row.qty:SetPoint("LEFT", row.dropdown, "RIGHT", MTH_AB_LAYOUT.ROW_QTY_GAP + 6, -3)
end
row.qty:SetWidth(40)
row.qty:SetHeight(20)
row.qty:SetNumeric(true)
row.qty:SetAutoFocus(false)
row.suffix = getglobal(nameBase .. "Suffix") or f:CreateFontString(nameBase .. "Suffix", "ARTWORK", "GameFontNormalSmall")
row.suffix:ClearAllPoints()
row.suffix:SetPoint("LEFT", row.qty, "RIGHT", MTH_AB_LAYOUT.ROW_SUFFIX_GAP, 0)
row.suffix:SetText("Stacks")
if row.check then
row.check:SetScript("OnClick", function()
if not this or MTH_AB_STATE.syncing then return end
local store = MTH_AB_EnsureConfig()
MTH_AB_SetRuleEnabled(store, subtype, index, MTH_AB_IsChecked(this))
MTH_AB_RefreshOptionsUI()
end)
end
row.qty:SetScript("OnEnterPressed", function()
if not this then return end
local store = MTH_AB_EnsureConfig()
MTH_AB_SetRuleStacks(store, subtype, index, this:GetText())
MTH_AB_RefreshOptionsUI()
this:ClearFocus()
end)
row.qty:SetScript("OnEditFocusLost", function()
if not this then return end
local store = MTH_AB_EnsureConfig()
MTH_AB_SetRuleStacks(store, subtype, index, this:GetText())
MTH_AB_RefreshOptionsUI()
end)
return row
end
local function MTH_AB_BuildUI(container)
if MTH_AB_STATE.built and MTH_AB_STATE.container == container then
return
end
local panel = MTH_Layout.Panel(container)
MTH_AB_STATE.container = container
MTH_AB_STATE.built = true
local controls = MTH_AB_STATE.controls
panel:Title("Auto Buy")
panel:Note("Configure automatic buying rules that trigger when you open a vendor. Quantity is how many STACKS of the item you want in your bags after purchase.",
{ lines = 2, color = MTH_Layout.Theme.colText })
controls.moduleEnabled = panel:TopCheckbox("MetaHuntOptionsAutoBuyModuleEnabled", "Enable Auto Buy module", {
onClick = function()
if not this or MTH_AB_STATE.syncing then return end
if MTH and MTH.SetModuleEnabled then
local ok, err = MTH:SetModuleEnabled("autobuy", MTH_AB_IsChecked(this))
if not ok and MTH and MTH.Print then
MTH:Print("Failed to change Auto Buy state: " .. tostring(err), "error")
end
end
MTH_AB_RefreshOptionsUI()
end,
})
controls.projectilesEnabled = panel:TopCheckbox("MetaHuntOptionsAutoBuyProjectilesEnabled", "Enable for Projectiles (arrows & bullets)", {
onClick = function()
if not this or MTH_AB_STATE.syncing then return end
local store = MTH_AB_EnsureConfig()
store.projectiles.enabled = MTH_AB_IsChecked(this)
MTH_AB_RefreshOptionsUI()
end,
})
-- ===== LEFT: Arrows / RIGHT: Bullets (3 rules each) =====
local arrowBox = panel:Box("left", "MetaHuntOptionsAutoBuyArrowsBox", "Arrows")
for i = 1, 3 do
controls.rows.arrow[i] = MTH_AB_CreateRow(arrowBox, "arrow", i)
end
local bulletBox = panel:Box("right", "MetaHuntOptionsAutoBuyBulletsBox", "Bullets")
for i = 1, 3 do
controls.rows.bullet[i] = MTH_AB_CreateRow(bulletBox, "bullet", i)
end
-- ===== Pet Food =====
local petBox = panel:Box(panel:ShorterSide(), "MetaHuntOptionsAutoBuyPetFoodBox", "Pet Food")
controls.petFoodEnabled = petBox:Checkbox("MetaHuntOptionsAutoBuyPetFoodEnabled", "Enable for Pet Food", {
onClick = function()
if not this or MTH_AB_STATE.syncing then return end
local store = MTH_AB_EnsureConfig()
store.petFood.enabled = MTH_AB_IsChecked(this)
MTH_AB_RefreshOptionsUI()
end,
})
controls.petFoodQty = petBox:EditRow("MetaHuntOptionsAutoBuyPetFoodQtyLabel", "Quantity:",
"MetaHuntOptionsAutoBuyPetFoodQty", 40, { numeric = true, height = 20 })
if controls.petFoodQty then
controls.petFoodQty:SetScript("OnEnterPressed", function()
if not this then return end
local store = MTH_AB_EnsureConfig()
MTH_AB_SetPetFoodStacks(store, this:GetText())
MTH_AB_RefreshOptionsUI()
this:ClearFocus()
end)
controls.petFoodQty:SetScript("OnEditFocusLost", function()
if not this then return end
local store = MTH_AB_EnsureConfig()
MTH_AB_SetPetFoodStacks(store, this:GetText())
MTH_AB_RefreshOptionsUI()
end)
local suffix = getglobal("MetaHuntOptionsAutoBuyPetFoodQtySuffix")
if not suffix then
suffix = petBox:Frame():CreateFontString("MetaHuntOptionsAutoBuyPetFoodQtySuffix", "ARTWORK", "GameFontNormalSmall")
end
suffix:ClearAllPoints()
suffix:SetPoint("LEFT", controls.petFoodQty, "RIGHT", 8, 0)
suffix:SetText("stacks")
controls.petFoodQtySuffix = suffix
end
controls.petFoodScopeCurrent = petBox:Checkbox("MetaHuntOptionsAutoBuyPetFoodScopeCurrent", "Buy only for my current pet", {
onClick = function()
if not this or MTH_AB_STATE.syncing then return end
local store = MTH_AB_EnsureConfig()
store.petFood.scope = "current"
MTH_AB_RefreshOptionsUI()
end,
})
controls.petFoodScopeAll = petBox:Checkbox("MetaHuntOptionsAutoBuyPetFoodScopeAll", "Buy for all my pets", {
onClick = function()
if not this or MTH_AB_STATE.syncing then return end
local store = MTH_AB_EnsureConfig()
store.petFood.scope = "all"
MTH_AB_RefreshOptionsUI()
end,
})
controls.petFoodPetLines = {}
for i = 1, 5 do
local f, y = petBox:Row(22)
local padX = petBox:PadX()
local icon = getglobal("MetaHuntOptionsAutoBuyPetFoodPetIcon" .. tostring(i))
if not icon then
icon = f:CreateTexture("MetaHuntOptionsAutoBuyPetFoodPetIcon" .. tostring(i), "ARTWORK")
end
icon:SetWidth(16)
icon:SetHeight(16)
icon:ClearAllPoints()
icon:SetPoint("TOPLEFT", f, "TOPLEFT", padX + 4, y)
icon:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark")
local text = getglobal("MetaHuntOptionsAutoBuyPetFoodPetText" .. tostring(i))
if not text then
text = f:CreateFontString("MetaHuntOptionsAutoBuyPetFoodPetText" .. tostring(i), "ARTWORK", "GameFontNormalSmall")
end
text:ClearAllPoints()
text:SetPoint("LEFT", icon, "RIGHT", 6, 0)
text:SetJustifyH("LEFT")
text:SetTextColor(1, 1, 1)
text:SetText("")
controls.petFoodPetLines[i] = { icon = icon, text = text }
end
panel:Finish()
end
function MTH_SetupAutoBuyOptions()
if not MTH_AB_READY then return end
local container = MTH_GetFrame("MetaHuntOptionsAutoBuy")
if not container then return end
if CloseDropDownMenus then
CloseDropDownMenus()
end
MTH_AB_BuildUI(container)
MTH_AB_RefreshOptionsUI()
end