mirror of
https://codeberg.org/Duvelcorp/MetaHunt.git
synced 2026-09-28 10:36:04 +00:00
1.5.1
This commit is contained in:
@@ -0,0 +1,321 @@
|
||||
------------------------------------------------------
|
||||
-- MetaHunt: SmartPet Options Panel
|
||||
-- TWoW 1.18.1
|
||||
------------------------------------------------------
|
||||
|
||||
local function MTH_SP_OPT_Ready()
|
||||
return type(MTH_GetFrame) == "function"
|
||||
and type(MTH_CreateCheckbox) == "function"
|
||||
and type(MTH_CreateSlider) == "function"
|
||||
end
|
||||
|
||||
local function MTH_SP_OPT_GetCfg()
|
||||
if not MTH_SmartPet or not MTH_SmartPet.GetConfig then return {} end
|
||||
return MTH_SmartPet.GetConfig()
|
||||
end
|
||||
|
||||
local MTH_SP_OPT_built = false
|
||||
|
||||
-- Layout constants
|
||||
local OPT_L = 16 -- left column X
|
||||
local OPT_R = 290 -- right column X
|
||||
local OPT_CW = 250 -- column width (for tip text wrapping)
|
||||
|
||||
-- Spacing constants
|
||||
local GAP_SECTION = 34 -- between sections
|
||||
local GAP_CB = 24 -- checkbox height (icon + text)
|
||||
local GAP_TIP = 16 -- small tip text height
|
||||
local GAP_BTN = 28 -- button height + margin
|
||||
local GAP_SLIDER = 52 -- slider total height (label + track + value)
|
||||
local GAP_CB_SLIDER = 40 -- checkbox to slider (checkbox + slider label above track)
|
||||
|
||||
-- Helper: checkbox with click handler
|
||||
local function SP_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 SP_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 SP_Tip(container, text, yOff, xOff)
|
||||
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(0.4, 0.6, 1.0)
|
||||
fs:SetText(text)
|
||||
return fs
|
||||
end
|
||||
|
||||
-- Taunt Mode cycle
|
||||
local TAUNT_MODES = { "auto", "growl", "cower", "off" }
|
||||
local TAUNT_LABELS = {
|
||||
auto = "Auto (solo=Growl, tank=Cower)",
|
||||
growl = "Always Growl",
|
||||
cower = "Always Cower",
|
||||
off = "Off (manual)",
|
||||
}
|
||||
|
||||
local function SP_NextTauntMode(current)
|
||||
for i = 1, 4 do
|
||||
if TAUNT_MODES[i] == current then
|
||||
return TAUNT_MODES[math.mod(i, 4) + 1]
|
||||
end
|
||||
end
|
||||
return "auto"
|
||||
end
|
||||
|
||||
-- Channel cycle
|
||||
local CHANNELS = { "SAY", "PARTY", "RAID", "GUILD" }
|
||||
|
||||
local function SP_NextChannel(current)
|
||||
for i = 1, 4 do
|
||||
if CHANNELS[i] == current then
|
||||
return CHANNELS[math.mod(i, 4) + 1]
|
||||
end
|
||||
end
|
||||
return "SAY"
|
||||
end
|
||||
|
||||
-- Build the UI
|
||||
local function MTH_SP_OPT_BuildUI(container)
|
||||
if MTH_SP_OPT_built then return end
|
||||
MTH_SP_OPT_built = true
|
||||
|
||||
local cfg = MTH_SP_OPT_GetCfg()
|
||||
local api = MTH_SmartPet or {}
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
-- Title (large, like ExpAmmo)
|
||||
---------------------------------------------------------------------------
|
||||
local title = container:CreateFontString(nil, "ARTWORK", "GameFontHighlightLarge")
|
||||
title:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_L, -16)
|
||||
title:SetText("Smart Pet - Pet Combat Management")
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
-- Module enable checkbox
|
||||
---------------------------------------------------------------------------
|
||||
local moduleEnabled = true
|
||||
if MTH and MTH.IsModuleEnabled then
|
||||
moduleEnabled = MTH:IsModuleEnabled("smartpet", false) and true or false
|
||||
end
|
||||
SP_CB(container, "MTH_SP_OPT_ModuleEnable", "Enable Smart Pet module",
|
||||
-46, OPT_L, moduleEnabled, function(v)
|
||||
if MTH and MTH.SetModuleEnabled then MTH:SetModuleEnabled("smartpet", v) end
|
||||
end)
|
||||
|
||||
-- Columns start below the module checkbox
|
||||
local COL_TOP = -80
|
||||
|
||||
-- Vertical divider
|
||||
local divider = container:CreateTexture(nil, "BACKGROUND")
|
||||
divider:SetTexture(0.3, 0.3, 0.3, 0.6)
|
||||
divider:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_R - 14, COL_TOP)
|
||||
divider:SetPoint("BOTTOMLEFT", container, "TOPLEFT", OPT_R - 14, -530)
|
||||
divider:SetWidth(1)
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
-- LEFT COLUMN — Focus Management
|
||||
---------------------------------------------------------------------------
|
||||
local y = COL_TOP
|
||||
|
||||
SP_Header(container, "Focus Management", y)
|
||||
y = y - 22
|
||||
|
||||
-- Smart Focus
|
||||
SP_CB(container, "MTH_SP_OPT_SmartFocus", "Enable Smart Focus",
|
||||
y, OPT_L, cfg.smartFocus, function(v)
|
||||
if api.SetSmartFocus then api.SetSmartFocus(v) end
|
||||
end)
|
||||
y = y - GAP_CB
|
||||
SP_Tip(container, "Budget pet focus across DPS abilities.", y)
|
||||
y = y - GAP_TIP
|
||||
SP_Tip(container, "|cff80ff80High focus|r — all DPS abilities ON.", y)
|
||||
y = y - GAP_TIP
|
||||
SP_Tip(container, "|cffffcc00Mid focus|r — expensive ability first, others wait.", y)
|
||||
y = y - GAP_TIP
|
||||
SP_Tip(container, "|cffff8080Low focus|r — cheapest ability always ON (never idle).", y)
|
||||
y = y - GAP_TIP
|
||||
SP_Tip(container, "Taunt cost is always reserved.", y)
|
||||
y = y - GAP_SECTION
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
-- LEFT COLUMN — Taunt Management
|
||||
---------------------------------------------------------------------------
|
||||
SP_Header(container, "Taunt Management", y)
|
||||
y = y - GAP_TIP
|
||||
SP_Tip(container, "Controls Growl/Cower autocast based on party.", y)
|
||||
y = y - 22
|
||||
|
||||
local tauntBtn = CreateFrame("Button", "MTH_SP_OPT_TauntBtn", container, "UIPanelButtonTemplate")
|
||||
tauntBtn:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_L, y)
|
||||
tauntBtn:SetWidth(250)
|
||||
tauntBtn:SetHeight(22)
|
||||
tauntBtn:SetText("Mode: " .. (TAUNT_LABELS[cfg.tauntMode] or "Auto"))
|
||||
tauntBtn:SetScript("OnClick", function()
|
||||
local c = MTH_SP_OPT_GetCfg()
|
||||
local newMode = SP_NextTauntMode(c.tauntMode)
|
||||
if api.SetTauntMode then api.SetTauntMode(newMode) end
|
||||
this:SetText("Mode: " .. (TAUNT_LABELS[newMode] or newMode))
|
||||
end)
|
||||
y = y - GAP_BTN
|
||||
|
||||
SP_CB(container, "MTH_SP_OPT_PvpDetaunt", "PVP Auto-Detaunt",
|
||||
y, OPT_L, cfg.pvpDetaunt, function(v)
|
||||
if api.SetPvpDetaunt then api.SetPvpDetaunt(v) end
|
||||
end)
|
||||
y = y - GAP_SECTION
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
-- LEFT COLUMN — CC-Break Prevention
|
||||
---------------------------------------------------------------------------
|
||||
SP_Header(container, "CC-Break Prevention", y)
|
||||
y = y - 22
|
||||
|
||||
SP_CB(container, "MTH_SP_OPT_CcBreak", "Check for breakable CC",
|
||||
y, OPT_L, cfg.ccBreakCheck, function(v)
|
||||
if api.SetCcBreakCheck then api.SetCcBreakCheck(v) end
|
||||
end)
|
||||
y = y - GAP_CB
|
||||
|
||||
local ccLabels = { block = "Block attack", warn = "Warn only" }
|
||||
local ccModeBtn = CreateFrame("Button", "MTH_SP_OPT_CcModeBtn", container, "UIPanelButtonTemplate")
|
||||
ccModeBtn:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_L + 20, y)
|
||||
ccModeBtn:SetWidth(180)
|
||||
ccModeBtn:SetHeight(20)
|
||||
ccModeBtn:SetText("CC Mode: " .. (ccLabels[cfg.ccBreakMode] or "Block"))
|
||||
ccModeBtn:SetScript("OnClick", function()
|
||||
local c = MTH_SP_OPT_GetCfg()
|
||||
local newMode = (c.ccBreakMode == "block") and "warn" or "block"
|
||||
if api.SetCcBreakMode then api.SetCcBreakMode(newMode) end
|
||||
this:SetText("CC Mode: " .. (ccLabels[newMode] or newMode))
|
||||
end)
|
||||
y = y - GAP_SECTION
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
-- RIGHT COLUMN — General
|
||||
---------------------------------------------------------------------------
|
||||
local ry = COL_TOP
|
||||
|
||||
-- The Button
|
||||
SP_Header(container, "The Button", ry, OPT_R)
|
||||
ry = ry - 22
|
||||
|
||||
SP_CB(container, "MTH_SP_OPT_TheButton", "Enable The Button keybind",
|
||||
ry, OPT_R, cfg.theButton, function(v)
|
||||
if api.SetTheButton then api.SetTheButton(v) end
|
||||
end)
|
||||
ry = ry - GAP_CB
|
||||
SP_Tip(container, "Enemy=attack, friendly=assist, none=recall.", ry, OPT_R)
|
||||
ry = ry - GAP_SECTION
|
||||
|
||||
-- Rush on Attack
|
||||
SP_CB(container, "MTH_SP_OPT_Rush", "Rush on initial attack",
|
||||
ry, OPT_R, cfg.rushOnAttack, function(v)
|
||||
if api.SetRushOnAttack then api.SetRushOnAttack(v) end
|
||||
end)
|
||||
ry = ry - GAP_CB
|
||||
SP_Tip(container, "Charge / Dash / Dive when pet is sent to attack.", ry, OPT_R)
|
||||
ry = ry - GAP_SECTION
|
||||
|
||||
-- NoChase
|
||||
SP_CB(container, "MTH_SP_OPT_NoChase", "NoChase (recall on mob flee)",
|
||||
ry, OPT_R, cfg.noChase, function(v)
|
||||
if api.SetNoChase then api.SetNoChase(v) end
|
||||
end)
|
||||
ry = ry - GAP_CB
|
||||
SP_Tip(container, "Recall pet when target attempts to flee.", ry, OPT_R)
|
||||
ry = ry - GAP_SECTION
|
||||
|
||||
-- AutoCower
|
||||
SP_Header(container, "AutoCower", ry, OPT_R)
|
||||
ry = ry - 22
|
||||
|
||||
SP_CB(container, "MTH_SP_OPT_AutoCower", "Enable AutoCower on low HP",
|
||||
ry, OPT_R, cfg.autoCower, function(v)
|
||||
if api.SetAutoCower then api.SetAutoCower(v) end
|
||||
end)
|
||||
ry = ry - GAP_CB_SLIDER
|
||||
|
||||
local acSlider = MTH_CreateSlider(container, "MTH_SP_OPT_AutoCowerSlider",
|
||||
"HP Threshold (%)", 5, 80, 5, ry)
|
||||
if acSlider then
|
||||
acSlider:ClearAllPoints()
|
||||
acSlider:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_R, ry)
|
||||
acSlider:SetWidth(200)
|
||||
acSlider:SetValue(cfg.autoCowerPct or 30)
|
||||
local valText = getglobal("MTH_SP_OPT_AutoCowerSliderValue")
|
||||
if valText then valText:SetText(tostring(cfg.autoCowerPct or 30)) end
|
||||
acSlider.onChange = function(val)
|
||||
if api.SetAutoCowerPct then api.SetAutoCowerPct(val) end
|
||||
end
|
||||
end
|
||||
ry = ry - GAP_SLIDER
|
||||
|
||||
-- AutoWarn
|
||||
SP_Header(container, "AutoWarn", ry, OPT_R)
|
||||
ry = ry - 22
|
||||
|
||||
SP_CB(container, "MTH_SP_OPT_AutoWarn", "Warn when pet HP is low",
|
||||
ry, OPT_R, cfg.autoWarn, function(v)
|
||||
if api.SetAutoWarn then api.SetAutoWarn(v) end
|
||||
end)
|
||||
ry = ry - GAP_CB_SLIDER
|
||||
|
||||
local awSlider = MTH_CreateSlider(container, "MTH_SP_OPT_AutoWarnSlider",
|
||||
"HP Threshold (%)", 5, 60, 5, ry)
|
||||
if awSlider then
|
||||
awSlider:ClearAllPoints()
|
||||
awSlider:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_R, ry)
|
||||
awSlider:SetWidth(200)
|
||||
awSlider:SetValue(cfg.autoWarnPct or 20)
|
||||
local valText = getglobal("MTH_SP_OPT_AutoWarnSliderValue")
|
||||
if valText then valText:SetText(tostring(cfg.autoWarnPct or 20)) end
|
||||
awSlider.onChange = function(val)
|
||||
if api.SetAutoWarnPct then api.SetAutoWarnPct(val) end
|
||||
end
|
||||
end
|
||||
ry = ry - GAP_SLIDER
|
||||
|
||||
local chanBtn = CreateFrame("Button", "MTH_SP_OPT_ChanBtn", container, "UIPanelButtonTemplate")
|
||||
chanBtn:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_R, ry)
|
||||
chanBtn:SetWidth(180)
|
||||
chanBtn:SetHeight(22)
|
||||
chanBtn:SetText("Channel: " .. (cfg.autoWarnChannel or "SAY"))
|
||||
chanBtn:SetScript("OnClick", function()
|
||||
local c = MTH_SP_OPT_GetCfg()
|
||||
local newChan = SP_NextChannel(c.autoWarnChannel or "SAY")
|
||||
if api.SetAutoWarnChannel then api.SetAutoWarnChannel(newChan) end
|
||||
this:SetText("Channel: " .. newChan)
|
||||
end)
|
||||
ry = ry - GAP_CB
|
||||
SP_Tip(container, "Chat channel for low-HP warnings.", ry, OPT_R)
|
||||
end
|
||||
|
||||
-- Public setup function (called by options-shell.lua)
|
||||
function MTH_SetupSmartPetOptions()
|
||||
if not MTH_SP_OPT_Ready() then return end
|
||||
local container = MTH_GetFrame("MetaHuntOptionsSmartPet")
|
||||
if not container then return end
|
||||
local ok, err = pcall(MTH_SP_OPT_BuildUI, container)
|
||||
if not ok then
|
||||
if MTH and MTH.Print then
|
||||
MTH:Print("[SmartPet Options] " .. tostring(err), "error")
|
||||
end
|
||||
MTH_SP_OPT_built = false
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user