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.
This commit is contained in:
DuvelCorp
2026-09-10 23:59:37 +02:00
parent adb21c336c
commit ccf9d8b0b6
16 changed files with 1770 additions and 1861 deletions
+2 -4
View File
@@ -9,9 +9,9 @@ Resurrecting on Octowow.
### Added
- **Pet Auto-Teach — Growl**: When you tame a new beast, MetaHunt now offers to teach it Growl at the best rank for the pet's level. Click **Yes** and it opens the Beast Training window, teaches the ability and closes the window for you — no manual trip to the pet trainer needed. Toggle it in **Options → General → Pet Auto-Teach** ("Activate Auto-Teach of Growl (Max rank)", on by default) or with `/mth growl on|off`.
- **Pet Auto-Teach — Growl**: When you tame a new beast, MetaHunt now offers to teach it Growl at the best rank for the pet's level. Click **Yes** and it opens the Beast Training window, teaches the ability and closes the window automatically.
- **Animations**: MetaHunt now plays optional animations that make the interface feel alive. A firework-and-banner celebration bursts on screen when your pet learns a new ability or a new rank, and a red shaking banner warns you when a pet runs away for good. Your pet button flashes when its happiness changes, it gains a loyalty level, or you feed it; the ammo button flashes when Smart Ammo swaps your bullets or auto-equips after a weapon swap; and the MM Widget pulses on a Lock & Load proc. The Great Book slides up and fades in when you open it, gently fades its list when you switch tabs or run a search, fades beast models into view, and fades out when closed; stable slots flash when a pet is deposited, withdrawn or swapped. The options window slides in when opened, fades its tabs as you switch them, and fades out when closed. The minimap button pulses when clicked, minimap markers ping as beasts come into range, collapsible zButton bars fade their buttons in as they expand, the zBar fades in when enabled, and world-map markers fade in when you locate a beast, vendor or master. Everything is optional and off-switchable: a new **Animations** tab (Options → Animations) lets you toggle each effect on its own — or disable them all at once. Powered by the PizzaSauce animation library.
- **Animations**: MetaHunt now plays optional animations that make the interface feel alive. Powered by the PizzaSauce library of [Pizzahawaii](https://codeberg.org/Pizzahawaii/) !
- **zTrack — Find Fish**: Added new spell Find Fish to the zTrack list of trackings.
@@ -19,8 +19,6 @@ Resurrecting on Octowow.
### Changed
- **zButton bars — expand animation**: Collapsible zButton flyout bars and the zBar now fade in together when they open, instead of stacking their buttons one after another, so expanding them feels smoother.
- **Complete revamp of SavedVariables**: All your settings now live in one tidy place instead of being scattered around. A migration happens the first time you log in, and you shouldn't lose any settings.
+47 -78
View File
@@ -80,102 +80,71 @@ function MTH_SetupAnimationsOptions()
return
end
MTH_ClearContainer(container)
local panel = MTH_Layout.Panel(container)
panel:Title(MTH_ANIM_L("ANIM_TITLE", "Animations"))
panel:Note(MTH_ANIM_L("ANIM_CREDIT",
"Animations are powered by PizzaSauce, a WoW 1.12 animation library kindly made and shared by Pizzahawaii. Thank you!"),
{ color = MTH_Layout.Theme.colText, lines = 2 })
panel:Link("MetaHuntOptionsAnimLink", MTH_ANIM_LINK, function() MTH_ANIM_InsertLink(MTH_ANIM_LINK) end)
MTH_ANIM_CTRL = {}
local title = container:CreateFontString("MetaHuntOptionsAnimationsTitle", "ARTWORK", "GameFontNormal")
title:SetPoint("TOPLEFT", container, "TOPLEFT", 10, -10)
title:SetText(MTH_ANIM_L("ANIM_TITLE", "Animations"))
title:SetTextColor(1.00, 0.82, 0.00)
local credit = container:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
credit:SetPoint("TOPLEFT", title, "BOTTOMLEFT", 0, -8)
credit:SetWidth(460)
credit:SetJustifyH("LEFT")
credit:SetText(MTH_ANIM_L("ANIM_CREDIT",
"Animations are powered by PizzaSauce, a WoW 1.12 animation library kindly made and shared by Pizzahawaii. Thank you!"))
credit:SetTextColor(0.93, 0.93, 0.93)
local link = CreateFrame("Button", nil, container)
link:SetPoint("TOPLEFT", credit, "BOTTOMLEFT", 0, -4)
link:SetHeight(16)
link:SetWidth(460)
local linkText = link:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
linkText:SetPoint("LEFT", link, "LEFT", 0, 0)
linkText:SetJustifyH("LEFT")
linkText:SetText(MTH_ANIM_LINK)
linkText:SetTextColor(0.40, 0.75, 1.00)
link:SetScript("OnClick", function() MTH_ANIM_InsertLink(MTH_ANIM_LINK) end)
link:SetScript("OnEnter", function() linkText:SetTextColor(0.60, 0.90, 1.00) end)
link:SetScript("OnLeave", function() linkText:SetTextColor(0.40, 0.75, 1.00) end)
-- Global master toggle.
local master = MTH_CreateCheckbox(container, "MetaHuntOptionsAnimMaster",
MTH_ANIM_L("ANIM_ENABLE_ALL", "Enable animations"), -70)
if master then
master:SetChecked(MTH_FX_AnimationsEnabled())
master:SetScript("OnClick", function()
MTH_FX_SetAnimationsEnabled(master:GetChecked())
-- Global master toggle (full width, above the columns).
panel:TopCheckbox("MetaHuntOptionsAnimMaster",
MTH_ANIM_L("ANIM_ENABLE_ALL", "Enable animations"), {
checked = MTH_FX_AnimationsEnabled,
onClick = function()
local cb = getglobal("MetaHuntOptionsAnimMaster")
MTH_FX_SetAnimationsEnabled(cb:GetChecked())
MTH_ANIM_UpdateChildStates()
end)
end
end,
})
-- Per-animation checkboxes, grouped by section, laid out in two columns.
-- Each whole section is placed into whichever column is currently shorter
-- (largest remaining Y), so the two columns stay balanced as defs grow.
local rowStep = 26
local sectionGap = 12
local columns = {
{ headerX = 15, cbX = 28, y = -104 },
{ headerX = 300, cbX = 313, y = -104 },
}
-- Per-animation checkboxes: each section is a self-sizing box, dropped into
-- whichever column currently has the most room so the two stay balanced.
local s = 1
while MTH_FX_ANIM_SECTIONS and s <= table.getn(MTH_FX_ANIM_SECTIONS) do
local sec = MTH_FX_ANIM_SECTIONS[s]
-- Pick the shorter column (the one whose cursor is nearest the top).
local col = columns[1]
if columns[2].y > columns[1].y then
col = columns[2]
end
local header = container:CreateFontString(nil, "ARTWORK", "GameFontNormal")
header:SetPoint("TOPLEFT", container, "TOPLEFT", col.headerX, col.y)
header:SetText(MTH_ANIM_L(sec.titleKey, sec.title))
header:SetTextColor(1.00, 0.82, 0.00)
col.y = col.y - 22
-- Collect this section's defs in order.
local secDefs = {}
local d = 1
while MTH_FX_ANIM_DEFS and d <= table.getn(MTH_FX_ANIM_DEFS) do
local def = MTH_FX_ANIM_DEFS[d]
if def.section == sec.id then
local cbName = "MetaHuntOptionsAnim_" .. string.gsub(def.key, "%.", "_")
local cb = MTH_CreateCheckbox(container, cbName, MTH_ANIM_L(def.labelKey, def.label), col.y, col.cbX)
if cb then
cb.mthKey = def.key
cb:SetChecked(MTH_FX_GetFlag(def.key))
cb:SetScript("OnClick", function()
MTH_FX_SetFlag(cb.mthKey, cb:GetChecked())
end)
if def.tooltip and def.tooltip ~= "" then
cb.mthTooltip = MTH_ANIM_L(def.tooltipKey, def.tooltip)
cb:SetScript("OnEnter", function()
GameTooltip:SetOwner(cb, "ANCHOR_RIGHT")
GameTooltip:SetText(cb.mthTooltip, 1, 1, 1, 1, true)
GameTooltip:Show()
end)
cb:SetScript("OnLeave", function() GameTooltip:Hide() end)
end
table.insert(MTH_ANIM_CTRL, cb)
col.y = col.y - rowStep
end
table.insert(secDefs, def)
end
d = d + 1
end
col.y = col.y - sectionGap
local count = table.getn(secDefs)
if count > 0 then
local box = panel:Box(panel:ShorterSide(),
"MetaHuntOptionsAnimBox_" .. tostring(sec.id),
MTH_ANIM_L(sec.titleKey, sec.title))
local di = 1
while di <= count do
local def = secDefs[di]
local cbName = "MetaHuntOptionsAnim_" .. string.gsub(def.key, "%.", "_")
local cb = box:Checkbox(cbName, MTH_ANIM_L(def.labelKey, def.label), {
checked = function() return MTH_FX_GetFlag(def.key) end,
tooltip = (def.tooltip and def.tooltip ~= "") and MTH_ANIM_L(def.tooltipKey, def.tooltip) or nil,
})
if cb then
cb.mthKey = def.key
cb:SetScript("OnClick", function()
MTH_FX_SetFlag(cb.mthKey, cb:GetChecked())
end)
table.insert(MTH_ANIM_CTRL, cb)
end
di = di + 1
end
end
s = s + 1
end
panel:Finish()
MTH_ANIM_UpdateChildStates()
MTH_ANIM_DBG.setupResult = "ok"
end
+70 -95
View File
@@ -589,7 +589,9 @@ local function MTH_AB_RefreshOptionsUI()
end
end
local function MTH_AB_CreateRow(container, subtype, index, xBase, yOffset)
local function MTH_AB_CreateRow(box, subtype, index)
local f, y = box:Row(38)
local padX = box:PadX()
local row = {
subtype = subtype,
index = index,
@@ -597,14 +599,15 @@ local function MTH_AB_CreateRow(container, subtype, index, xBase, yOffset)
}
local nameBase = "MetaHuntOptionsAutoBuy_" .. subtype .. "_" .. tostring(index)
row.check = MTH_CreateCheckbox(container, nameBase .. "Check", "", yOffset, xBase + MTH_AB_LAYOUT.ROW_CHECK_X)
row.label = container:CreateFontString(nameBase .. "Label", "ARTWORK", "GameFontNormalSmall")
row.label:SetPoint("TOPLEFT", container, "TOPLEFT", xBase + MTH_AB_LAYOUT.ROW_CHECK_LABEL_X, yOffset - 5)
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 = CreateFrame("Frame", nameBase .. "Drop", container, "UIDropDownMenuTemplate")
row.dropdown = getglobal(nameBase .. "Drop") or CreateFrame("Frame", nameBase .. "Drop", f, "UIDropDownMenuTemplate")
row.dropdown:ClearAllPoints()
row.dropdown:SetPoint("TOPLEFT", container, "TOPLEFT", xBase + MTH_AB_LAYOUT.ROW_DROPDOWN_X, yOffset + 3)
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
@@ -640,7 +643,8 @@ local function MTH_AB_CreateRow(container, subtype, index, xBase, yOffset)
end)
end
row.qty = CreateFrame("EditBox", nameBase .. "Qty", container, "InputBoxTemplate")
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)
@@ -652,7 +656,8 @@ local function MTH_AB_CreateRow(container, subtype, index, xBase, yOffset)
row.qty:SetNumeric(true)
row.qty:SetAutoFocus(false)
row.suffix = container:CreateFontString(nameBase .. "Suffix", "ARTWORK", "GameFontNormalSmall")
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")
@@ -687,32 +692,18 @@ local function MTH_AB_BuildUI(container)
return
end
MTH_ClearContainer(container)
local panel = MTH_Layout.Panel(container)
MTH_AB_STATE.container = container
MTH_AB_STATE.built = true
local controls = MTH_AB_STATE.controls
controls.title = container:CreateFontString("MetaHuntOptionsAutoBuyTitle", "ARTWORK", "GameFontHighlight")
if controls.title then
if controls.title.SetPoint then controls.title:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -10) end
if controls.title.SetText then controls.title:SetText("Auto Buy") end
end
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.body = container:CreateFontString("MetaHuntOptionsAutoBuyBody", "ARTWORK", "GameFontNormalSmall")
if controls.body then
if controls.body.SetPoint then controls.body:SetPoint("TOPLEFT", container, "TOPLEFT", 176, -30) end
if controls.body.SetWidth then controls.body:SetWidth(400) end
if controls.body.SetJustifyH then controls.body:SetJustifyH("LEFT") end
if controls.body.SetTextColor then controls.body:SetTextColor(1, 1, 1) end
if controls.body.SetText then
controls.body:SetText("Configure automatic buying rules that triggers when you open a vendor.\nThe quantity refers to how many STACKS of the item you want to have in your bags after your purchase")
end
end
controls.moduleEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyModuleEnabled", "Enable Auto Buy module", -30)
if controls.moduleEnabled then
controls.moduleEnabled:SetScript("OnClick", function()
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))
@@ -721,70 +712,44 @@ local function MTH_AB_BuildUI(container)
end
end
MTH_AB_RefreshOptionsUI()
end)
end
end,
})
controls.projectilesEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyProjectilesEnabled", "Enable for Projectiles", -74)
if controls.projectilesEnabled then
controls.projectilesEnabled:SetScript("OnClick", function()
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)
end
controls.sectionArrowTitle = container:CreateFontString("MetaHuntOptionsAutoBuyArrowsTitle", "ARTWORK", "GameFontHighlight")
if controls.sectionArrowTitle then
if controls.sectionArrowTitle.SetPoint then
controls.sectionArrowTitle:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_AB_LAYOUT.LEFT_SECTION_X, MTH_AB_LAYOUT.SECTION_TITLE_Y)
end
if controls.sectionArrowTitle.SetText then controls.sectionArrowTitle:SetText("Arrows") end
end
controls.sectionBulletTitle = container:CreateFontString("MetaHuntOptionsAutoBuyBulletsTitle", "ARTWORK", "GameFontHighlight")
if controls.sectionBulletTitle then
if controls.sectionBulletTitle.SetPoint then
controls.sectionBulletTitle:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_AB_LAYOUT.RIGHT_SECTION_X, MTH_AB_LAYOUT.SECTION_TITLE_Y)
end
if controls.sectionBulletTitle.SetText then controls.sectionBulletTitle:SetText("Bullets") end
end
end,
})
-- ===== LEFT: Arrows / RIGHT: Bullets (3 rules each) =====
local arrowBox = panel:Box("left", "MetaHuntOptionsAutoBuyArrowsBox", "Arrows")
for i = 1, 3 do
local rowY = MTH_AB_LAYOUT.SECTION_ROWS_Y0 - ((i - 1) * MTH_AB_LAYOUT.ROW_STEP)
controls.rows.arrow[i] = MTH_AB_CreateRow(container, "arrow", i, MTH_AB_LAYOUT.LEFT_SECTION_X, rowY)
controls.rows.bullet[i] = MTH_AB_CreateRow(container, "bullet", i, MTH_AB_LAYOUT.RIGHT_SECTION_X, rowY)
controls.rows.arrow[i] = MTH_AB_CreateRow(arrowBox, "arrow", i)
end
controls.petFoodTitle = container:CreateFontString("MetaHuntOptionsAutoBuyPetFoodTitle", "ARTWORK", "GameFontHighlight")
if controls.petFoodTitle then
controls.petFoodTitle:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_AB_LAYOUT.LEFT_SECTION_X, -300)
controls.petFoodTitle:SetText("Pet Food")
local bulletBox = panel:Box("right", "MetaHuntOptionsAutoBuyBulletsBox", "Bullets")
for i = 1, 3 do
controls.rows.bullet[i] = MTH_AB_CreateRow(bulletBox, "bullet", i)
end
controls.petFoodEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyPetFoodEnabled", "Enable for Pet Food", -322, MTH_AB_LAYOUT.LEFT_SECTION_X)
if controls.petFoodEnabled then
controls.petFoodEnabled:SetScript("OnClick", function()
-- ===== 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)
end
end,
})
controls.petFoodQtyLabel = container:CreateFontString("MetaHuntOptionsAutoBuyPetFoodQtyLabel", "ARTWORK", "GameFontNormalSmall")
if controls.petFoodQtyLabel then
controls.petFoodQtyLabel:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_AB_LAYOUT.LEFT_SECTION_X + 28, -350)
controls.petFoodQtyLabel:SetText("Quantity :")
end
controls.petFoodQty = CreateFrame("EditBox", "MetaHuntOptionsAutoBuyPetFoodQty", container, "InputBoxTemplate")
controls.petFoodQty = petBox:EditRow("MetaHuntOptionsAutoBuyPetFoodQtyLabel", "Quantity:",
"MetaHuntOptionsAutoBuyPetFoodQty", 40, { numeric = true, height = 20 })
if controls.petFoodQty then
controls.petFoodQty:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_AB_LAYOUT.LEFT_SECTION_X + 95, -347)
controls.petFoodQty:SetWidth(40)
controls.petFoodQty:SetHeight(20)
controls.petFoodQty:SetNumeric(true)
controls.petFoodQty:SetAutoFocus(false)
controls.petFoodQty:SetScript("OnEnterPressed", function()
if not this then return end
local store = MTH_AB_EnsureConfig()
@@ -798,43 +763,52 @@ local function MTH_AB_BuildUI(container)
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.petFoodQtySuffix = container:CreateFontString("MetaHuntOptionsAutoBuyPetFoodQtySuffix", "ARTWORK", "GameFontNormalSmall")
if controls.petFoodQtySuffix then
controls.petFoodQtySuffix:SetPoint("LEFT", controls.petFoodQty, "RIGHT", 8, 0)
controls.petFoodQtySuffix:SetText("stacks")
end
controls.petFoodScopeCurrent = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyPetFoodScopeCurrent", "Buy only for my current pet", -376, MTH_AB_LAYOUT.LEFT_SECTION_X + 28)
if controls.petFoodScopeCurrent then
controls.petFoodScopeCurrent:SetScript("OnClick", function()
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)
end
end,
})
controls.petFoodScopeAll = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyPetFoodScopeAll", "Buy for all my pets", -402, MTH_AB_LAYOUT.LEFT_SECTION_X + 28)
if controls.petFoodScopeAll then
controls.petFoodScopeAll:SetScript("OnClick", function()
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)
end
end,
})
controls.petFoodPetLines = {}
for i = 1, 5 do
local rowY = -434 - ((i - 1) * 22)
local icon = container:CreateTexture("MetaHuntOptionsAutoBuyPetFoodPetIcon" .. tostring(i), "ARTWORK")
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:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_AB_LAYOUT.LEFT_SECTION_X + 28, rowY)
icon:ClearAllPoints()
icon:SetPoint("TOPLEFT", f, "TOPLEFT", padX + 4, y)
icon:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark")
local text = container:CreateFontString("MetaHuntOptionsAutoBuyPetFoodPetText" .. tostring(i), "ARTWORK", "GameFontNormalSmall")
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)
@@ -842,6 +816,7 @@ local function MTH_AB_BuildUI(container)
controls.petFoodPetLines[i] = { icon = icon, text = text }
end
panel:Finish()
end
function MTH_SetupAutoBuyOptions()
+68 -152
View File
@@ -48,19 +48,10 @@ function MTH_SetupAutoQuestOptions()
local container = MTH_GetFrame("MetaHuntOptionsAutoQuest")
if not container then return end
MTH_ClearContainer(container)
local title = container:CreateFontString("MetaHuntOptionsAutoQuestTitle", "ARTWORK", "GameFontHighlight")
title:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -10)
title:SetText("Auto Quest")
local body = container:CreateFontString("MetaHuntOptionsAutoQuestBody", "ARTWORK", "GameFontNormalSmall")
body:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -30)
body:SetWidth(560)
body:SetJustifyH("LEFT")
body:SetJustifyV("TOP")
body:SetTextColor(0.45, 0.75, 1)
body:SetText("Automation for specific quest interactions.")
local store = MTH_AQ_EnsureStore()
if store.scorpokTooltip == nil then
store.scorpokTooltip = false
end
local moduleEnabled = true
if MTH and MTH.GetModule then
@@ -73,10 +64,14 @@ function MTH_SetupAutoQuestOptions()
elseif MTH and MTH.IsModuleEnabled then
moduleEnabled = MTH:IsModuleEnabled("autoquest", false) and true or false
end
local moduleToggle = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoQuestModuleToggle", "Enable Auto Quest module", -70, 20)
if moduleToggle then
moduleToggle:SetChecked(moduleEnabled and true or false)
moduleToggle:SetScript("OnClick", function()
local panel = MTH_Layout.Panel(container)
panel:Title("Auto Quest")
panel:Note("Automation for specific quest interactions.")
panel:TopCheckbox("MetaHuntOptionsAutoQuestModuleToggle", "Enable Auto Quest module", {
checked = moduleEnabled,
onClick = function()
if not this then return end
local enabled = MTH_AQ_IsChecked(this)
if MTH and MTH.SetModuleEnabled then
@@ -88,145 +83,66 @@ function MTH_SetupAutoQuestOptions()
local module = MTH and MTH.GetModule and MTH:GetModule("autoquest") or nil
local actual = (type(module) == "table" and module.enabled ~= nil) and (module.enabled and true or false) or enabled
this:SetChecked(actual and true or false)
end)
end
end,
})
local store = MTH_AQ_EnsureStore()
if store.scorpokTooltip == nil then
store.scorpokTooltip = false
end
local sectionWidth = (container:GetWidth() or 600) - 40
if sectionWidth < 360 then
sectionWidth = 360
end
local function ensureSection(name, sectionTitle, yOffset, height)
local section = getglobal(name)
if not section then
section = CreateFrame("Frame", name, container, "OptionFrameBoxTemplate")
end
if not section then
return nil
end
section:SetParent(container)
section:ClearAllPoints()
section:SetPoint("TOPLEFT", container, "TOPLEFT", 20, yOffset)
section:SetWidth(sectionWidth)
section:SetHeight(height)
section:Show()
local titleFrame = getglobal(name .. "Title")
if titleFrame then
titleFrame:SetText(sectionTitle)
end
return section
end
local function ensureCheckbox(section, name, label, yOffset, checked)
local check = getglobal(name)
if not check then
check = CreateFrame("CheckButton", name, section, "OptionsCheckButtonTemplate")
end
if not check then
return nil
end
check:SetParent(section)
check:ClearAllPoints()
check:SetPoint("TOPLEFT", section, "TOPLEFT", 12, yOffset)
check:SetChecked(checked and true or false)
check:Show()
local text = getglobal(name .. "Text")
if text then
text:SetText(label)
end
return check
end
local scorpokSection = ensureSection("MetaHuntAutoQuestScorpokBox", "Salt of the Scorpok", -130, 112)
if scorpokSection then
local scorpokToggle = ensureCheckbox(
scorpokSection,
"MetaHuntOptionsAutoQuestScorpokToggle",
"Enable SHIFT-rightclick for Bloodmage Drazial",
-10,
store.scorpokDrazial and true or false
)
if scorpokToggle then
scorpokToggle:SetScript("OnClick", function()
local enabled = MTH_AQ_IsChecked(this)
store.scorpokDrazial = enabled and true or false
if MTH and MTH.GetModuleCharSavedVariables then
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
if type(moduleStore) == "table" then
moduleStore.scorpokDrazial = store.scorpokDrazial and true or false
end
-- Salt of the Scorpok (left column)
local scorpok = panel:Box("left", "MetaHuntAutoQuestScorpokBox", "Salt of the Scorpok")
scorpok:Checkbox("MetaHuntOptionsAutoQuestScorpokToggle",
"Enable SHIFT-rightclick for Bloodmage Drazial", {
checked = store.scorpokDrazial and true or false,
onClick = function()
local enabled = MTH_AQ_IsChecked(this)
store.scorpokDrazial = enabled and true or false
if MTH and MTH.GetModuleCharSavedVariables then
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
if type(moduleStore) == "table" then
moduleStore.scorpokDrazial = store.scorpokDrazial and true or false
end
local module = MTH and MTH.GetModule and MTH:GetModule("autoquest")
if module and module.SetScorpokDrazialEnabled then
module:SetScorpokDrazialEnabled(enabled)
end
local module = MTH and MTH.GetModule and MTH:GetModule("autoquest")
if module and module.SetScorpokDrazialEnabled then
module:SetScorpokDrazialEnabled(enabled)
end
end,
})
scorpok:Checkbox("MetaHuntOptionsAutoQuestScorpokTooltipToggle",
"Enhance Tooltip on Drazial and related beasts (requires Tooltips module enabled)", {
checked = store.scorpokTooltip and true or false,
onClick = function()
local enabled = MTH_AQ_IsChecked(this)
store.scorpokTooltip = enabled and true or false
if MTH and MTH.GetModuleCharSavedVariables then
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
if type(moduleStore) == "table" then
moduleStore.scorpokTooltip = store.scorpokTooltip and true or false
end
end)
end
end
end,
})
local tooltipToggle = ensureCheckbox(
scorpokSection,
"MetaHuntOptionsAutoQuestScorpokTooltipToggle",
"Enhance Tooltip on Drazial and related beasts (requires Tooltips module enabled)",
-42,
store.scorpokTooltip and true or false
)
if tooltipToggle then
tooltipToggle:SetScript("OnClick", function()
local enabled = MTH_AQ_IsChecked(this)
store.scorpokTooltip = enabled and true or false
if MTH and MTH.GetModuleCharSavedVariables then
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
if type(moduleStore) == "table" then
moduleStore.scorpokTooltip = store.scorpokTooltip and true or false
end
-- Arrows Are For Sissies (right column)
local sissies = panel:Box("right", "MetaHuntAutoQuestSissiesBox", "Arrows Are For Sissies")
sissies:Note("MetaHuntOptionsAutoQuestSissiesNote",
"Note that you should not activate this if you are using LazyPig", { lines = 2 })
sissies:Checkbox("MetaHuntOptionsAutoQuestSissiesToggle",
"Enable SHIFT-rightclick for Artilleryman Sheldonore", {
checked = store.arrowsForSissies and true or false,
onClick = function()
local enabled = MTH_AQ_IsChecked(this)
store.arrowsForSissies = enabled and true or false
if MTH and MTH.GetModuleCharSavedVariables then
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
if type(moduleStore) == "table" then
moduleStore.arrowsForSissies = store.arrowsForSissies and true or false
end
end)
end
end
end
local module = MTH and MTH.GetModule and MTH:GetModule("autoquest")
if module and module.SetArrowsForSissiesEnabled then
module:SetArrowsForSissiesEnabled(enabled)
end
end,
})
local sissiesSection = ensureSection("MetaHuntAutoQuestSissiesBox", "Arrows Are For Sissies", -255, 108)
if sissiesSection then
local sissiesNote = getglobal("MetaHuntOptionsAutoQuestSissiesNote")
if not sissiesNote then
sissiesNote = sissiesSection:CreateFontString("MetaHuntOptionsAutoQuestSissiesNote", "ARTWORK", "GameFontNormalSmall")
end
sissiesNote:ClearAllPoints()
sissiesNote:SetPoint("TOPLEFT", sissiesSection, "TOPLEFT", 14, -10)
sissiesNote:SetWidth(sectionWidth - 28)
sissiesNote:SetJustifyH("LEFT")
sissiesNote:SetTextColor(0.45, 0.75, 1)
sissiesNote:SetText("Note that you should not activate this if you are using LazyPig")
sissiesNote:Show()
local sissiesToggle = ensureCheckbox(
sissiesSection,
"MetaHuntOptionsAutoQuestSissiesToggle",
"Enable SHIFT-rightclick for Artilleryman Sheldonore",
-40,
store.arrowsForSissies and true or false
)
if sissiesToggle then
sissiesToggle:SetScript("OnClick", function()
local enabled = MTH_AQ_IsChecked(this)
store.arrowsForSissies = enabled and true or false
if MTH and MTH.GetModuleCharSavedVariables then
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
if type(moduleStore) == "table" then
moduleStore.arrowsForSissies = store.arrowsForSissies and true or false
end
end
local module = MTH and MTH.GetModule and MTH:GetModule("autoquest")
if module and module.SetArrowsForSissiesEnabled then
module:SetArrowsForSissiesEnabled(enabled)
end
end)
end
end
panel:Finish()
end
+137 -176
View File
@@ -358,25 +358,14 @@ local function MTH_CHRON_NormalizeSection(tabKey)
return "general"
end
local function MTH_CHRON_RenderTimerSection(container, profile, title, items, bucket, opts)
opts = opts or {}
local timerX = opts.x or 20
local timerY = opts.y or -84
local prefix = tostring(opts.prefix or "Main")
MTH_CHRON_MakeTitle(container, "MetaHuntOptionsChronometerTimersHeader" .. prefix, title, timerX, timerY)
timerY = timerY - 24
local function MTH_CHRON_RenderTimerBox(box, profile, items, bucket, prefix)
prefix = tostring(prefix or "Main")
if table.getn(items) == 0 then
MTH_CHRON_MakeSmall(container, "MetaHuntOptionsChronometerSectionEmpty" .. prefix, "(none)", timerX + 8, timerY)
box:Text("MetaHuntOptionsChronometerSectionEmpty" .. prefix, "(none)")
return
end
for i = 1, table.getn(items) do
if timerY < -560 then
MTH_CHRON_MakeSmall(container, "MetaHuntOptionsChronometerOverflow" .. prefix, "...more", timerX + 8, timerY)
break
end
local row = items[i]
local timerName = row
local label = row
@@ -387,11 +376,9 @@ local function MTH_CHRON_RenderTimerSection(container, profile, title, items, bu
timerName = tostring(timerName or "")
label = tostring(label or timerName)
local controlName = "MetaHuntOptionsChronometerTimer" .. prefix .. tostring(bucket) .. tostring(i)
local check = MTH_CreateCheckbox(container, controlName, label, timerY, timerX)
if check then
check:SetChecked(profile.disabledSpells[bucket][timerName] == nil and true or false)
check:SetScript("OnClick", function()
if not this then return end
box:Checkbox(controlName, label, {
checked = profile.disabledSpells[bucket][timerName] == nil,
onClick = function()
local currentlyDisabled = profile.disabledSpells[bucket][timerName] ~= nil
if currentlyDisabled then
profile.disabledSpells[bucket][timerName] = nil
@@ -402,9 +389,8 @@ local function MTH_CHRON_RenderTimerSection(container, profile, title, items, bu
end
MTH_CHRON_ApplyLiveProfile(profile)
end)
end
timerY = timerY - 20
end,
})
end
end
@@ -461,210 +447,185 @@ function MTH_SetupChronometerOptions(tabKey)
local container = MTH_GetFrame("MetaHuntOptionsChronometer")
if not container then return end
MTH_ClearContainer(container)
MTH_CHRON_STATE.controls = {}
local profile = MTH_CHRON_GetProfile()
local _, class = UnitClass("player")
class = class or "HUNTER"
MTH_CHRON_MakeTitle(container, "MetaHuntOptionsChronometerTitle", "Chronometer", 20, -10)
local panel = MTH_Layout.Panel(container)
panel:Title("Chronometer")
local moduleCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerEnabled", "Enable Chronometer module", -54)
if moduleCheck then
local moduleEnabled = false
do
local module = MTH and MTH:GetModule("chronometer")
moduleCheck:SetChecked(module and module.enabled and true or false)
moduleCheck:SetScript("OnClick", function()
if not this then return end
local enabled = MTH_CHRON_IsChecked(this)
moduleEnabled = module and module.enabled and true or false
end
panel:TopCheckbox("MetaHuntOptionsChronometerEnabled", "Enable Chronometer module", {
checked = moduleEnabled,
onClick = function()
local enabled = this:GetChecked() == 1
if MTH and MTH.SetModuleEnabled then
MTH:SetModuleEnabled("chronometer", enabled)
end
end)
end
end,
})
if section == "general" then
MTH_CHRON_MakeTitle(container, "MetaHuntOptionsChronometerGeneralHeader", "General", 20, -84)
local ghostSlider = MTH_CreateSlider(container, "MetaHuntOptionsChronometerGhost", "Ghost Duration", 0, 30, 1, -112)
if ghostSlider then
ghostSlider:SetValue(tonumber(profile.ghost) or 0)
ghostSlider.onChange = function(value)
local genBox = panel:Box("left", "MetaHuntOptionsChronometerGeneralBox", "General")
genBox:Slider("MetaHuntOptionsChronometerGhost", {
label = "Ghost Duration", min = 0, max = 30, step = 1,
value = tonumber(profile.ghost) or 0,
onChange = function(value)
profile.ghost = tonumber(value) or 0
MTH_CHRON_ApplyLiveProfile(profile)
end
end
local killCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerFadeOnKill", "Fade on kill", -154)
if killCheck then
killCheck:SetChecked(profile.fadeonkill and true or false)
killCheck:SetScript("OnClick", function()
if not this then return end
profile.fadeonkill = MTH_CHRON_IsChecked(this)
end)
end
local fadeCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerFadeOnFade", "Fade on aura fade", -179)
if fadeCheck then
fadeCheck:SetChecked(profile.fadeonfade and true or false)
fadeCheck:SetScript("OnClick", function()
if not this then return end
profile.fadeonfade = MTH_CHRON_IsChecked(this)
end)
end
local selfCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerSelfBars", "Show self bars", -204)
if selfCheck then
selfCheck:SetChecked(profile.selfbars and true or false)
selfCheck:SetScript("OnClick", function()
if not this then return end
profile.selfbars = MTH_CHRON_IsChecked(this)
end)
end
local onlySelfCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerOnlySelf", "Only self target", -229)
if onlySelfCheck then
onlySelfCheck:SetChecked(profile.onlyself and true or false)
onlySelfCheck:SetScript("OnClick", function()
if not this then return end
profile.onlyself = MTH_CHRON_IsChecked(this)
end)
end
end,
})
genBox:Checkbox("MetaHuntOptionsChronometerFadeOnKill", "Fade on kill", {
checked = profile.fadeonkill and true or false,
onClick = function() profile.fadeonkill = this:GetChecked() == 1 end,
})
genBox:Checkbox("MetaHuntOptionsChronometerFadeOnFade", "Fade on aura fade", {
checked = profile.fadeonfade and true or false,
onClick = function() profile.fadeonfade = this:GetChecked() == 1 end,
})
genBox:Checkbox("MetaHuntOptionsChronometerSelfBars", "Show self bars", {
checked = profile.selfbars and true or false,
onClick = function() profile.selfbars = this:GetChecked() == 1 end,
})
genBox:Checkbox("MetaHuntOptionsChronometerOnlySelf", "Only self target", {
checked = profile.onlyself and true or false,
onClick = function() profile.onlyself = this:GetChecked() == 1 end,
})
elseif section == "bar" then
MTH_CHRON_MakeTitle(container, "MetaHuntOptionsChronometerBarHeader", "Bars", 20, -84)
local runTestButton = MTH_CreateActionButton(container, "MetaHuntOptionsChronometerRunTest", "Run Test", 20, -112, 130, 22, function()
local engine = MTH_ChronometerHunter
if engine and engine.RunTest then
engine:RunTest()
end
end)
local anchorButton = MTH_CreateActionButton(container, "MetaHuntOptionsChronometerAnchor", "Toggle Anchor", 165, -112, 130, 22, function()
local engine = MTH_ChronometerHunter
if engine and engine.ToggleAnchor then
engine:ToggleAnchor()
end
end)
if runTestButton then runTestButton:Show() end
if anchorButton then anchorButton:Show() end
local ctrlBox = panel:Box("left", "MetaHuntOptionsChronometerControlsBox", "Controls")
ctrlBox:Buttons({
{ name = "MetaHuntOptionsChronometerRunTest", label = "Run Test", width = 120,
onClick = function()
local engine = MTH_ChronometerHunter
if engine and engine.RunTest then engine:RunTest() end
end },
{ name = "MetaHuntOptionsChronometerAnchor", label = "Toggle Anchor", width = 120,
onClick = function()
local engine = MTH_ChronometerHunter
if engine and engine.ToggleAnchor then engine:ToggleAnchor() end
end },
})
local anchorX = tonumber(profile.barposition and profile.barposition.x) or 0
local anchorY = tonumber(profile.barposition and profile.barposition.y) or 0
MTH_CHRON_MakeSmall(container, "MetaHuntOptionsChronometerAnchorPos", "Anchor: X " .. tostring(anchorX) .. " Y " .. tostring(anchorY), 20, -142)
ctrlBox:Note("MetaHuntOptionsChronometerAnchorPos",
"Anchor: X " .. tostring(anchorX) .. " Y " .. tostring(anchorY))
local widthSlider = MTH_CreateSlider(container, "MetaHuntOptionsChronometerBarWidth", "Bar Width", 80, 320, 1, -180)
if widthSlider then
widthSlider:SetValue(tonumber(profile.barwidth) or 220)
widthSlider.onChange = function(value)
local dimBox = panel:Box("left", "MetaHuntOptionsChronometerDimBox", "Dimensions")
dimBox:Slider("MetaHuntOptionsChronometerBarWidth", {
label = "Bar Width", min = 80, max = 320, step = 1,
value = tonumber(profile.barwidth) or 220,
onChange = function(value)
profile.barwidth = tonumber(value) or 220
MTH_CHRON_ApplyLiveProfile(profile)
end
end
local scaleSlider = MTH_CreateSlider(container, "MetaHuntOptionsChronometerBarScale", "Bar Scale", 0.5, 1.5, 0.1, -222)
if scaleSlider then
scaleSlider:SetValue(tonumber(profile.barscale) or 1)
scaleSlider.onChange = function(value)
end,
})
dimBox:Slider("MetaHuntOptionsChronometerBarScale", {
label = "Bar Scale", min = 0.5, max = 1.5, step = 0.1,
value = tonumber(profile.barscale) or 1,
format = function(v) return string.format("%.1f", v) end,
onChange = function(value)
profile.barscale = tonumber(value) or 1
MTH_CHRON_ApplyLiveProfile(profile)
end
end
local heightSlider = MTH_CreateSlider(container, "MetaHuntOptionsChronometerBarHeight", "Bar Height", 8, 30, 1, -264)
if heightSlider then
heightSlider:SetValue(tonumber(profile.barheight) or 16)
heightSlider.onChange = function(value)
end,
})
dimBox:Slider("MetaHuntOptionsChronometerBarHeight", {
label = "Bar Height", min = 8, max = 30, step = 1,
value = tonumber(profile.barheight) or 16,
onChange = function(value)
profile.barheight = tonumber(value) or 16
MTH_CHRON_ApplyLiveProfile(profile)
end
end
local spacingSlider = MTH_CreateSlider(container, "MetaHuntOptionsChronometerBarSpacing", "Bar Spacing", 0, 15, 1, -306)
if spacingSlider then
spacingSlider:SetValue(tonumber(profile.spacing) or 0)
spacingSlider.onChange = function(value)
end,
})
dimBox:Slider("MetaHuntOptionsChronometerBarSpacing", {
label = "Bar Spacing", min = 0, max = 15, step = 1,
value = tonumber(profile.spacing) or 0,
onChange = function(value)
profile.spacing = tonumber(value) or 0
MTH_CHRON_ApplyLiveProfile(profile)
end
end
local textSizeSlider = MTH_CreateSlider(container, "MetaHuntOptionsChronometerTextSize", "Text Size", 8, 20, 1, -348)
if textSizeSlider then
textSizeSlider:SetValue(tonumber(profile.textsize) or 10)
textSizeSlider.onChange = function(value)
end,
})
dimBox:Slider("MetaHuntOptionsChronometerTextSize", {
label = "Text Size", min = 8, max = 20, step = 1,
value = tonumber(profile.textsize) or 10,
onChange = function(value)
profile.textsize = tonumber(value) or 10
MTH_CHRON_ApplyLiveProfile(profile)
end
end
end,
})
MTH_CHRON_MakeSmall(container, "MetaHuntOptionsChronometerTextPatternLabel", "Bar Text ($s spell, $t target)", 20, -390)
MTH_CHRON_MakeInput(container, "MetaHuntOptionsChronometerTextPattern", 20, -408, 220, 20, profile.text or "$t", function(newText)
if not newText or newText == "" then
newText = "$t"
end
profile.text = tostring(newText)
MTH_CHRON_ApplyLiveProfile(profile)
end)
local growCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerGrowUp", "Grow bars upward", -438)
if growCheck then
growCheck:SetChecked(profile.growup and true or false)
growCheck:SetScript("OnClick", function()
if not this then return end
profile.growup = MTH_CHRON_IsChecked(this)
local textBox = panel:Box("right", "MetaHuntOptionsChronometerTextBox", "Text & Growth")
textBox:Note("MetaHuntOptionsChronometerTextPatternHint",
"Bar text tokens: $s = spell, $t = target", { lines = 2 })
local patternEdit = textBox:EditRow("MetaHuntOptionsChronometerTextPatternLabel", "Bar Text",
"MetaHuntOptionsChronometerTextPattern", 150, { height = 20 })
if patternEdit then
patternEdit:SetText(tostring(profile.text or "$t"))
patternEdit:SetScript("OnEnterPressed", function()
local newText = this:GetText() or ""
if newText == "" then newText = "$t" end
profile.text = tostring(newText)
MTH_CHRON_ApplyLiveProfile(profile)
this:ClearFocus()
end)
end
local reverseCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerReverse", "Reverse bars", -463)
if reverseCheck then
reverseCheck:SetChecked(profile.reverse and true or false)
reverseCheck:SetScript("OnClick", function()
if not this then return end
profile.reverse = MTH_CHRON_IsChecked(this)
textBox:Checkbox("MetaHuntOptionsChronometerGrowUp", "Grow bars upward", {
checked = profile.growup and true or false,
onClick = function()
profile.growup = this:GetChecked() == 1
MTH_CHRON_ApplyLiveProfile(profile)
end)
end
end,
})
textBox:Checkbox("MetaHuntOptionsChronometerReverse", "Reverse bars", {
checked = profile.reverse and true or false,
onClick = function()
profile.reverse = this:GetChecked() == 1
MTH_CHRON_ApplyLiveProfile(profile)
end,
})
MTH_CHRON_MakeSmall(container, "MetaHuntOptionsChronometerIconPosLabel", "Icon Position", 20, -494)
local iconLeft = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerIconLeft", "Left", -514)
local iconRight = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerIconRight", "Right", -538)
if iconLeft and iconRight then
iconLeft:SetChecked(profile.iconposition ~= "RIGHT")
iconRight:SetChecked(profile.iconposition == "RIGHT")
iconLeft:SetScript("OnClick", function()
local iconBox = panel:Box("right", "MetaHuntOptionsChronometerIconBox", "Icon Position")
local iconLeft, iconRight
iconLeft = iconBox:Checkbox("MetaHuntOptionsChronometerIconLeft", "Left", {
checked = profile.iconposition ~= "RIGHT",
onClick = function()
profile.iconposition = "LEFT"
iconLeft:SetChecked(true)
iconRight:SetChecked(nil)
MTH_CHRON_ApplyLiveProfile(profile)
end)
iconRight:SetScript("OnClick", function()
end,
})
iconRight = iconBox:Checkbox("MetaHuntOptionsChronometerIconRight", "Right", {
checked = profile.iconposition == "RIGHT",
onClick = function()
profile.iconposition = "RIGHT"
iconRight:SetChecked(true)
iconLeft:SetChecked(nil)
MTH_CHRON_ApplyLiveProfile(profile)
end)
end
end,
})
else
local classSpells, classEvents, racial = MTH_CHRON_BuildTimerLists()
if section == "classspells" then
MTH_CHRON_RenderTimerSection(container, profile, "Hunter Spells", classSpells, class, {
x = 20,
y = -84,
prefix = "ClassSpells",
})
MTH_CHRON_RenderTimerSection(container, profile, "Hunter Trinkets", MTH_CHRON_BuildHunterTrinketItems(classEvents), class, {
x = 300,
y = -84,
prefix = "ClassTrinkets",
})
local spellsBox = panel:Box("left", "MetaHuntOptionsChronometerSpellsBox", "Hunter Spells")
MTH_CHRON_RenderTimerBox(spellsBox, profile, classSpells, class, "ClassSpells")
local trinketBox = panel:Box("right", "MetaHuntOptionsChronometerTrinketsBox", "Hunter Trinkets")
MTH_CHRON_RenderTimerBox(trinketBox, profile, MTH_CHRON_BuildHunterTrinketItems(classEvents), class, "ClassTrinkets")
elseif section == "classevents" then
MTH_CHRON_RenderTimerSection(container, profile, "Hunter Events", classEvents, class, { prefix = "ClassEvents" })
local eventsBox = panel:Box("left", "MetaHuntOptionsChronometerEventsBox", "Hunter Events")
MTH_CHRON_RenderTimerBox(eventsBox, profile, classEvents, class, "ClassEvents")
elseif section == "racial" then
MTH_CHRON_RenderTimerSection(container, profile, "Racial", racial, "RACIAL", { prefix = "Racial" })
local racialBox = panel:Box("left", "MetaHuntOptionsChronometerRacialBox", "Racial")
MTH_CHRON_RenderTimerBox(racialBox, profile, racial, "RACIAL", "Racial")
end
end
panel:Finish()
end
if _G then
+5 -9
View File
@@ -96,12 +96,8 @@ function MTH_SetupCreditsOptions()
local container = MTH_GetFrame("MetaHuntOptionsCredits")
if not container then return end
MTH_ClearContainer(container)
local title = container:CreateFontString("MetaHuntOptionsCreditsTitle", "ARTWORK", "GameFontNormal")
title:SetPoint("TOPLEFT", container, "TOPLEFT", 10, -10)
title:SetText(MTH_CR_L("CREDITS_TITLE", "Credits"))
title:SetTextColor(1.00, 0.82, 0.00)
local panel = MTH_Layout.Panel(container)
local title = panel:Title(MTH_CR_L("CREDITS_TITLE", "Credits"))
local scrollFrame = MTH_GetFrame("MetaHuntOptionsCreditsScroll")
if not scrollFrame then
@@ -124,12 +120,12 @@ function MTH_SetupCreditsOptions()
cursor = MTH_CreditsCreateText(content, cursor,
MTH_CR_L("CREDITS_ABOUT_CODE_INTRO",
"This addon is, in others, a compilation of old vanilla addons that I loved and played with during years. But most of them had become very buggy with TwoW as new contain was added to the server. \n I fixed, reworked, enhanced, and melted them within a modern modular framework that I created.\n"
.. "I want to make it crystal clear about what work is mine, and what is not and respectfully credit the original authors for the great stuff I've taken from them:"),
.. "I want to make it clear about what work is mine, and what is not and respectfully credit the original authors for the great stuff I've taken from them:"),
"GameFontNormalSmall", -10)
cursor = MTH_CreditsCreateText(content, cursor,
MTH_CR_L("CREDITS_ABOUT_ZHUNTER",
"- zBars, Antidaze and Autostrip were core functionalities of Vanilla zHunterMod addon. And I kept the \"z\" naming of bars/buttons to always remember it. On top of this I have created myself zBars, zAmmo, zCompanions, zMount, zToys, zCraft.\nAlso the SmartAmmo feature idea is coming from Zhuntermod: there was a file in it with that functionality, but was like a work-in-progress, totally unfunctional and even \"dangerous\" in its current state, and was not active in the addon. Since it was a fucking great idea, I recoded it mostly from scratch and made it work reliably and safely."),
"- zBars, Antidaze and Autostrip were core functionalities of Vanilla zHunterMod addon. And I kept the \"z\" naming of bars/buttons to always remember it. I improve it and added zBar, zAmmo, zCompanions, zMount, zToys, zCraft.\nAlso the SmartAmmo feature idea is coming from Zhuntermod: there was a file in it with that functionality, but was like a work-in-progress, totally unfunctional and even \"dangerous\" in its current state, and was not active in the addon. Since it was a fucking great idea, I recoded it mostly from scratch and made it work reliably and safely."),
"GameFontNormalSmall", -10)
cursor = MTH_CreditsCreateText(content, cursor,
@@ -189,7 +185,7 @@ function MTH_SetupCreditsOptions()
"GameFontNormalSmall", -10)
cursor = MTH_CreditsCreateText(content, cursor,
MTH_CR_L("CREDITS_CLOSING", "With that being said, go back hunting fellas! Preferably on Octowow."),
MTH_CR_L("CREDITS_CLOSING", ""),
"GameFontNormalSmall", -10, 1.00, 0.82, 0.00)
cursor = MTH_CreditsCreateText(content, cursor,
+138 -250
View File
@@ -15,16 +15,7 @@ local function MTH_EA_OPT_GetCfg()
return MTH_SavedVariables.modules["expammo"] or {}
end
local MTH_EA_OPT_built = false
local MTH_EA_OPT_STATE = { bindStatus = nil, bindButton = nil, captureFrame = nil }
-- ── Layout constants ──────────────────────────────────────────
-- Two equal columns separated by a gutter. Values are offsets from the
-- container TOPLEFT corner (positive X right, negative Y down).
local OPT_L = 20 -- left column X
local OPT_R = 300 -- right column X
local OPT_CW = 255 -- column width (used for text wrapping and sliders)
local function MTH_EA_OPT_GetBindText()
if not GetBindingKey then return "Unbound" end
local k1, k2 = GetBindingKey("EXPAMMO ACTION")
@@ -119,271 +110,168 @@ local function MTH_EA_OPT_StartCapture()
if bb then bb:SetText("Press key...") end
end
-- Helper: checkbox anchored to a given X column
local function MTH_EA_OPT_CB(container, name, label, yOff, xOff, isChecked, onClick)
local cb = MTH_CreateCheckbox(container, name, label, yOff, xOff or OPT_L)
if cb then
cb:SetChecked(isChecked and 1 or 0)
cb:SetScript("OnClick", function()
local v = this:GetChecked()
onClick(v == 1 or v == true)
end)
end
return cb
end
-- Helper: section header label
local function MTH_EA_OPT_Header(container, text, yOff, xOff)
local fs = container:CreateFontString(nil, "ARTWORK", "GameFontNormal")
fs:SetPoint("TOPLEFT", container, "TOPLEFT", xOff or OPT_L, yOff)
fs:SetText("|cffff9900" .. text .. "|r")
return fs
end
-- Helper: small descriptive text
local function MTH_EA_OPT_Tip(container, text, yOff, xOff, r, g, b)
local fs = container:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
fs:SetPoint("TOPLEFT", container, "TOPLEFT", xOff or OPT_L, yOff)
fs:SetWidth(OPT_CW)
fs:SetJustifyH("LEFT")
fs:SetTextColor(r or 0.6, g or 0.6, b or 0.6)
fs:SetText(text)
return fs
end
-- Enable or disable a list of widgets (supports Frames/Buttons and FontStrings)
local function MTH_EA_OPT_SetGroupEnabled(widgets, enabled)
for _, w in ipairs(widgets) do
if w then
if w.Enable and w.Disable then
-- Frame / Button / CheckButton
if enabled then w:Enable() else w:Disable() end
end
-- Dim all (including FontStrings and frames) via alpha
if w.SetAlpha then
w:SetAlpha(enabled and 1.0 or 0.35)
end
end
end
end
local function MTH_EA_OPT_BuildUI(container)
if MTH_EA_OPT_built then return end
MTH_EA_OPT_built = true
local cfg = MTH_EA_OPT_GetCfg()
local showHint = cfg.showHint ~= false
---------------------------------------------------------------------------
-- Title
---------------------------------------------------------------------------
local title = container:CreateFontString(nil, "ARTWORK", "GameFontHighlightLarge")
title:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_L, -16)
title:SetText("MM Widget — Experimental Ammunition Tracker")
local panel = MTH_Layout.Panel(container)
panel:Title("MM Widget — Experimental Ammunition Tracker")
---------------------------------------------------------------------------
-- LEFT COLUMN
---------------------------------------------------------------------------
-- ── Module ──────────────────────────────────────────────
MTH_EA_OPT_Header(container, "Module", -46)
-- Right-column gating: dim the box frames and disable their interactive
-- controls when the "Show action hint cell" checkbox is off.
local rightBoxes = {}
local rightControls = {}
local function setRightEnabled(enabled)
local i
for i = 1, table.getn(rightBoxes) do
local f = rightBoxes[i]
if f and f.SetAlpha then f:SetAlpha(enabled and 1.0 or 0.35) end
end
for i = 1, table.getn(rightControls) do
local c = rightControls[i]
if c and c.Enable and c.Disable then
if enabled then c:Enable() else c:Disable() end
end
end
end
-- ===== LEFT: Module =====
local moduleBox = panel:Box("left", "MTH_ExpAmmoModuleBox", "Module")
local moduleEnabled = true
if MTH and MTH.IsModuleEnabled then
moduleEnabled = MTH:IsModuleEnabled("expammo", true) and true or false
end
MTH_EA_OPT_CB(container, "MTH_ExpAmmoModuleCB",
"Enable MM Widget module",
-66, OPT_L, moduleEnabled,
function(v)
moduleBox:Checkbox("MTH_ExpAmmoModuleCB", "Enable MM Widget module", {
checked = moduleEnabled,
onClick = function()
local v = this:GetChecked() == 1
if MTH and MTH.SetModuleEnabled then MTH:SetModuleEnabled("expammo", v) end
if MTH_ExpAmmo then MTH_ExpAmmo.SetEnabled(v) end
end)
end,
})
-- ── Tracker Visibility ───────────────────────────────────
MTH_EA_OPT_Header(container, "Tracker Visibility", -100)
MTH_EA_OPT_CB(container, "MTH_ExpAmmoShowLnLCB",
"Show Lock and Load cell (top)",
-120, OPT_L, cfg.showLnL ~= false,
function(v) if MTH_ExpAmmo then MTH_ExpAmmo.SetShowLnL(v) end end)
-- "Show action hint cell" also gates the right column
local rightGroup = {} -- filled below; toggled when this CB changes
local showHintCB = MTH_EA_OPT_CB(container, "MTH_ExpAmmoShowHintCB",
"Show action hint cell (bottom)",
-144, OPT_L, showHint,
function(v)
-- ===== LEFT: Tracker Visibility =====
local visBox = panel:Box("left", "MTH_ExpAmmoVisBox", "Tracker Visibility")
visBox:Checkbox("MTH_ExpAmmoShowLnLCB", "Show Lock and Load cell (top)", {
checked = cfg.showLnL ~= false,
onClick = function() if MTH_ExpAmmo then MTH_ExpAmmo.SetShowLnL(this:GetChecked() == 1) end end,
})
visBox:Checkbox("MTH_ExpAmmoShowHintCB", "Show action hint cell (bottom)", {
checked = showHint,
onClick = function()
local v = this:GetChecked() == 1
if MTH_ExpAmmo then MTH_ExpAmmo.SetShowHint(v) end
MTH_EA_OPT_SetGroupEnabled(rightGroup, v)
end)
setRightEnabled(v)
end,
})
visBox:Checkbox("MTH_ExpAmmoHideOOCCB", "Hide widget when out of combat", {
checked = cfg.hideOOC == true,
onClick = function() if MTH_ExpAmmo then MTH_ExpAmmo.SetHideOOC(this:GetChecked() == 1) end end,
})
MTH_EA_OPT_CB(container, "MTH_ExpAmmoHideOOCCB",
"Hide widget when out of combat",
-168, OPT_L, cfg.hideOOC == true,
function(v) if MTH_ExpAmmo then MTH_ExpAmmo.SetHideOOC(v) end end)
-- ===== LEFT: Appearance =====
local appBox = panel:Box("left", "MTH_ExpAmmoAppBox", "Appearance")
appBox:Slider("MTH_ExpAmmoCellSizeSlider", {
label = "Cell Size (px)", min = 20, max = 80, step = 4,
value = math.max(20, math.min(80, cfg.cellSize or 40)),
onChange = function(val) if MTH_ExpAmmo then MTH_ExpAmmo.SetCellSize(val) end end,
})
appBox:Slider("MTH_ExpAmmoCellGapSlider", {
label = "Cell Spacing (px)", min = 0, max = 20, step = 1,
value = math.max(0, math.min(20, cfg.cellGap or 2)),
onChange = function(val) if MTH_ExpAmmo then MTH_ExpAmmo.SetCellGap(val) end end,
})
appBox:Checkbox("MTH_ExpAmmoBigCDCB", "Large cooldown numbers (centered in cell)", {
checked = cfg.bigCD == true,
onClick = function() if MTH_ExpAmmo then MTH_ExpAmmo.SetBigCD(this:GetChecked() == 1) end end,
})
-- ── Appearance ───────────────────────────────────────────
MTH_EA_OPT_Header(container, "Appearance", -202)
local sizeSlider = MTH_CreateSlider(container, "MTH_ExpAmmoCellSizeSlider",
"Cell Size (px)", 20, 80, 4, -222)
if sizeSlider then
sizeSlider:ClearAllPoints()
sizeSlider:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_L + 5, -222)
sizeSlider:SetWidth(OPT_CW - 10)
sizeSlider:SetValue(math.max(20, math.min(80, cfg.cellSize or 40)))
sizeSlider.onChange = function(val)
if MTH_ExpAmmo then MTH_ExpAmmo.SetCellSize(val) end
end
end
local gapSlider = MTH_CreateSlider(container, "MTH_ExpAmmoCellGapSlider",
"Cell Spacing (px)", 0, 20, 1, -286)
if gapSlider then
gapSlider:ClearAllPoints()
gapSlider:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_L + 5, -286)
gapSlider:SetWidth(OPT_CW - 10)
gapSlider:SetValue(math.max(0, math.min(20, cfg.cellGap or 2)))
gapSlider.onChange = function(val)
if MTH_ExpAmmo then MTH_ExpAmmo.SetCellGap(val) end
end
end
MTH_EA_OPT_CB(container, "MTH_ExpAmmoBigCDCB",
"Large cooldown numbers (centered in cell)",
-350, OPT_L, cfg.bigCD == true,
function(v) if MTH_ExpAmmo then MTH_ExpAmmo.SetBigCD(v) end end)
-- ── Position ─────────────────────────────────────────────
MTH_EA_OPT_Header(container, "Position", -390)
local anchorButton = MTH_CreateActionButton(container, "MTH_ExpAmmoToggleAnchor",
"Toggle Anchor", OPT_L, -410, 130, 22, function()
if MTH_ExpAmmo then MTH_ExpAmmo.ToggleAnchor() end
end)
if anchorButton then anchorButton:Show() end
MTH_EA_OPT_Tip(container,
-- ===== LEFT: Position =====
local posBox = panel:Box("left", "MTH_ExpAmmoPosBox", "Position")
posBox:Button("MTH_ExpAmmoToggleAnchor", "Toggle Anchor", {
width = 130,
onClick = function() if MTH_ExpAmmo then MTH_ExpAmmo.ToggleAnchor() end end,
})
posBox:Note("MTH_ExpAmmoPosNote",
"Shows 4 drag handles around the widget (top / bottom / left / right). Drag any one to reposition it.",
-436, OPT_L)
{ color = MTH_Layout.Theme.colText, lines = 3 })
---------------------------------------------------------------------------
-- RIGHT COLUMN — Action Hint Cell (keybind + casting)
-- All widgets here are greyed out when the bottom cell is hidden.
---------------------------------------------------------------------------
-- Vertical divider line
local divider = container:CreateTexture(nil, "BACKGROUND")
divider:SetTexture(0.3, 0.3, 0.3, 0.6)
divider:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_R - 10, -46)
divider:SetPoint("BOTTOMLEFT", container, "TOPLEFT", OPT_R - 10, -530)
divider:SetWidth(1)
-- Column title
local rTitle = container:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
rTitle:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_R, -46)
rTitle:SetText("|cffff9900" .. "Action Hint Cell" .. "|r")
table.insert(rightGroup, rTitle)
local rSubtitle = MTH_EA_OPT_Tip(container,
"Options below apply to the bottom cell only.\n Disable \"Show action hint cell\" to hide the cell and these controls.",
-64, OPT_R, 1.00, 1.00, 1.00)
if rSubtitle then rSubtitle:SetWidth(290) end
table.insert(rightGroup, rSubtitle)
local rNamPowerTip = MTH_EA_OPT_Tip(container,
-- ===== RIGHT: Smart Action Cell (helper + keybind + casting) =====
-- One feature = one box. The intro notes explain the bottom cell, and the
-- Keybind / Casting controls that drive it live underneath as sub-sections.
local cellBox = panel:Box("right", "MTH_ExpAmmoCellBox", "Smart Action Cell")
table.insert(rightBoxes, cellBox:Frame())
cellBox:Text("MTH_ExpAmmoHintSub",
"Options below apply to the bottom cell only. Disable \"Show action hint cell\" to hide the cell and these controls.",
{ color = { 1, 1, 1 }, lines = 3 })
cellBox:Note("MTH_ExpAmmoHintNam",
"Notes:\n - You need NAMPOWER for this to work reliably.\n - Aimed/Steady/Multi/Arcane Shots SHOULD BE on your action bars.",
-100, OPT_R, 0.35, 0.65, 1.00)
if rNamPowerTip then rNamPowerTip:SetWidth(290) end
table.insert(rightGroup, rNamPowerTip)
{ lines = 3 })
-- ── Keybind ──────────────────────────────────────────────
table.insert(rightGroup, MTH_EA_OPT_Header(container, "Keybind", -182, OPT_R))
-- Keybind sub-section
cellBox:Gap(4)
cellBox:Text("MTH_ExpAmmoKeyHead", "Keybind",
{ font = MTH_Layout.Theme.fontBoxTitle, color = MTH_Layout.Theme.colPanelTitle })
cellBox:Note("MTH_ExpAmmoBindTip",
"One key to rule them all.\n Aimed Shot when ready, Steady Shot while Aimed is on cooldown, consume-spell (Multi / Serpent / Arcane) when proc is up.",
{ lines = 4 })
MTH_EA_OPT_STATE.bindStatus = cellBox:Text("MTH_ExpAmmoBindStatus",
"Key: " .. MTH_EA_OPT_GetBindText())
local keyButtons = cellBox:Buttons({
{ name = "MTH_ExpAmmoBindButton", label = "Set Key", width = 90,
onClick = function()
if MTH_EA_OPT_STATE.captureFrame and MTH_EA_OPT_STATE.captureFrame:IsShown() then
MTH_EA_OPT_StopCapture()
else
MTH_EA_OPT_StartCapture()
end
end },
{ name = "MTH_ExpAmmoBindClear", label = "Clear", width = 70,
onClick = function() MTH_EA_OPT_SaveBinding(nil) end },
})
MTH_EA_OPT_STATE.bindButton = keyButtons[1]
table.insert(rightControls, keyButtons[1])
table.insert(rightControls, keyButtons[2])
local bindTip = MTH_EA_OPT_Tip(container,
"One key to rule them all.\n Aimed Shot when ready, Steady Shot while Aimed is on cooldown,\n consume-spell (Multi / Serpent / Arcane) when proc is up.",
-200, OPT_R, 0.65, 0.65, 0.65)
if bindTip then bindTip:SetWidth(290) end
table.insert(rightGroup, bindTip)
-- Casting sub-section
cellBox:Gap(4)
cellBox:Text("MTH_ExpAmmoCastHead", "Casting",
{ font = MTH_Layout.Theme.fontBoxTitle, color = MTH_Layout.Theme.colPanelTitle })
local quiverCB = cellBox:Checkbox("MTH_ExpAmmoQuiverNoClipCB", "Use Quiver no-clip casting", {
checked = cfg.useQuiverNoClip == true,
onClick = function() if MTH_ExpAmmo then MTH_ExpAmmo.SetUseQuiverNoClip(this:GetChecked() == 1) end end,
})
table.insert(rightControls, quiverCB)
cellBox:Note("MTH_ExpAmmoQuiverTip",
"Requires the Quiver addon. Routes Aimed/Steady/Multi cast through Quiver.CastNoClip to avoid clipping your auto-shot swing timer.",
{ lines = 3 })
local bindStatus = container:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
bindStatus:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_R, -248)
bindStatus:SetText("Key: " .. MTH_EA_OPT_GetBindText())
MTH_EA_OPT_STATE.bindStatus = bindStatus
table.insert(rightGroup, bindStatus)
-- ===== RIGHT: Rotation =====
local rotBox = panel:Box("right", "MTH_ExpAmmoRotBox", "Rotation")
table.insert(rightBoxes, rotBox:Frame())
rotBox:Note("MTH_ExpAmmoRotTip",
"Uncheck a shot to permanently skip it during its proc window. The keybind will cast Steady/Aimed instead.",
{ lines = 2 })
local multiCB = rotBox:Checkbox("MTH_ExpAmmoBlockMultiCB", "Multi-Shot (Explosive)", {
checked = cfg.blockExplosive ~= true,
onClick = function() if MTH_ExpAmmo then MTH_ExpAmmo.SetBlockExplosive(not (this:GetChecked() == 1)) end end,
})
table.insert(rightControls, multiCB)
local serpentCB = rotBox:Checkbox("MTH_ExpAmmoBlockSerpentCB", "Serpent Sting (Poisonous)", {
checked = cfg.blockPoisonous ~= true,
onClick = function() if MTH_ExpAmmo then MTH_ExpAmmo.SetBlockPoisonous(not (this:GetChecked() == 1)) end end,
})
table.insert(rightControls, serpentCB)
local arcaneCB = rotBox:Checkbox("MTH_ExpAmmoBlockArcaneCB", "Arcane Shot (Enchanted)", {
checked = cfg.blockEnchanted ~= true,
onClick = function() if MTH_ExpAmmo then MTH_ExpAmmo.SetBlockEnchanted(not (this:GetChecked() == 1)) end end,
})
table.insert(rightControls, arcaneCB)
local bindButton = CreateFrame("Button", "MTH_ExpAmmoBindButton", container, "UIPanelButtonTemplate")
bindButton:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_R, -264)
bindButton:SetWidth(90)
bindButton:SetHeight(22)
bindButton:SetText("Set Key")
bindButton:EnableKeyboard(false)
bindButton:SetScript("OnClick", function()
if MTH_EA_OPT_STATE.captureFrame and MTH_EA_OPT_STATE.captureFrame:IsShown() then
MTH_EA_OPT_StopCapture()
else
MTH_EA_OPT_StartCapture()
end
end)
MTH_EA_OPT_STATE.bindButton = bindButton
table.insert(rightGroup, bindButton)
panel:Finish()
local clearButton = CreateFrame("Button", "MTH_ExpAmmoBindClear", container, "UIPanelButtonTemplate")
clearButton:SetPoint("LEFT", bindButton, "RIGHT", 6, 0)
clearButton:SetWidth(70)
clearButton:SetHeight(22)
clearButton:SetText("Clear")
clearButton:SetScript("OnClick", function()
MTH_EA_OPT_SaveBinding(nil)
end)
table.insert(rightGroup, clearButton)
-- ── Casting ──────────────────────────────────────────────
table.insert(rightGroup, MTH_EA_OPT_Header(container, "Casting", -304, OPT_R))
local quiverCB = MTH_EA_OPT_CB(container, "MTH_ExpAmmoQuiverNoClipCB",
"Use Quiver no-clip casting",
-324, OPT_R, cfg.useQuiverNoClip == true,
function(v) if MTH_ExpAmmo then MTH_ExpAmmo.SetUseQuiverNoClip(v) end end)
table.insert(rightGroup, quiverCB)
local quiverTip = MTH_EA_OPT_Tip(container,
"|cff4d9cffRequires the Quiver addon.|r \n Routes Aimed/Steady/Multi cast through Quiver.CastNoClip \n to avoid clipping your auto-shot swing timer",
-350, OPT_R, 1, 1, 1)
if quiverTip then quiverTip:SetWidth(290) end
table.insert(rightGroup, quiverTip)
-- ── Rotation ─────────────────────────────────────────────
table.insert(rightGroup, MTH_EA_OPT_Header(container, "Rotation", -400, OPT_R))
local rotTip = MTH_EA_OPT_Tip(container,
"Uncheck a shot to permanently skip it during its proc window.\n The keybind will cast Steady/Aimed instead.",
-418, OPT_R, 0.65, 0.65, 0.65)
if rotTip then rotTip:SetWidth(290) end
table.insert(rightGroup, rotTip)
local multiCB = MTH_EA_OPT_CB(container, "MTH_ExpAmmoBlockMultiCB",
"Multi-Shot (Explosive)",
-452, OPT_R, cfg.blockExplosive ~= true,
function(v) if MTH_ExpAmmo then MTH_ExpAmmo.SetBlockExplosive(not v) end end)
table.insert(rightGroup, multiCB)
local serpentCB = MTH_EA_OPT_CB(container, "MTH_ExpAmmoBlockSerpentCB",
"Serpent Sting (Poisonous)",
-476, OPT_R, cfg.blockPoisonous ~= true,
function(v) if MTH_ExpAmmo then MTH_ExpAmmo.SetBlockPoisonous(not v) end end)
table.insert(rightGroup, serpentCB)
local arcaneCB = MTH_EA_OPT_CB(container, "MTH_ExpAmmoBlockArcaneCB",
"Arcane Shot (Enchanted)",
-500, OPT_R, cfg.blockEnchanted ~= true,
function(v) if MTH_ExpAmmo then MTH_ExpAmmo.SetBlockEnchanted(not v) end end)
table.insert(rightGroup, arcaneCB)
-- Apply initial enabled state
MTH_EA_OPT_SetGroupEnabled(rightGroup, showHint)
-- Apply initial gating state.
setRightEnabled(showHint)
end
function MTH_SetupExpAmmoOptions()
+107 -125
View File
@@ -242,31 +242,25 @@ function MTH_RefreshFeedOMaticOptions()
if MTH_FOM_STATE.ctrl.SaveCookNone then MTH_FOM_STATE.ctrl.SaveCookNone:SetChecked(FOM_Config.SaveForCookingLevel and FOM_Config.SaveForCookingLevel >= 4 and 1 or nil) end
end
-- Small label helper: prefer Feed-O-Matic's own button text, else localized.
local function MTH_FOM_Label(key, lkey, fallback)
return (FOM_OptionsButtonText and FOM_OptionsButtonText[key]) or MTH_FOM_L(lkey, fallback)
end
function MTH_SetupFeedOMaticOptions()
if not MTH_FOM_READY then return end
local container = MTH_GetFrame("MetaHuntOptionsFeedOMatic")
if not container then return end
local rightColumnX = 300
local yAdjust = -64
MTH_ClearContainer(container)
MTH_FOM_STATE.ctrl = {}
local title = container:CreateFontString("MetaHuntOptionsFeedOMaticTitle", "ARTWORK", "GameFontHighlight")
title:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -10)
title:SetText(MTH_FOM_L("FOM_TITLE", "Feed-O-Matic"))
local panel = MTH_Layout.Panel(container)
panel:Title(MTH_FOM_L("FOM_TITLE", "Feed-O-Matic"))
panel:Note(MTH_FOM_L("FOM_STATUS_NOTICE", "Feed-O-Matic, created by the great Fizzwidget, is not yet entirely ready for Twow because I am missing \na reliable list of all foods, mostly impossible to fetch from the DB.\n It still works much better in this version, but all stuff related to Food buff and Cooking isnt fully functional."), { lines = 4 })
local statusNotice = container:CreateFontString("MetaHuntOptionsFeedOMaticStatusNotice", "ARTWORK", "GameFontNormalSmall")
statusNotice:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -34)
statusNotice:SetWidth(600)
statusNotice:SetJustifyH("LEFT")
statusNotice:SetJustifyV("TOP")
statusNotice:SetTextColor(0.35, 0.65, 1)
statusNotice:SetText(MTH_FOM_L("FOM_STATUS_NOTICE", "Feed-O-Matic, created by the great Fizzwidget, is not yet entirely ready for Twow because I am missing \na reliable list of all foods, mostly impossible to fetch from the DB.\n It still works much better in this version, but all stuff related to Food buff and Cooking isnt fully functional."))
local moduleCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsFeedOMaticEnabled", MTH_FOM_L("FOM_ENABLE_MODULE", "Enable FeedOMatic module"), -32 + yAdjust)
if moduleCheck then
moduleCheck:SetScript("OnClick", function()
MTH_FOM_STATE.enableCheck = panel:TopCheckbox("MetaHuntOptionsFeedOMaticEnabled",
MTH_FOM_L("FOM_ENABLE_MODULE", "Enable FeedOMatic module"), {
onClick = function()
if not this then return end
local enabled = this:GetChecked() == 1
if MTH and MTH.SetModuleEnabled then
@@ -276,125 +270,113 @@ function MTH_SetupFeedOMaticOptions()
end
end
MTH_RefreshFeedOMaticOptions()
end)
MTH_FOM_STATE.enableCheck = moduleCheck
end
end,
})
local leftHeader = container:CreateFontString("MetaHuntOptionsFeedOMaticGeneralHeader", "ARTWORK", "GameFontHighlight")
leftHeader:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -62 + yAdjust)
leftHeader:SetText(MTH_FOM_L("FOM_HEADER_GENERAL", "General"))
-- ===== General (left column) =====
local general = panel:Box("left", "MetaHuntOptionsFOMGeneralBox", MTH_FOM_L("FOM_HEADER_GENERAL", "General"))
local bindStatus = container:CreateFontString("MetaHuntOptionsFOMBindStatus", "ARTWORK", "GameFontNormalSmall")
bindStatus:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -80 + yAdjust)
bindStatus:SetText(string.format(MTH_FOM_L("FOM_BIND_STATUS_VALUE", "Feed key: %s"), MTH_FOM_GetBindingDisplayText()))
MTH_FOM_STATE.bindStatus = bindStatus
MTH_FOM_STATE.bindStatus = general:Text("MetaHuntOptionsFOMBindStatus",
string.format(MTH_FOM_L("FOM_BIND_STATUS_VALUE", "Feed key: %s"), MTH_FOM_GetBindingDisplayText()))
local bindButton = CreateFrame("Button", "MetaHuntOptionsFOMBindButton", container, "UIPanelButtonTemplate")
bindButton:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -100 + yAdjust)
bindButton:SetWidth(90)
bindButton:SetHeight(22)
bindButton:SetText(MTH_FOM_L("FOM_BIND_SET_KEY", "Set Key"))
bindButton:SetScript("OnClick", function()
if MTH_FOM_STATE.captureFrame and MTH_FOM_STATE.captureFrame:IsShown() then
MTH_FOM_StopBindingCapture()
else
MTH_FOM_StartBindingCapture()
end
end)
MTH_FOM_STATE.bindButton = bindButton
local bindButtons = general:Buttons({
{ name = "MetaHuntOptionsFOMBindButton", label = MTH_FOM_L("FOM_BIND_SET_KEY", "Set Key"), width = 90,
onClick = function()
if MTH_FOM_STATE.captureFrame and MTH_FOM_STATE.captureFrame:IsShown() then
MTH_FOM_StopBindingCapture()
else
MTH_FOM_StartBindingCapture()
end
end },
{ name = "MetaHuntOptionsFOMBindClearButton", label = MTH_FOM_L("FOM_BIND_CLEAR", "Clear"), width = 70,
onClick = function() MTH_FOM_SaveBinding(nil) end },
})
MTH_FOM_STATE.bindButton = bindButtons[1]
MTH_FOM_STATE.bindClearButton = bindButtons[2]
local bindClearButton = CreateFrame("Button", "MetaHuntOptionsFOMBindClearButton", container, "UIPanelButtonTemplate")
bindClearButton:SetPoint("LEFT", bindButton, "RIGHT", 8, 0)
bindClearButton:SetWidth(70)
bindClearButton:SetHeight(22)
bindClearButton:SetText(MTH_FOM_L("FOM_BIND_CLEAR", "Clear"))
bindClearButton:SetScript("OnClick", function()
MTH_FOM_SaveBinding(nil)
end)
MTH_FOM_STATE.bindClearButton = bindClearButton
general:Note("MetaHuntOptionsFOMBindHint",
MTH_FOM_L("FOM_BIND_HINT", "You should assign a key bind for feed-o-matic,\nin order to feed your pet automatically.\nThe key \"P\" is an excellent candidate !"), { lines = 3 })
local bindHint = container:CreateFontString("MetaHuntOptionsFOMBindHint", "ARTWORK", "GameFontNormalSmall")
bindHint:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -128 + yAdjust)
bindHint:SetWidth(360)
bindHint:SetJustifyH("LEFT")
bindHint:SetJustifyV("TOP")
bindHint:SetTextColor(0.35, 0.65, 1)
bindHint:SetText(MTH_FOM_L("FOM_BIND_HINT", "You should assign a key bind for feed-o-matic,\nin order to feed your pet automatically.\nThe key \"P\" is an excellent candidate !"))
MTH_FOM_STATE.ctrl.AvoidQuestFood = general:Checkbox("MetaHuntOptionsFOMAvoidQuest",
MTH_FOM_Label("AvoidQuestFood", "FOM_LABEL_AVOID_QUEST_FOODS", "Avoid quest foods"),
{ onClick = function() if not this then return end FOM_Config.AvoidQuestFood = this:GetChecked() == 1 end })
MTH_FOM_STATE.ctrl.AvoidBonusFood = general:Checkbox("MetaHuntOptionsFOMAvoidBonus",
MTH_FOM_Label("AvoidBonusFood", "FOM_LABEL_AVOID_BONUS_FOODS", "Avoid bonus foods"),
{ onClick = function() if not this then return end FOM_Config.AvoidBonusFood = this:GetChecked() == 1 end })
MTH_FOM_STATE.ctrl.PreferHigherQuality = general:Checkbox("MetaHuntOptionsFOMPreferQuality",
MTH_FOM_Label("PreferHigherQuality", "FOM_LABEL_PREFER_HIGHER_QUALITY_FOOD", "Prefer higher quality food"),
{ onClick = function() if not this then return end FOM_Config.PreferHigherQuality = this:GetChecked() == 1 end })
MTH_FOM_STATE.ctrl.Fallback = general:Checkbox("MetaHuntOptionsFOMFallback",
MTH_FOM_Label("Fallback", "FOM_LABEL_FALLBACK_TO_AVOIDED_FOODS", "Fallback to avoided foods"),
{ onClick = function() if not this then return end FOM_Config.Fallback = this:GetChecked() == 1 end })
MTH_FOM_STATE.ctrl.AvoidQuestFood = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMAvoidQuest", FOM_OptionsButtonText and FOM_OptionsButtonText["AvoidQuestFood"] or MTH_FOM_L("FOM_LABEL_AVOID_QUEST_FOODS", "Avoid quest foods"), -170 + yAdjust)
MTH_FOM_STATE.ctrl.AvoidBonusFood = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMAvoidBonus", FOM_OptionsButtonText and FOM_OptionsButtonText["AvoidBonusFood"] or MTH_FOM_L("FOM_LABEL_AVOID_BONUS_FOODS", "Avoid bonus foods"), -195 + yAdjust)
MTH_FOM_STATE.ctrl.PreferHigherQuality = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMPreferQuality", FOM_OptionsButtonText and FOM_OptionsButtonText["PreferHigherQuality"] or MTH_FOM_L("FOM_LABEL_PREFER_HIGHER_QUALITY_FOOD", "Prefer higher quality food"), -220 + yAdjust)
MTH_FOM_STATE.ctrl.Fallback = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMFallback", FOM_OptionsButtonText and FOM_OptionsButtonText["Fallback"] or MTH_FOM_L("FOM_LABEL_FALLBACK_TO_AVOIDED_FOODS", "Fallback to avoided foods"), -245 + yAdjust)
MTH_FOM_STATE.keepOpenEdit = general:EditRow("MetaHuntOptionsFOMKeepOpenLabel",
MTH_FOM_L("FOM_KEEP_OPEN_BAG_SLOTS", "Keep open bag slots:"),
"MetaHuntOptionsFOMKeepOpen", 40, {
numeric = true,
onChange = function()
if not this then return end
FOM_Config.KeepOpenSlots = tonumber(this:GetText()) or 0
end,
})
if MTH_FOM_STATE.ctrl.AvoidQuestFood then MTH_FOM_STATE.ctrl.AvoidQuestFood:SetScript("OnClick", function() if not this then return end FOM_Config.AvoidQuestFood = this:GetChecked() == 1 end) end
if MTH_FOM_STATE.ctrl.AvoidBonusFood then MTH_FOM_STATE.ctrl.AvoidBonusFood:SetScript("OnClick", function() if not this then return end FOM_Config.AvoidBonusFood = this:GetChecked() == 1 end) end
if MTH_FOM_STATE.ctrl.PreferHigherQuality then MTH_FOM_STATE.ctrl.PreferHigherQuality:SetScript("OnClick", function() if not this then return end FOM_Config.PreferHigherQuality = this:GetChecked() == 1 end) end
if MTH_FOM_STATE.ctrl.Fallback then MTH_FOM_STATE.ctrl.Fallback:SetScript("OnClick", function() if not this then return end FOM_Config.Fallback = this:GetChecked() == 1 end) end
-- ===== Notify when feeding (left column) =====
local notify = panel:Box("left", "MetaHuntOptionsFOMNotifyBox", MTH_FOM_L("FOM_HEADER_NOTIFY_WHEN_FEEDING", "Notify when feeding"))
MTH_FOM_STATE.ctrl.AlertEmote = notify:Checkbox("MetaHuntOptionsFOMAlertEmote",
MTH_FOM_Label("AlertEmote", "FOM_LABEL_NOTIFY_VIA_EMOTE", "Via emote"),
{ onClick = function() MTH_FOM_SetAlert("emote"); MTH_RefreshFeedOMaticOptions() end })
MTH_FOM_STATE.ctrl.AlertChat = notify:Checkbox("MetaHuntOptionsFOMAlertChat",
MTH_FOM_Label("AlertChat", "FOM_LABEL_NOTIFY_IN_CHAT", "In chat"),
{ onClick = function() MTH_FOM_SetAlert("chat"); MTH_RefreshFeedOMaticOptions() end })
MTH_FOM_STATE.ctrl.AlertNone = notify:Checkbox("MetaHuntOptionsFOMAlertNone",
MTH_FOM_Label("AlertNone", "FOM_LABEL_NOTIFY_NONE", "Don't notify"),
{ onClick = function() MTH_FOM_SetAlert("none"); MTH_RefreshFeedOMaticOptions() end })
local keepOpenLabel = container:CreateFontString("MetaHuntOptionsFOMKeepOpenLabel", "ARTWORK", "GameFontNormalSmall")
keepOpenLabel:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -302 + yAdjust)
keepOpenLabel:SetText(MTH_FOM_L("FOM_KEEP_OPEN_BAG_SLOTS", "Keep open bag slots:"))
-- ===== Avoid foods used in cooking (right column) =====
local avoid = panel:Box("right", "MetaHuntOptionsFOMAvoidBox", MTH_FOM_L("FOM_HEADER_AVOID_FOODS_USED_IN_COOKING", "Avoid foods used in cooking"))
MTH_FOM_STATE.ctrl.SaveCookOrange = avoid:Checkbox("MetaHuntOptionsFOMSaveCookOrange",
MTH_FOM_Label("SaveForCook_Orange", "FOM_LABEL_ONLY_DIFFICULT_RECIPES", "Only difficult recipes"),
{ onClick = function() MTH_FOM_SetCookingLevel(3); MTH_RefreshFeedOMaticOptions() end })
MTH_FOM_STATE.ctrl.SaveCookYellow = avoid:Checkbox("MetaHuntOptionsFOMSaveCookYellow",
MTH_FOM_Label("SaveForCook_Yellow", "FOM_LABEL_MEDIUM_OR_BETTER", "Medium or better"),
{ onClick = function() MTH_FOM_SetCookingLevel(2); MTH_RefreshFeedOMaticOptions() end })
MTH_FOM_STATE.ctrl.SaveCookGreen = avoid:Checkbox("MetaHuntOptionsFOMSaveCookGreen",
MTH_FOM_Label("SaveForCook_Green", "FOM_LABEL_EASY_OR_BETTER", "Easy or better"),
{ onClick = function() MTH_FOM_SetCookingLevel(1); MTH_RefreshFeedOMaticOptions() end })
MTH_FOM_STATE.ctrl.SaveCookAll = avoid:Checkbox("MetaHuntOptionsFOMSaveCookAll",
MTH_FOM_Label("SaveForCook_All", "FOM_LABEL_ALL_FOODS", "All foods"),
{ onClick = function() MTH_FOM_SetCookingLevel(0); MTH_RefreshFeedOMaticOptions() end })
MTH_FOM_STATE.ctrl.SaveCookNone = avoid:Checkbox("MetaHuntOptionsFOMSaveCookNone",
MTH_FOM_Label("SaveForCook_None", "FOM_LABEL_DO_NOT_SAVE_COOKING_FOODS", "Do not save cooking foods"),
{ onClick = function() MTH_FOM_SetCookingLevel(4); MTH_RefreshFeedOMaticOptions() end })
local keepOpen = CreateFrame("EditBox", "MetaHuntOptionsFOMKeepOpen", container, "InputBoxTemplate")
keepOpen:SetPoint("LEFT", keepOpenLabel, "RIGHT", 8, 0)
keepOpen:SetWidth(40)
keepOpen:SetHeight(20)
keepOpen:SetNumeric(true)
keepOpen:SetAutoFocus(false)
keepOpen:SetScript("OnTextChanged", function()
if not this then return end
local value = tonumber(this:GetText()) or 0
FOM_Config.KeepOpenSlots = value
end)
keepOpen:SetScript("OnEnterPressed", function() if this then this:ClearFocus() end end)
keepOpen:SetScript("OnEscapePressed", function() if this then this:ClearFocus() end end)
MTH_FOM_STATE.keepOpenEdit = keepOpen
-- ===== Warn when pet needs feeding (right column) =====
local warn = panel:Box("right", "MetaHuntOptionsFOMWarnBox", MTH_FOM_L("FOM_HEADER_WARN_WHEN_PET_NEEDS_FEEDING", "Warn when pet needs feeding"))
MTH_FOM_STATE.ctrl.LevelContent = warn:Checkbox("MetaHuntOptionsFOMLevelContent",
MTH_FOM_Label("LevelContent", "FOM_LABEL_WARN_WHEN_CONTENT", "When content"),
{ onClick = function() MTH_FOM_SetLevel("content"); MTH_RefreshFeedOMaticOptions() end })
MTH_FOM_STATE.ctrl.LevelUnhappy = warn:Checkbox("MetaHuntOptionsFOMLevelUnhappy",
MTH_FOM_Label("LevelUnhappy", "FOM_LABEL_WARN_WHEN_UNHAPPY", "When unhappy"),
{ onClick = function() MTH_FOM_SetLevel("unhappy"); MTH_RefreshFeedOMaticOptions() end })
MTH_FOM_STATE.ctrl.LevelOff = warn:Checkbox("MetaHuntOptionsFOMLevelOff",
MTH_FOM_Label("LevelOff", "FOM_LABEL_DONT_WARN", "Don't warn"),
{ onClick = function() MTH_FOM_SetLevel("off"); MTH_RefreshFeedOMaticOptions() end })
local notifyHeader = container:CreateFontString("MetaHuntOptionsFOMNotifyHeader", "ARTWORK", "GameFontHighlight")
notifyHeader:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -336 + yAdjust)
notifyHeader:SetText(MTH_FOM_L("FOM_HEADER_NOTIFY_WHEN_FEEDING", "Notify when feeding"))
warn:Gap(6)
MTH_FOM_STATE.ctrl.AlertEmote = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMAlertEmote", FOM_OptionsButtonText and FOM_OptionsButtonText["AlertEmote"] or MTH_FOM_L("FOM_LABEL_NOTIFY_VIA_EMOTE", "Via emote"), -360 + yAdjust)
MTH_FOM_STATE.ctrl.AlertChat = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMAlertChat", FOM_OptionsButtonText and FOM_OptionsButtonText["AlertChat"] or MTH_FOM_L("FOM_LABEL_NOTIFY_IN_CHAT", "In chat"), -385 + yAdjust)
MTH_FOM_STATE.ctrl.AlertNone = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMAlertNone", FOM_OptionsButtonText and FOM_OptionsButtonText["AlertNone"] or MTH_FOM_L("FOM_LABEL_NOTIFY_NONE", "Don't notify"), -410 + yAdjust)
if MTH_FOM_STATE.ctrl.AlertEmote then MTH_FOM_STATE.ctrl.AlertEmote:SetScript("OnClick", function() MTH_FOM_SetAlert("emote"); MTH_RefreshFeedOMaticOptions() end) end
if MTH_FOM_STATE.ctrl.AlertChat then MTH_FOM_STATE.ctrl.AlertChat:SetScript("OnClick", function() MTH_FOM_SetAlert("chat"); MTH_RefreshFeedOMaticOptions() end) end
if MTH_FOM_STATE.ctrl.AlertNone then MTH_FOM_STATE.ctrl.AlertNone:SetScript("OnClick", function() MTH_FOM_SetAlert("none"); MTH_RefreshFeedOMaticOptions() end) end
local warnHeader = container:CreateFontString("MetaHuntOptionsFOMWarnHeader", "ARTWORK", "GameFontHighlight")
warnHeader:SetPoint("TOPLEFT", container, "TOPLEFT", rightColumnX, -276 + yAdjust)
warnHeader:SetText(MTH_FOM_L("FOM_HEADER_WARN_WHEN_PET_NEEDS_FEEDING", "Warn when pet needs feeding"))
MTH_FOM_STATE.ctrl.LevelContent = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMLevelContent", FOM_OptionsButtonText and FOM_OptionsButtonText["LevelContent"] or MTH_FOM_L("FOM_LABEL_WARN_WHEN_CONTENT", "When content"), -300 + yAdjust, rightColumnX)
MTH_FOM_STATE.ctrl.LevelUnhappy = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMLevelUnhappy", FOM_OptionsButtonText and FOM_OptionsButtonText["LevelUnhappy"] or MTH_FOM_L("FOM_LABEL_WARN_WHEN_UNHAPPY", "When unhappy"), -325 + yAdjust, rightColumnX)
MTH_FOM_STATE.ctrl.LevelOff = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMLevelOff", FOM_OptionsButtonText and FOM_OptionsButtonText["LevelOff"] or MTH_FOM_L("FOM_LABEL_DONT_WARN", "Don't warn"), -350 + yAdjust, rightColumnX)
if MTH_FOM_STATE.ctrl.LevelContent then MTH_FOM_STATE.ctrl.LevelContent:SetScript("OnClick", function() MTH_FOM_SetLevel("content"); MTH_RefreshFeedOMaticOptions() end) end
if MTH_FOM_STATE.ctrl.LevelUnhappy then MTH_FOM_STATE.ctrl.LevelUnhappy:SetScript("OnClick", function() MTH_FOM_SetLevel("unhappy"); MTH_RefreshFeedOMaticOptions() end) end
if MTH_FOM_STATE.ctrl.LevelOff then MTH_FOM_STATE.ctrl.LevelOff:SetScript("OnClick", function() MTH_FOM_SetLevel("off"); MTH_RefreshFeedOMaticOptions() end) end
MTH_FOM_STATE.ctrl.AudioWarning = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMAudioWarning", FOM_OptionsButtonText and FOM_OptionsButtonText["AudioWarning"] or MTH_FOM_L("FOM_LABEL_PLAY_SOUND", "Play sound"), -378 + yAdjust, rightColumnX)
MTH_FOM_STATE.ctrl.AudioWarningBell = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMAudioWarningBell", FOM_OptionsButtonText and FOM_OptionsButtonText["AudioWarningBell"] or MTH_FOM_L("FOM_LABEL_USE_BELL_SOUND", "Use bell sound"), -403 + yAdjust, rightColumnX)
MTH_FOM_STATE.ctrl.TextWarning = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMTextWarning", FOM_OptionsButtonText and FOM_OptionsButtonText["TextWarning"] or MTH_FOM_L("FOM_LABEL_SHOW_TEXT", "Show text"), -428 + yAdjust, rightColumnX)
MTH_FOM_STATE.ctrl.IconWarning = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMIconWarning", FOM_OptionsButtonText and FOM_OptionsButtonText["IconWarning"] or MTH_FOM_L("FOM_LABEL_FLASH_ICON", "Flash icon"), -453 + yAdjust, rightColumnX)
if MTH_FOM_STATE.ctrl.AudioWarning then MTH_FOM_STATE.ctrl.AudioWarning:SetScript("OnClick", function() if not this then return end if this:GetChecked() == 1 then if FOM_Config.AudioWarning ~= "bell" then FOM_Config.AudioWarning = true end else FOM_Config.AudioWarning = nil end MTH_RefreshFeedOMaticOptions() end) end
if MTH_FOM_STATE.ctrl.AudioWarningBell then MTH_FOM_STATE.ctrl.AudioWarningBell:SetScript("OnClick", function() if not this then return end if this:GetChecked() == 1 then FOM_Config.AudioWarning = "bell" else FOM_Config.AudioWarning = true end MTH_RefreshFeedOMaticOptions() end) end
if MTH_FOM_STATE.ctrl.TextWarning then MTH_FOM_STATE.ctrl.TextWarning:SetScript("OnClick", function() if not this then return end FOM_Config.TextWarning = this:GetChecked() == 1 end) end
if MTH_FOM_STATE.ctrl.IconWarning then MTH_FOM_STATE.ctrl.IconWarning:SetScript("OnClick", function() if not this then return end FOM_Config.IconWarning = this:GetChecked() == 1 end) end
local cookHeader = container:CreateFontString("MetaHuntOptionsFOMCookingHeader", "ARTWORK", "GameFontHighlight")
cookHeader:SetPoint("TOPLEFT", container, "TOPLEFT", rightColumnX, -62 + yAdjust)
cookHeader:SetText(MTH_FOM_L("FOM_HEADER_AVOID_FOODS_USED_IN_COOKING", "Avoid foods used in cooking"))
MTH_FOM_STATE.ctrl.SaveCookOrange = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMSaveCookOrange", FOM_OptionsButtonText and FOM_OptionsButtonText["SaveForCook_Orange"] or MTH_FOM_L("FOM_LABEL_ONLY_DIFFICULT_RECIPES", "Only difficult recipes"), -86 + yAdjust, rightColumnX)
MTH_FOM_STATE.ctrl.SaveCookYellow = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMSaveCookYellow", FOM_OptionsButtonText and FOM_OptionsButtonText["SaveForCook_Yellow"] or MTH_FOM_L("FOM_LABEL_MEDIUM_OR_BETTER", "Medium or better"), -111 + yAdjust, rightColumnX)
MTH_FOM_STATE.ctrl.SaveCookGreen = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMSaveCookGreen", FOM_OptionsButtonText and FOM_OptionsButtonText["SaveForCook_Green"] or MTH_FOM_L("FOM_LABEL_EASY_OR_BETTER", "Easy or better"), -136 + yAdjust, rightColumnX)
MTH_FOM_STATE.ctrl.SaveCookAll = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMSaveCookAll", FOM_OptionsButtonText and FOM_OptionsButtonText["SaveForCook_All"] or MTH_FOM_L("FOM_LABEL_ALL_FOODS", "All foods"), -161 + yAdjust, rightColumnX)
MTH_FOM_STATE.ctrl.SaveCookNone = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMSaveCookNone", FOM_OptionsButtonText and FOM_OptionsButtonText["SaveForCook_None"] or MTH_FOM_L("FOM_LABEL_DO_NOT_SAVE_COOKING_FOODS", "Do not save cooking foods"), -186 + yAdjust, rightColumnX)
if MTH_FOM_STATE.ctrl.SaveCookOrange then MTH_FOM_STATE.ctrl.SaveCookOrange:SetScript("OnClick", function() MTH_FOM_SetCookingLevel(3); MTH_RefreshFeedOMaticOptions() end) end
if MTH_FOM_STATE.ctrl.SaveCookYellow then MTH_FOM_STATE.ctrl.SaveCookYellow:SetScript("OnClick", function() MTH_FOM_SetCookingLevel(2); MTH_RefreshFeedOMaticOptions() end) end
if MTH_FOM_STATE.ctrl.SaveCookGreen then MTH_FOM_STATE.ctrl.SaveCookGreen:SetScript("OnClick", function() MTH_FOM_SetCookingLevel(1); MTH_RefreshFeedOMaticOptions() end) end
if MTH_FOM_STATE.ctrl.SaveCookAll then MTH_FOM_STATE.ctrl.SaveCookAll:SetScript("OnClick", function() MTH_FOM_SetCookingLevel(0); MTH_RefreshFeedOMaticOptions() end) end
if MTH_FOM_STATE.ctrl.SaveCookNone then MTH_FOM_STATE.ctrl.SaveCookNone:SetScript("OnClick", function() MTH_FOM_SetCookingLevel(4); MTH_RefreshFeedOMaticOptions() end) end
MTH_FOM_STATE.ctrl.AudioWarning = warn:Checkbox("MetaHuntOptionsFOMAudioWarning",
MTH_FOM_Label("AudioWarning", "FOM_LABEL_PLAY_SOUND", "Play sound"),
{ onClick = function() if not this then return end if this:GetChecked() == 1 then if FOM_Config.AudioWarning ~= "bell" then FOM_Config.AudioWarning = true end else FOM_Config.AudioWarning = nil end MTH_RefreshFeedOMaticOptions() end })
MTH_FOM_STATE.ctrl.AudioWarningBell = warn:Checkbox("MetaHuntOptionsFOMAudioWarningBell",
MTH_FOM_Label("AudioWarningBell", "FOM_LABEL_USE_BELL_SOUND", "Use bell sound"),
{ onClick = function() if not this then return end if this:GetChecked() == 1 then FOM_Config.AudioWarning = "bell" else FOM_Config.AudioWarning = true end MTH_RefreshFeedOMaticOptions() end })
MTH_FOM_STATE.ctrl.TextWarning = warn:Checkbox("MetaHuntOptionsFOMTextWarning",
MTH_FOM_Label("TextWarning", "FOM_LABEL_SHOW_TEXT", "Show text"),
{ onClick = function() if not this then return end FOM_Config.TextWarning = this:GetChecked() == 1 end })
MTH_FOM_STATE.ctrl.IconWarning = warn:Checkbox("MetaHuntOptionsFOMIconWarning",
MTH_FOM_Label("IconWarning", "FOM_LABEL_FLASH_ICON", "Flash icon"),
{ onClick = function() if not this then return end FOM_Config.IconWarning = this:GetChecked() == 1 end })
panel:Finish()
MTH_RefreshFeedOMaticOptions()
end
+103 -195
View File
@@ -197,31 +197,25 @@ local function MTH_ICU_OpenColorPicker(colorKey)
ColorPickerFrame:Show()
end
local function MTH_ICU_CreateOptionRow(container, rowName, label, key, y, labelX, dropdownX)
labelX = labelX or MTH_ICU_LAYOUT.LEFT_X
dropdownX = dropdownX or MTH_ICU_LAYOUT.LEFT_DROPDOWN_X
local function MTH_ICU_BuildUI(container)
MTH_ICU_OPT_STATE.controls = {}
MTH_ICU_OPT_STATE.container = container
MTH_ICU_OPT_STATE.built = true
local labelFs = container:CreateFontString(rowName .. "Label", "ARTWORK", "GameFontNormalSmall")
labelFs:SetPoint("TOPLEFT", container, "TOPLEFT", labelX, y)
labelFs:SetText(label)
local controls = MTH_ICU_OPT_STATE.controls
local dropdown = CreateFrame("Frame", rowName .. "Drop", container, "UIDropDownMenuTemplate")
dropdown:ClearAllPoints()
dropdown:SetPoint("TOPLEFT", container, "TOPLEFT", dropdownX, y + 12)
if UIDropDownMenu_SetWidth then
UIDropDownMenu_SetWidth(MTH_ICU_LAYOUT.DROPDOWN_WIDTH, dropdown)
end
if UIDropDownMenu_JustifyText then
UIDropDownMenu_JustifyText("LEFT", dropdown)
end
local panel = MTH_Layout.Panel(container)
panel:Title("MTH ICU")
panel:Note("ICU is a minimap targeting utility module for your Trackings. It provides enhanced target information and click actions for players and NPCs on the minimap.",
{ lines = 2 })
if UIDropDownMenu_Initialize then
UIDropDownMenu_Initialize(dropdown, function()
-- Standard UIDropDownMenu initialize factory for a stored option key.
local function makeInit(key)
return function()
local values = MTH_ICU_GetOptionValues(key)
local store = MTH_ICU_GetStore()
local current = tostring(store[key] or "")
local infoFactory = UIDropDownMenu_CreateInfo
for i = 1, table.getn(values) do
local optionValue = tostring(values[i])
local info = type(infoFactory) == "function" and infoFactory() or {}
@@ -229,76 +223,23 @@ local function MTH_ICU_CreateOptionRow(container, rowName, label, key, y, labelX
info.checked = optionValue == current and 1 or nil
info.func = function()
MTH_ICU_SetValue(key, optionValue)
MTH_RefreshICUOptions()
-- ANCHOR toggles whether the Toggle Anchor / Expand Up
-- controls exist, so rebuild instead of a plain refresh.
if key == "ANCHOR" then
MTH_SetupICUOptions()
else
MTH_RefreshICUOptions()
end
end
if UIDropDownMenu_AddButton then UIDropDownMenu_AddButton(info) end
end
end)
end
end
MTH_ICU_OPT_STATE.controls[key] = {
label = labelFs,
dropdown = dropdown,
}
end
local function MTH_ICU_CreateColorRow(container, rowName, label, colorKey, y, labelX, buttonX)
labelX = labelX or MTH_ICU_LAYOUT.RIGHT_X
buttonX = buttonX or MTH_ICU_LAYOUT.COLOR_BUTTON_X
local labelFs = container:CreateFontString(rowName .. "Label", "ARTWORK", "GameFontNormalSmall")
labelFs:SetPoint("TOPLEFT", container, "TOPLEFT", labelX, y)
labelFs:SetText(label)
local button = CreateFrame("Button", rowName .. "Button", container, "UIPanelButtonTemplate")
button:SetPoint("TOPLEFT", container, "TOPLEFT", buttonX, y + 8)
button:SetWidth(MTH_ICU_LAYOUT.COLOR_BUTTON_WIDTH)
button:SetHeight(22)
button:SetText("Pick")
button:SetScript("OnClick", function()
MTH_ICU_OpenColorPicker(colorKey)
end)
local swatch = button:CreateTexture(rowName .. "Swatch", "ARTWORK")
swatch:SetTexture("Interface\\Buttons\\WHITE8X8")
swatch:SetPoint("LEFT", button, "LEFT", 6, 0)
swatch:SetWidth(14)
swatch:SetHeight(14)
MTH_ICU_OPT_STATE.controls[colorKey] = {
label = labelFs,
button = button,
swatch = swatch,
isColor = true,
}
end
local function MTH_ICU_BuildUI(container)
if MTH_ICU_OPT_STATE.built and MTH_ICU_OPT_STATE.container == container then
return
end
MTH_ClearContainer(container)
MTH_ICU_OPT_STATE.controls = {}
MTH_ICU_OPT_STATE.container = container
MTH_ICU_OPT_STATE.built = true
local title = container:CreateFontString("MetaHuntOptionsICUTitle", "ARTWORK", "GameFontHighlight")
title:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -10)
title:SetText("MTH ICU")
local note = container:CreateFontString("MetaHuntOptionsICUNote", "ARTWORK", "GameFontNormalSmall")
note:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -32)
note:SetWidth(560)
note:SetJustifyH("LEFT")
note:SetJustifyV("TOP")
note:SetTextColor(0.35, 0.65, 1)
note:SetText("ICU is a minimap targeting utility module for your Trackings.\nIt provides enhanced target information and click actions for players and NPCs on the minimap.")
local moduleEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsICUModuleEnabled", "Enable ICU module", -72, MTH_ICU_LAYOUT.LEFT_X)
if moduleEnabled then
moduleEnabled:SetScript("OnClick", function()
if not this then return end
-- ===== LEFT: Module =====
local moduleBox = panel:Box("left", "MTH_ICUModuleBox", "Module")
controls.moduleEnabled = moduleBox:Checkbox("MetaHuntOptionsICUModuleEnabled", "Enable ICU module", {
onClick = function()
if MTH and MTH.SetModuleEnabled then
local ok, err = MTH:SetModuleEnabled("icu", this:GetChecked() == 1)
if not ok and MTH and MTH.Print then
@@ -306,130 +247,97 @@ local function MTH_ICU_BuildUI(container)
end
end
MTH_RefreshICUOptions()
end)
MTH_ICU_OPT_STATE.controls.moduleEnabled = moduleEnabled
end
local mouseOver = MTH_CreateCheckbox(container, "MetaHuntOptionsICUMouseOver", "Enable CTRL mouseover scan", -98, MTH_ICU_LAYOUT.LEFT_X)
if mouseOver then
mouseOver:SetScript("OnClick", function()
if not this then return end
end,
})
controls.mouseOver = moduleBox:Checkbox("MetaHuntOptionsICUMouseOver", "Enable CTRL mouseover scan", {
onClick = function()
local store = MTH_ICU_GetStore()
store.mouseOver = this:GetChecked() == 1 and true or false
end)
MTH_ICU_OPT_STATE.controls.mouseOver = mouseOver
end,
})
-- ===== LEFT: General Settings =====
local genBox = panel:Box("left", "MTH_ICUGeneralBox", "General Settings")
controls.ALERT = { dropdown = genBox:Dropdown("MetaHuntOptionsICUAlertDrop",
{ label = "ALERT PvP", width = 130, initialize = makeInit("ALERT") }) }
controls.ANNOUNCE = { dropdown = genBox:Dropdown("MetaHuntOptionsICUAnnounceDrop",
{ label = "ANNOUNCE on click", width = 130, initialize = makeInit("ANNOUNCE") }) }
controls.HEALTH_TEXT_MODE = { dropdown = genBox:Dropdown("MetaHuntOptionsICUHealthModeDrop",
{ label = "Health text", width = 130, initialize = makeInit("HEALTH_TEXT_MODE") }) }
controls.POPUP_HIDE_DELAY = { dropdown = genBox:Dropdown("MetaHuntOptionsICUHideDelayDrop",
{ label = "List hide delay", width = 130, initialize = makeInit("POPUP_HIDE_DELAY") }) }
controls.ANCHOR = { dropdown = genBox:Dropdown("MetaHuntOptionsICUAnchorDrop",
{ label = "ANCHOR", width = 130, initialize = makeInit("ANCHOR") }) }
-- The manual-anchor controls only apply to a CUSTOM anchor. Build them
-- only in that case so the box never reserves empty space for them.
if tostring(MTH_ICU_GetStore().ANCHOR or "") == "CUSTOM" then
controls.customAnchorButton = genBox:Button("MetaHuntOptionsICUToggleAnchorButton", "Toggle Anchor", {
width = 116,
onClick = function() if type(ICU_ToggleAnchor) == "function" then ICU_ToggleAnchor() end end,
})
controls.expandUp = genBox:Checkbox("MetaHuntOptionsICUExpandUp", "Expand Up", {
onClick = function()
local store = MTH_ICU_GetStore()
store.EXPAND_UP = this:GetChecked() == 1 and true or false
if type(ICU_SetPoints) == "function" then ICU_SetPoints() end
end,
})
end
local sectionHeader = container:CreateFontString("MetaHuntOptionsICUSectionHeader", "ARTWORK", "GameFontHighlight")
sectionHeader:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_ICU_LAYOUT.LEFT_X, -146)
sectionHeader:SetText("General Settings")
MTH_ICU_CreateOptionRow(container, "MetaHuntOptionsICUAlert", "ALERT PVP", "ALERT", -172, MTH_ICU_LAYOUT.LEFT_X, MTH_ICU_LAYOUT.LEFT_DROPDOWN_X)
MTH_ICU_CreateOptionRow(container, "MetaHuntOptionsICUAnnounce", "ANNOUNCE on click", "ANNOUNCE", -198, MTH_ICU_LAYOUT.LEFT_X, MTH_ICU_LAYOUT.LEFT_DROPDOWN_X)
MTH_ICU_CreateOptionRow(container, "MetaHuntOptionsICUHealthMode", "Health text", "HEALTH_TEXT_MODE", -224, MTH_ICU_LAYOUT.LEFT_X, MTH_ICU_LAYOUT.LEFT_DROPDOWN_X)
MTH_ICU_CreateOptionRow(container, "MetaHuntOptionsICUHideDelay", "List hide delay", "POPUP_HIDE_DELAY", -250, MTH_ICU_LAYOUT.LEFT_X, MTH_ICU_LAYOUT.LEFT_DROPDOWN_X)
MTH_ICU_CreateOptionRow(container, "MetaHuntOptionsICUAnchor", "ANCHOR", "ANCHOR", -276, MTH_ICU_LAYOUT.LEFT_X, MTH_ICU_LAYOUT.LEFT_DROPDOWN_X)
local toggleAnchorButton = CreateFrame("Button", "MetaHuntOptionsICUToggleAnchorButton", container, "UIPanelButtonTemplate")
toggleAnchorButton:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_ICU_LAYOUT.LEFT_X, -302)
toggleAnchorButton:SetWidth(116)
toggleAnchorButton:SetHeight(22)
toggleAnchorButton:SetText("Toggle Anchor")
toggleAnchorButton:SetScript("OnClick", function()
if type(ICU_ToggleAnchor) == "function" then
ICU_ToggleAnchor()
end
end)
MTH_ICU_OPT_STATE.controls.customAnchorButton = toggleAnchorButton
local expandUp = MTH_CreateCheckbox(container, "MetaHuntOptionsICUExpandUp", "Expand Up", -301, MTH_ICU_LAYOUT.LEFT_X + 132)
if expandUp then
expandUp:SetScript("OnClick", function()
if not this then return end
local store = MTH_ICU_GetStore()
store.EXPAND_UP = this:GetChecked() == 1 and true or false
if type(ICU_SetPoints) == "function" then
ICU_SetPoints()
end
end)
MTH_ICU_OPT_STATE.controls.expandUp = expandUp
end
local showGuild = MTH_CreateCheckbox(container, "MetaHuntOptionsICUShowGuild", "Show player guild names", -344, MTH_ICU_LAYOUT.LEFT_X)
if showGuild then
showGuild:SetScript("OnClick", function()
if not this then return end
local store = MTH_ICU_GetStore()
store.SHOW_GUILD_NAME = this:GetChecked() == 1 and true or false
end)
MTH_ICU_OPT_STATE.controls.showGuildName = showGuild
end
local showClass = MTH_CreateCheckbox(container, "MetaHuntOptionsICUShowClass", "Show player class", -368, MTH_ICU_LAYOUT.LEFT_X)
if showClass then
showClass:SetScript("OnClick", function()
if not this then return end
local store = MTH_ICU_GetStore()
store.SHOW_PLAYER_CLASS = this:GetChecked() == 1 and true or false
end)
MTH_ICU_OPT_STATE.controls.showPlayerClass = showClass
end
local showRace = MTH_CreateCheckbox(container, "MetaHuntOptionsICUShowRace", "Show player race", -392, MTH_ICU_LAYOUT.LEFT_X)
if showRace then
showRace:SetScript("OnClick", function()
if not this then return end
local store = MTH_ICU_GetStore()
store.SHOW_PLAYER_RACE = this:GetChecked() == 1 and true or false
end)
MTH_ICU_OPT_STATE.controls.showPlayerRace = showRace
end
local showTitles = MTH_CreateCheckbox(container, "MetaHuntOptionsICUShowTitles", "Show custom titles in alerts", -416, MTH_ICU_LAYOUT.LEFT_X)
if showTitles then
showTitles:SetScript("OnClick", function()
if not this then return end
local store = MTH_ICU_GetStore()
store.SHOW_CUSTOM_TITLES = this:GetChecked() == 1 and true or false
end)
MTH_ICU_OPT_STATE.controls.showCustomTitles = showTitles
end
local rightHeader = container:CreateFontString("MetaHuntOptionsICURightHeader", "ARTWORK", "GameFontHighlight")
rightHeader:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_ICU_LAYOUT.RIGHT_X, -146)
rightHeader:SetText("Background Colors")
MTH_ICU_CreateOptionRow(container, "MetaHuntOptionsICUPlayerColorMode", "Player colors", "PLAYER_COLOR_MODE", -172, MTH_ICU_LAYOUT.RIGHT_X, MTH_ICU_LAYOUT.RIGHT_DROPDOWN_X)
local reactionOnlyPvp = MTH_CreateCheckbox(container, "MetaHuntOptionsICUReactionOnlyPvp", "Reaction only when PvP-flagged", -200, MTH_ICU_LAYOUT.RIGHT_X)
if reactionOnlyPvp then
reactionOnlyPvp:SetScript("OnClick", function()
if not this then return end
-- ===== RIGHT: Background Colors =====
local bgBox = panel:Box("right", "MTH_ICUBgBox", "Background Colors")
controls.PLAYER_COLOR_MODE = { dropdown = bgBox:Dropdown("MetaHuntOptionsICUPlayerColorModeDrop",
{ label = "Player colors", width = 130, initialize = makeInit("PLAYER_COLOR_MODE") }) }
controls.reactionOnlyPvp = bgBox:Checkbox("MetaHuntOptionsICUReactionOnlyPvp", "Reaction only when PvP-flagged", {
onClick = function()
local store = MTH_ICU_GetStore()
store.REACTION_ONLY_PVP_PLAYERS = this:GetChecked() == 1 and true or false
end)
MTH_ICU_OPT_STATE.controls.reactionOnlyPvp = reactionOnlyPvp
end
end,
})
local colorHeader = container:CreateFontString("MetaHuntOptionsICUColorsHeader", "ARTWORK", "GameFontHighlight")
colorHeader:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_ICU_LAYOUT.RIGHT_X, -224)
local colorScope = container:CreateFontString("MetaHuntOptionsICUColorsScope", "ARTWORK", "GameFontNormalSmall")
colorScope:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_ICU_LAYOUT.RIGHT_X, -242)
colorScope:SetWidth(250)
colorScope:SetJustifyH("LEFT")
colorScope:SetJustifyV("TOP")
colorScope:SetTextColor(0.35, 0.65, 1)
colorScope:SetText("Player pickers: REACTION / FACTION / CUSTOM\nNPC pickers: always")
local colorY = -284
-- ===== RIGHT: Color Pickers =====
local colorBox = panel:Box("right", "MTH_ICUColorBox", "Color Pickers")
colorBox:Note("MetaHuntOptionsICUColorsScope",
"Player pickers: REACTION / FACTION / CUSTOM\nNPC pickers: always", { lines = 2 })
for i = 1, table.getn(MTH_ICU_COLOR_ROWS) do
local row = MTH_ICU_COLOR_ROWS[i]
MTH_ICU_CreateColorRow(container, "MetaHuntOptionsICUColor" .. tostring(i), row.label, row.key, colorY, MTH_ICU_LAYOUT.RIGHT_X, MTH_ICU_LAYOUT.COLOR_BUTTON_X)
colorY = colorY - MTH_ICU_LAYOUT.COLOR_ROW_STEP
local btn, swatch = colorBox:ColorRow("MetaHuntOptionsICUColor" .. tostring(i), {
label = row.label,
buttonText = "Pick",
buttonWidth = 78,
onClick = function() MTH_ICU_OpenColorPicker(row.key) end,
})
controls[row.key] = { button = btn, swatch = swatch, isColor = true }
end
-- ===== Player Info (placed on whichever column has the most room) =====
local infoBox = panel:Box(panel:ShorterSide(), "MTH_ICUInfoBox", "Player Info")
controls.showGuildName = infoBox:Checkbox("MetaHuntOptionsICUShowGuild", "Show player guild names", {
onClick = function()
local store = MTH_ICU_GetStore()
store.SHOW_GUILD_NAME = this:GetChecked() == 1 and true or false
end,
})
controls.showPlayerClass = infoBox:Checkbox("MetaHuntOptionsICUShowClass", "Show player class", {
onClick = function()
local store = MTH_ICU_GetStore()
store.SHOW_PLAYER_CLASS = this:GetChecked() == 1 and true or false
end,
})
controls.showPlayerRace = infoBox:Checkbox("MetaHuntOptionsICUShowRace", "Show player race", {
onClick = function()
local store = MTH_ICU_GetStore()
store.SHOW_PLAYER_RACE = this:GetChecked() == 1 and true or false
end,
})
controls.showCustomTitles = infoBox:Checkbox("MetaHuntOptionsICUShowTitles", "Show custom titles in alerts", {
onClick = function()
local store = MTH_ICU_GetStore()
store.SHOW_CUSTOM_TITLES = this:GetChecked() == 1 and true or false
end,
})
panel:Finish()
end
function MTH_RefreshICUOptions()
+608
View File
@@ -0,0 +1,608 @@
-- =====================================================================
-- MetaHunt Option Panel Layout Engine
-- ---------------------------------------------------------------------
-- One reusable builder that every option panel uses. It removes ALL
-- hand-typed pixel offsets and box heights from the panels: you declare
-- rows, the engine stacks them and auto-sizes each box.
--
-- Think of it as CSS + flexbox for WoW 1.12:
-- * MTH_Layout.Theme -> the "CSS variables" (spacing / fonts / colors).
-- Change a value here to restyle every panel.
-- * panel / box methods -> the "flexbox": append rows, boxes grow to fit.
--
-- Design rules baked in (so the classic bugs are impossible):
-- * Each box TITLE lives INSIDE its box -> titles can never collide.
-- * Box HEIGHT is computed from its content -> never cramped/too short.
-- * Box CONTENT is parented to the box frame -> correct z-order.
-- * Everything is reuse-by-name (getglobal) -> no duplicates on /rl.
--
-- Typical usage:
-- local panel = MTH_Layout.Panel(container)
-- panel:Title("Feed-O-Matic")
-- panel:Note("blue helper paragraph", { lines = 3 })
-- panel:TopCheckbox("MyEnable", "Enable module", { onClick = fn, checked = fn })
-- local box = panel:Box("left", "MyBoxName", "General")
-- box:Text("MyStatus", "Feed key: P")
-- box:Buttons({ { name="A", label="Set Key", width=90, onClick=fn },
-- { name="B", label="Clear", width=70, onClick=fn } })
-- box:Note("MyHint", "blue helper text", { lines = 3 })
-- local cb = box:Checkbox("MyOpt", "Some option", { onClick = fn, checked = true })
-- box:EditRow("MyLbl", "Keep open bag slots:", "MyEdit", 40, { numeric = true, onChange = fn })
-- panel:Finish()
-- =====================================================================
MTH_Layout = MTH_Layout or {}
local L = MTH_Layout
-- ---------------------------------------------------------------------
-- THEME ("CSS variables": tweak these to restyle the whole UI)
-- ---------------------------------------------------------------------
L.Theme = {
-- Spacing (pixels)
panelPad = 12, -- outer gutter from the panel edges
colGap = 12, -- horizontal gap between the two columns
boxGap = 16, -- vertical gap between stacked boxes
colTopGap = 8, -- gap between the header block and the first boxes
boxPadX = 10, -- content inset from a box's left edge
boxPadTop = 28, -- first row offset from a box's top (clears inside title)
boxPadBottom = 12, -- padding beneath the last row inside a box
cbInset = 8, -- checkbox inset from a box's left edge
rowCheckbox = 24, -- vertical step consumed by a checkbox / edit row
rowButton = 30, -- vertical step consumed by a button row
rowSlider = 46, -- vertical step consumed by a slider (label+track+value)
rowDropdown = 50, -- vertical step consumed by a dropdown (label+menu)
textLine = 14, -- height of one wrapped text line
textGap = 6, -- extra gap after a text/note block
titleInsetX = 10, -- box title inset X (inside the box)
titleInsetY = -12, -- box title inset Y (inside the box)
headTop = -12, -- Y where the panel header starts
headTitleStep = 24, -- vertical step after the panel title
headNoteGap = 10, -- extra gap after a header note
headRowGap = 8, -- extra gap after a header checkbox
headLinkStep = 18, -- vertical step after a header link
-- Fonts
fontPanelTitle = "GameFontNormal", -- panel heading
fontBoxTitle = "GameFontNormal", -- box title (recolored)
fontLabel = "GameFontNormalSmall", -- checkbox / edit labels
fontText = "GameFontNormalSmall", -- plain text
fontNote = "GameFontNormalSmall", -- helper paragraphs
fontLink = "GameFontHighlightSmall",
-- Colors { r, g, b }
colPanelTitle = { 1.00, 0.82, 0.00 }, -- gold
colBoxTitle = { 1.00, 1.00, 1.00 }, -- white
colNote = { 0.35, 0.65, 1.00 }, -- blue helper text
colText = { 0.93, 0.93, 0.93 }, -- normal text
colLink = { 0.40, 0.75, 1.00 }, -- link idle
colLinkHover = { 0.60, 0.90, 1.00 }, -- link hover
-- Templates
boxTemplate = "OptionFrameBoxTemplate",
checkTemplate = "UICheckButtonTemplate",
buttonTemplate = "UIPanelButtonTemplate",
editTemplate = "InputBoxTemplate",
}
-- ---------------------------------------------------------------------
-- Small shared helpers
-- ---------------------------------------------------------------------
local function applyColor(region, c)
if region and c then region:SetTextColor(c[1], c[2], c[3]) end
end
local function ensureFontString(parent, name, font)
local fs = getglobal(name)
if not fs then
fs = parent:CreateFontString(name, "ARTWORK", font)
end
fs:Show()
return fs
end
local function ensureFrame(kind, name, parent, template)
local f = getglobal(name)
if not f then
f = CreateFrame(kind, name, parent, template)
end
f:SetParent(parent)
return f
end
-- Attach (or refresh) a checkbox's label, tooltip, checked state and click.
-- labelWidth (optional) enables word-wrap; the wrapped text height is returned
-- so the caller can grow the row to fit multi-line labels.
local function configureCheckbox(cb, label, opts, T, labelWidth)
local txt = getglobal(cb:GetName() .. "Text")
if not txt then
txt = cb:CreateFontString(cb:GetName() .. "Text", "ARTWORK", T.fontLabel)
end
-- Anchor the label to the checkbox's top-right and let it grow downward so
-- wrapped lines never collide with the row above. Centre a single line
-- vertically against the checkbox.
local cbH = (cb.GetHeight and cb:GetHeight()) or 24
local topOff = -((cbH - T.textLine) / 2)
if topOff > 0 then topOff = 0 end
txt:ClearAllPoints()
txt:SetPoint("TOPLEFT", cb, "TOPRIGHT", 4, topOff)
if labelWidth and labelWidth > 0 then
txt:SetWidth(labelWidth)
else
txt:SetWidth(0)
end
txt:SetJustifyH("LEFT")
txt:SetJustifyV("TOP")
txt:SetText(label or "")
txt:Show()
if opts.checked ~= nil then
if type(opts.checked) == "function" then
cb:SetChecked(opts.checked())
else
cb:SetChecked(opts.checked)
end
end
if opts.onClick then
cb:SetScript("OnClick", opts.onClick)
end
if opts.tooltip and opts.tooltip ~= "" then
cb.mthTooltip = opts.tooltip
cb:SetScript("OnEnter", function()
GameTooltip:SetOwner(cb, "ANCHOR_RIGHT")
GameTooltip:SetText(cb.mthTooltip, 1, 1, 1, 1, true)
GameTooltip:Show()
end)
cb:SetScript("OnLeave", function() GameTooltip:Hide() end)
end
local h = 0
if txt.GetStringHeight then h = txt:GetStringHeight() end
if (not h or h <= 0) and txt.GetHeight then h = txt:GetHeight() end
return h or 0
end
-- ---------------------------------------------------------------------
-- Box object (returned by panel:Box). Appends rows top-to-bottom and
-- keeps the box height in sync with its content.
-- ---------------------------------------------------------------------
local function makeBox(container, box, boxWidth, state, T)
local self = {}
local function apply()
state.height = -state.cursor + T.boxPadBottom
box:SetHeight(state.height)
end
function self:Checkbox(name, label, opts)
opts = opts or {}
local cb = ensureFrame("CheckButton", name, box, T.checkTemplate)
cb:ClearAllPoints()
cb:SetPoint("TOPLEFT", box, "TOPLEFT", T.cbInset, state.cursor)
cb:Show()
-- Wrap width = box content width minus the checkbox frame, the 4px label
-- gap, and a 2px right cushion so wrapped text never touches the border.
local cbW = (cb.GetWidth and cb:GetWidth()) or 26
local labelWidth = boxWidth - T.boxPadX - (T.cbInset + cbW + 4) - 2
local txtH = configureCheckbox(cb, label, opts, T, labelWidth)
-- A single line keeps the compact row height; a wrapped label grows the
-- row to clear its top-centre offset plus a gap before the next row.
local rowH = T.rowCheckbox
local needed = txtH + 8
if txtH > (T.textLine + 4) then needed = txtH + 14 end
if needed > rowH then rowH = needed end
state.cursor = state.cursor - rowH
apply()
return cb
end
function self:Text(name, text, opts)
opts = opts or {}
local fs = ensureFontString(box, name, opts.font or T.fontText)
fs:ClearAllPoints()
fs:SetPoint("TOPLEFT", box, "TOPLEFT", T.boxPadX, state.cursor)
fs:SetWidth(opts.width or (boxWidth - T.boxPadX * 2))
fs:SetJustifyH("LEFT")
fs:SetJustifyV("TOP")
fs:SetText(text or "")
applyColor(fs, opts.color or T.colText)
-- Reserve vertical space: honour an explicit line count, otherwise
-- measure the wrapped height so callers don't have to guess.
local reserve
if opts.lines then
reserve = opts.lines * T.textLine
else
local h = (fs.GetStringHeight and fs:GetStringHeight()) or 0
if (not h or h <= 0) and fs.GetHeight then h = fs:GetHeight() end
if not h or h <= 0 then h = T.textLine end
reserve = h
end
state.cursor = state.cursor - reserve - T.textGap
apply()
return fs
end
-- Blue helper paragraph (same as MM Widget style), usable inside a box.
function self:Note(name, text, opts)
opts = opts or {}
opts.color = opts.color or T.colNote
opts.font = opts.font or T.fontNote
return self:Text(name, text, opts)
end
-- One row of buttons placed left-to-right.
-- list = { { name, label, width, height, onClick, gap, template }, ... }
function self:Buttons(list)
local out = {}
local x = T.boxPadX
local i = 1
while list and i <= table.getn(list) do
local spec = list[i]
local b = ensureFrame("Button", spec.name, box, spec.template or T.buttonTemplate)
b:ClearAllPoints()
b:SetPoint("TOPLEFT", box, "TOPLEFT", x, state.cursor)
b:SetWidth(spec.width or 90)
b:SetHeight(spec.height or 22)
b:SetText(spec.label or "")
b:Show()
if spec.onClick then b:SetScript("OnClick", spec.onClick) end
table.insert(out, b)
x = x + (spec.width or 90) + (spec.gap or 8)
i = i + 1
end
state.cursor = state.cursor - T.rowButton
apply()
return out
end
-- Label + edit box on one row (e.g. "Keep open bag slots: [__]").
function self:EditRow(labelName, labelText, editName, editWidth, opts)
opts = opts or {}
local lbl = ensureFontString(box, labelName, T.fontLabel)
lbl:ClearAllPoints()
lbl:SetPoint("TOPLEFT", box, "TOPLEFT", T.boxPadX, state.cursor)
lbl:SetText(labelText or "")
applyColor(lbl, T.colText)
local edit = ensureFrame("EditBox", editName, box, T.editTemplate)
edit:ClearAllPoints()
edit:SetPoint("LEFT", lbl, "RIGHT", 8, 0)
edit:SetWidth(editWidth or 40)
edit:SetHeight(opts.height or 20)
if opts.numeric then edit:SetNumeric(true) end
edit:SetAutoFocus(false)
edit:Show()
if opts.onChange then edit:SetScript("OnTextChanged", opts.onChange) end
edit:SetScript("OnEnterPressed", function() if this then this:ClearFocus() end end)
edit:SetScript("OnEscapePressed", function() if this then this:ClearFocus() end end)
state.cursor = state.cursor - T.rowCheckbox
apply()
return edit, lbl
end
-- Slider with a left label and a right-aligned live value readout.
-- opts = { label, min, max, step, value, width, onChange, format }
-- format(value) -> string (defaults to a rounded integer).
function self:Slider(name, opts)
opts = opts or {}
local lbl = ensureFontString(box, name .. "Caption", T.fontLabel)
lbl:ClearAllPoints()
lbl:SetPoint("TOPLEFT", box, "TOPLEFT", T.boxPadX, state.cursor)
lbl:SetText(opts.label or "")
applyColor(lbl, T.colText)
local valueFs = ensureFontString(box, name .. "Value", T.fontLabel)
valueFs:ClearAllPoints()
valueFs:SetPoint("TOPRIGHT", box, "TOPRIGHT", -T.boxPadX, state.cursor)
valueFs:SetJustifyH("RIGHT")
applyColor(valueFs, T.colPanelTitle)
local slider = ensureFrame("Slider", name, box, "OptionsSliderTemplate")
slider:ClearAllPoints()
slider:SetPoint("TOPLEFT", box, "TOPLEFT", T.boxPadX + 4, state.cursor - 18)
slider:SetWidth(opts.width or (boxWidth - T.boxPadX * 2 - 8))
slider:SetMinMaxValues(opts.min or 0, opts.max or 1)
slider:SetValueStep(opts.step or 1)
slider:Show()
-- OptionsSliderTemplate ships Low/High/Text children; silence them.
local lowFs = getglobal(name .. "Low"); if lowFs then lowFs:SetText(""); lowFs:Hide() end
local highFs = getglobal(name .. "High"); if highFs then highFs:SetText(""); highFs:Hide() end
local midFs = getglobal(name .. "Text"); if midFs then midFs:SetText("") end
slider.mthValueFs = valueFs
slider.mthFormat = opts.format
slider.mthOnChange = opts.onChange
slider:SetScript("OnValueChanged", function()
local v = tonumber(arg1)
if not v and this and this.GetValue then v = this:GetValue() end
if not v then v = 0 end
if this.mthValueFs then
if this.mthFormat then
this.mthValueFs:SetText(this.mthFormat(v))
else
this.mthValueFs:SetText(tostring(math.floor(v + 0.5)))
end
end
if this.mthOnChange then this.mthOnChange(v) end
end)
slider:SetValue(opts.value or opts.min or 0)
state.cursor = state.cursor - T.rowSlider
apply()
return slider
end
-- Dropdown menu with a left label. The caller supplies the standard
-- UIDropDownMenu initialize function and (optionally) the current text.
-- opts = { label, width, initialize, text }
function self:Dropdown(name, opts)
opts = opts or {}
local lbl = ensureFontString(box, name .. "Caption", T.fontLabel)
lbl:ClearAllPoints()
lbl:SetPoint("TOPLEFT", box, "TOPLEFT", T.boxPadX, state.cursor)
lbl:SetText(opts.label or "")
applyColor(lbl, T.colText)
local dd = ensureFrame("Frame", name, box, "UIDropDownMenuTemplate")
dd:ClearAllPoints()
-- UIDropDownMenu textures carry ~15px of built-in left inset.
dd:SetPoint("TOPLEFT", box, "TOPLEFT", T.boxPadX - 15, state.cursor - 16)
dd:Show()
if UIDropDownMenu_SetWidth then
UIDropDownMenu_SetWidth(opts.width or (boxWidth - T.boxPadX * 2 - 20), dd)
end
if UIDropDownMenu_JustifyText then UIDropDownMenu_JustifyText("LEFT", dd) end
if opts.initialize and UIDropDownMenu_Initialize then
UIDropDownMenu_Initialize(dd, opts.initialize)
end
if opts.text and UIDropDownMenu_SetText then
UIDropDownMenu_SetText(opts.text, dd)
end
state.cursor = state.cursor - T.rowDropdown
apply()
return dd
end
-- Single button occupying one button row (thin wrapper over :Buttons).
function self:Button(name, label, opts)
opts = opts or {}
local out = self:Buttons({ {
name = name, label = label,
width = opts.width, height = opts.height,
onClick = opts.onClick, template = opts.template,
} })
return out[1]
end
-- Label on the left, a colour swatch + "Pick" button on the right.
-- opts = { label, color = {r,g,b}, buttonText, buttonWidth, onClick }
function self:ColorRow(name, opts)
opts = opts or {}
local lbl = ensureFontString(box, name .. "Caption", T.fontLabel)
lbl:ClearAllPoints()
lbl:SetPoint("TOPLEFT", box, "TOPLEFT", T.boxPadX, state.cursor)
lbl:SetText(opts.label or "")
applyColor(lbl, T.colText)
local btn = ensureFrame("Button", name .. "Button", box, T.buttonTemplate)
btn:ClearAllPoints()
btn:SetPoint("TOPRIGHT", box, "TOPRIGHT", -T.boxPadX, state.cursor + 2)
btn:SetWidth(opts.buttonWidth or 60)
btn:SetHeight(20)
btn:SetText(opts.buttonText or "Pick")
btn:Show()
if opts.onClick then btn:SetScript("OnClick", opts.onClick) end
local swatch = getglobal(name .. "Swatch")
if not swatch then
swatch = btn:CreateTexture(name .. "Swatch", "OVERLAY")
swatch:SetTexture("Interface\\Buttons\\WHITE8X8")
swatch:SetWidth(12)
swatch:SetHeight(12)
swatch:SetPoint("LEFT", btn, "LEFT", 5, 0)
end
if opts.color then
swatch:SetVertexColor(opts.color[1], opts.color[2], opts.color[3])
end
state.cursor = state.cursor - T.rowCheckbox
apply()
return btn, swatch
end
-- Manual vertical spacer.
function self:Gap(px)
state.cursor = state.cursor - (px or 12)
apply()
end
-- Reserve a custom row of the given pixel height. Returns the box frame and
-- the TOPLEFT y-offset (within the box) where custom widgets can anchor.
-- Use for composite rows the primitives don't cover (e.g. checkbox +
-- dropdown + edit box on one line). x anchoring is left to the caller.
function self:Row(height)
local y = state.cursor
state.cursor = state.cursor - (height or T.rowCheckbox)
apply()
return box, y
end
-- Left content inset (px) for callers positioning custom row widgets.
function self:PadX() return T.boxPadX end
function self:Frame() return box end
return self
end
-- ---------------------------------------------------------------------
-- Panel object (returned by MTH_Layout.Panel).
-- ---------------------------------------------------------------------
function L.Panel(container)
if not container then return nil end
local T = L.Theme
MTH_ClearContainer(container)
local cname = (container.GetName and container:GetName()) or "MTHPanel"
local width = (container.GetWidth and container:GetWidth()) or 0
if not width or width < 460 then width = 580 end
local colWidth = math.floor((width - T.panelPad * 2 - T.colGap) / 2)
if colWidth < 220 then colWidth = 220 end
local leftX = T.panelPad
local rightX = T.panelPad + colWidth + T.colGap
local fullWidth = width - T.panelPad * 2
local headY = T.headTop
local started = false
local col = {
left = { x = leftX, y = 0, open = nil },
right = { x = rightX, y = 0, open = nil },
}
local noteId = 0
local panel = {}
local function startColumns()
if started then return end
started = true
local top = headY - T.colTopGap
col.left.y = top
col.right.y = top
end
local function closeSide(side)
local c = col[side]
if c and c.open then
c.y = c.y - c.open.height - T.boxGap
c.open = nil
end
end
-- ---- Header elements (full width, above the columns) ----
function panel:Title(text)
local fs = ensureFontString(container, cname .. "_Title", T.fontPanelTitle)
fs:ClearAllPoints()
fs:SetPoint("TOPLEFT", container, "TOPLEFT", T.panelPad, headY)
fs:SetText(text or "")
applyColor(fs, T.colPanelTitle)
headY = headY - T.headTitleStep
return fs
end
function panel:Note(text, opts)
opts = opts or {}
noteId = noteId + 1
local fs = ensureFontString(container, cname .. "_Note" .. noteId, T.fontNote)
fs:ClearAllPoints()
fs:SetPoint("TOPLEFT", container, "TOPLEFT", T.panelPad, headY)
fs:SetWidth(opts.width or fullWidth)
fs:SetJustifyH("LEFT")
fs:SetJustifyV("TOP")
fs:SetText(text or "")
applyColor(fs, opts.color or T.colNote)
local lines = opts.lines or 1
headY = headY - (lines * T.textLine) - T.headNoteGap
return fs
end
function panel:Link(name, text, onClick)
local btn = ensureFrame("Button", name, container, nil)
btn:ClearAllPoints()
btn:SetPoint("TOPLEFT", container, "TOPLEFT", T.panelPad, headY)
btn:SetHeight(16)
btn:SetWidth(fullWidth)
local fs = getglobal(name .. "Text")
if not fs then
fs = btn:CreateFontString(name .. "Text", "ARTWORK", T.fontLink)
fs:SetPoint("LEFT", btn, "LEFT", 0, 0)
fs:SetJustifyH("LEFT")
end
fs:SetText(text or "")
applyColor(fs, T.colLink)
btn:Show()
btn:SetScript("OnEnter", function() applyColor(fs, T.colLinkHover) end)
btn:SetScript("OnLeave", function() applyColor(fs, T.colLink) end)
if onClick then btn:SetScript("OnClick", onClick) end
headY = headY - T.headLinkStep
return btn
end
function panel:TopCheckbox(name, label, opts)
opts = opts or {}
local cb = ensureFrame("CheckButton", name, container, T.checkTemplate)
cb:ClearAllPoints()
cb:SetPoint("TOPLEFT", container, "TOPLEFT", T.panelPad, headY)
cb:Show()
local txtH = configureCheckbox(cb, label, opts, T, fullWidth - 26)
local rowH = T.rowCheckbox
if (txtH + 8) > rowH then rowH = txtH + 8 end
headY = headY - rowH - T.headRowGap
return cb
end
-- ---- Boxes (columns) ----
function panel:Box(side, name, title)
startColumns()
side = (side == "right") and "right" or "left"
closeSide(side)
local c = col[side]
local box = ensureFrame("Frame", name, container, T.boxTemplate)
box:ClearAllPoints()
box:SetPoint("TOPLEFT", container, "TOPLEFT", c.x, c.y)
box:SetWidth(colWidth)
box:Show()
local titleFS = getglobal(name .. "Title")
if titleFS then
titleFS:SetText(title or "")
applyColor(titleFS, T.colBoxTitle)
titleFS:ClearAllPoints()
titleFS:SetPoint("TOPLEFT", box, "TOPLEFT", T.titleInsetX, T.titleInsetY)
end
local state = {
cursor = -T.boxPadTop,
height = T.boxPadTop + T.boxPadBottom,
}
box:SetHeight(state.height)
c.open = state
return makeBox(container, box, colWidth, state, T)
end
-- Returns "left" or "right": whichever column currently has more room
-- left (i.e. its content bottom is higher). Lets callers auto-balance
-- a variable number of boxes without hand-picking columns.
function panel:ShorterSide()
startColumns()
local function bottom(side)
local c = col[side]
local y = c.y
if c.open then y = y - c.open.height - T.boxGap end
return y
end
if bottom("right") > bottom("left") then return "right" end
return "left"
end
function panel:Finish()
closeSide("left")
closeSide("right")
end
-- Expose geometry for callers that need it (rare).
panel.colWidth = colWidth
panel.fullWidth = fullWidth
return panel
end
+4 -5
View File
@@ -300,11 +300,10 @@ function MTH_SetupProfilesOptions()
if not container then return end
if not gSetupDone then
-- Title
local title = container:CreateFontString(nil, "ARTWORK", "GameFontNormal")
title:SetPoint("TOPLEFT", container, "TOPLEFT", 6, -6)
title:SetText("Profiles")
title:SetTextColor(1.00, 0.82, 0.00)
local panel = MTH_Layout.Panel(container)
-- Title (engine header, consistent gold styling)
local title = panel:Title("Profiles")
-- Active profile indicator
gActiveLabel = container:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
+2 -2
View File
@@ -3,8 +3,8 @@ local MTH_OPTIONS_SETUP = {} -- Track which frames have been set up
MTH_OPTIONS_CONST = MTH_OPTIONS_CONST or {}
MTH_OPTIONS_CONST.NAV_DEFAULT_WIDTH = MTH_OPTIONS_CONST.NAV_DEFAULT_WIDTH or 120
MTH_OPTIONS_CONST.WINDOW_PADDING = MTH_OPTIONS_CONST.WINDOW_PADDING or 12
MTH_OPTIONS_CONST.CONTENT_TOP_OFFSET = MTH_OPTIONS_CONST.CONTENT_TOP_OFFSET or -58
MTH_OPTIONS_CONST.CONTENT_HEIGHT = MTH_OPTIONS_CONST.CONTENT_HEIGHT or 566
MTH_OPTIONS_CONST.CONTENT_TOP_OFFSET = MTH_OPTIONS_CONST.CONTENT_TOP_OFFSET or -30
MTH_OPTIONS_CONST.CONTENT_HEIGHT = MTH_OPTIONS_CONST.CONTENT_HEIGHT or 600
MTH_OPTIONS_CONST.CLOSE_BTN_SIZE = MTH_OPTIONS_CONST.CLOSE_BTN_SIZE or 22
MTH_OPTIONS_CONST.CLOSE_BTN_OFFSET_X = MTH_OPTIONS_CONST.CLOSE_BTN_OFFSET_X or -8
MTH_OPTIONS_CONST.CLOSE_BTN_OFFSET_Y = MTH_OPTIONS_CONST.CLOSE_BTN_OFFSET_Y or -8
+476 -750
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -46,12 +46,12 @@
<Frames>
<Frame name="$parentNav" enableMouse="true">
<Size>
<AbsDimension x="120" y="566"/>
<AbsDimension x="120" y="600"/>
</Size>
<Anchors>
<Anchor point="TOPLEFT">
<Offset>
<AbsDimension x="12" y="-58"/>
<AbsDimension x="12" y="-30"/>
</Offset>
</Anchor>
</Anchors>
-18
View File
@@ -1,23 +1,5 @@
-- MetaHunt: auto-train Growl to a freshly tamed pet.
--
-- Growl is a "trainer" pet ability (Growl / Great Stamina / Natural Armor /
-- Great Resistance) that the hunter learns from a Pet Trainer NPC and then
-- teaches to the active pet through the always-available BEAST TRAINING window
-- (a spellbook-like hunter spell, no NPC required). Growl specifically costs
-- 0 training points, so it can always be taught to a brand-new pet.
--
-- The Beast Training window is driven by the vanilla Craft API:
-- GetNumCrafts() -> number of rows
-- GetCraftInfo(i) -> name, rankSubText, type, ...
-- DoCraft(i) -> trains that row (the "Select + Train" action)
-- CloseCraft() -> closes the window
--
-- The correct Growl rank is a function of the pet's level:
-- rank = floor(level / 10) + 1 (ranks 1..7, at pet levels 1/10/.../60)
--
-- Flow on a confirmed fresh tame (when enabled): compute the target rank, open
-- the Beast Training window, find the Growl row at that rank once the craft list
-- populates, DoCraft() it silently, then close the window if we opened it.
local MTH_GROWL_MAX_RANK = 7
+1
View File
@@ -14,6 +14,7 @@
<Include file="..\api\options-tree.lua"/>
<Include file="..\api\options.xml"/>
<Include file="..\api\options.lua"/>
<Include file="..\api\options-layout.lua"/>
<Include file="..\api\options-chronometer.lua"/>
<Include file="..\api\options-credits.lua"/>
<Include file="..\api\options-animations.lua"/>