mirror of
https://codeberg.org/Duvelcorp/MetaHunt.git
synced 2026-10-02 20:40:02 +00:00
Add Animations feature + fix own-pet tooltip false positive
Animations (all optional, default on, per-effect toggles): - New Options -> Animations tab with master switch + per-effect checkboxes - Embed PizzaSauce animation library (api/PizzaSauce.lua) - fx-celebrate: firework + banner when a pet learns a new ability/rank, triggered from core-scan-beasttraining pet-learn hook - Hunter's Book: slide + fade on open, results list fade on tab switch - Options window: slide + fade on open - All new user-facing strings keyed (ANIM_* namespace) Fixes: - Tooltip #19: own-pet lines (mood/loyalty/happiness/XP) no longer misfire on party members / targets. Removed the fragile title-name fallback in MTH_TT_IsTooltipOnOwnPet; ownership now requires positive unit identity. Temp (remove before release): /mth fx and /mth fxdebug diagnostics.
This commit is contained in:
+1347
File diff suppressed because it is too large
Load Diff
@@ -432,6 +432,9 @@ local function MTH_PT_ProcessLearnSystemMessage(rawMessage)
|
||||
if changed then
|
||||
MTH_PT_ApplyScan("learn-msg")
|
||||
end
|
||||
if changed and type(MTH_CelebratePetAbility) == "function" then
|
||||
MTH_CelebratePetAbility(label)
|
||||
end
|
||||
if type(MTH_PSP_RequestScan) == "function" then
|
||||
MTH_PSP_RequestScan("train-learn-msg")
|
||||
end
|
||||
|
||||
@@ -325,6 +325,69 @@ function SlashCmdList.MTH(msg, editbox)
|
||||
MTH_CommandBook()
|
||||
elseif lowerMsg == "peers" or lowerMsg == "who" then
|
||||
MTH_CommandPeers()
|
||||
elseif lowerCmd == "trainscan" or lowerCmd == "petscan" then
|
||||
if type(MTH_CommandTrainScan) == "function" then
|
||||
MTH_CommandTrainScan()
|
||||
else
|
||||
MTH:Print("Train scan is not available.")
|
||||
end
|
||||
elseif lowerCmd == "fx" or lowerCmd == "fireworks" or lowerCmd == "celebrate" then
|
||||
-- TEMP: preview the pet-ability celebration effect.
|
||||
if type(MTH_Celebrate) == "function" then
|
||||
local label = msg
|
||||
local _, _, rest = string.find(msg, "^%S+%s+(.-)%s*$")
|
||||
if rest and rest ~= "" then
|
||||
MTH_Celebrate("New Pet Ability!", rest)
|
||||
else
|
||||
MTH_Celebrate("New Pet Ability!", "Growl (Rank 3)")
|
||||
end
|
||||
else
|
||||
-- Self-diagnosing: report which piece failed to load so we can tell
|
||||
-- a stale UI from a genuine load error.
|
||||
MTH:Print("Celebration effect is not available. Diagnostics:")
|
||||
MTH:Print(" PizzaSauce global: " .. type(PizzaSauce))
|
||||
MTH:Print(" MTH_Celebrate: " .. type(MTH_Celebrate))
|
||||
MTH:Print(" MTH_FX_IsEnabled: " .. type(MTH_FX_IsEnabled))
|
||||
MTH:Print(" MTH_SetupAnimationsOptions: " .. type(MTH_SetupAnimationsOptions))
|
||||
MTH:Print(" -> If these are 'nil', do /reload (your UI is running code from before the feature was added).")
|
||||
end
|
||||
elseif lowerCmd == "fxdebug" then
|
||||
-- TEMP: dump the animation load-path tracers so we can see exactly where
|
||||
-- fx-celebrate.lua / options-animations.lua aborted at load time.
|
||||
MTH:Print("=== MetaHunt animation load debug ===")
|
||||
MTH:Print("Globals: PizzaSauce=" .. type(PizzaSauce)
|
||||
.. " CreateFrame=" .. type(CreateFrame)
|
||||
.. " MTH=" .. type(MTH))
|
||||
if type(MTH_FX_DBG) == "table" then
|
||||
MTH:Print("fx-celebrate: step=" .. tostring(MTH_FX_DBG.step)
|
||||
.. " sauceType=" .. tostring(MTH_FX_DBG.sauceType)
|
||||
.. " registerOk=" .. tostring(MTH_FX_DBG.registerOk)
|
||||
.. " registerSkipped=" .. tostring(MTH_FX_DBG.registerSkipped))
|
||||
if MTH_FX_DBG.registerErr ~= nil then
|
||||
MTH:Print("fx-celebrate: registerErr=" .. tostring(MTH_FX_DBG.registerErr))
|
||||
end
|
||||
MTH:Print("fx-celebrate: hasCelebrate=" .. tostring(MTH_FX_DBG.hasCelebrate)
|
||||
.. " hasIsEnabled=" .. tostring(MTH_FX_DBG.hasIsEnabled)
|
||||
.. " hasAnimEnabled=" .. tostring(MTH_FX_DBG.hasAnimEnabled))
|
||||
else
|
||||
MTH:Print("fx-celebrate: MTH_FX_DBG is " .. type(MTH_FX_DBG) .. " (file did not reach its first line)")
|
||||
end
|
||||
if type(MTH_ANIM_DBG) == "table" then
|
||||
MTH:Print("options-animations: step=" .. tostring(MTH_ANIM_DBG.step)
|
||||
.. " ready=" .. tostring(MTH_ANIM_DBG.ready)
|
||||
.. " hasSetup=" .. tostring(MTH_ANIM_DBG.hasSetup))
|
||||
MTH:Print("options-animations: req=" .. tostring(MTH_ANIM_DBG.reqType)
|
||||
.. " getFrame=" .. tostring(MTH_ANIM_DBG.getFrameType)
|
||||
.. " clear=" .. tostring(MTH_ANIM_DBG.clearType)
|
||||
.. " checkbox=" .. tostring(MTH_ANIM_DBG.checkboxType))
|
||||
MTH:Print("options-animations: setupCalled=" .. tostring(MTH_ANIM_DBG.setupCalled)
|
||||
.. " setupResult=" .. tostring(MTH_ANIM_DBG.setupResult)
|
||||
.. " containerType=" .. tostring(MTH_ANIM_DBG.containerType)
|
||||
.. " fxEnabledType=" .. tostring(MTH_ANIM_DBG.fxEnabledType))
|
||||
else
|
||||
MTH:Print("options-animations: MTH_ANIM_DBG is " .. type(MTH_ANIM_DBG) .. " (file did not reach its first line)")
|
||||
end
|
||||
MTH:Print("=== end animation load debug ===")
|
||||
elseif lowerMsg == "zoneinfo" then
|
||||
-- Dumps all available zone data for the current zone, for adding to ds-zones / ds-minimap-sizes
|
||||
pcall(SetMapToCurrentZone)
|
||||
|
||||
@@ -0,0 +1,297 @@
|
||||
-- MetaHunt: center-screen celebration effect (message + firework burst).
|
||||
-- Uses the embedded PizzaSauce animation library. Degrades to a silent no-op
|
||||
-- when PizzaSauce or the WoW frame API are unavailable (e.g. offline tests).
|
||||
|
||||
-- Capture our own PizzaSauce instance now, before another addon that ships its
|
||||
-- own copy can overwrite the global. This is the pattern the library requires.
|
||||
local Sauce = PizzaSauce
|
||||
|
||||
-- Localization helper: resolve a key through MetaHunt's loc system, falling back
|
||||
-- to the inline English default. Every user-facing string is keyed so the enUS
|
||||
-- strings can be harvested later; the inline default is the working English.
|
||||
local function MTH_FX_L(key, default)
|
||||
if MTH and type(MTH.GetLocalization) == "function" then
|
||||
return MTH:GetLocalization(key, default)
|
||||
end
|
||||
return default or key
|
||||
end
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- DEBUG: load-path tracer. Global so /mth fxdebug can dump it. Records how far
|
||||
-- this file got at load time and any error from the one executable file-scope
|
||||
-- block (RegisterType). TEMP diagnostic.
|
||||
-- ---------------------------------------------------------------------------
|
||||
MTH_FX_DBG = {
|
||||
sauceType = type(PizzaSauce),
|
||||
createFrameType = type(CreateFrame),
|
||||
step = "1-top",
|
||||
}
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Animation settings (shared by the effect code and the options "Animations" tab)
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Sections shown, in order, in the options panel. `titleKey` localizes `title`.
|
||||
MTH_FX_ANIM_SECTIONS = {
|
||||
{ id = "pet", title = "Pet", titleKey = "ANIM_SECTION_PET" },
|
||||
{ id = "book", title = "Book", titleKey = "ANIM_SECTION_BOOK" },
|
||||
{ id = "ui", title = "Interface", titleKey = "ANIM_SECTION_UI" },
|
||||
}
|
||||
|
||||
-- Every individual animation the addon can play. Each has a stable `key`, the
|
||||
-- section it belongs to, a checkbox label, an optional tooltip, and a default.
|
||||
-- labelKey/tooltipKey localize label/tooltip (resolved at render time).
|
||||
-- Adding a new animation = one entry here + one MTH_FX_IsEnabled("key") guard.
|
||||
MTH_FX_ANIM_DEFS = {
|
||||
{ key = "pet.celebrate", section = "pet", default = true,
|
||||
label = "Celebrate new pet abilities", labelKey = "ANIM_PET_CELEBRATE",
|
||||
tooltip = "Play a firework and a banner in the middle of the screen when your pet learns a new ability or a new rank.",
|
||||
tooltipKey = "ANIM_PET_CELEBRATE_TIP" },
|
||||
{ key = "book.open", section = "book", default = true,
|
||||
label = "Fade in the Hunter's Book", labelKey = "ANIM_BOOK_OPEN",
|
||||
tooltip = "Fade the Hunter's Book window in when you open it.",
|
||||
tooltipKey = "ANIM_BOOK_OPEN_TIP" },
|
||||
{ key = "book.tabs", section = "book", default = true,
|
||||
label = "Fade Hunter's Book tab changes", labelKey = "ANIM_BOOK_TABS",
|
||||
tooltip = "Fade the results list back in when you switch tabs inside the Hunter's Book.",
|
||||
tooltipKey = "ANIM_BOOK_TABS_TIP" },
|
||||
{ key = "ui.options", section = "ui", default = true,
|
||||
label = "Slide the options window open", labelKey = "ANIM_UI_OPTIONS",
|
||||
tooltip = "Slide and fade the MetaHunt options window in when you open it.",
|
||||
tooltipKey = "ANIM_UI_OPTIONS_TIP" },
|
||||
}
|
||||
|
||||
local function MTH_FX_Store()
|
||||
if MTH and type(MTH.GetModuleSavedVariables) == "function" then
|
||||
return MTH:GetModuleSavedVariables("animations")
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function MTH_FX_DefaultFor(key)
|
||||
local i = 1
|
||||
while i <= table.getn(MTH_FX_ANIM_DEFS) do
|
||||
if MTH_FX_ANIM_DEFS[i].key == key then
|
||||
return MTH_FX_ANIM_DEFS[i].default and true or false
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function MTH_FX_AnimationsEnabled()
|
||||
local store = MTH_FX_Store()
|
||||
if not store or store.enabled == nil then
|
||||
return true
|
||||
end
|
||||
return store.enabled and true or false
|
||||
end
|
||||
|
||||
function MTH_FX_SetAnimationsEnabled(value)
|
||||
local store = MTH_FX_Store()
|
||||
if not store then return end
|
||||
store.enabled = value and true or false
|
||||
end
|
||||
|
||||
function MTH_FX_GetFlag(key)
|
||||
local store = MTH_FX_Store()
|
||||
if store and store.flags and store.flags[key] ~= nil then
|
||||
return store.flags[key] and true or false
|
||||
end
|
||||
return MTH_FX_DefaultFor(key)
|
||||
end
|
||||
|
||||
function MTH_FX_SetFlag(key, value)
|
||||
local store = MTH_FX_Store()
|
||||
if not store then return end
|
||||
store.flags = store.flags or {}
|
||||
store.flags[key] = value and true or false
|
||||
end
|
||||
|
||||
-- Master gate every animation call site checks: false when animations are
|
||||
-- globally disabled, or when this specific animation is turned off.
|
||||
function MTH_FX_IsEnabled(key)
|
||||
if not MTH_FX_AnimationsEnabled() then
|
||||
return false
|
||||
end
|
||||
if key == nil then
|
||||
return true
|
||||
end
|
||||
return MTH_FX_GetFlag(key)
|
||||
end
|
||||
|
||||
-- Register a one-shot "ballistic" tween type: a spark that flies out from the
|
||||
-- center along a velocity vector while gravity pulls it back down.
|
||||
MTH_FX_DBG.step = "2-before-registertype"
|
||||
if Sauce and type(Sauce.RegisterType) == "function" and not Sauce.MTH_HasBallistic then
|
||||
local ok, err = pcall(function()
|
||||
Sauce.MTH_HasBallistic = true
|
||||
Sauce:RegisterType("mth_ballistic", {
|
||||
init = function(target, from)
|
||||
return from or { 0, 0 }
|
||||
end,
|
||||
apply = function(target, from, to, t, tween)
|
||||
local dur = tween.dur or 1
|
||||
local elapsed = t * dur
|
||||
local vx = tween.vx or 0
|
||||
local vy = tween.vy or 0
|
||||
local gravity = tween.gravity or 0
|
||||
local x = from[1] + vx * elapsed
|
||||
local y = from[2] + vy * elapsed - 0.5 * gravity * elapsed * elapsed
|
||||
local anchor = tween.anchor or UIParent
|
||||
target:ClearAllPoints()
|
||||
target:SetPoint("CENTER", anchor, "CENTER", x, y)
|
||||
end,
|
||||
})
|
||||
end)
|
||||
MTH_FX_DBG.registerOk = ok
|
||||
MTH_FX_DBG.registerErr = err
|
||||
else
|
||||
MTH_FX_DBG.registerSkipped = true
|
||||
end
|
||||
MTH_FX_DBG.step = "3-after-registertype"
|
||||
|
||||
local MTH_FX_NUM_SPARKS = 22
|
||||
local MTH_FX_Container
|
||||
local MTH_FX_MsgFrame
|
||||
local MTH_FX_TitleFS
|
||||
local MTH_FX_SubFS
|
||||
local MTH_FX_Sparks = {}
|
||||
|
||||
-- Palette for the firework sparks (r, g, b), warm celebratory tones.
|
||||
local MTH_FX_Colors = {
|
||||
{ 1.00, 0.82, 0.00 },
|
||||
{ 1.00, 0.45, 0.10 },
|
||||
{ 1.00, 0.20, 0.30 },
|
||||
{ 0.35, 0.70, 1.00 },
|
||||
{ 0.55, 1.00, 0.45 },
|
||||
{ 0.85, 0.50, 1.00 },
|
||||
}
|
||||
|
||||
local function MTH_FX_EnsureFrames()
|
||||
if type(CreateFrame) ~= "function" then
|
||||
return false
|
||||
end
|
||||
if MTH_FX_Container then
|
||||
return true
|
||||
end
|
||||
|
||||
MTH_FX_Container = CreateFrame("Frame", "MTH_FX_Container", UIParent)
|
||||
MTH_FX_Container:SetWidth(1)
|
||||
MTH_FX_Container:SetHeight(1)
|
||||
MTH_FX_Container:SetPoint("CENTER", UIParent, "CENTER", 0, 40)
|
||||
MTH_FX_Container:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||
MTH_FX_Container:Hide()
|
||||
|
||||
MTH_FX_MsgFrame = CreateFrame("Frame", "MTH_FX_Message", UIParent)
|
||||
MTH_FX_MsgFrame:SetWidth(512)
|
||||
MTH_FX_MsgFrame:SetHeight(90)
|
||||
MTH_FX_MsgFrame:SetPoint("CENTER", UIParent, "CENTER", 0, 80)
|
||||
MTH_FX_MsgFrame:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||
|
||||
MTH_FX_TitleFS = MTH_FX_MsgFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalHuge")
|
||||
MTH_FX_TitleFS:SetPoint("CENTER", MTH_FX_MsgFrame, "CENTER", 0, 14)
|
||||
MTH_FX_TitleFS:SetTextColor(1, 0.82, 0)
|
||||
|
||||
MTH_FX_SubFS = MTH_FX_MsgFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge")
|
||||
MTH_FX_SubFS:SetPoint("TOP", MTH_FX_TitleFS, "BOTTOM", 0, -8)
|
||||
MTH_FX_SubFS:SetTextColor(1, 1, 1)
|
||||
|
||||
MTH_FX_MsgFrame:Hide()
|
||||
|
||||
local i = 1
|
||||
while i <= MTH_FX_NUM_SPARKS do
|
||||
local spark = MTH_FX_Container:CreateTexture(nil, "OVERLAY")
|
||||
spark:SetTexture("Interface\\Cooldown\\star4")
|
||||
spark:SetWidth(22)
|
||||
spark:SetHeight(22)
|
||||
spark:SetBlendMode("ADD")
|
||||
spark:SetPoint("CENTER", MTH_FX_Container, "CENTER", 0, 0)
|
||||
spark:Hide()
|
||||
MTH_FX_Sparks[i] = spark
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- Public entry point: play a celebratory message + firework burst in the middle
|
||||
-- of the screen. `title` and `subtitle` are optional strings.
|
||||
function MTH_Celebrate(title, subtitle)
|
||||
if not Sauce then
|
||||
return
|
||||
end
|
||||
if not MTH_FX_EnsureFrames() then
|
||||
return
|
||||
end
|
||||
|
||||
MTH_FX_TitleFS:SetText(title or "")
|
||||
MTH_FX_SubFS:SetText(subtitle or "")
|
||||
|
||||
Sauce:Stop(MTH_FX_MsgFrame)
|
||||
MTH_FX_MsgFrame:SetAlpha(0)
|
||||
MTH_FX_MsgFrame:Show()
|
||||
Sauce:Sequence({
|
||||
Sauce:Group({
|
||||
Sauce:FadeTo(MTH_FX_MsgFrame, 1, 0.25),
|
||||
Sauce:Pulse(MTH_FX_MsgFrame, 1.22, 0.5),
|
||||
}),
|
||||
Sauce:FadeOut(MTH_FX_MsgFrame, 0.6, "inQuad", { delay = 2.2 }),
|
||||
})
|
||||
|
||||
MTH_FX_Container:Show()
|
||||
local colorCount = table.getn(MTH_FX_Colors)
|
||||
local colorIdx = 0
|
||||
local i = 1
|
||||
while i <= MTH_FX_NUM_SPARKS do
|
||||
local spark = MTH_FX_Sparks[i]
|
||||
local angle = (i / MTH_FX_NUM_SPARKS) * 2 * math.pi + (math.random() - 0.5) * 0.4
|
||||
local speed = 150 + math.random() * 130
|
||||
local vx = math.cos(angle) * speed
|
||||
local vy = math.sin(angle) * speed + 70
|
||||
local dur = 0.9 + math.random() * 0.4
|
||||
|
||||
colorIdx = colorIdx + 1
|
||||
if colorIdx > colorCount then colorIdx = 1 end
|
||||
local color = MTH_FX_Colors[colorIdx]
|
||||
spark:SetVertexColor(color[1], color[2], color[3])
|
||||
spark:SetAlpha(1)
|
||||
spark:Show()
|
||||
|
||||
Sauce:Stop(spark)
|
||||
Sauce:Group({
|
||||
Sauce:Tween(spark, {
|
||||
type = "mth_ballistic",
|
||||
from = { 0, 0 },
|
||||
duration = dur,
|
||||
easing = "linear",
|
||||
anchor = MTH_FX_Container,
|
||||
dur = dur,
|
||||
vx = vx,
|
||||
vy = vy,
|
||||
gravity = 300,
|
||||
}),
|
||||
Sauce:FadeTo(spark, 0, 0.45, "inQuad", {
|
||||
delay = dur - 0.45,
|
||||
onFinish = function()
|
||||
spark:Hide()
|
||||
end,
|
||||
}),
|
||||
})
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Convenience wrapper used when the hunter's pet learns a new ability/rank.
|
||||
function MTH_CelebratePetAbility(label)
|
||||
if not MTH_FX_IsEnabled("pet.celebrate") then
|
||||
return
|
||||
end
|
||||
MTH_Celebrate(MTH_FX_L("ANIM_PET_LEARNED_TITLE", "New Pet Ability!"), label)
|
||||
end
|
||||
|
||||
-- DEBUG: mark that the whole file finished loading and record which globals it
|
||||
-- successfully defined. TEMP diagnostic.
|
||||
MTH_FX_DBG.step = "4-complete"
|
||||
MTH_FX_DBG.hasCelebrate = type(MTH_Celebrate)
|
||||
MTH_FX_DBG.hasIsEnabled = type(MTH_FX_IsEnabled)
|
||||
MTH_FX_DBG.hasAnimEnabled = type(MTH_FX_AnimationsEnabled)
|
||||
@@ -1,5 +1,34 @@
|
||||
-- MetaHunt standalone Hunter Book UI (XML + Lua)
|
||||
|
||||
-- Capture our PizzaSauce instance for opening animations (may be nil if the
|
||||
-- library is unavailable; all uses are guarded).
|
||||
local Sauce = PizzaSauce
|
||||
|
||||
-- Fade the book window in on open, unless the player disabled it in options.
|
||||
local function MTH_BOOK_FadeInWindow(frame)
|
||||
if not Sauce or not frame then return end
|
||||
if type(MTH_FX_IsEnabled) == "function" and not MTH_FX_IsEnabled("book.open") then return end
|
||||
-- Hide the window's alpha THIS frame: Show() already ran, so without this the
|
||||
-- book renders fully opaque for one frame before the tween's onStart snaps it
|
||||
-- to 0 -- a flash that makes the fade look like it never happened.
|
||||
if type(frame.SetAlpha) == "function" then frame:SetAlpha(0) end
|
||||
-- Slide the whole window up into place while fading in. Position and alpha are
|
||||
-- the only safe properties on a complex frame: the built-in "scale" tween
|
||||
-- resizes width/height, which the child widgets do NOT follow (they clip), so
|
||||
-- a slide + fade is the strongest effect that keeps the layout intact.
|
||||
Sauce:SlideIn(frame, "UP", 60, 0.4, "outCubic")
|
||||
end
|
||||
|
||||
-- Fade the results list back in when switching Hunter's Book tabs, unless disabled.
|
||||
local function MTH_BOOK_AnimateTabSwitch()
|
||||
if not Sauce then return end
|
||||
if type(MTH_FX_IsEnabled) == "function" and not MTH_FX_IsEnabled("book.tabs") then return end
|
||||
local list = getglobal("MTH_BOOK_ListBackdrop")
|
||||
if not list then return end
|
||||
if type(list.SetAlpha) == "function" then list:SetAlpha(0) end
|
||||
Sauce:FadeIn(list, 0.25)
|
||||
end
|
||||
|
||||
MTH_HUNTERBOOK_LOADED = true
|
||||
MTH_HUNTERBOOK_TABS = MTH_HUNTERBOOK_TABS or {}
|
||||
|
||||
@@ -4929,6 +4958,7 @@ local function MTH_BOOK_SetMode(mode)
|
||||
MTH_BOOK_UpdateModeLabels()
|
||||
MTH_BOOK_UpdateSectionTabs()
|
||||
MTH_BOOK_RefreshFilter()
|
||||
MTH_BOOK_AnimateTabSwitch()
|
||||
end
|
||||
|
||||
function MTH_BOOK_JumpToBeastById(beastId)
|
||||
@@ -5712,6 +5742,7 @@ function MTH_OpenHunterBook()
|
||||
local frame = MTH_BOOK_EnsureWindow()
|
||||
if not frame then return end
|
||||
frame:Show()
|
||||
MTH_BOOK_FadeInWindow(frame)
|
||||
if MTH_BOOK_UpdateRealmGateOverlay(frame) then return end
|
||||
MTH_BOOK_RefreshFilter()
|
||||
end
|
||||
@@ -5724,6 +5755,7 @@ function MTH_ToggleHunterBook()
|
||||
frame:Hide()
|
||||
else
|
||||
frame:Show()
|
||||
MTH_BOOK_FadeInWindow(frame)
|
||||
if MTH_BOOK_UpdateRealmGateOverlay(frame) then return end
|
||||
MTH_BOOK_RefreshFilter()
|
||||
end
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
-- MetaHunt: "Animations" options panel.
|
||||
-- Global enable/disable plus a per-animation checkbox for each effect, grouped
|
||||
-- into sections (Pet, Book, ...). The animation registry lives in fx-celebrate.lua
|
||||
-- (MTH_FX_ANIM_SECTIONS / MTH_FX_ANIM_DEFS) so both the effects and this panel
|
||||
-- stay in sync.
|
||||
|
||||
local MTH_ANIM_READY = MTH_OptionsRequire and MTH_OptionsRequire("options-animations", {
|
||||
"MTH_GetFrame",
|
||||
"MTH_ClearContainer",
|
||||
"MTH_CreateCheckbox",
|
||||
})
|
||||
|
||||
-- DEBUG: load-path tracer, global so /mth fxdebug can dump it. TEMP diagnostic.
|
||||
MTH_ANIM_DBG = {
|
||||
ready = tostring(MTH_ANIM_READY),
|
||||
reqType = type(MTH_OptionsRequire),
|
||||
getFrameType = type(MTH_GetFrame),
|
||||
clearType = type(MTH_ClearContainer),
|
||||
checkboxType = type(MTH_CreateCheckbox),
|
||||
step = "1-top",
|
||||
}
|
||||
|
||||
local MTH_ANIM_LINK = "https://codeberg.org/Pizzahawaii/PizzaSauce"
|
||||
local MTH_ANIM_CTRL = {}
|
||||
|
||||
local function MTH_ANIM_L(key, default)
|
||||
if MTH and MTH.GetLocalization then
|
||||
return MTH:GetLocalization(key, default)
|
||||
end
|
||||
return default or key
|
||||
end
|
||||
|
||||
local function MTH_ANIM_InsertLink(url)
|
||||
local link = tostring(url or "")
|
||||
if link == "" then return end
|
||||
if type(MTH_InsertLinkToChat) == "function" and MTH_InsertLinkToChat(link) then
|
||||
if MTH and MTH.Print then
|
||||
MTH:Print(MTH_ANIM_L("ANIM_LINK_INSERTED", "Link inserted in chat: ") .. link)
|
||||
end
|
||||
return
|
||||
end
|
||||
if MTH and MTH.Print then
|
||||
MTH:Print(MTH_ANIM_L("ANIM_LINK_FALLBACK", "Link: ") .. link)
|
||||
end
|
||||
end
|
||||
|
||||
local function MTH_ANIM_UpdateChildStates()
|
||||
local master = MTH_FX_AnimationsEnabled()
|
||||
local i = 1
|
||||
while i <= table.getn(MTH_ANIM_CTRL) do
|
||||
local cb = MTH_ANIM_CTRL[i]
|
||||
if cb then
|
||||
cb:SetChecked(MTH_FX_GetFlag(cb.mthKey))
|
||||
if master then
|
||||
cb:Enable()
|
||||
else
|
||||
cb:Disable()
|
||||
end
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
function MTH_SetupAnimationsOptions()
|
||||
MTH_ANIM_DBG.setupCalled = true
|
||||
MTH_ANIM_DBG.fxEnabledType = type(MTH_FX_AnimationsEnabled)
|
||||
if not MTH_ANIM_READY then
|
||||
MTH_ANIM_DBG.setupResult = "abort-not-ready"
|
||||
return
|
||||
end
|
||||
if type(MTH_FX_AnimationsEnabled) ~= "function" then
|
||||
MTH_ANIM_DBG.setupResult = "abort-no-fx-globals"
|
||||
return
|
||||
end
|
||||
|
||||
local container = MTH_GetFrame("MetaHuntOptionsAnimations")
|
||||
MTH_ANIM_DBG.containerType = type(container)
|
||||
if not container then
|
||||
MTH_ANIM_DBG.setupResult = "abort-no-container"
|
||||
return
|
||||
end
|
||||
|
||||
MTH_ClearContainer(container)
|
||||
MTH_ANIM_CTRL = {}
|
||||
|
||||
local title = container:CreateFontString("MetaHuntOptionsAnimationsTitle", "ARTWORK", "GameFontNormal")
|
||||
title:SetPoint("TOPLEFT", container, "TOPLEFT", 10, -10)
|
||||
title:SetText(MTH_ANIM_L("ANIM_TITLE", "Animations"))
|
||||
title:SetTextColor(1.00, 0.82, 0.00)
|
||||
|
||||
local credit = container:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
||||
credit:SetPoint("TOPLEFT", title, "BOTTOMLEFT", 0, -8)
|
||||
credit:SetWidth(460)
|
||||
credit:SetJustifyH("LEFT")
|
||||
credit:SetText(MTH_ANIM_L("ANIM_CREDIT",
|
||||
"Animations are powered by PizzaSauce, a WoW 1.12 animation library kindly made and shared by Pizzahawaii. Thank you!"))
|
||||
credit:SetTextColor(0.93, 0.93, 0.93)
|
||||
|
||||
local link = CreateFrame("Button", nil, container)
|
||||
link:SetPoint("TOPLEFT", credit, "BOTTOMLEFT", 0, -4)
|
||||
link:SetHeight(16)
|
||||
link:SetWidth(460)
|
||||
local linkText = link:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
||||
linkText:SetPoint("LEFT", link, "LEFT", 0, 0)
|
||||
linkText:SetJustifyH("LEFT")
|
||||
linkText:SetText(MTH_ANIM_LINK)
|
||||
linkText:SetTextColor(0.40, 0.75, 1.00)
|
||||
link:SetScript("OnClick", function() MTH_ANIM_InsertLink(MTH_ANIM_LINK) end)
|
||||
link:SetScript("OnEnter", function() linkText:SetTextColor(0.60, 0.90, 1.00) end)
|
||||
link:SetScript("OnLeave", function() linkText:SetTextColor(0.40, 0.75, 1.00) end)
|
||||
|
||||
-- Global master toggle.
|
||||
local master = MTH_CreateCheckbox(container, "MetaHuntOptionsAnimMaster",
|
||||
MTH_ANIM_L("ANIM_ENABLE_ALL", "Enable animations"), -70)
|
||||
if master then
|
||||
master:SetChecked(MTH_FX_AnimationsEnabled())
|
||||
master:SetScript("OnClick", function()
|
||||
MTH_FX_SetAnimationsEnabled(master:GetChecked())
|
||||
MTH_ANIM_UpdateChildStates()
|
||||
end)
|
||||
end
|
||||
|
||||
-- Per-animation checkboxes, grouped by section.
|
||||
local y = -104
|
||||
local rowStep = 26
|
||||
local sectionGap = 12
|
||||
local s = 1
|
||||
while MTH_FX_ANIM_SECTIONS and s <= table.getn(MTH_FX_ANIM_SECTIONS) do
|
||||
local sec = MTH_FX_ANIM_SECTIONS[s]
|
||||
local header = container:CreateFontString(nil, "ARTWORK", "GameFontNormal")
|
||||
header:SetPoint("TOPLEFT", container, "TOPLEFT", 15, y)
|
||||
header:SetText(MTH_ANIM_L(sec.titleKey, sec.title))
|
||||
header:SetTextColor(1.00, 0.82, 0.00)
|
||||
y = y - 22
|
||||
|
||||
local d = 1
|
||||
while MTH_FX_ANIM_DEFS and d <= table.getn(MTH_FX_ANIM_DEFS) do
|
||||
local def = MTH_FX_ANIM_DEFS[d]
|
||||
if def.section == sec.id then
|
||||
local cbName = "MetaHuntOptionsAnim_" .. string.gsub(def.key, "%.", "_")
|
||||
local cb = MTH_CreateCheckbox(container, cbName, MTH_ANIM_L(def.labelKey, def.label), y, 28)
|
||||
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)
|
||||
y = y - rowStep
|
||||
end
|
||||
end
|
||||
d = d + 1
|
||||
end
|
||||
y = y - sectionGap
|
||||
s = s + 1
|
||||
end
|
||||
|
||||
MTH_ANIM_UpdateChildStates()
|
||||
MTH_ANIM_DBG.setupResult = "ok"
|
||||
end
|
||||
|
||||
-- DEBUG: mark that the whole file finished loading. TEMP diagnostic.
|
||||
MTH_ANIM_DBG.step = "2-complete"
|
||||
MTH_ANIM_DBG.hasSetup = type(MTH_SetupAnimationsOptions)
|
||||
@@ -20,6 +20,16 @@ local function MTH_OPT_L(key, default)
|
||||
return default or key
|
||||
end
|
||||
|
||||
-- Capture our PizzaSauce instance for the options-window open animation (guarded).
|
||||
local MTH_OPT_Sauce = PizzaSauce
|
||||
local function MTH_OPT_AnimateOpen(frame)
|
||||
if not MTH_OPT_Sauce or not frame then return end
|
||||
if type(MTH_FX_IsEnabled) == "function" and not MTH_FX_IsEnabled("ui.options") then return end
|
||||
-- Hide alpha this frame so there is no one-frame opaque flash before onStart.
|
||||
if type(frame.SetAlpha) == "function" then frame:SetAlpha(0) end
|
||||
MTH_OPT_Sauce:SlideIn(frame, "UP", 60, 0.4, "outCubic")
|
||||
end
|
||||
|
||||
local function MTH_RegisterEscClose(frameName)
|
||||
if not (frameName and UISpecialFrames) then
|
||||
return
|
||||
@@ -232,6 +242,13 @@ function MTH_SelectOptionsTab(tabKey)
|
||||
elseif MTH and MTH.Print then
|
||||
MTH:Print("ICU options setup function is not loaded", "error")
|
||||
end
|
||||
elseif tabKey == "Animations" then
|
||||
if not MTH_OPTIONS_SETUP["Animations"] then
|
||||
if type(MTH_SetupAnimationsOptions) == "function" then
|
||||
MTH_SetupAnimationsOptions()
|
||||
MTH_OPTIONS_SETUP["Animations"] = true
|
||||
end
|
||||
end
|
||||
elseif tabKey == "Credits" then
|
||||
local setupCredits = _G and _G["MTH_SetupCreditsOptions"]
|
||||
if type(setupCredits) == "function" then
|
||||
@@ -324,6 +341,7 @@ function MTH_OpenOptions(tabKey)
|
||||
return
|
||||
end
|
||||
optionsFrame:Show()
|
||||
MTH_OPT_AnimateOpen(optionsFrame)
|
||||
if MTH_OPTIONS_UpdateRealmGateOverlay(optionsFrame) then return end
|
||||
MTH_SelectOptionsTab(tabKey or "General")
|
||||
end
|
||||
|
||||
@@ -52,6 +52,7 @@ MTH_OPTIONS_TABS = MTH_OPTIONS_TABS or {
|
||||
{ key = "ChronometerClassSpells", label = "Hunter Spells", frame = "MetaHuntOptionsChronometer" },
|
||||
{ key = "ChronometerClassEvents", label = "Hunter Events", frame = "MetaHuntOptionsChronometer" },
|
||||
{ key = "ChronometerRacial", label = "Racial", frame = "MetaHuntOptionsChronometer" },
|
||||
{ key = "Animations", label = "Animations", frame = "MetaHuntOptionsAnimations" },
|
||||
{ key = "Credits", label = "Credits", frame = "MetaHuntOptionsCredits" },
|
||||
}
|
||||
|
||||
@@ -92,6 +93,7 @@ MTH_OPTIONS_TREE = MTH_OPTIONS_TREE or {
|
||||
{ label = "Racial", key = "ChronometerRacial" },
|
||||
},
|
||||
},
|
||||
{ label = "Animations", key = "Animations" },
|
||||
{ label = "Credits", key = "Credits" },
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +85,7 @@
|
||||
<Frame name="$parentICU" hidden="true" enableMouse="true"/>
|
||||
<Frame name="$parentExpAmmo" hidden="true" enableMouse="true"/>
|
||||
<Frame name="$parentChronometer" hidden="true" enableMouse="true"/>
|
||||
<Frame name="$parentAnimations" hidden="true" enableMouse="true"/>
|
||||
<Frame name="$parentCredits" hidden="true" enableMouse="true"/>
|
||||
|
||||
<!-- Top-right close button -->
|
||||
|
||||
Reference in New Issue
Block a user