This commit is contained in:
DuvelCorp
2026-03-31 21:25:35 +02:00
parent 680ddcba8a
commit 51d4c785fa
55 changed files with 5157 additions and 2530 deletions
-1
View File
@@ -6,7 +6,6 @@
local MTH_AutoBuy = {
name = "autobuy",
enabled = false,
version = "1.4.1",
events = {
"VARIABLES_LOADED",
"MERCHANT_SHOW",
-1
View File
@@ -6,7 +6,6 @@
local MTH_AutoQuest = {
name = "autoquest",
enabled = false,
version = "1.4.1",
events = {
"GOSSIP_SHOW",
"QUEST_GREETING",
+1 -2
View File
@@ -28,7 +28,6 @@ function MTH_ChronometerHunterInstallData(engine)
engine:AddTimer(engine.SPELL, BS["Flare"], 30, 0, 0, 0, { cr = "YELLOW", rc = true })
engine:AddTimer(engine.SPELL, BS["Hunter's Mark"], 120, 1, 0, 0, { cr = "RED", rc = true })
engine:AddTimer(engine.SPELL, BS["Immolation Trap"], 60, 0, 0, 0, { gr = 1, cr = "ORANGE", ea = { [BS["Immolation Trap Effect"]] = 60 } })
engine:AddTimer(engine.SPELL, BS["Aimed Shot"], 20, 0, 0, 0, { cr = "RED", rc = true, d = { tn = BS["Swiftshot"], tb = -2, ts = -2 } }) -- base 20s; Swiftshot reduces by 2s/rank (max -6s at rank 3)
engine:AddTimer(engine.SPELL, BS["Kill Command"], 12, 0, 0, 0, { cr = "RED", rc = true })
engine:AddTimer(engine.SPELL, BS["Rapid Fire"], 15, 0, 1, 1, { cr = "RED" })
engine:AddTimer(engine.SPELL, BS["Scare Beast"], 10, 1, 0, 0, { cr = "BLUE", rc = true, d = { rs = 5 } })
@@ -49,7 +48,7 @@ function MTH_ChronometerHunterInstallData(engine)
engine:AddTimer(engine.EVENT, BS["Immolation Trap Effect"], 15, 1, 0, 1, { gr = 1, cr = "ORANGE", xn = BS["Immolation Trap"] })
engine:AddTimer(engine.EVENT, BS["Improved Concussive Shot"], 3, 1, 0, 0, { a = 1, cr = "BLUE", xn = BS["Concussive Shot"] })
engine:AddTimer(engine.EVENT, BS["Improved Wing Clip"], 5, 1, 0, 0, { a = 1, cr = "MAROON", xn = BS["Wing Clip"] })
engine:AddTimer(engine.EVENT, BS["Lock and Load"], 10, 0, 1, 1, { a = 1, cr = "MAROON", tx = "Interface\\Icons\\ability_hunter_lockandload" }) -- 10s (tooltip confirmed; expires on Aimed Shot cast)
engine:AddTimer(engine.EVENT, BS["Lock and Load"], 10, 0, 1, 1, { a = 1, cr = "MAROON", tx = "Interface\\Icons\\ability_hunter_lockandload" }) -- 10s (tooltip confirmed; expires when consumed)
engine:AddTimer(engine.EVENT, BS["Scent of Blood"], 8, 0, 1, 1, { a = 1, cr = "RED" })
engine:AddTimer(engine.EVENT, BS["Piercing Shot"], 8, 1, 0, 1, { a = 1, cr = "PURPLE", tx = "Interface\\Icons\\Ability_Hunter_DisarmingShot" })
engine:AddTimer(engine.EVENT, BS["Entrapment"], 5, 1, 0, 1, { a = 1, cr = "MAROON", tx = "Interface\\Icons\\Spell_Nature_StrangleVines" })
+114 -2
View File
@@ -58,6 +58,18 @@ Chronometer.dataSetup = {}
local latins = { I = 1, II = 2, III = 3, IV = 4, V = 5, VI = 6, VII = 7, VIII = 8, IX = 9, X = 10, XI = 11, XII = 12, XIII = 13, XIV = 14 }
local BAR_GROUP = "MTHChronometer"
-- When growing up the group attachment point must flip so bars stack above the
-- anchor rather than below it. CandyBar uses the stored group point as-is when
-- positioning each bar, so SetCandyBarGroupGrowth alone is not enough.
local function applyGrowup(self, growup)
if growup then
self:SetCandyBarGroupPoint(BAR_GROUP, "BOTTOM", self.anchor, "TOP", 0, 0)
else
self:SetCandyBarGroupPoint(BAR_GROUP, "TOP", self.anchor, "BOTTOM", 0, 0)
end
self:SetCandyBarGroupGrowth(BAR_GROUP, growup)
end
local PARSER_OWNER = "MTHChronometerHunter"
@@ -556,7 +568,7 @@ function Chronometer:OnEnable()
self._mth_enabled = true
self.profile = ensureProfile()
self:SetCandyBarGroupGrowth(BAR_GROUP, self.profile.growup and true or false)
applyGrowup(self, self.profile.growup and true or false)
self:SetCandyBarGroupVerticalSpacing(BAR_GROUP, self.profile.spacing or 0)
if self.anchor then
end
@@ -650,15 +662,34 @@ function Chronometer:OnEnable()
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_SELF_DAMAGE", function(event, info) self:SELF_DAMAGE(event, info) end)
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_DAMAGESHIELDS_ON_SELF", function(event, info) self:SELF_DAMAGE(event, info) end)
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_FAILED_LOCALPLAYER", function(event, info) self:SPELL_FAILED(event, info) end)
-- NamPower: register authoritative self-aura events for instant bar
-- kill and duration resync. The ParserLib chat paths remain active as
-- they handle creature/target debuffs that NamPower cannot see.
if MTH and MTH.nampower then
self._nampowerSpellIdCache = {}
self:RegisterEvent("BUFF_ADDED_SELF")
self:RegisterEvent("BUFF_REMOVED_SELF")
self:RegisterEvent("DEBUFF_ADDED_SELF")
self:RegisterEvent("DEBUFF_REMOVED_SELF")
end
end
function Chronometer:VARIABLES_LOADED()
self.profile = ensureProfile()
if self._mth_enabled then
applyGrowup(self, self.profile.growup and true or false)
self:SetCandyBarGroupVerticalSpacing(BAR_GROUP, self.profile.spacing or 0)
end
MTH_CHRON_RestoreAnchorFromProfile(self, "VARIABLES_LOADED")
end
function Chronometer:PLAYER_ENTERING_WORLD()
self.profile = ensureProfile()
if self._mth_enabled then
applyGrowup(self, self.profile.growup and true or false)
self:SetCandyBarGroupVerticalSpacing(BAR_GROUP, self.profile.spacing or 0)
end
MTH_CHRON_RestoreAnchorFromProfile(self, "PLAYER_ENTERING_WORLD")
end
@@ -1249,6 +1280,85 @@ function Chronometer:CreateAnchor(text, r, g, b)
return frame
end
-- ────────────────────────────────────────────────────────────
-- NamPower self-aura handlers
-- ────────────────────────────────────────────────────────────
-- Helper: resolve spellId → spell name, with cache
local function NP_ResolveName(cache, spellId)
if not spellId or spellId == 0 then return nil end
local name = cache[spellId]
if name then return name end
name = GetSpellRecField(spellId, "name")
if name and name ~= "" then
cache[spellId] = name
return name
end
return nil
end
-- BUFF / DEBUFF removed from the player → kill matching self-bar instantly
function Chronometer:BUFF_REMOVED_SELF()
if not self.profile.fadeonfade then return end
local spellId = arg3
local name = NP_ResolveName(self._nampowerSpellIdCache, spellId)
if not name then return end
self:KillBar(name)
end
Chronometer.DEBUFF_REMOVED_SELF = Chronometer.BUFF_REMOVED_SELF
-- BUFF / DEBUFF added to the player → resync running bar duration
function Chronometer:BUFF_ADDED_SELF()
local spellId = arg3
local name = NP_ResolveName(self._nampowerSpellIdCache, spellId)
if not name then return end
-- Find the matching self-bar
local bar = nil
for i = 1, 20 do
if self.bars[i].id and self.bars[i].name == name then
local tgt = self.bars[i].target
if tgt == "none" or tgt == UnitName("player") then
bar = self.bars[i]
break
end
end
end
if not bar then return end
-- Get authoritative remaining duration from NamPower aura array
local remaining = nil
local auras = GetUnitField("player", "aura")
if auras then
for slot = 1, 48 do
if auras[slot] == spellId then
local _, ms = GetPlayerAuraDuration(slot - 1)
if ms and ms > 0 then
remaining = ms / 1000
end
break
end
end
end
if not remaining then
-- Fallback: use base DBC duration
local dms = GetSpellDuration(spellId)
if dms and dms > 0 then
remaining = dms / 1000
end
end
if not remaining then return end
-- Resync: update total first (allows SetTimeLeft to extend), then set remaining
self:SetCandyBarTime(bar.id, remaining)
self:SetCandyBarTimeLeft(bar.id, remaining)
end
Chronometer.DEBUFF_ADDED_SELF = Chronometer.BUFF_ADDED_SELF
-- ────────────────────────────────────────────────────────────
function Chronometer:COMBAT_DEATH(event, info)
if not self.profile.fadeonkill then return end
if info.type == "experience" then
@@ -1399,7 +1509,9 @@ function Chronometer:UNIT_AURA(unit)
end
local hasFeedAura = false
if type(UnitBuff) == "function" then
if type(MTH_FEED_HasPetFeedBuff) == "function" then
hasFeedAura = MTH_FEED_HasPetFeedBuff()
elseif type(UnitBuff) == "function" then
for i = 1, 32 do
local texture = UnitBuff("pet", i)
if not texture then
-1
View File
@@ -1,7 +1,6 @@
local MTH_ChronometerModule = {
name = "chronometer",
enabled = true,
version = "1.4.1",
events = {},
initialized = false,
}
+668 -246
View File
File diff suppressed because it is too large Load Diff
+49 -2
View File
@@ -125,6 +125,11 @@ FOM_FamilyToLegacyMap = {
-- [DISABLED] NO-BUFF quarantine: set to true to re-enable.
-- When false, failed feeds are still logged but items are never
-- blacklisted and the quarantine store is never consulted.
local FOM_QUARANTINE_ENABLED = false;
local function FOM_GetServerProfile()
return FOM_ServerProfiles[FOM_SERVER_PROFILE] or {};
end
@@ -186,6 +191,7 @@ local function FOM_GetFamilyKeyFromInfo(petInfo)
end
local function FOM_RegisterNoBuffQuarantine(itemID, petInfo)
if (not FOM_QUARANTINE_ENABLED) then return; end
local numericItem = tonumber(itemID);
if (numericItem == nil) then
return;
@@ -217,6 +223,7 @@ local function FOM_RegisterNoBuffQuarantine(itemID, petInfo)
end
local function FOM_IsQuarantined(itemID, petLevel, familyKey)
if (not FOM_QUARANTINE_ENABLED) then return false; end
local numericItem = tonumber(itemID);
local numericPet = tonumber(petLevel);
if (numericItem == nil or numericPet == nil or numericPet <= 0) then
@@ -1187,7 +1194,7 @@ function FOM_OnUpdate(elapsed)
FOM_CoreFinalizeAttempt(FOM_LastFeedAttempt.coreAttemptId, "rejected", "no-buff");
local currentPetInfo = MTH_FOM_GetCorePetInfo();
FOM_RegisterNoBuffQuarantine(FOM_LastFeedAttempt.itemId, currentPetInfo);
if (type(MTH_FEED_BlockItemForPetLevel) == "function") then
if (FOM_QUARANTINE_ENABLED and type(MTH_FEED_BlockItemForPetLevel) == "function") then
pcall(MTH_FEED_BlockItemForPetLevel,
FOM_LastFeedAttempt.itemId,
tonumber(currentPetInfo and currentPetInfo.level) or nil,
@@ -1274,6 +1281,43 @@ function FOM_CanFeed()
end
-- NamPower path: scan aura array by spellId → name, no tooltip needed
if MTH and MTH.nampower and type(GetUnitField) == "function" and type(GetSpellRecField) == "function" then
local auras = GetUnitField("player", "aura")
if type(auras) == "table" then
local dontFeedNames = {
["Shadowmeld"] = true,
["Feign Death"] = true,
["Food"] = true,
["Drink"] = true,
["Refreshment"] = true,
}
for i = 1, 32 do
local sid = tonumber(auras[i])
if sid and sid > 0 then
local name = GetSpellRecField(sid, "name")
if name then
if dontFeedNames[name] then
FOM_DebugLog("Can't feed; buff detected: " .. name)
return false
end
if UnitLevel("player") >= 40 then
local lname = string.lower(name)
for _, mountSub in FOM_MOUNT_NAME_SUBSTRINGS do
if string.find(lname, mountSub) then
FOM_DebugLog("Can't feed; mounted (" .. name .. ").")
return false
end
end
end
end
end
end
end
return true
end
-- Legacy path: texture + tooltip scanning
local buff, buffIndex;
local dontFeedBuffTextures = {
"Interface\\Icons\\Ability_Ambush", -- NE Shadowmeld (maybe not unique buff icon?)
@@ -1936,7 +1980,7 @@ function FOM_RemoveFood(diet, food)
end
-- Clear quarantine, core exception blocks, and RemovedFoods ban for a specific item (called when user explicitly re-adds via /fom add)
local function FOM_ClearItemBans(itemID)
function FOM_ClearItemBans(itemID)
local numericItem = tonumber(itemID);
if (numericItem == nil) then return; end
-- Clear from RemovedFoods across all diet lists
@@ -2076,6 +2120,9 @@ end
-- Check Feed Effect
function FOM_HasFeedEffect()
if type(MTH_FEED_HasPetFeedBuff) == "function" then
return MTH_FEED_HasPetFeedBuff()
end
local i = 1;
local buff;
-1
View File
@@ -6,7 +6,6 @@
local MTH_FeedOMatic = {
name = "feedomatic",
enabled = false,
version = "1.4.1",
events = {
"VARIABLES_LOADED",
"MERCHANT_SHOW",
-1
View File
@@ -6,7 +6,6 @@
local MTH_ICU = {
name = "icu",
enabled = false,
version = "1.4.1",
events = {
"VARIABLES_LOADED",
},
-1
View File
@@ -7,7 +7,6 @@ MTH_SA_MANAGED_HOOKS = true
local MTH_SmartAmmo = {
name = "smartammo",
enabled = true,
version = "1.4.1",
events = {
"VARIABLES_LOADED",
-- PLAYER_ENTERING_WORLD handled by engine's own frame
+2 -17
View File
@@ -6,7 +6,6 @@
local MTH_Tooltips = {
name = "tooltips",
enabled = true,
version = "1.4.1",
events = {
"UPDATE_MOUSEOVER_UNIT",
"UNIT_NAME_UPDATE",
@@ -1486,11 +1485,8 @@ local function MTH_TT_AddTooltip(unit)
local ammoVendorTooltipsEnabled = MTH_TT_IsAmmoVendorTooltipsEnabled()
local vendorInfo = ammoVendorTooltipsEnabled and MTH_TT_FindVendorInfo(name) or nil
local row = beastTooltipsEnabled and MTH_TT_FindBeastRow(name) or nil
local savedEntry = beastTooltipsEnabled
and (type(MTH_BLS_FindSavedBeastByName) == "function")
and MTH_BLS_FindSavedBeastByName(name) or nil
local scorpokAdded = MTH_TT_AddScorpokTargetsTooltip(unit, name)
if not row and not vendorInfo and not scorpokAdded and not savedEntry then
if not row and not vendorInfo and not scorpokAdded then
state.lookupMiss = (state.lookupMiss or 0) + 1
MTH_TT_StateSet("lookup-miss", name, normalized)
MTH_TT_Log("lookup miss: unit='" .. tostring(name) .. "' normalized='" .. tostring(normalized) .. "'")
@@ -1514,13 +1510,7 @@ local function MTH_TT_AddTooltip(unit)
MTH_TT_Log("vendor tooltip added: unit='" .. tostring(name) .. "'")
end
-- Determine which abilities source to display.
local abilitiesSource = nil
if row then
abilitiesSource = row.abilities
elseif savedEntry and savedEntry.abilities and savedEntry.abilities ~= "" then
abilitiesSource = savedEntry.abilities
end
local abilitiesSource = row and row.abilities or nil
if abilitiesSource then
local abilities = MTH_TT_ParseAbilities(abilitiesSource)
@@ -1546,11 +1536,6 @@ local function MTH_TT_AddTooltip(unit)
end
end
if savedEntry then
GameTooltip:AddLine("Beast recorded by you", 1.0, 0.85, 0.0)
addedAnything = 1
end
if addedAnything then
GameTooltip:Show()
state.added = (state.added or 0) + 1
+11 -2
View File
@@ -67,6 +67,8 @@ local function ZHunterMod_EnsureButtonFrame(buttonName)
created:SetPoint("TOP", UIParent, "TOP", 0, -464)
elseif buttonName == "zButtonToys" then
created:SetPoint("TOP", UIParent, "TOP", 0, -518)
elseif buttonName == "zButtonCraft" then
created:SetPoint("TOP", UIParent, "TOP", 0, -572)
else
created:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
end
@@ -85,7 +87,7 @@ function ZHunterMod_DeferredInit()
local mounts = ZHunterMod_EnsureButtonFrame("zButtonMounts")
local companions = ZHunterMod_EnsureButtonFrame("zButtonCompanions")
local toys = ZHunterMod_EnsureButtonFrame("zButtonToys")
local craft = ZHunterMod_EnsureButtonFrame("zButtonCraft")
-- Continue with all frames that exist; do not hard-abort when one optional frame is missing.
local missing = {}
@@ -98,12 +100,13 @@ function ZHunterMod_DeferredInit()
if not mounts then table.insert(missing, "Mounts") end
if not companions then table.insert(missing, "Companions") end
if not toys then table.insert(missing, "Toys") end
if not craft then table.insert(missing, "Craft") end
if table.getn(missing) > 0 then
MTH_ZH_Print("[ZHUNTER] Warning: missing frames: " .. table.concat(missing, ", ") .. ". Continuing with available buttons.", "error")
end
if not (pet or aspect or track or trap or ranged or ammo or mounts or companions or toys) then
if not (pet or aspect or track or trap or ranged or ammo or mounts or companions or toys or craft) then
MTH_ZH_Print("zhunter buttons not created - check for addon conflicts!", "error")
return
end
@@ -178,6 +181,12 @@ function ZHunterMod_DeferredInit()
end
end
if craft and zButtonCraft_OnEvent then
if ZHunterMod_SafeRunButtonInit(craft, zButtonCraft_OnEvent, "zButtonCraft") then
initialized = initialized + 1
end
end
if initialized <= 0 then
MTH_ZH_Print("zhunter buttons not created - check for addon conflicts!", "error")
return
+40 -13
View File
@@ -138,7 +138,6 @@ local function ZHunterMod_UpdateButtonCount(parent, found)
end
function ZSpellButton_SetExpandDirection(parent, direction)
local button = getglobal(parent.name.."1")
local offset = parent:GetWidth() / 36
local circleVisible = true
if type(MTH_ZH_GetSavedTable) == "function" and parent and parent.name then
@@ -154,11 +153,14 @@ function ZSpellButton_SetExpandDirection(parent, direction)
parent.circle:Hide()
end
end
-- Children have not been created yet; circle state is already updated above.
if not (parent and parent.name) then return end
if circleVisible then
offset = offset * 5
else
offset = offset * 3
end
local button = getglobal(parent.name.."1")
button:ClearAllPoints()
if direction == "TOP" then
button:SetPoint("BOTTOM", parent, "TOP", 0, offset)
@@ -683,28 +685,53 @@ function ZSpellButtonParent_OnLoad()
if this.SetScript then
this:SetScript("OnDragStart", function()
if IsAltKeyDown() then
this:StartMoving()
this.isMoving = true
if type(MTH_ZBar_IsActive) == "function" and MTH_ZBar_IsActive() then
-- Alt+drag any bar button to move the whole zBar via its invisible anchor
local anchor = type(MTH_ZBar_GetAnchor) == "function" and MTH_ZBar_GetAnchor()
if anchor then
anchor:StartMoving()
anchor.isMoving = true
end
else
this:StartMoving()
this.isMoving = true
end
end
end)
this:SetScript("OnDragStop", function()
if not this then
return
if not this then return end
if type(MTH_ZBar_IsActive) == "function" and MTH_ZBar_IsActive() then
local anchor = type(MTH_ZBar_GetAnchor) == "function" and MTH_ZBar_GetAnchor()
if anchor and anchor.isMoving then
if anchor.StopMovingOrSizing then anchor:StopMovingOrSizing() end
anchor.isMoving = false
if type(MTH_ZBar_SavePosition) == "function" then MTH_ZBar_SavePosition() end
if type(MTH_ZBar_ApplyLayout) == "function" then MTH_ZBar_ApplyLayout() end
end
else
if this.StopMovingOrSizing then this:StopMovingOrSizing() end
ZSpellButton_SaveParentPosition(this)
this.isMoving = false
end
if this.StopMovingOrSizing then
this:StopMovingOrSizing()
end
ZSpellButton_SaveParentPosition(this)
this.isMoving = false
end)
this:SetScript("OnMouseUp", function()
if this and this.isMoving then
if this.StopMovingOrSizing then
this:StopMovingOrSizing()
if this.StopMovingOrSizing then this:StopMovingOrSizing() end
if not (type(MTH_ZBar_IsActive) == "function" and MTH_ZBar_IsActive()) then
ZSpellButton_SaveParentPosition(this)
end
ZSpellButton_SaveParentPosition(this)
this.isMoving = false
end
-- Fallback: finish anchor movement started from OnDragStart
if type(MTH_ZBar_IsActive) == "function" and MTH_ZBar_IsActive() then
local anchor = type(MTH_ZBar_GetAnchor) == "function" and MTH_ZBar_GetAnchor()
if anchor and anchor.isMoving then
if anchor.StopMovingOrSizing then anchor:StopMovingOrSizing() end
anchor.isMoving = false
if type(MTH_ZBar_SavePosition) == "function" then MTH_ZBar_SavePosition() end
if type(MTH_ZBar_ApplyLayout) == "function" then MTH_ZBar_ApplyLayout() end
end
end
end)
end
end
+6
View File
@@ -22,6 +22,7 @@ Loads all zhunter addon code and wraps it in the MTH module system
<Include file="zButtonMounts.xml"/>
<Include file="zButtonCompanions.xml"/>
<Include file="zButtonToys.xml"/>
<Include file="zButtonCraft.xml"/>
<!-- Load main ZHunterMod.lua FIRST so ZHunterMod_Saved table exists before button files use it -->
<Include file="ZHunterMod.lua"/>
@@ -47,6 +48,11 @@ Loads all zhunter addon code and wraps it in the MTH module system
<Include file="zButtonCompanions.lua"/>
<Include file="zButtonToys.lua"/>
<Include file="zButtonCraft.lua"/>
<!-- zBar: unified draggable anchor bar (must load after all zButton files) -->
<Include file="zBar.lua"/>
<!-- Deferred initialization - runs LAST after all parsing is complete -->
<Include file="DeferredInit.lua"/>
+9 -2
View File
@@ -8,7 +8,6 @@ MTH_ZH_MANAGED_HOOKS = true
local MTH_ZHunter = {
name = "zhunter",
enabled = true,
version = "1.4.1",
events = {
"VARIABLES_LOADED",
-- PLAYER_ENTERING_WORLD handled by bootstrap frame + adjustment frames
@@ -59,6 +58,7 @@ local function MTH_ZH_ApplyDefaultWidgetSpawnLayoutOnce()
"zButtonMounts",
"zButtonCompanions",
"zButtonToys",
"zButtonCraft",
}
local startY = -140
@@ -191,6 +191,7 @@ MTH_ZH_SetButtonsVisible = function(visible)
"zButtonMounts",
"zButtonCompanions",
"zButtonToys",
"zButtonCraft",
}
local function MTH_ZH_SetChildButtonsVisible(parentButton, parentName, show)
@@ -303,6 +304,7 @@ local function MTH_ZH_SetAdjustmentHandlersActive(active)
{ frame = "MTH_ZH_MountsAdjust", handler = "MTH_ZH_MountsAdjust_OnEvent", getter = "zButtonMounts_GetSaved" },
{ frame = "MTH_ZH_CompanionsAdjust", handler = "MTH_ZH_CompanionsAdjust_OnEvent", getter = "zButtonCompanions_GetSaved" },
{ frame = "MTH_ZH_ToysAdjust", handler = "MTH_ZH_ToysAdjust_OnEvent", getter = "zButtonToys_GetSaved" },
{ frame = "MTH_ZH_CraftAdjust", handler = "MTH_ZH_CraftAdjust_OnEvent", getter = "zButtonCraft_GetSaved" },
}
local function isFeatureEnabled(getterName)
@@ -348,7 +350,9 @@ local function MTH_ZH_ClearRuntimeFeatureFlags()
end
MTH_ZH_RestoreRuntimeFeatureFlags = function()
return
if type(MTH_ZBar_Init) == "function" then
MTH_ZBar_Init()
end
end
function MTH_ZHunter:init()
@@ -372,6 +376,9 @@ function MTH_ZHunter:setEnabled(enabled)
MTH_ZH_SetAdjustmentHandlersActive(false)
MTH_ZH_SetButtonsVisible(false)
MTH_ZH_SetAuxFramesVisible(false)
-- Hide the zBar anchor so it doesn't float while the module is off
local zbarAnchor = getglobal("MTH_ZBar_Anchor")
if zbarAnchor then zbarAnchor:Hide() end
end
end
+333
View File
@@ -0,0 +1,333 @@
-- zBar: Unified draggable anchor bar for all zButton parent buttons.
-- When enabled, all included zButton parents are anchored to the zBar anchor
-- in a configurable row (horizontal) or column (vertical).
-- Individual Alt+drag on each zButton is suppressed while zBar is active.
local ZBAR_FRAME_NAME = "MTH_ZBar_Anchor"
local ZBAR_ALL_BUTTONS = {
"zButtonAspect",
"zButtonAmmo",
"zButtonTrack",
"zButtonTrap",
"zButtonPet",
"zButtonRanged",
"zButtonMounts",
"zButtonCompanions",
"zButtonToys",
"zButtonCraft",
}
local ZBAR_BUTTON_LABELS = {
zButtonAspect = "zAspect",
zButtonAmmo = "zAmmo",
zButtonTrack = "zTrack",
zButtonTrap = "zTrap",
zButtonPet = "zPet",
zButtonRanged = "zRanged",
zButtonMounts = "zMounts",
zButtonCompanions = "zCompanions",
zButtonToys = "zToys",
zButtonCraft = "zCraft",
}
function MTH_ZBar_GetAllButtons()
return ZBAR_ALL_BUTTONS
end
function MTH_ZBar_GetAllButtonLabels()
return ZBAR_BUTTON_LABELS
end
-- Returns (and initialises on first access) the _zbar saved-variable table.
function MTH_ZBar_GetSaved()
local root = MTH_ZH_GetSavedRoot()
if type(root["_zbar"]) ~= "table" then
root["_zbar"] = {}
end
local s = root["_zbar"]
if s.enabled == nil then s.enabled = false end
if s.direction == nil then s.direction = "HORIZONTAL" end
if type(s.spacing) ~= "number" then s.spacing = 4 end
if type(s.size) ~= "number" then s.size = 36 end
-- childexpand: which side children appear on (TOP/BOTTOM for H bar, LEFT/RIGHT for V bar)
if s.childexpand == nil then s.childexpand = "BOTTOM" end
-- childarrange: how children #2+ are laid out (VERTICAL=column, HORIZONTAL=row)
if s.childarrange == nil then s.childarrange = "VERTICAL" end
if type(s.order) ~= "table" then
s.order = {}
for i = 1, table.getn(ZBAR_ALL_BUTTONS) do
s.order[i] = ZBAR_ALL_BUTTONS[i]
end
end
if type(s.visible) ~= "table" then
s.visible = {}
end
-- Migration: ensure every known button is present in the order list and
-- has an explicit visible entry.
local present = {}
for _, v in ipairs(s.order) do
present[v] = true
end
for _, v in ipairs(ZBAR_ALL_BUTTONS) do
if not present[v] then
table.insert(s.order, v)
end
if s.visible[v] == nil then
s.visible[v] = true
end
end
return s
end
-- Returns true when the zBar feature is both enabled AND the anchor frame
-- has been created in memory.
function MTH_ZBar_IsActive()
local s = MTH_ZBar_GetSaved()
return (s.enabled == true) and (getglobal(ZBAR_FRAME_NAME) ~= nil)
end
-- ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
-- Position persistence
-- ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
function MTH_ZBar_SavePosition()
local bar = getglobal(ZBAR_FRAME_NAME)
if not (bar and bar.GetPoint) then return end
local s = MTH_ZBar_GetSaved()
local point, _, relPoint, x, y = bar:GetPoint()
if not point then return end
s.point = tostring(point)
s.relPoint = tostring(relPoint or point)
s.x = math.floor((tonumber(x) or 0) + 0.5)
s.y = math.floor((tonumber(y) or 0) + 0.5)
end
-- ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
-- Anchor frame creation
-- ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
-- Returns the invisible anchor frame (used internally and by button drag code).
function MTH_ZBar_GetAnchor()
return getglobal(ZBAR_FRAME_NAME)
end
function MTH_ZBar_EnsureAnchor()
local existing = getglobal(ZBAR_FRAME_NAME)
if existing then
existing:Show()
return existing
end
local s = MTH_ZBar_GetSaved()
-- Invisible 1x1 movable frame — used only as a position anchor for the bar.
-- Users interact via the zButton buttons themselves (Alt+drag any of them).
local bar = CreateFrame("Frame", ZBAR_FRAME_NAME, UIParent)
if not bar then return nil end
bar:SetWidth(1)
bar:SetHeight(1)
bar:SetFrameStrata("MEDIUM")
bar:SetFrameLevel(5)
bar:SetMovable(true)
bar:SetClampedToScreen(true)
-- Restore saved position (or fall back to a sensible default)
bar:ClearAllPoints()
if s.point and s.x and s.y then
bar:SetPoint(s.point, UIParent, s.relPoint or s.point, s.x, s.y)
else
bar:SetPoint("TOPLEFT", UIParent, "TOPLEFT", 400, -140)
end
bar:Show()
return bar
end
-- ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
-- Layout engine
-- ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
-- Anchors every included+enabled zButton parent relative to the zBar anchor
-- (or the previous button in the chain).
function MTH_ZBar_ApplyLayout()
local s = MTH_ZBar_GetSaved()
if not s.enabled then return end
local bar = getglobal(ZBAR_FRAME_NAME)
if not bar then return end
local direction = s.direction or "HORIZONTAL"
local spacing = tonumber(s.spacing) or 4
local prevFrame = bar
local count = 0
local placed = {}
for i = 1, table.getn(s.order) do
local buttonName = s.order[i]
if type(buttonName) == "string" then
local btn = getglobal(buttonName)
local globalEnabled = ZHunterMod_Saved
and type(ZHunterMod_Saved[buttonName]) == "table"
and ZHunterMod_Saved[buttonName]["enabled"] ~= false
and ZHunterMod_Saved[buttonName]["enabled"] ~= 0
local zbarVisible = s.visible[buttonName] ~= false
if btn and globalEnabled and zbarVisible then
btn:ClearAllPoints()
if direction == "HORIZONTAL" then
btn:SetPoint("LEFT", prevFrame, "RIGHT", spacing, 0)
else
btn:SetPoint("TOP", prevFrame, "BOTTOM", 0, -spacing)
end
-- Size, expand direction and child arrangement are handled by each
-- bar's own _SetupSizeAndPosition, which now calls MTH_ZBar_ApplyToButton.
local setupFunc = getglobal(buttonName .. "_SetupSizeAndPosition")
if type(setupFunc) == "function" then
setupFunc()
end
prevFrame = btn
count = count + 1
placed[buttonName] = true
end
end
end
-- For every button NOT placed in the bar, call its own setup function so that:
-- * disabled buttons get Hide() called on them immediately
-- * excluded buttons get their individual size/expand/position applied
for _, buttonName in ipairs(ZBAR_ALL_BUTTONS) do
if not placed[buttonName] then
local setupFunc = getglobal(buttonName .. "_SetupSizeAndPosition")
if type(setupFunc) == "function" then
setupFunc()
end
end
end
end
-- ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
-- Per-button zBar override (called from each zButton's _SetupSizeAndPosition)
-- ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
-- When zBar is active this is the MASTER for size, expand direction and child
-- layout. Each zButton's _SetupSizeAndPosition calls this first; if it returns
-- true the bar must skip its own saved settings entirely.
function MTH_ZBar_ApplyToButton(btn, displayCount)
if not (type(MTH_ZBar_IsActive) == "function" and MTH_ZBar_IsActive()) then
return false
end
local s = MTH_ZBar_GetSaved()
local btnKey = (btn and btn.name) or (btn and btn.GetName and btn:GetName()) or ""
-- Only take master control if this button is actually placed in the active bar.
local globalEnabled = ZHunterMod_Saved
and type(ZHunterMod_Saved[btnKey]) == "table"
and ZHunterMod_Saved[btnKey]["enabled"] ~= false
and ZHunterMod_Saved[btnKey]["enabled"] ~= 0
if not globalEnabled or s.visible[btnKey] == false then
return false
end
local btnSize = tonumber(s.size) or 36
local expandDir = s.childexpand or "BOTTOM"
local arrange = s.childarrange or "VERTICAL"
local arHoriz = (expandDir == "LEFT")
local arVert = (expandDir == "TOP")
ZSpellButton_SetSize(btn, btnSize)
ZSpellButton_SetExpandDirection(btn, expandDir)
if displayCount and displayCount > 1 then
local rows = (arrange == "VERTICAL") and displayCount or 1
ZSpellButton_ArrangeChildren(btn, rows, displayCount, arHoriz, arVert)
end
if btn.circle then btn.circle:Hide() end
return true
end
-- ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
-- Enable / disable
-- ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
-- Restores each bar to its individually saved position and hides the anchor.
function MTH_ZBar_Release()
local bar = getglobal(ZBAR_FRAME_NAME)
if bar then bar:Hide() end
for _, buttonName in ipairs(ZBAR_ALL_BUTTONS) do
local btn = getglobal(buttonName)
if btn and ZHunterMod_Saved and type(ZHunterMod_Saved[buttonName]) == "table" then
-- Restore individually saved position
local parentSaved = ZHunterMod_Saved[buttonName]["parent"]
if type(parentSaved) == "table" then
local px = tonumber(parentSaved["x"])
local py = tonumber(parentSaved["y"])
local point = parentSaved["point"]
local rPoint = parentSaved["relativePoint"] or point
if px and py and type(point) == "string" and point ~= "" then
btn:ClearAllPoints()
btn:SetPoint(point, UIParent, rPoint, px, py)
end
end
-- Restore size, circle, expand direction and child layout from the bar's own saved settings
local setupFunc = getglobal(buttonName .. "_SetupSizeAndPosition")
if type(setupFunc) == "function" then
setupFunc()
end
end
end
end
-- Called when the user toggles the Enable checkbox in the options.
function MTH_ZBar_SetEnabled(enabled)
local s = MTH_ZBar_GetSaved()
s.enabled = enabled and true or false
if enabled then
MTH_ZBar_EnsureAnchor()
MTH_ZBar_ApplyLayout()
else
MTH_ZBar_Release()
end
end
-- Resize all bar buttons (and persist the value).
function MTH_ZBar_SetSize(size)
local s = MTH_ZBar_GetSaved()
s.size = tonumber(size) or 36
if s.enabled and type(MTH_ZBar_ApplyLayout) == "function" then
MTH_ZBar_ApplyLayout()
end
end
-- Called from DeferredInit / RestoreRuntimeFeatureFlags after saved vars are
-- fully loaded; creates the anchor and applies layout only when enabled.
function MTH_ZBar_Init()
local s = MTH_ZBar_GetSaved()
-- One-time migration: fix firstbutton values corrupted to "BOTTOM" by an
-- early version of zBar that incorrectly wrote per-bar saved variables.
if not s._firstbutton_fixed then
for _, buttonName in ipairs(ZBAR_ALL_BUTTONS) do
if ZHunterMod_Saved and type(ZHunterMod_Saved[buttonName]) == "table" then
if ZHunterMod_Saved[buttonName]["firstbutton"] == "BOTTOM" then
ZHunterMod_Saved[buttonName]["firstbutton"] = "RIGHT"
end
end
end
s._firstbutton_fixed = true
-- Re-run each bar's own setup now so the fix takes immediate visual effect
for _, buttonName in ipairs(ZBAR_ALL_BUTTONS) do
local setupFunc = getglobal(buttonName .. "_SetupSizeAndPosition")
if type(setupFunc) == "function" then setupFunc() end
end
end
if s.enabled then
MTH_ZBar_EnsureAnchor()
MTH_ZBar_ApplyLayout()
end
end
+8 -6
View File
@@ -898,12 +898,14 @@ function zButtonAmmo_SetupSizeAndPosition()
if arrangeCount < 0 then
arrangeCount = 0
end
ZSpellButton_SetSize(zButtonAmmo, saved["parent"]["size"])
ZSpellButton_SetSize(zButtonAmmo, saved["children"]["size"], 1)
ZSpellButton_SetExpandDirection(zButtonAmmo, saved["firstbutton"])
ZSpellButton_ArrangeChildren(zButtonAmmo, saved["rows"],
arrangeCount, saved["horizontal"],
saved["vertical"])
if not (type(MTH_ZBar_ApplyToButton) == "function" and MTH_ZBar_ApplyToButton(zButtonAmmo, arrangeCount)) then
ZSpellButton_SetSize(zButtonAmmo, saved["parent"]["size"])
ZSpellButton_SetSize(zButtonAmmo, saved["children"]["size"], 1)
ZSpellButton_SetExpandDirection(zButtonAmmo, saved["firstbutton"])
ZSpellButton_ArrangeChildren(zButtonAmmo, saved["rows"],
arrangeCount, saved["horizontal"],
saved["vertical"])
end
end
function zButtonAmmo_Reset()
+36 -13
View File
@@ -39,6 +39,7 @@ local zButtonAspect_MinAuraIntervalCombat = 0.60
local zButtonAspect_LastAuraTexture = nil
local zButtonAspect_LastParentId = nil
local zButtonAspect_AuraProbeTextLeft1 = nil
local MTH_ZH_UseNamPower = false
local function zButtonAspect_GetSaved()
local currentRoot = zButtonAspect_GetRoot()
@@ -72,6 +73,9 @@ local function zButtonAspect_EnsureConfig()
if saved["parent"]["circle"] == nil then
saved["parent"]["circle"] = 1
end
if saved["parent"]["smart"] == nil then
saved["parent"]["smart"] = true
end
if not saved["children"] then
saved["children"] = {}
end
@@ -167,6 +171,12 @@ function zButtonAspect_OnEvent()
MTH_ZH_AspectAdjust:RegisterEvent("CHARACTER_POINTS_CHANGED")
MTH_ZH_AspectAdjust:RegisterEvent("LEARNED_SPELL_IN_TAB")
MTH_ZH_AspectAdjust:SetScript("OnEvent", MTH_ZH_AspectAdjust_OnEvent)
if MTH and MTH.nampower then
MTH_ZH_UseNamPower = true
MTH_ZH_AspectAdjust:UnregisterEvent("PLAYER_AURAS_CHANGED")
MTH_ZH_AspectAdjust:RegisterEvent("BUFF_ADDED_SELF")
MTH_ZH_AspectAdjust:RegisterEvent("BUFF_REMOVED_SELF")
end
zButtonAspect_Tooltip = CreateFrame("GameTooltip", "MTH_ZH_AspectProbe", nil, "GameTooltipTemplate")
if zButtonAspect_Tooltip and zButtonAspect_Tooltip.GetName then
local tooltipName = zButtonAspect_Tooltip:GetName()
@@ -221,12 +231,14 @@ function zButtonAspect_SetupSizeAndPosition()
if displayCount < 0 then
displayCount = 0
end
ZSpellButton_SetSize(zButtonAspect, saved["parent"]["size"])
ZSpellButton_SetSize(zButtonAspect, saved["children"]["size"], 1)
ZSpellButton_SetExpandDirection(zButtonAspect, saved["firstbutton"])
ZSpellButton_ArrangeChildren(zButtonAspect, saved["rows"],
displayCount, saved["horizontal"],
saved["vertical"])
if not (type(MTH_ZBar_ApplyToButton) == "function" and MTH_ZBar_ApplyToButton(zButtonAspect, displayCount)) then
ZSpellButton_SetSize(zButtonAspect, saved["parent"]["size"])
ZSpellButton_SetSize(zButtonAspect, saved["children"]["size"], 1)
ZSpellButton_SetExpandDirection(zButtonAspect, saved["firstbutton"])
ZSpellButton_ArrangeChildren(zButtonAspect, saved["rows"],
displayCount, saved["horizontal"],
saved["vertical"])
end
end
function zButtonAspect_Reset()
@@ -255,7 +267,11 @@ function MTH_ZH_AspectAdjust_OnEvent()
if not zButtonAspect or not zButtonAspect.count then
return
end
if event == "PLAYER_AURAS_CHANGED" then
if event == "BUFF_ADDED_SELF" or event == "BUFF_REMOVED_SELF" then
-- NamPower: targeted event, no throttle needed.
-- arg3 may not be a reliable DBC ID so we skip spell-ID filtering and let
-- the existing texture/change guard below handle early-exit cheaply.
elseif event == "PLAYER_AURAS_CHANGED" then
local now = GetTime and GetTime() or 0
local minInterval = zButtonAspect_MinAuraInterval
if UnitAffectingCombat and UnitAffectingCombat("player") then
@@ -271,7 +287,8 @@ function MTH_ZH_AspectAdjust_OnEvent()
zButtonAspect_SetupSizeAndPosition()
zButtonAspect_EnsureValidParentId()
end
if event == "PLAYER_AURAS_CHANGED" or event == "PLAYER_ENTERING_WORLD"
if event == "PLAYER_AURAS_CHANGED" or event == "BUFF_ADDED_SELF" or event == "BUFF_REMOVED_SELF"
or event == "PLAYER_ENTERING_WORLD"
or event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" or event == "LEARNED_SPELL_IN_TAB" then
zButtonAspect_EnsureValidParentId()
if not zButtonAspect1.id then
@@ -304,13 +321,19 @@ function MTH_ZH_AspectAdjust_OnEvent()
end
end
local i = 1
local texture = GetSpellTexture(zButtonAspect1.id, "spell")
local texture1 = GetSpellTexture(zButtonAspect1.id, "spell")
local texture2 = zButtonAspect2 and zButtonAspect2.id and GetSpellTexture(zButtonAspect2.id, "spell") or nil
local buff = UnitBuff("player", i)
local spellname, buffname
local newParentId = zButtonAspect1.id
local smartEnabled = zButtonAspect_GetSaved()["parent"]["smart"] ~= false
while buff do
if texture == buff and zButtonAspect2.id then
newParentId = zButtonAspect2.id
if smartEnabled and zButtonAspect2 and zButtonAspect2.id then
if texture1 == buff then
newParentId = zButtonAspect2.id
elseif texture2 and texture2 == buff then
newParentId = zButtonAspect1.id
end
end
if needChildIconScan and buttontextures[buff] then
if hasDuplicateChildTexture then
@@ -332,10 +355,10 @@ function MTH_ZH_AspectAdjust_OnEvent()
i = i + 1
buff = UnitBuff("player", i)
end
if event == "PLAYER_AURAS_CHANGED" and zButtonAspect_LastAuraTexture == texture and zButtonAspect.id == newParentId and zButtonAspect_LastParentId == newParentId and not isParentTooltipOwned then
if (event == "PLAYER_AURAS_CHANGED" or event == "BUFF_ADDED_SELF" or event == "BUFF_REMOVED_SELF") and zButtonAspect_LastAuraTexture == texture1 and zButtonAspect.id == newParentId and zButtonAspect_LastParentId == newParentId and not isParentTooltipOwned then
return
end
zButtonAspect_LastAuraTexture = texture
zButtonAspect_LastAuraTexture = texture1
zButtonAspect_LastParentId = newParentId
zButtonAspect.id = newParentId
ZSpellButton_UpdateButton(zButtonAspect)
+30 -7
View File
@@ -75,6 +75,9 @@ local function zButtonCompanions_EnsureConfig()
if saved["parent"]["circle"] == nil then
saved["parent"]["circle"] = 1
end
if saved["parent"]["random"] == nil then
saved["parent"]["random"] = false
end
if not saved["children"]["size"] then
saved["children"]["size"] = 36
end
@@ -177,7 +180,14 @@ local function zButtonCompanions_ApplySpellIds(spellIds)
end
if found > 0 then
parent.id = spellIds[1]
local saved = zButtonCompanions_GetSaved()
if saved["parent"]["random"] and found > 1 then
local pick = math.random(1, found)
local child = getglobal("zButtonCompanions" .. pick)
parent.id = child and child.id or spellIds[1]
else
parent.id = spellIds[1]
end
parent.isspell = 1
ZSpellButton_UpdateButton(parent)
parent:Enable()
@@ -227,6 +237,17 @@ function zButtonCompanions_OnEvent()
return
end
zButtonCompanions_CreateButtons()
zButtonCompanions.afterclick = function(button)
local saved = zButtonCompanions_GetSaved()
if saved["parent"]["random"] and zButtonCompanions.found and zButtonCompanions.found > 1 then
local pick = math.random(1, zButtonCompanions.found)
local child = getglobal("zButtonCompanions" .. pick)
if child and child.id then
zButtonCompanions.id = child.id
ZSpellButton_UpdateButton(zButtonCompanions)
end
end
end
MTH_ZH_CompanionsAdjust = CreateFrame("Frame", "MTH_ZH_CompanionsAdjust")
MTH_ZH_CompanionsAdjust:RegisterEvent("SPELLS_CHANGED")
MTH_ZH_CompanionsAdjust:RegisterEvent("PLAYER_ENTERING_WORLD")
@@ -264,12 +285,14 @@ function zButtonCompanions_SetupSizeAndPosition()
if displayCount < 0 then
displayCount = 0
end
ZSpellButton_SetSize(zButtonCompanions, saved["parent"]["size"])
ZSpellButton_SetSize(zButtonCompanions, saved["children"]["size"], 1)
ZSpellButton_SetExpandDirection(zButtonCompanions, saved["firstbutton"])
ZSpellButton_ArrangeChildren(zButtonCompanions, saved["rows"],
displayCount, saved["horizontal"],
saved["vertical"])
if not (type(MTH_ZBar_ApplyToButton) == "function" and MTH_ZBar_ApplyToButton(zButtonCompanions, displayCount)) then
ZSpellButton_SetSize(zButtonCompanions, saved["parent"]["size"])
ZSpellButton_SetSize(zButtonCompanions, saved["children"]["size"], 1)
ZSpellButton_SetExpandDirection(zButtonCompanions, saved["firstbutton"])
ZSpellButton_ArrangeChildren(zButtonCompanions, saved["rows"],
displayCount, saved["horizontal"],
saved["vertical"])
end
end
function zButtonCompanions_Reset()
+401
View File
@@ -0,0 +1,401 @@
local function zButtonCraft_GetRoot()
return MTH_ZH_GetSavedRoot()
end
local root = zButtonCraft_GetRoot()
if not root["zButtonCraft"] then
root["zButtonCraft"] = {}
root["zButtonCraft"]["spells"] = {}
root["zButtonCraft"]["rows"] = 1
root["zButtonCraft"]["horizontal"] = nil
root["zButtonCraft"]["vertical"] = nil
root["zButtonCraft"]["firstbutton"] = "RIGHT"
root["zButtonCraft"]["enabled"] = 0
root["zButtonCraft"]["tooltip"] = 1
root["zButtonCraft"]["parent"] = {}
root["zButtonCraft"]["parent"]["size"] = 36
root["zButtonCraft"]["parent"]["hide"] = nil
root["zButtonCraft"]["parent"]["circle"] = 1
root["zButtonCraft"]["children"] = {}
root["zButtonCraft"]["children"]["size"] = 36
root["zButtonCraft"]["children"]["hideonclick"] = 1
end
local ZHUNTER_CRAFT_BUTTON_MAX = 14
local zButtonCraft_LastSpellSignature = nil
local zButtonCraft_LastRefreshAt = 0
local zButtonCraft_MinRefreshInterval = 0.50
-- Exact spell names as they appear in the General spellbook tab.
-- spellName = the name returned by GetSpellName() to match against (case-insensitive)
-- display = label used for tooltips and options
local ZCRAFT_PROFESSIONS = {
{ spellName = "Alchemy", display = "Alchemy" },
{ spellName = "Blacksmithing", display = "Blacksmithing" },
{ spellName = "Disenchanting", display = "Disenchanting" },
{ spellName = "Enchanting", display = "Enchanting" },
{ spellName = "Engineering", display = "Engineering" },
{ spellName = "Leatherworking", display = "Leatherworking" },
{ spellName = "Tailoring", display = "Tailoring" },
{ spellName = "Jewelcrafting", display = "Jewelcrafting" },
{ spellName = "Mining", display = "Smelting" },
{ spellName = "Cooking", display = "Cooking" },
{ spellName = "First Aid", display = "First Aid" },
{ spellName = "Herbalism", display = "Herbalism" },
{ spellName = "Survival", display = "Survival" },
{ spellName = "Fishing", display = "Fishing" },
{ spellName = "Skinning", display = "Skinning" },
}
-- Build a lookup: lowercase spell name → ZCRAFT_PROFESSIONS entry
local ZCRAFT_SPELL_LOOKUP = {}
for i = 1, table.getn(ZCRAFT_PROFESSIONS) do
ZCRAFT_SPELL_LOOKUP[string.lower(ZCRAFT_PROFESSIONS[i].spellName)] = ZCRAFT_PROFESSIONS[i]
end
function zButtonCraft_GetSaved()
local currentRoot = zButtonCraft_GetRoot()
if not currentRoot["zButtonCraft"] then
currentRoot["zButtonCraft"] = {}
end
return currentRoot["zButtonCraft"]
end
local function zButtonCraft_EnsureConfig()
local saved = zButtonCraft_GetSaved()
saved["count"] = nil
if saved["enabled"] == nil then
saved["enabled"] = 0
end
if saved["tooltip"] == nil then
saved["tooltip"] = 1
end
if not saved["children"] then
saved["children"] = {}
end
if saved["children"]["hideonclick"] == nil then
saved["children"]["hideonclick"] = 1
end
if not saved["spells"] then
saved["spells"] = {}
end
if not saved["parent"] then
saved["parent"] = {}
end
if not saved["parent"]["size"] then
saved["parent"]["size"] = 36
end
if saved["parent"]["circle"] == nil then
saved["parent"]["circle"] = 1
end
if not saved["children"]["size"] then
saved["children"]["size"] = 36
end
if not saved["rows"] or saved["rows"] < 1 then
saved["rows"] = 1
end
if not saved["firstbutton"] then
saved["firstbutton"] = "RIGHT"
end
end
local function zButtonCraft_ApplyRuntimeSettings()
if not zButtonCraft then return end
local saved = zButtonCraft_GetSaved()
zButtonCraft.tooltip = saved["tooltip"] and true or false
zButtonCraft.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false
zButtonCraft.expandonhover = saved["children"] and saved["children"]["expandonhover"] and true or false
zButtonCraft.fadetimer = saved["children"] and tonumber(saved["children"]["fadetimer"]) or 0
end
local function zButtonCraft_GetSpellSignature(spellIds)
if type(spellIds) ~= "table" or table.getn(spellIds) == 0 then return "" end
local parts = {}
for i = 1, table.getn(spellIds) do
parts[i] = tostring(spellIds[i] or "")
end
return table.concat(parts, ",")
end
-- Scans individual spells in the General tab and returns two parallel arrays:
-- spellIds = spellbook index of each matched craft spell
-- spellNames = display label for that profession
-- Results are ordered by ZCRAFT_PROFESSIONS priority.
local function zButtonCraft_CollectProfessions()
if type(GetNumSpellTabs) ~= "function" or type(GetSpellTabInfo) ~= "function"
or type(GetSpellName) ~= "function" then
return {}, {}
end
local bookType = BOOKTYPE_SPELL or "spell"
-- Find the General tab (always tab 1, but look it up to be safe)
local generalOffset, generalEntries
local tabCount = GetNumSpellTabs() or 0
for tabIndex = 1, tabCount do
local tabName, _, tabOffset, tabEntries = GetSpellTabInfo(tabIndex)
if tabName and string.lower(tabName) == "general" then
generalOffset = tabOffset
generalEntries = tabEntries
break
end
end
if not generalOffset or not generalEntries or generalEntries <= 0 then
return {}, {}
end
-- Scan every spell in General; collect matches keyed by profession order
local found = {} -- profession display → spellbook index (first match wins)
for i = 1, generalEntries do
local spellIndex = generalOffset + i
local spellName = GetSpellName(spellIndex, bookType)
if spellName then
local prof = ZCRAFT_SPELL_LOOKUP[string.lower(spellName)]
if prof and not found[prof.display] then
found[prof.display] = spellIndex
end
end
end
-- Return results in ZCRAFT_PROFESSIONS order
local spellIds = {}
local spellNames = {}
for profIndex = 1, table.getn(ZCRAFT_PROFESSIONS) do
local prof = ZCRAFT_PROFESSIONS[profIndex]
local spellIndex = found[prof.display]
if spellIndex then
table.insert(spellIds, spellIndex)
table.insert(spellNames, prof.display)
end
end
return spellIds, spellNames
end
local function zButtonCraft_ApplySpellIds(spellIds)
if not zButtonCraft then return 0 end
local parent = zButtonCraft
local childCount = parent.count or ZHUNTER_CRAFT_BUTTON_MAX
for i = 1, childCount do
local child = getglobal("zButtonCraft" .. i)
if child then
child:Hide()
child.id = nil
child.icon = nil
child.isspell = nil
end
end
local found = 0
for i = 1, table.getn(spellIds) do
if found >= childCount then break end
local spellId = spellIds[i]
if spellId then
found = found + 1
local child = getglobal("zButtonCraft" .. found)
if child then
child.id = spellId
child.isspell = 1
ZSpellButton_UpdateButton(child)
child:Show()
end
end
end
if found > 0 then
parent.id = spellIds[1]
parent.isspell = 1
ZSpellButton_UpdateButton(parent)
parent:Enable()
parent:Show()
else
parent.id = nil
parent:Hide()
end
return found
end
local function zButtonCraft_RefreshProfessions()
if not zButtonCraft then return 0 end
local saved = zButtonCraft_GetSaved()
local freshIds, freshNames = zButtonCraft_CollectProfessions()
-- Build lookup: display name → spellbook index from the fresh scan
local nameToId = {}
for i = 1, table.getn(freshNames) do
nameToId[freshNames[i]] = freshIds[i]
end
-- Honour saved user order when it exists
local existing = saved["spells"]
if existing and table.getn(existing) > 0 then
local orderedNames = {}
local orderedIds = {}
local seen = {}
-- Keep entries that still exist, in the user's order
for i = 1, table.getn(existing) do
local name = existing[i]
if nameToId[name] then
table.insert(orderedNames, name)
table.insert(orderedIds, nameToId[name])
seen[name] = true
end
end
-- Append any newly learned professions at the end
for i = 1, table.getn(freshNames) do
if not seen[freshNames[i]] then
table.insert(orderedNames, freshNames[i])
table.insert(orderedIds, freshIds[i])
end
end
freshNames = orderedNames
freshIds = orderedIds
end
saved["spellIds"] = freshIds
saved["spells"] = freshNames
zButtonCraft.spells = freshNames
zButtonCraft.found = zButtonCraft_ApplySpellIds(freshIds)
zButtonCraft_ApplyRuntimeSettings()
return zButtonCraft.found or 0
end
function zButtonCraft_OnLoad()
this:RegisterEvent("VARIABLES_LOADED")
end
function zButtonCraft_OnEvent()
if event == "VARIABLES_LOADED" then
if not zButtonCraft then return end
if UnitClass("player") ~= ZHUNTER_HUNTER then
zButtonCraft:UnregisterAllEvents()
zButtonCraft:Hide()
return
end
zButtonCraft_CreateButtons()
MTH_ZH_CraftAdjust = CreateFrame("Frame", "MTH_ZH_CraftAdjust")
MTH_ZH_CraftAdjust:RegisterEvent("SPELLS_CHANGED")
MTH_ZH_CraftAdjust:RegisterEvent("PLAYER_ENTERING_WORLD")
MTH_ZH_CraftAdjust:SetScript("OnEvent", MTH_ZH_CraftAdjust_OnEvent)
zButtonCraft_SetupSizeAndPosition()
end
end
function zButtonCraft_CreateButtons()
zButtonCraft_EnsureConfig()
if not zButtonCraft._mthChildrenCreated then
ZSpellButton_CreateChildren(zButtonCraft, "zButtonCraft", ZHUNTER_CRAFT_BUTTON_MAX)
zButtonCraft._mthChildrenCreated = 1
end
zButtonCraft_RefreshProfessions()
end
function zButtonCraft_SetupSizeAndPosition()
local saved = zButtonCraft_GetSaved()
if saved["enabled"] == false or saved["enabled"] == 0 then
if MTH_ZH_CraftAdjust then
MTH_ZH_CraftAdjust:UnregisterAllEvents()
MTH_ZH_CraftAdjust:SetScript("OnEvent", nil)
end
if zButtonCraft and zButtonCraft.Hide then
zButtonCraft:Hide()
end
return
end
if MTH_ZH_CraftAdjust then
MTH_ZH_CraftAdjust:RegisterEvent("SPELLS_CHANGED")
MTH_ZH_CraftAdjust:RegisterEvent("PLAYER_ENTERING_WORLD")
MTH_ZH_CraftAdjust:SetScript("OnEvent", MTH_ZH_CraftAdjust_OnEvent)
end
local displayCount = zButtonCraft.found or 0
if displayCount < 0 then displayCount = 0 end
if not (type(MTH_ZBar_ApplyToButton) == "function" and MTH_ZBar_ApplyToButton(zButtonCraft, displayCount)) then
ZSpellButton_SetSize(zButtonCraft, saved["parent"]["size"])
ZSpellButton_SetSize(zButtonCraft, saved["children"]["size"], 1)
ZSpellButton_SetExpandDirection(zButtonCraft, saved["firstbutton"])
ZSpellButton_ArrangeChildren(zButtonCraft, saved["rows"],
displayCount, saved["horizontal"], saved["vertical"])
end
end
function zButtonCraft_Reset()
local currentRoot = zButtonCraft_GetRoot()
currentRoot["zButtonCraft"] = {}
local saved = zButtonCraft_GetSaved()
saved["spells"] = {}
saved["rows"] = 1
saved["horizontal"] = nil
saved["vertical"] = nil
saved["firstbutton"] = "RIGHT"
saved["enabled"] = 1
saved["tooltip"] = 1
saved["parent"] = {}
saved["parent"]["size"] = 36
saved["parent"]["hide"] = nil
saved["parent"]["circle"] = 1
saved["children"] = {}
saved["children"]["size"] = 36
saved["children"]["hideonclick"] = 1
zButtonCraft_EnsureConfig()
end
function MTH_ZH_CraftAdjust_OnEvent()
if not zButtonCraft then return end
if event == "SPELLS_CHANGED" then
local now = GetTime and GetTime() or 0
if now > 0 and zButtonCraft_LastRefreshAt > 0 and (now - zButtonCraft_LastRefreshAt) < zButtonCraft_MinRefreshInterval then
return
end
local spellIds, _ = zButtonCraft_CollectProfessions()
local signature = zButtonCraft_GetSpellSignature(spellIds)
if signature == zButtonCraft_LastSpellSignature and not GameTooltip:IsOwned(zButtonCraft) then
return
end
zButtonCraft_LastSpellSignature = signature
zButtonCraft_LastRefreshAt = now
end
zButtonCraft_RefreshProfessions()
zButtonCraft_SetupSizeAndPosition()
if GameTooltip:IsOwned(zButtonCraft) then
ZSpellButtonParent_OnEnter(zButtonCraft)
end
end
function zButtonCraft_KeyBinding(index)
if MTH_ZH_IsModuleEnabled and not MTH_ZH_IsModuleEnabled() then return end
local button
if index then
button = getglobal("zButtonCraft" .. index)
else
button = zButtonCraft
end
if button and button.id then
CastSpell(button.id, "spell")
if zButtonCraft.hideonclick then
if type(ZSpellButton_SetChildrenExpanded) == "function" then
ZSpellButton_SetChildrenExpanded(zButtonCraft, false)
elseif zButtonCraft.children then
zButtonCraft.children:Hide()
end
end
end
end
SLASH_zButtonCraft1 = "/ZCraft"
SlashCmdList["zButtonCraft"] = function(msg)
if MTH_ZH_HandleDisabledSlash and MTH_ZH_HandleDisabledSlash("Craft button is disabled while module 'zhunter' is disabled.") then
return
end
if msg == "reset" then
zButtonCraft_Reset()
zButtonCraft:ClearAllPoints()
zButtonCraft:SetPoint("TOP", UIParent, "TOP", 0, -558)
zButtonCraft_RefreshProfessions()
zButtonCraft_SetupSizeAndPosition()
else
MTH_ZH_Print("Possible Commands: \"reset\"")
end
end
+14
View File
@@ -0,0 +1,14 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<Frame name="zButtonCraftFrame">
</Frame>
<CheckButton name="zButtonCraft" inherits="ZSpellButtonTemplate">
<Anchors>
<Anchor point="CENTER" relativeTo="UIParent" relativePoint="CENTER">
<Offset>
<AbsDimension x="0" y="-288"/>
</Offset>
</Anchor>
</Anchors>
</CheckButton>
</Ui>
+79 -7
View File
@@ -75,6 +75,12 @@ local function zButtonMounts_EnsureConfig()
if saved["parent"]["circle"] == nil then
saved["parent"]["circle"] = 1
end
if saved["parent"]["random"] == nil then
saved["parent"]["random"] = false
end
if saved["parent"]["aqfilter"] == nil then
saved["parent"]["aqfilter"] = true
end
if not saved["children"]["size"] then
saved["children"]["size"] = 36
end
@@ -177,7 +183,14 @@ local function zButtonMounts_ApplySpellIds(spellIds)
end
if found > 0 then
parent.id = spellIds[1]
local saved = zButtonMounts_GetSaved()
if saved["parent"]["random"] and found > 1 then
local pick = math.random(1, found)
local child = getglobal("zButtonMounts" .. pick)
parent.id = child and child.id or spellIds[1]
else
parent.id = spellIds[1]
end
parent.isspell = 1
ZSpellButton_UpdateButton(parent)
parent:Enable()
@@ -190,6 +203,49 @@ local function zButtonMounts_ApplySpellIds(spellIds)
return found
end
local function zButtonMounts_IsQirajiSpell(spellId)
local bookType = BOOKTYPE_SPELL or "spell"
local name = GetSpellName(spellId, bookType)
if name and string.find(string.lower(name), "qiraji", 1, true) then
return true
end
return false
end
local function zButtonMounts_IsInAQ40()
local zone = GetRealZoneText and GetRealZoneText() or ""
if zone == "Temple of Ahn'Qiraj" or zone == "Ahn'Qiraj" then
return true
end
return false
end
local function zButtonMounts_FilterAQ(spellIds)
local saved = zButtonMounts_GetSaved()
if not saved["parent"]["aqfilter"] then
return spellIds
end
local inAQ = zButtonMounts_IsInAQ40()
local filtered = {}
for i = 1, table.getn(spellIds) do
local isQiraji = zButtonMounts_IsQirajiSpell(spellIds[i])
if inAQ then
if isQiraji then
table.insert(filtered, spellIds[i])
end
else
if not isQiraji then
table.insert(filtered, spellIds[i])
end
end
end
-- Fallback: if filtering removed everything, return original list
if table.getn(filtered) == 0 then
return spellIds
end
return filtered
end
local function zButtonMounts_RefreshSpells()
if not zButtonMounts then
return 0
@@ -207,6 +263,7 @@ local function zButtonMounts_RefreshSpells()
saved["spellIds"] = spellIds
saved["spells"] = spellNames
zButtonMounts.spells = spellNames
spellIds = zButtonMounts_FilterAQ(spellIds)
zButtonMounts.found = zButtonMounts_ApplySpellIds(spellIds)
zButtonMounts_ApplyRuntimeSettings()
return zButtonMounts.found or 0
@@ -227,9 +284,21 @@ function zButtonMounts_OnEvent()
return
end
zButtonMounts_CreateButtons()
zButtonMounts.afterclick = function(button)
local saved = zButtonMounts_GetSaved()
if saved["parent"]["random"] and zButtonMounts.found and zButtonMounts.found > 1 then
local pick = math.random(1, zButtonMounts.found)
local child = getglobal("zButtonMounts" .. pick)
if child and child.id then
zButtonMounts.id = child.id
ZSpellButton_UpdateButton(zButtonMounts)
end
end
end
MTH_ZH_MountsAdjust = CreateFrame("Frame", "MTH_ZH_MountsAdjust")
MTH_ZH_MountsAdjust:RegisterEvent("SPELLS_CHANGED")
MTH_ZH_MountsAdjust:RegisterEvent("PLAYER_ENTERING_WORLD")
MTH_ZH_MountsAdjust:RegisterEvent("ZONE_CHANGED_NEW_AREA")
MTH_ZH_MountsAdjust:SetScript("OnEvent", MTH_ZH_MountsAdjust_OnEvent)
zButtonMounts_SetupSizeAndPosition()
end
@@ -261,18 +330,21 @@ function zButtonMounts_SetupSizeAndPosition()
if MTH_ZH_MountsAdjust then
MTH_ZH_MountsAdjust:RegisterEvent("SPELLS_CHANGED")
MTH_ZH_MountsAdjust:RegisterEvent("PLAYER_ENTERING_WORLD")
MTH_ZH_MountsAdjust:RegisterEvent("ZONE_CHANGED_NEW_AREA")
MTH_ZH_MountsAdjust:SetScript("OnEvent", MTH_ZH_MountsAdjust_OnEvent)
end
local displayCount = zButtonMounts.found or 0
if displayCount < 0 then
displayCount = 0
end
ZSpellButton_SetSize(zButtonMounts, saved["parent"]["size"])
ZSpellButton_SetSize(zButtonMounts, saved["children"]["size"], 1)
ZSpellButton_SetExpandDirection(zButtonMounts, saved["firstbutton"])
ZSpellButton_ArrangeChildren(zButtonMounts, saved["rows"],
displayCount, saved["horizontal"],
saved["vertical"])
if not (type(MTH_ZBar_ApplyToButton) == "function" and MTH_ZBar_ApplyToButton(zButtonMounts, displayCount)) then
ZSpellButton_SetSize(zButtonMounts, saved["parent"]["size"])
ZSpellButton_SetSize(zButtonMounts, saved["children"]["size"], 1)
ZSpellButton_SetExpandDirection(zButtonMounts, saved["firstbutton"])
ZSpellButton_ArrangeChildren(zButtonMounts, saved["rows"],
displayCount, saved["horizontal"],
saved["vertical"])
end
end
function zButtonMounts_Reset()
+16 -7
View File
@@ -84,6 +84,9 @@ local function zButtonPet_EnsureConfig()
if saved["parent"]["circle"] == nil then
saved["parent"]["circle"] = 1
end
if saved["parent"]["smart"] == nil then
saved["parent"]["smart"] = true
end
if saved["enabled"] == nil then
saved["enabled"] = 1
end
@@ -258,12 +261,14 @@ function zButtonPet_SetupSizeAndPosition()
if displayCount < 0 then
displayCount = 0
end
ZSpellButton_SetSize(zButtonPet, saved["parent"]["size"])
ZSpellButton_SetSize(zButtonPet, saved["children"]["size"], 1)
ZSpellButton_SetExpandDirection(zButtonPet, saved["firstbutton"])
ZSpellButton_ArrangeChildren(zButtonPet, saved["rows"],
displayCount, saved["horizontal"],
saved["vertical"])
if not (type(MTH_ZBar_ApplyToButton) == "function" and MTH_ZBar_ApplyToButton(zButtonPet, displayCount)) then
ZSpellButton_SetSize(zButtonPet, saved["parent"]["size"])
ZSpellButton_SetSize(zButtonPet, saved["children"]["size"], 1)
ZSpellButton_SetExpandDirection(zButtonPet, saved["firstbutton"])
ZSpellButton_ArrangeChildren(zButtonPet, saved["rows"],
displayCount, saved["horizontal"],
saved["vertical"])
end
end
function zButtonPet_Reset()
@@ -502,7 +507,11 @@ local function zButtonPet_RefreshParentSpell()
local id = zButtonPet.id
name = nil
if hasCurrentPet == false and hasLivePet == false then
if saved["parent"]["smart"] == false then
if choiceId then
id = choiceId
end
elseif hasCurrentPet == false and hasLivePet == false then
name = ZHUNTER_PET_TAMING
elseif not status then
name = ZHUNTER_PET_CALL
+6 -4
View File
@@ -648,10 +648,12 @@ function zButtonRanged_SetupSizeAndPosition()
if displayCount < 0 then
displayCount = 0
end
ZSpellButton_SetSize(zButtonRanged, saved["parent"]["size"])
ZSpellButton_SetSize(zButtonRanged, saved["children"]["size"], 1)
ZSpellButton_SetExpandDirection(zButtonRanged, saved["firstbutton"])
ZSpellButton_ArrangeChildren(zButtonRanged, saved["rows"], displayCount, saved["horizontal"], saved["vertical"])
if not (type(MTH_ZBar_ApplyToButton) == "function" and MTH_ZBar_ApplyToButton(zButtonRanged, displayCount)) then
ZSpellButton_SetSize(zButtonRanged, saved["parent"]["size"])
ZSpellButton_SetSize(zButtonRanged, saved["children"]["size"], 1)
ZSpellButton_SetExpandDirection(zButtonRanged, saved["firstbutton"])
ZSpellButton_ArrangeChildren(zButtonRanged, saved["rows"], displayCount, saved["horizontal"], saved["vertical"])
end
zButtonRanged_UpdateButton(zButtonRanged)
end
+8 -6
View File
@@ -267,12 +267,14 @@ function zButtonToys_SetupSizeAndPosition()
if displayCount < 0 then
displayCount = 0
end
ZSpellButton_SetSize(zButtonToys, saved["parent"]["size"])
ZSpellButton_SetSize(zButtonToys, saved["children"]["size"], 1)
ZSpellButton_SetExpandDirection(zButtonToys, saved["firstbutton"])
ZSpellButton_ArrangeChildren(zButtonToys, saved["rows"],
displayCount, saved["horizontal"],
saved["vertical"])
if not (type(MTH_ZBar_ApplyToButton) == "function" and MTH_ZBar_ApplyToButton(zButtonToys, displayCount)) then
ZSpellButton_SetSize(zButtonToys, saved["parent"]["size"])
ZSpellButton_SetSize(zButtonToys, saved["children"]["size"], 1)
ZSpellButton_SetExpandDirection(zButtonToys, saved["firstbutton"])
ZSpellButton_ArrangeChildren(zButtonToys, saved["rows"],
displayCount, saved["horizontal"],
saved["vertical"])
end
end
function zButtonToys_Reset()
+91 -31
View File
@@ -93,6 +93,32 @@ local function zButtonTrack_FindSpellIdByTrackingName(trackingName)
return nil
end
local function zButtonTrack_ScanBuffsForTrackingSpell()
if not zButtonTrack or not zButtonTrack.count then
return nil, nil
end
local childTextures = {}
for i = 1, zButtonTrack.count do
local child = getglobal("zButtonTrack" .. i)
if child and child.id then
local tex = GetSpellTexture and GetSpellTexture(child.id, "spell") or nil
if tex then
childTextures[tex] = child.id
end
end
end
local buffIndex = 1
local buff = UnitBuff("player", buffIndex)
while buff do
if childTextures[buff] then
return childTextures[buff], buff
end
buffIndex = buffIndex + 1
buff = UnitBuff("player", buffIndex)
end
return nil, nil
end
local function zButtonTrack_GetActiveTrackingSpellId()
local activeName = nil
local activeTexture = nil
@@ -112,10 +138,26 @@ local function zButtonTrack_GetActiveTrackingSpellId()
return byName, activeTexture
end
if activeTexture then
return zButtonTrack_FindSpellIdByTrackingTexture(activeTexture), activeTexture
local byTex = zButtonTrack_FindSpellIdByTrackingTexture(activeTexture)
if byTex then
return byTex, activeTexture
end
end
local buff = GetTrackingTexture and GetTrackingTexture() or nil
return zButtonTrack_FindSpellIdByTrackingTexture(buff), buff
-- Fallback: scan player buffs for tracking spell icon textures
local buffId, buffTex = zButtonTrack_ScanBuffsForTrackingSpell()
if buffId then
return buffId, buffTex
end
return nil, nil
end
local function zButtonTrack_SmartParentId(activeChildId)
local child1 = getglobal("zButtonTrack1")
local child2 = getglobal("zButtonTrack2")
if not child1 or not child1.id then return nil end
if not child2 or not child2.id then return child1.id end
if activeChildId == child1.id then return child2.id end
return child1.id
end
local function zButtonTrack_AfterClick(button)
@@ -123,9 +165,19 @@ local function zButtonTrack_AfterClick(button)
return
end
if button and button.id then
zButtonTrack.id = button.id
ZSpellButton_UpdateButton(zButtonTrack)
ZSpellButton_UpdateCooldown(zButtonTrack)
local saved = zButtonTrack_GetSaved()
local newId
if saved["parent"]["smart"] ~= false then
newId = zButtonTrack_SmartParentId(button.id)
else
local firstChild = getglobal("zButtonTrack1")
newId = firstChild and firstChild.id
end
if newId and newId ~= zButtonTrack.id then
zButtonTrack.id = newId
ZSpellButton_UpdateButton(zButtonTrack)
ZSpellButton_UpdateCooldown(zButtonTrack)
end
zButtonTrack_SyncActiveChild(button.id)
if GetSpellTexture then
zButtonTrack_LastTrackingTexture = GetSpellTexture(button.id, "spell") or zButtonTrack_LastTrackingTexture
@@ -156,34 +208,36 @@ local function zButtonTrack_RefreshTrackingState()
if not zButtonTrack or not zButtonTrack.count then
return
end
local newId, trackingTexture = zButtonTrack_GetActiveTrackingSpellId()
local buff = trackingTexture or (GetTrackingTexture and GetTrackingTexture() or nil)
if not newId and not buff then
if zButtonTrack.id then
zButtonTrack_SyncActiveChild(zButtonTrack.id)
else
zButtonTrack_LastTrackingTexture = nil
zButtonTrack_SyncActiveChild(nil)
local saved = zButtonTrack_GetSaved()
local firstChild = getglobal("zButtonTrack1")
-- Smart OFF: always show first child
if saved["parent"]["smart"] == false then
if firstChild and firstChild.id and zButtonTrack.id ~= firstChild.id then
zButtonTrack.id = firstChild.id
ZSpellButton_UpdateButton(zButtonTrack)
ZSpellButton_UpdateCooldown(zButtonTrack)
end
return
end
-- Smart ON: detect which tracking is active, show the OTHER one
local activeId = zButtonTrack_GetActiveTrackingSpellId()
local newId = zButtonTrack_SmartParentId(activeId)
if not newId then
newId = zButtonTrack.id or nil
end
if not newId then
return
end
if zButtonTrack_NormalizeTexture(zButtonTrack_LastTrackingTexture) == zButtonTrack_NormalizeTexture(buff) and zButtonTrack.id == newId then
zButtonTrack_SyncActiveChild(newId)
return
newId = firstChild and firstChild.id
end
if not newId then return end
-- Sync checked state on children
zButtonTrack_SyncActiveChild(activeId)
if zButtonTrack.id == newId then return end
local isOwned = GameTooltip and GameTooltip.IsOwned and GameTooltip:IsOwned(zButtonTrack)
zButtonTrack_LastTrackingTexture = buff
zButtonTrack.id = newId
ZSpellButton_UpdateButton(zButtonTrack)
ZSpellButton_UpdateCooldown(zButtonTrack)
zButtonTrack_SyncActiveChild(newId)
if isOwned then
ZSpellButtonParent_OnEnter(zButtonTrack)
end
@@ -221,6 +275,9 @@ local function zButtonTrack_EnsureConfig()
if saved["parent"]["circle"] == nil then
saved["parent"]["circle"] = 1
end
if saved["parent"]["smart"] == nil then
saved["parent"]["smart"] = true
end
if not saved["children"] then
saved["children"] = {}
end
@@ -323,6 +380,7 @@ function zButtonTrack_SetupSizeAndPosition()
end
if MTH_ZH_TrackAdjust then
MTH_ZH_TrackAdjust:RegisterEvent("MINIMAP_UPDATE_TRACKING")
MTH_ZH_TrackAdjust:RegisterEvent("PLAYER_AURAS_CHANGED")
MTH_ZH_TrackAdjust:RegisterEvent("PLAYER_ENTERING_WORLD")
MTH_ZH_TrackAdjust:RegisterEvent("SPELLS_CHANGED")
MTH_ZH_TrackAdjust:RegisterEvent("CHARACTER_POINTS_CHANGED")
@@ -333,12 +391,14 @@ function zButtonTrack_SetupSizeAndPosition()
if displayCount < 0 then
displayCount = 0
end
ZSpellButton_SetSize(zButtonTrack, saved["parent"]["size"])
ZSpellButton_SetSize(zButtonTrack, saved["children"]["size"], 1)
ZSpellButton_SetExpandDirection(zButtonTrack, saved["firstbutton"])
ZSpellButton_ArrangeChildren(zButtonTrack, saved["rows"],
displayCount, saved["horizontal"],
saved["vertical"])
if not (type(MTH_ZBar_ApplyToButton) == "function" and MTH_ZBar_ApplyToButton(zButtonTrack, displayCount)) then
ZSpellButton_SetSize(zButtonTrack, saved["parent"]["size"])
ZSpellButton_SetSize(zButtonTrack, saved["children"]["size"], 1)
ZSpellButton_SetExpandDirection(zButtonTrack, saved["firstbutton"])
ZSpellButton_ArrangeChildren(zButtonTrack, saved["rows"],
displayCount, saved["horizontal"],
saved["vertical"])
end
zButtonTrack_RefreshTrackingState()
end
@@ -372,7 +432,7 @@ function MTH_ZH_TrackAdjust_OnEvent()
zButtonTrack_CreateButtons()
zButtonTrack_SetupSizeAndPosition()
end
if event == "MINIMAP_UPDATE_TRACKING" or event == "PLAYER_ENTERING_WORLD"
if event == "MINIMAP_UPDATE_TRACKING" or event == "PLAYER_AURAS_CHANGED" or event == "PLAYER_ENTERING_WORLD"
or event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" or event == "LEARNED_SPELL_IN_TAB" then
zButtonTrack_RefreshTrackingState()
end
+8 -6
View File
@@ -175,12 +175,14 @@ function zButtonTrap_SetupSizeAndPosition()
if displayCount < 0 then
displayCount = 0
end
ZSpellButton_SetSize(zButtonTrap, saved["parent"]["size"])
ZSpellButton_SetSize(zButtonTrap, saved["children"]["size"], 1)
ZSpellButton_SetExpandDirection(zButtonTrap, saved["firstbutton"])
ZSpellButton_ArrangeChildren(zButtonTrap, saved["rows"],
displayCount, saved["horizontal"],
saved["vertical"])
if not (type(MTH_ZBar_ApplyToButton) == "function" and MTH_ZBar_ApplyToButton(zButtonTrap, displayCount)) then
ZSpellButton_SetSize(zButtonTrap, saved["parent"]["size"])
ZSpellButton_SetSize(zButtonTrap, saved["children"]["size"], 1)
ZSpellButton_SetExpandDirection(zButtonTrap, saved["firstbutton"])
ZSpellButton_ArrangeChildren(zButtonTrap, saved["rows"],
displayCount, saved["horizontal"],
saved["vertical"])
end
end
function zButtonTrap_Reset()