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 ### 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. - **zTrack — Find Fish**: Added new spell Find Fish to the zTrack list of trackings.
@@ -19,8 +19,6 @@ Resurrecting on Octowow.
### Changed ### 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. - **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 return
end 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 = {} MTH_ANIM_CTRL = {}
local title = container:CreateFontString("MetaHuntOptionsAnimationsTitle", "ARTWORK", "GameFontNormal") -- Global master toggle (full width, above the columns).
title:SetPoint("TOPLEFT", container, "TOPLEFT", 10, -10) panel:TopCheckbox("MetaHuntOptionsAnimMaster",
title:SetText(MTH_ANIM_L("ANIM_TITLE", "Animations")) MTH_ANIM_L("ANIM_ENABLE_ALL", "Enable animations"), {
title:SetTextColor(1.00, 0.82, 0.00) checked = MTH_FX_AnimationsEnabled,
onClick = function()
local credit = container:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall") local cb = getglobal("MetaHuntOptionsAnimMaster")
credit:SetPoint("TOPLEFT", title, "BOTTOMLEFT", 0, -8) MTH_FX_SetAnimationsEnabled(cb:GetChecked())
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())
MTH_ANIM_UpdateChildStates() MTH_ANIM_UpdateChildStates()
end) end,
end })
-- Per-animation checkboxes, grouped by section, laid out in two columns. -- Per-animation checkboxes: each section is a self-sizing box, dropped into
-- Each whole section is placed into whichever column is currently shorter -- whichever column currently has the most room so the two stay balanced.
-- (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 },
}
local s = 1 local s = 1
while MTH_FX_ANIM_SECTIONS and s <= table.getn(MTH_FX_ANIM_SECTIONS) do while MTH_FX_ANIM_SECTIONS and s <= table.getn(MTH_FX_ANIM_SECTIONS) do
local sec = MTH_FX_ANIM_SECTIONS[s] local sec = MTH_FX_ANIM_SECTIONS[s]
-- Pick the shorter column (the one whose cursor is nearest the top). -- Collect this section's defs in order.
local col = columns[1] local secDefs = {}
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
local d = 1 local d = 1
while MTH_FX_ANIM_DEFS and d <= table.getn(MTH_FX_ANIM_DEFS) do while MTH_FX_ANIM_DEFS and d <= table.getn(MTH_FX_ANIM_DEFS) do
local def = MTH_FX_ANIM_DEFS[d] local def = MTH_FX_ANIM_DEFS[d]
if def.section == sec.id then if def.section == sec.id then
local cbName = "MetaHuntOptionsAnim_" .. string.gsub(def.key, "%.", "_") table.insert(secDefs, def)
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
end end
d = d + 1 d = d + 1
end 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 s = s + 1
end end
panel:Finish()
MTH_ANIM_UpdateChildStates() MTH_ANIM_UpdateChildStates()
MTH_ANIM_DBG.setupResult = "ok" MTH_ANIM_DBG.setupResult = "ok"
end end
+70 -95
View File
@@ -589,7 +589,9 @@ local function MTH_AB_RefreshOptionsUI()
end end
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 = { local row = {
subtype = subtype, subtype = subtype,
index = index, index = index,
@@ -597,14 +599,15 @@ local function MTH_AB_CreateRow(container, subtype, index, xBase, yOffset)
} }
local nameBase = "MetaHuntOptionsAutoBuy_" .. subtype .. "_" .. tostring(index) local nameBase = "MetaHuntOptionsAutoBuy_" .. subtype .. "_" .. tostring(index)
row.check = MTH_CreateCheckbox(container, nameBase .. "Check", "", yOffset, xBase + MTH_AB_LAYOUT.ROW_CHECK_X) row.check = MTH_CreateCheckbox(f, nameBase .. "Check", "", y, padX)
row.label = container:CreateFontString(nameBase .. "Label", "ARTWORK", "GameFontNormalSmall") row.label = getglobal(nameBase .. "Label") or f:CreateFontString(nameBase .. "Label", "ARTWORK", "GameFontNormalSmall")
row.label:SetPoint("TOPLEFT", container, "TOPLEFT", xBase + MTH_AB_LAYOUT.ROW_CHECK_LABEL_X, yOffset - 5) row.label:ClearAllPoints()
row.label:SetPoint("TOPLEFT", f, "TOPLEFT", padX + 27, y - 5)
row.label:SetText("On?") 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: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 if UIDropDownMenu_SetWidth then
UIDropDownMenu_SetWidth(MTH_AB_LAYOUT.ROW_DROPDOWN_WIDTH, row.dropdown) UIDropDownMenu_SetWidth(MTH_AB_LAYOUT.ROW_DROPDOWN_WIDTH, row.dropdown)
end end
@@ -640,7 +643,8 @@ local function MTH_AB_CreateRow(container, subtype, index, xBase, yOffset)
end) end)
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") local dropButton = getglobal(nameBase .. "DropButton")
if dropButton then if dropButton then
row.qty:SetPoint("LEFT", dropButton, "RIGHT", MTH_AB_LAYOUT.ROW_QTY_GAP, -1) 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:SetNumeric(true)
row.qty:SetAutoFocus(false) 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:SetPoint("LEFT", row.qty, "RIGHT", MTH_AB_LAYOUT.ROW_SUFFIX_GAP, 0)
row.suffix:SetText("Stacks") row.suffix:SetText("Stacks")
@@ -687,32 +692,18 @@ local function MTH_AB_BuildUI(container)
return return
end end
MTH_ClearContainer(container) local panel = MTH_Layout.Panel(container)
MTH_AB_STATE.container = container MTH_AB_STATE.container = container
MTH_AB_STATE.built = true MTH_AB_STATE.built = true
local controls = MTH_AB_STATE.controls local controls = MTH_AB_STATE.controls
controls.title = container:CreateFontString("MetaHuntOptionsAutoBuyTitle", "ARTWORK", "GameFontHighlight") panel:Title("Auto Buy")
if controls.title then 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.",
if controls.title.SetPoint then controls.title:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -10) end { lines = 2, color = MTH_Layout.Theme.colText })
if controls.title.SetText then controls.title:SetText("Auto Buy") end
end
controls.body = container:CreateFontString("MetaHuntOptionsAutoBuyBody", "ARTWORK", "GameFontNormalSmall") controls.moduleEnabled = panel:TopCheckbox("MetaHuntOptionsAutoBuyModuleEnabled", "Enable Auto Buy module", {
if controls.body then onClick = function()
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()
if not this or MTH_AB_STATE.syncing then return end if not this or MTH_AB_STATE.syncing then return end
if MTH and MTH.SetModuleEnabled then if MTH and MTH.SetModuleEnabled then
local ok, err = MTH:SetModuleEnabled("autobuy", MTH_AB_IsChecked(this)) local ok, err = MTH:SetModuleEnabled("autobuy", MTH_AB_IsChecked(this))
@@ -721,70 +712,44 @@ local function MTH_AB_BuildUI(container)
end end
end end
MTH_AB_RefreshOptionsUI() MTH_AB_RefreshOptionsUI()
end) end,
end })
controls.projectilesEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyProjectilesEnabled", "Enable for Projectiles", -74) controls.projectilesEnabled = panel:TopCheckbox("MetaHuntOptionsAutoBuyProjectilesEnabled", "Enable for Projectiles (arrows & bullets)", {
if controls.projectilesEnabled then onClick = function()
controls.projectilesEnabled:SetScript("OnClick", function()
if not this or MTH_AB_STATE.syncing then return end if not this or MTH_AB_STATE.syncing then return end
local store = MTH_AB_EnsureConfig() local store = MTH_AB_EnsureConfig()
store.projectiles.enabled = MTH_AB_IsChecked(this) store.projectiles.enabled = MTH_AB_IsChecked(this)
MTH_AB_RefreshOptionsUI() MTH_AB_RefreshOptionsUI()
end) 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
-- ===== LEFT: Arrows / RIGHT: Bullets (3 rules each) =====
local arrowBox = panel:Box("left", "MetaHuntOptionsAutoBuyArrowsBox", "Arrows")
for i = 1, 3 do 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(arrowBox, "arrow", i)
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)
end end
controls.petFoodTitle = container:CreateFontString("MetaHuntOptionsAutoBuyPetFoodTitle", "ARTWORK", "GameFontHighlight") local bulletBox = panel:Box("right", "MetaHuntOptionsAutoBuyBulletsBox", "Bullets")
if controls.petFoodTitle then for i = 1, 3 do
controls.petFoodTitle:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_AB_LAYOUT.LEFT_SECTION_X, -300) controls.rows.bullet[i] = MTH_AB_CreateRow(bulletBox, "bullet", i)
controls.petFoodTitle:SetText("Pet Food")
end end
controls.petFoodEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyPetFoodEnabled", "Enable for Pet Food", -322, MTH_AB_LAYOUT.LEFT_SECTION_X) -- ===== Pet Food =====
if controls.petFoodEnabled then local petBox = panel:Box(panel:ShorterSide(), "MetaHuntOptionsAutoBuyPetFoodBox", "Pet Food")
controls.petFoodEnabled:SetScript("OnClick", function()
controls.petFoodEnabled = petBox:Checkbox("MetaHuntOptionsAutoBuyPetFoodEnabled", "Enable for Pet Food", {
onClick = function()
if not this or MTH_AB_STATE.syncing then return end if not this or MTH_AB_STATE.syncing then return end
local store = MTH_AB_EnsureConfig() local store = MTH_AB_EnsureConfig()
store.petFood.enabled = MTH_AB_IsChecked(this) store.petFood.enabled = MTH_AB_IsChecked(this)
MTH_AB_RefreshOptionsUI() MTH_AB_RefreshOptionsUI()
end) end,
end })
controls.petFoodQtyLabel = container:CreateFontString("MetaHuntOptionsAutoBuyPetFoodQtyLabel", "ARTWORK", "GameFontNormalSmall") controls.petFoodQty = petBox:EditRow("MetaHuntOptionsAutoBuyPetFoodQtyLabel", "Quantity:",
if controls.petFoodQtyLabel then "MetaHuntOptionsAutoBuyPetFoodQty", 40, { numeric = true, height = 20 })
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")
if controls.petFoodQty then 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() controls.petFoodQty:SetScript("OnEnterPressed", function()
if not this then return end if not this then return end
local store = MTH_AB_EnsureConfig() local store = MTH_AB_EnsureConfig()
@@ -798,43 +763,52 @@ local function MTH_AB_BuildUI(container)
MTH_AB_SetPetFoodStacks(store, this:GetText()) MTH_AB_SetPetFoodStacks(store, this:GetText())
MTH_AB_RefreshOptionsUI() MTH_AB_RefreshOptionsUI()
end) 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 end
controls.petFoodQtySuffix = container:CreateFontString("MetaHuntOptionsAutoBuyPetFoodQtySuffix", "ARTWORK", "GameFontNormalSmall") controls.petFoodScopeCurrent = petBox:Checkbox("MetaHuntOptionsAutoBuyPetFoodScopeCurrent", "Buy only for my current pet", {
if controls.petFoodQtySuffix then onClick = function()
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()
if not this or MTH_AB_STATE.syncing then return end if not this or MTH_AB_STATE.syncing then return end
local store = MTH_AB_EnsureConfig() local store = MTH_AB_EnsureConfig()
store.petFood.scope = "current" store.petFood.scope = "current"
MTH_AB_RefreshOptionsUI() 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) controls.petFoodScopeAll = petBox:Checkbox("MetaHuntOptionsAutoBuyPetFoodScopeAll", "Buy for all my pets", {
if controls.petFoodScopeAll then onClick = function()
controls.petFoodScopeAll:SetScript("OnClick", function()
if not this or MTH_AB_STATE.syncing then return end if not this or MTH_AB_STATE.syncing then return end
local store = MTH_AB_EnsureConfig() local store = MTH_AB_EnsureConfig()
store.petFood.scope = "all" store.petFood.scope = "all"
MTH_AB_RefreshOptionsUI() MTH_AB_RefreshOptionsUI()
end) end,
end })
controls.petFoodPetLines = {} controls.petFoodPetLines = {}
for i = 1, 5 do for i = 1, 5 do
local rowY = -434 - ((i - 1) * 22) local f, y = petBox:Row(22)
local icon = container:CreateTexture("MetaHuntOptionsAutoBuyPetFoodPetIcon" .. tostring(i), "ARTWORK") 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:SetWidth(16)
icon:SetHeight(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") 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:SetPoint("LEFT", icon, "RIGHT", 6, 0)
text:SetJustifyH("LEFT") text:SetJustifyH("LEFT")
text:SetTextColor(1, 1, 1) text:SetTextColor(1, 1, 1)
@@ -842,6 +816,7 @@ local function MTH_AB_BuildUI(container)
controls.petFoodPetLines[i] = { icon = icon, text = text } controls.petFoodPetLines[i] = { icon = icon, text = text }
end end
panel:Finish()
end end
function MTH_SetupAutoBuyOptions() function MTH_SetupAutoBuyOptions()
+68 -152
View File
@@ -48,19 +48,10 @@ function MTH_SetupAutoQuestOptions()
local container = MTH_GetFrame("MetaHuntOptionsAutoQuest") local container = MTH_GetFrame("MetaHuntOptionsAutoQuest")
if not container then return end if not container then return end
MTH_ClearContainer(container) local store = MTH_AQ_EnsureStore()
if store.scorpokTooltip == nil then
local title = container:CreateFontString("MetaHuntOptionsAutoQuestTitle", "ARTWORK", "GameFontHighlight") store.scorpokTooltip = false
title:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -10) end
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 moduleEnabled = true local moduleEnabled = true
if MTH and MTH.GetModule then if MTH and MTH.GetModule then
@@ -73,10 +64,14 @@ function MTH_SetupAutoQuestOptions()
elseif MTH and MTH.IsModuleEnabled then elseif MTH and MTH.IsModuleEnabled then
moduleEnabled = MTH:IsModuleEnabled("autoquest", false) and true or false moduleEnabled = MTH:IsModuleEnabled("autoquest", false) and true or false
end end
local moduleToggle = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoQuestModuleToggle", "Enable Auto Quest module", -70, 20)
if moduleToggle then local panel = MTH_Layout.Panel(container)
moduleToggle:SetChecked(moduleEnabled and true or false) panel:Title("Auto Quest")
moduleToggle:SetScript("OnClick", function() panel:Note("Automation for specific quest interactions.")
panel:TopCheckbox("MetaHuntOptionsAutoQuestModuleToggle", "Enable Auto Quest module", {
checked = moduleEnabled,
onClick = function()
if not this then return end if not this then return end
local enabled = MTH_AQ_IsChecked(this) local enabled = MTH_AQ_IsChecked(this)
if MTH and MTH.SetModuleEnabled then 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 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 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) this:SetChecked(actual and true or false)
end) end,
end })
local store = MTH_AQ_EnsureStore() -- Salt of the Scorpok (left column)
if store.scorpokTooltip == nil then local scorpok = panel:Box("left", "MetaHuntAutoQuestScorpokBox", "Salt of the Scorpok")
store.scorpokTooltip = false scorpok:Checkbox("MetaHuntOptionsAutoQuestScorpokToggle",
end "Enable SHIFT-rightclick for Bloodmage Drazial", {
checked = store.scorpokDrazial and true or false,
local sectionWidth = (container:GetWidth() or 600) - 40 onClick = function()
if sectionWidth < 360 then local enabled = MTH_AQ_IsChecked(this)
sectionWidth = 360 store.scorpokDrazial = enabled and true or false
end if MTH and MTH.GetModuleCharSavedVariables then
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
local function ensureSection(name, sectionTitle, yOffset, height) if type(moduleStore) == "table" then
local section = getglobal(name) moduleStore.scorpokDrazial = store.scorpokDrazial and true or false
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
end end
local module = MTH and MTH.GetModule and MTH:GetModule("autoquest") end
if module and module.SetScorpokDrazialEnabled then local module = MTH and MTH.GetModule and MTH:GetModule("autoquest")
module:SetScorpokDrazialEnabled(enabled) 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 end,
})
local tooltipToggle = ensureCheckbox( -- Arrows Are For Sissies (right column)
scorpokSection, local sissies = panel:Box("right", "MetaHuntAutoQuestSissiesBox", "Arrows Are For Sissies")
"MetaHuntOptionsAutoQuestScorpokTooltipToggle", sissies:Note("MetaHuntOptionsAutoQuestSissiesNote",
"Enhance Tooltip on Drazial and related beasts (requires Tooltips module enabled)", "Note that you should not activate this if you are using LazyPig", { lines = 2 })
-42, sissies:Checkbox("MetaHuntOptionsAutoQuestSissiesToggle",
store.scorpokTooltip and true or false "Enable SHIFT-rightclick for Artilleryman Sheldonore", {
) checked = store.arrowsForSissies and true or false,
if tooltipToggle then onClick = function()
tooltipToggle:SetScript("OnClick", function() local enabled = MTH_AQ_IsChecked(this)
local enabled = MTH_AQ_IsChecked(this) store.arrowsForSissies = enabled and true or false
store.scorpokTooltip = enabled and true or false if MTH and MTH.GetModuleCharSavedVariables then
if MTH and MTH.GetModuleCharSavedVariables then local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest") if type(moduleStore) == "table" then
if type(moduleStore) == "table" then moduleStore.arrowsForSissies = store.arrowsForSissies and true or false
moduleStore.scorpokTooltip = store.scorpokTooltip and true or false
end
end end
end) end
end local module = MTH and MTH.GetModule and MTH:GetModule("autoquest")
end if module and module.SetArrowsForSissiesEnabled then
module:SetArrowsForSissiesEnabled(enabled)
end
end,
})
local sissiesSection = ensureSection("MetaHuntAutoQuestSissiesBox", "Arrows Are For Sissies", -255, 108) panel:Finish()
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
end end
+137 -176
View File
@@ -358,25 +358,14 @@ local function MTH_CHRON_NormalizeSection(tabKey)
return "general" return "general"
end end
local function MTH_CHRON_RenderTimerSection(container, profile, title, items, bucket, opts) local function MTH_CHRON_RenderTimerBox(box, profile, items, bucket, prefix)
opts = opts or {} prefix = tostring(prefix or "Main")
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
if table.getn(items) == 0 then if table.getn(items) == 0 then
MTH_CHRON_MakeSmall(container, "MetaHuntOptionsChronometerSectionEmpty" .. prefix, "(none)", timerX + 8, timerY) box:Text("MetaHuntOptionsChronometerSectionEmpty" .. prefix, "(none)")
return return
end end
for i = 1, table.getn(items) do 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 row = items[i]
local timerName = row local timerName = row
local label = row local label = row
@@ -387,11 +376,9 @@ local function MTH_CHRON_RenderTimerSection(container, profile, title, items, bu
timerName = tostring(timerName or "") timerName = tostring(timerName or "")
label = tostring(label or timerName) label = tostring(label or timerName)
local controlName = "MetaHuntOptionsChronometerTimer" .. prefix .. tostring(bucket) .. tostring(i) local controlName = "MetaHuntOptionsChronometerTimer" .. prefix .. tostring(bucket) .. tostring(i)
local check = MTH_CreateCheckbox(container, controlName, label, timerY, timerX) box:Checkbox(controlName, label, {
if check then checked = profile.disabledSpells[bucket][timerName] == nil,
check:SetChecked(profile.disabledSpells[bucket][timerName] == nil and true or false) onClick = function()
check:SetScript("OnClick", function()
if not this then return end
local currentlyDisabled = profile.disabledSpells[bucket][timerName] ~= nil local currentlyDisabled = profile.disabledSpells[bucket][timerName] ~= nil
if currentlyDisabled then if currentlyDisabled then
profile.disabledSpells[bucket][timerName] = nil profile.disabledSpells[bucket][timerName] = nil
@@ -402,9 +389,8 @@ local function MTH_CHRON_RenderTimerSection(container, profile, title, items, bu
end end
MTH_CHRON_ApplyLiveProfile(profile) MTH_CHRON_ApplyLiveProfile(profile)
end) end,
end })
timerY = timerY - 20
end end
end end
@@ -461,210 +447,185 @@ function MTH_SetupChronometerOptions(tabKey)
local container = MTH_GetFrame("MetaHuntOptionsChronometer") local container = MTH_GetFrame("MetaHuntOptionsChronometer")
if not container then return end if not container then return end
MTH_ClearContainer(container)
MTH_CHRON_STATE.controls = {} MTH_CHRON_STATE.controls = {}
local profile = MTH_CHRON_GetProfile() local profile = MTH_CHRON_GetProfile()
local _, class = UnitClass("player") local _, class = UnitClass("player")
class = class or "HUNTER" 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) local moduleEnabled = false
if moduleCheck then do
local module = MTH and MTH:GetModule("chronometer") local module = MTH and MTH:GetModule("chronometer")
moduleCheck:SetChecked(module and module.enabled and true or false) moduleEnabled = module and module.enabled and true or false
moduleCheck:SetScript("OnClick", function() end
if not this then return end panel:TopCheckbox("MetaHuntOptionsChronometerEnabled", "Enable Chronometer module", {
local enabled = MTH_CHRON_IsChecked(this) checked = moduleEnabled,
onClick = function()
local enabled = this:GetChecked() == 1
if MTH and MTH.SetModuleEnabled then if MTH and MTH.SetModuleEnabled then
MTH:SetModuleEnabled("chronometer", enabled) MTH:SetModuleEnabled("chronometer", enabled)
end end
end) end,
end })
if section == "general" then if section == "general" then
MTH_CHRON_MakeTitle(container, "MetaHuntOptionsChronometerGeneralHeader", "General", 20, -84) local genBox = panel:Box("left", "MetaHuntOptionsChronometerGeneralBox", "General")
genBox:Slider("MetaHuntOptionsChronometerGhost", {
local ghostSlider = MTH_CreateSlider(container, "MetaHuntOptionsChronometerGhost", "Ghost Duration", 0, 30, 1, -112) label = "Ghost Duration", min = 0, max = 30, step = 1,
if ghostSlider then value = tonumber(profile.ghost) or 0,
ghostSlider:SetValue(tonumber(profile.ghost) or 0) onChange = function(value)
ghostSlider.onChange = function(value)
profile.ghost = tonumber(value) or 0 profile.ghost = tonumber(value) or 0
MTH_CHRON_ApplyLiveProfile(profile) MTH_CHRON_ApplyLiveProfile(profile)
end end,
end })
genBox:Checkbox("MetaHuntOptionsChronometerFadeOnKill", "Fade on kill", {
local killCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerFadeOnKill", "Fade on kill", -154) checked = profile.fadeonkill and true or false,
if killCheck then onClick = function() profile.fadeonkill = this:GetChecked() == 1 end,
killCheck:SetChecked(profile.fadeonkill and true or false) })
killCheck:SetScript("OnClick", function() genBox:Checkbox("MetaHuntOptionsChronometerFadeOnFade", "Fade on aura fade", {
if not this then return end checked = profile.fadeonfade and true or false,
profile.fadeonkill = MTH_CHRON_IsChecked(this) onClick = function() profile.fadeonfade = this:GetChecked() == 1 end,
end) })
end genBox:Checkbox("MetaHuntOptionsChronometerSelfBars", "Show self bars", {
checked = profile.selfbars and true or false,
local fadeCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerFadeOnFade", "Fade on aura fade", -179) onClick = function() profile.selfbars = this:GetChecked() == 1 end,
if fadeCheck then })
fadeCheck:SetChecked(profile.fadeonfade and true or false) genBox:Checkbox("MetaHuntOptionsChronometerOnlySelf", "Only self target", {
fadeCheck:SetScript("OnClick", function() checked = profile.onlyself and true or false,
if not this then return end onClick = function() profile.onlyself = this:GetChecked() == 1 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
elseif section == "bar" then elseif section == "bar" then
MTH_CHRON_MakeTitle(container, "MetaHuntOptionsChronometerBarHeader", "Bars", 20, -84) local ctrlBox = panel:Box("left", "MetaHuntOptionsChronometerControlsBox", "Controls")
ctrlBox:Buttons({
local runTestButton = MTH_CreateActionButton(container, "MetaHuntOptionsChronometerRunTest", "Run Test", 20, -112, 130, 22, function() { name = "MetaHuntOptionsChronometerRunTest", label = "Run Test", width = 120,
local engine = MTH_ChronometerHunter onClick = function()
if engine and engine.RunTest then local engine = MTH_ChronometerHunter
engine:RunTest() if engine and engine.RunTest then engine:RunTest() end
end end },
end) { name = "MetaHuntOptionsChronometerAnchor", label = "Toggle Anchor", width = 120,
local anchorButton = MTH_CreateActionButton(container, "MetaHuntOptionsChronometerAnchor", "Toggle Anchor", 165, -112, 130, 22, function() onClick = function()
local engine = MTH_ChronometerHunter local engine = MTH_ChronometerHunter
if engine and engine.ToggleAnchor then if engine and engine.ToggleAnchor then engine:ToggleAnchor() end
engine:ToggleAnchor() end },
end })
end)
if runTestButton then runTestButton:Show() end
if anchorButton then anchorButton:Show() end
local anchorX = tonumber(profile.barposition and profile.barposition.x) or 0 local anchorX = tonumber(profile.barposition and profile.barposition.x) or 0
local anchorY = tonumber(profile.barposition and profile.barposition.y) 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) local dimBox = panel:Box("left", "MetaHuntOptionsChronometerDimBox", "Dimensions")
if widthSlider then dimBox:Slider("MetaHuntOptionsChronometerBarWidth", {
widthSlider:SetValue(tonumber(profile.barwidth) or 220) label = "Bar Width", min = 80, max = 320, step = 1,
widthSlider.onChange = function(value) value = tonumber(profile.barwidth) or 220,
onChange = function(value)
profile.barwidth = tonumber(value) or 220 profile.barwidth = tonumber(value) or 220
MTH_CHRON_ApplyLiveProfile(profile) MTH_CHRON_ApplyLiveProfile(profile)
end end,
end })
dimBox:Slider("MetaHuntOptionsChronometerBarScale", {
local scaleSlider = MTH_CreateSlider(container, "MetaHuntOptionsChronometerBarScale", "Bar Scale", 0.5, 1.5, 0.1, -222) label = "Bar Scale", min = 0.5, max = 1.5, step = 0.1,
if scaleSlider then value = tonumber(profile.barscale) or 1,
scaleSlider:SetValue(tonumber(profile.barscale) or 1) format = function(v) return string.format("%.1f", v) end,
scaleSlider.onChange = function(value) onChange = function(value)
profile.barscale = tonumber(value) or 1 profile.barscale = tonumber(value) or 1
MTH_CHRON_ApplyLiveProfile(profile) MTH_CHRON_ApplyLiveProfile(profile)
end end,
end })
dimBox:Slider("MetaHuntOptionsChronometerBarHeight", {
local heightSlider = MTH_CreateSlider(container, "MetaHuntOptionsChronometerBarHeight", "Bar Height", 8, 30, 1, -264) label = "Bar Height", min = 8, max = 30, step = 1,
if heightSlider then value = tonumber(profile.barheight) or 16,
heightSlider:SetValue(tonumber(profile.barheight) or 16) onChange = function(value)
heightSlider.onChange = function(value)
profile.barheight = tonumber(value) or 16 profile.barheight = tonumber(value) or 16
MTH_CHRON_ApplyLiveProfile(profile) MTH_CHRON_ApplyLiveProfile(profile)
end end,
end })
dimBox:Slider("MetaHuntOptionsChronometerBarSpacing", {
local spacingSlider = MTH_CreateSlider(container, "MetaHuntOptionsChronometerBarSpacing", "Bar Spacing", 0, 15, 1, -306) label = "Bar Spacing", min = 0, max = 15, step = 1,
if spacingSlider then value = tonumber(profile.spacing) or 0,
spacingSlider:SetValue(tonumber(profile.spacing) or 0) onChange = function(value)
spacingSlider.onChange = function(value)
profile.spacing = tonumber(value) or 0 profile.spacing = tonumber(value) or 0
MTH_CHRON_ApplyLiveProfile(profile) MTH_CHRON_ApplyLiveProfile(profile)
end end,
end })
dimBox:Slider("MetaHuntOptionsChronometerTextSize", {
local textSizeSlider = MTH_CreateSlider(container, "MetaHuntOptionsChronometerTextSize", "Text Size", 8, 20, 1, -348) label = "Text Size", min = 8, max = 20, step = 1,
if textSizeSlider then value = tonumber(profile.textsize) or 10,
textSizeSlider:SetValue(tonumber(profile.textsize) or 10) onChange = function(value)
textSizeSlider.onChange = function(value)
profile.textsize = tonumber(value) or 10 profile.textsize = tonumber(value) or 10
MTH_CHRON_ApplyLiveProfile(profile) MTH_CHRON_ApplyLiveProfile(profile)
end end,
end })
MTH_CHRON_MakeSmall(container, "MetaHuntOptionsChronometerTextPatternLabel", "Bar Text ($s spell, $t target)", 20, -390) local textBox = panel:Box("right", "MetaHuntOptionsChronometerTextBox", "Text & Growth")
MTH_CHRON_MakeInput(container, "MetaHuntOptionsChronometerTextPattern", 20, -408, 220, 20, profile.text or "$t", function(newText) textBox:Note("MetaHuntOptionsChronometerTextPatternHint",
if not newText or newText == "" then "Bar text tokens: $s = spell, $t = target", { lines = 2 })
newText = "$t" local patternEdit = textBox:EditRow("MetaHuntOptionsChronometerTextPatternLabel", "Bar Text",
end "MetaHuntOptionsChronometerTextPattern", 150, { height = 20 })
profile.text = tostring(newText) if patternEdit then
MTH_CHRON_ApplyLiveProfile(profile) patternEdit:SetText(tostring(profile.text or "$t"))
end) patternEdit:SetScript("OnEnterPressed", function()
local newText = this:GetText() or ""
local growCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerGrowUp", "Grow bars upward", -438) if newText == "" then newText = "$t" end
if growCheck then profile.text = tostring(newText)
growCheck:SetChecked(profile.growup and true or false)
growCheck:SetScript("OnClick", function()
if not this then return end
profile.growup = MTH_CHRON_IsChecked(this)
MTH_CHRON_ApplyLiveProfile(profile) MTH_CHRON_ApplyLiveProfile(profile)
this:ClearFocus()
end) end)
end end
textBox:Checkbox("MetaHuntOptionsChronometerGrowUp", "Grow bars upward", {
local reverseCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerReverse", "Reverse bars", -463) checked = profile.growup and true or false,
if reverseCheck then onClick = function()
reverseCheck:SetChecked(profile.reverse and true or false) profile.growup = this:GetChecked() == 1
reverseCheck:SetScript("OnClick", function()
if not this then return end
profile.reverse = MTH_CHRON_IsChecked(this)
MTH_CHRON_ApplyLiveProfile(profile) 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 iconBox = panel:Box("right", "MetaHuntOptionsChronometerIconBox", "Icon Position")
local iconLeft = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerIconLeft", "Left", -514) local iconLeft, iconRight
local iconRight = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerIconRight", "Right", -538) iconLeft = iconBox:Checkbox("MetaHuntOptionsChronometerIconLeft", "Left", {
if iconLeft and iconRight then checked = profile.iconposition ~= "RIGHT",
iconLeft:SetChecked(profile.iconposition ~= "RIGHT") onClick = function()
iconRight:SetChecked(profile.iconposition == "RIGHT")
iconLeft:SetScript("OnClick", function()
profile.iconposition = "LEFT" profile.iconposition = "LEFT"
iconLeft:SetChecked(true) iconLeft:SetChecked(true)
iconRight:SetChecked(nil) iconRight:SetChecked(nil)
MTH_CHRON_ApplyLiveProfile(profile) MTH_CHRON_ApplyLiveProfile(profile)
end) end,
iconRight:SetScript("OnClick", function() })
iconRight = iconBox:Checkbox("MetaHuntOptionsChronometerIconRight", "Right", {
checked = profile.iconposition == "RIGHT",
onClick = function()
profile.iconposition = "RIGHT" profile.iconposition = "RIGHT"
iconRight:SetChecked(true) iconRight:SetChecked(true)
iconLeft:SetChecked(nil) iconLeft:SetChecked(nil)
MTH_CHRON_ApplyLiveProfile(profile) MTH_CHRON_ApplyLiveProfile(profile)
end) end,
end })
else else
local classSpells, classEvents, racial = MTH_CHRON_BuildTimerLists() local classSpells, classEvents, racial = MTH_CHRON_BuildTimerLists()
if section == "classspells" then if section == "classspells" then
MTH_CHRON_RenderTimerSection(container, profile, "Hunter Spells", classSpells, class, { local spellsBox = panel:Box("left", "MetaHuntOptionsChronometerSpellsBox", "Hunter Spells")
x = 20, MTH_CHRON_RenderTimerBox(spellsBox, profile, classSpells, class, "ClassSpells")
y = -84, local trinketBox = panel:Box("right", "MetaHuntOptionsChronometerTrinketsBox", "Hunter Trinkets")
prefix = "ClassSpells", MTH_CHRON_RenderTimerBox(trinketBox, profile, MTH_CHRON_BuildHunterTrinketItems(classEvents), class, "ClassTrinkets")
})
MTH_CHRON_RenderTimerSection(container, profile, "Hunter Trinkets", MTH_CHRON_BuildHunterTrinketItems(classEvents), class, {
x = 300,
y = -84,
prefix = "ClassTrinkets",
})
elseif section == "classevents" then 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 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
end end
panel:Finish()
end end
if _G then if _G then
+5 -9
View File
@@ -96,12 +96,8 @@ function MTH_SetupCreditsOptions()
local container = MTH_GetFrame("MetaHuntOptionsCredits") local container = MTH_GetFrame("MetaHuntOptionsCredits")
if not container then return end if not container then return end
MTH_ClearContainer(container) local panel = MTH_Layout.Panel(container)
local title = panel:Title(MTH_CR_L("CREDITS_TITLE", "Credits"))
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 scrollFrame = MTH_GetFrame("MetaHuntOptionsCreditsScroll") local scrollFrame = MTH_GetFrame("MetaHuntOptionsCreditsScroll")
if not scrollFrame then if not scrollFrame then
@@ -124,12 +120,12 @@ function MTH_SetupCreditsOptions()
cursor = MTH_CreditsCreateText(content, cursor, cursor = MTH_CreditsCreateText(content, cursor,
MTH_CR_L("CREDITS_ABOUT_CODE_INTRO", 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" "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) "GameFontNormalSmall", -10)
cursor = MTH_CreditsCreateText(content, cursor, cursor = MTH_CreditsCreateText(content, cursor,
MTH_CR_L("CREDITS_ABOUT_ZHUNTER", 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) "GameFontNormalSmall", -10)
cursor = MTH_CreditsCreateText(content, cursor, cursor = MTH_CreditsCreateText(content, cursor,
@@ -189,7 +185,7 @@ function MTH_SetupCreditsOptions()
"GameFontNormalSmall", -10) "GameFontNormalSmall", -10)
cursor = MTH_CreditsCreateText(content, cursor, 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) "GameFontNormalSmall", -10, 1.00, 0.82, 0.00)
cursor = MTH_CreditsCreateText(content, cursor, 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 {} return MTH_SavedVariables.modules["expammo"] or {}
end end
local MTH_EA_OPT_built = false
local MTH_EA_OPT_STATE = { bindStatus = nil, bindButton = nil, captureFrame = nil } 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() local function MTH_EA_OPT_GetBindText()
if not GetBindingKey then return "Unbound" end if not GetBindingKey then return "Unbound" end
local k1, k2 = GetBindingKey("EXPAMMO ACTION") local k1, k2 = GetBindingKey("EXPAMMO ACTION")
@@ -119,271 +110,168 @@ local function MTH_EA_OPT_StartCapture()
if bb then bb:SetText("Press key...") end if bb then bb:SetText("Press key...") end
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) 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 cfg = MTH_EA_OPT_GetCfg()
local showHint = cfg.showHint ~= false local showHint = cfg.showHint ~= false
--------------------------------------------------------------------------- local panel = MTH_Layout.Panel(container)
-- Title panel:Title("MM Widget — Experimental Ammunition Tracker")
---------------------------------------------------------------------------
local title = container:CreateFontString(nil, "ARTWORK", "GameFontHighlightLarge")
title:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_L, -16)
title:SetText("MM Widget — Experimental Ammunition Tracker")
--------------------------------------------------------------------------- -- Right-column gating: dim the box frames and disable their interactive
-- LEFT COLUMN -- controls when the "Show action hint cell" checkbox is off.
--------------------------------------------------------------------------- local rightBoxes = {}
local rightControls = {}
-- ── Module ────────────────────────────────────────────── local function setRightEnabled(enabled)
MTH_EA_OPT_Header(container, "Module", -46) 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 local moduleEnabled = true
if MTH and MTH.IsModuleEnabled then if MTH and MTH.IsModuleEnabled then
moduleEnabled = MTH:IsModuleEnabled("expammo", true) and true or false moduleEnabled = MTH:IsModuleEnabled("expammo", true) and true or false
end end
MTH_EA_OPT_CB(container, "MTH_ExpAmmoModuleCB", moduleBox:Checkbox("MTH_ExpAmmoModuleCB", "Enable MM Widget module", {
"Enable MM Widget module", checked = moduleEnabled,
-66, OPT_L, moduleEnabled, onClick = function()
function(v) local v = this:GetChecked() == 1
if MTH and MTH.SetModuleEnabled then MTH:SetModuleEnabled("expammo", v) end if MTH and MTH.SetModuleEnabled then MTH:SetModuleEnabled("expammo", v) end
if MTH_ExpAmmo then MTH_ExpAmmo.SetEnabled(v) end if MTH_ExpAmmo then MTH_ExpAmmo.SetEnabled(v) end
end) end,
})
-- ── Tracker Visibility ─────────────────────────────────── -- ===== LEFT: Tracker Visibility =====
MTH_EA_OPT_Header(container, "Tracker Visibility", -100) local visBox = panel:Box("left", "MTH_ExpAmmoVisBox", "Tracker Visibility")
visBox:Checkbox("MTH_ExpAmmoShowLnLCB", "Show Lock and Load cell (top)", {
MTH_EA_OPT_CB(container, "MTH_ExpAmmoShowLnLCB", checked = cfg.showLnL ~= false,
"Show Lock and Load cell (top)", onClick = function() if MTH_ExpAmmo then MTH_ExpAmmo.SetShowLnL(this:GetChecked() == 1) end end,
-120, OPT_L, cfg.showLnL ~= false, })
function(v) if MTH_ExpAmmo then MTH_ExpAmmo.SetShowLnL(v) end end) visBox:Checkbox("MTH_ExpAmmoShowHintCB", "Show action hint cell (bottom)", {
checked = showHint,
-- "Show action hint cell" also gates the right column onClick = function()
local rightGroup = {} -- filled below; toggled when this CB changes local v = this:GetChecked() == 1
local showHintCB = MTH_EA_OPT_CB(container, "MTH_ExpAmmoShowHintCB",
"Show action hint cell (bottom)",
-144, OPT_L, showHint,
function(v)
if MTH_ExpAmmo then MTH_ExpAmmo.SetShowHint(v) end if MTH_ExpAmmo then MTH_ExpAmmo.SetShowHint(v) end
MTH_EA_OPT_SetGroupEnabled(rightGroup, v) setRightEnabled(v)
end) 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", -- ===== LEFT: Appearance =====
"Hide widget when out of combat", local appBox = panel:Box("left", "MTH_ExpAmmoAppBox", "Appearance")
-168, OPT_L, cfg.hideOOC == true, appBox:Slider("MTH_ExpAmmoCellSizeSlider", {
function(v) if MTH_ExpAmmo then MTH_ExpAmmo.SetHideOOC(v) end end) 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 ─────────────────────────────────────────── -- ===== LEFT: Position =====
MTH_EA_OPT_Header(container, "Appearance", -202) local posBox = panel:Box("left", "MTH_ExpAmmoPosBox", "Position")
posBox:Button("MTH_ExpAmmoToggleAnchor", "Toggle Anchor", {
local sizeSlider = MTH_CreateSlider(container, "MTH_ExpAmmoCellSizeSlider", width = 130,
"Cell Size (px)", 20, 80, 4, -222) onClick = function() if MTH_ExpAmmo then MTH_ExpAmmo.ToggleAnchor() end end,
if sizeSlider then })
sizeSlider:ClearAllPoints() posBox:Note("MTH_ExpAmmoPosNote",
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,
"Shows 4 drag handles around the widget (top / bottom / left / right). Drag any one to reposition it.", "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: Smart Action Cell (helper + keybind + casting) =====
-- RIGHT COLUMN — Action Hint Cell (keybind + casting) -- One feature = one box. The intro notes explain the bottom cell, and the
-- All widgets here are greyed out when the bottom cell is hidden. -- 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())
-- Vertical divider line cellBox:Text("MTH_ExpAmmoHintSub",
local divider = container:CreateTexture(nil, "BACKGROUND") "Options below apply to the bottom cell only. Disable \"Show action hint cell\" to hide the cell and these controls.",
divider:SetTexture(0.3, 0.3, 0.3, 0.6) { color = { 1, 1, 1 }, lines = 3 })
divider:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_R - 10, -46) cellBox:Note("MTH_ExpAmmoHintNam",
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,
"Notes:\n - You need NAMPOWER for this to work reliably.\n - Aimed/Steady/Multi/Arcane Shots SHOULD BE on your action bars.", "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) { lines = 3 })
if rNamPowerTip then rNamPowerTip:SetWidth(290) end
table.insert(rightGroup, rNamPowerTip)
-- ── Keybind ────────────────────────────────────────────── -- Keybind sub-section
table.insert(rightGroup, MTH_EA_OPT_Header(container, "Keybind", -182, OPT_R)) 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, -- Casting sub-section
"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.", cellBox:Gap(4)
-200, OPT_R, 0.65, 0.65, 0.65) cellBox:Text("MTH_ExpAmmoCastHead", "Casting",
if bindTip then bindTip:SetWidth(290) end { font = MTH_Layout.Theme.fontBoxTitle, color = MTH_Layout.Theme.colPanelTitle })
table.insert(rightGroup, bindTip) 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") -- ===== RIGHT: Rotation =====
bindStatus:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_R, -248) local rotBox = panel:Box("right", "MTH_ExpAmmoRotBox", "Rotation")
bindStatus:SetText("Key: " .. MTH_EA_OPT_GetBindText()) table.insert(rightBoxes, rotBox:Frame())
MTH_EA_OPT_STATE.bindStatus = bindStatus rotBox:Note("MTH_ExpAmmoRotTip",
table.insert(rightGroup, bindStatus) "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") panel:Finish()
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)
local clearButton = CreateFrame("Button", "MTH_ExpAmmoBindClear", container, "UIPanelButtonTemplate") -- Apply initial gating state.
clearButton:SetPoint("LEFT", bindButton, "RIGHT", 6, 0) setRightEnabled(showHint)
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)
end end
function MTH_SetupExpAmmoOptions() 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 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 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() function MTH_SetupFeedOMaticOptions()
if not MTH_FOM_READY then return end if not MTH_FOM_READY then return end
local container = MTH_GetFrame("MetaHuntOptionsFeedOMatic") local container = MTH_GetFrame("MetaHuntOptionsFeedOMatic")
if not container then return end if not container then return end
local rightColumnX = 300
local yAdjust = -64
MTH_ClearContainer(container)
MTH_FOM_STATE.ctrl = {} MTH_FOM_STATE.ctrl = {}
local title = container:CreateFontString("MetaHuntOptionsFeedOMaticTitle", "ARTWORK", "GameFontHighlight") local panel = MTH_Layout.Panel(container)
title:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -10) panel:Title(MTH_FOM_L("FOM_TITLE", "Feed-O-Matic"))
title:SetText(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") MTH_FOM_STATE.enableCheck = panel:TopCheckbox("MetaHuntOptionsFeedOMaticEnabled",
statusNotice:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -34) MTH_FOM_L("FOM_ENABLE_MODULE", "Enable FeedOMatic module"), {
statusNotice:SetWidth(600) onClick = function()
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()
if not this then return end if not this then return end
local enabled = this:GetChecked() == 1 local enabled = this:GetChecked() == 1
if MTH and MTH.SetModuleEnabled then if MTH and MTH.SetModuleEnabled then
@@ -276,125 +270,113 @@ function MTH_SetupFeedOMaticOptions()
end end
end end
MTH_RefreshFeedOMaticOptions() MTH_RefreshFeedOMaticOptions()
end) end,
MTH_FOM_STATE.enableCheck = moduleCheck })
end
local leftHeader = container:CreateFontString("MetaHuntOptionsFeedOMaticGeneralHeader", "ARTWORK", "GameFontHighlight") -- ===== General (left column) =====
leftHeader:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -62 + yAdjust) local general = panel:Box("left", "MetaHuntOptionsFOMGeneralBox", MTH_FOM_L("FOM_HEADER_GENERAL", "General"))
leftHeader:SetText(MTH_FOM_L("FOM_HEADER_GENERAL", "General"))
local bindStatus = container:CreateFontString("MetaHuntOptionsFOMBindStatus", "ARTWORK", "GameFontNormalSmall") MTH_FOM_STATE.bindStatus = general:Text("MetaHuntOptionsFOMBindStatus",
bindStatus:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -80 + yAdjust) string.format(MTH_FOM_L("FOM_BIND_STATUS_VALUE", "Feed key: %s"), MTH_FOM_GetBindingDisplayText()))
bindStatus:SetText(string.format(MTH_FOM_L("FOM_BIND_STATUS_VALUE", "Feed key: %s"), MTH_FOM_GetBindingDisplayText()))
MTH_FOM_STATE.bindStatus = bindStatus
local bindButton = CreateFrame("Button", "MetaHuntOptionsFOMBindButton", container, "UIPanelButtonTemplate") local bindButtons = general:Buttons({
bindButton:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -100 + yAdjust) { name = "MetaHuntOptionsFOMBindButton", label = MTH_FOM_L("FOM_BIND_SET_KEY", "Set Key"), width = 90,
bindButton:SetWidth(90) onClick = function()
bindButton:SetHeight(22) if MTH_FOM_STATE.captureFrame and MTH_FOM_STATE.captureFrame:IsShown() then
bindButton:SetText(MTH_FOM_L("FOM_BIND_SET_KEY", "Set Key")) MTH_FOM_StopBindingCapture()
bindButton:SetScript("OnClick", function() else
if MTH_FOM_STATE.captureFrame and MTH_FOM_STATE.captureFrame:IsShown() then MTH_FOM_StartBindingCapture()
MTH_FOM_StopBindingCapture() end
else end },
MTH_FOM_StartBindingCapture() { name = "MetaHuntOptionsFOMBindClearButton", label = MTH_FOM_L("FOM_BIND_CLEAR", "Clear"), width = 70,
end onClick = function() MTH_FOM_SaveBinding(nil) end },
end) })
MTH_FOM_STATE.bindButton = bindButton MTH_FOM_STATE.bindButton = bindButtons[1]
MTH_FOM_STATE.bindClearButton = bindButtons[2]
local bindClearButton = CreateFrame("Button", "MetaHuntOptionsFOMBindClearButton", container, "UIPanelButtonTemplate") general:Note("MetaHuntOptionsFOMBindHint",
bindClearButton:SetPoint("LEFT", bindButton, "RIGHT", 8, 0) 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 })
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
local bindHint = container:CreateFontString("MetaHuntOptionsFOMBindHint", "ARTWORK", "GameFontNormalSmall") MTH_FOM_STATE.ctrl.AvoidQuestFood = general:Checkbox("MetaHuntOptionsFOMAvoidQuest",
bindHint:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -128 + yAdjust) MTH_FOM_Label("AvoidQuestFood", "FOM_LABEL_AVOID_QUEST_FOODS", "Avoid quest foods"),
bindHint:SetWidth(360) { onClick = function() if not this then return end FOM_Config.AvoidQuestFood = this:GetChecked() == 1 end })
bindHint:SetJustifyH("LEFT") MTH_FOM_STATE.ctrl.AvoidBonusFood = general:Checkbox("MetaHuntOptionsFOMAvoidBonus",
bindHint:SetJustifyV("TOP") MTH_FOM_Label("AvoidBonusFood", "FOM_LABEL_AVOID_BONUS_FOODS", "Avoid bonus foods"),
bindHint:SetTextColor(0.35, 0.65, 1) { onClick = function() if not this then return end FOM_Config.AvoidBonusFood = this:GetChecked() == 1 end })
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.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.keepOpenEdit = general:EditRow("MetaHuntOptionsFOMKeepOpenLabel",
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_L("FOM_KEEP_OPEN_BAG_SLOTS", "Keep open bag slots:"),
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) "MetaHuntOptionsFOMKeepOpen", 40, {
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) 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 -- ===== Notify when feeding (left column) =====
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 local notify = panel:Box("left", "MetaHuntOptionsFOMNotifyBox", MTH_FOM_L("FOM_HEADER_NOTIFY_WHEN_FEEDING", "Notify when feeding"))
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 MTH_FOM_STATE.ctrl.AlertEmote = notify:Checkbox("MetaHuntOptionsFOMAlertEmote",
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 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") -- ===== Avoid foods used in cooking (right column) =====
keepOpenLabel:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -302 + yAdjust) local avoid = panel:Box("right", "MetaHuntOptionsFOMAvoidBox", MTH_FOM_L("FOM_HEADER_AVOID_FOODS_USED_IN_COOKING", "Avoid foods used in cooking"))
keepOpenLabel:SetText(MTH_FOM_L("FOM_KEEP_OPEN_BAG_SLOTS", "Keep open bag slots:")) 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") -- ===== Warn when pet needs feeding (right column) =====
keepOpen:SetPoint("LEFT", keepOpenLabel, "RIGHT", 8, 0) local warn = panel:Box("right", "MetaHuntOptionsFOMWarnBox", MTH_FOM_L("FOM_HEADER_WARN_WHEN_PET_NEEDS_FEEDING", "Warn when pet needs feeding"))
keepOpen:SetWidth(40) MTH_FOM_STATE.ctrl.LevelContent = warn:Checkbox("MetaHuntOptionsFOMLevelContent",
keepOpen:SetHeight(20) MTH_FOM_Label("LevelContent", "FOM_LABEL_WARN_WHEN_CONTENT", "When content"),
keepOpen:SetNumeric(true) { onClick = function() MTH_FOM_SetLevel("content"); MTH_RefreshFeedOMaticOptions() end })
keepOpen:SetAutoFocus(false) MTH_FOM_STATE.ctrl.LevelUnhappy = warn:Checkbox("MetaHuntOptionsFOMLevelUnhappy",
keepOpen:SetScript("OnTextChanged", function() MTH_FOM_Label("LevelUnhappy", "FOM_LABEL_WARN_WHEN_UNHAPPY", "When unhappy"),
if not this then return end { onClick = function() MTH_FOM_SetLevel("unhappy"); MTH_RefreshFeedOMaticOptions() end })
local value = tonumber(this:GetText()) or 0 MTH_FOM_STATE.ctrl.LevelOff = warn:Checkbox("MetaHuntOptionsFOMLevelOff",
FOM_Config.KeepOpenSlots = value MTH_FOM_Label("LevelOff", "FOM_LABEL_DONT_WARN", "Don't warn"),
end) { onClick = function() MTH_FOM_SetLevel("off"); MTH_RefreshFeedOMaticOptions() 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
local notifyHeader = container:CreateFontString("MetaHuntOptionsFOMNotifyHeader", "ARTWORK", "GameFontHighlight") warn:Gap(6)
notifyHeader:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -336 + yAdjust)
notifyHeader:SetText(MTH_FOM_L("FOM_HEADER_NOTIFY_WHEN_FEEDING", "Notify when feeding"))
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.AudioWarning = warn:Checkbox("MetaHuntOptionsFOMAudioWarning",
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_Label("AudioWarning", "FOM_LABEL_PLAY_SOUND", "Play sound"),
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) { 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 })
if MTH_FOM_STATE.ctrl.AlertEmote then MTH_FOM_STATE.ctrl.AlertEmote:SetScript("OnClick", function() MTH_FOM_SetAlert("emote"); MTH_RefreshFeedOMaticOptions() end) end MTH_FOM_STATE.ctrl.AudioWarningBell = warn:Checkbox("MetaHuntOptionsFOMAudioWarningBell",
if MTH_FOM_STATE.ctrl.AlertChat then MTH_FOM_STATE.ctrl.AlertChat:SetScript("OnClick", function() MTH_FOM_SetAlert("chat"); MTH_RefreshFeedOMaticOptions() end) end MTH_FOM_Label("AudioWarningBell", "FOM_LABEL_USE_BELL_SOUND", "Use bell sound"),
if MTH_FOM_STATE.ctrl.AlertNone then MTH_FOM_STATE.ctrl.AlertNone:SetScript("OnClick", function() MTH_FOM_SetAlert("none"); MTH_RefreshFeedOMaticOptions() end) end { 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",
local warnHeader = container:CreateFontString("MetaHuntOptionsFOMWarnHeader", "ARTWORK", "GameFontHighlight") MTH_FOM_Label("TextWarning", "FOM_LABEL_SHOW_TEXT", "Show text"),
warnHeader:SetPoint("TOPLEFT", container, "TOPLEFT", rightColumnX, -276 + yAdjust) { onClick = function() if not this then return end FOM_Config.TextWarning = this:GetChecked() == 1 end })
warnHeader:SetText(MTH_FOM_L("FOM_HEADER_WARN_WHEN_PET_NEEDS_FEEDING", "Warn when pet needs feeding")) MTH_FOM_STATE.ctrl.IconWarning = warn:Checkbox("MetaHuntOptionsFOMIconWarning",
MTH_FOM_Label("IconWarning", "FOM_LABEL_FLASH_ICON", "Flash icon"),
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) { onClick = function() if not this then return end FOM_Config.IconWarning = this:GetChecked() == 1 end })
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
panel:Finish()
MTH_RefreshFeedOMaticOptions() MTH_RefreshFeedOMaticOptions()
end end
+103 -195
View File
@@ -197,31 +197,25 @@ local function MTH_ICU_OpenColorPicker(colorKey)
ColorPickerFrame:Show() ColorPickerFrame:Show()
end end
local function MTH_ICU_CreateOptionRow(container, rowName, label, key, y, labelX, dropdownX) local function MTH_ICU_BuildUI(container)
labelX = labelX or MTH_ICU_LAYOUT.LEFT_X MTH_ICU_OPT_STATE.controls = {}
dropdownX = dropdownX or MTH_ICU_LAYOUT.LEFT_DROPDOWN_X MTH_ICU_OPT_STATE.container = container
MTH_ICU_OPT_STATE.built = true
local labelFs = container:CreateFontString(rowName .. "Label", "ARTWORK", "GameFontNormalSmall") local controls = MTH_ICU_OPT_STATE.controls
labelFs:SetPoint("TOPLEFT", container, "TOPLEFT", labelX, y)
labelFs:SetText(label)
local dropdown = CreateFrame("Frame", rowName .. "Drop", container, "UIDropDownMenuTemplate") local panel = MTH_Layout.Panel(container)
dropdown:ClearAllPoints() panel:Title("MTH ICU")
dropdown:SetPoint("TOPLEFT", container, "TOPLEFT", dropdownX, y + 12) 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.",
if UIDropDownMenu_SetWidth then { lines = 2 })
UIDropDownMenu_SetWidth(MTH_ICU_LAYOUT.DROPDOWN_WIDTH, dropdown)
end
if UIDropDownMenu_JustifyText then
UIDropDownMenu_JustifyText("LEFT", dropdown)
end
if UIDropDownMenu_Initialize then -- Standard UIDropDownMenu initialize factory for a stored option key.
UIDropDownMenu_Initialize(dropdown, function() local function makeInit(key)
return function()
local values = MTH_ICU_GetOptionValues(key) local values = MTH_ICU_GetOptionValues(key)
local store = MTH_ICU_GetStore() local store = MTH_ICU_GetStore()
local current = tostring(store[key] or "") local current = tostring(store[key] or "")
local infoFactory = UIDropDownMenu_CreateInfo local infoFactory = UIDropDownMenu_CreateInfo
for i = 1, table.getn(values) do for i = 1, table.getn(values) do
local optionValue = tostring(values[i]) local optionValue = tostring(values[i])
local info = type(infoFactory) == "function" and infoFactory() or {} 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.checked = optionValue == current and 1 or nil
info.func = function() info.func = function()
MTH_ICU_SetValue(key, optionValue) 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 end
if UIDropDownMenu_AddButton then UIDropDownMenu_AddButton(info) end if UIDropDownMenu_AddButton then UIDropDownMenu_AddButton(info) end
end end
end) end
end end
MTH_ICU_OPT_STATE.controls[key] = { -- ===== LEFT: Module =====
label = labelFs, local moduleBox = panel:Box("left", "MTH_ICUModuleBox", "Module")
dropdown = dropdown, controls.moduleEnabled = moduleBox:Checkbox("MetaHuntOptionsICUModuleEnabled", "Enable ICU module", {
} onClick = function()
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
if MTH and MTH.SetModuleEnabled then if MTH and MTH.SetModuleEnabled then
local ok, err = MTH:SetModuleEnabled("icu", this:GetChecked() == 1) local ok, err = MTH:SetModuleEnabled("icu", this:GetChecked() == 1)
if not ok and MTH and MTH.Print then if not ok and MTH and MTH.Print then
@@ -306,130 +247,97 @@ local function MTH_ICU_BuildUI(container)
end end
end end
MTH_RefreshICUOptions() MTH_RefreshICUOptions()
end) end,
MTH_ICU_OPT_STATE.controls.moduleEnabled = moduleEnabled })
end controls.mouseOver = moduleBox:Checkbox("MetaHuntOptionsICUMouseOver", "Enable CTRL mouseover scan", {
onClick = function()
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
local store = MTH_ICU_GetStore() local store = MTH_ICU_GetStore()
store.mouseOver = this:GetChecked() == 1 and true or false store.mouseOver = this:GetChecked() == 1 and true or false
end) end,
MTH_ICU_OPT_STATE.controls.mouseOver = mouseOver })
-- ===== 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 end
local sectionHeader = container:CreateFontString("MetaHuntOptionsICUSectionHeader", "ARTWORK", "GameFontHighlight") -- ===== RIGHT: Background Colors =====
sectionHeader:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_ICU_LAYOUT.LEFT_X, -146) local bgBox = panel:Box("right", "MTH_ICUBgBox", "Background Colors")
sectionHeader:SetText("General Settings") controls.PLAYER_COLOR_MODE = { dropdown = bgBox:Dropdown("MetaHuntOptionsICUPlayerColorModeDrop",
{ label = "Player colors", width = 130, initialize = makeInit("PLAYER_COLOR_MODE") }) }
MTH_ICU_CreateOptionRow(container, "MetaHuntOptionsICUAlert", "ALERT PVP", "ALERT", -172, MTH_ICU_LAYOUT.LEFT_X, MTH_ICU_LAYOUT.LEFT_DROPDOWN_X) controls.reactionOnlyPvp = bgBox:Checkbox("MetaHuntOptionsICUReactionOnlyPvp", "Reaction only when PvP-flagged", {
MTH_ICU_CreateOptionRow(container, "MetaHuntOptionsICUAnnounce", "ANNOUNCE on click", "ANNOUNCE", -198, MTH_ICU_LAYOUT.LEFT_X, MTH_ICU_LAYOUT.LEFT_DROPDOWN_X) onClick = function()
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
local store = MTH_ICU_GetStore() local store = MTH_ICU_GetStore()
store.REACTION_ONLY_PVP_PLAYERS = this:GetChecked() == 1 and true or false store.REACTION_ONLY_PVP_PLAYERS = this:GetChecked() == 1 and true or false
end) end,
MTH_ICU_OPT_STATE.controls.reactionOnlyPvp = reactionOnlyPvp })
end
local colorHeader = container:CreateFontString("MetaHuntOptionsICUColorsHeader", "ARTWORK", "GameFontHighlight") -- ===== RIGHT: Color Pickers =====
colorHeader:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_ICU_LAYOUT.RIGHT_X, -224) local colorBox = panel:Box("right", "MTH_ICUColorBox", "Color Pickers")
colorBox:Note("MetaHuntOptionsICUColorsScope",
local colorScope = container:CreateFontString("MetaHuntOptionsICUColorsScope", "ARTWORK", "GameFontNormalSmall") "Player pickers: REACTION / FACTION / CUSTOM\nNPC pickers: always", { lines = 2 })
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
for i = 1, table.getn(MTH_ICU_COLOR_ROWS) do for i = 1, table.getn(MTH_ICU_COLOR_ROWS) do
local row = MTH_ICU_COLOR_ROWS[i] 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) local btn, swatch = colorBox:ColorRow("MetaHuntOptionsICUColor" .. tostring(i), {
colorY = colorY - MTH_ICU_LAYOUT.COLOR_ROW_STEP 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 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 end
function MTH_RefreshICUOptions() 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 container then return end
if not gSetupDone then if not gSetupDone then
-- Title local panel = MTH_Layout.Panel(container)
local title = container:CreateFontString(nil, "ARTWORK", "GameFontNormal")
title:SetPoint("TOPLEFT", container, "TOPLEFT", 6, -6) -- Title (engine header, consistent gold styling)
title:SetText("Profiles") local title = panel:Title("Profiles")
title:SetTextColor(1.00, 0.82, 0.00)
-- Active profile indicator -- Active profile indicator
gActiveLabel = container:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall") 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 = MTH_OPTIONS_CONST or {}
MTH_OPTIONS_CONST.NAV_DEFAULT_WIDTH = MTH_OPTIONS_CONST.NAV_DEFAULT_WIDTH or 120 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.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_TOP_OFFSET = MTH_OPTIONS_CONST.CONTENT_TOP_OFFSET or -30
MTH_OPTIONS_CONST.CONTENT_HEIGHT = MTH_OPTIONS_CONST.CONTENT_HEIGHT or 566 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_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_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 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> <Frames>
<Frame name="$parentNav" enableMouse="true"> <Frame name="$parentNav" enableMouse="true">
<Size> <Size>
<AbsDimension x="120" y="566"/> <AbsDimension x="120" y="600"/>
</Size> </Size>
<Anchors> <Anchors>
<Anchor point="TOPLEFT"> <Anchor point="TOPLEFT">
<Offset> <Offset>
<AbsDimension x="12" y="-58"/> <AbsDimension x="12" y="-30"/>
</Offset> </Offset>
</Anchor> </Anchor>
</Anchors> </Anchors>
-18
View File
@@ -1,23 +1,5 @@
-- MetaHunt: auto-train Growl to a freshly tamed pet. -- 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 local MTH_GROWL_MAX_RANK = 7
+1
View File
@@ -14,6 +14,7 @@
<Include file="..\api\options-tree.lua"/> <Include file="..\api\options-tree.lua"/>
<Include file="..\api\options.xml"/> <Include file="..\api\options.xml"/>
<Include file="..\api\options.lua"/> <Include file="..\api\options.lua"/>
<Include file="..\api\options-layout.lua"/>
<Include file="..\api\options-chronometer.lua"/> <Include file="..\api\options-chronometer.lua"/>
<Include file="..\api\options-credits.lua"/> <Include file="..\api\options-credits.lua"/>
<Include file="..\api\options-animations.lua"/> <Include file="..\api\options-animations.lua"/>