8 Commits

Author SHA1 Message Date
DuvelCorp c0c2c275eb v1.2.0 2026-03-11 00:40:35 +01:00
Duvel ab34946775 Fix typos and enhance clarity in README
Corrected typos and improved wording in the README.
2026-03-09 15:18:11 +01:00
Duvel d41703949d Merge pull request #4 from DuvelCorp/1.1.0
v1.1.0
2026-03-09 13:42:21 +01:00
DuvelCorp 27d37564ce v1.1.0 2026-03-09 13:41:30 +01:00
Duvel 4aed1174dd Merge pull request #3 from DuvelCorp/v1.0.6
v1.0.6
2026-03-05 12:31:27 +01:00
DuvelCorp 233899b2a0 v1.0.6 2026-03-05 12:30:24 +01:00
Duvel 89fd8e079c Merge pull request #2 from DuvelCorp/v1.0.5
## [1.0.5] - 2026-03-01

### Fixed
- Multiple changes to the addon to reduce its memory and CPU time footprint to the strict minimum possible.
- Restored FeedOMatic pet hunger notifications so hungry/very hungry warnings are emitted reliably again when enabled.
- Fixed Chronometer `Wing Clip` tracking by adding a safe fallback timer path for the missing trigger case.
- Fixed Chronometer `Quick Shots` bar icon by mapping the event to the correct icon texture.
- Fixed module enabled/disabled persistence to be truly per-character (`MTH_CharSavedVariables.moduleStates`) instead of account-shared.
- Fixed AutoBuy persistence fallback by removing undeclared `MTH_AutoBuy_Saved` paths and using module stores/transient runtime fallback only.
- Consolidated FeedOMatic legacy persistence to a single module-backed store (`modules.feedomatic.legacy`) with globals bound to that source.
- Switched Chronometer profile persistence to per-character module storage with one-time migration from existing account profile data.
- Switched Tooltips module options persistence to per-character module storage with one-time migration from existing account settings.
2026-03-01 09:12:06 +01:00
DuvelCorp 1a28d95b87 v1.0.5 2026-03-01 09:10:22 +01:00
74 changed files with 13580 additions and 6004 deletions
-1
View File
@@ -9,4 +9,3 @@
tools/ tools/
LOC*.md LOC*.md
LOCALIZATION*.md LOCALIZATION*.md
CHANGELOG.md
+117
View File
@@ -0,0 +1,117 @@
# Changelog
All notable changes to MetaHunt will be documented in this file.
## [1.2.0] - 2026-03-10
### Added
- Added keybinding text overlay on zButtons: parent and child buttons now display their bound key for the 5 bindable sets (Aspect, Track, Trap, Ammo, Pet).
- Added "Expand on Hover" option for zButton children: when enabled, hovering over the parent button automatically expands children (instead of requiring right-click).
- Added "Auto-Hide Timer" option for zButton children: a configurable 0–10 second timer that automatically collapses expanded children after the mouse leaves the button group. Timer resets while hovering any button in the group.
### Fixed
- Fixed SavedVariables data loss on login caused by initialization race condition overwriting persisted data.
- Fixed SavedVariables bloat by adding a migration that strips redundant default-valued keys on first load.
- Fixed six performance issues including throttling high-frequency event handlers, caching repeated `getglobal` lookups, and reducing unnecessary table allocations in hot paths.
- Cleaned up ICU module global variable leaks by properly scoping locals.
- Standardized all remaining `SetScript` handler patterns to use the WoW 1.12 `this`-based convention consistently.
## [1.1.0] - 2026-03-09
### Added
- Added new `ICU` module with dedicated options panel.
- Added ICU custom popup anchor mode with draggable anchor and direction toggle.
- Added ICU popup hide delay options (`INSTANT`, 1..10 seconds).
- Added new `Auto Quest` module for :
- `Salt of the Scorpok` (`Bloodmage Drazial`)
- `Arrows Are For Sissies` (`Artilleryman Sheldonore`)
- Added a Food Feed learning feature to Feed-O-Matic.
- Added Chronometer `Entrapment` effect tracking support.
### Changed
- Loads of Frame/Handlers/Processes adjustments to optimize addon's CPU time and Memory usage.
- Updated Chronometer Improved Wing Clip effect color to `MAROON` for clearer effect-bar distinction.
- Reworked Stable Master processing to minimize swap-time overhead:
- No auto-scan on `PET_STABLE_SHOW`.
- Deferred stable scan moved to `PET_STABLE_CLOSED`.
- Optional heavy workloads are skipped while stable UI is open.
- Changed Hunter Book page order, and default opening page to `Beast Lore`.
- Optimized `Pet History` result build/sort path using cached precomputed sort keys.
- Modules Auto-Buy, Auto-Quest, ICU, Feed-O-Matic are by default disabled on first use on a character.
### Fixed
- Fixed issues with zBouttons,Autostrp and Chronometer bar anchor not retaining their configured spawn position after the disabling/renabling of the Addon.
- Fixed issues with options checkbox-state not always retaining their state on startup.
- Fixed multiple issues in Feeed-O-Matic with some foods that were accepted by lvl 60 pets in Vanilla and are not anymore on Turtle.
- Fixed Chronometer spell/event disable toggles in options so disabled entries now reliably block bar creation.
- Fixed Chronometer `Feed Pet` bar missing trigger by adding `UNIT_AURA` fallback detection.
- Fixed stable swap stutter/freezes by removing heavy processing from repeated `UNIT_PET` bursts during stable interactions.
## [1.0.6] - 2026-03-05
### Fixed
- Added missing abilities to all pet families.
- Rescraped from Twow DB the previously in correct `Roar of Fortitude` pet-ability.
- Fixed an issue with Tooltip on pet action bar abilities, that were falsely displayed as not learned yet for rankless abilities.
- Restored visible Stable Master auto-scan feedback (`Stable scan complete: X slot(s).`) when opening the stable window.
- Fixed stable scan icon persistence for active pets that were never stabled by capturing current-pet icon data during stable scans.
- Hardened stable-scan bootstrap to initialize on both `PET_STABLE_SHOW` and `PET_STABLE_UPDATE` event paths.
- Fixed issues with taming pet metadata that were not properly recorded since the last update.
- Fixed issues with pet runaway interception that was broken since the last update.
- Updated version-update notification text to include clearer upgrade guidance and plain GitHub URL text for updates.
- Fixed an issue with `zTrack` buttons spells being incorrect after having respec the talents using brainwashing device.
## [1.0.5] - 2026-03-01
### Fixed
- Multiple changes to the addon to reduce its memory and CPU time footprint to the strict minimum possible.
- Restored FeedOMatic pet hunger notifications so hungry/very hungry warnings are emitted reliably again when enabled.
- Fixed Chronometer `Wing Clip` tracking by adding a safe fallback timer path for the missing trigger case.
- Fixed Chronometer `Quick Shots` bar icon by mapping the event to the correct icon texture.
- Fixed module enabled/disabled persistence to be truly per-character (`MTH_CharSavedVariables.moduleStates`) instead of account-shared.
- Fixed AutoBuy persistence fallback by removing undeclared `MTH_AutoBuy_Saved` paths and using module stores/transient runtime fallback only.
- Consolidated FeedOMatic legacy persistence to a single module-backed store (`modules.feedomatic.legacy`) with globals bound to that source.
- Switched Chronometer profile persistence to per-character module storage with one-time migration from existing account profile data.
- Switched Tooltips module options persistence to per-character module storage with one-time migration from existing account settings.
## [1.0.4] - 2026-02-27
### Added
- Added new zButton bar `zRanged` that tracks all ranged weapons in bags and allows to quickly swap them.
- Added structured localization architecture with dedicated locale packs under `locales/` and loader wiring through `init/localization.xml`.
- Added a dedicated `Messages` options panel with per-message toggles.
- Added Smart Ammo option `Enable Weapon-Swap Auto Ammo` to instantly equip best bullets/arrows when switching ranged weapon type.
- Added two new Hunter Book pages in the main tab bar: `Projectiles` and `Ammo Bags`
### Changed
- Reworked core localization runtime to support explicit locale fallback rules (`enUS`, `deDE`, `esES`, `ptBR`, `ruRU`, `zhCN`; no `frFR` target).
- Updated Hunter Book NPC finder and map vendor markers to use localized NPC names by NPC ID.
- Updated Hunter Book, item search/sort, AutoBuy item labels, and drop map markers to use localized item names by item ID.
### Fixed
- Fixed version metadata consistency so all first-party module descriptors report the same release version as the main addon.
- Fixed SmartAmmo junk-shot detection by including `Baited Shot` and `Tranquilizing Shot` in `MTH_AMMO_JUNKSHOT_SET`.
- Fixed zButtons options side effect where opening Mounts/Companions/Toys options could implicitly enable those buttons.
- Normalized zButtons checkbox defaults (`enabled`, `tooltip`, `hideonclick`, `parent.hide`, `parent.circle`, `showammoname`) so toggle states are always explicit and never nil.
- Fixed Beast Lore ability dropdown to exclude trainer-only abilities and list beast-learned abilities only.
- Removed junk `TBD` ability value from Wind Serpent dataset entry (`Venomflayer Serpent`) so it no longer appears in Beast Lore filters.
- Fixed zhunter child-button visibility restore so collapsed bars no longer hard-hide children (`ztrack` / `ztrap` expansion regression).
- Fixed pet tame metadata fallback so existing pets are not assigned current zone/time unless a real tame attempt is pending.
- Fixed Smart Ammo options copy mismatch by clarifying junk-shot swap behavior and restoring ammo target as previous equipped ammo.
- Fixed Smart Ammo default state so junk-shot swaps are enabled when no saved value exists.
- Fixed Beast Training startup prompt behavior so low-level hunters no longer receive training-scan warnings before level threshold.
- Restored hidden `/mth err` slash command behavior for debug-frame access.
- Fixed `zammo` children refresh on bag/inventory updates so newly acquired ammo types appear without `/reload`.
- Preserved `zammo` out-of-stock behavior so previously shown ammo entries still remain visible with zero/out state.
- Fixed intermittent `ztrack`/`ztrap` right-click expand/collapse issue after fresh login by preventing duplicate child-frame recreation during startup.
- Fixed `zpet` spell resolution after trainer updates by using robust spellbook lookup and immediate refresh on `LEARNED_SPELL_IN_TAB`.
## [1.0.3] - 2026-02-24
### Added
- Initial published release.
+1 -1
View File
@@ -1,5 +1,5 @@
## Interface: 11200 ## Interface: 11200
## Version: 1.0.4 ## Version: 1.2.0
## Title: MetaHunt - |cff00ff00Hunter ## Title: MetaHunt - |cff00ff00Hunter
## Author: Metasploit and his Copilot ;) ## Author: Metasploit and his Copilot ;)
## Notes: Unified addon suite for huntards making old addons compatible with TurtleWoW, and adding an arsenal of never seen Hunter's utilities. ## Notes: Unified addon suite for huntards making old addons compatible with TurtleWoW, and adding an arsenal of never seen Hunter's utilities.
+23 -8
View File
@@ -1,12 +1,12 @@
# MetaHunt # MetaHunt
MetaHunt is a Turtle WoW Hunter toolkit. MetaHunt is a Turtle WoW Hunter toolkit.
It combines never-seen pet-centric and beast tracking features, and revives old broken hunter add-ons. It is a modern modular addon that combines never-seen features, and improves/fixes a few old hunter add-ons.
It provides usefull tools for all hunters, wheter they are still leveling, lone-wolf, or HL raider. It provides a bunch useful tools for all huntards, wheter they are still levelling, lone-wolf, or HL raider.
## Twow Data ## Twow Data
Metahunt ships with larges up-to-date datastores for all Turtle WOW data a hunter needs : MetaHunt ships with large up-to-date datastores for all Turtle WOW data a hunter needs :
- All beasts, their location, and the abilities they can learn you - All beasts, their location, and the abilities they can learn you
- All Pet families, their abilities and their diet - All Pet families, their abilities and their diet
@@ -37,7 +37,7 @@ Old zHunterMod addon on steroids. Fully compatible with Twow, and enhanced with
- zPet : Intelligent collapsible pet Bar regrouping all pet spells and providing an intelligent button that always show you the right spell to use depending on the situation - zPet : Intelligent collapsible pet Bar regrouping all pet spells and providing an intelligent button that always show you the right spell to use depending on the situation
- zTrack: All your trackings in one collapsible bar - zTrack: All your trackings in one collapsible bar
- zAspect: All your trackings in one collapsible bar - zAspect: All your trackings in one collapsible bar
- zRanged : All the rnaged weampons currently in your bags to swap them fast - zRanged : All the ranged weampons currently in your bags to swap them fast
- But also zMounts, zToys and zCompanions. - But also zMounts, zToys and zCompanions.
## Feed-O-Matic ## Feed-O-Matic
@@ -48,16 +48,31 @@ Now compatible with Turtle, feed your pet with one key bind, it will always pick
The good old Chronometer addon, purged of non-necessary things and reconfigured for a pure hunter use. The good old Chronometer addon, purged of non-necessary things and reconfigured for a pure hunter use.
## Autobuy ## ICU (I see you)
Old addon used to display Targets' enhanced information when you click on your minimap tracking things. MetaHunt offers many more customization options for it.
## Auto-Buy
Define your own simple rules for auto buy ammo and pet food when you open a vendor. Define your own simple rules for auto buy ammo and pet food when you open a vendor.
## The book of Hunters ## Auto-Quest
The book of Hunters is the main GUI of Metahunt, it allows to display the data constantly collected about you and your pet, and browse the addon's data to find anything a Hunter needs. Just spam SHIFT-click on the NPC to validate quests Scorpok and Thorium arrows. Additionally you can have an enhanced tooltip that display your actual Scorpok-related items when you mouseover the mobs involved.
- Browse the Metahunt datastores of NPCs (Beast, vendors, masters) and open the map to locate them like in pfQuest
## The Great Book of Huntards
The Book is the main GUI of MetaHunt, it allows to display the data constantly collected about you and your pet, and browse the addon's data to find anything a Hunter needs.
- Browse the MetaHunt datastores of NPCs (Beast, vendors, masters) and open the map to locate them like in pfQuest
- Track all info about the pet abilities that you know and don't know yet - Track all info about the pet abilities that you know and don't know yet
- Track all info about your stabled pets - Track all info about your stabled pets
- Keep an history of all your pets after you abandon them or if they run away. - Keep an history of all your pets after you abandon them or if they run away.
## What it will never do.
The goal of MetaHunt is to offer hunter's features that are not covered by existing Twow addons, and in others https://github.com/SabineWren/Quiver .
There's no point to reinvent the wheel, except is the wheel is broken. Nothing will work better than Quiver for auto-shot, castbar and tranqshot mgt. MetaHunt is build to work alongside of Quiver and is complementary to it, and it will remain like this unless Quiver turns to be not upgraded anymore.
+3 -3
View File
@@ -98,7 +98,7 @@ local function AntiDaze_CancelRelevantAspect(isSelfDazed)
AntiDazeTooltip:SetOwner(UIParent, "ANCHOR_NONE") AntiDazeTooltip:SetOwner(UIParent, "ANCHOR_NONE")
AntiDazeTooltip:SetPlayerBuff(i, "HELPFUL") AntiDazeTooltip:SetPlayerBuff(i, "HELPFUL")
local text = AntiDazeTooltipTextLeft1 and AntiDazeTooltipTextLeft1:GetText() local text = MTH_AntiDazeProbeTextLeft1 and MTH_AntiDazeProbeTextLeft1:GetText()
if text == packName or (isSelfDazed and text == cheetahName) then if text == packName or (isSelfDazed and text == cheetahName) then
CancelPlayerBuff(i) CancelPlayerBuff(i)
return 1 return 1
@@ -112,8 +112,8 @@ local function AntiDaze_HandleSlash()
AntiDaze_SetEnabled(not AntiDaze_IsEnabled()) AntiDaze_SetEnabled(not AntiDaze_IsEnabled())
end end
AntiDazeTooltip = CreateFrame("GameTooltip", "AntiDazeTooltip", nil, "GameTooltipTemplate") AntiDazeTooltip = CreateFrame("GameTooltip", "MTH_AntiDazeProbe", nil, "GameTooltipTemplate")
AntiDazeFrame = CreateFrame("Frame", "AntiDazeFrame") AntiDazeFrame = CreateFrame("Frame", "MTH_AntiDazeEvent")
if AntiDazeFrame then if AntiDazeFrame then
AntiDazeFrame:RegisterEvent("VARIABLES_LOADED") AntiDazeFrame:RegisterEvent("VARIABLES_LOADED")
AntiDazeFrame:SetScript("OnEvent", function() AntiDazeFrame:SetScript("OnEvent", function()
+153 -1
View File
@@ -6,6 +6,29 @@ local function AutoStrip_Print(msg)
end end
end end
local AutoStrip_TraceEnabled = false
local function AutoStrip_Trace(msg)
if not AutoStrip_TraceEnabled then
return
end
AutoStrip_Print("[ASTRACE] " .. tostring(msg))
end
function AutoStrip_CommandTrace(mode)
local action = string.lower(tostring(mode or "status"))
if action == "on" or action == "1" or action == "true" then
AutoStrip_TraceEnabled = true
AutoStrip_Trace("trace enabled")
return
elseif action == "off" or action == "0" or action == "false" then
AutoStrip_Trace("trace disabled")
AutoStrip_TraceEnabled = false
return
end
AutoStrip_Print("[ASTRACE] status=" .. tostring(AutoStrip_TraceEnabled and true or false))
end
function AutoStrip_GetSaved() function AutoStrip_GetSaved()
if type(MTH_CharSavedVariables) ~= "table" then if type(MTH_CharSavedVariables) ~= "table" then
MTH_CharSavedVariables = {} MTH_CharSavedVariables = {}
@@ -20,6 +43,90 @@ local AUTO_STRIP_ORDER = {16, 17, 18, 5, 7, 1, 3, 10, 8, 6, 9}
AutoStrip_On = nil AutoStrip_On = nil
AutoStrip_WasInCombat = nil AutoStrip_WasInCombat = nil
AutoStrip_Frame = nil AutoStrip_Frame = nil
local AutoStrip_RestoreFrame = nil
local function AutoStrip_DescribePoint(frame)
if not (frame and frame.GetPoint) then
return "<no-frame>"
end
local point, relTo, relPoint, x, y = frame:GetPoint()
local relName = "nil"
if type(relTo) == "table" and relTo.GetName then
relName = tostring(relTo:GetName() or "<anon>")
elseif relTo then
relName = tostring(relTo)
end
return tostring(point or "nil")
.. "->" .. relName
.. ":" .. tostring(relPoint or "nil")
.. " @(" .. tostring(x) .. "," .. tostring(y) .. ")"
end
function AutoStrip_SaveDisplayPosition(reason)
if not (AutoStripDisplay and AutoStripDisplay.GetPoint) then
return
end
local saved = AutoStrip_GetSaved()
local point, _, relPoint, x, y = AutoStripDisplay:GetPoint()
x = tonumber(x)
y = tonumber(y)
if not (point and relPoint and x and y) then
return
end
saved["point"] = tostring(point)
saved["relativePoint"] = tostring(relPoint)
saved["x"] = math.floor(x + 0.5)
saved["y"] = math.floor(y + 0.5)
AutoStrip_Trace("persist-display-position reason=" .. tostring(reason or "")
.. " point=" .. tostring(saved["point"])
.. " rel=" .. tostring(saved["relativePoint"])
.. " x=" .. tostring(saved["x"])
.. " y=" .. tostring(saved["y"]))
end
local function AutoStrip_RestoreDisplayPosition(reason)
if not (AutoStripDisplay and AutoStripDisplay.ClearAllPoints and AutoStripDisplay.SetPoint) then
return false
end
local saved = AutoStrip_GetSaved()
local point = tostring(saved["point"] or "")
local relPoint = tostring(saved["relativePoint"] or "")
local x = tonumber(saved["x"])
local y = tonumber(saved["y"])
if point == "" or not x or not y then
AutoStrip_Trace("restore-display-position skipped reason=" .. tostring(reason or "")
.. " savedPoint=" .. tostring(saved["point"])
.. " savedX=" .. tostring(saved["x"])
.. " savedY=" .. tostring(saved["y"]))
return false
end
if relPoint == "" then
relPoint = point
end
AutoStripDisplay:ClearAllPoints()
AutoStripDisplay:SetPoint(point, UIParent, relPoint, x, y)
AutoStrip_Trace("restore-display-position reason=" .. tostring(reason or "")
.. " frame=" .. AutoStrip_DescribePoint(AutoStripDisplay))
return true
end
local function AutoStrip_QueueDeferredRestore(reason)
if not AutoStrip_RestoreFrame then
AutoStrip_RestoreFrame = CreateFrame("Frame", "MTH_AutoStripRestore")
if not AutoStrip_RestoreFrame then
return
end
end
AutoStrip_RestoreFrame._elapsed = 0
AutoStrip_RestoreFrame:SetScript("OnUpdate", function()
this._elapsed = (this._elapsed or 0) + (arg1 or 0)
if this._elapsed < 0.2 then
return
end
this:SetScript("OnUpdate", nil)
AutoStrip_RestoreDisplayPosition("deferred:" .. tostring(reason or ""))
end)
end
function AutoStrip_SetDisplayIcon() function AutoStrip_SetDisplayIcon()
local icon = getglobal("AutoStripDisplayIcon") or getglobal("AutoStripDisplayIconTexture") local icon = getglobal("AutoStripDisplayIcon") or getglobal("AutoStripDisplayIconTexture")
@@ -35,6 +142,11 @@ end
function AutoStrip_SetAutoStripToggle(enabled, silent) function AutoStrip_SetAutoStripToggle(enabled, silent)
local saved = AutoStrip_GetSaved() local saved = AutoStrip_GetSaved()
AutoStrip_Trace("SetAutoStripToggle enabled=" .. tostring(enabled and true or false)
.. " silent=" .. tostring(silent and true or false)
.. " savedBefore=" .. tostring(saved["autostrip"] and 1 or 0)
.. " runtimeBefore=" .. tostring(AutoStrip_On and 1 or 0)
.. " castShownBefore=" .. tostring((AutoStripDisplayAutoCast and AutoStripDisplayAutoCast:IsVisible()) and 1 or 0))
if enabled then if enabled then
saved["autostrip"] = 1 saved["autostrip"] = 1
AutoStrip_On = 1 AutoStrip_On = 1
@@ -54,10 +166,17 @@ function AutoStrip_SetAutoStripToggle(enabled, silent)
AutoStrip_Print("Auto-Strip disabled.") AutoStrip_Print("Auto-Strip disabled.")
end end
end end
AutoStrip_Trace("SetAutoStripToggle savedAfter=" .. tostring(saved["autostrip"] and 1 or 0)
.. " runtimeAfter=" .. tostring(AutoStrip_On and 1 or 0)
.. " castShownAfter=" .. tostring((AutoStripDisplayAutoCast and AutoStripDisplayAutoCast:IsVisible()) and 1 or 0))
end end
function AutoStrip_SetDisplayToggle(enabled, silent) function AutoStrip_SetDisplayToggle(enabled, silent)
local saved = AutoStrip_GetSaved() local saved = AutoStrip_GetSaved()
AutoStrip_Trace("SetDisplayToggle enabled=" .. tostring(enabled and true or false)
.. " silent=" .. tostring(silent and true or false)
.. " savedDisplayBefore=" .. tostring(saved["display"] and 1 or 0)
.. " frameShownBefore=" .. tostring((AutoStripDisplay and AutoStripDisplay:IsVisible()) and 1 or 0))
if enabled then if enabled then
saved["display"] = 1 saved["display"] = 1
if AutoStripDisplay then if AutoStripDisplay then
@@ -79,9 +198,15 @@ function AutoStrip_SetDisplayToggle(enabled, silent)
AutoStrip_Print("AutoStrip button is now hidden.") AutoStrip_Print("AutoStrip button is now hidden.")
end end
end end
AutoStrip_Trace("SetDisplayToggle savedDisplayAfter=" .. tostring(saved["display"] and 1 or 0)
.. " frameShownAfter=" .. tostring((AutoStripDisplay and AutoStripDisplay:IsVisible()) and 1 or 0)
.. " castShownAfter=" .. tostring((AutoStripDisplayAutoCast and AutoStripDisplayAutoCast:IsVisible()) and 1 or 0))
end end
function AutoStrip_UnequipAll(weaponsOnly) function AutoStrip_UnequipAll(weaponsOnly)
AutoStrip_Trace("UnequipAll called weaponsOnly=" .. tostring(weaponsOnly and 1 or 0)
.. " runtimeBefore=" .. tostring(AutoStrip_On and 1 or 0)
.. " wasInCombat=" .. tostring(AutoStrip_WasInCombat and 1 or 0))
AutoStrip_On = nil AutoStrip_On = nil
if AutoStripDisplayAutoCast then if AutoStripDisplayAutoCast then
AutoStripDisplayAutoCast:Hide() AutoStripDisplayAutoCast:Hide()
@@ -102,6 +227,7 @@ function AutoStrip_UnequipAll(weaponsOnly)
if not hasEmptySlot then if not hasEmptySlot then
AutoStrip_Print("You need at least one empty bag slot to auto-strip.") AutoStrip_Print("You need at least one empty bag slot to auto-strip.")
AutoStrip_Trace("UnequipAll aborted no-empty-slot")
return return
end end
@@ -121,19 +247,36 @@ function AutoStrip_UnequipAll(weaponsOnly)
end end
end end
end end
AutoStrip_Trace("UnequipAll completed runtimeAfter=" .. tostring(AutoStrip_On and 1 or 0)
.. " castShownAfter=" .. tostring((AutoStripDisplayAutoCast and AutoStripDisplayAutoCast:IsVisible()) and 1 or 0))
end end
local function AutoStrip_OnEvent() local function AutoStrip_OnEvent()
AutoStrip_Trace("OnEvent evt=" .. tostring(event or "")
.. " runtime=" .. tostring(AutoStrip_On and 1 or 0)
.. " wasInCombat=" .. tostring(AutoStrip_WasInCombat and 1 or 0)
.. " playerInCombat=" .. tostring((type(UnitAffectingCombat) == "function" and UnitAffectingCombat("player")) and 1 or 0))
if event == "VARIABLES_LOADED" then if event == "VARIABLES_LOADED" then
local saved = AutoStrip_GetSaved() local saved = AutoStrip_GetSaved()
AutoStrip_Trace("VARIABLES_LOADED saved.autostrip=" .. tostring(saved["autostrip"] and 1 or 0)
.. " saved.display=" .. tostring(saved["display"] and 1 or 0))
AutoStrip_WasInCombat = UnitAffectingCombat("player") and 1 or nil AutoStrip_WasInCombat = UnitAffectingCombat("player") and 1 or nil
AutoStrip_RestoreDisplayPosition("VARIABLES_LOADED")
AutoStrip_SetDisplayToggle(saved["display"] and true or false, 1) AutoStrip_SetDisplayToggle(saved["display"] and true or false, 1)
AutoStrip_SetAutoStripToggle(saved["autostrip"] and true or false, 1) AutoStrip_SetAutoStripToggle(saved["autostrip"] and true or false, 1)
AutoStrip_QueueDeferredRestore("VARIABLES_LOADED")
return return
end end
if event == "PLAYER_ENTERING_WORLD" then if event == "PLAYER_ENTERING_WORLD" then
AutoStrip_WasInCombat = UnitAffectingCombat("player") and 1 or nil AutoStrip_WasInCombat = UnitAffectingCombat("player") and 1 or nil
AutoStrip_RestoreDisplayPosition("PLAYER_ENTERING_WORLD")
AutoStrip_QueueDeferredRestore("PLAYER_ENTERING_WORLD")
return
end
if event == "PLAYER_LOGOUT" then
AutoStrip_SaveDisplayPosition("PLAYER_LOGOUT")
return return
end end
@@ -144,6 +287,7 @@ local function AutoStrip_OnEvent()
if event == "PLAYER_REGEN_ENABLED" then if event == "PLAYER_REGEN_ENABLED" then
if AutoStrip_On and AutoStrip_WasInCombat then if AutoStrip_On and AutoStrip_WasInCombat then
AutoStrip_Trace("PLAYER_REGEN_ENABLED triggering auto strip")
AutoStrip_UnequipAll() AutoStrip_UnequipAll()
end end
AutoStrip_WasInCombat = nil AutoStrip_WasInCombat = nil
@@ -152,6 +296,8 @@ end
local function AutoStrip_HandleSlash(msg) local function AutoStrip_HandleSlash(msg)
local saved = AutoStrip_GetSaved() local saved = AutoStrip_GetSaved()
AutoStrip_Trace("Slash msg='" .. tostring(msg or "") .. "' saved.autostrip=" .. tostring(saved["autostrip"] and 1 or 0)
.. " runtime=" .. tostring(AutoStrip_On and 1 or 0))
if msg == "display" then if msg == "display" then
AutoStrip_SetDisplayToggle(not (saved["display"] and true or false)) AutoStrip_SetDisplayToggle(not (saved["display"] and true or false))
elseif msg == "toggle" then elseif msg == "toggle" then
@@ -170,12 +316,13 @@ local function AutoStrip_HandleSlash(msg)
end end
end end
AutoStrip_Frame = CreateFrame("Frame", "AutoStripFrame") AutoStrip_Frame = CreateFrame("Frame", "MTH_AutoStripEvent")
if AutoStrip_Frame then if AutoStrip_Frame then
AutoStrip_Frame:RegisterEvent("VARIABLES_LOADED") AutoStrip_Frame:RegisterEvent("VARIABLES_LOADED")
AutoStrip_Frame:RegisterEvent("PLAYER_REGEN_DISABLED") AutoStrip_Frame:RegisterEvent("PLAYER_REGEN_DISABLED")
AutoStrip_Frame:RegisterEvent("PLAYER_REGEN_ENABLED") AutoStrip_Frame:RegisterEvent("PLAYER_REGEN_ENABLED")
AutoStrip_Frame:RegisterEvent("PLAYER_ENTERING_WORLD") AutoStrip_Frame:RegisterEvent("PLAYER_ENTERING_WORLD")
AutoStrip_Frame:RegisterEvent("PLAYER_LOGOUT")
AutoStrip_Frame:SetScript("OnEvent", AutoStrip_OnEvent) AutoStrip_Frame:SetScript("OnEvent", AutoStrip_OnEvent)
end end
@@ -187,3 +334,8 @@ SLASH_AUTOSTRIP1 = "/autostrip"
SlashCmdList["AUTOSTRIP"] = AutoStrip_HandleSlash SlashCmdList["AUTOSTRIP"] = AutoStrip_HandleSlash
SLASH_ZSTRIP1 = "/zstrip" SLASH_ZSTRIP1 = "/zstrip"
SlashCmdList["ZSTRIP"] = AutoStrip_HandleSlash SlashCmdList["ZSTRIP"] = AutoStrip_HandleSlash
SLASH_AUTOSTRIPTRACE1 = "/autostriptrace"
SLASH_AUTOSTRIPTRACE2 = "/astrace"
SlashCmdList["AUTOSTRIPTRACE"] = function(msg)
AutoStrip_CommandTrace(msg)
end
+6
View File
@@ -68,6 +68,9 @@
if ( this.isMoving ) then if ( this.isMoving ) then
this:StopMovingOrSizing() this:StopMovingOrSizing()
this.isMoving = false this.isMoving = false
if AutoStrip_SaveDisplayPosition then
AutoStrip_SaveDisplayPosition("mouse-up-stop")
end
end end
</OnMouseUp> </OnMouseUp>
<OnDragStart> <OnDragStart>
@@ -79,6 +82,9 @@
<OnDragStop> <OnDragStop>
this:StopMovingOrSizing() this:StopMovingOrSizing()
this.isMoving = false this.isMoving = false
if AutoStrip_SaveDisplayPosition then
AutoStrip_SaveDisplayPosition("drag-stop")
end
</OnDragStop> </OnDragStop>
</Scripts> </Scripts>
<NormalTexture name="$parentNormalTexture" file="Interface\Buttons\UI-Quickslot2"> <NormalTexture name="$parentNormalTexture" file="Interface\Buttons\UI-Quickslot2">
+1 -1
View File
@@ -1,5 +1,5 @@
MTH_CONST = MTH_CONST or {} MTH_CONST = MTH_CONST or {}
MTH_CONST.version = MTH_CONST.version or "1.0.4" MTH_CONST.version = MTH_CONST.version or "1.2.0"
MTH_CONST.WEAPON_TYPES = { MTH_CONST.WEAPON_TYPES = {
BOWS = "Bows", BOWS = "Bows",
+144 -13
View File
@@ -460,6 +460,7 @@ local function MTH_FEED_CoreTrackerOnEvent()
end end
elseif evt == "BAG_UPDATE" then elseif evt == "BAG_UPDATE" then
MTH_FEED_IndexBagFoods() MTH_FEED_IndexBagFoods()
MTH_FEED_InvalidateDietMapCache()
elseif evt == "CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS" then elseif evt == "CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS" then
if MTH_FEED_ActiveCoreAttemptId and MTH_FEED_HasPetFeedBuff() then if MTH_FEED_ActiveCoreAttemptId and MTH_FEED_HasPetFeedBuff() then
MTH_FEED_Trace("Core tracker buff event confirms acceptance") MTH_FEED_Trace("Core tracker buff event confirms acceptance")
@@ -468,7 +469,32 @@ local function MTH_FEED_CoreTrackerOnEvent()
end end
end end
local MTH_FEED_CoreTrackerUpdateElapsed = 0
local MTH_FEED_LastStaleCleanupAt = 0
local function MTH_FEED_CoreTrackerOnUpdate() local function MTH_FEED_CoreTrackerOnUpdate()
MTH_FEED_CoreTrackerUpdateElapsed = MTH_FEED_CoreTrackerUpdateElapsed + (arg1 or 0)
if MTH_FEED_CoreTrackerUpdateElapsed < 0.10 then
return
end
MTH_FEED_CoreTrackerUpdateElapsed = 0
-- Periodic stale attempt cleanup (every ~30 seconds)
local now = GetTime() or 0
if (now - MTH_FEED_LastStaleCleanupAt) >= 30 then
MTH_FEED_LastStaleCleanupAt = now
if MTH_FEED_Runtime and type(MTH_FEED_Runtime.attempts) == "table" then
for id, row in pairs(MTH_FEED_Runtime.attempts) do
if type(row) == "table" then
local age = now - (tonumber(row.startedAt) or now)
if age > 10 then
MTH_FEED_Runtime.attempts[id] = nil
end
end
end
end
end
local attemptId = MTH_FEED_ActiveCoreAttemptId local attemptId = MTH_FEED_ActiveCoreAttemptId
if attemptId == nil then if attemptId == nil then
return return
@@ -499,7 +525,7 @@ local function MTH_FEED_EnsureTrackerFrame()
if MTH_FEED_TrackerFrame then if MTH_FEED_TrackerFrame then
return MTH_FEED_TrackerFrame return MTH_FEED_TrackerFrame
end end
local frame = CreateFrame("Frame", "MTH_FeedTrackingFrame") local frame = CreateFrame("Frame", "MTH_FeedTracking")
if not frame then if not frame then
return nil return nil
end end
@@ -526,6 +552,7 @@ local function MTH_FEED_CoreDropItemOnUnitHook(unit)
end end
if target == "pet" and CursorHasItem and CursorHasItem() then if target == "pet" and CursorHasItem and CursorHasItem() then
MTH_FEED_EnsureTrackerFrame()
local itemId, itemName, itemLink, itemIcon = MTH_FEED_GetCursorItemSnapshot() local itemId, itemName, itemLink, itemIcon = MTH_FEED_GetCursorItemSnapshot()
local pet = MTH_FEED_GetCurrentPetContext() local pet = MTH_FEED_GetCurrentPetContext()
if not itemId then if not itemId then
@@ -608,7 +635,6 @@ function MTH_FEED_DebugStatus()
end end
function MTH_FEED_ReinstallCoreTracking() function MTH_FEED_ReinstallCoreTracking()
MTH_FEED_EnsureTrackerFrame()
local ok = MTH_FEED_InstallCoreHooks() local ok = MTH_FEED_InstallCoreHooks()
return ok and true or false return ok and true or false
end end
@@ -617,7 +643,7 @@ local function MTH_FEED_EnsureBootstrapFrame()
if MTH_FEED_BootstrapFrame ~= nil then if MTH_FEED_BootstrapFrame ~= nil then
return MTH_FEED_BootstrapFrame return MTH_FEED_BootstrapFrame
end end
local frame = CreateFrame("Frame", "MTH_FeedTrackingBootstrapFrame") local frame = CreateFrame("Frame", "MTH_FeedTrackingBoot")
if not frame then if not frame then
return nil return nil
end end
@@ -626,6 +652,8 @@ local function MTH_FEED_EnsureBootstrapFrame()
frame:RegisterEvent("PLAYER_ENTERING_WORLD") frame:RegisterEvent("PLAYER_ENTERING_WORLD")
frame:SetScript("OnEvent", function() frame:SetScript("OnEvent", function()
MTH_FEED_ReinstallCoreTracking() MTH_FEED_ReinstallCoreTracking()
this:UnregisterAllEvents()
this:SetScript("OnEvent", nil)
end) end)
MTH_FEED_BootstrapFrame = frame MTH_FEED_BootstrapFrame = frame
return frame return frame
@@ -822,7 +850,16 @@ local function MTH_FEED_NormalizeReason(reason, rawMessage)
return "unknown" return "unknown"
end end
local MTH_FEED_DietMapCache = nil
local function MTH_FEED_InvalidateDietMapCache()
MTH_FEED_DietMapCache = nil
end
local function MTH_FEED_GetDietByItemIdMap() local function MTH_FEED_GetDietByItemIdMap()
if MTH_FEED_DietMapCache then
return MTH_FEED_DietMapCache
end
local map = {} local map = {}
if type(FOM_Foods) ~= "table" then if type(FOM_Foods) ~= "table" then
return map return map
@@ -837,6 +874,7 @@ local function MTH_FEED_GetDietByItemIdMap()
end end
end end
end end
MTH_FEED_DietMapCache = map
return map return map
end end
@@ -940,9 +978,6 @@ function MTH_FEED_BeginAttempt(payload)
itemIcon = infoTexture itemIcon = infoTexture
end end
end end
if (not itemIcon or itemIcon == "") then
itemIcon = MTH_FEED_FindItemIconInBags(itemId, payload and payload.itemName)
end
MTH_FEED_Runtime.attempts[attemptId] = { MTH_FEED_Runtime.attempts[attemptId] = {
id = attemptId, id = attemptId,
@@ -1113,7 +1148,7 @@ function MTH_FEED_IsFoodCompatible(petLevel, foodLevel)
return true return true
end end
function MTH_FEED_IsExceptionReject(itemId) function MTH_FEED_IsExceptionReject(itemId, petLevel)
local key = tonumber(itemId) local key = tonumber(itemId)
if not key then if not key then
return false return false
@@ -1123,6 +1158,11 @@ function MTH_FEED_IsExceptionReject(itemId)
if type(row) ~= "table" then if type(row) ~= "table" then
return false return false
end end
local numericPet = tonumber(petLevel)
local blockedAtOrAbove = tonumber(row.blockAtOrAbovePetLevel)
if blockedAtOrAbove and numericPet and numericPet >= blockedAtOrAbove then
return true
end
if row.anomalyReject ~= true then if row.anomalyReject ~= true then
return false return false
end end
@@ -1137,6 +1177,17 @@ function MTH_FEED_IsExceptionReject(itemId)
if not reasons then if not reasons then
return false return false
end end
local lowLevelCount = tonumber(reasons.lowLevel) or 0
if lowLevelCount >= 1 then
local maxPetLevel = tonumber(row.maxPetLevel)
if numericPet and maxPetLevel then
if numericPet > maxPetLevel then
return true
end
else
return true
end
end
local wrongFoodCount = tonumber(reasons.wrongFood) or 0 local wrongFoodCount = tonumber(reasons.wrongFood) or 0
if wrongFoodCount < 2 then if wrongFoodCount < 2 then
return false return false
@@ -1144,6 +1195,49 @@ function MTH_FEED_IsExceptionReject(itemId)
return true return true
end end
function MTH_FEED_BlockItemForPetLevel(itemId, petLevel, reason)
local key = tonumber(itemId)
local numericPet = tonumber(petLevel)
if not key or not numericPet then
return false
end
if numericPet < 1 then
numericPet = 1
end
local store = MTH_FEED_EnsureStore()
if type(store.exceptions.byItemId[key]) ~= "table" then
store.exceptions.byItemId[key] = {
anomalyReject = true,
reasons = { noBuff = 0, wrongFood = 0, lowLevel = 0, unknown = 0 },
lastObservedAt = 0,
}
end
local row = store.exceptions.byItemId[key]
if type(row.reasons) ~= "table" then
row.reasons = { noBuff = 0, wrongFood = 0, lowLevel = 0, unknown = 0 }
end
row.anomalyReject = true
row.lastObservedAt = MTH_FEED_Now()
if tonumber(row.blockAtOrAbovePetLevel) == nil or numericPet < tonumber(row.blockAtOrAbovePetLevel) then
row.blockAtOrAbovePetLevel = numericPet
end
local normalizedReason = MTH_FEED_NormalizeReason(reason, nil)
if normalizedReason == "no-buff" then
row.reasons.noBuff = (tonumber(row.reasons.noBuff) or 0) + 1
elseif normalizedReason == "low-level" then
row.reasons.lowLevel = (tonumber(row.reasons.lowLevel) or 0) + 1
elseif normalizedReason == "wrong-food" then
row.reasons.wrongFood = (tonumber(row.reasons.wrongFood) or 0) + 1
else
row.reasons.unknown = (tonumber(row.reasons.unknown) or 0) + 1
end
MTH_FEED_TouchStore(store)
MTH_FEED_Trace("BlockItemForPetLevel itemId=" .. tostring(key)
.. " blockAtOrAbove=" .. tostring(row.blockAtOrAbovePetLevel)
.. " reason=" .. tostring(normalizedReason))
return true
end
function MTH_FEED_GetPetFeedStats(petId) function MTH_FEED_GetPetFeedStats(petId)
local key = tostring(petId or "") local key = tostring(petId or "")
if key == "" then if key == "" then
@@ -1153,7 +1247,7 @@ function MTH_FEED_GetPetFeedStats(petId)
return store.byPetId[key] return store.byPetId[key]
end end
local function MTH_FEED_UpsertException(store, itemId, reason) local function MTH_FEED_UpsertException(store, itemId, reason, petLevel)
if not itemId then if not itemId then
return return
end end
@@ -1175,6 +1269,16 @@ local function MTH_FEED_UpsertException(store, itemId, reason)
row.reasons.wrongFood = (tonumber(row.reasons.wrongFood) or 0) + 1 row.reasons.wrongFood = (tonumber(row.reasons.wrongFood) or 0) + 1
elseif reason == "low-level" then elseif reason == "low-level" then
row.reasons.lowLevel = (tonumber(row.reasons.lowLevel) or 0) + 1 row.reasons.lowLevel = (tonumber(row.reasons.lowLevel) or 0) + 1
local numericPetLevel = tonumber(petLevel)
if numericPetLevel and numericPetLevel > 1 then
local derivedMaxPetLevel = numericPetLevel - 1
if derivedMaxPetLevel < 1 then
derivedMaxPetLevel = 1
end
if tonumber(row.maxPetLevel) == nil or derivedMaxPetLevel < tonumber(row.maxPetLevel) then
row.maxPetLevel = derivedMaxPetLevel
end
end
else else
row.reasons.unknown = (tonumber(row.reasons.unknown) or 0) + 1 row.reasons.unknown = (tonumber(row.reasons.unknown) or 0) + 1
end end
@@ -1182,6 +1286,36 @@ local function MTH_FEED_UpsertException(store, itemId, reason)
row.lastObservedAt = MTH_FEED_Now() row.lastObservedAt = MTH_FEED_Now()
end end
local function MTH_FEED_ClearStaleExceptionOnAccept(store, itemId)
if not itemId or type(store) ~= "table" or type(store.exceptions) ~= "table" or type(store.exceptions.byItemId) ~= "table" then
return
end
local key = tonumber(itemId) or itemId
local row = store.exceptions.byItemId[key]
if type(row) ~= "table" then
return
end
if type(row.reasons) ~= "table" then
store.exceptions.byItemId[key] = nil
return
end
row.reasons.noBuff = 0
row.lastObservedAt = MTH_FEED_Now()
local noBuff = tonumber(row.reasons.noBuff) or 0
local lowLevel = tonumber(row.reasons.lowLevel) or 0
local wrongFood = tonumber(row.reasons.wrongFood) or 0
local unknown = tonumber(row.reasons.unknown) or 0
if noBuff <= 0
and lowLevel <= 0
and wrongFood <= 0
and unknown <= 0
and tonumber(row.blockAtOrAbovePetLevel) == nil
and tonumber(row.maxPetLevel) == nil then
store.exceptions.byItemId[key] = nil
end
end
function MTH_FEED_FinalizeAttempt(attemptId, payload) function MTH_FEED_FinalizeAttempt(attemptId, payload)
local row = MTH_FEED_Runtime.attempts[attemptId] local row = MTH_FEED_Runtime.attempts[attemptId]
if type(row) ~= "table" then if type(row) ~= "table" then
@@ -1241,6 +1375,7 @@ function MTH_FEED_FinalizeAttempt(attemptId, payload)
if itemRow then if itemRow then
itemRow.accepted = itemRow.accepted + 1 itemRow.accepted = itemRow.accepted + 1
end end
MTH_FEED_ClearStaleExceptionOnAccept(store, row.itemId)
local petKey = tostring((petRow and petRow.petId) or row.petId or "") local petKey = tostring((petRow and petRow.petId) or row.petId or "")
if petKey ~= "" then if petKey ~= "" then
MTH_FEED_Runtime.sessionFeedsByPetId[petKey] = (tonumber(MTH_FEED_Runtime.sessionFeedsByPetId[petKey]) or 0) + 1 MTH_FEED_Runtime.sessionFeedsByPetId[petKey] = (tonumber(MTH_FEED_Runtime.sessionFeedsByPetId[petKey]) or 0) + 1
@@ -1257,7 +1392,7 @@ function MTH_FEED_FinalizeAttempt(attemptId, payload)
if itemRow then if itemRow then
itemRow.rejected = itemRow.rejected + 1 itemRow.rejected = itemRow.rejected + 1
end end
MTH_FEED_UpsertException(store, row.itemId, reason) MTH_FEED_UpsertException(store, row.itemId, reason, row.petLevel)
end end
if itemRow then if itemRow then
@@ -1280,9 +1415,6 @@ function MTH_FEED_FinalizeAttempt(attemptId, payload)
persistedIcon = directTexture persistedIcon = directTexture
end end
end end
if (not persistedIcon or persistedIcon == "") then
persistedIcon = MTH_FEED_FindItemIconInBags(row.itemId, row.itemName)
end
if persistedIcon and persistedIcon ~= "" then if persistedIcon and persistedIcon ~= "" then
itemRow.itemIcon = persistedIcon itemRow.itemIcon = persistedIcon
end end
@@ -1542,6 +1674,5 @@ function MTH_FEED_DebugDumpCurrentPet(limit)
return true return true
end end
MTH_FEED_EnsureTrackerFrame()
MTH_FEED_InstallCoreHooks() MTH_FEED_InstallCoreHooks()
MTH_FEED_EnsureBootstrapFrame() MTH_FEED_EnsureBootstrapFrame()
+143 -80
View File
@@ -1,5 +1,5 @@
MTH = MTH or { MTH = MTH or {
version = "1.0.4", version = "1.2.0",
name = "MetaHunt", name = "MetaHunt",
modules = {}, modules = {},
config = {}, config = {},
@@ -16,6 +16,14 @@ local MTH_MESSAGE_DEFAULTS = {
spellbookScan = false, spellbookScan = false,
petRanAway = true, petRanAway = true,
mapMarkers = true, mapMarkers = true,
stableScan = true,
}
local MTH_MODULE_DEFAULT_STATES = {
autoquest = false,
autobuy = false,
feedomatic = false,
icu = false,
} }
local function MTH_ClassGateTrace(_step, _detail) local function MTH_ClassGateTrace(_step, _detail)
@@ -36,7 +44,7 @@ local function MTH_ClassGateEnsureAnnounceFrame(self)
if not self or self._classGateAnnounceFrame then if not self or self._classGateAnnounceFrame then
return return
end end
local frame = CreateFrame("Frame", "MTH_ClassGateAnnounceFrame") local frame = CreateFrame("Frame", "MTH_ClassGateAnnounce")
if not frame then if not frame then
return return
end end
@@ -47,12 +55,12 @@ local function MTH_ClassGateEnsureAnnounceFrame(self)
end end
end) end)
frame._mthElapsed = 0 frame._mthElapsed = 0
frame:SetScript("OnUpdate", function(self, elapsed) frame:SetScript("OnUpdate", function()
self._mthElapsed = (self._mthElapsed or 0) + (elapsed or arg1 or 0) this._mthElapsed = (this._mthElapsed or 0) + (arg1 or 0)
if self._mthElapsed < 0.5 then if this._mthElapsed < 0.5 then
return return
end end
self._mthElapsed = 0 this._mthElapsed = 0
if MTH and MTH._classGateAnnouncedChat then if MTH and MTH._classGateAnnouncedChat then
MTH_ClassGateClearAnnounceFrame(MTH) MTH_ClassGateClearAnnounceFrame(MTH)
return return
@@ -184,21 +192,19 @@ end
MTH:ApplyClassGate("startup") MTH:ApplyClassGate("startup")
if not MTH._classGateLifecycleFrame then if not MTH._classGateLifecycleFrame then
local classGateFrame = CreateFrame("Frame", "MTH_ClassGateLifecycleFrame") local classGateFrame = CreateFrame("Frame", "MTH_ClassGateLifecycle")
if classGateFrame then if classGateFrame then
classGateFrame:RegisterEvent("PLAYER_LOGIN") classGateFrame:RegisterEvent("PLAYER_LOGIN")
classGateFrame:RegisterEvent("PLAYER_ENTERING_WORLD") classGateFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
classGateFrame:SetScript("OnEvent", function(self, eventName) classGateFrame:SetScript("OnEvent", function()
self = self or this if MTH and event == "PLAYER_LOGIN" then
eventName = eventName or event
if MTH and eventName == "PLAYER_LOGIN" then
MTH._classGateAnnouncedChat = nil MTH._classGateAnnouncedChat = nil
MTH._classGateAnnounced = nil MTH._classGateAnnounced = nil
MTH._classGateAnnouncePending = nil MTH._classGateAnnouncePending = nil
end end
if MTH and MTH.ApplyClassGate and MTH:ApplyClassGate(eventName) and MTH._classGateAnnouncedChat then if MTH and MTH.ApplyClassGate and MTH:ApplyClassGate(event) and MTH._classGateAnnouncedChat then
self:UnregisterAllEvents() this:UnregisterAllEvents()
self:SetScript("OnEvent", nil) this:SetScript("OnEvent", nil)
end end
end) end)
MTH._classGateLifecycleFrame = classGateFrame MTH._classGateLifecycleFrame = classGateFrame
@@ -424,9 +430,53 @@ local function MTH_GetPersistedModuleEnabled(name, defaultEnabled)
local resolvedName = MTH_NormalizeModuleName(name) local resolvedName = MTH_NormalizeModuleName(name)
local candidates = MTH_ModuleNameCandidates(name) local candidates = MTH_ModuleNameCandidates(name)
if type(MTH_CharSavedVariables) ~= "table" then
MTH_CharSavedVariables = {}
end
if type(MTH_CharSavedVariables.moduleStates) ~= "table" then
MTH_CharSavedVariables.moduleStates = {}
end
if type(MTH_CharSavedVariables.modules) ~= "table" then
MTH_CharSavedVariables.modules = {}
end
if type(MTH_CharSavedVariables.modules[resolvedName]) ~= "table" then
MTH_CharSavedVariables.modules[resolvedName] = {}
end
if type(MTH_SavedVariables) ~= "table" then if type(MTH_SavedVariables) ~= "table" then
MTH_ModuleStateDebug("read " .. tostring(name) .. " no-savedvars fallback-default=" .. tostring(defaultEnabled and true or false)) MTH_SavedVariables = {}
return defaultEnabled and true or false end
if type(MTH_SavedVariables.moduleStates) ~= "table" then
MTH_SavedVariables.moduleStates = {}
end
if type(MTH_SavedVariables.modules) ~= "table" then
MTH_SavedVariables.modules = {}
end
local hardDefault = MTH_MODULE_DEFAULT_STATES[resolvedName]
if hardDefault ~= nil then
local hasCharState = MTH_CharSavedVariables.moduleStates[resolvedName] ~= nil
or MTH_CharSavedVariables.modules[resolvedName].enabled ~= nil
if not hasCharState then
local resolved = hardDefault and true or false
MTH_CharSavedVariables.moduleStates[resolvedName] = resolved
MTH_CharSavedVariables.modules[resolvedName].enabled = resolved
MTH_ModuleStateDebug("read " .. tostring(name) .. " seeded char default=" .. tostring(resolved))
return resolved
end
end
if type(MTH_CharSavedVariables.moduleStates) == "table"
then
for i = 1, table.getn(candidates) do
local key = candidates[i]
if MTH_CharSavedVariables.moduleStates[key] ~= nil then
local resolved = MTH_CharSavedVariables.moduleStates[key] and true or false
MTH_ModuleStateDebug("read " .. tostring(name) .. " from char.moduleStates." .. tostring(key) .. "=" .. tostring(resolved))
MTH_CharSavedVariables.moduleStates[resolvedName] = resolved
return resolved
end
end
end end
if type(MTH_SavedVariables.moduleStates) == "table" then if type(MTH_SavedVariables.moduleStates) == "table" then
@@ -435,25 +485,11 @@ local function MTH_GetPersistedModuleEnabled(name, defaultEnabled)
if MTH_SavedVariables.moduleStates[key] ~= nil then if MTH_SavedVariables.moduleStates[key] ~= nil then
local resolved = MTH_SavedVariables.moduleStates[key] and true or false local resolved = MTH_SavedVariables.moduleStates[key] and true or false
MTH_ModuleStateDebug("read " .. tostring(name) .. " from moduleStates." .. tostring(key) .. "=" .. tostring(resolved)) MTH_ModuleStateDebug("read " .. tostring(name) .. " from moduleStates." .. tostring(key) .. "=" .. tostring(resolved))
MTH_SavedVariables.moduleStates[resolvedName] = resolved
return resolved
end
end
end
if type(MTH_CharSavedVariables) == "table"
and type(MTH_CharSavedVariables.moduleStates) == "table"
then
for i = 1, table.getn(candidates) do
local key = candidates[i]
if MTH_CharSavedVariables.moduleStates[key] ~= nil then
local resolved = MTH_CharSavedVariables.moduleStates[key] and true or false
MTH_ModuleStateDebug("read " .. tostring(name) .. " from char.moduleStates." .. tostring(key) .. "=" .. tostring(resolved))
if type(MTH_SavedVariables.moduleStates) ~= "table" then
MTH_SavedVariables.moduleStates = {}
end
MTH_SavedVariables.moduleStates[resolvedName] = resolved
MTH_CharSavedVariables.moduleStates[resolvedName] = resolved MTH_CharSavedVariables.moduleStates[resolvedName] = resolved
if type(MTH_CharSavedVariables.modules[resolvedName]) ~= "table" then
MTH_CharSavedVariables.modules[resolvedName] = {}
end
MTH_CharSavedVariables.modules[resolvedName].enabled = resolved
return resolved return resolved
end end
end end
@@ -465,9 +501,11 @@ local function MTH_GetPersistedModuleEnabled(name, defaultEnabled)
if type(MTH_SavedVariables.modules[key]) == "table" and MTH_SavedVariables.modules[key].enabled ~= nil then if type(MTH_SavedVariables.modules[key]) == "table" and MTH_SavedVariables.modules[key].enabled ~= nil then
local resolved = MTH_SavedVariables.modules[key].enabled and true or false local resolved = MTH_SavedVariables.modules[key].enabled and true or false
MTH_ModuleStateDebug("read " .. tostring(name) .. " from modules." .. tostring(key) .. ".enabled=" .. tostring(resolved)) MTH_ModuleStateDebug("read " .. tostring(name) .. " from modules." .. tostring(key) .. ".enabled=" .. tostring(resolved))
if type(MTH_SavedVariables.modules[resolvedName]) ~= "table" then MTH_CharSavedVariables.moduleStates[resolvedName] = resolved
MTH_SavedVariables.modules[resolvedName] = MTH_SavedVariables.modules[key] if type(MTH_CharSavedVariables.modules[resolvedName]) ~= "table" then
MTH_CharSavedVariables.modules[resolvedName] = {}
end end
MTH_CharSavedVariables.modules[resolvedName].enabled = resolved
return resolved return resolved
end end
end end
@@ -478,16 +516,11 @@ local function MTH_GetPersistedModuleEnabled(name, defaultEnabled)
if type(MTH_SavedVariables[key]) == "table" and MTH_SavedVariables[key].enabled ~= nil then if type(MTH_SavedVariables[key]) == "table" and MTH_SavedVariables[key].enabled ~= nil then
local resolved = MTH_SavedVariables[key].enabled and true or false local resolved = MTH_SavedVariables[key].enabled and true or false
MTH_ModuleStateDebug("read " .. tostring(name) .. " from legacy-top-level." .. tostring(key) .. ".enabled=" .. tostring(resolved)) MTH_ModuleStateDebug("read " .. tostring(name) .. " from legacy-top-level." .. tostring(key) .. ".enabled=" .. tostring(resolved))
if type(MTH_SavedVariables.modules) ~= "table" then MTH_CharSavedVariables.moduleStates[resolvedName] = resolved
MTH_SavedVariables.modules = {} if type(MTH_CharSavedVariables.modules[resolvedName]) ~= "table" then
MTH_CharSavedVariables.modules[resolvedName] = {}
end end
if type(MTH_SavedVariables.modules[resolvedName]) ~= "table" then MTH_CharSavedVariables.modules[resolvedName].enabled = resolved
MTH_SavedVariables.modules[resolvedName] = MTH_SavedVariables[key]
end
if type(MTH_SavedVariables.moduleStates) ~= "table" then
MTH_SavedVariables.moduleStates = {}
end
MTH_SavedVariables.moduleStates[resolvedName] = resolved
return resolved return resolved
end end
end end
@@ -506,27 +539,22 @@ local function MTH_SetPersistedModuleEnabled(name, enabled)
if type(MTH_SavedVariables) ~= "table" then if type(MTH_SavedVariables) ~= "table" then
MTH_SavedVariables = {} MTH_SavedVariables = {}
end end
if type(MTH_SavedVariables.moduleStates) ~= "table" then
MTH_SavedVariables.moduleStates = {}
end
if type(MTH_SavedVariables.modules) ~= "table" then
MTH_SavedVariables.modules = {}
end
if type(MTH_SavedVariables.modules[name]) ~= "table" then
MTH_SavedVariables.modules[name] = {}
end
if type(MTH_CharSavedVariables) ~= "table" then if type(MTH_CharSavedVariables) ~= "table" then
MTH_CharSavedVariables = {} MTH_CharSavedVariables = {}
end end
if type(MTH_CharSavedVariables.moduleStates) ~= "table" then if type(MTH_CharSavedVariables.moduleStates) ~= "table" then
MTH_CharSavedVariables.moduleStates = {} MTH_CharSavedVariables.moduleStates = {}
end end
if type(MTH_CharSavedVariables.modules) ~= "table" then
MTH_CharSavedVariables.modules = {}
end
if type(MTH_CharSavedVariables.modules[name]) ~= "table" then
MTH_CharSavedVariables.modules[name] = {}
end
enabled = enabled and true or false enabled = enabled and true or false
MTH_SavedVariables.moduleStates[name] = enabled
MTH_SavedVariables.modules[name].enabled = enabled
MTH_SavedVariables[name] = MTH_SavedVariables.modules[name]
MTH_CharSavedVariables.moduleStates[name] = enabled MTH_CharSavedVariables.moduleStates[name] = enabled
MTH_CharSavedVariables.modules[name].enabled = enabled
MTH_ModuleStateDebug("write " .. tostring(name) .. " enabled=" .. tostring(enabled)) MTH_ModuleStateDebug("write " .. tostring(name) .. " enabled=" .. tostring(enabled))
end end
@@ -535,10 +563,10 @@ function MTH:InitEventRouter()
return self._eventRouter.frame return self._eventRouter.frame
end end
local frame = CreateFrame("Frame", "MTH_EventRouterFrame") local frame = CreateFrame("Frame", "MTH_EventRouter")
frame:SetScript("OnEvent", function(self, evt, a1, a2, a3, a4, a5, a6, a7, a8, a9) frame:SetScript("OnEvent", function()
if MTH and MTH.DispatchEvent then if MTH and MTH.DispatchEvent then
MTH:DispatchEvent(evt, a1, a2, a3, a4, a5, a6, a7, a8, a9) MTH:DispatchEvent(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
end end
end) end)
@@ -598,7 +626,7 @@ function MTH:_SetModuleEventSubscriptions(name, enabled)
end end
end end
function MTH:DispatchEvent(evt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) function MTH:DispatchEvent(evt, ea1, ea2, ea3, ea4, ea5, ea6, ea7, ea8, ea9)
for name, module in pairs(self.modules) do for name, module in pairs(self.modules) do
if module.enabled and module.onEvent then if module.enabled and module.onEvent then
local allow = true local allow = true
@@ -607,11 +635,10 @@ function MTH:DispatchEvent(evt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
end end
if allow then if allow then
local ok, err = pcall(function() local ok, err = pcall(function()
module:onEvent(evt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) module:onEvent(evt, ea1, ea2, ea3, ea4, ea5, ea6, ea7, ea8, ea9)
end) end)
if not ok then if not ok then
self:Print("Module '" .. name .. "' event error on '" .. tostring(evt) .. "': " .. tostring(err)) MTH:Print("Module '" .. name .. "' event error on '" .. tostring(evt) .. "': " .. tostring(err), "error")
MTH:Print("[MTH] Module event error (" .. name .. ", " .. tostring(evt) .. "): " .. tostring(err), "error")
end end
end end
end end
@@ -1265,24 +1292,22 @@ function MTH:EnsureModuleStateBootstrap()
return self._moduleStateBootstrapFrame return self._moduleStateBootstrapFrame
end end
local frame = CreateFrame("Frame", "MTH_ModuleStateBootstrapFrame") local frame = CreateFrame("Frame", "MTH_ModuleBootstrap")
if not frame then if not frame then
return nil return nil
end end
frame:RegisterEvent("VARIABLES_LOADED") frame:RegisterEvent("VARIABLES_LOADED")
frame:SetScript("OnEvent", function(self, eventName) frame:SetScript("OnEvent", function()
self = self or this if event ~= "VARIABLES_LOADED" then
eventName = eventName or event
if eventName ~= "VARIABLES_LOADED" then
return return
end end
if MTH and MTH.ApplyPersistedModuleStates then if MTH and MTH.ApplyPersistedModuleStates then
MTH:ApplyPersistedModuleStates("VARIABLES_LOADED") MTH:ApplyPersistedModuleStates("VARIABLES_LOADED")
end end
if not self then return end if not this then return end
self:UnregisterAllEvents() this:UnregisterAllEvents()
self:SetScript("OnEvent", nil) this:SetScript("OnEvent", nil)
end) end)
self._moduleStateBootstrapFrame = frame self._moduleStateBootstrapFrame = frame
@@ -1460,6 +1485,46 @@ function MTH:AnnounceLoadComplete()
"Addon synced. Your threat meter just sent a stress signal.", "Addon synced. Your threat meter just sent a stress signal.",
"Loaded cleanly. Reputation with healers currently in freefall.", "Loaded cleanly. Reputation with healers currently in freefall.",
"Mission start: hit things from far away and deny everything in chat.", "Mission start: hit things from far away and deny everything in chat.",
"Welcome back. Your pet missed you. Just kidding, it ran away.",
"MetaHunt loaded. You're still a Huntard, but now you're an organized one.",
"Aspects, traps, tracking... Don't worry, I'll handle the hard parts.",
"Oh good, another hunter who needs an addon to remember their own spells.",
"MetaHunt ready. Feign Death is not a personality trait.",
"Loaded successfully. No, I can't fix your DPS.",
"Welcome. Your pet's loyalty is higher than your raid attendance.",
"MetaHunt online. Please don't Multishot the sheep.",
"Greetings, hunter. I see you've chosen the 'easy' class and still need help.",
"All systems go. Try not to pull the entire dungeon this time.",
"MetaHunt activated. Reminder: Melee range is not your home.",
"Welcome back. Your ammo count is almost as low as your situational awareness.",
"Loaded. I'll manage your buttons since you clearly have too many.",
"MetaHunt ready. Aspect of the Cheetah in dungeons is a choice, not a strategy.",
"Oh look, a hunter that uses addons. There might be hope for you yet.",
"Welcome. No, you cannot tame that. Or that. Stop asking.",
"MetaHunt standing by. Unlike you during your last Feign Death.",
"Initialized. Fun fact: your pet has more utility than you do.",
"All buttons configured. Now if only I could configure your aim.",
"MetaHunt loaded. Growl is off, right? ...RIGHT?",
"MetaHunt loaded. Your Freezing Trap will still break early. That's on you.",
"Welcome. Aspect of the Pack is ready. Your group is not.",
"Initializing... unlike your pet, I actually come when called.",
"MetaHunt online. Remember: Hunter loot is everything. Everything.",
"Loaded. Concussive Shot the flag carrier, not the rogue vanishing.",
"Welcome back. Eyes of the Beast is not a valid boss strategy.",
"Ready. Your Aimed Shot takes longer to cast than this addon took to load.",
"MetaHunt armed. Scatter Shot into Freezing Trap — you'll get it right someday.",
"Online. Don't worry, I track your cooldowns since you clearly don't.",
"Welcome. Wing Clip and run. It's what you do best.",
"Loaded. Distracting Shot is for the boss, not for your ego.",
"MetaHunt ready. Your quiver is full but your skill bar is empty.",
"Initialized. Serpent Sting on every target doesn't make you a DoT class.",
"Welcome, hunter. Viper Sting the healer. No, the OTHER healer.",
"Ready to hunt. Mend Pet is not optional, it's a lifestyle.",
"MetaHunt loaded. Tranquilizing Shot the enrage, not the warrior.",
"Online. Rapid Fire is a cooldown, not your approach to pulling.",
"Welcome. You have 28 arrows left. Should've checked before the raid.",
"Loaded. Bestial Wrath does not make YOU immune. Learned that yet?",
"MetaHunt standing by. Dead zone? What dead zone? Oh... that dead zone.",
} }
local welcomeIndex = 1 local welcomeIndex = 1
@@ -1490,24 +1555,22 @@ function MTH:EnsureLoadCompleteAnnouncement()
return self._loadCompleteFrame return self._loadCompleteFrame
end end
local frame = CreateFrame("Frame", "MTH_LoadCompleteAnnounceFrame") local frame = CreateFrame("Frame", "MTH_LoadAnnounce")
if not frame then if not frame then
return nil return nil
end end
frame:RegisterEvent("PLAYER_ENTERING_WORLD") frame:RegisterEvent("PLAYER_ENTERING_WORLD")
frame:SetScript("OnEvent", function(self, eventName) frame:SetScript("OnEvent", function()
self = self or this if event ~= "PLAYER_ENTERING_WORLD" then
eventName = eventName or event
if eventName ~= "PLAYER_ENTERING_WORLD" then
return return
end end
if MTH and MTH.AnnounceLoadComplete then if MTH and MTH.AnnounceLoadComplete then
MTH:AnnounceLoadComplete() MTH:AnnounceLoadComplete()
end end
if not self then return end if not this then return end
self:UnregisterAllEvents() this:UnregisterAllEvents()
self:SetScript("OnEvent", nil) this:SetScript("OnEvent", nil)
end) end)
self._loadCompleteFrame = frame self._loadCompleteFrame = frame
+34 -4
View File
@@ -20,6 +20,7 @@ end
local MTH_PT_ApplyScan local MTH_PT_ApplyScan
local MTH_PT_AbilityHasPositiveRanks local MTH_PT_AbilityHasPositiveRanks
local MTH_PT_PromoteUnrankedKnownAliases local MTH_PT_PromoteUnrankedKnownAliases
local MTH_PT_BootstrapFrame = nil
local MTH_PT_VERBOSE_SCAN_LOGS = false local MTH_PT_VERBOSE_SCAN_LOGS = false
@@ -801,7 +802,7 @@ function MTH_PT_InitService()
if MTH_PetTrainingFrame then if MTH_PetTrainingFrame then
return return
end end
MTH_PetTrainingFrame = CreateFrame("Frame", "MTHPetTrainingScanFrame") MTH_PetTrainingFrame = CreateFrame("Frame", "MTH_PetTrainingScan")
MTH_PetTrainingFrame:RegisterEvent("PLAYER_ENTERING_WORLD") MTH_PetTrainingFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
MTH_PetTrainingFrame:RegisterEvent("LEARNED_SPELL_IN_TAB") MTH_PetTrainingFrame:RegisterEvent("LEARNED_SPELL_IN_TAB")
MTH_PetTrainingFrame:RegisterEvent("PET_TRAINING_SHOW") MTH_PetTrainingFrame:RegisterEvent("PET_TRAINING_SHOW")
@@ -812,9 +813,8 @@ function MTH_PT_InitService()
MTH_PetTrainingFrame:RegisterEvent("CRAFT_SHOW") MTH_PetTrainingFrame:RegisterEvent("CRAFT_SHOW")
MTH_PetTrainingFrame:RegisterEvent("CRAFT_UPDATE") MTH_PetTrainingFrame:RegisterEvent("CRAFT_UPDATE")
MTH_PetTrainingFrame:SetScript("OnEvent", MTH_PT_OnEvent) MTH_PetTrainingFrame:SetScript("OnEvent", MTH_PT_OnEvent)
MTH_PetTrainingFrame:SetScript("OnUpdate", function(_, elapsed) MTH_PetTrainingFrame:SetScript("OnUpdate", function()
elapsed = elapsed or arg1 MTH_PT_PetBookPollElapsed = (MTH_PT_PetBookPollElapsed or 0) + (arg1 or 0)
MTH_PT_PetBookPollElapsed = (MTH_PT_PetBookPollElapsed or 0) + (elapsed or 0)
if MTH_PT_PetBookPollElapsed < 0.20 then if MTH_PT_PetBookPollElapsed < 0.20 then
return return
end end
@@ -846,6 +846,35 @@ function MTH_PT_InitService()
end) end)
end end
function MTH_PT_InitBootstrap()
if MTH and MTH.ApplyClassGate and MTH:ApplyClassGate("trainscan-bootstrap") then
return
end
if MTH_PetTrainingFrame or MTH_PT_BootstrapFrame then
return
end
local frame = CreateFrame("Frame")
if not frame then
return
end
frame:RegisterEvent("PET_TRAINING_SHOW")
frame:RegisterEvent("CRAFT_SHOW")
frame:SetScript("OnEvent", function()
if event ~= "PET_TRAINING_SHOW" and event ~= "CRAFT_SHOW" then
return
end
MTH_PT_InitService()
if type(MTH_PT_OnEvent) == "function" then
MTH_PT_OnEvent(MTH_PetTrainingFrame, event)
end
this:UnregisterAllEvents()
this:SetScript("OnEvent", nil)
MTH_PT_BootstrapFrame = nil
end)
MTH_PT_BootstrapFrame = frame
end
function MTH_PT_ShutdownService(_reason) function MTH_PT_ShutdownService(_reason)
if not MTH_PetTrainingFrame then if not MTH_PetTrainingFrame then
return return
@@ -929,3 +958,4 @@ end
MTH_TR_InitService = MTH_PT_InitService MTH_TR_InitService = MTH_PT_InitService
MTH_TR_ShutdownService = MTH_PT_ShutdownService MTH_TR_ShutdownService = MTH_PT_ShutdownService
MTH_TR_InitBootstrap = MTH_PT_InitBootstrap
+85 -2
View File
@@ -7,6 +7,25 @@ local MTH_PS_LastScanAt = 0
local MTH_PS_VERBOSE_LOGS = false local MTH_PS_VERBOSE_LOGS = false
local MTH_PS_ForceScanUntil = 0 local MTH_PS_ForceScanUntil = 0
local MTH_PS_ForceScanBudget = 0 local MTH_PS_ForceScanBudget = 0
local MTH_PS_EventThrottle = {}
local MTH_PS_LastNoPetScanAt = 0
local function MTH_PS_IsPlayerDeadOrGhost()
if type(UnitIsDeadOrGhost) == "function" then
return UnitIsDeadOrGhost("player") and true or false
end
if type(UnitIsDead) == "function" then
return UnitIsDead("player") and true or false
end
return false
end
local function MTH_PS_HasLivePet()
if type(UnitExists) ~= "function" then
return false
end
return UnitExists("pet") and true or false
end
local function MTH_PS_ClearForceWindow() local function MTH_PS_ClearForceWindow()
MTH_PS_ForceScanUntil = 0 MTH_PS_ForceScanUntil = 0
@@ -26,9 +45,25 @@ end
local function MTH_PS_IsFollowupEventTrigger(trigger) local function MTH_PS_IsFollowupEventTrigger(trigger)
local t = tostring(trigger or "") local t = tostring(trigger or "")
return t == "event:UNIT_PET" return t == "event:UNIT_PET"
or t == "UNIT_PET"
or t == "event:PET_BAR_UPDATE" or t == "event:PET_BAR_UPDATE"
or t == "PET_BAR_UPDATE"
or t == "event:SPELLS_CHANGED" or t == "event:SPELLS_CHANGED"
or t == "SPELLS_CHANGED"
or t == "event:LEARNED_SPELL_IN_TAB" or t == "event:LEARNED_SPELL_IN_TAB"
or t == "LEARNED_SPELL_IN_TAB"
end
local function MTH_PS_ShouldHandleEvent(evt, minIntervalSeconds)
local now = tonumber(GetTime and GetTime() or time()) or 0
local key = tostring(evt or "")
local minInterval = tonumber(minIntervalSeconds) or 0
local last = tonumber(MTH_PS_EventThrottle[key] or 0) or 0
if minInterval > 0 and (now - last) < minInterval then
return false
end
MTH_PS_EventThrottle[key] = now
return true
end end
local function MTH_PS_IsPriorityTrigger(trigger) local function MTH_PS_IsPriorityTrigger(trigger)
@@ -190,6 +225,41 @@ function MTH_PSP_RequestScan(trigger, minIntervalSeconds)
local minInterval = tonumber(minIntervalSeconds) or 1 local minInterval = tonumber(minIntervalSeconds) or 1
local bypassThrottle = false local bypassThrottle = false
local bypassReason = "" local bypassReason = ""
local deadOrGhost = MTH_PS_IsPlayerDeadOrGhost()
local hasLivePet = MTH_PS_HasLivePet()
if deadOrGhost then
if triggerText == "PET_BAR_UPDATE" or triggerText == "event:PET_BAR_UPDATE"
or triggerText == "SPELLS_CHANGED" or triggerText == "event:SPELLS_CHANGED"
or triggerText == "LEARNED_SPELL_IN_TAB" or triggerText == "event:LEARNED_SPELL_IN_TAB"
then
MTH_PS_TraceTrigger(triggerText, false, "dead-skip")
return false
end
end
if not hasLivePet then
if MTH_PS_IsFollowupEventTrigger(triggerText) then
MTH_PS_TraceTrigger(triggerText, false, "no-pet-followup")
return false
end
if triggerText ~= "manual"
and triggerText ~= "PLAYER_ENTERING_WORLD"
and triggerText ~= "event:PLAYER_ENTERING_WORLD"
and triggerText ~= "UNIT_PET"
and triggerText ~= "event:UNIT_PET"
then
MTH_PS_TraceTrigger(triggerText, false, "no-pet")
return false
end
if (now - (tonumber(MTH_PS_LastNoPetScanAt) or 0)) < 5 then
MTH_PS_TraceTrigger(triggerText, false, "no-pet-throttled")
return false
end
MTH_PS_LastNoPetScanAt = now
else
MTH_PS_LastNoPetScanAt = 0
end
if MTH_PS_IsPriorityTrigger(triggerText) then if MTH_PS_IsPriorityTrigger(triggerText) then
bypassThrottle = true bypassThrottle = true
@@ -237,7 +307,19 @@ local function MTH_PS_OnEvent(_, evt, eventArg1)
end end
if evt == "PLAYER_ENTERING_WORLD" or evt == "UNIT_PET" or evt == "PET_BAR_UPDATE" or evt == "SPELLS_CHANGED" or evt == "LEARNED_SPELL_IN_TAB" then if evt == "PLAYER_ENTERING_WORLD" or evt == "UNIT_PET" or evt == "PET_BAR_UPDATE" or evt == "SPELLS_CHANGED" or evt == "LEARNED_SPELL_IN_TAB" then
MTH_PSP_RequestScan("event:" .. tostring(evt), 1) local minInterval = 1
if evt == "PET_BAR_UPDATE" then
minInterval = 4
elseif evt == "SPELLS_CHANGED" then
minInterval = 4
elseif evt == "LEARNED_SPELL_IN_TAB" then
minInterval = 1.5
elseif evt == "UNIT_PET" then
minInterval = 1
end
if MTH_PS_ShouldHandleEvent(evt, minInterval) then
MTH_PSP_RequestScan(evt, minInterval)
end
end end
end end
@@ -249,7 +331,7 @@ function MTH_PS_InitService()
return return
end end
MTH_PS_Frame = CreateFrame("Frame", "MTHPetSpellScanFrame") MTH_PS_Frame = CreateFrame("Frame", "MTH_PetSpellbookEvent")
MTH_PS_Frame:RegisterEvent("PLAYER_ENTERING_WORLD") MTH_PS_Frame:RegisterEvent("PLAYER_ENTERING_WORLD")
MTH_PS_Frame:RegisterEvent("UNIT_PET") MTH_PS_Frame:RegisterEvent("UNIT_PET")
MTH_PS_Frame:RegisterEvent("PET_BAR_UPDATE") MTH_PS_Frame:RegisterEvent("PET_BAR_UPDATE")
@@ -266,6 +348,7 @@ function MTH_PS_ShutdownService(_reason)
MTH_PS_Frame:SetScript("OnEvent", nil) MTH_PS_Frame:SetScript("OnEvent", nil)
MTH_PS_Frame = nil MTH_PS_Frame = nil
MTH_PS_LastScanAt = 0 MTH_PS_LastScanAt = 0
MTH_PS_LastNoPetScanAt = 0
MTH_PS_ClearForceWindow() MTH_PS_ClearForceWindow()
end end
File diff suppressed because it is too large Load Diff
+134 -18
View File
@@ -12,7 +12,7 @@ local function MTH_PT_GetGlobal(name)
return nil return nil
end end
local MTH_ItemLinkCacheTooltip = nil local MTH_ItemLinkCache = nil
local function MTH_GetQualityHexColor(quality) local function MTH_GetQualityHexColor(quality)
local q = tonumber(quality) local q = tonumber(quality)
@@ -34,14 +34,14 @@ function MTH_PrimeItemCache(itemId)
if not id or id <= 0 then return false end if not id or id <= 0 then return false end
if type(GetItemInfo) == "function" and GetItemInfo(id) then return true end if type(GetItemInfo) == "function" and GetItemInfo(id) then return true end
if not MTH_ItemLinkCacheTooltip then if not MTH_ItemLinkCache then
MTH_ItemLinkCacheTooltip = CreateFrame("GameTooltip", "MTH_ItemLinkCacheTooltip", UIParent, "GameTooltipTemplate") MTH_ItemLinkCache = CreateFrame("GameTooltip", "MTH_ItemLinkCache", UIParent, "GameTooltipTemplate")
if not MTH_ItemLinkCacheTooltip then return false end if not MTH_ItemLinkCache then return false end
MTH_ItemLinkCacheTooltip:SetOwner(UIParent, "ANCHOR_NONE") MTH_ItemLinkCache:SetOwner(UIParent, "ANCHOR_NONE")
end end
MTH_ItemLinkCacheTooltip:ClearLines() MTH_ItemLinkCache:ClearLines()
MTH_ItemLinkCacheTooltip:SetHyperlink("item:" .. tostring(id) .. ":0:0:0") MTH_ItemLinkCache:SetHyperlink("item:" .. tostring(id) .. ":0:0:0")
return type(GetItemInfo) == "function" and (GetItemInfo(id) ~= nil) or false return type(GetItemInfo) == "function" and (GetItemInfo(id) ~= nil) or false
end end
@@ -129,6 +129,49 @@ local function MTH_CommandOptions()
end end
end end
local function MTH_FormatAgeSeconds(seconds)
local value = tonumber(seconds) or 0
if value < 0 then value = 0 end
if value < 60 then
return tostring(math.floor(value)) .. "s"
end
if value < 3600 then
return tostring(math.floor(value / 60)) .. "m"
end
if value < 86400 then
return tostring(math.floor(value / 3600)) .. "h"
end
return tostring(math.floor(value / 86400)) .. "d"
end
local function MTH_CommandPeers()
if not (MTH and MTH.VersionCheck and type(MTH.VersionCheck.GetTrackedPeers) == "function") then
MTH:Print("Peer tracker is not available yet")
return
end
local peers = MTH.VersionCheck:GetTrackedPeers()
local count = table.getn(peers)
if count <= 0 then
MTH:Print("No MetaHunt broadcasters seen yet on LFT")
return
end
MTH:Print("MetaHunt broadcasters seen on LFT: " .. tostring(count))
local now = (type(time) == "function" and time()) or (type(GetTime) == "function" and math.floor(GetTime())) or 0
local maxRows = math.min(count, 20)
for i = 1, maxRows do
local peer = peers[i]
if type(peer) == "table" then
local age = MTH_FormatAgeSeconds((now or 0) - (tonumber(peer.lastSeenAt) or 0))
MTH:Print("- " .. tostring(peer.name or "?") .. " v" .. tostring(peer.versionText or "?") .. " (seen " .. tostring(age) .. " ago)")
end
end
if count > maxRows then
MTH:Print("... and " .. tostring(count - maxRows) .. " more")
end
end
local function MTH_CommandPetSpellScanFallback() local function MTH_CommandPetSpellScanFallback()
local getSpellName = (type(getglobal) == "function" and getglobal("GetSpellName")) or (_G and _G["GetSpellName"]) local getSpellName = (type(getglobal) == "function" and getglobal("GetSpellName")) or (_G and _G["GetSpellName"])
local getSpellTexture = (type(getglobal) == "function" and getglobal("GetSpellTexture")) or (_G and _G["GetSpellTexture"]) local getSpellTexture = (type(getglobal) == "function" and getglobal("GetSpellTexture")) or (_G and _G["GetSpellTexture"])
@@ -197,6 +240,34 @@ local function MTH_CommandPetSpellScanFallback()
end end
end end
local function MTH_CommandFoodData(limitText)
if type(FOM_PrintCollectedFoodData) ~= "function" then
MTH:Print("Food data command is not available yet")
return
end
local trimmed = string.gsub(tostring(limitText or ""), "^%s+", "")
trimmed = string.gsub(trimmed, "%s+$", "")
if string.lower(trimmed) == "purge" then
if type(FOM_PruneCollectedFoodData) ~= "function" then
MTH:Print("Food data purge is not available yet")
return
end
local removed = tonumber(FOM_PruneCollectedFoodData()) or 0
MTH:Print("Food data purge removed rows: " .. tostring(removed))
return
end
if trimmed == "" then
FOM_PrintCollectedFoodData(nil)
return
end
local limit = tonumber(trimmed)
if not limit then
MTH:Print("Usage: /mth food [limit|purge]")
return
end
FOM_PrintCollectedFoodData(limit)
end
if type(MTH_PS_ScanNow) ~= "function" then if type(MTH_PS_ScanNow) ~= "function" then
function MTH_PS_ScanNow(trigger) function MTH_PS_ScanNow(trigger)
local ok, count = MTH_CommandPetSpellScanFallback() local ok, count = MTH_CommandPetSpellScanFallback()
@@ -230,6 +301,46 @@ if type(MTH_CommandPetSpellScan) ~= "function" then
end end
end end
------------------------------------------------------
-- /mth diag — Runtime Diagnostics
------------------------------------------------------
function MTH_CommandDiag()
MTH:Print("======= MetaHunt Diagnostics =======", "debug")
-- 1. Lua version
local luaVer = _VERSION or "unknown"
MTH:Print("[DIAG] _VERSION = " .. tostring(luaVer), "debug")
MTH:Print("[DIAG] string.match = " .. tostring(type(string.match) == "function"), "debug")
MTH:Print("[DIAG] string.gfind = " .. tostring(type(string.gfind) == "function"), "debug")
-- 2. Active modules
local moduleCount = 0
local enabledModules = {}
if MTH.modules then
for name, mod in pairs(MTH.modules) do
moduleCount = moduleCount + 1
if mod.enabled then
table.insert(enabledModules, name)
end
end
end
MTH:Print("[DIAG] Registered modules: " .. tostring(moduleCount), "debug")
MTH:Print("[DIAG] Enabled: " .. table.concat(enabledModules, ", "), "debug")
-- 3. Event router state
local routerFrame = (MTH._eventRouter and MTH._eventRouter.frame) or nil
local routerEvents = (MTH._eventRouter and MTH._eventRouter.eventRefs) or {}
local eventCount = 0
for _ in pairs(routerEvents) do eventCount = eventCount + 1 end
MTH:Print("[DIAG] EventRouter frame: " .. tostring(routerFrame ~= nil) .. ", events: " .. tostring(eventCount), "debug")
-- 4. Debug frame initialized?
local dfInit = (MTH_DebugFrame and MTH_DebugFrame.initialized) and true or false
MTH:Print("[DIAG] DebugFrame initialized: " .. tostring(dfInit), "debug")
MTH:Print("======= End Diagnostics =======", "debug")
end
function SlashCmdList.MTH(msg, editbox) function SlashCmdList.MTH(msg, editbox)
if MTH and MTH.ApplyClassGate and MTH:ApplyClassGate("slash") then if MTH and MTH.ApplyClassGate and MTH:ApplyClassGate("slash") then
return return
@@ -239,33 +350,38 @@ function SlashCmdList.MTH(msg, editbox)
msg = string.gsub(tostring(msg), "^%s+", "") msg = string.gsub(tostring(msg), "^%s+", "")
msg = string.gsub(msg, "%s+$", "") msg = string.gsub(msg, "%s+$", "")
local lowerMsg = string.lower(msg) local lowerMsg = string.lower(msg)
local _, _, lowerCmd, lowerArg = string.find(lowerMsg, "^(%S+)%s*(.-)%s*$")
if msg == "" then if msg == "" then
MTH:Print("Available: /mth options, /mth book") MTH:Print("Available: /mth options, /mth book, /mth diag, /mth err")
elseif lowerMsg == "options" then elseif lowerMsg == "options" then
MTH_CommandOptions() MTH_CommandOptions()
elseif lowerMsg == "book" or lowerMsg == "hunterbook" then elseif lowerMsg == "book" or lowerMsg == "hunterbook" then
MTH_CommandBook() MTH_CommandBook()
elseif lowerMsg == "err" then elseif lowerMsg == "peers" or lowerMsg == "who" then
if MTH_DebugFrame and type(MTH_DebugFrame.Toggle) == "function" then MTH_CommandPeers()
elseif lowerMsg == "diag" then
MTH_CommandDiag()
elseif lowerMsg == "err" or lowerMsg == "errors" or lowerMsg == "debug" then
if MTH_DebugFrame and MTH_DebugFrame.Toggle then
MTH_DebugFrame:Toggle() MTH_DebugFrame:Toggle()
else else
MTH:Print("Debug frame is not available yet") MTH:Print("Debug frame is not available.")
end end
else else
MTH:Print("Unknown command: " .. tostring(msg)) MTH:Print("Unknown command: " .. tostring(msg))
MTH:Print("Available: /mth options, /mth book") MTH:Print("Available: /mth options, /mth book, /mth diag, /mth err")
end end
end end
-- Initialize on load -- Initialize on load
MTH:InitSavedVariables() MTH:InitSavedVariables()
if type(MTH_ST_InitService) == "function" then if type(MTH_ST_InitBootstrap) == "function" then
MTH_ST_InitService() MTH_ST_InitBootstrap()
end end
if type(MTH_TR_InitService) == "function" then if type(MTH_TR_InitBootstrap) == "function" then
MTH_TR_InitService() MTH_TR_InitBootstrap()
elseif type(MTH_PT_InitService) == "function" then elseif type(MTH_PT_InitBootstrap) == "function" then
MTH_PT_InitService() MTH_PT_InitBootstrap()
end end
if type(MTH_PS_InitService) == "function" then if type(MTH_PS_InitService) == "function" then
MTH_PS_InitService() MTH_PS_InitService()
+6 -6
View File
@@ -29,7 +29,7 @@ function MTH_DebugFrame:Initialize()
self.initialized = true self.initialized = true
-- Create main frame -- Create main frame
self.frame = CreateFrame("Frame", "MTH_DebugFrameWindow", UIParent) self.frame = CreateFrame("Frame", "MTH_DebugWindow", UIParent)
self.frame:SetWidth(800) self.frame:SetWidth(800)
self.frame:SetHeight(400) self.frame:SetHeight(400)
self.frame:SetPoint("CENTER", UIParent, "CENTER") self.frame:SetPoint("CENTER", UIParent, "CENTER")
@@ -51,13 +51,13 @@ function MTH_DebugFrame:Initialize()
if UISpecialFrames then if UISpecialFrames then
local already = false local already = false
for i = 1, table.getn(UISpecialFrames) do for i = 1, table.getn(UISpecialFrames) do
if UISpecialFrames[i] == "MTH_DebugFrameWindow" then if UISpecialFrames[i] == "MTH_DebugWindow" then
already = true already = true
break break
end end
end end
if not already then if not already then
table.insert(UISpecialFrames, "MTH_DebugFrameWindow") table.insert(UISpecialFrames, "MTH_DebugWindow")
end end
end end
@@ -91,7 +91,7 @@ function MTH_DebugFrame:Initialize()
copyButton:SetScript("OnClick", function() MTH_DebugFrame:SelectAllText() end) copyButton:SetScript("OnClick", function() MTH_DebugFrame:SelectAllText() end)
-- Scroll frame + text content with proper vertical scrollbar -- Scroll frame + text content with proper vertical scrollbar
self.scrollFrame = CreateFrame("ScrollFrame", "MTH_DebugScrollFrame", self.frame, "UIPanelScrollFrameTemplate") self.scrollFrame = CreateFrame("ScrollFrame", "MTH_DebugScroll", self.frame, "UIPanelScrollFrameTemplate")
self.scrollFrame:SetPoint("TOPLEFT", self.frame, "TOPLEFT", 15, -50) self.scrollFrame:SetPoint("TOPLEFT", self.frame, "TOPLEFT", 15, -50)
self.scrollFrame:SetPoint("BOTTOMRIGHT", self.frame, "BOTTOMRIGHT", -35, 45) self.scrollFrame:SetPoint("BOTTOMRIGHT", self.frame, "BOTTOMRIGHT", -35, 45)
@@ -366,8 +366,8 @@ MTH_DebugFrame.UninstallHooks = MTH_DF_UninstallHooks
-- Event listener for addon load -- Event listener for addon load
local eventFrame = CreateFrame("Frame") local eventFrame = CreateFrame("Frame")
eventFrame:RegisterEvent("ADDON_LOADED") eventFrame:RegisterEvent("ADDON_LOADED")
eventFrame:SetScript("OnEvent", function(self, event, addonName) eventFrame:SetScript("OnEvent", function()
if event == "ADDON_LOADED" and addonName == "MetaHunt" then if event == "ADDON_LOADED" and arg1 == "MetaHunt" then
if MTH and MTH.GetConfig then if MTH and MTH.GetConfig then
MTH_DF_SetGlobalCaptureEnabled(MTH:GetConfig("debug", "globalErrorCapture", false)) MTH_DF_SetGlobalCaptureEnabled(MTH:GetConfig("debug", "globalErrorCapture", false))
end end
+77 -35
View File
@@ -7,8 +7,8 @@ MTH_HUNTERBOOK_TABS.families = {
{ x = 10, width = 106, align = "LEFT" }, { x = 10, width = 106, align = "LEFT" },
{ x = 122, width = 52, align = "LEFT" }, { x = 122, width = 52, align = "LEFT" },
{ x = 176, width = 52, align = "LEFT" }, { x = 176, width = 52, align = "LEFT" },
{ x = 232, width = 292, align = "LEFT" }, { x = 232, width = 364, align = "LEFT" },
{ x = 460, width = 184, align = "LEFT" }, { x = 532, width = 112, align = "LEFT" },
}, },
} }
@@ -27,6 +27,11 @@ local function MTH_BOOKTAB_FamiliesTrim(value)
return text return text
end end
local function MTH_BOOKTAB_ShouldDisplayAllDiet(familyName)
local token = MTH_BOOKTAB_FamiliesSafeLower(MTH_BOOKTAB_FamiliesTrim(familyName))
return token == "bears" or token == "boars"
end
local function MTH_BOOKTAB_FindAbilityBundle(abilityName) local function MTH_BOOKTAB_FindAbilityBundle(abilityName)
if not (MTH_DS_PetSpells and type(MTH_DS_PetSpells.byAbility) == "table") then if not (MTH_DS_PetSpells and type(MTH_DS_PetSpells.byAbility) == "table") then
return nil return nil
@@ -95,25 +100,49 @@ function MTH_BOOKTAB_BuildFamiliesRows()
if token ~= "" and not seen[token] then if token ~= "" and not seen[token] then
seen[token] = true seen[token] = true
local spellRows = (type(bundle) == "table" and type(bundle.spells) == "table") and bundle.spells or {} local spellRows = (type(bundle) == "table" and type(bundle.spells) == "table") and bundle.spells or {}
local firstAnySpell = nil
local firstBeastSpell = nil local firstBeastSpell = nil
local rankMin = nil local beastRankMin = nil
local rankMax = nil local beastRankMax = nil
local rankMap = {} local beastRankMap = {}
local anyRankMin = nil
local anyRankMax = nil
local anyRankMap = {}
for s = 1, table.getn(spellRows) do for s = 1, table.getn(spellRows) do
local spell = spellRows[s] local spell = spellRows[s]
if type(spell) == "table" and MTH_BOOKTAB_FamiliesSafeLower(spell.learnMethod or "beast") ~= "trainer" then if type(spell) == "table" then
if not firstBeastSpell then if not firstAnySpell then
firstBeastSpell = spell firstAnySpell = spell
end end
local rank = tonumber(spell.rankNumber) local rank = tonumber(spell.rankNumber)
if rank and rank > 0 then if rank and rank > 0 then
rankMap[rank] = true anyRankMap[rank] = true
if not rankMin or rank < rankMin then rankMin = rank end if not anyRankMin or rank < anyRankMin then anyRankMin = rank end
if not rankMax or rank > rankMax then rankMax = rank end if not anyRankMax or rank > anyRankMax then anyRankMax = rank end
end
if MTH_BOOKTAB_FamiliesSafeLower(spell.learnMethod or "beast") ~= "trainer" then
if not firstBeastSpell then
firstBeastSpell = spell
end
if rank and rank > 0 then
beastRankMap[rank] = true
if not beastRankMin or rank < beastRankMin then beastRankMin = rank end
if not beastRankMax or rank > beastRankMax then beastRankMax = rank end
end
end end
end end
end end
local displaySpell = firstBeastSpell or firstAnySpell
local rankMap = beastRankMap
local rankMin = beastRankMin
local rankMax = beastRankMax
if not firstBeastSpell then
rankMap = anyRankMap
rankMin = anyRankMin
rankMax = anyRankMax
end
local rankCount = 0 local rankCount = 0
for _ in pairs(rankMap) do for _ in pairs(rankMap) do
rankCount = rankCount + 1 rankCount = rankCount + 1
@@ -123,8 +152,8 @@ function MTH_BOOKTAB_BuildFamiliesRows()
name = canonicalMap[token] or canonical, name = canonicalMap[token] or canonical,
token = token, token = token,
isUnique = (abilityCounts[token] or 0) == 1, isUnique = (abilityCounts[token] or 0) == 1,
icon = firstBeastSpell and firstBeastSpell.icon or nil, icon = displaySpell and displaySpell.icon or nil,
description = firstBeastSpell and firstBeastSpell.description or "", description = displaySpell and displaySpell.description or "",
rankMin = rankMin, rankMin = rankMin,
rankMax = rankMax, rankMax = rankMax,
rankCount = rankCount, rankCount = rankCount,
@@ -141,17 +170,23 @@ function MTH_BOOKTAB_BuildFamiliesRows()
return MTH_BOOKTAB_FamiliesSafeLower(a.name) < MTH_BOOKTAB_FamiliesSafeLower(b.name) return MTH_BOOKTAB_FamiliesSafeLower(a.name) < MTH_BOOKTAB_FamiliesSafeLower(b.name)
end) end)
local dietItems = {} local dietText = ""
if type(familyRow.food) == "table" then if MTH_BOOKTAB_ShouldDisplayAllDiet(familyName) then
for i = 1, table.getn(familyRow.food) do dietText = "ALL"
local food = MTH_BOOKTAB_FamiliesTrim(familyRow.food[i]) else
if food ~= "" then local dietItems = {}
table.insert(dietItems, string.upper(string.sub(food, 1, 1)) .. string.sub(food, 2)) if type(familyRow.food) == "table" then
for i = 1, table.getn(familyRow.food) do
local food = MTH_BOOKTAB_FamiliesTrim(familyRow.food[i])
if food ~= "" then
table.insert(dietItems, string.upper(string.sub(food, 1, 1)) .. string.sub(food, 2))
end
end end
table.sort(dietItems, function(a, b)
return MTH_BOOKTAB_FamiliesSafeLower(a) < MTH_BOOKTAB_FamiliesSafeLower(b)
end)
end end
table.sort(dietItems, function(a, b) dietText = table.concat(dietItems, ", ")
return MTH_BOOKTAB_FamiliesSafeLower(a) < MTH_BOOKTAB_FamiliesSafeLower(b)
end)
end end
table.insert(results, { table.insert(results, {
@@ -159,7 +194,7 @@ function MTH_BOOKTAB_BuildFamiliesRows()
named = tonumber(familyRow.named) or 0, named = tonumber(familyRow.named) or 0,
coords = tonumber(familyRow.coords) or 0, coords = tonumber(familyRow.coords) or 0,
abilities = abilities, abilities = abilities,
dietText = table.concat(dietItems, ", "), dietText = dietText,
}) })
end end
end end
@@ -238,7 +273,7 @@ function MTH_BOOKTAB_EnsureFamiliesUI()
ui.headerAbilities:SetText("Abilities") ui.headerAbilities:SetText("Abilities")
ui.headerDiet = ui.frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall") ui.headerDiet = ui.frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
ui.headerDiet:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 460, -2) ui.headerDiet:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 532, -2)
ui.headerDiet:SetTextColor(1.00, 0.82, 0.00) ui.headerDiet:SetTextColor(1.00, 0.82, 0.00)
ui.headerDiet:SetText("Diet") ui.headerDiet:SetText("Diet")
@@ -270,8 +305,8 @@ function MTH_BOOKTAB_EnsureFamiliesUI()
row.coords:SetJustifyH("LEFT") row.coords:SetJustifyH("LEFT")
row.diet = row:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall") row.diet = row:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
row.diet:SetPoint("LEFT", row, "LEFT", 460, 0) row.diet:SetPoint("LEFT", row, "LEFT", 532, 0)
row.diet:SetWidth(184) row.diet:SetWidth(112)
row.diet:SetJustifyH("LEFT") row.diet:SetJustifyH("LEFT")
row.abilityButtons = {} row.abilityButtons = {}
@@ -363,6 +398,7 @@ function MTH_BOOKTAB_RenderFamiliesList()
rowFrame.diet:SetText(tostring(row.dietText or "-")) rowFrame.diet:SetText(tostring(row.dietText or "-"))
local offsetX = 232 local offsetX = 232
local abilityMaxRight = 526
for b = 1, table.getn(rowFrame.abilityButtons) do for b = 1, table.getn(rowFrame.abilityButtons) do
local button = rowFrame.abilityButtons[b] local button = rowFrame.abilityButtons[b]
local ability = row.abilities and row.abilities[b] or nil local ability = row.abilities and row.abilities[b] or nil
@@ -375,17 +411,23 @@ function MTH_BOOKTAB_RenderFamiliesList()
button.text:SetText(nameText) button.text:SetText(nameText)
local textW = button.text:GetStringWidth() or 40 local textW = button.text:GetStringWidth() or 40
if textW < 24 then textW = 24 end if textW < 24 then textW = 24 end
button:SetWidth(14 + textW) local buttonWidth = 14 + textW
button:ClearAllPoints() if (offsetX + buttonWidth) > abilityMaxRight then
button:SetPoint("LEFT", rowFrame, "LEFT", offsetX, 0) button.entry = nil
local iconPath = ability.icon and MTH_BOOK_ResolveIconPath and MTH_BOOK_ResolveIconPath(ability.icon) or nil button:Hide()
if iconPath then
button.icon:SetTexture(iconPath)
else else
button.icon:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark") button:SetWidth(buttonWidth)
button:ClearAllPoints()
button:SetPoint("LEFT", rowFrame, "LEFT", offsetX, 0)
local iconPath = ability.icon and MTH_BOOK_ResolveIconPath and MTH_BOOK_ResolveIconPath(ability.icon) or nil
if iconPath then
button.icon:SetTexture(iconPath)
else
button.icon:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark")
end
button:Show()
offsetX = offsetX + button:GetWidth() + 6
end end
button:Show()
offsetX = offsetX + button:GetWidth() + 6
else else
button.entry = nil button.entry = nil
button:Hide() button:Hide()
+1 -1
View File
@@ -140,7 +140,7 @@ function MTH_BOOK_GetResistanceShortName(nameText)
if string.find(lowerName, "arcane", 1, true) then return "AR" end if string.find(lowerName, "arcane", 1, true) then return "AR" end
if string.find(lowerName, "nature", 1, true) then return "NR" end if string.find(lowerName, "nature", 1, true) then return "NR" end
if string.find(lowerName, "fire", 1, true) then return "FR" end if string.find(lowerName, "fire", 1, true) then return "FR" end
if string.find(lowerName, "frost", 1, true) then return "FR" end if string.find(lowerName, "frost", 1, true) then return "FrR" end
if string.find(lowerName, "shadow", 1, true) then return "SR" end if string.find(lowerName, "shadow", 1, true) then return "SR" end
return tostring(nameText or "-") return tostring(nameText or "-")
end end
+100 -38
View File
@@ -55,7 +55,7 @@ local function MTH_BOOK_FamiliesTrace(message)
end end
local MTH_BOOK_STATE = { local MTH_BOOK_STATE = {
mode = "stable", mode = "pets",
search = "", search = "",
quick = "all", quick = "all",
minLevel = nil, minLevel = nil,
@@ -1002,9 +1002,9 @@ end
local function MTH_BOOK_ParseProjectileDPSFromText(text) local function MTH_BOOK_ParseProjectileDPSFromText(text)
if type(text) ~= "string" or text == "" then return nil end if type(text) ~= "string" or text == "" then return nil end
local lowered = string.lower(text) local lowered = string.lower(text)
local raw = string.match(lowered, "adds%s+([%d]+[%.,]?[%d]*)%s+damage%s+per%s+seconds?") local _, _, raw = string.find(lowered, "adds%s+([%d]+[%.,]?[%d]*)%s+damage%s+per%s+seconds?")
if not raw then if not raw then
raw = string.match(lowered, "([%d]+[%.,]?[%d]*)%s+damage%s+per%s+seconds?") _, _, raw = string.find(lowered, "([%d]+[%.,]?[%d]*)%s+damage%s+per%s+seconds?")
end end
if not raw then return nil end if not raw then return nil end
local normalized = string.gsub(raw, ",", ".") local normalized = string.gsub(raw, ",", ".")
@@ -1537,13 +1537,75 @@ local function MTH_BOOK_BuildResults()
if MTH_BOOK_STATE.mode == "pethistory" then if MTH_BOOK_STATE.mode == "pethistory" then
local store = MTH_BOOK_GetPetDatastore() local store = MTH_BOOK_GetPetDatastore()
if type(store) ~= "table" or type(store.historyById) ~= "table" then return results end if type(store) ~= "table" or type(store.historyById) ~= "table" then return results end
local cached = {}
for petId, row in pairs(store.historyById) do for petId, row in pairs(store.historyById) do
if type(row) == "table" then if type(row) == "table" then
table.insert(results, petId) local idText = tostring(petId)
table.insert(cached, {
id = petId,
idText = idText,
name = MTH_BOOK_SafeLower(row.name),
family = MTH_BOOK_SafeLower(row.family),
level = tonumber(row.level) or 0,
abandonedAt = tonumber(row.abandonedAt) or 0,
reason = MTH_BOOK_SafeLower(tostring(row.abandonReason or "")),
})
end end
end end
table.sort(results, MTH_BOOK_PetHistorySort)
MTH_BOOK_ApplyActiveSort(results) local function defaultHistoryCompare(a, b)
if a.abandonedAt ~= b.abandonedAt then
return a.abandonedAt > b.abandonedAt
end
if a.name ~= b.name then
return a.name < b.name
end
return a.idText < b.idText
end
local state = MTH_BOOK_GetSortState()
if state and state.col then
table.sort(cached, function(a, b)
local ka = nil
local kb = nil
if state.col == 1 then
ka = a.idText
kb = b.idText
elseif state.col == 2 then
ka = a.name
kb = b.name
elseif state.col == 3 then
ka = a.family
kb = b.family
elseif state.col == 4 then
ka = a.level
kb = b.level
elseif state.col == 5 then
ka = a.abandonedAt
kb = b.abandonedAt
elseif state.col == 6 then
ka = a.reason
kb = b.reason
end
if ka ~= kb then
if ka == nil then return not state.asc end
if kb == nil then return state.asc end
if state.asc then
return ka < kb
end
return ka > kb
end
return defaultHistoryCompare(a, b)
end)
else
table.sort(cached, defaultHistoryCompare)
end
for i = 1, table.getn(cached) do
table.insert(results, cached[i].id)
end
return results return results
end end
@@ -4379,23 +4441,14 @@ local function MTH_BOOK_LayoutSectionTabs()
local sectionPetHistory = getglobal("MTH_BOOK_SectionPetHistory") local sectionPetHistory = getglobal("MTH_BOOK_SectionPetHistory")
if not (tabBar and sectionPets and sectionFamilies and sectionPetAbilities and sectionItems and sectionNPCs and sectionProjectiles and sectionAmmoBags) then return end if not (tabBar and sectionPets and sectionFamilies and sectionPetAbilities and sectionItems and sectionNPCs and sectionProjectiles and sectionAmmoBags) then return end
if sectionStable then sectionPets:ClearAllPoints()
sectionStable:ClearAllPoints() sectionPets:SetPoint("TOPLEFT", tabBar, "TOPLEFT", 0, 0)
sectionStable:SetPoint("TOPLEFT", tabBar, "TOPLEFT", 0, 0)
end
sectionPetAbilities:ClearAllPoints() sectionPetAbilities:ClearAllPoints()
if sectionStable then sectionPetAbilities:SetPoint("LEFT", sectionPets, "RIGHT", 2, 0)
sectionPetAbilities:SetPoint("LEFT", sectionStable, "RIGHT", 2, 0)
else
sectionPetAbilities:SetPoint("TOPLEFT", tabBar, "TOPLEFT", 0, 0)
end
sectionPets:ClearAllPoints()
sectionPets:SetPoint("LEFT", sectionPetAbilities, "RIGHT", 2, 0)
sectionFamilies:ClearAllPoints() sectionFamilies:ClearAllPoints()
sectionFamilies:SetPoint("LEFT", sectionPets, "RIGHT", 2, 0) sectionFamilies:SetPoint("LEFT", sectionPetAbilities, "RIGHT", 2, 0)
sectionNPCs:ClearAllPoints() sectionNPCs:ClearAllPoints()
sectionNPCs:SetPoint("LEFT", sectionFamilies, "RIGHT", 2, 0) sectionNPCs:SetPoint("LEFT", sectionFamilies, "RIGHT", 2, 0)
@@ -4409,9 +4462,18 @@ local function MTH_BOOK_LayoutSectionTabs()
sectionAmmoBags:ClearAllPoints() sectionAmmoBags:ClearAllPoints()
sectionAmmoBags:SetPoint("LEFT", sectionProjectiles, "RIGHT", 2, 0) sectionAmmoBags:SetPoint("LEFT", sectionProjectiles, "RIGHT", 2, 0)
if sectionStable then
sectionStable:ClearAllPoints()
sectionStable:SetPoint("LEFT", sectionAmmoBags, "RIGHT", 2, 0)
end
if sectionPetHistory then if sectionPetHistory then
sectionPetHistory:ClearAllPoints() sectionPetHistory:ClearAllPoints()
sectionPetHistory:SetPoint("LEFT", sectionAmmoBags, "RIGHT", 2, 0) if sectionStable then
sectionPetHistory:SetPoint("LEFT", sectionStable, "RIGHT", 2, 0)
else
sectionPetHistory:SetPoint("LEFT", sectionAmmoBags, "RIGHT", 2, 0)
end
end end
end end
@@ -5004,19 +5066,19 @@ local function MTH_BOOK_WireUI(frame)
listSlider:SetScript("OnMouseDown", function() listSlider:SetScript("OnMouseDown", function()
MTH_BOOK_STATE.sliderDragging = true MTH_BOOK_STATE.sliderDragging = true
MTH_BOOK_SetSliderFromCursor(this) MTH_BOOK_SetSliderFromCursor(this)
this:SetScript("OnUpdate", function()
if IsMouseButtonDown and not IsMouseButtonDown("LeftButton") then
MTH_BOOK_STATE.sliderDragging = false
this:SetScript("OnUpdate", nil)
else
MTH_BOOK_SetSliderFromCursor(this)
end
end)
end) end)
listSlider:SetScript("OnMouseUp", function() listSlider:SetScript("OnMouseUp", function()
MTH_BOOK_SetSliderFromCursor(this) MTH_BOOK_SetSliderFromCursor(this)
MTH_BOOK_STATE.sliderDragging = false MTH_BOOK_STATE.sliderDragging = false
end) this:SetScript("OnUpdate", nil)
listSlider:SetScript("OnUpdate", function()
if MTH_BOOK_STATE.sliderDragging then
if IsMouseButtonDown and not IsMouseButtonDown("LeftButton") then
MTH_BOOK_STATE.sliderDragging = false
else
MTH_BOOK_SetSliderFromCursor(this)
end
end
end) end)
listSlider:SetScript("OnValueChanged", function() listSlider:SetScript("OnValueChanged", function()
local value = this:GetValue() local value = this:GetValue()
@@ -5119,19 +5181,19 @@ local function MTH_BOOK_WireUI(frame)
sliderBackdrop:SetScript("OnMouseDown", function() sliderBackdrop:SetScript("OnMouseDown", function()
MTH_BOOK_STATE.sliderDragging = true MTH_BOOK_STATE.sliderDragging = true
MTH_BOOK_SetSliderFromCursor(listSlider) MTH_BOOK_SetSliderFromCursor(listSlider)
listSlider:SetScript("OnUpdate", function()
if IsMouseButtonDown and not IsMouseButtonDown("LeftButton") then
MTH_BOOK_STATE.sliderDragging = false
this:SetScript("OnUpdate", nil)
else
MTH_BOOK_SetSliderFromCursor(listSlider)
end
end)
end) end)
sliderBackdrop:SetScript("OnMouseUp", function() sliderBackdrop:SetScript("OnMouseUp", function()
MTH_BOOK_SetSliderFromCursor(listSlider) MTH_BOOK_SetSliderFromCursor(listSlider)
MTH_BOOK_STATE.sliderDragging = false MTH_BOOK_STATE.sliderDragging = false
end) listSlider:SetScript("OnUpdate", nil)
sliderBackdrop:SetScript("OnUpdate", function()
if MTH_BOOK_STATE.sliderDragging then
if IsMouseButtonDown and not IsMouseButtonDown("LeftButton") then
MTH_BOOK_STATE.sliderDragging = false
else
MTH_BOOK_SetSliderFromCursor(listSlider)
end
end
end) end)
end end
end end
+3 -1
View File
@@ -9,7 +9,6 @@ local MTH_LOCALE_ALIASES = {
enGB = "enUS", enGB = "enUS",
esMX = "esES", esMX = "esES",
zhTW = "zhCN", zhTW = "zhCN",
frFR = "enUS",
} }
local MTH_SUPPORTED_LOCALES = { local MTH_SUPPORTED_LOCALES = {
@@ -198,6 +197,9 @@ local MTH_SPELL_ID_BY_TOKEN = {
["Counterattack"] = 19306, ["Counterattack"] = 19306,
["Clever Traps"] = 19239, ["Clever Traps"] = 19239,
["Deterrence"] = 19263, ["Deterrence"] = 19263,
["Entrapment"] = 19184,
["Entrapment (Rank 2)"] = 19387,
["Entrapment (Rank 3)"] = 19388,
["Explosive Trap"] = 13813, ["Explosive Trap"] = 13813,
["Explosive Trap Effect"] = 13812, ["Explosive Trap Effect"] = 13812,
["Feed Pet"] = 6991, ["Feed Pet"] = 6991,
+94 -42
View File
@@ -2,7 +2,7 @@ MTH_Map = {
enabled = true, enabled = true,
showWorld = true, showWorld = true,
showMinimap = true, showMinimap = true,
activeSource = "beasts", activeSource = "focus",
providers = {}, providers = {},
nodesByZone = {}, nodesByZone = {},
worldPins = {}, worldPins = {},
@@ -21,6 +21,10 @@ MTH_Map = {
lastWorldReason = "n/a", lastWorldReason = "n/a",
lastMiniReason = "n/a", lastMiniReason = "n/a",
nodeRevision = 0, nodeRevision = 0,
minimapForceRefreshInterval = 1.0,
verboseMiniReasons = false,
minimapTickActive = 0.20,
minimapTickIdle = 0.75,
} }
local MTH_MAP_MINIMAP_ZOOM = { local MTH_MAP_MINIMAP_ZOOM = {
@@ -468,7 +472,18 @@ local function MTH_Map_ClearPendingZoneOpen()
MTH_Map.pendingZoneOpenNextAttemptAt = 0 MTH_Map.pendingZoneOpenNextAttemptAt = 0
end end
function MTH_Map:EnsureInitialized()
if self.controller then
return true
end
self:Init()
return self.controller ~= nil
end
function MTH_Map:SetSource(key) function MTH_Map:SetSource(key)
if not self:EnsureInitialized() then
return false
end
if not self.providers[key] then if not self.providers[key] then
return false return false
end end
@@ -672,6 +687,9 @@ function MTH_Map:SetEnabled(enabled)
if not self.enabled then if not self.enabled then
self:HideAllPins() self:HideAllPins()
else else
if not self:EnsureInitialized() then
return
end
self:UpdateWorldMap() self:UpdateWorldMap()
self:UpdateMinimap() self:UpdateMinimap()
end end
@@ -682,6 +700,9 @@ function MTH_Map:SetWorldEnabled(enabled)
if not self.showWorld then if not self.showWorld then
self:HideWorldPins() self:HideWorldPins()
else else
if not self:EnsureInitialized() then
return
end
self:UpdateWorldMap() self:UpdateWorldMap()
end end
end end
@@ -691,6 +712,9 @@ function MTH_Map:SetMinimapEnabled(enabled)
if not self.showMinimap then if not self.showMinimap then
self:HideMinimapPins() self:HideMinimapPins()
else else
if not self:EnsureInitialized() then
return
end
self:UpdateMinimap() self:UpdateMinimap()
end end
end end
@@ -952,22 +976,21 @@ function MTH_Map:UpdateMinimap()
end end
local mapId = self:GetCurrentMapID() local mapId = self:GetCurrentMapID()
if not mapId or not self.nodesByZone[mapId] then local nodes = mapId and self.nodesByZone[mapId] or nil
if not mapId or not nodes then
self.lastMiniReason = "no-mapid-or-nodes" self.lastMiniReason = "no-mapid-or-nodes"
self._lastMiniState = nil self._lastMiniState = nil
self:HideMinimapPins() self:HideMinimapPins()
return return
end end
if table.getn(nodes) <= 0 then
local minimapSizes = MTH_DS_MinimapSizes or (pfDB and pfDB["minimap"]) self.lastMiniReason = "no-nodes-in-zone"
local mapSize = minimapSizes and minimapSizes[mapId]
if not mapSize then
self.lastMiniReason = "missing-minimap-size"
self._lastMiniState = nil self._lastMiniState = nil
self:HideMinimapPins() self:HideMinimapPins()
return return
end end
local now = GetTime() or 0
local xPlayer, yPlayer = GetPlayerMapPosition("player") local xPlayer, yPlayer = GetPlayerMapPosition("player")
if not xPlayer or not yPlayer or (xPlayer == 0 and yPlayer == 0) then if not xPlayer or not yPlayer or (xPlayer == 0 and yPlayer == 0) then
self.lastMiniReason = "player-position-unavailable" self.lastMiniReason = "player-position-unavailable"
@@ -980,10 +1003,33 @@ function MTH_Map:UpdateMinimap()
yPlayer = yPlayer * 100 yPlayer = yPlayer * 100
local zoom = Minimap:GetZoom() local zoom = Minimap:GetZoom()
local miniState = self._lastMiniState
if miniState
and miniState.mapId == mapId
and miniState.zoom == zoom
and miniState.nodeRevision == (self.nodeRevision or 0)
then
local dx = math.abs((xPlayer or 0) - (miniState.xPlayer or 0))
local dy = math.abs((yPlayer or 0) - (miniState.yPlayer or 0))
if dx < 0.05 and dy < 0.05 and now < (miniState.nextForceAt or 0) then
self.lastMiniReason = self.verboseMiniReasons and "throttled-small-move" or "throttle"
return
end
end
local minimapSizes = MTH_DS_MinimapSizes or (pfDB and pfDB["minimap"])
local mapSize = minimapSizes and minimapSizes[mapId]
if not mapSize then
self.lastMiniReason = self.verboseMiniReasons and "missing-minimap-size" or "missing-size"
self._lastMiniState = nil
self:HideMinimapPins()
return
end
local indoor = MTH_Map_MinimapIndoorState() local indoor = MTH_Map_MinimapIndoorState()
local zoomSet = MTH_MAP_MINIMAP_ZOOM[indoor] local zoomSet = MTH_MAP_MINIMAP_ZOOM[indoor]
if not zoomSet then if not zoomSet then
self.lastMiniReason = "missing-zoomset" self.lastMiniReason = self.verboseMiniReasons and "missing-zoomset" or "missing-zoomset"
self._lastMiniState = nil self._lastMiniState = nil
self:HideMinimapPins() self:HideMinimapPins()
return return
@@ -991,7 +1037,7 @@ function MTH_Map:UpdateMinimap()
local mapZoom = zoomSet[zoom] local mapZoom = zoomSet[zoom]
if not mapZoom then if not mapZoom then
self.lastMiniReason = "missing-mapzoom" self.lastMiniReason = self.verboseMiniReasons and "missing-mapzoom" or "missing-zoom"
self._lastMiniState = nil self._lastMiniState = nil
self:HideMinimapPins() self:HideMinimapPins()
return return
@@ -1000,33 +1046,16 @@ function MTH_Map:UpdateMinimap()
local mapWidth = mapSize[1] local mapWidth = mapSize[1]
local mapHeight = mapSize[2] local mapHeight = mapSize[2]
if not mapWidth or not mapHeight or mapWidth == 0 or mapHeight == 0 then if not mapWidth or not mapHeight or mapWidth == 0 or mapHeight == 0 then
self.lastMiniReason = "invalid-map-size" self.lastMiniReason = self.verboseMiniReasons and "invalid-map-size" or "invalid-size"
self._lastMiniState = nil self._lastMiniState = nil
self:HideMinimapPins() self:HideMinimapPins()
return return
end end
local miniState = self._lastMiniState
if miniState
and miniState.mapId == mapId
and miniState.zoom == zoom
and miniState.indoor == indoor
and miniState.nodeRevision == (self.nodeRevision or 0)
then
local dx = math.abs((xPlayer or 0) - (miniState.xPlayer or 0))
local dy = math.abs((yPlayer or 0) - (miniState.yPlayer or 0))
if dx < 0.05 and dy < 0.05 then
self.lastMiniReason = "throttled-small-move"
return
end
end
local xScale = mapZoom / mapWidth local xScale = mapZoom / mapWidth
local yScale = mapZoom / mapHeight local yScale = mapZoom / mapHeight
local xDraw = Minimap:GetWidth() / xScale / 100 local xDraw = Minimap:GetWidth() / xScale / 100
local yDraw = Minimap:GetHeight() / yScale / 100 local yDraw = Minimap:GetHeight() / yScale / 100
local nodes = self.nodesByZone[mapId]
local shown = 0 local shown = 0
for i = 1, table.getn(nodes) do for i = 1, table.getn(nodes) do
@@ -1057,16 +1086,21 @@ function MTH_Map:UpdateMinimap()
if self.minimapPins[i] then self.minimapPins[i]:Hide() end if self.minimapPins[i] then self.minimapPins[i]:Hide() end
end end
self._lastMiniState = { local lastState = self._lastMiniState or {}
mapId = mapId, lastState.mapId = mapId
zoom = zoom, lastState.zoom = zoom
indoor = indoor, lastState.indoor = indoor
xPlayer = xPlayer, lastState.xPlayer = xPlayer
yPlayer = yPlayer, lastState.yPlayer = yPlayer
nodeRevision = self.nodeRevision or 0, lastState.nodeRevision = self.nodeRevision or 0
} lastState.nextForceAt = now + (tonumber(self.minimapForceRefreshInterval) or 1.0)
self._lastMiniState = lastState
self.lastMiniReason = "ok(map=" .. tostring(mapId) .. ",shown=" .. tostring(shown) .. ")" if self.verboseMiniReasons then
self.lastMiniReason = "ok(map=" .. tostring(mapId) .. ",shown=" .. tostring(shown) .. ")"
else
self.lastMiniReason = "ok"
end
end end
function MTH_Map:RegisterDefaultProviders() function MTH_Map:RegisterDefaultProviders()
@@ -1202,12 +1236,15 @@ function MTH_Map:RegisterDefaultProviders()
end end
function MTH_Map:Init() function MTH_Map:Init()
if self.controller then
return
end
self:BuildZoneLookup() self:BuildZoneLookup()
self:RegisterDefaultProviders() self:RegisterDefaultProviders()
self:RebuildNodes() self.nodesByZone = self.nodesByZone or {}
if not self.controller then if not self.controller then
self.controller = CreateFrame("Frame", "MTHMapController", UIParent) self.controller = CreateFrame("Frame", "MTH_MapController", UIParent)
self.controller:RegisterEvent("PLAYER_ENTERING_WORLD") self.controller:RegisterEvent("PLAYER_ENTERING_WORLD")
self.controller:RegisterEvent("ZONE_CHANGED") self.controller:RegisterEvent("ZONE_CHANGED")
self.controller:RegisterEvent("ZONE_CHANGED_NEW_AREA") self.controller:RegisterEvent("ZONE_CHANGED_NEW_AREA")
@@ -1230,7 +1267,6 @@ function MTH_Map:Init()
if not frame then return end if not frame then return end
local now = GetTime() or 0 local now = GetTime() or 0
if (frame._mthTick or 0) > now then return end if (frame._mthTick or 0) > now then return end
frame._mthTick = now + 0.12
if MTH_Map.pendingZoneOpenId and MTH_Map.pendingZoneOpenAttempts and MTH_Map.pendingZoneOpenAttempts > 0 then if MTH_Map.pendingZoneOpenId and MTH_Map.pendingZoneOpenAttempts and MTH_Map.pendingZoneOpenAttempts > 0 then
if (MTH_Map.pendingZoneOpenNextAttemptAt or 0) <= now then if (MTH_Map.pendingZoneOpenNextAttemptAt or 0) <= now then
@@ -1259,12 +1295,28 @@ function MTH_Map:Init()
end end
if MTH_Map.enabled and MTH_Map.showMinimap then if MTH_Map.enabled and MTH_Map.showMinimap then
MTH_Map:UpdateMinimap() local mapId = MTH_Map:GetCurrentMapID()
if not mapId and (frame._mthMapRecoverAt or 0) <= now then
frame._mthMapRecoverAt = now + 2.0
if SetMapToCurrentZone and (not WorldMapFrame or not WorldMapFrame:IsShown()) then
SetMapToCurrentZone()
mapId = MTH_Map:GetCurrentMapID()
end
end
local nodes = mapId and MTH_Map.nodesByZone and MTH_Map.nodesByZone[mapId] or nil
local hasNodes = nodes and table.getn(nodes) > 0
frame._mthTick = now + (hasNodes and (tonumber(MTH_Map.minimapTickActive) or 0.20) or (tonumber(MTH_Map.minimapTickIdle) or 0.75))
if hasNodes then
MTH_Map:UpdateMinimap()
elseif (frame._mthNoNodeTick or 0) <= now then
frame._mthNoNodeTick = now + 1.0
MTH_Map:UpdateMinimap()
end
else
frame._mthTick = now + (tonumber(MTH_Map.minimapTickIdle) or 0.75)
end end
end) end)
end end
MTH_Map_Log("Map system initialized") MTH_Map_Log("Map system initialized")
end end
MTH_Map:Init()
+29 -22
View File
@@ -1,5 +1,13 @@
------------------------------------------------------ ------------------------------------------------------
-- MetaHunt Minimap Button -- MetaHunt Minimap Button
--
-- NOTE: The namespace table is MTH_MinimapButton (a plain Lua table).
-- The actual UI frame is named "MTH_MinimapBtn" to avoid a global
-- collision — CreateFrame("...", "MTH_MinimapButton", ...) would
-- OVERWRITE the namespace table with the frame object, orphaning
-- all methods and .frame/.icon references. pfUI iterates Minimap
-- children by name and calls _G[name]:GetHeight(); if the global is
-- a plain {} table instead of a frame, that call crashes.
------------------------------------------------------ ------------------------------------------------------
if not MTH_MinimapButton then if not MTH_MinimapButton then
@@ -84,7 +92,9 @@ function MTH_MinimapButton:Initialize()
return return
end end
local button = CreateFrame("Button", "MTH_MinimapButtonFrame", Minimap) -- Frame name is MTH_MinimapBtn (NOT "MTH_MinimapButton") to avoid
-- overwriting the namespace table in _G.
local button = CreateFrame("Button", "MTH_MinimapBtn", Minimap)
if not button then if not button then
return return
end end
@@ -114,10 +124,9 @@ function MTH_MinimapButton:Initialize()
highlight:SetHeight(31) highlight:SetHeight(31)
highlight:SetPoint("CENTER", button, "CENTER", 0, 0) highlight:SetPoint("CENTER", button, "CENTER", 0, 0)
button:SetScript("OnEnter", function(self) button:SetScript("OnEnter", function()
self = self or this if not this then return end
if not self then return end GameTooltip:SetOwner(this, "ANCHOR_LEFT")
GameTooltip:SetOwner(self, "ANCHOR_LEFT")
GameTooltip:SetText(MTH_MB_L("MINIMAP_TITLE", "MetaHunt"), 1, 0.82, 0) GameTooltip:SetText(MTH_MB_L("MINIMAP_TITLE", "MetaHunt"), 1, 0.82, 0)
GameTooltip:AddLine(MTH_MB_L("MINIMAP_HINT_LEFT_CLICK", "Left-Click: Open Hunter Book"), 1, 1, 1) GameTooltip:AddLine(MTH_MB_L("MINIMAP_HINT_LEFT_CLICK", "Left-Click: Open Hunter Book"), 1, 1, 1)
GameTooltip:AddLine(MTH_MB_L("MINIMAP_HINT_RIGHT_CLICK", "Right-Click: Open MetaHunt Options"), 1, 1, 1) GameTooltip:AddLine(MTH_MB_L("MINIMAP_HINT_RIGHT_CLICK", "Right-Click: Open MetaHunt Options"), 1, 1, 1)
@@ -129,25 +138,23 @@ function MTH_MinimapButton:Initialize()
GameTooltip:Hide() GameTooltip:Hide()
end) end)
button:SetScript("OnDragStart", function(self) button:SetScript("OnDragStart", function()
self = self or this if not this then return end
if not self then return end this.dragging = 1
self.dragging = 1 this:SetScript("OnUpdate", function()
self:SetScript("OnUpdate", function()
MTH_MB_UpdateDragPosition() MTH_MB_UpdateDragPosition()
end) end)
end) end)
button:SetScript("OnDragStop", function(self) button:SetScript("OnDragStop", function()
self = self or this if not this then return end
if not self then return end this.dragging = nil
self.dragging = nil this:SetScript("OnUpdate", nil)
self:SetScript("OnUpdate", nil)
MTH_MB_UpdateDragPosition() MTH_MB_UpdateDragPosition()
end) end)
button:SetScript("OnClick", function(_, mouseButton) button:SetScript("OnClick", function()
mouseButton = mouseButton or arg1 local mouseButton = arg1
if mouseButton == "RightButton" then if mouseButton == "RightButton" then
if type(MTH_OpenOptions) == "function" then if type(MTH_OpenOptions) == "function" then
MTH_OpenOptions("General") MTH_OpenOptions("General")
@@ -167,12 +174,12 @@ function MTH_MinimapButton:Initialize()
MTH_MB_UpdatePosition() MTH_MB_UpdatePosition()
end end
local loader = CreateFrame("Frame", "MTH_MinimapButtonLoader") local loader = CreateFrame("Frame", "MTH_MinimapLoader")
loader:RegisterEvent("ADDON_LOADED") loader:RegisterEvent("ADDON_LOADED")
loader:SetScript("OnEvent", function(_, eventName, addonName) loader:SetScript("OnEvent", function()
eventName = eventName or event if event == "ADDON_LOADED" and arg1 == "MetaHunt" then
addonName = addonName or arg1
if eventName == "ADDON_LOADED" and addonName == "MetaHunt" then
MTH_MinimapButton:Initialize() MTH_MinimapButton:Initialize()
this:UnregisterAllEvents()
this:SetScript("OnEvent", nil)
end end
end) end)
+45 -45
View File
@@ -44,6 +44,8 @@ local MTH_AB_STATE = {
}, },
} }
local MTH_AB_TRANSIENT_STORE = {}
local function MTH_AB_SetCheckedNoClick(check, checked) local function MTH_AB_SetCheckedNoClick(check, checked)
if not check then return end if not check then return end
MTH_AB_STATE.syncing = true MTH_AB_STATE.syncing = true
@@ -51,6 +53,14 @@ local function MTH_AB_SetCheckedNoClick(check, checked)
MTH_AB_STATE.syncing = false MTH_AB_STATE.syncing = false
end end
local function MTH_AB_IsChecked(control)
if not control or type(control.GetChecked) ~= "function" then
return false
end
local checked = control:GetChecked()
return checked == 1 or checked == true
end
local function MTH_AB_GetEngine() local function MTH_AB_GetEngine()
return MTH_AutoBuyEngine return MTH_AutoBuyEngine
end end
@@ -60,8 +70,7 @@ local function MTH_AB_GetStore()
if engine and engine.EnsureDefaults then if engine and engine.EnsureDefaults then
return engine:EnsureDefaults() return engine:EnsureDefaults()
end end
MTH_AutoBuy_Saved = MTH_AutoBuy_Saved or {} return MTH_AB_TRANSIENT_STORE
return MTH_AutoBuy_Saved
end end
local function MTH_AB_NormalizeRule(rule) local function MTH_AB_NormalizeRule(rule)
@@ -91,10 +100,10 @@ end
local function MTH_AB_EnsureConfig() local function MTH_AB_EnsureConfig()
local store = MTH_AB_GetStore() local store = MTH_AB_GetStore()
if store.enabled == nil then store.enabled = true end if store.enabled == nil then store.enabled = false end
if type(store.projectiles) ~= "table" then store.projectiles = {} end if type(store.projectiles) ~= "table" then store.projectiles = {} end
if type(store.petFood) ~= "table" then store.petFood = {} end if type(store.petFood) ~= "table" then store.petFood = {} end
if store.projectiles.enabled == nil then store.projectiles.enabled = true end if store.projectiles.enabled == nil then store.projectiles.enabled = false end
if store.petFood.enabled == nil then store.petFood.enabled = false end if store.petFood.enabled == nil then store.petFood.enabled = false end
if store.petFood.stacks == nil then store.petFood.stacks = 1 end if store.petFood.stacks == nil then store.petFood.stacks = 1 end
if store.petFood.scope == nil then store.petFood.scope = "current" end if store.petFood.scope == nil then store.petFood.scope = "current" end
@@ -509,7 +518,7 @@ local function MTH_AB_RefreshOptionsUI()
local store = MTH_AB_EnsureConfig() local store = MTH_AB_EnsureConfig()
local moduleEnabled = true local moduleEnabled = true
if MTH and MTH.IsModuleEnabled then if MTH and MTH.IsModuleEnabled then
moduleEnabled = MTH:IsModuleEnabled("autobuy", true) and true or false moduleEnabled = MTH:IsModuleEnabled("autobuy", false) and true or false
end end
MTH_AB_SetCheckedNoClick(MTH_AB_STATE.controls.moduleEnabled, moduleEnabled) MTH_AB_SetCheckedNoClick(MTH_AB_STATE.controls.moduleEnabled, moduleEnabled)
@@ -648,28 +657,25 @@ local function MTH_AB_CreateRow(container, subtype, index, xBase, yOffset)
row.suffix:SetText("Stacks") row.suffix:SetText("Stacks")
if row.check then if row.check then
row.check:SetScript("OnClick", function(self) row.check:SetScript("OnClick", function()
self = self or this if not this or MTH_AB_STATE.syncing then return end
if not self or MTH_AB_STATE.syncing then return end
local store = MTH_AB_EnsureConfig() local store = MTH_AB_EnsureConfig()
MTH_AB_SetRuleEnabled(store, subtype, index, self:GetChecked() and true or false) MTH_AB_SetRuleEnabled(store, subtype, index, MTH_AB_IsChecked(this))
MTH_AB_RefreshOptionsUI() MTH_AB_RefreshOptionsUI()
end) end)
end end
row.qty:SetScript("OnEnterPressed", function(self) row.qty:SetScript("OnEnterPressed", function()
self = self or this if not this then return end
if not self then return end
local store = MTH_AB_EnsureConfig() local store = MTH_AB_EnsureConfig()
MTH_AB_SetRuleStacks(store, subtype, index, self:GetText()) MTH_AB_SetRuleStacks(store, subtype, index, this:GetText())
MTH_AB_RefreshOptionsUI() MTH_AB_RefreshOptionsUI()
self:ClearFocus() this:ClearFocus()
end) end)
row.qty:SetScript("OnEditFocusLost", function(self) row.qty:SetScript("OnEditFocusLost", function()
self = self or this if not this then return end
if not self then return end
local store = MTH_AB_EnsureConfig() local store = MTH_AB_EnsureConfig()
MTH_AB_SetRuleStacks(store, subtype, index, self:GetText()) MTH_AB_SetRuleStacks(store, subtype, index, this:GetText())
MTH_AB_RefreshOptionsUI() MTH_AB_RefreshOptionsUI()
end) end)
@@ -706,11 +712,10 @@ local function MTH_AB_BuildUI(container)
controls.moduleEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyModuleEnabled", "Enable Auto Buy module", -30) controls.moduleEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyModuleEnabled", "Enable Auto Buy module", -30)
if controls.moduleEnabled then if controls.moduleEnabled then
controls.moduleEnabled:SetScript("OnClick", function(self) controls.moduleEnabled:SetScript("OnClick", function()
self = self or this if not this or MTH_AB_STATE.syncing then return end
if not self or MTH_AB_STATE.syncing then return end
if MTH and MTH.SetModuleEnabled then if MTH and MTH.SetModuleEnabled then
local ok, err = MTH:SetModuleEnabled("autobuy", self:GetChecked() and true or false) local ok, err = MTH:SetModuleEnabled("autobuy", MTH_AB_IsChecked(this))
if not ok and MTH and MTH.Print then if not ok and MTH and MTH.Print then
MTH:Print("Failed to change Auto Buy state: " .. tostring(err), "error") MTH:Print("Failed to change Auto Buy state: " .. tostring(err), "error")
end end
@@ -721,11 +726,10 @@ local function MTH_AB_BuildUI(container)
controls.projectilesEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyProjectilesEnabled", "Enable for Projectiles", -74) controls.projectilesEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyProjectilesEnabled", "Enable for Projectiles", -74)
if controls.projectilesEnabled then if controls.projectilesEnabled then
controls.projectilesEnabled:SetScript("OnClick", function(self) controls.projectilesEnabled:SetScript("OnClick", function()
self = self or this if not this or MTH_AB_STATE.syncing then return end
if not self or MTH_AB_STATE.syncing then return end
local store = MTH_AB_EnsureConfig() local store = MTH_AB_EnsureConfig()
store.projectiles.enabled = self:GetChecked() and true or false store.projectiles.enabled = MTH_AB_IsChecked(this)
MTH_AB_RefreshOptionsUI() MTH_AB_RefreshOptionsUI()
end) end)
end end
@@ -760,11 +764,10 @@ local function MTH_AB_BuildUI(container)
controls.petFoodEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyPetFoodEnabled", "Enable for Pet Food", -322, MTH_AB_LAYOUT.LEFT_SECTION_X) controls.petFoodEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyPetFoodEnabled", "Enable for Pet Food", -322, MTH_AB_LAYOUT.LEFT_SECTION_X)
if controls.petFoodEnabled then if controls.petFoodEnabled then
controls.petFoodEnabled:SetScript("OnClick", function(self) controls.petFoodEnabled:SetScript("OnClick", function()
self = self or this if not this or MTH_AB_STATE.syncing then return end
if not self or MTH_AB_STATE.syncing then return end
local store = MTH_AB_EnsureConfig() local store = MTH_AB_EnsureConfig()
store.petFood.enabled = self:GetChecked() and true or false store.petFood.enabled = MTH_AB_IsChecked(this)
MTH_AB_RefreshOptionsUI() MTH_AB_RefreshOptionsUI()
end) end)
end end
@@ -782,19 +785,17 @@ local function MTH_AB_BuildUI(container)
controls.petFoodQty:SetHeight(20) controls.petFoodQty:SetHeight(20)
controls.petFoodQty:SetNumeric(true) controls.petFoodQty:SetNumeric(true)
controls.petFoodQty:SetAutoFocus(false) controls.petFoodQty:SetAutoFocus(false)
controls.petFoodQty:SetScript("OnEnterPressed", function(self) controls.petFoodQty:SetScript("OnEnterPressed", function()
self = self or this if not this then return end
if not self then return end
local store = MTH_AB_EnsureConfig() local store = MTH_AB_EnsureConfig()
MTH_AB_SetPetFoodStacks(store, self:GetText()) MTH_AB_SetPetFoodStacks(store, this:GetText())
MTH_AB_RefreshOptionsUI() MTH_AB_RefreshOptionsUI()
self:ClearFocus() this:ClearFocus()
end) end)
controls.petFoodQty:SetScript("OnEditFocusLost", function(self) controls.petFoodQty:SetScript("OnEditFocusLost", function()
self = self or this if not this then return end
if not self then return end
local store = MTH_AB_EnsureConfig() local store = MTH_AB_EnsureConfig()
MTH_AB_SetPetFoodStacks(store, self:GetText()) MTH_AB_SetPetFoodStacks(store, this:GetText())
MTH_AB_RefreshOptionsUI() MTH_AB_RefreshOptionsUI()
end) end)
end end
@@ -807,9 +808,8 @@ local function MTH_AB_BuildUI(container)
controls.petFoodScopeCurrent = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyPetFoodScopeCurrent", "Buy only for my current pet", -376, MTH_AB_LAYOUT.LEFT_SECTION_X + 28) controls.petFoodScopeCurrent = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyPetFoodScopeCurrent", "Buy only for my current pet", -376, MTH_AB_LAYOUT.LEFT_SECTION_X + 28)
if controls.petFoodScopeCurrent then if controls.petFoodScopeCurrent then
controls.petFoodScopeCurrent:SetScript("OnClick", function(self) controls.petFoodScopeCurrent:SetScript("OnClick", function()
self = self or this if not this or MTH_AB_STATE.syncing then return end
if not self or MTH_AB_STATE.syncing then return end
local store = MTH_AB_EnsureConfig() local store = MTH_AB_EnsureConfig()
store.petFood.scope = "current" store.petFood.scope = "current"
MTH_AB_RefreshOptionsUI() MTH_AB_RefreshOptionsUI()
@@ -818,9 +818,8 @@ local function MTH_AB_BuildUI(container)
controls.petFoodScopeAll = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyPetFoodScopeAll", "Buy for all my pets", -402, MTH_AB_LAYOUT.LEFT_SECTION_X + 28) controls.petFoodScopeAll = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyPetFoodScopeAll", "Buy for all my pets", -402, MTH_AB_LAYOUT.LEFT_SECTION_X + 28)
if controls.petFoodScopeAll then if controls.petFoodScopeAll then
controls.petFoodScopeAll:SetScript("OnClick", function(self) controls.petFoodScopeAll:SetScript("OnClick", function()
self = self or this if not this or MTH_AB_STATE.syncing then return end
if not self or MTH_AB_STATE.syncing then return end
local store = MTH_AB_EnsureConfig() local store = MTH_AB_EnsureConfig()
store.petFood.scope = "all" store.petFood.scope = "all"
MTH_AB_RefreshOptionsUI() MTH_AB_RefreshOptionsUI()
@@ -842,6 +841,7 @@ local function MTH_AB_BuildUI(container)
text:SetText("") text:SetText("")
controls.petFoodPetLines[i] = { icon = icon, text = text } controls.petFoodPetLines[i] = { icon = icon, text = text }
end end
end end
function MTH_SetupAutoBuyOptions() function MTH_SetupAutoBuyOptions()
+228
View File
@@ -0,0 +1,228 @@
local MTH_AQ_READY = MTH_OptionsRequire and MTH_OptionsRequire("options-autoquest", {
"MTH_GetFrame",
"MTH_ClearContainer",
"MTH_CreateCheckbox",
})
local function MTH_AQ_IsChecked(control)
if not control or type(control.GetChecked) ~= "function" then
return false
end
local checked = control:GetChecked()
return checked == 1 or checked == true
end
local function MTH_AQ_EnsureStore()
if type(MTH_CharSavedVariables) ~= "table" then
MTH_CharSavedVariables = {}
end
if type(MTH_CharSavedVariables.autoquest) ~= "table" then
MTH_CharSavedVariables.autoquest = {}
end
local store = MTH_CharSavedVariables.autoquest
if type(MTH_CharSavedVariables.questautomation) == "table" then
local legacy = MTH_CharSavedVariables.questautomation
if store.scorpokDrazial == nil and legacy.scorpokDrazial ~= nil then
store.scorpokDrazial = legacy.scorpokDrazial and true or false
end
if store.scorpokTooltip == nil and legacy.scorpokTooltip ~= nil then
store.scorpokTooltip = legacy.scorpokTooltip and true or false
end
end
if store.scorpokDrazial == nil then
store.scorpokDrazial = false
end
if store.arrowsForSissies == nil then
store.arrowsForSissies = false
end
return store
end
function MTH_SetupAutoQuestOptions()
if not MTH_AQ_READY then return end
local container = MTH_GetFrame("MetaHuntOptionsAutoQuest")
if not container then return end
MTH_ClearContainer(container)
local title = container:CreateFontString("MetaHuntOptionsAutoQuestTitle", "ARTWORK", "GameFontHighlight")
title:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -10)
title:SetText("Auto Quest")
local body = container:CreateFontString("MetaHuntOptionsAutoQuestBody", "ARTWORK", "GameFontNormalSmall")
body:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -30)
body:SetWidth(560)
body:SetJustifyH("LEFT")
body:SetJustifyV("TOP")
body:SetTextColor(0.45, 0.75, 1)
body:SetText("Automation for specific quest interactions.")
local moduleEnabled = true
if MTH and MTH.GetModule then
local module = MTH:GetModule("autoquest")
if type(module) == "table" and module.enabled ~= nil then
moduleEnabled = module.enabled and true or false
elseif MTH and MTH.IsModuleEnabled then
moduleEnabled = MTH:IsModuleEnabled("autoquest", false) and true or false
end
elseif MTH and MTH.IsModuleEnabled then
moduleEnabled = MTH:IsModuleEnabled("autoquest", false) and true or false
end
local moduleToggle = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoQuestModuleToggle", "Enable Auto Quest module", -70, 20)
if moduleToggle then
moduleToggle:SetChecked(moduleEnabled and true or false)
moduleToggle:SetScript("OnClick", function()
if not this then return end
local enabled = MTH_AQ_IsChecked(this)
if MTH and MTH.SetModuleEnabled then
local ok, err = MTH:SetModuleEnabled("autoquest", enabled)
if not ok and MTH and MTH.Print then
MTH:Print("Failed to change Auto Quest module state: " .. tostring(err), "error")
end
end
local module = MTH and MTH.GetModule and MTH:GetModule("autoquest") or nil
local actual = (type(module) == "table" and module.enabled ~= nil) and (module.enabled and true or false) or enabled
this:SetChecked(actual and true or false)
end)
end
local store = MTH_AQ_EnsureStore()
if store.scorpokTooltip == nil then
store.scorpokTooltip = false
end
local sectionWidth = (container:GetWidth() or 600) - 40
if sectionWidth < 360 then
sectionWidth = 360
end
local function ensureSection(name, sectionTitle, yOffset, height)
local section = getglobal(name)
if not section then
section = CreateFrame("Frame", name, container, "OptionFrameBoxTemplate")
end
if not section then
return nil
end
section:SetParent(container)
section:ClearAllPoints()
section:SetPoint("TOPLEFT", container, "TOPLEFT", 20, yOffset)
section:SetWidth(sectionWidth)
section:SetHeight(height)
section:Show()
local titleFrame = getglobal(name .. "Title")
if titleFrame then
titleFrame:SetText(sectionTitle)
end
return section
end
local function ensureCheckbox(section, name, label, yOffset, checked)
local check = getglobal(name)
if not check then
check = CreateFrame("CheckButton", name, section, "OptionsCheckButtonTemplate")
end
if not check then
return nil
end
check:SetParent(section)
check:ClearAllPoints()
check:SetPoint("TOPLEFT", section, "TOPLEFT", 12, yOffset)
check:SetChecked(checked and true or false)
check:Show()
local text = getglobal(name .. "Text")
if text then
text:SetText(label)
end
return check
end
local scorpokSection = ensureSection("MetaHuntAutoQuestScorpokBox", "Salt of the Scorpok", -130, 112)
if scorpokSection then
local scorpokToggle = ensureCheckbox(
scorpokSection,
"MetaHuntOptionsAutoQuestScorpokToggle",
"Enable SHIFT-rightclick for Bloodmage Drazial",
-10,
store.scorpokDrazial and true or false
)
if scorpokToggle then
scorpokToggle:SetScript("OnClick", function()
local enabled = MTH_AQ_IsChecked(this)
store.scorpokDrazial = enabled and true or false
if MTH and MTH.GetModuleCharSavedVariables then
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
if type(moduleStore) == "table" then
moduleStore.scorpokDrazial = store.scorpokDrazial and true or false
end
end
local module = MTH and MTH.GetModule and MTH:GetModule("autoquest")
if module and module.SetScorpokDrazialEnabled then
module:SetScorpokDrazialEnabled(enabled)
end
end)
end
local tooltipToggle = ensureCheckbox(
scorpokSection,
"MetaHuntOptionsAutoQuestScorpokTooltipToggle",
"Enhance Tooltip on Drazial and related beasts (requires Tooltips module enabled)",
-42,
store.scorpokTooltip and true or false
)
if tooltipToggle then
tooltipToggle:SetScript("OnClick", function()
local enabled = MTH_AQ_IsChecked(this)
store.scorpokTooltip = enabled and true or false
if MTH and MTH.GetModuleCharSavedVariables then
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
if type(moduleStore) == "table" then
moduleStore.scorpokTooltip = store.scorpokTooltip and true or false
end
end
end)
end
end
local sissiesSection = ensureSection("MetaHuntAutoQuestSissiesBox", "Arrows Are For Sissies", -255, 108)
if sissiesSection then
local sissiesNote = getglobal("MetaHuntOptionsAutoQuestSissiesNote")
if not sissiesNote then
sissiesNote = sissiesSection:CreateFontString("MetaHuntOptionsAutoQuestSissiesNote", "ARTWORK", "GameFontNormalSmall")
end
sissiesNote:ClearAllPoints()
sissiesNote:SetPoint("TOPLEFT", sissiesSection, "TOPLEFT", 14, -10)
sissiesNote:SetWidth(sectionWidth - 28)
sissiesNote:SetJustifyH("LEFT")
sissiesNote:SetTextColor(0.45, 0.75, 1)
sissiesNote:SetText("Note that you should not activate this if you are using LazyPig")
sissiesNote:Show()
local sissiesToggle = ensureCheckbox(
sissiesSection,
"MetaHuntOptionsAutoQuestSissiesToggle",
"Enable SHIFT-rightclick for Artilleryman Sheldonore",
-40,
store.arrowsForSissies and true or false
)
if sissiesToggle then
sissiesToggle:SetScript("OnClick", function()
local enabled = MTH_AQ_IsChecked(this)
store.arrowsForSissies = enabled and true or false
if MTH and MTH.GetModuleCharSavedVariables then
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
if type(moduleStore) == "table" then
moduleStore.arrowsForSissies = store.arrowsForSissies and true or false
end
end
local module = MTH and MTH.GetModule and MTH:GetModule("autoquest")
if module and module.SetArrowsForSissiesEnabled then
module:SetArrowsForSissiesEnabled(enabled)
end
end)
end
end
end
+52 -39
View File
@@ -98,11 +98,20 @@ local function MTH_CHRON_CopyTable(source)
end end
local function MTH_CHRON_GetProfile() local function MTH_CHRON_GetProfile()
if not (MTH and MTH.GetModuleSavedVariables) then if not (MTH and MTH.GetModuleCharSavedVariables) then
return MTH_CHRON_CopyTable(MTH_CHRON_DEFAULTS) return MTH_CHRON_CopyTable(MTH_CHRON_DEFAULTS)
end end
local store = MTH:GetModuleSavedVariables("chronometer") local store = MTH:GetModuleCharSavedVariables("chronometer")
if type(store) ~= "table" then
return MTH_CHRON_CopyTable(MTH_CHRON_DEFAULTS)
end
if type(store.profile) ~= "table" and MTH.GetModuleSavedVariables then
local accountStore = MTH:GetModuleSavedVariables("chronometer")
if type(accountStore) == "table" and type(accountStore.profile) == "table" then
store.profile = MTH_CHRON_CopyTable(accountStore.profile)
end
end
if type(store.profile) ~= "table" then if type(store.profile) ~= "table" then
store.profile = {} store.profile = {}
end end
@@ -298,6 +307,14 @@ local function MTH_CHRON_MakeSmall(parent, name, text, x, y)
return label return label
end end
local function MTH_CHRON_IsChecked(control)
if not control or type(control.GetChecked) ~= "function" then
return false
end
local checked = control:GetChecked()
return checked == 1 or checked == true
end
local function MTH_CHRON_MakeInput(parent, name, x, y, width, height, value, onAccept) local function MTH_CHRON_MakeInput(parent, name, x, y, width, height, value, onAccept)
local edit = CreateFrame("EditBox", name, parent, "InputBoxTemplate") local edit = CreateFrame("EditBox", name, parent, "InputBoxTemplate")
@@ -309,13 +326,12 @@ local function MTH_CHRON_MakeInput(parent, name, x, y, width, height, value, onA
edit:SetHeight(height or 20) edit:SetHeight(height or 20)
edit:SetAutoFocus(false) edit:SetAutoFocus(false)
edit:SetText(tostring(value or "")) edit:SetText(tostring(value or ""))
edit:SetScript("OnEnterPressed", function(self) edit:SetScript("OnEnterPressed", function()
self = self or this if not this then return end
if not self then return end
if type(onAccept) == "function" then if type(onAccept) == "function" then
onAccept(self:GetText() or "") onAccept(this:GetText() or "")
end end
self:ClearFocus() this:ClearFocus()
end) end)
return edit return edit
end end
@@ -368,14 +384,18 @@ local function MTH_CHRON_RenderTimerSection(container, profile, title, items, bu
local check = MTH_CreateCheckbox(container, controlName, label, timerY, timerX) local check = MTH_CreateCheckbox(container, controlName, label, timerY, timerX)
if check then if check then
check:SetChecked(profile.disabledSpells[bucket][timerName] == nil and true or false) check:SetChecked(profile.disabledSpells[bucket][timerName] == nil and true or false)
check:SetScript("OnClick", function(self) check:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end local currentlyDisabled = profile.disabledSpells[bucket][timerName] ~= nil
if self:GetChecked() then if currentlyDisabled then
profile.disabledSpells[bucket][timerName] = nil profile.disabledSpells[bucket][timerName] = nil
this:SetChecked(true)
else else
profile.disabledSpells[bucket][timerName] = {} profile.disabledSpells[bucket][timerName] = {}
this:SetChecked(nil)
end end
MTH_CHRON_ApplyLiveProfile(profile)
end) end)
end end
timerY = timerY - 20 timerY = timerY - 20
@@ -448,10 +468,9 @@ function MTH_SetupChronometerOptions(tabKey)
if moduleCheck then if moduleCheck then
local module = MTH and MTH:GetModule("chronometer") local module = MTH and MTH:GetModule("chronometer")
moduleCheck:SetChecked(module and module.enabled and true or false) moduleCheck:SetChecked(module and module.enabled and true or false)
moduleCheck:SetScript("OnClick", function(self) moduleCheck:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end local enabled = MTH_CHRON_IsChecked(this)
local enabled = self:GetChecked() and true or false
if MTH and MTH.SetModuleEnabled then if MTH and MTH.SetModuleEnabled then
MTH:SetModuleEnabled("chronometer", enabled) MTH:SetModuleEnabled("chronometer", enabled)
end end
@@ -473,40 +492,36 @@ function MTH_SetupChronometerOptions(tabKey)
local killCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerFadeOnKill", "Fade on kill", -154) local killCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerFadeOnKill", "Fade on kill", -154)
if killCheck then if killCheck then
killCheck:SetChecked(profile.fadeonkill and true or false) killCheck:SetChecked(profile.fadeonkill and true or false)
killCheck:SetScript("OnClick", function(self) killCheck:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end profile.fadeonkill = MTH_CHRON_IsChecked(this)
profile.fadeonkill = self:GetChecked() and true or false
end) end)
end end
local fadeCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerFadeOnFade", "Fade on aura fade", -179) local fadeCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerFadeOnFade", "Fade on aura fade", -179)
if fadeCheck then if fadeCheck then
fadeCheck:SetChecked(profile.fadeonfade and true or false) fadeCheck:SetChecked(profile.fadeonfade and true or false)
fadeCheck:SetScript("OnClick", function(self) fadeCheck:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end profile.fadeonfade = MTH_CHRON_IsChecked(this)
profile.fadeonfade = self:GetChecked() and true or false
end) end)
end end
local selfCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerSelfBars", "Show self bars", -204) local selfCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerSelfBars", "Show self bars", -204)
if selfCheck then if selfCheck then
selfCheck:SetChecked(profile.selfbars and true or false) selfCheck:SetChecked(profile.selfbars and true or false)
selfCheck:SetScript("OnClick", function(self) selfCheck:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end profile.selfbars = MTH_CHRON_IsChecked(this)
profile.selfbars = self:GetChecked() and true or false
end) end)
end end
local onlySelfCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerOnlySelf", "Only self target", -229) local onlySelfCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerOnlySelf", "Only self target", -229)
if onlySelfCheck then if onlySelfCheck then
onlySelfCheck:SetChecked(profile.onlyself and true or false) onlySelfCheck:SetChecked(profile.onlyself and true or false)
onlySelfCheck:SetScript("OnClick", function(self) onlySelfCheck:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end profile.onlyself = MTH_CHRON_IsChecked(this)
profile.onlyself = self:GetChecked() and true or false
end) end)
end end
elseif section == "bar" then elseif section == "bar" then
@@ -588,10 +603,9 @@ function MTH_SetupChronometerOptions(tabKey)
local growCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerGrowUp", "Grow bars upward", -438) local growCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerGrowUp", "Grow bars upward", -438)
if growCheck then if growCheck then
growCheck:SetChecked(profile.growup and true or false) growCheck:SetChecked(profile.growup and true or false)
growCheck:SetScript("OnClick", function(self) growCheck:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end profile.growup = MTH_CHRON_IsChecked(this)
profile.growup = self:GetChecked() and true or false
MTH_CHRON_ApplyLiveProfile(profile) MTH_CHRON_ApplyLiveProfile(profile)
end) end)
end end
@@ -599,10 +613,9 @@ function MTH_SetupChronometerOptions(tabKey)
local reverseCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerReverse", "Reverse bars", -463) local reverseCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerReverse", "Reverse bars", -463)
if reverseCheck then if reverseCheck then
reverseCheck:SetChecked(profile.reverse and true or false) reverseCheck:SetChecked(profile.reverse and true or false)
reverseCheck:SetScript("OnClick", function(self) reverseCheck:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end profile.reverse = MTH_CHRON_IsChecked(this)
profile.reverse = self:GetChecked() and true or false
MTH_CHRON_ApplyLiveProfile(profile) MTH_CHRON_ApplyLiveProfile(profile)
end) end)
end end
+10
View File
@@ -159,6 +159,16 @@ function MTH_SetupCreditsOptions()
cursor, cursor,
-4) -4)
cursor = MTH_CreditsCreateText(content, cursor,
MTH_CR_L("CREDITS_ABOUT_ICU", "- ICU was an old vanilla addon. I used the following last revision and added many more features of config options to it."),
"GameFontNormalSmall", -10)
cursor = MTH_CreditsCreateLink(content,
"https://github.com/wigan91/ICU-TWoW",
"https://github.com/wigan91/ICU-TWoW",
cursor,
-4)
cursor = MTH_CreditsCreateText(content, cursor, cursor = MTH_CreditsCreateText(content, cursor,
MTH_CR_L("CREDITS_ABOUT_MAP", "- The Map/Marker system is the one of pfQuest from Master Shagu. Unfortunately he is no more reachable for some months and I could not have some talk with him about this. I mostly let it untouched, I just made slight modifications so it can integrate better within Metahunt, and doesn't conflict with pfQuest."), MTH_CR_L("CREDITS_ABOUT_MAP", "- The Map/Marker system is the one of pfQuest from Master Shagu. Unfortunately he is no more reachable for some months and I could not have some talk with him about this. I mostly let it untouched, I just made slight modifications so it can integrate better within Metahunt, and doesn't conflict with pfQuest."),
"GameFontNormalSmall", -10) "GameFontNormalSmall", -10)
+18 -20
View File
@@ -226,10 +226,9 @@ function MTH_SetupFeedOMaticOptions()
local moduleCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsFeedOMaticEnabled", MTH_FOM_L("FOM_ENABLE_MODULE", "Enable FeedOMatic module"), -32 + yAdjust) local moduleCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsFeedOMaticEnabled", MTH_FOM_L("FOM_ENABLE_MODULE", "Enable FeedOMatic module"), -32 + yAdjust)
if moduleCheck then if moduleCheck then
moduleCheck:SetScript("OnClick", function(self) moduleCheck:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end local enabled = this:GetChecked() == 1
local enabled = self:GetChecked() == 1
if MTH and MTH.SetModuleEnabled then if MTH and MTH.SetModuleEnabled then
local ok, err = MTH:SetModuleEnabled("feedomatic", enabled) local ok, err = MTH:SetModuleEnabled("feedomatic", enabled)
if not ok and MTH and MTH.Print then if not ok and MTH and MTH.Print then
@@ -263,11 +262,11 @@ function MTH_SetupFeedOMaticOptions()
MTH_FOM_StartBindingCapture() MTH_FOM_StartBindingCapture()
end end
end) end)
bindButton:SetScript("OnKeyDown", function(_, key) bindButton:SetScript("OnKeyDown", function()
if not MTH_FOM_STATE.bindingCapture then if not MTH_FOM_STATE.bindingCapture then
return return
end end
key = key or arg1 local key = arg1
if not key or key == "" then if not key or key == "" then
return return
end end
@@ -305,10 +304,10 @@ function MTH_SetupFeedOMaticOptions()
MTH_FOM_STATE.ctrl.PreferHigherQuality = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMPreferQuality", FOM_OptionsButtonText and FOM_OptionsButtonText["PreferHigherQuality"] or MTH_FOM_L("FOM_LABEL_PREFER_HIGHER_QUALITY_FOOD", "Prefer higher quality food"), -220 + yAdjust) MTH_FOM_STATE.ctrl.PreferHigherQuality = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMPreferQuality", FOM_OptionsButtonText and FOM_OptionsButtonText["PreferHigherQuality"] or MTH_FOM_L("FOM_LABEL_PREFER_HIGHER_QUALITY_FOOD", "Prefer higher quality food"), -220 + yAdjust)
MTH_FOM_STATE.ctrl.Fallback = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMFallback", FOM_OptionsButtonText and FOM_OptionsButtonText["Fallback"] or MTH_FOM_L("FOM_LABEL_FALLBACK_TO_AVOIDED_FOODS", "Fallback to avoided foods"), -245 + yAdjust) MTH_FOM_STATE.ctrl.Fallback = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMFallback", FOM_OptionsButtonText and FOM_OptionsButtonText["Fallback"] or MTH_FOM_L("FOM_LABEL_FALLBACK_TO_AVOIDED_FOODS", "Fallback to avoided foods"), -245 + yAdjust)
if MTH_FOM_STATE.ctrl.AvoidQuestFood then MTH_FOM_STATE.ctrl.AvoidQuestFood:SetScript("OnClick", function(self) self = self or this if not self then return end FOM_Config.AvoidQuestFood = self:GetChecked() == 1 end) end if MTH_FOM_STATE.ctrl.AvoidQuestFood then MTH_FOM_STATE.ctrl.AvoidQuestFood:SetScript("OnClick", function() if not this then return end FOM_Config.AvoidQuestFood = this:GetChecked() == 1 end) end
if MTH_FOM_STATE.ctrl.AvoidBonusFood then MTH_FOM_STATE.ctrl.AvoidBonusFood:SetScript("OnClick", function(self) self = self or this if not self then return end FOM_Config.AvoidBonusFood = self:GetChecked() == 1 end) end if MTH_FOM_STATE.ctrl.AvoidBonusFood then MTH_FOM_STATE.ctrl.AvoidBonusFood:SetScript("OnClick", function() if not this then return end FOM_Config.AvoidBonusFood = this:GetChecked() == 1 end) end
if MTH_FOM_STATE.ctrl.PreferHigherQuality then MTH_FOM_STATE.ctrl.PreferHigherQuality:SetScript("OnClick", function(self) self = self or this if not self then return end FOM_Config.PreferHigherQuality = self:GetChecked() == 1 end) end if MTH_FOM_STATE.ctrl.PreferHigherQuality then MTH_FOM_STATE.ctrl.PreferHigherQuality:SetScript("OnClick", function() if not this then return end FOM_Config.PreferHigherQuality = this:GetChecked() == 1 end) end
if MTH_FOM_STATE.ctrl.Fallback then MTH_FOM_STATE.ctrl.Fallback:SetScript("OnClick", function(self) self = self or this if not self then return end FOM_Config.Fallback = self:GetChecked() == 1 end) end if MTH_FOM_STATE.ctrl.Fallback then MTH_FOM_STATE.ctrl.Fallback:SetScript("OnClick", function() if not this then return end FOM_Config.Fallback = this:GetChecked() == 1 end) end
local keepOpenLabel = container:CreateFontString("MetaHuntOptionsFOMKeepOpenLabel", "ARTWORK", "GameFontNormalSmall") local keepOpenLabel = container:CreateFontString("MetaHuntOptionsFOMKeepOpenLabel", "ARTWORK", "GameFontNormalSmall")
keepOpenLabel:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -302 + yAdjust) keepOpenLabel:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -302 + yAdjust)
@@ -320,14 +319,13 @@ function MTH_SetupFeedOMaticOptions()
keepOpen:SetHeight(20) keepOpen:SetHeight(20)
keepOpen:SetNumeric(true) keepOpen:SetNumeric(true)
keepOpen:SetAutoFocus(false) keepOpen:SetAutoFocus(false)
keepOpen:SetScript("OnTextChanged", function(self) keepOpen:SetScript("OnTextChanged", function()
self = self or this if not this then return end
if not self then return end local value = tonumber(this:GetText()) or 0
local value = tonumber(self:GetText()) or 0
FOM_Config.KeepOpenSlots = value FOM_Config.KeepOpenSlots = value
end) end)
keepOpen:SetScript("OnEnterPressed", function(self) self = self or this if self then self:ClearFocus() end end) keepOpen:SetScript("OnEnterPressed", function() if this then this:ClearFocus() end end)
keepOpen:SetScript("OnEscapePressed", function(self) self = self or this if self then self:ClearFocus() end end) keepOpen:SetScript("OnEscapePressed", function() if this then this:ClearFocus() end end)
MTH_FOM_STATE.keepOpenEdit = keepOpen MTH_FOM_STATE.keepOpenEdit = keepOpen
local notifyHeader = container:CreateFontString("MetaHuntOptionsFOMNotifyHeader", "ARTWORK", "GameFontHighlight") local notifyHeader = container:CreateFontString("MetaHuntOptionsFOMNotifyHeader", "ARTWORK", "GameFontHighlight")
@@ -356,10 +354,10 @@ function MTH_SetupFeedOMaticOptions()
MTH_FOM_STATE.ctrl.AudioWarningBell = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMAudioWarningBell", FOM_OptionsButtonText and FOM_OptionsButtonText["AudioWarningBell"] or MTH_FOM_L("FOM_LABEL_USE_BELL_SOUND", "Use bell sound"), -403 + yAdjust, rightColumnX) MTH_FOM_STATE.ctrl.AudioWarningBell = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMAudioWarningBell", FOM_OptionsButtonText and FOM_OptionsButtonText["AudioWarningBell"] or MTH_FOM_L("FOM_LABEL_USE_BELL_SOUND", "Use bell sound"), -403 + yAdjust, rightColumnX)
MTH_FOM_STATE.ctrl.TextWarning = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMTextWarning", FOM_OptionsButtonText and FOM_OptionsButtonText["TextWarning"] or MTH_FOM_L("FOM_LABEL_SHOW_TEXT", "Show text"), -428 + yAdjust, rightColumnX) MTH_FOM_STATE.ctrl.TextWarning = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMTextWarning", FOM_OptionsButtonText and FOM_OptionsButtonText["TextWarning"] or MTH_FOM_L("FOM_LABEL_SHOW_TEXT", "Show text"), -428 + yAdjust, rightColumnX)
MTH_FOM_STATE.ctrl.IconWarning = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMIconWarning", FOM_OptionsButtonText and FOM_OptionsButtonText["IconWarning"] or MTH_FOM_L("FOM_LABEL_FLASH_ICON", "Flash icon"), -453 + yAdjust, rightColumnX) MTH_FOM_STATE.ctrl.IconWarning = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMIconWarning", FOM_OptionsButtonText and FOM_OptionsButtonText["IconWarning"] or MTH_FOM_L("FOM_LABEL_FLASH_ICON", "Flash icon"), -453 + yAdjust, rightColumnX)
if MTH_FOM_STATE.ctrl.AudioWarning then MTH_FOM_STATE.ctrl.AudioWarning:SetScript("OnClick", function(self) self = self or this if not self then return end if self:GetChecked() == 1 then if FOM_Config.AudioWarning ~= "bell" then FOM_Config.AudioWarning = true end else FOM_Config.AudioWarning = nil end MTH_RefreshFeedOMaticOptions() end) end if MTH_FOM_STATE.ctrl.AudioWarning then MTH_FOM_STATE.ctrl.AudioWarning:SetScript("OnClick", function() if not this then return end if this:GetChecked() == 1 then if FOM_Config.AudioWarning ~= "bell" then FOM_Config.AudioWarning = true end else FOM_Config.AudioWarning = nil end MTH_RefreshFeedOMaticOptions() end) end
if MTH_FOM_STATE.ctrl.AudioWarningBell then MTH_FOM_STATE.ctrl.AudioWarningBell:SetScript("OnClick", function(self) self = self or this if not self then return end if self:GetChecked() == 1 then FOM_Config.AudioWarning = "bell" else FOM_Config.AudioWarning = true end MTH_RefreshFeedOMaticOptions() end) end if MTH_FOM_STATE.ctrl.AudioWarningBell then MTH_FOM_STATE.ctrl.AudioWarningBell:SetScript("OnClick", function() if not this then return end if this:GetChecked() == 1 then FOM_Config.AudioWarning = "bell" else FOM_Config.AudioWarning = true end MTH_RefreshFeedOMaticOptions() end) end
if MTH_FOM_STATE.ctrl.TextWarning then MTH_FOM_STATE.ctrl.TextWarning:SetScript("OnClick", function(self) self = self or this if not self then return end FOM_Config.TextWarning = self:GetChecked() == 1 end) end if MTH_FOM_STATE.ctrl.TextWarning then MTH_FOM_STATE.ctrl.TextWarning:SetScript("OnClick", function() if not this then return end FOM_Config.TextWarning = this:GetChecked() == 1 end) end
if MTH_FOM_STATE.ctrl.IconWarning then MTH_FOM_STATE.ctrl.IconWarning:SetScript("OnClick", function(self) self = self or this if not self then return end FOM_Config.IconWarning = self:GetChecked() == 1 end) end if MTH_FOM_STATE.ctrl.IconWarning then MTH_FOM_STATE.ctrl.IconWarning:SetScript("OnClick", function() if not this then return end FOM_Config.IconWarning = this:GetChecked() == 1 end) end
local cookHeader = container:CreateFontString("MetaHuntOptionsFOMCookingHeader", "ARTWORK", "GameFontHighlight") local cookHeader = container:CreateFontString("MetaHuntOptionsFOMCookingHeader", "ARTWORK", "GameFontHighlight")
cookHeader:SetPoint("TOPLEFT", container, "TOPLEFT", rightColumnX, -62 + yAdjust) cookHeader:SetPoint("TOPLEFT", container, "TOPLEFT", rightColumnX, -62 + yAdjust)
+590
View File
@@ -0,0 +1,590 @@
local MTH_ICU_OPT_READY = true
local MTH_ICU_OPT_MISSING = {}
if type(MTH_GetFrame) ~= "function" then table.insert(MTH_ICU_OPT_MISSING, "MTH_GetFrame") end
if type(MTH_ClearContainer) ~= "function" then table.insert(MTH_ICU_OPT_MISSING, "MTH_ClearContainer") end
if type(MTH_CreateCheckbox) ~= "function" then table.insert(MTH_ICU_OPT_MISSING, "MTH_CreateCheckbox") end
if table.getn(MTH_ICU_OPT_MISSING) > 0 then
MTH_ICU_OPT_READY = false
if MTH and MTH.Print then
MTH:Print("[MTH ICU OPTIONS] missing dependencies: " .. table.concat(MTH_ICU_OPT_MISSING, ", "), "error")
end
end
local MTH_ICU_OPT_STATE = {
container = nil,
built = false,
controls = {},
}
local MTH_ICU_LAYOUT = {
LEFT_X = 20,
LEFT_DROPDOWN_X = 94,
RIGHT_X = 280,
RIGHT_DROPDOWN_X = 366,
DROPDOWN_WIDTH = 108,
COLOR_BUTTON_X = 378,
COLOR_BUTTON_WIDTH = 78,
COLOR_ROW_STEP = 24,
}
local MTH_ICU_OPTIONS_FALLBACK = {
ALERT = { "AUTO", "PARTY", "RAID", "SELF", "MTH Message", "OFF" },
ANNOUNCE = { "AUTO", "SAY", "YELL", "PARTY", "RAID", "SELF", "MTH Message", "OFF" },
ANCHOR = { "TOP", "TOPLEFT", "TOPRIGHT", "BOTTOM", "BOTTOMLEFT", "BOTTOMRIGHT", "LEFT", "RIGHT", "CUSTOM" },
POPUP_HIDE_DELAY = { "INSTANT", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
HEALTH_TEXT_MODE = { "NONE", "PERCENT", "HP", "BOTH" },
PLAYER_COLOR_MODE = { "CLASS", "REACTION", "FACTION", "CUSTOM" },
}
local MTH_ICU_DEFAULT_BG_COLORS = {
PLAYER_HOSTILE = { 1.00, 0.20, 0.20 },
PLAYER_NEUTRAL = { 1.00, 0.85, 0.10 },
PLAYER_FRIENDLY = { 0.20, 0.75, 1.00 },
NPC_HOSTILE = { 1.00, 0.20, 0.20 },
NPC_NEUTRAL = { 1.00, 0.85, 0.10 },
NPC_FRIENDLY = { 0.10, 0.90, 0.10 },
UNKNOWN = { 0.70, 0.70, 0.70 },
}
local MTH_ICU_COLOR_ROWS = {
{ key = "PLAYER_HOSTILE", label = "Player hostile" },
{ key = "PLAYER_NEUTRAL", label = "Player neutral" },
{ key = "PLAYER_FRIENDLY", label = "Player friendly" },
{ key = "NPC_HOSTILE", label = "NPC hostile" },
{ key = "NPC_NEUTRAL", label = "NPC neutral" },
{ key = "NPC_FRIENDLY", label = "NPC friendly" },
{ key = "UNKNOWN", label = "Unknown fallback" },
}
local function MTH_ICU_GetStore()
local store = nil
if MTH and MTH.GetModuleCharSavedVariables then
store = MTH:GetModuleCharSavedVariables("icu")
end
if type(store) ~= "table" then
ICUvars = ICUvars or {}
store = ICUvars
end
if store.ALERT == nil then store.ALERT = "MTH Message" end
if store.ALERT == "SAY" or store.ALERT == "YELL" then store.ALERT = "SELF" end
if store.ANNOUNCE == nil then store.ANNOUNCE = "MTH Message" end
if store.ANCHOR == nil then store.ANCHOR = "BOTTOMRIGHT" end
if store.POPUP_HIDE_DELAY == nil then
store.POPUP_HIDE_DELAY = "INSTANT"
else
local rawDelay = tostring(store.POPUP_HIDE_DELAY)
if rawDelay ~= "INSTANT" then
local n = tonumber(rawDelay)
if not n then
store.POPUP_HIDE_DELAY = "INSTANT"
else
n = math.floor(n)
if n < 1 then
store.POPUP_HIDE_DELAY = "INSTANT"
elseif n > 10 then
store.POPUP_HIDE_DELAY = "10"
else
store.POPUP_HIDE_DELAY = tostring(n)
end
end
end
end
if store.mouseOver == nil then store.mouseOver = false end
if store.HEALTH_TEXT_MODE == nil then store.HEALTH_TEXT_MODE = "BOTH" end
if store.HEALTH_TEXT_MODE == "AUTO" then store.HEALTH_TEXT_MODE = "BOTH" end
if store.PLAYER_COLOR_MODE == nil then store.PLAYER_COLOR_MODE = "CLASS" end
if store.REACTION_ONLY_PVP_PLAYERS == nil then store.REACTION_ONLY_PVP_PLAYERS = true end
if store.SHOW_GUILD_NAME == nil then store.SHOW_GUILD_NAME = false end
if store.SHOW_PLAYER_CLASS == nil then store.SHOW_PLAYER_CLASS = true end
if store.SHOW_PLAYER_RACE == nil then store.SHOW_PLAYER_RACE = true end
if store.SHOW_CUSTOM_TITLES == nil then store.SHOW_CUSTOM_TITLES = false end
if store.EXPAND_UP == nil then store.EXPAND_UP = false end
if type(store.COLORS) ~= "table" then
store.COLORS = {}
end
for key, def in pairs(MTH_ICU_DEFAULT_BG_COLORS) do
if type(store.COLORS[key]) ~= "table" then
store.COLORS[key] = { def[1], def[2], def[3] }
end
end
ICUvars = store
return store
end
local function MTH_ICU_GetOptionValues(key)
if type(ICU_OPTIONS) == "table" and type(ICU_OPTIONS[key]) == "table" then
return ICU_OPTIONS[key]
end
return MTH_ICU_OPTIONS_FALLBACK[key] or {}
end
local function MTH_ICU_SetValue(key, value)
local store = MTH_ICU_GetStore()
store[key] = tostring(value or "")
if key == "ANCHOR" and type(ICU_SetPoints) == "function" then
ICU_SetPoints()
end
end
local function MTH_ICU_DropdownSetText(frame, text)
if UIDropDownMenu_SetText then
UIDropDownMenu_SetText(tostring(text or ""), frame)
return
end
if not frame or not frame.GetName then return end
local textRegion = getglobal(frame:GetName() .. "Text")
if textRegion and textRegion.SetText then
textRegion:SetText(tostring(text or ""))
end
end
local function MTH_ICU_GetColor(key)
local store = MTH_ICU_GetStore()
local row = store.COLORS and store.COLORS[key]
if type(row) == "table" then
return tonumber(row[1]) or 0, tonumber(row[2]) or 0, tonumber(row[3]) or 0
end
local def = MTH_ICU_DEFAULT_BG_COLORS[key] or MTH_ICU_DEFAULT_BG_COLORS.UNKNOWN
return def[1], def[2], def[3]
end
local function MTH_ICU_SetColor(key, r, g, b)
local store = MTH_ICU_GetStore()
if type(store.COLORS) ~= "table" then
store.COLORS = {}
end
store.COLORS[key] = {
math.max(0, math.min(1, tonumber(r) or 0)),
math.max(0, math.min(1, tonumber(g) or 0)),
math.max(0, math.min(1, tonumber(b) or 0)),
}
end
local function MTH_ICU_OpenColorPicker(colorKey)
if not ColorPickerFrame then
if MTH and MTH.Print then
MTH:Print("ColorPickerFrame is not available in this client", "error")
end
return
end
local currentR, currentG, currentB = MTH_ICU_GetColor(colorKey)
local function applyColor()
local r, g, b = ColorPickerFrame:GetColorRGB()
MTH_ICU_SetColor(colorKey, r, g, b)
MTH_RefreshICUOptions()
end
ColorPickerFrame.func = applyColor
ColorPickerFrame.cancelFunc = function(prev)
if type(prev) == "table" then
local r = prev.r or prev[1] or currentR
local g = prev.g or prev[2] or currentG
local b = prev.b or prev[3] or currentB
MTH_ICU_SetColor(colorKey, r, g, b)
MTH_RefreshICUOptions()
end
end
ColorPickerFrame:SetColorRGB(currentR, currentG, currentB)
ColorPickerFrame.hasOpacity = false
ColorPickerFrame.opacity = 1
ColorPickerFrame.previousValues = { currentR, currentG, currentB }
ColorPickerFrame:Show()
end
local function MTH_ICU_CreateOptionRow(container, rowName, label, key, y, labelX, dropdownX)
labelX = labelX or MTH_ICU_LAYOUT.LEFT_X
dropdownX = dropdownX or MTH_ICU_LAYOUT.LEFT_DROPDOWN_X
local labelFs = container:CreateFontString(rowName .. "Label", "ARTWORK", "GameFontNormalSmall")
labelFs:SetPoint("TOPLEFT", container, "TOPLEFT", labelX, y)
labelFs:SetText(label)
local dropdown = CreateFrame("Frame", rowName .. "Drop", container, "UIDropDownMenuTemplate")
dropdown:ClearAllPoints()
dropdown:SetPoint("TOPLEFT", container, "TOPLEFT", dropdownX, y + 12)
if UIDropDownMenu_SetWidth then
UIDropDownMenu_SetWidth(MTH_ICU_LAYOUT.DROPDOWN_WIDTH, dropdown)
end
if UIDropDownMenu_JustifyText then
UIDropDownMenu_JustifyText("LEFT", dropdown)
end
if UIDropDownMenu_Initialize then
UIDropDownMenu_Initialize(dropdown, function()
local values = MTH_ICU_GetOptionValues(key)
local store = MTH_ICU_GetStore()
local current = tostring(store[key] or "")
local infoFactory = UIDropDownMenu_CreateInfo
for i = 1, table.getn(values) do
local optionValue = tostring(values[i])
local info = type(infoFactory) == "function" and infoFactory() or {}
info.text = optionValue
info.checked = optionValue == current and 1 or nil
info.func = function()
MTH_ICU_SetValue(key, optionValue)
MTH_RefreshICUOptions()
end
if UIDropDownMenu_AddButton then UIDropDownMenu_AddButton(info) end
end
end)
end
MTH_ICU_OPT_STATE.controls[key] = {
label = labelFs,
dropdown = dropdown,
}
end
local function MTH_ICU_CreateColorRow(container, rowName, label, colorKey, y, labelX, buttonX)
labelX = labelX or MTH_ICU_LAYOUT.RIGHT_X
buttonX = buttonX or MTH_ICU_LAYOUT.COLOR_BUTTON_X
local labelFs = container:CreateFontString(rowName .. "Label", "ARTWORK", "GameFontNormalSmall")
labelFs:SetPoint("TOPLEFT", container, "TOPLEFT", labelX, y)
labelFs:SetText(label)
local button = CreateFrame("Button", rowName .. "Button", container, "UIPanelButtonTemplate")
button:SetPoint("TOPLEFT", container, "TOPLEFT", buttonX, y + 8)
button:SetWidth(MTH_ICU_LAYOUT.COLOR_BUTTON_WIDTH)
button:SetHeight(22)
button:SetText("Pick")
button:SetScript("OnClick", function()
MTH_ICU_OpenColorPicker(colorKey)
end)
local swatch = button:CreateTexture(rowName .. "Swatch", "ARTWORK")
swatch:SetTexture("Interface\\Buttons\\WHITE8X8")
swatch:SetPoint("LEFT", button, "LEFT", 6, 0)
swatch:SetWidth(14)
swatch:SetHeight(14)
MTH_ICU_OPT_STATE.controls[colorKey] = {
label = labelFs,
button = button,
swatch = swatch,
isColor = true,
}
end
local function MTH_ICU_BuildUI(container)
if MTH_ICU_OPT_STATE.built and MTH_ICU_OPT_STATE.container == container then
return
end
MTH_ClearContainer(container)
MTH_ICU_OPT_STATE.controls = {}
MTH_ICU_OPT_STATE.container = container
MTH_ICU_OPT_STATE.built = true
local title = container:CreateFontString("MetaHuntOptionsICUTitle", "ARTWORK", "GameFontHighlight")
title:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -10)
title:SetText("MTH ICU")
local note = container:CreateFontString("MetaHuntOptionsICUNote", "ARTWORK", "GameFontNormalSmall")
note:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -32)
note:SetWidth(560)
note:SetJustifyH("LEFT")
note:SetJustifyV("TOP")
note:SetTextColor(0.35, 0.65, 1)
note:SetText("ICU is a minimap targeting utility module for your Trackings.\nIt provides enhanced target information and click actions for players and NPCs on the minimap.")
local moduleEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsICUModuleEnabled", "Enable ICU module", -72, MTH_ICU_LAYOUT.LEFT_X)
if moduleEnabled then
moduleEnabled:SetScript("OnClick", function()
if not this then return end
if MTH and MTH.SetModuleEnabled then
local ok, err = MTH:SetModuleEnabled("icu", this:GetChecked() == 1)
if not ok and MTH and MTH.Print then
MTH:Print("Failed to change ICU module state: " .. tostring(err), "error")
end
end
MTH_RefreshICUOptions()
end)
MTH_ICU_OPT_STATE.controls.moduleEnabled = moduleEnabled
end
local mouseOver = MTH_CreateCheckbox(container, "MetaHuntOptionsICUMouseOver", "Enable CTRL mouseover scan", -98, MTH_ICU_LAYOUT.LEFT_X)
if mouseOver then
mouseOver:SetScript("OnClick", function()
if not this then return end
local store = MTH_ICU_GetStore()
store.mouseOver = this:GetChecked() == 1 and true or false
end)
MTH_ICU_OPT_STATE.controls.mouseOver = mouseOver
end
local sectionHeader = container:CreateFontString("MetaHuntOptionsICUSectionHeader", "ARTWORK", "GameFontHighlight")
sectionHeader:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_ICU_LAYOUT.LEFT_X, -146)
sectionHeader:SetText("General Settings")
MTH_ICU_CreateOptionRow(container, "MetaHuntOptionsICUAlert", "ALERT PVP", "ALERT", -172, MTH_ICU_LAYOUT.LEFT_X, MTH_ICU_LAYOUT.LEFT_DROPDOWN_X)
MTH_ICU_CreateOptionRow(container, "MetaHuntOptionsICUAnnounce", "ANNOUNCE on click", "ANNOUNCE", -198, MTH_ICU_LAYOUT.LEFT_X, MTH_ICU_LAYOUT.LEFT_DROPDOWN_X)
MTH_ICU_CreateOptionRow(container, "MetaHuntOptionsICUHealthMode", "Health text", "HEALTH_TEXT_MODE", -224, MTH_ICU_LAYOUT.LEFT_X, MTH_ICU_LAYOUT.LEFT_DROPDOWN_X)
MTH_ICU_CreateOptionRow(container, "MetaHuntOptionsICUHideDelay", "List hide delay", "POPUP_HIDE_DELAY", -250, MTH_ICU_LAYOUT.LEFT_X, MTH_ICU_LAYOUT.LEFT_DROPDOWN_X)
MTH_ICU_CreateOptionRow(container, "MetaHuntOptionsICUAnchor", "ANCHOR", "ANCHOR", -276, MTH_ICU_LAYOUT.LEFT_X, MTH_ICU_LAYOUT.LEFT_DROPDOWN_X)
local toggleAnchorButton = CreateFrame("Button", "MetaHuntOptionsICUToggleAnchorButton", container, "UIPanelButtonTemplate")
toggleAnchorButton:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_ICU_LAYOUT.LEFT_X, -302)
toggleAnchorButton:SetWidth(116)
toggleAnchorButton:SetHeight(22)
toggleAnchorButton:SetText("Toggle Anchor")
toggleAnchorButton:SetScript("OnClick", function()
if type(ICU_ToggleAnchor) == "function" then
ICU_ToggleAnchor()
end
end)
MTH_ICU_OPT_STATE.controls.customAnchorButton = toggleAnchorButton
local expandUp = MTH_CreateCheckbox(container, "MetaHuntOptionsICUExpandUp", "Expand Up", -301, MTH_ICU_LAYOUT.LEFT_X + 132)
if expandUp then
expandUp:SetScript("OnClick", function()
if not this then return end
local store = MTH_ICU_GetStore()
store.EXPAND_UP = this:GetChecked() == 1 and true or false
if type(ICU_SetPoints) == "function" then
ICU_SetPoints()
end
end)
MTH_ICU_OPT_STATE.controls.expandUp = expandUp
end
local showGuild = MTH_CreateCheckbox(container, "MetaHuntOptionsICUShowGuild", "Show player guild names", -344, MTH_ICU_LAYOUT.LEFT_X)
if showGuild then
showGuild:SetScript("OnClick", function()
if not this then return end
local store = MTH_ICU_GetStore()
store.SHOW_GUILD_NAME = this:GetChecked() == 1 and true or false
end)
MTH_ICU_OPT_STATE.controls.showGuildName = showGuild
end
local showClass = MTH_CreateCheckbox(container, "MetaHuntOptionsICUShowClass", "Show player class", -368, MTH_ICU_LAYOUT.LEFT_X)
if showClass then
showClass:SetScript("OnClick", function()
if not this then return end
local store = MTH_ICU_GetStore()
store.SHOW_PLAYER_CLASS = this:GetChecked() == 1 and true or false
end)
MTH_ICU_OPT_STATE.controls.showPlayerClass = showClass
end
local showRace = MTH_CreateCheckbox(container, "MetaHuntOptionsICUShowRace", "Show player race", -392, MTH_ICU_LAYOUT.LEFT_X)
if showRace then
showRace:SetScript("OnClick", function()
if not this then return end
local store = MTH_ICU_GetStore()
store.SHOW_PLAYER_RACE = this:GetChecked() == 1 and true or false
end)
MTH_ICU_OPT_STATE.controls.showPlayerRace = showRace
end
local showTitles = MTH_CreateCheckbox(container, "MetaHuntOptionsICUShowTitles", "Show custom titles in alerts", -416, MTH_ICU_LAYOUT.LEFT_X)
if showTitles then
showTitles:SetScript("OnClick", function()
if not this then return end
local store = MTH_ICU_GetStore()
store.SHOW_CUSTOM_TITLES = this:GetChecked() == 1 and true or false
end)
MTH_ICU_OPT_STATE.controls.showCustomTitles = showTitles
end
local rightHeader = container:CreateFontString("MetaHuntOptionsICURightHeader", "ARTWORK", "GameFontHighlight")
rightHeader:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_ICU_LAYOUT.RIGHT_X, -146)
rightHeader:SetText("Background Colors")
MTH_ICU_CreateOptionRow(container, "MetaHuntOptionsICUPlayerColorMode", "Player colors", "PLAYER_COLOR_MODE", -172, MTH_ICU_LAYOUT.RIGHT_X, MTH_ICU_LAYOUT.RIGHT_DROPDOWN_X)
local reactionOnlyPvp = MTH_CreateCheckbox(container, "MetaHuntOptionsICUReactionOnlyPvp", "Reaction only when PvP-flagged", -200, MTH_ICU_LAYOUT.RIGHT_X)
if reactionOnlyPvp then
reactionOnlyPvp:SetScript("OnClick", function()
if not this then return end
local store = MTH_ICU_GetStore()
store.REACTION_ONLY_PVP_PLAYERS = this:GetChecked() == 1 and true or false
end)
MTH_ICU_OPT_STATE.controls.reactionOnlyPvp = reactionOnlyPvp
end
local colorHeader = container:CreateFontString("MetaHuntOptionsICUColorsHeader", "ARTWORK", "GameFontHighlight")
colorHeader:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_ICU_LAYOUT.RIGHT_X, -224)
local colorScope = container:CreateFontString("MetaHuntOptionsICUColorsScope", "ARTWORK", "GameFontNormalSmall")
colorScope:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_ICU_LAYOUT.RIGHT_X, -242)
colorScope:SetWidth(250)
colorScope:SetJustifyH("LEFT")
colorScope:SetJustifyV("TOP")
colorScope:SetTextColor(0.35, 0.65, 1)
colorScope:SetText("Player pickers: REACTION / FACTION / CUSTOM\nNPC pickers: always")
local colorY = -284
for i = 1, table.getn(MTH_ICU_COLOR_ROWS) do
local row = MTH_ICU_COLOR_ROWS[i]
MTH_ICU_CreateColorRow(container, "MetaHuntOptionsICUColor" .. tostring(i), row.label, row.key, colorY, MTH_ICU_LAYOUT.RIGHT_X, MTH_ICU_LAYOUT.COLOR_BUTTON_X)
colorY = colorY - MTH_ICU_LAYOUT.COLOR_ROW_STEP
end
end
function MTH_RefreshICUOptions()
if not MTH_ICU_OPT_READY then return end
local controls = MTH_ICU_OPT_STATE.controls
if type(controls) ~= "table" then
return
end
local store = MTH_ICU_GetStore()
local moduleEnabled = MTH and MTH.IsModuleEnabled and MTH:IsModuleEnabled("icu", false) or false
if controls.moduleEnabled then
controls.moduleEnabled:SetChecked(moduleEnabled and 1 or nil)
end
if controls.mouseOver then
controls.mouseOver:SetChecked(store.mouseOver and 1 or nil)
if controls.mouseOver.Enable then
if moduleEnabled then controls.mouseOver:Enable() else controls.mouseOver:Disable() end
end
end
if controls.showGuildName then
controls.showGuildName:SetChecked(store.SHOW_GUILD_NAME and 1 or nil)
if controls.showGuildName.Enable then
if moduleEnabled then controls.showGuildName:Enable() else controls.showGuildName:Disable() end
end
end
if controls.showPlayerClass then
controls.showPlayerClass:SetChecked(store.SHOW_PLAYER_CLASS and 1 or nil)
if controls.showPlayerClass.Enable then
if moduleEnabled then controls.showPlayerClass:Enable() else controls.showPlayerClass:Disable() end
end
end
if controls.showPlayerRace then
controls.showPlayerRace:SetChecked(store.SHOW_PLAYER_RACE and 1 or nil)
if controls.showPlayerRace.Enable then
if moduleEnabled then controls.showPlayerRace:Enable() else controls.showPlayerRace:Disable() end
end
end
if controls.showCustomTitles then
controls.showCustomTitles:SetChecked(store.SHOW_CUSTOM_TITLES and 1 or nil)
if controls.showCustomTitles.Enable then
if moduleEnabled then controls.showCustomTitles:Enable() else controls.showCustomTitles:Disable() end
end
end
local isCustomAnchor = tostring(store.ANCHOR or "") == "CUSTOM"
if controls.customAnchorButton then
if moduleEnabled and isCustomAnchor then
controls.customAnchorButton:Show()
if controls.customAnchorButton.Enable then controls.customAnchorButton:Enable() end
else
controls.customAnchorButton:Hide()
end
end
if controls.expandUp then
controls.expandUp:SetChecked(store.EXPAND_UP and 1 or nil)
if moduleEnabled and isCustomAnchor then
controls.expandUp:Show()
if controls.expandUp.Enable then controls.expandUp:Enable() end
else
controls.expandUp:Hide()
end
end
local optionKeys = { "ALERT", "ANNOUNCE", "ANCHOR", "HEALTH_TEXT_MODE", "POPUP_HIDE_DELAY", "PLAYER_COLOR_MODE" }
for i = 1, table.getn(optionKeys) do
local key = optionKeys[i]
local row = controls[key]
if row and row.dropdown then
MTH_ICU_DropdownSetText(row.dropdown, tostring(store[key] or ""))
if UIDropDownMenu_EnableDropDown and UIDropDownMenu_DisableDropDown then
if moduleEnabled then
UIDropDownMenu_EnableDropDown(row.dropdown)
else
UIDropDownMenu_DisableDropDown(row.dropdown)
end
end
end
end
if controls.reactionOnlyPvp then
controls.reactionOnlyPvp:SetChecked(store.REACTION_ONLY_PVP_PLAYERS and 1 or nil)
if controls.reactionOnlyPvp.Enable then
if moduleEnabled and tostring(store.PLAYER_COLOR_MODE or "") == "REACTION" then
controls.reactionOnlyPvp:Enable()
else
controls.reactionOnlyPvp:Disable()
end
end
end
for i = 1, table.getn(MTH_ICU_COLOR_ROWS) do
local row = MTH_ICU_COLOR_ROWS[i]
local ctrl = controls[row.key]
if ctrl and ctrl.swatch then
local r, g, b = MTH_ICU_GetColor(row.key)
ctrl.swatch:SetVertexColor(r, g, b)
if ctrl.button and ctrl.button.Enable then
if moduleEnabled then ctrl.button:Enable() else ctrl.button:Disable() end
end
end
end
end
function MTH_SetupICUOptions()
local container = MTH_GetFrame("MetaHuntOptionsICU")
if not container then return end
if not MTH_ICU_OPT_READY then
if type(MTH_ClearContainer) == "function" then
MTH_ClearContainer(container)
end
local title = container:CreateFontString("MetaHuntOptionsICUErrorTitle", "ARTWORK", "GameFontHighlight")
title:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -10)
title:SetText("MTH ICU")
local body = container:CreateFontString("MetaHuntOptionsICUErrorBody", "ARTWORK", "GameFontNormalSmall")
body:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -34)
body:SetWidth(620)
body:SetJustifyH("LEFT")
body:SetJustifyV("TOP")
body:SetTextColor(1, 0.3, 0.3)
body:SetText("ICU options cannot initialize. Missing dependencies: " .. table.concat(MTH_ICU_OPT_MISSING, ", "))
return
end
local ok, err = pcall(function()
MTH_ICU_BuildUI(container)
MTH_RefreshICUOptions()
end)
if not ok then
if MTH and MTH.Print then
MTH:Print("[MTH ICU OPTIONS] setup failed: " .. tostring(err), "error")
end
if type(MTH_ClearContainer) == "function" then
MTH_ClearContainer(container)
end
local title = container:CreateFontString("MetaHuntOptionsICUCrashTitle", "ARTWORK", "GameFontHighlight")
title:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -10)
title:SetText("MTH ICU")
local body = container:CreateFontString("MetaHuntOptionsICUCrashBody", "ARTWORK", "GameFontNormalSmall")
body:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -34)
body:SetWidth(620)
body:SetJustifyH("LEFT")
body:SetJustifyV("TOP")
body:SetTextColor(1, 0.3, 0.3)
body:SetText("ICU options failed to render. Check chat/debug for details.")
end
end
+15
View File
@@ -195,6 +195,21 @@ function MTH_SelectOptionsTab(tabKey)
else else
MTH_SetupAutoBuyOptions() MTH_SetupAutoBuyOptions()
end end
elseif tabKey == "AutoQuest" then
if type(MTH_SetupAutoQuestOptions) == "function" then
MTH_SetupAutoQuestOptions()
MTH_OPTIONS_SETUP["AutoQuest"] = true
end
elseif tabKey == "ICU" then
if type(MTH_SetupICUOptions) == "function" then
MTH_SetupICUOptions()
MTH_OPTIONS_SETUP["ICU"] = true
if type(MTH_RefreshICUOptions) == "function" then
MTH_RefreshICUOptions()
end
elseif MTH and MTH.Print then
MTH:Print("ICU options setup function is not loaded", "error")
end
elseif tabKey == "Credits" then elseif tabKey == "Credits" then
local setupCredits = _G and _G["MTH_SetupCreditsOptions"] local setupCredits = _G and _G["MTH_SetupCreditsOptions"]
if type(setupCredits) == "function" then if type(setupCredits) == "function" then
+4
View File
@@ -41,6 +41,8 @@ MTH_OPTIONS_TABS = MTH_OPTIONS_TABS or {
{ key = "SmartAmmo", label = "Smart Ammo", frame = "MetaHuntOptionsSmartAmmo" }, { key = "SmartAmmo", label = "Smart Ammo", frame = "MetaHuntOptionsSmartAmmo" },
{ key = "FeedOMatic", label = "FeedOMatic", frame = "MetaHuntOptionsFeedOMatic" }, { key = "FeedOMatic", label = "FeedOMatic", frame = "MetaHuntOptionsFeedOMatic" },
{ key = "AutoBuy", label = "Auto Buy", frame = "MetaHuntOptionsAutoBuy" }, { key = "AutoBuy", label = "Auto Buy", frame = "MetaHuntOptionsAutoBuy" },
{ key = "AutoQuest", label = "Auto Quest", frame = "MetaHuntOptionsAutoQuest" },
{ key = "ICU", label = "ICU", frame = "MetaHuntOptionsICU" },
{ key = "ChronometerGeneral", label = "General", frame = "MetaHuntOptionsChronometer" }, { key = "ChronometerGeneral", label = "General", frame = "MetaHuntOptionsChronometer" },
{ key = "ChronometerBar", label = "Bar", frame = "MetaHuntOptionsChronometer" }, { key = "ChronometerBar", label = "Bar", frame = "MetaHuntOptionsChronometer" },
{ key = "ChronometerClassSpells", label = "Hunter Spells", frame = "MetaHuntOptionsChronometer" }, { key = "ChronometerClassSpells", label = "Hunter Spells", frame = "MetaHuntOptionsChronometer" },
@@ -53,7 +55,9 @@ MTH_OPTIONS_TREE = MTH_OPTIONS_TREE or {
{ label = "General", key = "General" }, { label = "General", key = "General" },
{ label = "Messages", key = "Messages" }, { label = "Messages", key = "Messages" },
{ label = "Auto Buy", key = "AutoBuy" }, { label = "Auto Buy", key = "AutoBuy" },
{ label = "Auto Quest", key = "AutoQuest" },
{ label = "Feed-O-Matic", key = "FeedOMatic" }, { label = "Feed-O-Matic", key = "FeedOMatic" },
{ label = "ICU", key = "ICU" },
{ {
label = "zButtons", label = "zButtons",
node = "zButtons", node = "zButtons",
+185 -123
View File
@@ -21,6 +21,14 @@ local function MTH_ZB_RefreshTab(tabName)
end end
end end
local function MTH_ZB_IsChecked(control)
if not control or type(control.GetChecked) ~= "function" then
return false
end
local checked = control:GetChecked()
return checked == 1 or checked == true
end
local function MTH_RebuildSpellOrder(buttonName, buttonObj, itemList, maxButtons) local function MTH_RebuildSpellOrder(buttonName, buttonObj, itemList, maxButtons)
if not (buttonName and buttonObj and itemList and maxButtons) then return end if not (buttonName and buttonObj and itemList and maxButtons) then return end
local info = {} local info = {}
@@ -187,15 +195,15 @@ local function MTH_EnsureAmmoOptionsWatcher()
if MTH_AmmoOptionsWatcher then if MTH_AmmoOptionsWatcher then
return return
end end
MTH_AmmoOptionsWatcher = CreateFrame("Frame", "MTHAmmoOptionsWatcherFrame") MTH_AmmoOptionsWatcher = CreateFrame("Frame", "MTH_AmmoOptionsWatcher")
if not MTH_AmmoOptionsWatcher then if not MTH_AmmoOptionsWatcher then
return return
end end
MTH_AmmoOptionsWatcher:RegisterEvent("UNIT_INVENTORY_CHANGED") MTH_AmmoOptionsWatcher:RegisterEvent("UNIT_INVENTORY_CHANGED")
MTH_AmmoOptionsWatcher:RegisterEvent("BAG_UPDATE") MTH_AmmoOptionsWatcher:RegisterEvent("BAG_UPDATE")
MTH_AmmoOptionsWatcher:SetScript("OnEvent", function(_, eventName, unit) MTH_AmmoOptionsWatcher:SetScript("OnEvent", function()
eventName = eventName or event local eventName = event
unit = unit or arg1 local unit = arg1
if eventName == "UNIT_INVENTORY_CHANGED" and unit and unit ~= "player" then if eventName == "UNIT_INVENTORY_CHANGED" and unit and unit ~= "player" then
return return
end end
@@ -239,6 +247,16 @@ local function MTH_ZB_EnsureButtonOptionDefaults(buttonName)
end end
saved["children"]["hideonclick"] = saved["children"]["hideonclick"] and true or false saved["children"]["hideonclick"] = saved["children"]["hideonclick"] and true or false
if saved["children"]["expandonhover"] == nil then
saved["children"]["expandonhover"] = false
end
saved["children"]["expandonhover"] = saved["children"]["expandonhover"] and true or false
if saved["children"]["fadetimer"] == nil then
saved["children"]["fadetimer"] = 0
end
saved["children"]["fadetimer"] = tonumber(saved["children"]["fadetimer"]) or 0
if type(saved["parent"]) ~= "table" then if type(saved["parent"]) ~= "table" then
saved["parent"] = {} saved["parent"] = {}
end end
@@ -325,16 +343,15 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
enableButton:SetChecked(enabledValue and true or false) enableButton:SetChecked(enabledValue and true or false)
enableButton.buttonName = buttonName enableButton.buttonName = buttonName
enableButton.buttonObj = buttonObj enableButton.buttonObj = buttonObj
enableButton:SetScript("OnClick", function(self) enableButton:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end local checked = MTH_ZB_IsChecked(this)
local checked = self:GetChecked() and true or false MTH_SetButtonEnabledState(this.buttonName, this.buttonObj, checked)
MTH_SetButtonEnabledState(self.buttonName, self.buttonObj, checked)
end) end)
end end
local parentSection = MTH_ZB_EnsureSection(containerName.."ParentSection", MTH_ZB_L("ZB_SECTION_PARENT_BUTTON", "Parent Button"), -52, 116) local parentSection = MTH_ZB_EnsureSection(containerName.."ParentSection", MTH_ZB_L("ZB_SECTION_PARENT_BUTTON", "Parent Button"), -52, 116)
local childrenSection = MTH_ZB_EnsureSection(containerName.."ChildrenSection", MTH_ZB_L("ZB_SECTION_CHILDREN_BUTTONS", "Children Buttons"), -184, 235) local childrenSection = MTH_ZB_EnsureSection(containerName.."ChildrenSection", MTH_ZB_L("ZB_SECTION_CHILDREN_BUTTONS", "Children Buttons"), -184, 310)
local parentYOffset = -18 local parentYOffset = -18
local childrenYOffset = -18 local childrenYOffset = -18
@@ -384,16 +401,15 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
expandLeft:SetChecked(saved["firstbutton"] == "LEFT") expandLeft:SetChecked(saved["firstbutton"] == "LEFT")
expandLeft.buttonName = buttonName expandLeft.buttonName = buttonName
expandLeft.buttonObj = buttonObj expandLeft.buttonObj = buttonObj
expandLeft:SetScript("OnClick", function(self) expandLeft:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end local checked = MTH_ZB_IsChecked(this)
local checked = self:GetChecked() and true or false local btnName = this.buttonName
local btnName = self.buttonName
if not btnName or not (ZHunterMod_Saved and ZHunterMod_Saved[btnName]) then return end if not btnName or not (ZHunterMod_Saved and ZHunterMod_Saved[btnName]) then return end
ZHunterMod_Saved[btnName]["firstbutton"] = checked and "LEFT" or "RIGHT" ZHunterMod_Saved[btnName]["firstbutton"] = checked and "LEFT" or "RIGHT"
ZHunterMod_Saved[btnName]["horizontal"] = checked and 1 or nil ZHunterMod_Saved[btnName]["horizontal"] = checked and 1 or nil
ZHunterMod_Saved[btnName]["vertical"] = checked and 1 or nil ZHunterMod_Saved[btnName]["vertical"] = checked and 1 or nil
MTH_RefreshButtonGeometry(btnName, self.buttonObj) MTH_RefreshButtonGeometry(btnName, this.buttonObj)
end) end)
end end
childrenYOffset = childrenYOffset - 30 childrenYOffset = childrenYOffset - 30
@@ -406,17 +422,64 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
if hideClick.buttonObj then if hideClick.buttonObj then
hideClick.buttonObj.hideonclick = saved["children"]["hideonclick"] and true or false hideClick.buttonObj.hideonclick = saved["children"]["hideonclick"] and true or false
end end
hideClick:SetScript("OnClick", function(self) hideClick:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end local checked = MTH_ZB_IsChecked(this)
local checked = self:GetChecked() and true or false ZHunterMod_Saved[this.buttonName]["children"]["hideonclick"] = checked
ZHunterMod_Saved[self.buttonName]["children"]["hideonclick"] = checked local btnObj = this.buttonObj or getglobal(this.buttonName)
local btnObj = self.buttonObj or getglobal(self.buttonName)
if btnObj then btnObj.hideonclick = checked end if btnObj then btnObj.hideonclick = checked end
end) end)
end end
childrenYOffset = childrenYOffset - 25 childrenYOffset = childrenYOffset - 25
local expandOnHover = MTH_CreateCheckbox(childrenSection or container, containerName.."ExpandOnHover", MTH_ZB_L("ZB_LABEL_EXPAND_ON_HOVER", "Expand on Hover"), childrenYOffset)
if expandOnHover then
expandOnHover:SetChecked(saved["children"]["expandonhover"])
expandOnHover.buttonName = buttonName
expandOnHover.buttonObj = buttonObj
expandOnHover:SetScript("OnClick", function()
if not this then return end
local checked = MTH_ZB_IsChecked(this)
local btnName = this.buttonName
if not btnName or not (ZHunterMod_Saved and ZHunterMod_Saved[btnName]) then return end
if not ZHunterMod_Saved[btnName]["children"] then
ZHunterMod_Saved[btnName]["children"] = {}
end
ZHunterMod_Saved[btnName]["children"]["expandonhover"] = checked
local btnObj = this.buttonObj or getglobal(btnName)
if btnObj then btnObj.expandonhover = checked end
end)
end
childrenYOffset = childrenYOffset - 40
local fadeTimer = MTH_CreateSlider(childrenSection or container, containerName.."FadeTimer", MTH_ZB_L("ZB_LABEL_AUTO_HIDE_TIMER", "Auto-Hide Timer (seconds)"), 0, 10, 1, childrenYOffset)
if fadeTimer then
fadeTimer:SetWidth(leftWidth - 40)
fadeTimer:SetValue(saved["children"]["fadetimer"] or 0)
fadeTimer.buttonName = buttonName
fadeTimer.buttonObj = buttonObj
fadeTimer.onChange = function(val, slider)
local frame = slider or fadeTimer
local btnName = frame and frame.buttonName
if not btnName or not (ZHunterMod_Saved and ZHunterMod_Saved[btnName]) then return end
if not ZHunterMod_Saved[btnName]["children"] then
ZHunterMod_Saved[btnName]["children"] = {}
end
local secs = math.floor((val or 0) + 0.5)
ZHunterMod_Saved[btnName]["children"]["fadetimer"] = secs
local btnObj = frame.buttonObj or getglobal(btnName)
if btnObj then
btnObj.fadetimer = secs
if secs <= 0 then
ZSpellButton_StopFadeTimer(btnObj)
elseif btnObj.children and btnObj.children:IsVisible() then
ZSpellButton_StartFadeTimer(btnObj)
end
end
end
end
childrenYOffset = childrenYOffset - 50
local showTooltip = MTH_CreateCheckbox(childrenSection or container, containerName.."ShowTooltip", MTH_ZB_L("ZB_LABEL_SHOW_TOOLTIP", "Show Tooltip"), childrenYOffset) local showTooltip = MTH_CreateCheckbox(childrenSection or container, containerName.."ShowTooltip", MTH_ZB_L("ZB_LABEL_SHOW_TOOLTIP", "Show Tooltip"), childrenYOffset)
if showTooltip then if showTooltip then
showTooltip:SetChecked(saved["tooltip"]) showTooltip:SetChecked(saved["tooltip"])
@@ -425,12 +488,11 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
if showTooltip.buttonObj then if showTooltip.buttonObj then
showTooltip.buttonObj.tooltip = saved["tooltip"] and true or false showTooltip.buttonObj.tooltip = saved["tooltip"] and true or false
end end
showTooltip:SetScript("OnClick", function(self) showTooltip:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end local checked = MTH_ZB_IsChecked(this)
local checked = self:GetChecked() and true or false ZHunterMod_Saved[this.buttonName]["tooltip"] = checked
ZHunterMod_Saved[self.buttonName]["tooltip"] = checked local btnObj = this.buttonObj or getglobal(this.buttonName)
local btnObj = self.buttonObj or getglobal(self.buttonName)
if btnObj then btnObj.tooltip = checked end if btnObj then btnObj.tooltip = checked end
end) end)
end end
@@ -443,13 +505,12 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
showAmmoName.buttonName = buttonName showAmmoName.buttonName = buttonName
showAmmoName.buttonObj = buttonObj showAmmoName.buttonObj = buttonObj
showAmmoName.maxButtons = maxButtons showAmmoName.maxButtons = maxButtons
showAmmoName:SetScript("OnClick", function(self) showAmmoName:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end local checked = MTH_ZB_IsChecked(this)
local checked = self:GetChecked() and true or false local btnName = this.buttonName
local btnName = self.buttonName
ZHunterMod_Saved[btnName]["showammoname"] = checked ZHunterMod_Saved[btnName]["showammoname"] = checked
local btnObj = self.buttonObj or getglobal(btnName) local btnObj = this.buttonObj or getglobal(btnName)
if btnObj then if btnObj then
for i = 1, (btnObj.count or 0) do for i = 1, (btnObj.count or 0) do
local child = getglobal(btnName..i) local child = getglobal(btnName..i)
@@ -498,13 +559,12 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
hideButton:SetChecked(saved["parent"]["hide"]) hideButton:SetChecked(saved["parent"]["hide"])
hideButton.buttonName = buttonName hideButton.buttonName = buttonName
hideButton.buttonObj = buttonObj hideButton.buttonObj = buttonObj
hideButton:SetScript("OnClick", function(self) hideButton:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end local checked = this:GetChecked() == 1
local checked = self:GetChecked() == 1 ZHunterMod_Saved[this.buttonName]["parent"]["hide"] = checked
ZHunterMod_Saved[self.buttonName]["parent"]["hide"] = checked if this.buttonObj then
if self.buttonObj then if checked then this.buttonObj:Hide() else this.buttonObj:Show() end
if checked then self.buttonObj:Hide() else self.buttonObj:Show() end
end end
end) end)
end end
@@ -515,13 +575,12 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
useCircle:SetChecked(saved["parent"]["circle"]) useCircle:SetChecked(saved["parent"]["circle"])
useCircle.buttonName = buttonName useCircle.buttonName = buttonName
useCircle.buttonObj = buttonObj useCircle.buttonObj = buttonObj
useCircle:SetScript("OnClick", function(self) useCircle:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end local checked = this:GetChecked() == 1
local checked = self:GetChecked() == 1 ZHunterMod_Saved[this.buttonName]["parent"]["circle"] = checked
ZHunterMod_Saved[self.buttonName]["parent"]["circle"] = checked if this.buttonObj and this.buttonObj.circle then
if self.buttonObj and self.buttonObj.circle then if checked then this.buttonObj.circle:Show() else this.buttonObj.circle:Hide() end
if checked then self.buttonObj.circle:Show() else self.buttonObj.circle:Hide() end
end end
end) end)
end end
@@ -579,17 +638,16 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
showText:SetText("") showText:SetText("")
end end
showToggle:SetChecked(ZHunterMod_Saved[buttonName]["visible"][showToggle.spellIndex] ~= false) showToggle:SetChecked(ZHunterMod_Saved[buttonName]["visible"][showToggle.spellIndex] ~= false)
showToggle:SetScript("OnClick", function(self) showToggle:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end local checked = this:GetChecked() == 1
local checked = self:GetChecked() == 1 local btnName = this.buttonName
local btnName = self.buttonName local visibleIndex = this.spellIndex
local visibleIndex = self.spellIndex
if not ZHunterMod_Saved[btnName]["visible"] then if not ZHunterMod_Saved[btnName]["visible"] then
ZHunterMod_Saved[btnName]["visible"] = {} ZHunterMod_Saved[btnName]["visible"] = {}
end end
ZHunterMod_Saved[btnName]["visible"][visibleIndex] = checked ZHunterMod_Saved[btnName]["visible"][visibleIndex] = checked
MTH_RefreshButtonLayout(btnName, self.buttonObj, self.itemList, self.maxButtons) MTH_RefreshButtonLayout(btnName, this.buttonObj, this.itemList, this.maxButtons)
end) end)
end end
@@ -604,18 +662,17 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
downBtn.buttonObj = buttonObj downBtn.buttonObj = buttonObj
downBtn.itemList = itemList downBtn.itemList = itemList
downBtn.maxButtons = maxButtons downBtn.maxButtons = maxButtons
downBtn:SetScript("OnClick", function(self) downBtn:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end local idx = this.spellIndex
local idx = self.spellIndex local btnName = this.buttonName
local btnName = self.buttonName local contName = this.containerName
local contName = self.containerName local maxBtns = this.maxButtons
local maxBtns = self.maxButtons
if idx < maxBtns then if idx < maxBtns then
local temp = ZHunterMod_Saved[btnName]["spells"][idx+1] local temp = ZHunterMod_Saved[btnName]["spells"][idx+1]
ZHunterMod_Saved[btnName]["spells"][idx+1] = ZHunterMod_Saved[btnName]["spells"][idx] ZHunterMod_Saved[btnName]["spells"][idx+1] = ZHunterMod_Saved[btnName]["spells"][idx]
ZHunterMod_Saved[btnName]["spells"][idx] = temp ZHunterMod_Saved[btnName]["spells"][idx] = temp
MTH_RebuildSpellOrder(btnName, self.buttonObj, self.itemList, self.maxButtons) MTH_RebuildSpellOrder(btnName, this.buttonObj, this.itemList, this.maxButtons)
local tabName = gsub(contName, "MetaHuntOptions", "") local tabName = gsub(contName, "MetaHuntOptions", "")
MTH_ZB_RefreshTab(tabName) MTH_ZB_RefreshTab(tabName)
end end
@@ -632,17 +689,16 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
upBtn.buttonObj = buttonObj upBtn.buttonObj = buttonObj
upBtn.itemList = itemList upBtn.itemList = itemList
upBtn.maxButtons = maxButtons upBtn.maxButtons = maxButtons
upBtn:SetScript("OnClick", function(self) upBtn:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end local idx = this.spellIndex
local idx = self.spellIndex local btnName = this.buttonName
local btnName = self.buttonName local contName = this.containerName
local contName = self.containerName
if idx > 1 then if idx > 1 then
local temp = ZHunterMod_Saved[btnName]["spells"][idx-1] local temp = ZHunterMod_Saved[btnName]["spells"][idx-1]
ZHunterMod_Saved[btnName]["spells"][idx-1] = ZHunterMod_Saved[btnName]["spells"][idx] ZHunterMod_Saved[btnName]["spells"][idx-1] = ZHunterMod_Saved[btnName]["spells"][idx]
ZHunterMod_Saved[btnName]["spells"][idx] = temp ZHunterMod_Saved[btnName]["spells"][idx] = temp
MTH_RebuildSpellOrder(btnName, self.buttonObj, self.itemList, self.maxButtons) MTH_RebuildSpellOrder(btnName, this.buttonObj, this.itemList, this.maxButtons)
local tabName = gsub(contName, "MetaHuntOptions", "") local tabName = gsub(contName, "MetaHuntOptions", "")
MTH_ZB_RefreshTab(tabName) MTH_ZB_RefreshTab(tabName)
end end
@@ -741,11 +797,10 @@ function MTH_SetupSmartAmmoOptions()
end end
if moduleToggle then if moduleToggle then
moduleToggle:SetChecked(moduleEnabled) moduleToggle:SetChecked(moduleEnabled)
moduleToggle:SetScript("OnClick", function(self) moduleToggle:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end
if MTH and MTH.SetModuleEnabled then if MTH and MTH.SetModuleEnabled then
MTH:SetModuleEnabled("smartammo", self:GetChecked() and true or false) MTH:SetModuleEnabled("smartammo", MTH_ZB_IsChecked(this))
end end
MTH_SetupSmartAmmoOptions() MTH_SetupSmartAmmoOptions()
end) end)
@@ -758,11 +813,10 @@ function MTH_SetupSmartAmmoOptions()
if not moduleEnabled then if not moduleEnabled then
smartToggle:Disable() smartToggle:Disable()
end end
smartToggle:SetScript("OnClick", function(self) smartToggle:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end
if type(MTHSmartAmmo_SetSmartEnabled) == "function" then if type(MTHSmartAmmo_SetSmartEnabled) == "function" then
MTHSmartAmmo_SetSmartEnabled(self:GetChecked() and 1 or nil) MTHSmartAmmo_SetSmartEnabled(MTH_ZB_IsChecked(this) and 1 or nil)
end end
end) end)
end end
@@ -777,11 +831,10 @@ function MTH_SetupSmartAmmoOptions()
if not moduleEnabled then if not moduleEnabled then
reloadToggle:Disable() reloadToggle:Disable()
end end
reloadToggle:SetScript("OnClick", function(self) reloadToggle:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end
if type(MTHSmartAmmo_SetReloadEnabled) == "function" then if type(MTHSmartAmmo_SetReloadEnabled) == "function" then
MTHSmartAmmo_SetReloadEnabled(self:GetChecked() and 1 or nil) MTHSmartAmmo_SetReloadEnabled(MTH_ZB_IsChecked(this) and 1 or nil)
end end
end) end)
end end
@@ -817,11 +870,10 @@ function MTH_SetupMessagesOptions()
local initModulesToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesInitModules", "Init : modules loaded", -36) local initModulesToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesInitModules", "Init : modules loaded", -36)
if initModulesToggle then if initModulesToggle then
initModulesToggle:SetChecked(msgSettings.initModulesLoaded and true or false) initModulesToggle:SetChecked(msgSettings.initModulesLoaded and true or false)
initModulesToggle:SetScript("OnClick", function(self) initModulesToggle:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end
if MTH and MTH.SetMessageEnabled then if MTH and MTH.SetMessageEnabled then
MTH:SetMessageEnabled("initModulesLoaded", self:GetChecked() and true or false) MTH:SetMessageEnabled("initModulesLoaded", MTH_ZB_IsChecked(this))
end end
end) end)
end end
@@ -829,11 +881,10 @@ function MTH_SetupMessagesOptions()
local initWelcomeToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesInitWelcome", "Init : Sarcastic welcome message", -64) local initWelcomeToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesInitWelcome", "Init : Sarcastic welcome message", -64)
if initWelcomeToggle then if initWelcomeToggle then
initWelcomeToggle:SetChecked(msgSettings.initSarcasticWelcome ~= false) initWelcomeToggle:SetChecked(msgSettings.initSarcasticWelcome ~= false)
initWelcomeToggle:SetScript("OnClick", function(self) initWelcomeToggle:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end
if MTH and MTH.SetMessageEnabled then if MTH and MTH.SetMessageEnabled then
MTH:SetMessageEnabled("initSarcasticWelcome", self:GetChecked() and true or false) MTH:SetMessageEnabled("initSarcasticWelcome", MTH_ZB_IsChecked(this))
end end
end) end)
end end
@@ -841,11 +892,10 @@ function MTH_SetupMessagesOptions()
local petHungryToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesPetHungry", "Pet is hungry (spam)", -92) local petHungryToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesPetHungry", "Pet is hungry (spam)", -92)
if petHungryToggle then if petHungryToggle then
petHungryToggle:SetChecked(msgSettings.petHungry and true or false) petHungryToggle:SetChecked(msgSettings.petHungry and true or false)
petHungryToggle:SetScript("OnClick", function(self) petHungryToggle:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end
if MTH and MTH.SetMessageEnabled then if MTH and MTH.SetMessageEnabled then
MTH:SetMessageEnabled("petHungry", self:GetChecked() and true or false) MTH:SetMessageEnabled("petHungry", MTH_ZB_IsChecked(this))
end end
end) end)
end end
@@ -853,11 +903,10 @@ function MTH_SetupMessagesOptions()
local beastTrainingScanToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesBeastTrainingScan", "Beasttraining scan", -120) local beastTrainingScanToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesBeastTrainingScan", "Beasttraining scan", -120)
if beastTrainingScanToggle then if beastTrainingScanToggle then
beastTrainingScanToggle:SetChecked(msgSettings.beastTrainingScan ~= false) beastTrainingScanToggle:SetChecked(msgSettings.beastTrainingScan ~= false)
beastTrainingScanToggle:SetScript("OnClick", function(self) beastTrainingScanToggle:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end
if MTH and MTH.SetMessageEnabled then if MTH and MTH.SetMessageEnabled then
MTH:SetMessageEnabled("beastTrainingScan", self:GetChecked() and true or false) MTH:SetMessageEnabled("beastTrainingScan", MTH_ZB_IsChecked(this))
end end
end) end)
end end
@@ -865,11 +914,10 @@ function MTH_SetupMessagesOptions()
local spellbookScanToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesSpellbookScan", "Spellbook scan", -148) local spellbookScanToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesSpellbookScan", "Spellbook scan", -148)
if spellbookScanToggle then if spellbookScanToggle then
spellbookScanToggle:SetChecked(msgSettings.spellbookScan and true or false) spellbookScanToggle:SetChecked(msgSettings.spellbookScan and true or false)
spellbookScanToggle:SetScript("OnClick", function(self) spellbookScanToggle:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end
if MTH and MTH.SetMessageEnabled then if MTH and MTH.SetMessageEnabled then
MTH:SetMessageEnabled("spellbookScan", self:GetChecked() and true or false) MTH:SetMessageEnabled("spellbookScan", MTH_ZB_IsChecked(this))
end end
end) end)
end end
@@ -877,11 +925,10 @@ function MTH_SetupMessagesOptions()
local petRanAwayToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesPetRanAway", "Pet ran away", -176) local petRanAwayToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesPetRanAway", "Pet ran away", -176)
if petRanAwayToggle then if petRanAwayToggle then
petRanAwayToggle:SetChecked(msgSettings.petRanAway ~= false) petRanAwayToggle:SetChecked(msgSettings.petRanAway ~= false)
petRanAwayToggle:SetScript("OnClick", function(self) petRanAwayToggle:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end
if MTH and MTH.SetMessageEnabled then if MTH and MTH.SetMessageEnabled then
MTH:SetMessageEnabled("petRanAway", self:GetChecked() and true or false) MTH:SetMessageEnabled("petRanAway", MTH_ZB_IsChecked(this))
end end
end) end)
end end
@@ -889,11 +936,10 @@ function MTH_SetupMessagesOptions()
local mapMarkersToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesMapMarkers", "Map markers", -204) local mapMarkersToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesMapMarkers", "Map markers", -204)
if mapMarkersToggle then if mapMarkersToggle then
mapMarkersToggle:SetChecked(msgSettings.mapMarkers ~= false) mapMarkersToggle:SetChecked(msgSettings.mapMarkers ~= false)
mapMarkersToggle:SetScript("OnClick", function(self) mapMarkersToggle:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end
if MTH and MTH.SetMessageEnabled then if MTH and MTH.SetMessageEnabled then
MTH:SetMessageEnabled("mapMarkers", self:GetChecked() and true or false) MTH:SetMessageEnabled("mapMarkers", MTH_ZB_IsChecked(this))
end end
end) end)
end end
@@ -1002,7 +1048,7 @@ function MTH_SetupGeneralOptions()
local smartModuleToggle = ensureCheckbox(smartAmmoSection, "MetaHuntGeneralSmartAmmoModuleToggle", "Enable module", -10, smartModuleEnabled) local smartModuleToggle = ensureCheckbox(smartAmmoSection, "MetaHuntGeneralSmartAmmoModuleToggle", "Enable module", -10, smartModuleEnabled)
if smartModuleToggle then if smartModuleToggle then
smartModuleToggle:SetScript("OnClick", function() smartModuleToggle:SetScript("OnClick", function()
local enabled = this:GetChecked() and true or false local enabled = MTH_ZB_IsChecked(this)
if MTH and MTH.SetModuleEnabled then if MTH and MTH.SetModuleEnabled then
local ok = MTH:SetModuleEnabled("smartammo", enabled) local ok = MTH:SetModuleEnabled("smartammo", enabled)
if not ok then if not ok then
@@ -1031,7 +1077,7 @@ function MTH_SetupGeneralOptions()
end end
smartToggle:SetScript("OnClick", function() smartToggle:SetScript("OnClick", function()
if type(MTHSmartAmmo_SetSmartEnabled) == "function" then if type(MTHSmartAmmo_SetSmartEnabled) == "function" then
MTHSmartAmmo_SetSmartEnabled(this:GetChecked() and 1 or nil) MTHSmartAmmo_SetSmartEnabled(MTH_ZB_IsChecked(this) and 1 or nil)
end end
end) end)
end end
@@ -1045,7 +1091,7 @@ function MTH_SetupGeneralOptions()
end end
reloadToggle:SetScript("OnClick", function() reloadToggle:SetScript("OnClick", function()
if type(MTHSmartAmmo_SetReloadEnabled) == "function" then if type(MTHSmartAmmo_SetReloadEnabled) == "function" then
MTHSmartAmmo_SetReloadEnabled(this:GetChecked() and 1 or nil) MTHSmartAmmo_SetReloadEnabled(MTH_ZB_IsChecked(this) and 1 or nil)
end end
end) end)
end end
@@ -1059,7 +1105,7 @@ function MTH_SetupGeneralOptions()
end end
weaponSwapToggle:SetScript("OnClick", function() weaponSwapToggle:SetScript("OnClick", function()
if type(MTHSmartAmmo_SetWeaponSwapEnabled) == "function" then if type(MTHSmartAmmo_SetWeaponSwapEnabled) == "function" then
MTHSmartAmmo_SetWeaponSwapEnabled(this:GetChecked() and 1 or nil) MTHSmartAmmo_SetWeaponSwapEnabled(MTH_ZB_IsChecked(this) and 1 or nil)
end end
end) end)
end end
@@ -1072,7 +1118,7 @@ function MTH_SetupGeneralOptions()
if autoStripToggle then if autoStripToggle then
autoStripToggle:SetScript("OnClick", function() autoStripToggle:SetScript("OnClick", function()
if type(AutoStrip_SetAutoStripToggle) == "function" then if type(AutoStrip_SetAutoStripToggle) == "function" then
AutoStrip_SetAutoStripToggle(this:GetChecked()) AutoStrip_SetAutoStripToggle(MTH_ZB_IsChecked(this))
end end
end) end)
end end
@@ -1081,7 +1127,7 @@ function MTH_SetupGeneralOptions()
if displayToggle then if displayToggle then
displayToggle:SetScript("OnClick", function() displayToggle:SetScript("OnClick", function()
if type(AutoStrip_SetDisplayToggle) == "function" then if type(AutoStrip_SetDisplayToggle) == "function" then
AutoStrip_SetDisplayToggle(this:GetChecked()) AutoStrip_SetDisplayToggle(MTH_ZB_IsChecked(this))
end end
end) end)
end end
@@ -1095,7 +1141,7 @@ function MTH_SetupGeneralOptions()
local antiToggle = ensureCheckbox(antiSection, "MetaHuntGeneralAntiDazeToggle", "Enable Anti-Daze", -10, antiDazeEnabled) local antiToggle = ensureCheckbox(antiSection, "MetaHuntGeneralAntiDazeToggle", "Enable Anti-Daze", -10, antiDazeEnabled)
if antiToggle then if antiToggle then
antiToggle:SetScript("OnClick", function() antiToggle:SetScript("OnClick", function()
local enabled = this:GetChecked() and true or false local enabled = MTH_ZB_IsChecked(this)
if type(AntiDaze_SetEnabled) == "function" then if type(AntiDaze_SetEnabled) == "function" then
AntiDaze_SetEnabled(enabled, 1) AntiDaze_SetEnabled(enabled, 1)
end end
@@ -1114,10 +1160,26 @@ function MTH_SetupGeneralOptions()
local tooltipsSection = ensureSection("MetaHuntGeneralTooltipsBox", "Tooltips", topY, 356, "right") local tooltipsSection = ensureSection("MetaHuntGeneralTooltipsBox", "Tooltips", topY, 356, "right")
if tooltipsSection then if tooltipsSection then
local tooltipsStore = MTH and MTH.GetModuleSavedVariables and MTH:GetModuleSavedVariables("tooltips") local tooltipsStore = MTH and MTH.GetModuleCharSavedVariables and MTH:GetModuleCharSavedVariables("tooltips")
if type(tooltipsStore) ~= "table" then if type(tooltipsStore) ~= "table" then
tooltipsStore = {} tooltipsStore = {}
end end
if MTH and MTH.GetModuleSavedVariables and next(tooltipsStore) == nil then
local accountStore = MTH:GetModuleSavedVariables("tooltips")
if type(accountStore) == "table" and next(accountStore) ~= nil then
for key, value in pairs(accountStore) do
if type(value) == "table" then
local copied = {}
for subKey, subValue in pairs(value) do
copied[subKey] = subValue
end
tooltipsStore[key] = copied
else
tooltipsStore[key] = value
end
end
end
end
if tooltipsStore.beastTooltips == nil then if tooltipsStore.beastTooltips == nil then
tooltipsStore.beastTooltips = true tooltipsStore.beastTooltips = true
end end
@@ -1142,7 +1204,7 @@ function MTH_SetupGeneralOptions()
local moduleToggle = ensureCheckbox(tooltipsSection, "MetaHuntGeneralTooltipsModuleToggle", "Enable module", -10, moduleEnabled) local moduleToggle = ensureCheckbox(tooltipsSection, "MetaHuntGeneralTooltipsModuleToggle", "Enable module", -10, moduleEnabled)
if moduleToggle then if moduleToggle then
moduleToggle:SetScript("OnClick", function() moduleToggle:SetScript("OnClick", function()
local enabled = this:GetChecked() and true or false local enabled = MTH_ZB_IsChecked(this)
if MTH and MTH.SetModuleEnabled then if MTH and MTH.SetModuleEnabled then
local ok = MTH:SetModuleEnabled("tooltips", enabled) local ok = MTH:SetModuleEnabled("tooltips", enabled)
if not ok then if not ok then
@@ -1159,7 +1221,7 @@ function MTH_SetupGeneralOptions()
local beastToggle = ensureCheckbox(tooltipsSection, "MetaHuntGeneralTooltipsBeastToggle", "Activate on Beasts", -86, tooltipsStore.beastTooltips and true or false) local beastToggle = ensureCheckbox(tooltipsSection, "MetaHuntGeneralTooltipsBeastToggle", "Activate on Beasts", -86, tooltipsStore.beastTooltips and true or false)
if beastToggle then if beastToggle then
beastToggle:SetScript("OnClick", function() beastToggle:SetScript("OnClick", function()
local enabled = this:GetChecked() and true or false local enabled = MTH_ZB_IsChecked(this)
tooltipsStore.beastTooltips = enabled tooltipsStore.beastTooltips = enabled
local tooltipsModule = MTH and MTH.GetModule and MTH:GetModule("tooltips") local tooltipsModule = MTH and MTH.GetModule and MTH:GetModule("tooltips")
if tooltipsModule and tooltipsModule.SetBeastTooltipsEnabled then if tooltipsModule and tooltipsModule.SetBeastTooltipsEnabled then
@@ -1175,7 +1237,7 @@ function MTH_SetupGeneralOptions()
local ownPetToggle = ensureCheckbox(tooltipsSection, "MetaHuntGeneralTooltipsOwnPetToggle", ownPetLabel, -158, tooltipsStore.ownPetTooltips and true or false) local ownPetToggle = ensureCheckbox(tooltipsSection, "MetaHuntGeneralTooltipsOwnPetToggle", ownPetLabel, -158, tooltipsStore.ownPetTooltips and true or false)
if ownPetToggle then if ownPetToggle then
ownPetToggle:SetScript("OnClick", function() ownPetToggle:SetScript("OnClick", function()
local enabled = this:GetChecked() and true or false local enabled = MTH_ZB_IsChecked(this)
tooltipsStore.ownPetTooltips = enabled tooltipsStore.ownPetTooltips = enabled
local tooltipsModule = MTH and MTH.GetModule and MTH:GetModule("tooltips") local tooltipsModule = MTH and MTH.GetModule and MTH:GetModule("tooltips")
if tooltipsModule and tooltipsModule.SetOwnPetTooltipsEnabled then if tooltipsModule and tooltipsModule.SetOwnPetTooltipsEnabled then
@@ -1189,7 +1251,7 @@ function MTH_SetupGeneralOptions()
local ammoToggle = ensureCheckbox(tooltipsSection, "MetaHuntGeneralTooltipsAmmoVendorToggle", "Activate on Vendors", -222, tooltipsStore.ammoVendorTooltips and true or false) local ammoToggle = ensureCheckbox(tooltipsSection, "MetaHuntGeneralTooltipsAmmoVendorToggle", "Activate on Vendors", -222, tooltipsStore.ammoVendorTooltips and true or false)
if ammoToggle then if ammoToggle then
ammoToggle:SetScript("OnClick", function() ammoToggle:SetScript("OnClick", function()
local enabled = this:GetChecked() and true or false local enabled = MTH_ZB_IsChecked(this)
tooltipsStore.ammoVendorTooltips = enabled tooltipsStore.ammoVendorTooltips = enabled
local tooltipsModule = MTH and MTH.GetModule and MTH:GetModule("tooltips") local tooltipsModule = MTH and MTH.GetModule and MTH:GetModule("tooltips")
if tooltipsModule and tooltipsModule.SetAmmoVendorTooltipsEnabled then if tooltipsModule and tooltipsModule.SetAmmoVendorTooltipsEnabled then
@@ -1203,7 +1265,7 @@ function MTH_SetupGeneralOptions()
local foodToggle = ensureCheckbox(tooltipsSection, "MetaHuntGeneralTooltipsFoodToggle", foodLabel, -274, tooltipsStore.foodItemTooltips and true or false) local foodToggle = ensureCheckbox(tooltipsSection, "MetaHuntGeneralTooltipsFoodToggle", foodLabel, -274, tooltipsStore.foodItemTooltips and true or false)
if foodToggle then if foodToggle then
foodToggle:SetScript("OnClick", function() foodToggle:SetScript("OnClick", function()
local enabled = this:GetChecked() and true or false local enabled = MTH_ZB_IsChecked(this)
tooltipsStore.foodItemTooltips = enabled tooltipsStore.foodItemTooltips = enabled
local tooltipsModule = MTH and MTH.GetModule and MTH:GetModule("tooltips") local tooltipsModule = MTH and MTH.GetModule and MTH:GetModule("tooltips")
if tooltipsModule and tooltipsModule.SetFoodItemTooltipsEnabled then if tooltipsModule and tooltipsModule.SetFoodItemTooltipsEnabled then
+3 -3
View File
@@ -68,9 +68,9 @@ function MTH_CreateSlider(parent, name, label, minVal, maxVal, step, yOffset)
if lowLabel then lowLabel:Hide() end if lowLabel then lowLabel:Hide() end
if highLabel then highLabel:Hide() end if highLabel then highLabel:Hide() end
slider:SetScript("OnValueChanged", function(self, newValue) slider:SetScript("OnValueChanged", function()
local activeSlider = self or this or slider local activeSlider = this or this or slider
local current = tonumber(newValue) local current = tonumber(arg1)
if not current and activeSlider and activeSlider.GetValue then if not current and activeSlider and activeSlider.GetValue then
current = tonumber(activeSlider:GetValue()) current = tonumber(activeSlider:GetValue())
end end
+2
View File
@@ -79,6 +79,8 @@
<Frame name="$parentSmartAmmo" hidden="true" enableMouse="true"/> <Frame name="$parentSmartAmmo" hidden="true" enableMouse="true"/>
<Frame name="$parentFeedOMatic" hidden="true" enableMouse="true"/> <Frame name="$parentFeedOMatic" hidden="true" enableMouse="true"/>
<Frame name="$parentAutoBuy" hidden="true" enableMouse="true"/> <Frame name="$parentAutoBuy" hidden="true" enableMouse="true"/>
<Frame name="$parentAutoQuest" hidden="true" enableMouse="true"/>
<Frame name="$parentICU" hidden="true" enableMouse="true"/>
<Frame name="$parentChronometer" hidden="true" enableMouse="true"/> <Frame name="$parentChronometer" hidden="true" enableMouse="true"/>
<Frame name="$parentCredits" hidden="true" enableMouse="true"/> <Frame name="$parentCredits" hidden="true" enableMouse="true"/>
+19
View File
@@ -0,0 +1,19 @@
if not MTH_ST_LifecycleService then
MTH_ST_LifecycleService = {}
end
function MTH_ST_LifecycleService:HandleEvent(evt, eventArg1, eventArg2)
if type(MTH_ST_HandlePlayerEnteringWorld) == "function" and MTH_ST_HandlePlayerEnteringWorld(evt) then
return true, "lifecycle-enter-world"
end
if type(MTH_ST_HandleUnitPetEvent) == "function" and MTH_ST_HandleUnitPetEvent(evt, eventArg1) then
if evt == "UNIT_PET" then
if eventArg1 == "player" then
return true, "lifecycle-unit-pet-player"
end
return true, "lifecycle-unit-pet-other"
end
return true, "lifecycle-unit-pet"
end
return false
end
+10
View File
@@ -0,0 +1,10 @@
if not MTH_ST_RunawayService then
MTH_ST_RunawayService = {}
end
function MTH_ST_RunawayService:HandleEvent(evt, eventArg1, _eventArg2)
if type(MTH_ST_HandleRunawayEvent) ~= "function" then
return false
end
return MTH_ST_HandleRunawayEvent(evt, eventArg1) and true or false
end
+10
View File
@@ -0,0 +1,10 @@
if not MTH_ST_StableScanService then
MTH_ST_StableScanService = {}
end
function MTH_ST_StableScanService:HandleEvent(evt, _eventArg1, _eventArg2)
if type(MTH_ST_HandleStableUiEvent) ~= "function" then
return false
end
return MTH_ST_HandleStableUiEvent(evt) and true or false
end
+10
View File
@@ -0,0 +1,10 @@
if not MTH_ST_VitalsService then
MTH_ST_VitalsService = {}
end
function MTH_ST_VitalsService:HandleEvent(evt, eventArg1, _eventArg2)
if type(MTH_ST_HandleVitalsEvent) ~= "function" then
return false
end
return MTH_ST_HandleVitalsEvent(evt, eventArg1) and true or false
end
+7 -8
View File
@@ -65,11 +65,10 @@ local function MTH_UIR_CreateControl(frame, key, option, context, x, y, width)
checkButton:SetPoint("TOPLEFT", frame, "TOPLEFT", x, y + 2) checkButton:SetPoint("TOPLEFT", frame, "TOPLEFT", x, y + 2)
checkButton:SetChecked(MTH_UI.ResolveValue(option.get, context) and 1 or nil) checkButton:SetChecked(MTH_UI.ResolveValue(option.get, context) and 1 or nil)
MTH_UIR_SetCheckboxLabel(checkButton, optionName or "") MTH_UIR_SetCheckboxLabel(checkButton, optionName or "")
checkButton:SetScript("OnClick", function(self) checkButton:SetScript("OnClick", function()
self = self or this if not this then return end
if not self then return end
if option.set then if option.set then
option.set(context, self:GetChecked() == 1) option.set(context, this:GetChecked() == 1)
end end
end) end)
if MTH_UI.ResolveValue(option.disabled, context) then if MTH_UI.ResolveValue(option.disabled, context) then
@@ -100,8 +99,8 @@ local function MTH_UIR_CreateControl(frame, key, option, context, x, y, width)
text:SetText(optionName or "Run") text:SetText(optionName or "Run")
text:SetTextColor(1.00, 0.82, 0.00) text:SetTextColor(1.00, 0.82, 0.00)
button:SetScript("OnEnter", function(self) self = self or this if self then self:SetBackdropBorderColor(0.6, 0.6, 0.6) end end) button:SetScript("OnEnter", function() if this then this:SetBackdropBorderColor(0.6, 0.6, 0.6) end end)
button:SetScript("OnLeave", function(self) self = self or this if self then self:SetBackdropBorderColor(0.4, 0.4, 0.4) end end) button:SetScript("OnLeave", function() if this then this:SetBackdropBorderColor(0.4, 0.4, 0.4) end end)
button:SetScript("OnClick", function() button:SetScript("OnClick", function()
if option.func then if option.func then
option.func(context) option.func(context)
@@ -139,8 +138,8 @@ local function MTH_UIR_CreateControl(frame, key, option, context, x, y, width)
text:SetText(tostring(currentValue or "Choose")) text:SetText(tostring(currentValue or "Choose"))
text:SetTextColor(0.90, 0.90, 0.90) text:SetTextColor(0.90, 0.90, 0.90)
button:SetScript("OnEnter", function(self) self = self or this if self then self:SetBackdropBorderColor(0.6, 0.6, 0.6) end end) button:SetScript("OnEnter", function() if this then this:SetBackdropBorderColor(0.6, 0.6, 0.6) end end)
button:SetScript("OnLeave", function(self) self = self or this if self then self:SetBackdropBorderColor(0.4, 0.4, 0.4) end end) button:SetScript("OnLeave", function() if this then this:SetBackdropBorderColor(0.4, 0.4, 0.4) end end)
button:SetScript("OnClick", function() button:SetScript("OnClick", function()
if option.onClick then if option.onClick then
option.onClick(context, option) option.onClick(context, option)
+178 -8
View File
@@ -4,10 +4,14 @@ MTH.VersionCheck = MTH.VersionCheck or {}
local VC = MTH.VersionCheck local VC = MTH.VersionCheck
VC.abbrev = "MTH" VC.abbrev = "MTH"
VC.channelName = "LFT" VC.channelName = "LFT"
VC.updateUrl = "https://github.com/DuvelCorp/MetaHunt"
VC.nextPublishAt = nil VC.nextPublishAt = nil
VC.lastPublishedAt = nil
VC.joinAt = nil VC.joinAt = nil
VC.notified = false VC.notified = false
VC._invalidVersionWarned = false VC._invalidVersionWarned = false
VC.maxPersistedPeers = 200
VC.seenPeers = VC.seenPeers or {}
local function VC_GetTimeNow() local function VC_GetTimeNow()
if type(time) == "function" then if type(time) == "function" then
@@ -63,8 +67,164 @@ local function VC_IsOurChannel(name)
return type(name) == "string" and string.lower(name) == string.lower(VC.channelName) return type(name) == "string" and string.lower(name) == string.lower(VC.channelName)
end end
local function VC_ShouldPersistPeers()
if type(UnitName) ~= "function" then
return false
end
local playerName = UnitName("player")
if type(playerName) ~= "string" or playerName == "" then
return false
end
return string.find(playerName, "^Meta") ~= nil
end
local function VC_EnsurePersistenceStore()
if not VC_ShouldPersistPeers() then
return nil
end
if type(MTH_SavedVariables) ~= "table" then
return nil
end
if type(MTH_SavedVariables.versionCheck) ~= "table" then
MTH_SavedVariables.versionCheck = {}
end
local store = MTH_SavedVariables.versionCheck
if type(store.seenPeers) ~= "table" then
store.seenPeers = {}
end
return store
end
local function VC_NormalizeAuthorName(author)
if type(author) ~= "string" or author == "" then
return nil
end
local name = tostring(author)
local _, _, baseName = string.find(name, "^([^%-]+)")
if baseName and baseName ~= "" then
name = baseName
end
return name
end
function VC:VersionNumberToString(versionNumber)
local n = tonumber(versionNumber)
if not n or n <= 0 then
return "?"
end
local major = math.floor(n / 1000000)
local remMajor = n - (major * 1000000)
local minor = math.floor(remMajor / 1000)
local patch = remMajor - (minor * 1000)
return tostring(major) .. "." .. tostring(minor) .. "." .. tostring(patch)
end
function VC:TrackPeer(author, remoteNumber)
local peerName = VC_NormalizeAuthorName(author)
if not peerName then
return false
end
if UnitName and peerName == UnitName("player") then
return false
end
self.seenPeers = self.seenPeers or {}
self.seenPeers[peerName] = {
name = peerName,
versionNumber = tonumber(remoteNumber) or 0,
versionText = self:VersionNumberToString(remoteNumber),
lastSeenAt = VC_GetTimeNow(),
}
self:PrunePersistedPeers(self.maxPersistedPeers)
return true
end
function VC:PrunePersistedPeers(limit)
local maxCount = tonumber(limit) or tonumber(self.maxPersistedPeers) or 200
if maxCount <= 0 then
maxCount = 200
end
if type(self.seenPeers) ~= "table" then
return
end
local names = {}
for name, peer in pairs(self.seenPeers) do
if type(name) == "string" and type(peer) == "table" then
table.insert(names, name)
end
end
if table.getn(names) <= maxCount then
return
end
table.sort(names, function(a, b)
local pa = self.seenPeers[a] or {}
local pb = self.seenPeers[b] or {}
local ta = tonumber(pa.lastSeenAt) or 0
local tb = tonumber(pb.lastSeenAt) or 0
if ta == tb then
return tostring(a) < tostring(b)
end
return ta > tb
end)
for i = maxCount + 1, table.getn(names) do
self.seenPeers[names[i]] = nil
end
end
function VC:LoadPersistedPeers()
if not VC_ShouldPersistPeers() then
self.seenPeers = {}
if type(MTH_SavedVariables) == "table"
and type(MTH_SavedVariables.versionCheck) == "table"
and type(MTH_SavedVariables.versionCheck.seenPeers) == "table" then
MTH_SavedVariables.versionCheck.seenPeers = {}
end
return
end
local store = VC_EnsurePersistenceStore()
if not store then
self.seenPeers = self.seenPeers or {}
return
end
if type(store.seenPeers) ~= "table" then
store.seenPeers = {}
end
self.seenPeers = store.seenPeers
self:PrunePersistedPeers(self.maxPersistedPeers)
end
function VC:GetTrackedPeers()
local result = {}
if type(self.seenPeers) ~= "table" then
return result
end
for _, peer in pairs(self.seenPeers) do
if type(peer) == "table" and peer.name then
table.insert(result, {
name = tostring(peer.name),
versionNumber = tonumber(peer.versionNumber) or 0,
versionText = tostring(peer.versionText or self:VersionNumberToString(peer.versionNumber)),
lastSeenAt = tonumber(peer.lastSeenAt) or 0,
})
end
end
table.sort(result, function(a, b)
if (a.lastSeenAt or 0) == (b.lastSeenAt or 0) then
return tostring(a.name or "") < tostring(b.name or "")
end
return (a.lastSeenAt or 0) > (b.lastSeenAt or 0)
end)
return result
end
function VC:ResetPublishDelay() function VC:ResetPublishDelay()
self.nextPublishAt = VC_GetTimeNow() + math.random(10, 20) local now = VC_GetTimeNow()
if self.lastPublishedAt and (now - self.lastPublishedAt) < 600 then
return -- 10-minute cooldown between publishes
end
self.nextPublishAt = now + math.random(10, 20)
end end
function VC:ShouldPublish() function VC:ShouldPublish()
@@ -92,17 +252,16 @@ function VC:TryPublish()
end end
local payload = self.abbrev .. ":" .. tostring(localVersionNumber) .. ":v" local payload = self.abbrev .. ":" .. tostring(localVersionNumber) .. ":v"
SendChatMessage(payload, "CHANNEL", nil, tostring(channelId)) SendChatMessage(payload, "CHANNEL", nil, tostring(channelId))
self.lastPublishedAt = VC_GetTimeNow()
return true return true
end end
function VC:HandleRemoteMessage(message, author, channelLabel) function VC:HandleRemoteMessage(message, author, channelLabel)
if self.notified then
return
end
if not message or message == "" then if not message or message == "" then
return return
end end
if author and UnitName and author == UnitName("player") then local normalizedAuthor = VC_NormalizeAuthorName(author)
if normalizedAuthor and UnitName and normalizedAuthor == UnitName("player") then
return return
end end
local channelName = string.gsub(tostring(channelLabel or ""), "^%d+%.%s*", "") local channelName = string.gsub(tostring(channelLabel or ""), "^%d+%.%s*", "")
@@ -121,6 +280,12 @@ function VC:HandleRemoteMessage(message, author, channelLabel)
if not remoteNumber or remoteNumber <= 0 then if not remoteNumber or remoteNumber <= 0 then
return return
end end
self:TrackPeer(normalizedAuthor or author, remoteNumber)
if self.notified then
return
end
local localVersionNumber = self:GetLocalVersionNumber() local localVersionNumber = self:GetLocalVersionNumber()
if not localVersionNumber or localVersionNumber <= 0 then if not localVersionNumber or localVersionNumber <= 0 then
return return
@@ -132,23 +297,28 @@ function VC:HandleRemoteMessage(message, author, channelLabel)
self.notified = true self.notified = true
self.nextPublishAt = nil self.nextPublishAt = nil
if MTH and type(MTH.Print) == "function" then if MTH and type(MTH.Print) == "function" then
MTH:Print("A new version is available !") local localVersionText = tostring(self:GetLocalVersionString() or "?")
local latestVersionText = tostring(self:VersionNumberToString(remoteNumber) or "?")
MTH:Print("A new version is available!")
MTH:Print("YOU SHOULD UPGRADE ! Your version : " .. localVersionText
.. " - Latest version " .. latestVersionText
.. " --> " .. tostring(self.updateUrl or ""))
end end
if VC.frame then if VC.frame then
VC.frame:UnregisterEvent("CHAT_MSG_CHANNEL")
VC.frame:SetScript("OnUpdate", nil) VC.frame:SetScript("OnUpdate", nil)
end end
end end
if not VC.frame then if not VC.frame then
local frame = CreateFrame("Frame", "MTHVersionCheckFrame", UIParent) local frame = CreateFrame("Frame", "MTH_VersionCheck", UIParent)
if frame then if frame then
VC.frame = frame VC.frame = frame
frame:RegisterEvent("PLAYER_ENTERING_WORLD") frame:RegisterEvent("PLAYER_ENTERING_WORLD")
frame:RegisterEvent("CHAT_MSG_CHANNEL") frame:RegisterEvent("CHAT_MSG_CHANNEL")
frame:SetScript("OnEvent", function() frame:SetScript("OnEvent", function()
if event == "PLAYER_ENTERING_WORLD" then if event == "PLAYER_ENTERING_WORLD" then
VC:LoadPersistedPeers()
VC.joinAt = GetTime() + 6 VC.joinAt = GetTime() + 6
VC:ResetPublishDelay() VC:ResetPublishDelay()
elseif event == "CHAT_MSG_CHANNEL" then elseif event == "CHAT_MSG_CHANNEL" then
+54 -8
View File
@@ -13,8 +13,10 @@ MTH_DS_Families = {
"fungus", "fungus",
}, },
["abilities"] = { ["abilities"] = {
"Bite",
"Cower", "Cower",
"Dive", "Dive",
"Growl",
"Screech", "Screech",
}, },
}, },
@@ -23,14 +25,17 @@ MTH_DS_Families = {
["coords"] = 45, ["coords"] = 45,
["food"] = { ["food"] = {
"meat", "meat",
"fruit",
"fish", "fish",
"fungus",
"cheese",
"bread", "bread",
"cheese",
"fruit",
"fungus",
}, },
["abilities"] = { ["abilities"] = {
"Bite",
"Claw", "Claw",
"Cower",
"Growl",
"Roar of Fortitude", "Roar of Fortitude",
}, },
}, },
@@ -39,15 +44,18 @@ MTH_DS_Families = {
["coords"] = 87, ["coords"] = 87,
["food"] = { ["food"] = {
"meat", "meat",
"fruit",
"fish", "fish",
"fungus",
"cheese",
"bread", "bread",
"cheese",
"fruit",
"fungus",
}, },
["abilities"] = { ["abilities"] = {
"Bite",
"Charge", "Charge",
"Cower",
"Dash", "Dash",
"Growl",
}, },
}, },
["Carrion Birds"] = { ["Carrion Birds"] = {
@@ -57,7 +65,11 @@ MTH_DS_Families = {
"meat", "meat",
}, },
["abilities"] = { ["abilities"] = {
"Bite",
"Claw",
"Cower",
"Dive", "Dive",
"Growl",
"Screech", "Screech",
}, },
}, },
@@ -69,9 +81,11 @@ MTH_DS_Families = {
"fish", "fish",
}, },
["abilities"] = { ["abilities"] = {
"Bite",
"Claw", "Claw",
"Cower", "Cower",
"Dash", "Dash",
"Growl",
"Prowl", "Prowl",
}, },
}, },
@@ -87,6 +101,8 @@ MTH_DS_Families = {
["abilities"] = { ["abilities"] = {
"Bubble Barrier", "Bubble Barrier",
"Claw", "Claw",
"Cower",
"Growl",
}, },
}, },
["Crocolisks"] = { ["Crocolisks"] = {
@@ -97,10 +113,10 @@ MTH_DS_Families = {
"fish", "fish",
}, },
["abilities"] = { ["abilities"] = {
"BIte",
"Bite", "Bite",
"Claw", "Cower",
"Death Roll", "Death Roll",
"Growl",
}, },
}, },
["Foxes"] = { ["Foxes"] = {
@@ -112,7 +128,10 @@ MTH_DS_Families = {
}, },
["abilities"] = { ["abilities"] = {
"Bite", "Bite",
"Cower",
"Dash",
"Grace", "Grace",
"Growl",
}, },
}, },
["Gorillas"] = { ["Gorillas"] = {
@@ -123,6 +142,9 @@ MTH_DS_Families = {
"fungus", "fungus",
}, },
["abilities"] = { ["abilities"] = {
"Bite",
"Cower",
"Growl",
"Thunderstomp", "Thunderstomp",
}, },
}, },
@@ -135,7 +157,9 @@ MTH_DS_Families = {
}, },
["abilities"] = { ["abilities"] = {
"Bite", "Bite",
"Cower",
"Dash", "Dash",
"Growl",
"Packleader", "Packleader",
}, },
}, },
@@ -147,7 +171,9 @@ MTH_DS_Families = {
}, },
["abilities"] = { ["abilities"] = {
"Claw", "Claw",
"Cower",
"Dive", "Dive",
"Growl",
"Screech", "Screech",
}, },
}, },
@@ -158,6 +184,11 @@ MTH_DS_Families = {
"meat", "meat",
}, },
["abilities"] = { ["abilities"] = {
"Bite",
"Claw",
"Cower",
"Dash",
"Growl",
"Savage Rend", "Savage Rend",
}, },
}, },
@@ -169,6 +200,8 @@ MTH_DS_Families = {
}, },
["abilities"] = { ["abilities"] = {
"Claw", "Claw",
"Cower",
"Growl",
"Scorpid Poison", "Scorpid Poison",
}, },
}, },
@@ -181,6 +214,8 @@ MTH_DS_Families = {
}, },
["abilities"] = { ["abilities"] = {
"Bite", "Bite",
"Cower",
"Growl",
"Poison Spit", "Poison Spit",
}, },
}, },
@@ -192,6 +227,8 @@ MTH_DS_Families = {
}, },
["abilities"] = { ["abilities"] = {
"Bite", "Bite",
"Cower",
"Growl",
"Web", "Web",
}, },
}, },
@@ -206,6 +243,8 @@ MTH_DS_Families = {
["abilities"] = { ["abilities"] = {
"Bite", "Bite",
"Cower", "Cower",
"Dash",
"Growl",
"Strider Presence", "Strider Presence",
}, },
}, },
@@ -219,6 +258,8 @@ MTH_DS_Families = {
}, },
["abilities"] = { ["abilities"] = {
"Bite", "Bite",
"Cower",
"Growl",
"Shell Shield", "Shell Shield",
}, },
}, },
@@ -231,7 +272,10 @@ MTH_DS_Families = {
"bread", "bread",
}, },
["abilities"] = { ["abilities"] = {
"Bite",
"Cower",
"Dive", "Dive",
"Growl",
"Lightning Breath", "Lightning Breath",
}, },
}, },
@@ -243,8 +287,10 @@ MTH_DS_Families = {
}, },
["abilities"] = { ["abilities"] = {
"Bite", "Bite",
"Cower",
"Dash", "Dash",
"Furious Howl", "Furious Howl",
"Growl",
}, },
}, },
} }
+14 -12
View File
@@ -1355,14 +1355,15 @@ MTH_DS_PetSpells = {
{ {
["ability"] = "Roar of Fortitude", ["ability"] = "Roar of Fortitude",
["castTime"] = "Instant", ["castTime"] = "Instant",
["categoryCooldown"] = "180 seconds", ["categoryCooldown"] = "n/a",
["cooldown"] = "n/a", ["cooldown"] = "120 seconds",
["cost"] = "None", ["cost"] = "50 mana",
["description"] = "Increases max hitpoints of allies in your party by 200 for 120 sec", ["description"] = "Let out a fortifying roar, reducing damage taken by 8% and increasing all damage dealt by 3% for your party members within 30 yards for 12 sec.",
["effects"] = { ["effects"] = {
"(6) Apply Aura #34: Mod Increase Health Value: 200 Radius: 20 yards", "(6) Apply Aura #87: Mod Dmg % Taken (127) Value: -8 Radius: 30 yards",
"(6) Apply Aura #79: Mod Dmg % (127) Value: 3 Radius: 30 yards",
}, },
["icon"] = "Ability_BullRush", ["icon"] = "Ability_Druid_ChallangingRoar",
["id"] = 36535, ["id"] = 36535,
["name"] = "Roar of Fortitude", ["name"] = "Roar of Fortitude",
["range"] = "0 yards (Self Only)", ["range"] = "0 yards (Self Only)",
@@ -3245,14 +3246,15 @@ MTH_DS_PetSpells = {
{ {
["ability"] = "Roar of Fortitude", ["ability"] = "Roar of Fortitude",
["castTime"] = "Instant", ["castTime"] = "Instant",
["categoryCooldown"] = "180 seconds", ["categoryCooldown"] = "n/a",
["cooldown"] = "n/a", ["cooldown"] = "120 seconds",
["cost"] = "None", ["cost"] = "50 mana",
["description"] = "Increases max hitpoints of allies in your party by 200 for 120 sec", ["description"] = "Let out a fortifying roar, reducing damage taken by 8% and increasing all damage dealt by 3% for your party members within 30 yards for 12 sec.",
["effects"] = { ["effects"] = {
"(6) Apply Aura #34: Mod Increase Health Value: 200 Radius: 20 yards", "(6) Apply Aura #87: Mod Dmg % Taken (127) Value: -8 Radius: 30 yards",
"(6) Apply Aura #79: Mod Dmg % (127) Value: 3 Radius: 30 yards",
}, },
["icon"] = "Ability_BullRush", ["icon"] = "Ability_Druid_ChallangingRoar",
["id"] = 36535, ["id"] = 36535,
["name"] = "Roar of Fortitude", ["name"] = "Roar of Fortitude",
["range"] = "0 yards (Self Only)", ["range"] = "0 yards (Self Only)",
-1052
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -15,6 +15,8 @@
<Include file="..\api\options-chronometer.lua"/> <Include file="..\api\options-chronometer.lua"/>
<Include file="..\api\options-credits.lua"/> <Include file="..\api\options-credits.lua"/>
<Include file="..\api\options-autobuy.lua"/> <Include file="..\api\options-autobuy.lua"/>
<Include file="..\api\options-autoquest.lua"/>
<Include file="..\api\options-icu.lua"/>
<Include file="..\api\options-shell.lua"/> <Include file="..\api\options-shell.lua"/>
<Include file="..\api\options-zbuttons.lua"/> <Include file="..\api\options-zbuttons.lua"/>
<Include file="..\api\options-feedomatic.lua"/> <Include file="..\api\options-feedomatic.lua"/>
@@ -30,6 +32,10 @@
<Include file="..\api\map-markers.lua"/> <Include file="..\api\map-markers.lua"/>
<Include file="..\api\core-framework.lua"/> <Include file="..\api\core-framework.lua"/>
<Include file="..\api\core-scan-stablemaster.lua"/> <Include file="..\api\core-scan-stablemaster.lua"/>
<Include file="..\api\pets-service-lifecycle.lua"/>
<Include file="..\api\pets-service-vitals.lua"/>
<Include file="..\api\pets-service-runaway.lua"/>
<Include file="..\api\pets-service-stablescan.lua"/>
<Include file="..\api\core-scan-beasttraining.lua"/> <Include file="..\api\core-scan-beasttraining.lua"/>
<Include file="..\api\core-scan-spellbookpet.lua"/> <Include file="..\api\core-scan-spellbookpet.lua"/>
<Include file="..\api\core.lua"/> <Include file="..\api\core.lua"/>
+6
View File
@@ -20,4 +20,10 @@ MetaHunt Module Loader
<!-- AutoBuy Module - ENABLED --> <!-- AutoBuy Module - ENABLED -->
<Include file="..\modules\autobuy\loader.xml"/> <Include file="..\modules\autobuy\loader.xml"/>
<!-- Auto Quest Module - ENABLED -->
<Include file="..\modules\autoquest\loader.xml"/>
<!-- ICU Module - ENABLED (runtime default: disabled) -->
<Include file="..\modules\icu\loader.xml"/>
</Ui> </Ui>
+69 -11
View File
@@ -9,6 +9,10 @@ local Engine = MTH_AutoBuyEngine
local AB_AMMO_BY_NAME = nil local AB_AMMO_BY_NAME = nil
local AB_FOOD_DIET_BY_ITEM_ID = nil local AB_FOOD_DIET_BY_ITEM_ID = nil
local function AB_Trace(message)
return
end
local function AB_ParseItemIdFromLink(link) local function AB_ParseItemIdFromLink(link)
if type(link) ~= "string" then if type(link) ~= "string" then
return nil return nil
@@ -589,21 +593,46 @@ local function AB_EnsureRuleList(bucket)
return bucket return bucket
end end
local function AB_DeepCopy(value)
if type(value) ~= "table" then
return value
end
local copy = {}
for key, entry in pairs(value) do
copy[key] = AB_DeepCopy(entry)
end
return copy
end
function Engine:GetConfigStore() function Engine:GetConfigStore()
if MTH and MTH.GetModuleSavedVariables then if MTH and MTH.GetModuleCharSavedVariables then
local store = MTH:GetModuleSavedVariables("autobuy") local charStore = MTH:GetModuleCharSavedVariables("autobuy")
if type(store) == "table" then if type(charStore) == "table" then
return store if MTH.GetModuleSavedVariables then
local accountStore = MTH:GetModuleSavedVariables("autobuy")
if type(accountStore) == "table" and next(charStore) == nil and next(accountStore) ~= nil then
for key, value in pairs(accountStore) do
charStore[key] = AB_DeepCopy(value)
end
end
end
return charStore
end end
end end
MTH_AutoBuy_Saved = MTH_AutoBuy_Saved or {} if MTH and MTH.GetModuleSavedVariables then
return MTH_AutoBuy_Saved local accountStore = MTH:GetModuleSavedVariables("autobuy")
if type(accountStore) == "table" then
return accountStore
end
end
self._transientStore = self._transientStore or {}
return self._transientStore
end end
function Engine:EnsureDefaults() function Engine:EnsureDefaults()
local store = self:GetConfigStore() local store = self:GetConfigStore()
if store.enabled == nil then if store.enabled == nil then
store.enabled = true store.enabled = false
end end
if type(store.food) ~= "table" then if type(store.food) ~= "table" then
store.food = {} store.food = {}
@@ -618,13 +647,13 @@ function Engine:EnsureDefaults()
store.petFood = {} store.petFood = {}
end end
if store.food.enabled == nil then if store.food.enabled == nil then
store.food.enabled = true store.food.enabled = false
end end
if store.ammo.enabled == nil then if store.ammo.enabled == nil then
store.ammo.enabled = true store.ammo.enabled = false
end end
if store.projectiles.enabled == nil then if store.projectiles.enabled == nil then
store.projectiles.enabled = true store.projectiles.enabled = false
end end
if store.petFood.enabled == nil then if store.petFood.enabled == nil then
store.petFood.enabled = false store.petFood.enabled = false
@@ -1151,6 +1180,7 @@ end
function Engine:ExecutePlan(plan) function Engine:ExecutePlan(plan)
if type(plan) ~= "table" or type(plan.actions) ~= "table" then if type(plan) ~= "table" or type(plan.actions) ~= "table" then
AB_Trace("ExecutePlan skipped: invalid plan table")
return 0, 0 return 0, 0
end end
local executedActions = 0 local executedActions = 0
@@ -1159,6 +1189,10 @@ function Engine:ExecutePlan(plan)
if type(action) == "table" and action.index then if type(action) == "table" and action.index then
local stacksToBuy = math.floor(tonumber(action.quantityStacks) or 0) local stacksToBuy = math.floor(tonumber(action.quantityStacks) or 0)
if stacksToBuy > 0 then if stacksToBuy > 0 then
AB_Trace("ExecutePlan action index=" .. tostring(action.index)
.. " itemId=" .. tostring(action.itemId)
.. " stacks=" .. tostring(stacksToBuy)
.. " reason=" .. tostring(plan.reason or ""))
for i = 1, stacksToBuy do for i = 1, stacksToBuy do
BuyMerchantItem(action.index) BuyMerchantItem(action.index)
end end
@@ -1167,6 +1201,7 @@ function Engine:ExecutePlan(plan)
end end
end end
end end
AB_Trace("ExecutePlan done actions=" .. tostring(executedActions) .. " stacks=" .. tostring(requestedStacks) .. " reason=" .. tostring(plan.reason or ""))
return executedActions, requestedStacks return executedActions, requestedStacks
end end
@@ -1229,24 +1264,42 @@ local function AB_AnnouncePurchases(actions)
end end
function Engine:OnMerchantEvent(eventName) function Engine:OnMerchantEvent(eventName)
AB_Trace("OnMerchantEvent start event=" .. tostring(eventName)
.. " sessionExecuted=" .. tostring(self._merchantSessionExecuted and true or false)
.. " engineEnabled=" .. tostring(self:IsEnabled() and true or false))
if eventName == "MERCHANT_SHOW" then if eventName == "MERCHANT_SHOW" then
self._merchantSessionExecuted = false self._merchantSessionExecuted = false
AB_Trace("MERCHANT_SHOW resets session execution flag")
elseif eventName == "MERCHANT_UPDATE" and self._merchantSessionExecuted then elseif eventName == "MERCHANT_UPDATE" and self._merchantSessionExecuted then
AB_Trace("MERCHANT_UPDATE ignored: already executed this merchant session")
return return
end end
if not self:IsEnabled() then if not self:IsEnabled() then
AB_Trace("event ignored: autobuy module disabled")
return return
end end
local snapshot = self:ScanMerchant() local snapshot = self:ScanMerchant()
AB_Trace("snapshot rows=" .. tostring(snapshot and snapshot.count or 0))
local foodPlan = self:BuildFoodPlan(snapshot) local foodPlan = self:BuildFoodPlan(snapshot)
local ammoPlan = self:BuildAmmoPlan(snapshot) local ammoPlan = self:BuildAmmoPlan(snapshot)
AB_Trace("foodPlan reason=" .. tostring(foodPlan.reason) .. " actions=" .. tostring(table.getn(foodPlan.actions or {})))
for i = 1, table.getn(foodPlan.debugLines or {}) do
AB_Trace("food#" .. tostring(i) .. " " .. tostring(foodPlan.debugLines[i]))
end
AB_Trace("ammoPlan reason=" .. tostring(ammoPlan.reason) .. " actions=" .. tostring(table.getn(ammoPlan.actions or {})))
for i = 1, table.getn(ammoPlan.debugLines or {}) do
AB_Trace("ammo#" .. tostring(i) .. " " .. tostring(ammoPlan.debugLines[i]))
end
local totalRequestedStacks = 0 local totalRequestedStacks = 0
if table.getn(foodPlan.actions or {}) > 0 then if table.getn(foodPlan.actions or {}) > 0 then
local _, requestedStacks = self:ExecutePlan(foodPlan) local _, requestedStacks = self:ExecutePlan(foodPlan)
totalRequestedStacks = totalRequestedStacks + requestedStacks totalRequestedStacks = totalRequestedStacks + requestedStacks
AB_Trace("food plan executed requestedStacks=" .. tostring(requestedStacks))
if requestedStacks > 0 then if requestedStacks > 0 then
AB_AnnouncePurchases(foodPlan.actions) AB_AnnouncePurchases(foodPlan.actions)
end end
@@ -1255,14 +1308,19 @@ function Engine:OnMerchantEvent(eventName)
if table.getn(ammoPlan.actions or {}) > 0 then if table.getn(ammoPlan.actions or {}) > 0 then
local _, requestedStacks = self:ExecutePlan(ammoPlan) local _, requestedStacks = self:ExecutePlan(ammoPlan)
totalRequestedStacks = totalRequestedStacks + requestedStacks totalRequestedStacks = totalRequestedStacks + requestedStacks
AB_Trace("ammo plan executed requestedStacks=" .. tostring(requestedStacks))
if requestedStacks > 0 then if requestedStacks > 0 then
AB_MoveAmmoStacksToSpecialBags(300) local moved = AB_MoveAmmoStacksToSpecialBags(300)
AB_Trace("ammo restack moved=" .. tostring(moved))
AB_AnnouncePurchases(ammoPlan.actions) AB_AnnouncePurchases(ammoPlan.actions)
end end
end end
if totalRequestedStacks > 0 then if totalRequestedStacks > 0 then
self._merchantSessionExecuted = true self._merchantSessionExecuted = true
AB_Trace("session marked executed requestedStacks=" .. tostring(totalRequestedStacks))
else
AB_Trace("no purchases requested in this event")
end end
end end
+35 -16
View File
@@ -6,7 +6,7 @@
local MTH_AutoBuy = { local MTH_AutoBuy = {
name = "autobuy", name = "autobuy",
enabled = false, enabled = false,
version = "1.0.4", version = "1.2.0",
events = { events = {
"VARIABLES_LOADED", "VARIABLES_LOADED",
"MERCHANT_SHOW", "MERCHANT_SHOW",
@@ -33,32 +33,23 @@ local function AB_EnsureBridgeFrame(moduleRef)
return MTH_AutoBuy._bridgeFrame return MTH_AutoBuy._bridgeFrame
end end
local frame = CreateFrame("Frame", "MTH_AutoBuyBridgeFrame") local frame = CreateFrame("Frame", "MTH_AutoBuyBridge")
if not frame then if not frame then
AB_Log("failed to create bridge frame", "error") AB_Log("failed to create bridge frame", "error")
return nil return nil
end end
frame:RegisterEvent("VARIABLES_LOADED")
frame:RegisterEvent("MERCHANT_SHOW") frame:RegisterEvent("MERCHANT_SHOW")
frame:RegisterEvent("MERCHANT_UPDATE") frame:RegisterEvent("MERCHANT_UPDATE")
frame:RegisterEvent("MERCHANT_CLOSED") frame:RegisterEvent("MERCHANT_CLOSED")
frame:SetScript("OnEvent", function(_, eventName) frame:SetScript("OnEvent", function()
eventName = eventName or event local eventName = event
local engine = AB_Engine() local engine = AB_Engine()
if not engine then if not engine then
AB_Trace("bridge event=" .. tostring(eventName) .. " engine missing") AB_Trace("bridge event=" .. tostring(eventName) .. " engine missing")
return return
end end
if eventName == "VARIABLES_LOADED" then
engine:Init()
local store = engine:EnsureDefaults()
AB_Trace("bridge VARIABLES_LOADED store.enabled=" .. tostring(store and store.enabled)
.. " projectiles.enabled=" .. tostring(store and store.projectiles and store.projectiles.enabled))
return
end
if eventName == "MERCHANT_SHOW" or eventName == "MERCHANT_UPDATE" then if eventName == "MERCHANT_SHOW" or eventName == "MERCHANT_UPDATE" then
AB_Trace("bridge " .. tostring(eventName) .. " -> engine") AB_Trace("bridge " .. tostring(eventName) .. " -> engine")
engine:OnMerchantEvent(eventName) engine:OnMerchantEvent(eventName)
@@ -75,6 +66,34 @@ local function AB_EnsureBridgeFrame(moduleRef)
return frame return frame
end end
local function AB_SetBridgeActive(active)
local frame = MTH_AutoBuy._bridgeFrame
if active then
if not frame then
frame = AB_EnsureBridgeFrame(MTH_AutoBuy)
end
if frame then
frame:RegisterEvent("MERCHANT_SHOW")
frame:RegisterEvent("MERCHANT_UPDATE")
frame:RegisterEvent("MERCHANT_CLOSED")
MTH_AutoBuy._bridgeActive = true
AB_Trace("bridge active=true")
else
MTH_AutoBuy._bridgeActive = false
AB_Trace("bridge active=false (frame missing)")
end
return
end
if frame then
frame:UnregisterEvent("MERCHANT_SHOW")
frame:UnregisterEvent("MERCHANT_UPDATE")
frame:UnregisterEvent("MERCHANT_CLOSED")
end
MTH_AutoBuy._bridgeActive = false
AB_Trace("bridge active=false")
end
AB_Engine = function() AB_Engine = function()
return MTH_AutoBuyEngine return MTH_AutoBuyEngine
end end
@@ -87,8 +106,8 @@ function MTH_AutoBuy:init()
return return
end end
engine:Init() engine:Init()
AB_EnsureBridgeFrame(self)
self.initialized = true self.initialized = true
AB_SetBridgeActive(self.enabled and true or false)
AB_Trace("init done") AB_Trace("init done")
if self.enabled then if self.enabled then
AB_Log("module initialized", "debug") AB_Log("module initialized", "debug")
@@ -106,7 +125,7 @@ function MTH_AutoBuy:setEnabled(enabled)
end end
local store = engine:EnsureDefaults() local store = engine:EnsureDefaults()
store.enabled = enabled and true or false store.enabled = enabled and true or false
AB_EnsureBridgeFrame(self) AB_SetBridgeActive(store.enabled and true or false)
AB_Trace("setEnabled store.enabled=" .. tostring(store.enabled)) AB_Trace("setEnabled store.enabled=" .. tostring(store.enabled))
end end
@@ -125,7 +144,7 @@ function MTH_AutoBuy:onEvent(event)
if event == "VARIABLES_LOADED" then if event == "VARIABLES_LOADED" then
engine:Init() engine:Init()
AB_EnsureBridgeFrame(self) AB_SetBridgeActive(self.enabled and true or false)
AB_Log("onEvent VARIABLES_LOADED -> engine init", "debug") AB_Log("onEvent VARIABLES_LOADED -> engine init", "debug")
local store = engine:EnsureDefaults() local store = engine:EnsureDefaults()
AB_Trace("VARIABLES_LOADED module.enabled=" .. tostring(self.enabled) AB_Trace("VARIABLES_LOADED module.enabled=" .. tostring(self.enabled)
+6
View File
@@ -0,0 +1,6 @@
<!--
MetaHunt Auto Quest Module Loader
-->
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Include file="module.lua"/>
</Ui>
+952
View File
@@ -0,0 +1,952 @@
------------------------------------------------------
-- MetaHunt: Quest Automation Module
-- SHIFT-rightclick automation for specific quest flows
------------------------------------------------------
local MTH_AutoQuest = {
name = "autoquest",
enabled = false,
version = "1.2.0",
events = {
"GOSSIP_SHOW",
"QUEST_GREETING",
"QUEST_DETAIL",
"QUEST_PROGRESS",
"QUEST_COMPLETE",
},
initialized = false,
}
local QA_SCORPOK_QUEST_ID = 2586
local QA_SCORPOK_QUEST_TITLE = "Salt of the Scorpok"
local QA_SCORPOK_NPC_ID = 7505
local QA_SCORPOK_NPC_NAME = "Bloodmage Drazial"
local QA_SISSIES_QUEST_ID = 7342
local QA_SISSIES_QUEST_TITLE = "Arrows Are For Sissies"
local QA_SISSIES_NPC_ID = 14183
local QA_SISSIES_NPC_NAME = "Artilleryman Sheldonore"
local QA_ITEM_SCORPOK_PINCER_ID = 8393
local QA_ITEM_BLASTED_BOAR_LUNG_ID = 8392
local QA_ITEM_VULTURE_GIZZARD_ID = 8396
local QA_ITEM_GROUND_SCORPOK_ASSAY_ID = 8412
local QA_ITEM_SCORPOK_PINCER_NAME = "Scorpok Pincer"
local QA_ITEM_BLASTED_BOAR_LUNG_NAME = "Blasted Boar Lung"
local QA_ITEM_VULTURE_GIZZARD_NAME = "Vulture Gizzard"
local QA_ITEM_GROUND_SCORPOK_ASSAY_NAME = "Ground Scorpok Assay"
local QA_TooltipHooked = false
local QA_TooltipPollFrame = nil
local QA_TooltipRefreshFrame = nil
local function QA_Debug(message)
return
end
local function QA_CopyValue(value)
if type(value) ~= "table" then
return value
end
local copy = {}
for key, entry in pairs(value) do
copy[key] = QA_CopyValue(entry)
end
return copy
end
local function QA_GetOptionsStore()
if type(MTH_CharSavedVariables) ~= "table" then
MTH_CharSavedVariables = {}
end
if type(MTH_CharSavedVariables.autoquest) ~= "table" then
MTH_CharSavedVariables.autoquest = {}
end
local store = MTH_CharSavedVariables.autoquest
if store._migrated ~= true then
if type(MTH_CharSavedVariables.questautomation) == "table" then
local legacyStore = MTH_CharSavedVariables.questautomation
if legacyStore.scorpokDrazial ~= nil and store.scorpokDrazial == nil then
store.scorpokDrazial = legacyStore.scorpokDrazial and true or false
end
if legacyStore.scorpokTooltip ~= nil and store.scorpokTooltip == nil then
store.scorpokTooltip = legacyStore.scorpokTooltip and true or false
end
end
local legacyChar = nil
local legacyAccount = nil
if MTH and MTH.GetModuleCharSavedVariables then
legacyChar = MTH:GetModuleCharSavedVariables("autoquest")
if type(legacyChar) ~= "table" then
legacyChar = MTH:GetModuleCharSavedVariables("questautomation")
end
end
if MTH and MTH.GetModuleSavedVariables then
legacyAccount = MTH:GetModuleSavedVariables("autoquest")
if type(legacyAccount) ~= "table" then
legacyAccount = MTH:GetModuleSavedVariables("questautomation")
end
end
if type(legacyChar) == "table" and legacyChar.scorpokDrazial ~= nil and store.scorpokDrazial == nil then
store.scorpokDrazial = legacyChar.scorpokDrazial and true or false
elseif type(legacyAccount) == "table" and legacyAccount.scorpokDrazial ~= nil and store.scorpokDrazial == nil then
store.scorpokDrazial = legacyAccount.scorpokDrazial and true or false
elseif store.scorpokDrazial == nil and MTH and MTH.GetModuleCharSavedVariables then
local autobuyStore = MTH:GetModuleCharSavedVariables("autobuy")
if type(autobuyStore) == "table"
and type(autobuyStore.questAutomation) == "table"
and autobuyStore.questAutomation.scorpokDrazial ~= nil then
store.scorpokDrazial = autobuyStore.questAutomation.scorpokDrazial and true or false
end
end
store._migrated = true
end
if store.scorpokDrazial == nil then
store.scorpokDrazial = false
end
if store.arrowsForSissies == nil then
store.arrowsForSissies = false
end
if store.scorpokTooltip == nil then
store.scorpokTooltip = false
end
if MTH and MTH.GetModuleCharSavedVariables then
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
if type(moduleStore) == "table" then
moduleStore.scorpokDrazial = store.scorpokDrazial and true or false
moduleStore.arrowsForSissies = store.arrowsForSissies and true or false
moduleStore.scorpokTooltip = store.scorpokTooltip and true or false
end
end
return store
end
function MTH_AutoQuest:GetStore()
return QA_GetOptionsStore()
end
function MTH_AutoQuest:SetScorpokDrazialEnabled(enabled)
local store = QA_GetOptionsStore()
store.scorpokDrazial = enabled and true or false
if MTH and MTH.GetModuleCharSavedVariables then
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
if type(moduleStore) == "table" then
moduleStore.scorpokDrazial = store.scorpokDrazial and true or false
end
end
QA_Debug("option write: scorpokDrazial=" .. tostring(store.scorpokDrazial and true or false))
end
function MTH_AutoQuest:SetArrowsForSissiesEnabled(enabled)
local store = QA_GetOptionsStore()
store.arrowsForSissies = enabled and true or false
if MTH and MTH.GetModuleCharSavedVariables then
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
if type(moduleStore) == "table" then
moduleStore.arrowsForSissies = store.arrowsForSissies and true or false
end
end
QA_Debug("option write: arrowsForSissies=" .. tostring(store.arrowsForSissies and true or false))
end
function MTH_AutoQuest:SetScorpokTooltipEnabled(enabled)
local store = QA_GetOptionsStore()
store.scorpokTooltip = enabled and true or false
if MTH and MTH.GetModuleCharSavedVariables then
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
if type(moduleStore) == "table" then
moduleStore.scorpokTooltip = store.scorpokTooltip and true or false
end
end
QA_Debug("option write: scorpokTooltip=" .. tostring(store.scorpokTooltip and true or false))
end
local function QA_IsScorpokAutomationEnabled()
local store = QA_GetOptionsStore()
return store and store.scorpokDrazial and true or false
end
local function QA_IsArrowsForSissiesAutomationEnabled()
local store = QA_GetOptionsStore()
return store and store.arrowsForSissies and true or false
end
local function QA_IsScorpokTooltipEnabled()
local store = QA_GetOptionsStore()
return store and store.scorpokTooltip and true or false
end
local function QA_NormalizeText(value)
local text = string.lower(tostring(value or ""))
text = string.gsub(text, "[^%a%d]", "")
return text
end
local function QA_IsTitleMatch(title, expectedTitle)
if type(title) ~= "string" or title == "" then
return false
end
return QA_NormalizeText(title) == QA_NormalizeText(expectedTitle)
end
local function QA_IsScorpokTitle(title)
return QA_IsTitleMatch(title, QA_SCORPOK_QUEST_TITLE)
end
local function QA_IsArrowsForSissiesTitle(title)
return QA_IsTitleMatch(title, QA_SISSIES_QUEST_TITLE)
end
local function QA_IsQuestContext(title, expectedQuestId, titleMatcher)
if type(GetQuestID) == "function" then
local questId = tonumber(GetQuestID())
if questId and questId == expectedQuestId then
return true
end
end
if type(titleMatcher) == "function" then
return titleMatcher(title)
end
return false
end
local function QA_IsScorpokQuestContext(title)
return QA_IsQuestContext(title, QA_SCORPOK_QUEST_ID, QA_IsScorpokTitle)
end
local function QA_IsArrowsForSissiesQuestContext(title)
return QA_IsQuestContext(title, QA_SISSIES_QUEST_ID, QA_IsArrowsForSissiesTitle)
end
local function QA_GetNpcIdFromGuid(guid)
if type(guid) ~= "string" or guid == "" then
return nil
end
local _, _, _, _, _, npcId = string.find(guid, "^Creature%-%d+%-%d+%-%d+%-%d+%-(%d+)%-%x+$")
if npcId then
return tonumber(npcId)
end
if string.sub(guid, 1, 2) == "0x" and string.len(guid) >= 12 then
local hex = string.sub(guid, 9, 12)
local parsed = tonumber(hex, 16)
if parsed and parsed > 0 then
return parsed
end
end
return nil
end
local function QA_ColorByThreshold(count, threshold)
local value = math.floor(tonumber(count) or 0)
if value <= 0 then
return "|cffff0000" .. tostring(value) .. "|r"
end
local modFn = nil
if type(rawget) == "function" and type(math) == "table" then
modFn = rawget(math, "mod") or rawget(math, "fmod")
elseif type(math) == "table" then
modFn = math.fmod
end
if threshold > 0 and type(modFn) == "function" and modFn(value, threshold) == 0 then
return "|cff00ff00" .. tostring(value) .. "|r"
end
return "|cffffa500" .. tostring(value) .. "|r"
end
local function QA_ColorAssay(count)
local value = math.floor(tonumber(count) or 0)
if value > 0 then
return "|cff66ccff" .. tostring(value) .. "|r"
end
return tostring(value)
end
local function QA_MatchesItem(itemId, itemName, expectedId, expectedName)
if expectedId and tonumber(itemId) == tonumber(expectedId) then
return true
end
if type(itemName) == "string" and type(expectedName) == "string" and QA_NormalizeText(itemName) == QA_NormalizeText(expectedName) then
return true
end
return false
end
local function QA_CountItemInBags(expectedId, expectedName)
local getContainerNumSlots = _G and _G["GetContainerNumSlots"] or nil
local getContainerItemLink = _G and _G["GetContainerItemLink"] or nil
local getContainerItemInfo = _G and _G["GetContainerItemInfo"] or nil
local getItemInfo = _G and _G["GetItemInfo"] or nil
if type(getContainerNumSlots) ~= "function" or type(getContainerItemLink) ~= "function" then
return 0
end
local total = 0
for bag = 0, 4 do
local slots = math.floor(tonumber(getContainerNumSlots(bag)) or 0)
for slot = 1, slots do
local link = getContainerItemLink(bag, slot)
if type(link) == "string" and link ~= "" then
local _, _, itemIdStr = string.find(link, "item:(%d+)")
local itemId = tonumber(itemIdStr)
local itemName = nil
if type(getItemInfo) == "function" then
itemName = getItemInfo(link)
end
if QA_MatchesItem(itemId, itemName, expectedId, expectedName) then
local texture, stackCount = nil, nil
if type(getContainerItemInfo) == "function" then
texture, stackCount = getContainerItemInfo(bag, slot)
end
total = total + math.floor(tonumber(stackCount) or 1)
end
end
end
end
return total
end
local function QA_TooltipTrace(message, force)
return
end
local function QA_GetTooltipNpc(tooltip)
if not tooltip or type(tooltip.GetUnit) ~= "function" then
return nil, nil, nil, nil
end
local ok, unitA, unitB = pcall(function()
return tooltip:GetUnit()
end)
local unit = nil
if ok then
if type(unitB) == "string" and unitB ~= "" then
unit = unitB
elseif type(unitA) == "string" and unitA ~= "" then
unit = unitA
end
end
if (type(unit) ~= "string" or unit == "") and type(UnitExists) == "function" and UnitExists("mouseover") then
unit = "mouseover"
end
if type(unit) ~= "string" or unit == "" then
local left1 = (type(getglobal) == "function" and getglobal("GameTooltipTextLeft1")) or (_G and _G["GameTooltipTextLeft1"])
local title = left1 and left1.GetText and left1:GetText() or nil
if type(title) == "string" and title ~= "" then
return nil, title, nil, title
end
return nil, nil, nil, nil
end
local guid = UnitGUID and UnitGUID(unit) or nil
local npcId = QA_GetNpcIdFromGuid(guid)
local name = UnitName and UnitName(unit) or nil
local title = nil
if (type(name) ~= "string" or name == "") then
local left1 = (type(getglobal) == "function" and getglobal("GameTooltipTextLeft1")) or (_G and _G["GameTooltipTextLeft1"])
title = left1 and left1.GetText and left1:GetText() or nil
if type(title) == "string" and title ~= "" then
name = title
end
end
return npcId, name, unit, title
end
local function QA_TooltipAlreadyExtended(tooltip)
if not tooltip or type(tooltip.NumLines) ~= "function" then
return false
end
local lines = math.floor(tonumber(tooltip:NumLines()) or 0)
for i = 1, lines do
local line = (type(getglobal) == "function" and getglobal("GameTooltipTextLeft" .. tostring(i))) or (_G and _G["GameTooltipTextLeft" .. tostring(i)])
local text = line and line.GetText and line:GetText() or nil
if type(text) == "string" and QA_NormalizeText(text) == QA_NormalizeText("Quest Automation") then
return true
end
end
return false
end
local function QA_IsTooltipDrazial(tooltip)
local npcId, npcName = QA_GetTooltipNpc(tooltip)
if tonumber(npcId) == QA_SCORPOK_NPC_ID then
return true
end
if type(npcName) == "string" and npcName ~= "" and QA_NormalizeText(npcName) == QA_NormalizeText(QA_SCORPOK_NPC_NAME) then
return true
end
return false
end
local function QA_AppendDrazialTooltip(tooltip, sourceTag)
sourceTag = tostring(sourceTag or "unknown")
if not (MTH_AutoQuest and MTH_AutoQuest.enabled) then
QA_TooltipTrace("skip: module disabled source=" .. sourceTag)
return
end
if not QA_IsScorpokAutomationEnabled() or not QA_IsScorpokTooltipEnabled() then
QA_TooltipTrace("skip: option disabled source=" .. sourceTag)
return
end
local npcId, npcName, unitToken, title = QA_GetTooltipNpc(tooltip)
local isMatch = tonumber(npcId) == QA_SCORPOK_NPC_ID
if not isMatch and type(npcName) == "string" and npcName ~= "" and QA_NormalizeText(npcName) == QA_NormalizeText(QA_SCORPOK_NPC_NAME) then
isMatch = true
end
if not isMatch then
QA_TooltipTrace("skip: npc mismatch source=" .. sourceTag
.. " unit=" .. tostring(unitToken)
.. " id=" .. tostring(npcId)
.. " name='" .. tostring(npcName or "") .. "'"
.. " title='" .. tostring(title or "") .. "'")
return
end
if QA_TooltipAlreadyExtended(tooltip) then
QA_TooltipTrace("skip: already-extended source=" .. sourceTag)
return
end
local pincerCount = QA_CountItemInBags(QA_ITEM_SCORPOK_PINCER_ID, QA_ITEM_SCORPOK_PINCER_NAME)
local gizzardCount = QA_CountItemInBags(QA_ITEM_VULTURE_GIZZARD_ID, QA_ITEM_VULTURE_GIZZARD_NAME)
local lungCount = QA_CountItemInBags(QA_ITEM_BLASTED_BOAR_LUNG_ID, QA_ITEM_BLASTED_BOAR_LUNG_NAME)
local assayCount = QA_CountItemInBags(QA_ITEM_GROUND_SCORPOK_ASSAY_ID, QA_ITEM_GROUND_SCORPOK_ASSAY_NAME)
tooltip:AddLine(" ")
tooltip:AddLine("|cffffff00Quest Automation|r")
tooltip:AddLine("Scorpok Pincer: " .. QA_ColorByThreshold(pincerCount, 3), 1, 1, 1)
tooltip:AddLine("Vulture Gizzard: " .. QA_ColorByThreshold(gizzardCount, 2), 1, 1, 1)
tooltip:AddLine("Blasted Boar Lung: " .. QA_ColorByThreshold(lungCount, 1), 1, 1, 1)
tooltip:AddLine("Ground Scorpok Assay: " .. QA_ColorAssay(assayCount), 1, 1, 1)
tooltip:AddLine("Spam SHIFT-click!", 0.7, 0.9, 1)
tooltip:AddLine("Recipes: 3x Pincer, 2x Gizzard, 1x Lung", 0.7, 0.7, 0.7)
tooltip:Show()
QA_TooltipTrace("added: source=" .. sourceTag
.. " id=" .. tostring(npcId)
.. " name='" .. tostring(npcName or "") .. "'", true)
end
local function QA_EnsureTooltipHook()
if QA_TooltipHooked then
return
end
if not GameTooltip then
return
end
local hasGetScript = type(GameTooltip.GetScript) == "function"
local hasSetScript = type(GameTooltip.SetScript) == "function"
local hasHookScript = type(GameTooltip.HookScript) == "function"
local onTooltipSetUnitExists = false
local onShowExists = false
if hasGetScript then
local okSetUnit, existingSetUnit = pcall(function()
return GameTooltip:GetScript("OnTooltipSetUnit")
end)
onTooltipSetUnitExists = okSetUnit and type(existingSetUnit) == "function"
local okShow, existingShow = pcall(function()
return GameTooltip:GetScript("OnShow")
end)
onShowExists = okShow and type(existingShow) == "function"
end
if hasHookScript and onTooltipSetUnitExists then
pcall(function()
GameTooltip:HookScript("OnTooltipSetUnit", function()
QA_AppendDrazialTooltip(this, "hook:setunit")
end)
end)
elseif hasSetScript and hasGetScript and onTooltipSetUnitExists then
local okGetPrev, previous = pcall(function()
return GameTooltip:GetScript("OnTooltipSetUnit")
end)
if okGetPrev then
pcall(function()
GameTooltip:SetScript("OnTooltipSetUnit", function()
if type(previous) == "function" then
previous()
end
QA_AppendDrazialTooltip(this, "script:setunit")
end)
end)
end
end
if hasHookScript and onShowExists then
pcall(function()
GameTooltip:HookScript("OnShow", function()
QA_AppendDrazialTooltip(this, "hook:show")
end)
end)
elseif hasSetScript and hasGetScript and onShowExists then
local okGetPrevShow, previousShow = pcall(function()
return GameTooltip:GetScript("OnShow")
end)
if okGetPrevShow then
pcall(function()
GameTooltip:SetScript("OnShow", function()
if type(previousShow) == "function" then
previousShow()
end
QA_AppendDrazialTooltip(this, "script:show")
end)
end)
end
end
QA_TooltipHooked = true
end
local function QA_EnsureTooltipPoller()
if QA_TooltipPollFrame then
return
end
local frame = CreateFrame("Frame", "MTH_AQTooltipPoll")
if not frame then
return
end
frame._mthElapsed = 0
frame:SetScript("OnUpdate", function()
this._mthElapsed = (this._mthElapsed or 0) + (arg1 or 0)
if this._mthElapsed < 0.20 then
return
end
this._mthElapsed = 0
if not (MTH_AutoQuest and MTH_AutoQuest.enabled) then
return
end
if GameTooltip and type(GameTooltip.IsVisible) == "function" and GameTooltip:IsVisible() then
QA_AppendDrazialTooltip(GameTooltip, "poll")
end
end)
QA_TooltipPollFrame = frame
end
local function QA_GetInteractedNpcId()
local getGuid = _G and _G["UnitGUID"] or nil
if type(getGuid) ~= "function" then
return nil
end
local npcGuid = getGuid("npc")
local npcId = QA_GetNpcIdFromGuid(npcGuid)
if npcId then
return npcId
end
return QA_GetNpcIdFromGuid(getGuid("target"))
end
local function QA_GetInteractedNpcName()
local getName = _G and _G["UnitName"] or nil
if type(getName) ~= "function" then
return nil
end
local name = getName("npc")
if type(name) == "string" and name ~= "" then
return name
end
name = getName("target")
if type(name) == "string" and name ~= "" then
return name
end
return nil
end
local function QA_IsInteractedNpc(expectedNpcId, expectedNpcName)
local npcId = QA_GetInteractedNpcId()
if tonumber(npcId) == tonumber(expectedNpcId) then
return true
end
local npcName = QA_GetInteractedNpcName()
if type(npcName) == "string" and npcName ~= "" and QA_NormalizeText(npcName) == QA_NormalizeText(expectedNpcName) then
return true
end
return false
end
local function QA_IsScorpokNpc()
return QA_IsInteractedNpc(QA_SCORPOK_NPC_ID, QA_SCORPOK_NPC_NAME)
end
local function QA_IsArrowsForSissiesNpc()
return QA_IsInteractedNpc(QA_SISSIES_NPC_ID, QA_SISSIES_NPC_NAME)
end
local function QA_RefreshMouseoverTooltip()
local tooltip = _G and _G["GameTooltip"] or GameTooltip
if not tooltip then
return
end
if type(UnitExists) == "function" and UnitExists("mouseover") and type(tooltip.SetUnit) == "function" then
tooltip:SetUnit("mouseover")
if type(tooltip.Show) == "function" then
tooltip:Show()
end
end
end
local function QA_RequestTooltipRefresh(delaySeconds)
delaySeconds = tonumber(delaySeconds) or 0.10
if not QA_TooltipRefreshFrame then
QA_TooltipRefreshFrame = CreateFrame("Frame", "MTH_AQTooltipRefresh")
if not QA_TooltipRefreshFrame then
return
end
QA_TooltipRefreshFrame:SetScript("OnUpdate", function()
local frameRef = this or QA_TooltipRefreshFrame
if not frameRef then
return
end
frameRef._elapsed = (frameRef._elapsed or 0) + (arg1 or 0)
if frameRef._elapsed < (frameRef._delay or 0.10) then
return
end
frameRef._elapsed = 0
frameRef._delay = 0
frameRef:SetScript("OnUpdate", nil)
QA_RefreshMouseoverTooltip()
end)
end
QA_TooltipRefreshFrame._delay = delaySeconds
QA_TooltipRefreshFrame._elapsed = 0
QA_TooltipRefreshFrame:SetScript("OnUpdate", QA_TooltipRefreshFrame:GetScript("OnUpdate"))
end
local QA_PROFILE_SCORPOK = {
key = "scorpokDrazial",
label = "Scorpok",
optionCheck = QA_IsScorpokAutomationEnabled,
npcCheck = QA_IsScorpokNpc,
titleCheck = QA_IsScorpokTitle,
questContextCheck = QA_IsScorpokQuestContext,
lastActionField = "_scorpokLastActionAt",
refreshTooltipOnComplete = true,
}
local QA_PROFILE_SISSIES = {
key = "arrowsForSissies",
label = "ArrowsForSissies",
optionCheck = QA_IsArrowsForSissiesAutomationEnabled,
npcCheck = QA_IsArrowsForSissiesNpc,
titleCheck = QA_IsArrowsForSissiesTitle,
questContextCheck = QA_IsArrowsForSissiesQuestContext,
lastActionField = "_sissiesLastActionAt",
refreshTooltipOnComplete = false,
}
local QA_LastActionAt = {}
local function QA_GetLastActionAt(profile)
local key = type(profile) == "table" and tostring(profile.lastActionField or "") or ""
if key == "" then
return 0
end
return tonumber(QA_LastActionAt[key]) or 0
end
local function QA_SetLastActionAt(profile, value)
local key = type(profile) == "table" and tostring(profile.lastActionField or "") or ""
if key == "" then
return
end
QA_LastActionAt[key] = tonumber(value) or 0
end
local function QA_CanRunProfile(profile)
if type(profile) ~= "table" then
return false
end
if type(profile.optionCheck) ~= "function" or not profile.optionCheck() then
QA_Debug("[" .. tostring(profile.label or "AutoQuest") .. "] skip: option disabled")
return false
end
if type(IsShiftKeyDown) ~= "function" or not IsShiftKeyDown() then
QA_Debug("[" .. tostring(profile.label or "AutoQuest") .. "] skip: SHIFT not held")
return false
end
local npcOk = type(profile.npcCheck) == "function" and profile.npcCheck() or false
if not npcOk then
QA_Debug("[" .. tostring(profile.label or "AutoQuest") .. "] skip: NPC mismatch (id=" .. tostring(QA_GetInteractedNpcId()) .. ", name='" .. tostring(QA_GetInteractedNpcName() or "") .. "')")
end
return npcOk
end
local function QA_FindGossipQuestIndex(rawEntries, count, profile)
if type(rawEntries) ~= "table" or tonumber(count) == nil or tonumber(count) <= 0 then
return nil
end
if type(profile) ~= "table" or type(profile.titleCheck) ~= "function" then
return nil
end
local entryCount = math.floor(tonumber(count) or 0)
local tupleSize = math.floor(table.getn(rawEntries) / entryCount)
if tupleSize < 1 then
tupleSize = 1
end
for i = 1, entryCount do
local title = tostring(rawEntries[((i - 1) * tupleSize) + 1] or "")
if profile.titleCheck(title) then
return i
end
end
if entryCount == 1 and type(profile.npcCheck) == "function" and profile.npcCheck() then
QA_Debug("[" .. tostring(profile.label or "AutoQuest") .. "] gossip fallback: single quest entry -> selecting index 1")
return 1
end
return nil
end
local function QA_FindQuestGreetingIndex(isActive, profile)
local getCount = isActive and _G and _G["GetNumActiveQuests"] or _G and _G["GetNumAvailableQuests"]
local getTitle = isActive and _G and _G["GetActiveTitle"] or _G and _G["GetAvailableTitle"]
if type(getCount) ~= "function" or type(getTitle) ~= "function" or type(profile) ~= "table" or type(profile.titleCheck) ~= "function" then
return nil
end
local count = math.floor(tonumber(getCount()) or 0)
if count <= 0 then
return nil
end
for i = 1, count do
local title = tostring(getTitle(i) or "")
if profile.titleCheck(title) then
return i
end
end
if count == 1 and type(profile.npcCheck) == "function" and profile.npcCheck() then
QA_Debug("[" .. tostring(profile.label or "AutoQuest") .. "] quest greeting fallback: single quest entry -> selecting index 1")
return 1
end
return nil
end
local function QA_GetFrameText(frame)
if type(frame) ~= "table" then
return ""
end
if type(frame.GetText) == "function" then
return tostring(frame:GetText() or "")
end
if type(frame.GetName) == "function" then
local name = frame:GetName()
if type(name) == "string" and name ~= "" then
local textRegion = _G and _G[name .. "Text"] or nil
if textRegion and type(textRegion.GetText) == "function" then
return tostring(textRegion:GetText() or "")
end
end
end
return ""
end
local function QA_ClickGossipTitleButtonFallback(profile)
if type(profile) ~= "table" or type(profile.titleCheck) ~= "function" then
return false
end
for i = 1, 40 do
local button = _G and _G["GossipTitleButton" .. tostring(i)] or nil
if button then
local visible = true
if type(button.IsVisible) == "function" then
visible = button:IsVisible() and true or false
end
if visible then
local title = QA_GetFrameText(button)
if profile.titleCheck(title) then
QA_Debug("action: GossipTitleButton" .. tostring(i) .. " click title='" .. tostring(title) .. "'")
if type(button.Click) == "function" then
button:Click()
return true
end
local onClick = type(button.GetScript) == "function" and button:GetScript("OnClick") or nil
if type(onClick) == "function" then
onClick(button)
return true
end
end
end
end
end
return false
end
local function QA_RunProfileAutomation(eventName, profile)
if type(profile) ~= "table" then
return
end
QA_Debug("[" .. tostring(profile.label or "AutoQuest") .. "] event=" .. tostring(eventName))
if not QA_CanRunProfile(profile) then
return
end
local getTimeFn = _G and _G["GetTime"] or nil
if eventName == "GOSSIP_SHOW" and type(getTimeFn) == "function" then
local now = tonumber(getTimeFn()) or 0
local last = QA_GetLastActionAt(profile)
if (now - last) < 0.05 then
QA_Debug("skip: throttled dt=" .. tostring(now - last))
return
end
end
if eventName == "QUEST_GREETING" then
local selectAvailableQuest = _G and _G["SelectAvailableQuest"] or nil
local selectActiveQuest = _G and _G["SelectActiveQuest"] or nil
local availableIndex = QA_FindQuestGreetingIndex(false, profile)
if availableIndex and type(selectAvailableQuest) == "function" then
QA_Debug("action: SelectAvailableQuest (compat) index=" .. tostring(availableIndex))
selectAvailableQuest()
QA_SetLastActionAt(profile, type(getTimeFn) == "function" and getTimeFn() or 0)
return
end
local activeIndex = QA_FindQuestGreetingIndex(true, profile)
if activeIndex and type(selectActiveQuest) == "function" then
QA_Debug("action: SelectActiveQuest (compat) index=" .. tostring(activeIndex))
selectActiveQuest()
QA_SetLastActionAt(profile, type(getTimeFn) == "function" and getTimeFn() or 0)
return
end
for i = 1, 40 do
local button = _G and _G["QuestTitleButton" .. tostring(i)] or nil
if button and (type(button.IsVisible) ~= "function" or button:IsVisible()) then
local title = QA_GetFrameText(button)
if profile.titleCheck(title) then
QA_Debug("action: QuestTitleButton" .. tostring(i) .. " click title='" .. tostring(title) .. "'")
if type(button.Click) == "function" then
button:Click()
QA_SetLastActionAt(profile, type(getTimeFn) == "function" and getTimeFn() or 0)
return
end
end
end
end
QA_Debug("quest greeting: no action taken")
return
end
if eventName == "GOSSIP_SHOW" then
local getNumGossipAvailableQuests = _G and _G["GetNumGossipAvailableQuests"] or nil
local getGossipAvailableQuests = _G and _G["GetGossipAvailableQuests"] or nil
local selectGossipAvailableQuest = _G and _G["SelectGossipAvailableQuest"] or nil
QA_Debug("api available: numAvail=" .. tostring(type(getNumGossipAvailableQuests) == "function")
.. " getAvail=" .. tostring(type(getGossipAvailableQuests) == "function")
.. " selAvail=" .. tostring(type(selectGossipAvailableQuest) == "function"))
if type(getNumGossipAvailableQuests) == "function" and type(getGossipAvailableQuests) == "function" and type(selectGossipAvailableQuest) == "function" then
local availableCount = math.floor(tonumber(getNumGossipAvailableQuests()) or 0)
QA_Debug("gossip available count=" .. tostring(availableCount))
if availableCount > 0 then
local availableIndex = QA_FindGossipQuestIndex({ getGossipAvailableQuests() }, availableCount, profile)
if availableIndex then
QA_Debug("action: SelectGossipAvailableQuest index=" .. tostring(availableIndex))
selectGossipAvailableQuest(availableIndex)
QA_SetLastActionAt(profile, type(getTimeFn) == "function" and getTimeFn() or 0)
return
end
QA_Debug("gossip available: no Scorpok match")
end
end
local getNumGossipActiveQuests = _G and _G["GetNumGossipActiveQuests"] or nil
local getGossipActiveQuests = _G and _G["GetGossipActiveQuests"] or nil
local selectGossipActiveQuest = _G and _G["SelectGossipActiveQuest"] or nil
QA_Debug("api active: numActive=" .. tostring(type(getNumGossipActiveQuests) == "function")
.. " getActive=" .. tostring(type(getGossipActiveQuests) == "function")
.. " selActive=" .. tostring(type(selectGossipActiveQuest) == "function"))
if type(getNumGossipActiveQuests) == "function" and type(getGossipActiveQuests) == "function" and type(selectGossipActiveQuest) == "function" then
local activeCount = math.floor(tonumber(getNumGossipActiveQuests()) or 0)
QA_Debug("gossip active count=" .. tostring(activeCount))
if activeCount > 0 then
local activeIndex = QA_FindGossipQuestIndex({ getGossipActiveQuests() }, activeCount, profile)
if activeIndex then
QA_Debug("action: SelectGossipActiveQuest index=" .. tostring(activeIndex))
selectGossipActiveQuest(activeIndex)
QA_SetLastActionAt(profile, type(getTimeFn) == "function" and getTimeFn() or 0)
return
end
QA_Debug("gossip active: no Scorpok match")
end
end
if QA_ClickGossipTitleButtonFallback(profile) then
QA_SetLastActionAt(profile, type(getTimeFn) == "function" and getTimeFn() or 0)
return
end
QA_Debug("gossip: no action taken")
return
end
local title = type(GetTitleText) == "function" and tostring(GetTitleText() or "") or ""
QA_Debug("quest frame title='" .. tostring(title) .. "'")
if type(profile.questContextCheck) ~= "function" or not profile.questContextCheck(title) then
QA_Debug("skip: quest context mismatch")
return
end
if eventName == "QUEST_DETAIL" then
if type(AcceptQuest) == "function" then
QA_Debug("action: AcceptQuest")
AcceptQuest()
QA_SetLastActionAt(profile, type(getTimeFn) == "function" and getTimeFn() or 0)
end
elseif eventName == "QUEST_PROGRESS" then
if type(CompleteQuest) == "function" then
if type(IsQuestCompletable) ~= "function" or IsQuestCompletable() then
QA_Debug("action: CompleteQuest")
CompleteQuest()
QA_SetLastActionAt(profile, type(getTimeFn) == "function" and getTimeFn() or 0)
else
QA_Debug("skip: quest not completable yet")
end
end
elseif eventName == "QUEST_COMPLETE" then
if type(GetQuestReward) == "function" then
local choices = type(GetNumQuestChoices) == "function" and math.floor(tonumber(GetNumQuestChoices()) or 0) or 0
if choices <= 1 then
QA_Debug("action: GetQuestReward(1)")
GetQuestReward(1)
QA_SetLastActionAt(profile, type(getTimeFn) == "function" and getTimeFn() or 0)
if profile.refreshTooltipOnComplete then
QA_RequestTooltipRefresh(0.10)
end
else
QA_Debug("skip: multiple reward choices=" .. tostring(choices))
end
end
end
end
-- NOTE: QA_DirectEventFrame removed (Phase 2 fix #22b)
-- The central event router already dispatches GOSSIP_SHOW, QUEST_GREETING,
-- QUEST_DETAIL, QUEST_PROGRESS, QUEST_COMPLETE to MTH_AutoQuest:onEvent().
-- Having a second frame register the same events caused double-dispatch.
function MTH_AutoQuest:init()
local store = QA_GetOptionsStore()
self.initialized = true
QA_Debug("init: module active=" .. tostring(self.enabled and true or false)
.. ", option scorpokDrazial=" .. tostring(store and store.scorpokDrazial and true or false)
.. ", option arrowsForSissies=" .. tostring(store and store.arrowsForSissies and true or false)
.. ", option scorpokTooltip=" .. tostring(store and store.scorpokTooltip and true or false))
end
function MTH_AutoQuest:setEnabled(enabled)
self.enabled = enabled and true or false
end
function MTH_AutoQuest:onEvent(eventName)
if eventName == "GOSSIP_SHOW"
or eventName == "QUEST_GREETING"
or eventName == "QUEST_DETAIL"
or eventName == "QUEST_PROGRESS"
or eventName == "QUEST_COMPLETE" then
QA_Debug("onEvent=" .. tostring(eventName))
QA_RunProfileAutomation(eventName, QA_PROFILE_SCORPOK)
QA_RunProfileAutomation(eventName, QA_PROFILE_SISSIES)
end
end
function MTH_AutoQuest:cleanup()
-- no-op: direct event frame removed in Phase 2
end
MTH:RegisterModule("autoquest", MTH_AutoQuest)
+4 -2
View File
@@ -43,9 +43,11 @@ function MTH_ChronometerHunterInstallData(engine)
engine:AddTimer(engine.EVENT, BS["Frost Trap Aura"], 30, 0, 0, 0, { gr = 1, cr = "CYAN", a = 1, d = { tn = BS["Clever Traps"], tb = 0.15, tp = 1 }, xn = BS["Frost Trap"] }) engine:AddTimer(engine.EVENT, BS["Frost Trap Aura"], 30, 0, 0, 0, { gr = 1, cr = "CYAN", a = 1, d = { tn = BS["Clever Traps"], tb = 0.15, tp = 1 }, xn = BS["Frost Trap"] })
engine:AddTimer(engine.EVENT, BS["Immolation Trap Effect"], 15, 1, 0, 1, { gr = 1, cr = "ORANGE", a = 1, xn = BS["Immolation Trap"] }) engine:AddTimer(engine.EVENT, BS["Immolation Trap Effect"], 15, 1, 0, 1, { gr = 1, cr = "ORANGE", a = 1, 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 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 = "YELLOW", xn = BS["Wing Clip"] }) 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["Piercing Shot"], 8, 1, 0, 1, { a = 1, cr = "PURPLE", tx = "Interface\\Icons\\Ability_Hunter_DisarmingShot" }) 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["Quick Shots"], 12, 0, 1, 1, { a = 1, cr = "MAROON", tx = "Interface\\Icons\\Ability_Hunter_Quickshot" }) engine:AddTimer(engine.EVENT, BS["Entrapment"], 5, 1, 0, 1, { a = 1, cr = "MAROON", tx = "Interface\\Icons\\Spell_Nature_StrangleVines" })
engine:AddTimer(engine.EVENT, BS["Quick Shots"], 12, 0, 1, 1, { a = 1, cr = "MAROON", tx = "Interface\\Icons\\Ability_Warrior_InnerRage" })
engine:AddTimer(engine.EVENT, BS["Wing Clip"], 10, 1, 0, 1, { a = 1, cr = "YELLOW" })
engine:AddTimer(engine.EVENT, BS["Scorpid Poison"], 10, 1, 0, 0, { gr = 3, cr = "PURPLE", a = 1, dn = 1 }) engine:AddTimer(engine.EVENT, BS["Scorpid Poison"], 10, 1, 0, 0, { gr = 3, cr = "PURPLE", a = 1, dn = 1 })
engine:AddTimer(engine.EVENT, BS["Devilsaur Fury"], 20, 0, 1, 1, { a = 1, cr = "PURPLE", xn = BS["Devilsaur Eye"], tx = "Interface\\Icons\\Ability_Hunter_Pet_Raptor" }) engine:AddTimer(engine.EVENT, BS["Devilsaur Fury"], 20, 0, 1, 1, { a = 1, cr = "PURPLE", xn = BS["Devilsaur Eye"], tx = "Interface\\Icons\\Ability_Hunter_Pet_Raptor" })
engine:AddTimer(engine.EVENT, BS["Restless Strength"], 20, 0, 1, 1, { a = 1, cr = "PURPLE", xn = BS["Zandalarian Hero Medallion"], tx = "Interface\\Icons\\INV_Jewelry_Necklace_13" }) engine:AddTimer(engine.EVENT, BS["Restless Strength"], 20, 0, 1, 1, { a = 1, cr = "PURPLE", xn = BS["Zandalarian Hero Medallion"], tx = "Interface\\Icons\\INV_Jewelry_Necklace_13" })
+365 -26
View File
@@ -59,6 +59,45 @@ 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 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" local BAR_GROUP = "MTHChronometer"
local PARSER_OWNER = "MTHChronometerHunter" local PARSER_OWNER = "MTHChronometerHunter"
local MTH_CHRON_TRACE_ENABLED = false
local function MTH_CHRON_Trace(msg)
if not MTH_CHRON_TRACE_ENABLED then
return
end
if MTH and MTH.Print then
MTH:Print("[CHRONTRACE] " .. tostring(msg), "debug")
elseif DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then
DEFAULT_CHAT_FRAME:AddMessage("[CHRONTRACE] " .. tostring(msg))
end
end
local function MTH_CHRON_FormatBarPosition(profile)
local bp = profile and profile.barposition
if type(bp) ~= "table" then
return "<none>"
end
return tostring(bp.point or "nil")
.. "/" .. tostring(bp.relativePoint or "nil")
.. " @(" .. tostring(bp.x) .. "," .. tostring(bp.y) .. ")"
end
local function MTH_CHRON_DescribePoint(frame)
if not (frame and frame.GetPoint) then
return "<no-frame>"
end
local point, relTo, relPoint, x, y = frame:GetPoint()
local relName = "nil"
if type(relTo) == "table" and relTo.GetName then
relName = tostring(relTo:GetName() or "<anon>")
elseif relTo then
relName = tostring(relTo)
end
return tostring(point or "nil")
.. "->" .. relName
.. ":" .. tostring(relPoint or "nil")
.. " @(" .. tostring(x) .. "," .. tostring(y) .. ")"
end
local COLOR_NAME_MAP = { local COLOR_NAME_MAP = {
white = { 1.0, 1.0, 1.0 }, white = { 1.0, 1.0, 1.0 },
@@ -143,15 +182,80 @@ local function shallowCopy(source)
return dest return dest
end end
local function deepCopyValue(value)
if type(value) ~= "table" then
return value
end
local copy = {}
for key, entry in pairs(value) do
copy[key] = deepCopyValue(entry)
end
return copy
end
local function ensureProfile() local function ensureProfile()
if not MTH or not MTH.GetModuleSavedVariables then if not MTH or not MTH.GetModuleCharSavedVariables then
MTH_CHRON_Trace("ensureProfile fallback defaults (no MTH store)")
return shallowCopy(DEFAULTS) return shallowCopy(DEFAULTS)
end end
local store = MTH:GetModuleSavedVariables("chronometer") local store = MTH:GetModuleCharSavedVariables("chronometer")
if type(store) ~= "table" then
MTH_CHRON_Trace("ensureProfile fallback defaults (invalid store)")
return shallowCopy(DEFAULTS)
end
if type(store.profile) ~= "table"
and type(MTH_CharSavedVariables) == "table"
and type(MTH_CharSavedVariables.chronometer) == "table"
then
local legacyChar = MTH_CharSavedVariables.chronometer
if type(legacyChar.profile) == "table" then
store.profile = deepCopyValue(legacyChar.profile)
MTH_CHRON_Trace("ensureProfile migrated legacy MTH_CharSavedVariables.chronometer.profile")
elseif type(legacyChar.barposition) == "table" then
store.profile = { barposition = deepCopyValue(legacyChar.barposition) }
MTH_CHRON_Trace("ensureProfile migrated legacy MTH_CharSavedVariables.chronometer.barposition")
end
end
if type(store.profile) ~= "table"
and type(MTH_SavedVariables) == "table"
and type(MTH_SavedVariables.chronometer) == "table"
then
local legacyAccount = MTH_SavedVariables.chronometer
if type(legacyAccount.profile) == "table" then
store.profile = deepCopyValue(legacyAccount.profile)
MTH_CHRON_Trace("ensureProfile migrated legacy MTH_SavedVariables.chronometer.profile")
elseif type(legacyAccount.barposition) == "table" then
store.profile = { barposition = deepCopyValue(legacyAccount.barposition) }
MTH_CHRON_Trace("ensureProfile migrated legacy MTH_SavedVariables.chronometer.barposition")
end
end
if type(store.profile) ~= "table" and MTH.GetModuleSavedVariables then
local accountStore = MTH:GetModuleSavedVariables("chronometer")
if type(accountStore) == "table" and type(accountStore.profile) == "table" then
store.profile = deepCopyValue(accountStore.profile)
MTH_CHRON_Trace("ensureProfile copied account profile into char store")
end
end
if type(store.profile) ~= "table" then if type(store.profile) ~= "table" then
store.profile = {} store.profile = {}
end end
if type(store.profile.barposition) ~= "table" and type(store.barposition) == "table" then
store.profile.barposition = deepCopyValue(store.barposition)
MTH_CHRON_Trace("ensureProfile migrated legacy char barposition -> profile.barposition")
end
if type(store.profile.barposition) ~= "table" and MTH.GetModuleSavedVariables then
local accountStore = MTH:GetModuleSavedVariables("chronometer")
if type(accountStore) == "table" then
if type(accountStore.barposition) == "table" then
store.profile.barposition = deepCopyValue(accountStore.barposition)
MTH_CHRON_Trace("ensureProfile migrated legacy account barposition -> profile.barposition")
elseif type(accountStore.profile) == "table" and type(accountStore.profile.barposition) == "table" then
store.profile.barposition = deepCopyValue(accountStore.profile.barposition)
MTH_CHRON_Trace("ensureProfile copied account profile.barposition -> char profile.barposition")
end
end
end
local profile = store.profile local profile = store.profile
for key, value in pairs(DEFAULTS) do for key, value in pairs(DEFAULTS) do
@@ -178,9 +282,68 @@ local function ensureProfile()
profile.disabledSpells.HUNTER = {} profile.disabledSpells.HUNTER = {}
end end
MTH_CHRON_Trace("ensureProfile result barposition=" .. MTH_CHRON_FormatBarPosition(profile))
return profile return profile
end end
local function MTH_CHRON_PersistAnchorPosition(self, reason)
if not (self and self.anchor and self.anchor.GetPoint) then
return false
end
if type(self.profile) ~= "table" then
return false
end
if type(self.profile.barposition) ~= "table" then
self.profile.barposition = {}
end
local point, _, relPoint, x, y = self.anchor:GetPoint()
x = tonumber(x)
y = tonumber(y)
if not (point and relPoint and x and y) then
return false
end
x = math.floor(x + 0.5)
y = math.floor(y + 0.5)
self.profile.barposition.point = point
self.profile.barposition.relativePoint = relPoint
self.profile.barposition.x = x
self.profile.barposition.y = y
MTH_CHRON_Trace("persist-anchor reason=" .. tostring(reason or "")
.. " profile=" .. MTH_CHRON_FormatBarPosition(self.profile))
return true
end
local function MTH_CHRON_RestoreAnchorFromProfile(self, reason)
if not (self and self.anchor and self.anchor.ClearAllPoints and self.anchor.SetPoint) then
return false
end
if type(self.profile) ~= "table" then
return false
end
local bp = self.profile.barposition
if type(bp) ~= "table" then
return false
end
local px = tonumber(bp.x)
local py = tonumber(bp.y)
local ppoint = tostring(bp.point or "")
local prelpoint = tostring(bp.relativePoint or "")
if not (px and py and ppoint ~= "") then
MTH_CHRON_Trace("restore-anchor skipped reason=" .. tostring(reason or "")
.. " profile=" .. MTH_CHRON_FormatBarPosition(self.profile))
return false
end
if prelpoint == "" then
prelpoint = ppoint
end
self.anchor:ClearAllPoints()
self.anchor:SetPoint(ppoint, UIParent, prelpoint, px, py)
MTH_CHRON_Trace("restore-anchor applied reason=" .. tostring(reason or "")
.. " frame=" .. MTH_CHRON_DescribePoint(self.anchor))
return true
end
local function MTH_CHRON_IsPersistedEnabled() local function MTH_CHRON_IsPersistedEnabled()
if MTH and MTH.IsModuleEnabled then if MTH and MTH.IsModuleEnabled then
return MTH:IsModuleEnabled("chronometer", true) and true or false return MTH:IsModuleEnabled("chronometer", true) and true or false
@@ -252,22 +415,92 @@ local function parseRankNumber(text)
return 0 return 0
end end
local function resolvePlayerClassBucket(profile)
profile = profile or {}
local buckets = profile.disabledSpells
if type(buckets) ~= "table" then
return "HUNTER"
end
local localizedClass, classToken = UnitClass("player")
local candidates = {
classToken,
localizedClass,
string.upper(tostring(classToken or "")),
string.upper(tostring(localizedClass or "")),
"HUNTER",
}
for i = 1, table.getn(candidates) do
local key = tostring(candidates[i] or "")
if key ~= "" and type(buckets[key]) == "table" then
return key
end
end
return tostring(classToken or localizedClass or "HUNTER")
end
local function normalizeTimerName(name)
local normalized = tostring(name or "")
normalized = string.gsub(normalized, "^%s+", "")
normalized = string.gsub(normalized, "%s+$", "")
normalized = string.gsub(normalized, "%s+", " ")
normalized = string.lower(normalized)
return normalized
end
local function isTimerDisabled(profile, timerClass, timerName)
local disabledSpells = profile and profile.disabledSpells
if type(disabledSpells) ~= "table" then
return false, "no-disabled-table"
end
local classBucket = disabledSpells[timerClass]
if type(classBucket) ~= "table" then
return false, "no-class-bucket"
end
if classBucket[timerName] ~= nil then
return true, "exact"
end
local wanted = normalizeTimerName(timerName)
if wanted == "" then
return false, "empty-name"
end
for key, value in pairs(classBucket) do
if value ~= nil and normalizeTimerName(key) == wanted then
return true, "normalized"
end
end
return false, "miss"
end
local function getActionSpell(slot) local function getActionSpell(slot)
if GetActionText(slot) or not HasAction(slot) then if GetActionText(slot) or not HasAction(slot) then
return nil, 0 return nil, 0
end end
if not Chronometer._scanTooltip then if not Chronometer._scanTooltip then
Chronometer._scanTooltip = CreateFrame("GameTooltip", "MTH_ChronometerScanTooltip", UIParent, "GameTooltipTemplate") local tip = CreateFrame("GameTooltip", "MTH_ChrBarProbe", UIParent)
Chronometer._scanTooltip:SetOwner(UIParent, "ANCHOR_NONE") tip:SetOwner(UIParent, "ANCHOR_NONE")
for i = 1, 4 do
local L = tip:CreateFontString("MTH_ChrBarProbeTextLeft"..i, "ARTWORK", "GameTooltipText")
local R = tip:CreateFontString("MTH_ChrBarProbeTextRight"..i, "ARTWORK", "GameTooltipText")
tip:AddFontStrings(L, R)
end
Chronometer._scanTooltip = tip
end end
local tooltip = Chronometer._scanTooltip local tooltip = Chronometer._scanTooltip
tooltip:ClearLines() tooltip:ClearLines()
tooltip:SetAction(slot) tooltip:SetAction(slot)
local left1 = getglobal("MTH_ChronometerScanTooltipTextLeft1") local left1 = getglobal("MTH_ChrBarProbeTextLeft1")
local left2 = getglobal("MTH_ChronometerScanTooltipTextLeft2") local left2 = getglobal("MTH_ChrBarProbeTextLeft2")
local spellName = left1 and left1:GetText() or nil local spellName = left1 and left1:GetText() or nil
if not spellName or spellName == "" then if not spellName or spellName == "" then
return nil, 0 return nil, 0
@@ -294,6 +527,7 @@ function Chronometer:MTH_Initialize()
end end
self.profile = ensureProfile() self.profile = ensureProfile()
MTH_CHRON_Trace("MTH_Initialize profile=" .. MTH_CHRON_FormatBarPosition(self.profile))
self.parser = ParserLib:GetInstance("1.1") self.parser = ParserLib:GetInstance("1.1")
self.COLOR_MAP = { self.COLOR_MAP = {
@@ -304,6 +538,7 @@ function Chronometer:MTH_Initialize()
} }
self.anchor = self:CreateAnchor("MetaHunt Chronometer", 0, 1, 0) self.anchor = self:CreateAnchor("MetaHunt Chronometer", 0, 1, 0)
MTH_CHRON_Trace("MTH_Initialize anchor-created point=" .. MTH_CHRON_DescribePoint(self.anchor))
self:RegisterCandyBarGroup(BAR_GROUP) self:RegisterCandyBarGroup(BAR_GROUP)
self:SetCandyBarGroupPoint(BAR_GROUP, "TOP", self.anchor, "BOTTOM", 0, 0) self:SetCandyBarGroupPoint(BAR_GROUP, "TOP", self.anchor, "BOTTOM", 0, 0)
@@ -312,16 +547,19 @@ end
function Chronometer:MTH_Enable() function Chronometer:MTH_Enable()
self._mth_explicitEnable = true self._mth_explicitEnable = true
MTH_CHRON_Trace("MTH_Enable called")
self:MTH_Initialize() self:MTH_Initialize()
self:OnEnable() self:OnEnable()
self._mth_explicitEnable = nil self._mth_explicitEnable = nil
end end
function Chronometer:MTH_Disable() function Chronometer:MTH_Disable()
MTH_CHRON_Trace("MTH_Disable called")
self:OnDisable() self:OnDisable()
end end
function Chronometer:OnEnable() function Chronometer:OnEnable()
MTH_CHRON_Trace("OnEnable begin enabled=" .. tostring(self._mth_enabled and true or false))
if self._mth_enabled then if self._mth_enabled then
return return
end end
@@ -351,8 +589,13 @@ function Chronometer:OnEnable()
self._mth_enabled = true self._mth_enabled = true
self.profile = ensureProfile() self.profile = ensureProfile()
MTH_CHRON_Trace("OnEnable profile-after-ensure=" .. MTH_CHRON_FormatBarPosition(self.profile))
self:SetCandyBarGroupGrowth(BAR_GROUP, self.profile.growup and true or false) self:SetCandyBarGroupGrowth(BAR_GROUP, self.profile.growup and true or false)
self:SetCandyBarGroupVerticalSpacing(BAR_GROUP, self.profile.spacing or 0) self:SetCandyBarGroupVerticalSpacing(BAR_GROUP, self.profile.spacing or 0)
if self.anchor then
MTH_CHRON_Trace("OnEnable anchor-current-point=" .. MTH_CHRON_DescribePoint(self.anchor))
end
MTH_CHRON_RestoreAnchorFromProfile(self, "OnEnable")
self.groups = {} self.groups = {}
self.timers = {} self.timers = {}
@@ -430,16 +673,39 @@ function Chronometer:OnEnable()
self:RegisterEvent("SPELLCAST_INTERRUPTED") self:RegisterEvent("SPELLCAST_INTERRUPTED")
self:RegisterEvent("SPELLCAST_START") self:RegisterEvent("SPELLCAST_START")
self:RegisterEvent("SPELLCAST_STOP") self:RegisterEvent("SPELLCAST_STOP")
self:RegisterEvent("UNIT_AURA")
self:RegisterEvent("PLAYER_DEAD") self:RegisterEvent("PLAYER_DEAD")
self:RegisterEvent("VARIABLES_LOADED")
self:RegisterEvent("PLAYER_ENTERING_WORLD")
self:RegisterEvent("PLAYER_LOGOUT")
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_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_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) self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_FAILED_LOCALPLAYER", function(event, info) self:SPELL_FAILED(event, info) end)
end end
function Chronometer:VARIABLES_LOADED()
self.profile = ensureProfile()
MTH_CHRON_RestoreAnchorFromProfile(self, "VARIABLES_LOADED")
end
function Chronometer:PLAYER_ENTERING_WORLD()
self.profile = ensureProfile()
MTH_CHRON_RestoreAnchorFromProfile(self, "PLAYER_ENTERING_WORLD")
end
function Chronometer:PLAYER_LOGOUT()
MTH_CHRON_PersistAnchorPosition(self, "PLAYER_LOGOUT")
end
function Chronometer:OnDisable() function Chronometer:OnDisable()
if not self._mth_enabled then if not self._mth_enabled then
return return
end end
MTH_CHRON_Trace("OnDisable begin profile=" .. MTH_CHRON_FormatBarPosition(self.profile))
if self.anchor then
MTH_CHRON_Trace("OnDisable anchor-point=" .. MTH_CHRON_DescribePoint(self.anchor))
end
MTH_CHRON_PersistAnchorPosition(self, "OnDisable")
self._mth_enabled = false self._mth_enabled = false
if self.bars then if self.bars then
@@ -543,9 +809,12 @@ function Chronometer:StartTimer(timer, name, target, rank, durmod)
end end
end end
local _, class = UnitClass("player") local timerClass = timer.x.cl
local timerClass = timer.x.cl == nil and class or timer.x.cl if timerClass == nil then
if self.profile.disabledSpells[timerClass] and self.profile.disabledSpells[timerClass][name] ~= nil then timerClass = resolvePlayerClassBucket(self.profile)
end
local blocked, reason = isTimerDisabled(self.profile, timerClass, name)
if blocked then
return return
end end
@@ -928,7 +1197,7 @@ function Chronometer:ToggleAnchor()
end end
function Chronometer:CreateAnchor(text, r, g, b) function Chronometer:CreateAnchor(text, r, g, b)
local frame = CreateFrame("Button", "MTHChronometerAnchor", UIParent) local frame = CreateFrame("Button", "MTH_ChronometerAnchor", UIParent)
frame:SetWidth(220) frame:SetWidth(220)
frame:SetHeight(25) frame:SetHeight(25)
frame.owner = self frame.owner = self
@@ -938,31 +1207,41 @@ function Chronometer:CreateAnchor(text, r, g, b)
local px = tonumber(self.profile and self.profile.barposition and self.profile.barposition.x) local px = tonumber(self.profile and self.profile.barposition and self.profile.barposition.x)
local py = tonumber(self.profile and self.profile.barposition and self.profile.barposition.y) local py = tonumber(self.profile and self.profile.barposition and self.profile.barposition.y)
local ppoint = tostring(self.profile and self.profile.barposition and self.profile.barposition.point or "")
local prelpoint = tostring(self.profile and self.profile.barposition and self.profile.barposition.relativePoint or "")
MTH_CHRON_Trace("CreateAnchor saved-in profile=" .. MTH_CHRON_FormatBarPosition(self.profile))
if px ~= nil and py ~= nil then if px ~= nil and py ~= nil then
if ppoint == "" then
ppoint = "TOPLEFT"
end
if prelpoint == "" then
prelpoint = ppoint
end
frame:ClearAllPoints() frame:ClearAllPoints()
frame:SetPoint("TOPLEFT", UIParent, "TOPLEFT", px, py) frame:SetPoint(ppoint, UIParent, prelpoint, px, py)
MTH_CHRON_Trace("CreateAnchor restored point=" .. MTH_CHRON_DescribePoint(frame))
else else
frame:SetPoint("CENTER", UIParent, "CENTER", 0, 50) frame:SetPoint("CENTER", UIParent, "CENTER", 0, 50)
MTH_CHRON_Trace("CreateAnchor default point=" .. MTH_CHRON_DescribePoint(frame))
end end
frame:SetScript("OnDragStart", function(self) frame:SetScript("OnDragStart", function()
self = self or this if not this or not this.StartMoving then
if not self or not self.StartMoving then
return return
end end
self:StartMoving() MTH_CHRON_Trace("anchor drag-start point=" .. MTH_CHRON_DescribePoint(this))
this:StartMoving()
end) end)
frame:SetScript("OnDragStop", function(self) frame:SetScript("OnDragStop", function()
self = self or this if not this then
if not self then
return return
end end
if self.StopMovingOrSizing then if this.StopMovingOrSizing then
self:StopMovingOrSizing() this:StopMovingOrSizing()
end end
local point, _, _, x, y = self:GetPoint() local point, _, _, x, y = this:GetPoint()
x = tonumber(x) x = tonumber(x)
y = tonumber(y) y = tonumber(y)
if not x or not y then if not x or not y then
@@ -971,12 +1250,16 @@ function Chronometer:CreateAnchor(text, r, g, b)
x = math.floor(x + 0.5) x = math.floor(x + 0.5)
y = math.floor(y + 0.5) y = math.floor(y + 0.5)
self:ClearAllPoints() this:ClearAllPoints()
self:SetPoint(point or "TOPLEFT", UIParent, point or "TOPLEFT", x, y) this:SetPoint(point or "TOPLEFT", UIParent, point or "TOPLEFT", x, y)
if self.owner and self.owner.profile and type(self.owner.profile.barposition) == "table" then if this.owner and this.owner.profile and type(this.owner.profile.barposition) == "table" then
self.owner.profile.barposition.x = x this.owner.profile.barposition.point = point or "TOPLEFT"
self.owner.profile.barposition.y = y this.owner.profile.barposition.relativePoint = point or "TOPLEFT"
this.owner.profile.barposition.x = x
this.owner.profile.barposition.y = y
MTH_CHRON_Trace("anchor drag-stop saved profile=" .. MTH_CHRON_FormatBarPosition(this.owner.profile)
.. " frame=" .. MTH_CHRON_DescribePoint(this))
end end
end) end)
@@ -1102,6 +1385,62 @@ function Chronometer:PLAYER_DEAD()
end end
end end
function Chronometer:UNIT_AURA(unit)
local auraUnit = unit
if (not auraUnit or auraUnit == "") and type(arg1) == "string" then
auraUnit = arg1
end
if auraUnit ~= "pet" then
return
end
if not (UnitExists and UnitExists("pet")) then
return
end
local feedSpell = BS and BS["Feed Pet"] or "Feed Pet"
local timer = self.timers and self.timers[self.SPELL] and self.timers[self.SPELL][feedSpell]
if not timer then
return
end
local hasFeedAura = false
if type(UnitBuff) == "function" then
for i = 1, 32 do
local texture = UnitBuff("pet", i)
if not texture then
break
end
local tex = tostring(texture)
if string.find(tex, "Ability_Hunter_BeastTraining", 1, true)
or string.find(tex, "INV_Misc_Fork&Knife", 1, true)
then
hasFeedAura = true
break
end
end
end
if not hasFeedAura then
return
end
local petName = UnitName and UnitName("pet") or "none"
if not petName or petName == "" then
petName = "none"
end
for i = 1, 20 do
local bar = self.bars and self.bars[i]
if bar and bar.id and bar.name == feedSpell then
if bar.target == petName or bar.target == "none" then
return
end
end
end
self:StartTimer(timer, feedSpell, petName)
end
function Chronometer:UseAction(slot, clicked, onself) function Chronometer:UseAction(slot, clicked, onself)
local name, rank = getActionSpell(slot) local name, rank = getActionSpell(slot)
if name then if name then
@@ -8,7 +8,6 @@ Documentation: http://web.archive.org/web/20070314234510/http://wowace.com/wiki/
Description: A timer bars library. Description: A timer bars library.
Dependencies: AceLibrary, AceOO-2.0, PaintChips-2.0 Dependencies: AceLibrary, AceOO-2.0, PaintChips-2.0
]] ]]
local match = string.match
local getn,setn,tinsert = table.getn, table.setn,table.insert local getn,setn,tinsert = table.getn, table.setn,table.insert
local vmajor, vminor = "CandyBar-2.0", "$Revision: 16011 $" local vmajor, vminor = "CandyBar-2.0", "$Revision: 16011 $"
+21 -1
View File
@@ -1,13 +1,28 @@
local MTH_ChronometerModule = { local MTH_ChronometerModule = {
name = "chronometer", name = "chronometer",
enabled = true, enabled = true,
version = "1.0.4", version = "1.2.0",
events = {}, events = {},
initialized = false, initialized = false,
} }
local MTH_CHRON_MODULE_TRACE_ENABLED = false
local function MTH_CHRON_ModuleTrace(msg)
if not MTH_CHRON_MODULE_TRACE_ENABLED then
return
end
if MTH and MTH.Print then
MTH:Print("[CHRONTRACE] " .. tostring(msg), "debug")
elseif DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then
DEFAULT_CHAT_FRAME:AddMessage("[CHRONTRACE] " .. tostring(msg))
end
end
local function MTH_CHRON_ApplyRuntimeEnabledState(enabled) local function MTH_CHRON_ApplyRuntimeEnabledState(enabled)
MTH_CHRON_ModuleTrace("module apply runtime enabled=" .. tostring(enabled and true or false))
if not MTH_ChronometerHunter then if not MTH_ChronometerHunter then
MTH_CHRON_ModuleTrace("module apply runtime skipped (engine unavailable)")
return return
end end
if enabled then if enabled then
@@ -22,14 +37,18 @@ local function MTH_CHRON_ApplyRuntimeEnabledState(enabled)
end end
function MTH_ChronometerModule:init() function MTH_ChronometerModule:init()
MTH_CHRON_ModuleTrace("module init begin enabled=" .. tostring(self.enabled and true or false))
if MTH_ChronometerHunter and MTH_ChronometerHunter.MTH_Initialize then if MTH_ChronometerHunter and MTH_ChronometerHunter.MTH_Initialize then
MTH_ChronometerHunter:MTH_Initialize() MTH_ChronometerHunter:MTH_Initialize()
end end
MTH_CHRON_ApplyRuntimeEnabledState(self.enabled and true or false) MTH_CHRON_ApplyRuntimeEnabledState(self.enabled and true or false)
self.initialized = true self.initialized = true
MTH_CHRON_ModuleTrace("module init end initialized=true")
end end
function MTH_ChronometerModule:setEnabled(enabled) function MTH_ChronometerModule:setEnabled(enabled)
MTH_CHRON_ModuleTrace("module setEnabled enabled=" .. tostring(enabled and true or false)
.. " initialized=" .. tostring(self.initialized and true or false))
if not self.initialized then if not self.initialized then
self:init() self:init()
end end
@@ -37,6 +56,7 @@ function MTH_ChronometerModule:setEnabled(enabled)
end end
function MTH_ChronometerModule:cleanup() function MTH_ChronometerModule:cleanup()
MTH_CHRON_ModuleTrace("module cleanup")
if MTH_ChronometerHunter and MTH_ChronometerHunter.MTH_Disable then if MTH_ChronometerHunter and MTH_ChronometerHunter.MTH_Disable then
MTH_ChronometerHunter:MTH_Disable() MTH_ChronometerHunter:MTH_Disable()
end end
File diff suppressed because it is too large Load Diff
+1 -127
View File
@@ -4,7 +4,7 @@
------------------------------------------------------ ------------------------------------------------------
-- Key bindings -- Key bindings
BINDING_HEADER_FEEDOMATIC = "Fizzwidget Feed-O-Matic"; -- NOTE: BINDING_HEADER_FEEDOMATIC is defined in api/localization.lua via the MTH_L() system.
BINDING_NAME_FEEDOMATIC = "Feed Pet"; BINDING_NAME_FEEDOMATIC = "Feed Pet";
-- Diet names. These should be the all-lowercase versions of the six diets returned from GetPetFoodTypes(). (Want to get them all nice and quick for your localization? Go tame a bear... they eat anything.) -- Diet names. These should be the all-lowercase versions of the six diets returned from GetPetFoodTypes(). (Want to get them all nice and quick for your localization? Go tame a bear... they eat anything.)
@@ -111,110 +111,6 @@ FOM_OptionsButtonText = {
}; };
------------------------------------------------------ ------------------------------------------------------
if (GetLocale() == "frFR") then
-- Diet names. These should be the all-lowercase versions of the six diets returned from GetPetFoodTypes(). (Want to get them all nice and quick for your localization? Go tame a bear... they eat anything.)
-- THESE STRINGS MUST BE LOCALIZED for Feed-O-Matic to work properly in other locales.
FOM_DIET_MEAT = "viande";
FOM_DIET_FISH = "poisson";
FOM_DIET_BREAD = "pain";
FOM_DIET_CHEESE = "fromage";
FOM_DIET_FRUIT = "fruit";
FOM_DIET_FUNGUS = "champignon";
-- If the player has a buff whose icon name contains "Ability_Mount" and whose name contains one of these substrings, we assume the player is mounted. We have to use this rather oblique way to check for mounted because some other buffs use the Ability_Mount_* icons. If these aren't localized, we may not recognize when the player is mounted and still try to feed the pet.
FOM_MOUNT_NAME_SUBSTRINGS = { "kodo", "loup", "raptor", "steed", "cheval", "bélier", "tigre", "mécanotrotteur", };
-- It's not clear whether the 5th and 6th returns from GetItemInfo() are supposed to be localized... so we have localized keys for them just in case. If these aren't localized, we'll just needlessly search your ammo bags for food.
FOM_AMMO_POUCH = "Giberne";
FOM_QUIVER = "Carquois";
-- From here on down, the localized strings are just for readability... they don't affect whether Feed-O-Matic works.
-- Two special diets; one is used for tracking food that provides a bonus (or at least, that you don't want to have fed to your pet when the 'savebonus' option is on), and another that's used in the chat-line interface for listing all diets.
FOM_DIET_BONUS = "bonus";
FOM_DIET_ALL = "tous";
-- Used in tooltips to indicate food quality.
FOM_QUALITY_UNKNOWN = "%s peut le manger, mais n'a jamais essayé.";
FOM_QUALITY_UNDER = "%s n'en mange plus désormais.";
FOM_QUALITY_MIGHT = "%s en mangera peut-être.";
FOM_QUALITY_WILL = "%s en mangera.";
FOM_QUALITY_LIKE = "%s aime en manger.";
FOM_QUALITY_LOVE = "%s adore en manger.";
-- User-visible errors
FOM_ERROR_NO_PET = "Vous n'avez pas de familier.";
FOM_ERROR_PET_DEAD = "Votre familier est mort.";
FOM_ERROR_NO_FEEDABLE_PET = "Vous n'avez pas de familier capable de manger.";
FOM_ERROR_FOOD_NOT_FOUND = "%s n'a pas trouvé de %s dans votre sac.";
FOM_ERROR_NO_FOOD = "%s n'a pas trouvé de nourriture dans votre sac.";
-- Feeding status messages
FOM_FEEDING_EAT_ANOTHER = "%s n'aime pas cette nourriture et va essayer autre chose..."
FOM_FEEDING_FEED_ANOTHER = "cherche autre chose à donner à %s...";
FOM_FEEDING_EAT = "%s mange un(e) %s.";
FOM_FEEDING_FEED = "donne à %s à manger un(e) %s. ";
-- Beast family names
BAT = "Chauve-souris";
BEAR = "Ours";
BOAR = "Sanglier";
CARRION_BIRD = "Charognard";
CAT = "Félin";
CRAB = "Crabe";
CROCOLISK = "Crocilisque";
GORILLA = "Gorille";
HYENA = "Hyène";
OWL = "Chouette";
RAPTOR = "Raptor";
SCORPID = "Scorpide";
SPIDER = "Araignée";
TALLSTRIDER = "Haut-trotteur";
TURTLE = "Tortue";
WIND_SERPENT = "Serpent des vents";
WOLF = "Loup";
FOM_PET_HUNGRY = "%s a faim!";
FOM_PET_VERY_HUNGRY = "%s a très faim!";
FOM_OPTIONS_HEADER = "Feed-O-Matic Options";
FOM_OPTIONS_GENERAL = "Options générales:";
FOM_OPTIONS_FOOD_CHOICE = "Eviter la nourriture utilisée en cuisine:";
FOM_OPTIONS_FEED_NOTIFY = "Prévenir lorsque votre familier est nourrit:";
FOM_OPTIONS_WARNING = "Avertir quand votre familier a besoin d'être nourrit:";
FOM_KEEPOPEN = "Essayer de garder au moins";
FOM_KEEPOPEN_SLOTS = "emplacements de sac libres";
FOM_KEEPOPEN_INFO = "(Le familier choisira la nourriture des piles les plus petites, sans tenir compte de ses préférences.)";
FOM_OptionsButtonText = {
["Tooltip"] = "Afficher l'avis de votre familier concernant la nourriture",
["AvoidQuestFood"] = "Eviter la nourriture utile dans les quêtes",
["AvoidBonusFood"] = "Eviter la nourriture donnant un bonus",
["PreferHigherQuality"] = "Privilégier la nourriture que votre familier préfère",
["Fallback"] = "Utiliser la nourriture évitée s'il n'y en a plus d'autres",
["SaveForCook_All"] = "Toutes nourritures utilisées pour la cuisine",
["SaveForCook_Green"] = "si elle est utilisée dans les recettes |cff3fbf3f\"faciles\"|r ou supérieures",
["SaveForCook_Yellow"] = "si elle est utilisée dans les recettes |cffffff00\"moyennes\"|r ou supérieures",
["SaveForCook_Orange"] = "si elle est utilisée dans les recettes |cffff7f3f\"difficiles\"|r",
["SaveForCook_None"] = "Ne pas éviter la nourriture utilisée en cuisine",
["IconWarning"] = "Clignoter l'icône",
["TextWarning"] = "Afficher un texte",
["AudioWarning"] = "Jouer un son",
["AudioWarningBell"] = "Un son de cloche au lieu du cri du familier",
["AlertEmote"] = "Via emote (visible par les autres)",
["AlertChat"] = "Dans la fenêtre de discussion (visible uniquement par vous)",
["AlertNone"] = "Ne pas prévenir",
["LevelContent"] = "quand \"content\"",
["LevelUnhappy"] = "quand \"mécontent\"",
["LevelOff"] = "Ne pas avertir",
};
end
------------------------------------------------------
if (GetLocale() == "deDE") then if (GetLocale() == "deDE") then
-- Diet names. These should be the all-lowercase versions of the six diets returned from GetPetFoodTypes(). (Want to get them all nice and quick for your localization? Go tame a bear... they eat anything.) -- Diet names. These should be the all-lowercase versions of the six diets returned from GetPetFoodTypes(). (Want to get them all nice and quick for your localization? Go tame a bear... they eat anything.)
@@ -279,26 +175,4 @@ if (GetLocale() == "deDE") then
WIND_SERPENT = "Windnatter"; WIND_SERPENT = "Windnatter";
-- WOLF = "Wolf"; -- same as enUS -- WOLF = "Wolf"; -- same as enUS
end
------------------------------------------------------
if (GetLocale() == "koKR") then
-- Diet names. These should be the all-lowercase versions of the six diets returned from GetPetFoodTypes(). (Want to get them all nice and quick for your localization? Go tame a bear... they eat anything.)
-- THESE STRINGS MUST BE LOCALIZED for Feed-O-Matic to work properly in other locales.
-- FOM_DIET_MEAT = "meat";
-- FOM_DIET_FISH = "fish";
-- FOM_DIET_BREAD = "bread";
-- FOM_DIET_CHEESE = "cheese";
-- FOM_DIET_FRUIT = "fruit";
-- FOM_DIET_FUNGUS = "fungus";
-- If the player has a buff whose icon name contains "Ability_Mount" and whose name contains one of these substrings, we assume the player is mounted. We have to use this rather oblique way to check for mounted because some other buffs use the Ability_Mount_* icons.
-- FOM_MOUNT_NAME_SUBSTRINGS = { "kodo", "wolf", "raptor", "steed", "horse", "ram", "saber", "mechanostrider" };
-- It's not clear whether the 5th and 6th returns from GetItemInfo() are supposed to be localized... so we have localized keys for them just in case.
-- FOM_AMMO_POUCH = "Ammo Pouch";
FOM_QUIVER = "화살통";
end end
+47 -60
View File
@@ -6,7 +6,7 @@
local MTH_FeedOMatic = { local MTH_FeedOMatic = {
name = "feedomatic", name = "feedomatic",
enabled = false, enabled = false,
version = "1.0.4", version = "1.2.0",
events = { events = {
"VARIABLES_LOADED", "VARIABLES_LOADED",
"MERCHANT_SHOW", "MERCHANT_SHOW",
@@ -32,13 +32,13 @@ local MTH_FeedOMatic = {
} }
local MTH_PETL_HOOK_BOUNDARY_KEY = "pet-lifecycle-hooks" local MTH_PETL_HOOK_BOUNDARY_KEY = "pet-lifecycle-hooks"
local MTH_FeedOMatic_MerchantProbeFrame = nil local MTH_FOM_MerchantProbe = nil
function MTH_FeedOMatic_OnUpdate(elapsed) function MTH_FeedOMatic_OnUpdate(elapsed)
if not elapsed then if not elapsed then
return return
end end
if not (MTH and MTH.IsModuleEnabled and MTH:IsModuleEnabled("feedomatic", true)) then if not (MTH and MTH.IsModuleEnabled and MTH:IsModuleEnabled("feedomatic", false)) then
return return
end end
if type(FOM_OnUpdate) == "function" then if type(FOM_OnUpdate) == "function" then
@@ -47,7 +47,7 @@ function MTH_FeedOMatic_OnUpdate(elapsed)
end end
local function MTH_FeedOMatic_GetRuntimeFrame() local function MTH_FeedOMatic_GetRuntimeFrame()
return getglobal("Frame_GFW_FeedOMatic") return getglobal("MTH_FOM_OnUpdateFrame")
end end
local function MTH_FeedOMatic_CaptureHookBoundary() local function MTH_FeedOMatic_CaptureHookBoundary()
@@ -137,47 +137,31 @@ local function MTH_FeedOMatic_SyncSavedVariables()
moduleStore.legacy = {} moduleStore.legacy = {}
end end
if type(FOM_Config) == "table" then local function bindLegacyTable(globalName)
moduleStore.legacy.FOM_Config = FOM_Config local legacyValue = moduleStore.legacy[globalName]
elseif type(moduleStore.legacy.FOM_Config) == "table" then local globalValue = _G and _G[globalName] or nil
FOM_Config = moduleStore.legacy.FOM_Config
if type(legacyValue) ~= "table" then
if type(globalValue) == "table" then
legacyValue = globalValue
else
legacyValue = {}
end
moduleStore.legacy[globalName] = legacyValue
end
if _G then
_G[globalName] = legacyValue
end
end end
if type(FOM_FoodQuality) == "table" then bindLegacyTable("FOM_Config")
moduleStore.legacy.FOM_FoodQuality = FOM_FoodQuality bindLegacyTable("FOM_FoodQuality")
elseif type(moduleStore.legacy.FOM_FoodQuality) == "table" then bindLegacyTable("FOM_AddedFoods")
FOM_FoodQuality = moduleStore.legacy.FOM_FoodQuality bindLegacyTable("FOM_RemovedFoods")
end bindLegacyTable("FOM_Cooking")
bindLegacyTable("FOM_QuestFood")
if type(FOM_AddedFoods) == "table" then bindLegacyTable("FOM_LocaleInfo")
moduleStore.legacy.FOM_AddedFoods = FOM_AddedFoods
elseif type(moduleStore.legacy.FOM_AddedFoods) == "table" then
FOM_AddedFoods = moduleStore.legacy.FOM_AddedFoods
end
if type(FOM_RemovedFoods) == "table" then
moduleStore.legacy.FOM_RemovedFoods = FOM_RemovedFoods
elseif type(moduleStore.legacy.FOM_RemovedFoods) == "table" then
FOM_RemovedFoods = moduleStore.legacy.FOM_RemovedFoods
end
if type(FOM_Cooking) == "table" then
moduleStore.legacy.FOM_Cooking = FOM_Cooking
elseif type(moduleStore.legacy.FOM_Cooking) == "table" then
FOM_Cooking = moduleStore.legacy.FOM_Cooking
end
if type(FOM_QuestFood) == "table" then
moduleStore.legacy.FOM_QuestFood = FOM_QuestFood
elseif type(moduleStore.legacy.FOM_QuestFood) == "table" then
FOM_QuestFood = moduleStore.legacy.FOM_QuestFood
end
if type(FOM_LocaleInfo) == "table" then
moduleStore.legacy.FOM_LocaleInfo = FOM_LocaleInfo
elseif type(moduleStore.legacy.FOM_LocaleInfo) == "table" then
FOM_LocaleInfo = moduleStore.legacy.FOM_LocaleInfo
end
end end
local function MTH_FeedOMatic_Log(message, severity) local function MTH_FeedOMatic_Log(message, severity)
@@ -231,9 +215,17 @@ local function MTH_FeedOMatic_DebugMerchantScan(sourceEvent)
end end
local function MTH_FeedOMatic_SetMerchantProbeEnabled(enabled) local function MTH_FeedOMatic_SetMerchantProbeEnabled(enabled)
if not MTH_FeedOMatic_MerchantProbeFrame then if not enabled then
MTH_FeedOMatic_MerchantProbeFrame = CreateFrame("Frame", "MTH_FeedOMatic_MerchantProbeFrame") if MTH_FOM_MerchantProbe then
MTH_FeedOMatic_MerchantProbeFrame:SetScript("OnEvent", function() MTH_FOM_MerchantProbe:UnregisterEvent("MERCHANT_SHOW")
MTH_FOM_MerchantProbe:UnregisterEvent("MERCHANT_UPDATE")
end
return
end
if not MTH_FOM_MerchantProbe then
MTH_FOM_MerchantProbe = CreateFrame("Frame", "MTH_FOM_MerchantProbe")
MTH_FOM_MerchantProbe:SetScript("OnEvent", function()
local evt = event local evt = event
if evt == "MERCHANT_SHOW" or evt == "MERCHANT_UPDATE" then if evt == "MERCHANT_SHOW" or evt == "MERCHANT_UPDATE" then
MTH_FeedOMatic_Log("probe event received: " .. tostring(evt), "debug") MTH_FeedOMatic_Log("probe event received: " .. tostring(evt), "debug")
@@ -242,14 +234,9 @@ local function MTH_FeedOMatic_SetMerchantProbeEnabled(enabled)
end) end)
end end
if enabled then MTH_FOM_MerchantProbe:RegisterEvent("MERCHANT_SHOW")
MTH_FeedOMatic_MerchantProbeFrame:RegisterEvent("MERCHANT_SHOW") MTH_FOM_MerchantProbe:RegisterEvent("MERCHANT_UPDATE")
MTH_FeedOMatic_MerchantProbeFrame:RegisterEvent("MERCHANT_UPDATE") MTH_FeedOMatic_Log("merchant probe enabled", "debug")
MTH_FeedOMatic_Log("merchant probe enabled", "debug")
else
MTH_FeedOMatic_MerchantProbeFrame:UnregisterEvent("MERCHANT_SHOW")
MTH_FeedOMatic_MerchantProbeFrame:UnregisterEvent("MERCHANT_UPDATE")
end
end end
function MTH_FeedOMatic:init() function MTH_FeedOMatic:init()
@@ -290,8 +277,8 @@ function MTH_FeedOMatic:setEnabled(enabled)
MTH_FeedOMatic_SyncSavedVariables() MTH_FeedOMatic_SyncSavedVariables()
MTH_FeedOMatic_EnsureVariablesLoaded(self) MTH_FeedOMatic_EnsureVariablesLoaded(self)
MTH_FeedOMatic_SetMerchantProbeEnabled(false) MTH_FeedOMatic_SetMerchantProbeEnabled(false)
if FOM_FeedButton then if MTH_FOM_FeedButton then
FOM_FeedButton:Show() MTH_FOM_FeedButton:Show()
end end
else else
-- Disable FeedOMatic functionality -- Disable FeedOMatic functionality
@@ -300,8 +287,8 @@ function MTH_FeedOMatic:setEnabled(enabled)
FOM_State.ShouldFeed = false FOM_State.ShouldFeed = false
end end
MTH_FeedOMatic_SetMerchantProbeEnabled(false) MTH_FeedOMatic_SetMerchantProbeEnabled(false)
if FOM_FeedButton then if MTH_FOM_FeedButton then
FOM_FeedButton:Hide() MTH_FOM_FeedButton:Hide()
end end
end end
end end
@@ -329,8 +316,8 @@ function MTH_FeedOMatic:cleanup()
FOM_State.ShouldFeed = false FOM_State.ShouldFeed = false
end end
MTH_FeedOMatic_SetMerchantProbeEnabled(false) MTH_FeedOMatic_SetMerchantProbeEnabled(false)
if FOM_FeedButton then if MTH_FOM_FeedButton then
FOM_FeedButton:Hide(); MTH_FOM_FeedButton:Hide();
end end
end end
+2 -2
View File
@@ -3,7 +3,7 @@ FeedOMatic Runtime Frame Loader (MetaHunt)
Minimal runtime XML without legacy options window definitions. Minimal runtime XML without legacy options window definitions.
--> -->
<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"> <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="Frame_GFW_FeedOMatic"> <Frame name="MTH_FOM_OnUpdateFrame">
<Scripts> <Scripts>
<OnUpdate> <OnUpdate>
if (MTH_FOM_OnUpdate) then if (MTH_FOM_OnUpdate) then
@@ -15,7 +15,7 @@ Minimal runtime XML without legacy options window definitions.
</Scripts> </Scripts>
</Frame> </Frame>
<GameTooltip name="FOMTooltip" frameStrata="TOOLTIP" hidden="true" parent="UIParent" inherits="GameTooltipTemplate"> <GameTooltip name="MTH_FOM_Tooltip" frameStrata="TOOLTIP" hidden="true" parent="UIParent" inherits="GameTooltipTemplate">
<Scripts> <Scripts>
<OnLoad> <OnLoad>
this:SetOwner(UIParent, "ANCHOR_NONE"); this:SetOwner(UIParent, "ANCHOR_NONE");
File diff suppressed because it is too large Load Diff
+320
View File
@@ -0,0 +1,320 @@
<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/">
<Script file="MTH_ICU.lua"/>
<!-- The main ICU frame -->
<Frame name="ICU_Frame">
<Scripts>
<OnLoad>
ICU_OnLoad();
</OnLoad>
<OnEvent>
ICU_OnEvent(event);
</OnEvent>
</Scripts>
</Frame>
<!-- A button template, to be inherited by each button -->
<Frame name="ICU_PopupButtonTemplate" virtual="true">
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
<BackgroundInsets>
<AbsInset left="5" right="5" top="5" bottom="5"/>
</BackgroundInsets>
<TileSize>
<AbsValue val="16"/>
</TileSize>
<EdgeSize>
<AbsValue val="16"/>
</EdgeSize>
</Backdrop>
<Size>
<AbsDimension x="30" y="28"/>
</Size>
<Layers>
<Layer level="ARTWORK">
<Texture name="$parentButtonPortraitIcon">
<Size>
<AbsDimension x="20" y="20"/>
</Size>
<Anchors>
<Anchor point="LEFT" relativePoint="LEFT">
<Offset>
<AbsDimension x="5" y="0"/>
</Offset>
</Anchor>
</Anchors>
</Texture>
<Texture name="$parentButtonClassIcon">
<Size>
<AbsDimension x="20" y="20"/>
</Size>
<Anchors>
<Anchor point="LEFT" relativePoint="RIGHT" relativeTo="$parentButtonPortraitIcon">
<Offset>
<AbsDimension x="0" y="0"/>
</Offset>
</Anchor>
</Anchors>
</Texture>
<Texture name="$parentButtonRankIcon">
<Size>
<AbsDimension x="20" y="20"/>
</Size>
<Anchors>
<Anchor point="RIGHT" relativePoint="LEFT">
<Offset>
<AbsDimension x="0" y="0"/>
</Offset>
</Anchor>
</Anchors>
</Texture>
</Layer>
</Layers>
<Frames>
<Button name="$parentButton" frameStrata="ARTWORK">
<Size>
<AbsDimension x="20" y="20"/>
</Size>
<Anchors>
<Anchor point="LEFT" relativePoint="LEFT">
<Offset>
<AbsDimension x="5" y="0"/>
</Offset>
</Anchor>
</Anchors>
<HighlightTexture file="Interface\QuestFrame\UI-QuestTitleHighlight" alphaMode="ADD" setAllPoints="true" hidden="true"/>
<NormalText inherits="GameFontNormal">
<Anchors>
<Anchor point="LEFT" relativePoint="RIGHT" relativeTo="$parentClassIcon">
<Offset>
<AbsDimension x="5" y="0"/>
</Offset>
</Anchor>
</Anchors>
</NormalText>
<HighlightText inherits="GameFontHighlight">
<Anchors>
<Anchor point="LEFT" relativePoint="RIGHT" relativeTo="$parentClassIcon">
<Offset>
<AbsDimension x="5" y="0"/>
</Offset>
</Anchor>
</Anchors>
</HighlightText>
<DisabledText inherits="GameFontDisable">
<Anchors>
<Anchor point="LEFT" relativePoint="RIGHT" relativeTo="$parentClassIcon">
<Offset>
<AbsDimension x="5" y="0"/>
</Offset>
</Anchor>
</Anchors>
</DisabledText>
<Scripts>
<OnClick>
ICU_ButtonClick();
</OnClick>
</Scripts>
</Button>
<StatusBar name="$parentButtonBar" inherits="TextStatusBar" frameStrata="ARTWORK">
<Size>
<AbsDimension x="20" y="20"/>
</Size>
<Anchors>
<Anchor point="LEFT" relativePoint="RIGHT" relativeTo="$parentButtonClassIcon">
<Offset>
<AbsDimension x="0" y="0"/>
</Offset>
</Anchor>
</Anchors>
<BarTexture file="Interface\TargetingFrame\UI-TargetingFrame-BarFill"/>
<BarColor r="0" g="0.8" b="0" a="0.7" />
<!--
<Layers>
<Layer level="OVERLAY">
<FontString name="$parentLeftText" inherits="GameFontNormal" text="">
<Anchors>
<Anchor point="LEFT" relativePoint="LEFT">
<Offset>
<AbsDimension x="10" y="1"/>
</Offset>
</Anchor>
</Anchors>
</FontString>
<FontString name="$parentRightText" inherits="GameFontNormal" text="">
<Anchors>
<Anchor point="RIGHT" relativePoint="RIGHT">
<Offset>
<AbsDimension x="-10" y="1"/>
</Offset>
</Anchor>
</Anchors>
</FontString>
</Layer>
</Layers>
!-->
<Scripts>
<OnLoad>
this:SetMinMaxValues(0, 100);
</OnLoad>
</Scripts>
</StatusBar>
<StatusBar name="$parentButtonBGBar" inherits="TextStatusBar" frameStrata="ARTWORK">
<Size>
<AbsDimension x="20" y="20"/>
</Size>
<Anchors>
<Anchor point="TOP" relativePoint="TOP" relativeTo="$parentButtonBar">
<Offset>
<AbsDimension x="0" y="0"/>
</Offset>
</Anchor>
</Anchors>
<BarTexture file="Interface\TargetingFrame\UI-TargetingFrame-BarFill"/>
<BarColor r="0" g="0.8" b="0" a="0.25"/>
</StatusBar>
</Frames>
<Scripts>
<OnLoad>
this:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b);
this:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b);
</OnLoad>
</Scripts>
</Frame>
<!-- The popup menu -->
<Frame name="ICU_Popup" toplevel="true" frameStrata="DIALOG" enableMouse="true" hidden="true" parent="UIParent">
<Anchors>
<Anchor point="TOPRIGHT" relativeTo="MinimapCluster" relativePoint="BOTTOMRIGHT"/>
</Anchors>
<!--
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
<BackgroundInsets>
<AbsInset left="5" right="5" top="5" bottom="5"/>
</BackgroundInsets>
<TileSize>
<AbsValue val="16"/>
</TileSize>
<EdgeSize>
<AbsValue val="16"/>
</EdgeSize>
</Backdrop>
!-->
<!-- Within the popup menu, the clickable buttons which to display text -->
<Frames>
<!-- Button 1 -->
<Frame name="ICU_PopupButton1" inherits="ICU_PopupButtonTemplate" id="1" ICU_DATA="">
<Anchors>
<Anchor point="TOP">
<Offset>
<AbsDimension x="0" y="-6"/>
</Offset>
</Anchor>
</Anchors>
</Frame>
<!-- Frame 2 -->
<Frame name="ICU_PopupButton2" inherits="ICU_PopupButtonTemplate" id="2" ICU_DATA="">
<Anchors>
<Anchor point="TOP" relativeTo="ICU_PopupButton1" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="4"/>
</Offset>
</Anchor>
</Anchors>
</Frame>
<!-- Frame 3 -->
<Frame name="ICU_PopupButton3" inherits="ICU_PopupButtonTemplate" id="3" ICU_DATA="">
<Anchors>
<Anchor point="TOP" relativeTo="ICU_PopupButton2" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="4"/>
</Offset>
</Anchor>
</Anchors>
</Frame>
<!-- Frame 4 -->
<Frame name="ICU_PopupButton4" inherits="ICU_PopupButtonTemplate" id="4" ICU_DATA="">
<Anchors>
<Anchor point="TOP" relativeTo="ICU_PopupButton3" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="4"/>
</Offset>
</Anchor>
</Anchors>
</Frame>
<!-- Frame 5 -->
<Frame name="ICU_PopupButton5" inherits="ICU_PopupButtonTemplate" id="5" ICU_DATA="">
<Anchors>
<Anchor point="TOP" relativeTo="ICU_PopupButton4" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="4"/>
</Offset>
</Anchor>
</Anchors>
</Frame>
<!-- Frame 6 -->
<Frame name="ICU_PopupButton6" inherits="ICU_PopupButtonTemplate" id="6" ICU_DATA="">
<Anchors>
<Anchor point="TOP" relativeTo="ICU_PopupButton5" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="4"/>
</Offset>
</Anchor>
</Anchors>
</Frame>
<!-- Frame 7 -->
<Frame name="ICU_PopupButton7" inherits="ICU_PopupButtonTemplate" id="7" ICU_DATA="">
<Anchors>
<Anchor point="TOP" relativeTo="ICU_PopupButton6" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="4"/>
</Offset>
</Anchor>
</Anchors>
</Frame>
<!-- Frame 8 -->
<Frame name="ICU_PopupButton8" inherits="ICU_PopupButtonTemplate" id="8" ICU_DATA="">
<Anchors>
<Anchor point="TOP" relativeTo="ICU_PopupButton7" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="4"/>
</Offset>
</Anchor>
</Anchors>
</Frame>
<!-- Frame 9 -->
<Frame name="ICU_PopupButton9" inherits="ICU_PopupButtonTemplate" id="9" ICU_DATA="">
<Anchors>
<Anchor point="TOP" relativeTo="ICU_PopupButton8" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="4"/>
</Offset>
</Anchor>
</Anchors>
</Frame>
<!-- Frame 10 -->
<Frame name="ICU_PopupButton10" inherits="ICU_PopupButtonTemplate" id="10" ICU_DATA="">
<Anchors>
<Anchor point="TOP" relativeTo="ICU_PopupButton9" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="4"/>
</Offset>
</Anchor>
</Anchors>
</Frame>
</Frames>
<Scripts>
<OnLoad>
<!-- This makes the dialog look like a normal tooltip -->
this:SetBackdropBorderColor( TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b );
this:SetBackdropColor( TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b );
</OnLoad>
<OnUpdate>
ICU_Popup_OnUpdate();
</OnUpdate>
</Scripts>
</Frame>
<Frame name="ICU_UpdateFrame" hidden="true">
<Scripts>
<OnUpdate>
ICU_MouseOverUpdate();
</OnUpdate>
</Scripts>
</Frame>
</Ui>
+8
View File
@@ -0,0 +1,8 @@
<!--
ICU Module Loader
Loads ICU runtime and wraps it in the MetaHunt module system.
-->
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Include file="MTH_ICU.xml"/>
<Include file="module.lua"/>
</Ui>
+52
View File
@@ -0,0 +1,52 @@
------------------------------------------------------
-- MetaHunt: ICU Module Wrapper
-- Safe wrapper for ICU minimap targeting utilities
------------------------------------------------------
local MTH_ICU = {
name = "icu",
enabled = false,
version = "1.2.0",
events = {
"VARIABLES_LOADED",
},
initialized = false,
}
local function ICU_Log(message, severity)
if type(MTH_Log) == "function" then
MTH_Log("[ICU] " .. tostring(message or ""), severity)
end
end
function MTH_ICU:init()
self.initialized = true
if type(ICU_SetEnabled) == "function" then
ICU_SetEnabled(self.enabled and true or false)
end
end
function MTH_ICU:setEnabled(enabled)
if not self.initialized then
self:init()
end
if type(ICU_SetEnabled) == "function" then
ICU_SetEnabled(enabled and true or false)
else
ICU_Log("runtime not loaded; cannot change enabled state", "error")
end
end
function MTH_ICU:onEvent(eventName)
if eventName == "VARIABLES_LOADED" and type(ICU_SetEnabled) == "function" then
ICU_SetEnabled(self.enabled and true or false)
end
end
function MTH_ICU:cleanup()
if type(ICU_SetEnabled) == "function" then
ICU_SetEnabled(false)
end
end
MTH:RegisterModule("icu", MTH_ICU)
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -7,10 +7,10 @@ MTH_SA_MANAGED_HOOKS = true
local MTH_SmartAmmo = { local MTH_SmartAmmo = {
name = "smartammo", name = "smartammo",
enabled = true, enabled = true,
version = "1.0.4", version = "1.2.0",
events = { events = {
"VARIABLES_LOADED", "VARIABLES_LOADED",
"PLAYER_ENTERING_WORLD", -- PLAYER_ENTERING_WORLD handled by engine's own frame
}, },
} }
+500 -29
View File
@@ -6,7 +6,7 @@
local MTH_Tooltips = { local MTH_Tooltips = {
name = "tooltips", name = "tooltips",
enabled = true, enabled = true,
version = "1.0.4", version = "1.2.0",
events = { events = {
"UPDATE_MOUSEOVER_UNIT", "UPDATE_MOUSEOVER_UNIT",
"UNIT_NAME_UPDATE", "UNIT_NAME_UPDATE",
@@ -34,14 +34,33 @@ local MTH_Tooltips = {
injectFrame = nil, injectFrame = nil,
pollFrame = nil, pollFrame = nil,
pollElapsed = 0, pollElapsed = 0,
hintElapsed = 0,
lastMouseoverKey = "", lastMouseoverKey = "",
} }
local function MTH_TT_CopyValue(value)
if type(value) ~= "table" then
return value
end
local copy = {}
for key, entry in pairs(value) do
copy[key] = MTH_TT_CopyValue(entry)
end
return copy
end
local function MTH_TT_GetOptionsStore() local function MTH_TT_GetOptionsStore()
if MTH and MTH.GetModuleSavedVariables then if MTH and MTH.GetModuleCharSavedVariables then
local store = MTH:GetModuleSavedVariables("tooltips") local store = MTH:GetModuleCharSavedVariables("tooltips")
if type(store) == "table" then if type(store) == "table" then
if MTH.GetModuleSavedVariables and next(store) == nil then
local accountStore = MTH:GetModuleSavedVariables("tooltips")
if type(accountStore) == "table" and next(accountStore) ~= nil then
for key, value in pairs(accountStore) do
store[key] = MTH_TT_CopyValue(value)
end
end
end
if store.beastTooltips == nil then if store.beastTooltips == nil then
store.beastTooltips = true store.beastTooltips = true
end end
@@ -96,6 +115,55 @@ local function MTH_TT_IsOwnPetTooltipsEnabled()
return false return false
end end
local function MTH_TT_GetAutoQuestStore()
if type(MTH_CharSavedVariables) ~= "table" then
return nil
end
local store = MTH_CharSavedVariables.autoquest
if type(store) ~= "table" then
store = MTH_CharSavedVariables.questautomation
end
if type(store) ~= "table" then
return nil
end
if store.scorpokDrazial == nil then
store.scorpokDrazial = false
end
if store.scorpokTooltip == nil then
store.scorpokTooltip = false
end
return store
end
local function MTH_TT_IsScorpokAutomationEnabled()
local store = MTH_TT_GetAutoQuestStore()
if type(store) ~= "table" then
return false
end
return store.scorpokDrazial and true or false
end
local function MTH_TT_IsScorpokTooltipEnabled()
local store = MTH_TT_GetAutoQuestStore()
if type(store) ~= "table" then
return false
end
return store.scorpokTooltip and true or false
end
local function MTH_TT_IsAutoQuestModuleEnabled()
if MTH and type(MTH.GetModule) == "function" then
local module = MTH:GetModule("autoquest")
if type(module) == "table" and module.enabled ~= nil then
return module.enabled and true or false
end
end
if MTH and type(MTH.IsModuleEnabled) == "function" then
return MTH:IsModuleEnabled("autoquest", false) and true or false
end
return false
end
local function MTH_TT_Loc(key, fallback) local function MTH_TT_Loc(key, fallback)
if MTH and MTH.GetLocalization then if MTH and MTH.GetLocalization then
return MTH:GetLocalization(key, fallback) return MTH:GetLocalization(key, fallback)
@@ -539,6 +607,191 @@ local function MTH_TT_ColorizeDigitsBlue(text)
return string.gsub(source, "(%d+)", "|cff73bfff%1|r") return string.gsub(source, "(%d+)", "|cff73bfff%1|r")
end end
local MTH_TT_SCORPOK_NPC_NAME = "Bloodmage Drazial"
local MTH_TT_SCORPOK_TARGET_NPC_IDS = {
[7505] = true,
[5988] = true,
[5982] = true,
[5992] = true,
[5993] = true,
}
local MTH_TT_SCORPOK_TARGET_NPC_NAMES = {
[MTH_TT_NormalizeName("Bloodmage Drazial")] = true,
[MTH_TT_NormalizeName("Scorpok Stinger")] = true,
[MTH_TT_NormalizeName("Black Slayer")] = true,
[MTH_TT_NormalizeName("Ashmane Boar")] = true,
[MTH_TT_NormalizeName("Helboar")] = true,
}
local MTH_TT_ITEM_SCORPOK_PINCER_ID = 8393
local MTH_TT_ITEM_VULTURE_GIZZARD_ID = 8396
local MTH_TT_ITEM_BLASTED_BOAR_LUNG_ID = 8392
local MTH_TT_ITEM_GROUND_SCORPOK_ASSAY_ID = 8412
local function MTH_TT_ParseNpcIdFromGuid(guid)
if type(guid) ~= "string" or guid == "" then
return nil
end
local _, _, _, _, _, npcId = string.find(guid, "^Creature%-%d+%-%d+%-%d+%-%d+%-(%d+)%-%x+$")
if npcId then
return tonumber(npcId)
end
if string.sub(guid, 1, 2) == "0x" and string.len(guid) >= 12 then
local hex = string.sub(guid, 9, 12)
local parsed = tonumber(hex, 16)
if parsed and parsed > 0 then
return parsed
end
end
return nil
end
local function MTH_TT_GetBagItemCount(itemId)
local getContainerNumSlots = _G and _G["GetContainerNumSlots"] or nil
local getContainerItemLink = _G and _G["GetContainerItemLink"] or nil
local getContainerItemInfo = _G and _G["GetContainerItemInfo"] or nil
if type(getContainerNumSlots) ~= "function" or type(getContainerItemLink) ~= "function" then
return 0
end
local total = 0
for bag = 0, 4 do
local slots = math.floor(tonumber(getContainerNumSlots(bag)) or 0)
for slot = 1, slots do
local link = getContainerItemLink(bag, slot)
if type(link) == "string" and link ~= "" then
local _, _, foundText = string.find(link, "item:(%d+)")
local found = tonumber(foundText)
if found and tonumber(found) == tonumber(itemId) then
local count = 1
if type(getContainerItemInfo) == "function" then
local _, stackCount = getContainerItemInfo(bag, slot)
count = math.floor(tonumber(stackCount) or 1)
end
total = total + count
end
end
end
end
return total
end
local function MTH_TT_ColorCountByThreshold(value, threshold)
local n = math.floor(tonumber(value) or 0)
if n <= 0 then
return "|cffff0000" .. tostring(n) .. "|r"
end
local modFn = nil
if type(rawget) == "function" and type(math) == "table" then
modFn = rawget(math, "mod") or rawget(math, "fmod")
elseif type(math) == "table" then
modFn = math.fmod
end
if threshold > 0 and type(modFn) == "function" and modFn(n, threshold) == 0 then
return "|cff00ff00" .. tostring(n) .. "|r"
end
return "|cffffa500" .. tostring(n) .. "|r"
end
local function MTH_TT_ColorAssayCount(value)
local n = math.floor(tonumber(value) or 0)
if n > 0 then
return "|cff73bfff" .. tostring(n) .. "|r"
end
return tostring(n)
end
local function MTH_TT_HasScorpokTooltipLine()
if not GameTooltip or not GameTooltip.NumLines then return false end
for i = 1, GameTooltip:NumLines() do
local left = getglobal("GameTooltipTextLeft" .. i)
if left and left.GetText then
local text = tostring(left:GetText() or "")
if string.find(text, "MTH Auto Quest", 1, true)
or string.find(text, "Ground Scorpok Assay", 1, true) then
return true
end
end
end
return false
end
local function MTH_TT_IsScorpokTooltipZoneAllowed()
local getRealZoneText = _G and _G["GetRealZoneText"] or nil
local getZoneText = _G and _G["GetZoneText"] or nil
local zoneName = ""
if type(getRealZoneText) == "function" then
zoneName = tostring(getRealZoneText() or "")
end
if zoneName == "" and type(getZoneText) == "function" then
zoneName = tostring(getZoneText() or "")
end
if zoneName == "" then
return true
end
return MTH_TT_NormalizeName(zoneName) == MTH_TT_NormalizeName("Blasted Lands")
end
local function MTH_TT_AddScorpokTargetsTooltip(unit, unitName)
if not MTH_TT_IsAutoQuestModuleEnabled() then
return false
end
if not MTH_TT_IsScorpokAutomationEnabled() or not MTH_TT_IsScorpokTooltipEnabled() then
return false
end
if not MTH_TT_IsScorpokTooltipZoneAllowed() then
return false
end
if MTH_TT_HasScorpokTooltipLine() then
return false
end
local npcId = nil
if type(UnitGUID) == "function" then
npcId = MTH_TT_ParseNpcIdFromGuid(UnitGUID(unit))
end
local isDrazial = false
if tonumber(npcId) == 7505 then
isDrazial = true
elseif MTH_TT_Lower(unitName) == MTH_TT_Lower(MTH_TT_SCORPOK_NPC_NAME) then
isDrazial = true
end
local isTargetNpc = false
if npcId and MTH_TT_SCORPOK_TARGET_NPC_IDS[tonumber(npcId)] then
isTargetNpc = true
end
if not isTargetNpc then
local normalizedName = MTH_TT_NormalizeName(unitName)
isTargetNpc = MTH_TT_SCORPOK_TARGET_NPC_NAMES[normalizedName] and true or false
if not isTargetNpc then
isTargetNpc = MTH_TT_Lower(unitName) == MTH_TT_Lower(MTH_TT_SCORPOK_NPC_NAME)
end
end
if not isTargetNpc then
return false
end
local pincer = MTH_TT_GetBagItemCount(MTH_TT_ITEM_SCORPOK_PINCER_ID)
local gizzard = MTH_TT_GetBagItemCount(MTH_TT_ITEM_VULTURE_GIZZARD_ID)
local lung = MTH_TT_GetBagItemCount(MTH_TT_ITEM_BLASTED_BOAR_LUNG_ID)
local assayInBag = MTH_TT_GetBagItemCount(MTH_TT_ITEM_GROUND_SCORPOK_ASSAY_ID)
local assaysToGet = math.floor(math.min((pincer / 3), (gizzard / 2), lung))
GameTooltip:AddLine(" ")
GameTooltip:AddLine("|cffffff00MTH Auto Quest|r")
GameTooltip:AddLine(" - Scorpok Pincer - " .. MTH_TT_ColorCountByThreshold(pincer, 3), 1, 1, 1)
GameTooltip:AddLine(" - Vulture Gizzard - " .. MTH_TT_ColorCountByThreshold(gizzard, 2), 1, 1, 1)
GameTooltip:AddLine(" - Blasted Boar Lung - " .. MTH_TT_ColorCountByThreshold(lung, 1), 1, 1, 1)
local assaysToGetText = "|cff73bfff" .. tostring(assaysToGet) .. "|r"
GameTooltip:AddLine(
"Assays to get : " .. assaysToGetText .. " | Assays in bag : " .. MTH_TT_ColorAssayCount(assayInBag),
1, 1, 1
)
if isDrazial then
GameTooltip:AddLine("Spam SHIFT-click!", 0.7, 0.9, 1)
end
GameTooltip:AddLine("Recipes: 3x Pincer, 2x Gizzard, 1x Lung", 0.7, 0.7, 0.7)
return true
end
local function MTH_TT_AddOwnPetTooltipHint() local function MTH_TT_AddOwnPetTooltipHint()
if not (MTH_Tooltips and MTH_Tooltips.enabled) then if not (MTH_Tooltips and MTH_Tooltips.enabled) then
return return
@@ -845,7 +1098,37 @@ local function MTH_TT_FindAbilityCanonicalName(abilityName)
return nil return nil
end end
local function MTH_TT_ParseRankFromText(value) local function MTH_TT_AbilityHasPositiveRanks(canonicalAbilityName)
if canonicalAbilityName == nil or canonicalAbilityName == "" then
return false
end
if not (MTH_DS_PetSpells and type(MTH_DS_PetSpells.byAbility) == "table") then
return false
end
local bucket = MTH_DS_PetSpells.byAbility[canonicalAbilityName]
if not (bucket and type(bucket.spells) == "table") then
return false
end
for i = 1, table.getn(bucket.spells) do
local spell = bucket.spells[i]
if spell then
local rank = tonumber(spell.rankNumber)
if not rank and spell.rank then
local _, _, parsed = string.find(tostring(spell.rank), "(%d+)")
rank = tonumber(parsed)
end
if rank and rank > 0 then
return true
end
end
end
return false
end
local function MTH_TT_ParseRankFromText(value, allowTrailingNumber)
local text = MTH_TT_Trim(value) local text = MTH_TT_Trim(value)
if text == "" then if text == "" then
return nil return nil
@@ -854,9 +1137,11 @@ local function MTH_TT_ParseRankFromText(value)
if rankText then if rankText then
return tonumber(rankText) return tonumber(rankText)
end end
local _, _, trailing = string.find(text, "(%d+)$") if allowTrailingNumber == true then
if trailing then local _, _, trailing = string.find(text, "(%d+)$")
return tonumber(trailing) if trailing then
return tonumber(trailing)
end
end end
return nil return nil
end end
@@ -884,10 +1169,10 @@ local function MTH_TT_GetTooltipSpellNameAndRank()
if ok then if ok then
if type(a) == "string" then if type(a) == "string" then
spellName = a spellName = a
rankNumber = MTH_TT_ParseRankFromText(b) rankNumber = MTH_TT_ParseRankFromText(b, true)
elseif type(b) == "string" then elseif type(b) == "string" then
spellName = b spellName = b
rankNumber = MTH_TT_ParseRankFromText(a) rankNumber = MTH_TT_ParseRankFromText(a, true)
end end
end end
end end
@@ -899,24 +1184,28 @@ local function MTH_TT_GetTooltipSpellNameAndRank()
end end
end end
if not rankNumber then
rankNumber = MTH_TT_ParseRankFromText(spellName, true)
end
if not rankNumber then if not rankNumber then
local right1 = getglobal("GameTooltipTextRight1") local right1 = getglobal("GameTooltipTextRight1")
if right1 and right1.GetText then if right1 and right1.GetText then
rankNumber = MTH_TT_ParseRankFromText(right1:GetText()) rankNumber = MTH_TT_ParseRankFromText(right1:GetText(), false)
end end
end end
if not rankNumber then if not rankNumber then
local left2 = getglobal("GameTooltipTextLeft2") local left2 = getglobal("GameTooltipTextLeft2")
if left2 and left2.GetText then if left2 and left2.GetText then
rankNumber = MTH_TT_ParseRankFromText(left2:GetText()) rankNumber = MTH_TT_ParseRankFromText(left2:GetText(), false)
end end
end end
if not rankNumber then if not rankNumber then
local right2 = getglobal("GameTooltipTextRight2") local right2 = getglobal("GameTooltipTextRight2")
if right2 and right2.GetText then if right2 and right2.GetText then
rankNumber = MTH_TT_ParseRankFromText(right2:GetText()) rankNumber = MTH_TT_ParseRankFromText(right2:GetText(), false)
end end
end end
@@ -925,7 +1214,7 @@ local function MTH_TT_GetTooltipSpellNameAndRank()
local left = getglobal("GameTooltipTextLeft" .. i) local left = getglobal("GameTooltipTextLeft" .. i)
if left and left.GetText then if left and left.GetText then
local text = MTH_TT_Trim(left:GetText()) local text = MTH_TT_Trim(left:GetText())
local parsed = MTH_TT_ParseRankFromText(text) local parsed = MTH_TT_ParseRankFromText(text, false)
if parsed and parsed > 0 then if parsed and parsed > 0 then
rankNumber = parsed rankNumber = parsed
break break
@@ -933,7 +1222,7 @@ local function MTH_TT_GetTooltipSpellNameAndRank()
end end
local right = getglobal("GameTooltipTextRight" .. i) local right = getglobal("GameTooltipTextRight" .. i)
if right and right.GetText then if right and right.GetText then
local parsedRight = MTH_TT_ParseRankFromText(right:GetText()) local parsedRight = MTH_TT_ParseRankFromText(right:GetText(), false)
if parsedRight and parsedRight > 0 then if parsedRight and parsedRight > 0 then
rankNumber = parsedRight rankNumber = parsedRight
break break
@@ -945,6 +1234,87 @@ local function MTH_TT_GetTooltipSpellNameAndRank()
return MTH_TT_CleanSpellName(spellName), rankNumber return MTH_TT_CleanSpellName(spellName), rankNumber
end end
local function MTH_TT_GetCurrentPetRowForTooltip()
local pets = nil
if type(MTH_PETS_GetRootStore) == "function" then
pets = MTH_PETS_GetRootStore()
elseif type(MTH_CharSavedVariables) == "table" then
pets = MTH_CharSavedVariables.MTH_Pets
end
if type(pets) ~= "table" then
return nil
end
local currentId = pets.currentPetId
if (currentId == nil or tostring(currentId) == "") and type(pets.currentPet) == "table" and pets.currentPet.exists == true then
currentId = pets.currentPet.id
end
if currentId == nil or tostring(currentId) == "" then
return nil
end
local activeById = type(pets.petStore) == "table" and pets.petStore.activeById or nil
if type(activeById) ~= "table" then
return nil
end
return activeById[currentId] or activeById[tostring(currentId)]
end
local function MTH_TT_CurrentPetKnowsAbility(abilityLower, rankNumber)
if abilityLower == "" then
return false
end
local row = MTH_TT_GetCurrentPetRowForTooltip()
if type(row) ~= "table" then
return false
end
local wantedRank = tonumber(rankNumber)
local spellbook = row.petSpellbook
if type(spellbook) == "table" and type(spellbook.spells) == "table" then
for i = 1, table.getn(spellbook.spells) do
local spell = spellbook.spells[i]
if type(spell) == "table" then
local spellLower = MTH_TT_Lower(MTH_TT_CleanSpellName(spell.name))
if spellLower == abilityLower then
if wantedRank then
local spellRank = tonumber(spell.rank)
if not spellRank then
spellRank = MTH_TT_ParseRankFromText(spell.name, true)
end
if spellRank and tonumber(spellRank) == wantedRank then
return true
end
else
return true
end
end
end
end
end
if type(row.abilities) == "table" then
for _, ability in pairs(row.abilities) do
if type(ability) == "table" then
local abilityLowerName = MTH_TT_Lower(MTH_TT_CleanSpellName(ability.name))
if abilityLowerName == abilityLower then
if wantedRank then
local abilityRank = tonumber(ability.rank)
if abilityRank and abilityRank == wantedRank then
return true
end
else
return true
end
end
end
end
end
return false
end
local function MTH_TT_IsPetActionTooltipOwner() local function MTH_TT_IsPetActionTooltipOwner()
if not GameTooltip or type(GameTooltip.GetOwner) ~= "function" then if not GameTooltip or type(GameTooltip.GetOwner) ~= "function" then
return false return false
@@ -1031,7 +1401,15 @@ local function MTH_TT_AddPetActionNotLearnedHint()
return return
end end
local known = MTH_TT_HunterKnowsAbility(MTH_TT_Lower(canonical), rankNumber) if rankNumber and rankNumber > 0 and not MTH_TT_AbilityHasPositiveRanks(canonical) then
rankNumber = nil
end
local canonicalLower = MTH_TT_Lower(canonical)
local known = MTH_TT_HunterKnowsAbility(canonicalLower, rankNumber)
if not known then
known = MTH_TT_CurrentPetKnowsAbility(canonicalLower, rankNumber)
end
if known then if known then
return return
end end
@@ -1107,7 +1485,8 @@ local function MTH_TT_AddTooltip(unit)
local ammoVendorTooltipsEnabled = MTH_TT_IsAmmoVendorTooltipsEnabled() local ammoVendorTooltipsEnabled = MTH_TT_IsAmmoVendorTooltipsEnabled()
local vendorInfo = ammoVendorTooltipsEnabled and MTH_TT_FindVendorInfo(name) or nil local vendorInfo = ammoVendorTooltipsEnabled and MTH_TT_FindVendorInfo(name) or nil
local row = beastTooltipsEnabled and MTH_TT_FindBeastRow(name) or nil local row = beastTooltipsEnabled and MTH_TT_FindBeastRow(name) or nil
if not row and not vendorInfo then local scorpokAdded = MTH_TT_AddScorpokTargetsTooltip(unit, name)
if not row and not vendorInfo and not scorpokAdded then
state.lookupMiss = (state.lookupMiss or 0) + 1 state.lookupMiss = (state.lookupMiss or 0) + 1
MTH_TT_StateSet("lookup-miss", name, normalized) MTH_TT_StateSet("lookup-miss", name, normalized)
MTH_TT_Log("lookup miss: unit='" .. tostring(name) .. "' normalized='" .. tostring(normalized) .. "'") MTH_TT_Log("lookup miss: unit='" .. tostring(name) .. "' normalized='" .. tostring(normalized) .. "'")
@@ -1115,6 +1494,9 @@ local function MTH_TT_AddTooltip(unit)
end end
local addedAnything = nil local addedAnything = nil
if scorpokAdded then
addedAnything = 1
end
if vendorInfo and (vendorInfo.arrows or vendorInfo.bullets) and not MTH_TT_HasExistingVendorTooltipLine() then if vendorInfo and (vendorInfo.arrows or vendorInfo.bullets) and not MTH_TT_HasExistingVendorTooltipLine() then
if vendorInfo.arrows and vendorInfo.bullets then if vendorInfo.arrows and vendorInfo.bullets then
@@ -1163,18 +1545,22 @@ local function MTH_TT_EnsureInjectFrame()
if MTH_Tooltips.injectFrame then if MTH_Tooltips.injectFrame then
return MTH_Tooltips.injectFrame return MTH_Tooltips.injectFrame
end end
local frame = CreateFrame("Frame", "MTH_TooltipsInjectFrame") local frame = CreateFrame("Frame", "MTH_TooltipsInject")
frame.pending = false frame.pending = false
frame:SetScript("OnUpdate", function(self) frame.onUpdate = function()
self = self or this if not this then
if not self or not self.pending then
return return
end end
self.pending = false if not this.pending then
this:SetScript("OnUpdate", nil)
return
end
this.pending = false
this:SetScript("OnUpdate", nil)
if MTH_Tooltips and MTH_Tooltips.enabled then if MTH_Tooltips and MTH_Tooltips.enabled then
MTH_TT_AddTooltip("mouseover") MTH_TT_AddTooltip("mouseover")
end end
end) end
MTH_Tooltips.injectFrame = frame MTH_Tooltips.injectFrame = frame
return frame return frame
end end
@@ -1183,6 +1569,9 @@ local function MTH_TT_RequestInject()
local frame = MTH_TT_EnsureInjectFrame() local frame = MTH_TT_EnsureInjectFrame()
if frame then if frame then
frame.pending = true frame.pending = true
if not frame:GetScript("OnUpdate") then
frame:SetScript("OnUpdate", frame.onUpdate)
end
end end
end end
@@ -1191,20 +1580,23 @@ local function MTH_TT_EnsurePollFrame()
return MTH_Tooltips.pollFrame return MTH_Tooltips.pollFrame
end end
local frame = CreateFrame("Frame", "MTH_TooltipsPollFrame") local frame = CreateFrame("Frame", "MTH_TooltipsPoll")
frame:SetScript("OnUpdate", function(_, elapsed) frame:SetScript("OnUpdate", function()
if not (MTH_Tooltips and MTH_Tooltips.enabled) then if not (MTH_Tooltips and MTH_Tooltips.enabled) then
return return
end end
if GameTooltip and GameTooltip.IsShown and GameTooltip:IsShown() then MTH_Tooltips.hintElapsed = (MTH_Tooltips.hintElapsed or 0) + (arg1 or 0)
MTH_TT_AddOwnPetTooltipHint() if MTH_Tooltips.hintElapsed >= 0.25 then
if not MTH_TT_HasExistingNotLearnedLine() then MTH_Tooltips.hintElapsed = 0
MTH_TT_AddPetActionNotLearnedHint() if GameTooltip and GameTooltip.IsShown and GameTooltip:IsShown() then
MTH_TT_AddOwnPetTooltipHint()
if not MTH_TT_HasExistingNotLearnedLine() then
MTH_TT_AddPetActionNotLearnedHint()
end
end end
end end
elapsed = elapsed or arg1
MTH_Tooltips.pollElapsed = (MTH_Tooltips.pollElapsed or 0) + (elapsed or 0) MTH_Tooltips.pollElapsed = (MTH_Tooltips.pollElapsed or 0) + (elapsed or 0)
if MTH_Tooltips.pollElapsed < 0.15 then if MTH_Tooltips.pollElapsed < 0.15 then
return return
@@ -1242,6 +1634,74 @@ local function MTH_TT_EnsurePollFrame()
return frame return frame
end end
local function MTH_TT_SetRuntimeActive(active)
local injectFrame = MTH_Tooltips.injectFrame
if injectFrame then
if not active then
injectFrame.pending = false
injectFrame:SetScript("OnUpdate", nil)
end
end
local pollFrame = MTH_Tooltips.pollFrame
if pollFrame then
if active then
pollFrame:SetScript("OnUpdate", pollFrame:GetScript("OnUpdate") or function()
if not (MTH_Tooltips and MTH_Tooltips.enabled) then
return
end
MTH_Tooltips.hintElapsed = (MTH_Tooltips.hintElapsed or 0) + (arg1 or 0)
if MTH_Tooltips.hintElapsed >= 0.25 then
MTH_Tooltips.hintElapsed = 0
if GameTooltip and GameTooltip.IsShown and GameTooltip:IsShown() then
MTH_TT_AddOwnPetTooltipHint()
if not MTH_TT_HasExistingNotLearnedLine() then
MTH_TT_AddPetActionNotLearnedHint()
end
end
end
MTH_Tooltips.pollElapsed = (MTH_Tooltips.pollElapsed or 0) + (elapsed or 0)
if MTH_Tooltips.pollElapsed < 0.15 then
return
end
MTH_Tooltips.pollElapsed = 0
local state = MTH_Tooltips.debugState
state.pollTicks = (state.pollTicks or 0) + 1
if not UnitExists("mouseover") then
MTH_Tooltips.lastMouseoverKey = ""
return
end
local name = UnitName("mouseover")
if not name or name == "" then
return
end
local lvl = UnitLevel and UnitLevel("mouseover") or 0
local key = tostring(name) .. "#" .. tostring(lvl)
if key ~= MTH_Tooltips.lastMouseoverKey then
MTH_Tooltips.lastMouseoverKey = key
state.pollTriggers = (state.pollTriggers or 0) + 1
MTH_TT_RequestInject()
return
end
if not MTH_TT_HasExistingTooltipLine() then
MTH_TT_RequestInject()
end
end)
else
MTH_Tooltips.pollElapsed = 0
MTH_Tooltips.hintElapsed = 0
pollFrame:SetScript("OnUpdate", nil)
end
end
end
local function MTH_TT_InstallTooltipHook() local function MTH_TT_InstallTooltipHook()
if MTH_Tooltips.hookInstalled then if MTH_Tooltips.hookInstalled then
return return
@@ -1260,9 +1720,15 @@ local function MTH_TT_InstallTooltipHook()
MTH_TT_RequestInject() MTH_TT_RequestInject()
end) end)
GameTooltip:HookScript("OnTooltipSetItem", function() GameTooltip:HookScript("OnTooltipSetItem", function()
if not (MTH_Tooltips and MTH_Tooltips.enabled) then
return
end
MTH_TT_AddFoodTooltipHint() MTH_TT_AddFoodTooltipHint()
end) end)
GameTooltip:HookScript("OnTooltipSetSpell", function() GameTooltip:HookScript("OnTooltipSetSpell", function()
if not (MTH_Tooltips and MTH_Tooltips.enabled) then
return
end
MTH_TT_AddPetActionNotLearnedHint() MTH_TT_AddPetActionNotLearnedHint()
end) end)
end) end)
@@ -1284,6 +1750,7 @@ function MTH_Tooltips:init()
MTH_TT_InstallTooltipHook() MTH_TT_InstallTooltipHook()
MTH_TT_EnsureInjectFrame() MTH_TT_EnsureInjectFrame()
MTH_TT_EnsurePollFrame() MTH_TT_EnsurePollFrame()
MTH_TT_SetRuntimeActive(self.enabled)
MTH_TT_Log("module init complete") MTH_TT_Log("module init complete")
end end
@@ -1307,6 +1774,9 @@ function MTH_Tooltips:setEnabled(enabled)
elseif self.enabled then elseif self.enabled then
MTH_TT_EnsurePollFrame() MTH_TT_EnsurePollFrame()
MTH_TT_EnsureInjectFrame() MTH_TT_EnsureInjectFrame()
MTH_TT_SetRuntimeActive(true)
else
MTH_TT_SetRuntimeActive(false)
end end
end end
@@ -1357,6 +1827,7 @@ end
function MTH_Tooltips:cleanup() function MTH_Tooltips:cleanup()
self.enabled = false self.enabled = false
MTH_TT_SetRuntimeActive(false)
end end
function MTH_Tooltips:GetDebugSnapshot() function MTH_Tooltips:GetDebugSnapshot()
+217 -149
View File
@@ -1,149 +1,217 @@
if not ZHunterMod_Saved then if not ZHunterMod_Saved then
ZHunterMod_Saved = {} ZHunterMod_Saved = {}
end end
BINDING_HEADER_ZAspectHeader = "ZAspect Buttons" BINDING_HEADER_ZAspectHeader = "ZAspect Buttons"
BINDING_HEADER_ZTrackHeader = "ZTrack Buttons" BINDING_HEADER_ZTrackHeader = "ZTrack Buttons"
BINDING_HEADER_ZTrapHeader = "ZTrap Buttons" BINDING_HEADER_ZTrapHeader = "ZTrap Buttons"
BINDING_HEADER_ZPetHeader = "ZPet Buttons" BINDING_HEADER_ZPetHeader = "ZPet Buttons"
BINDING_HEADER_ZAmmoHeader = "ZAmmo Buttons" BINDING_HEADER_ZAmmoHeader = "ZAmmo Buttons"
BINDING_HEADER_ZMountsHeader = "ZMounts Buttons" BINDING_HEADER_ZMountsHeader = "ZMounts Buttons"
BINDING_HEADER_ZCompanionsHeader = "ZCompanions Buttons" BINDING_HEADER_ZCompanionsHeader = "ZCompanions Buttons"
BINDING_HEADER_ZToysHeader = "ZToys Buttons" BINDING_HEADER_ZToysHeader = "ZToys Buttons"
ZHunterModTooltip = CreateFrame("GameTooltip", "ZHunterModTooltip", nil, "GameTooltipTemplate") ZHunterModTooltip = CreateFrame("GameTooltip", "MTH_ZH_AbilityProbe", nil, "GameTooltipTemplate")
ZHunterModTooltipTextLeft1 = getglobal("MTH_ZH_AbilityProbeTextLeft1")
function MTH_ZH_IsModuleEnabled()
if not (MTH and MTH.IsModuleEnabled) then MTH_ZH_TRACE_ENABLED = false
return true
end local function MTH_ZH_DescribePoint(frame)
return MTH:IsModuleEnabled("zhunter", true) if not (frame and frame.GetPoint) then
end return "<no-frame>"
end
function MTH_ZH_GetSavedRoot() local point, relTo, relPoint, x, y = frame:GetPoint()
if type(ZHunterMod_Saved) ~= "table" then local relName = "nil"
ZHunterMod_Saved = {} if type(relTo) == "table" and relTo.GetName then
end relName = tostring(relTo:GetName() or "<anon>")
return ZHunterMod_Saved elseif relTo then
end relName = tostring(relTo)
end
function MTH_ZH_GetSavedTable(key) return tostring(point or "nil")
local root = MTH_ZH_GetSavedRoot() .. "->" .. relName
if type(key) ~= "string" or key == "" then .. ":" .. tostring(relPoint or "nil")
return root .. " @(" .. tostring(x) .. "," .. tostring(y) .. ")"
end end
if type(root[key]) ~= "table" then
root[key] = {} function MTH_ZH_Trace(msg)
end if not MTH_ZH_TRACE_ENABLED then
return root[key] return
end end
if MTH and MTH.Print then
local function MTH_ZH_MigrateButtonSavedKeys_Replace() MTH:Print("[ZHTRACE] " .. tostring(msg), "debug")
local root = MTH_ZH_GetSavedRoot() elseif DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then
if type(root) ~= "table" then DEFAULT_CHAT_FRAME:AddMessage("[ZHTRACE] " .. tostring(msg))
return end
end end
local mapping = { function MTH_ZH_TraceButtonPoint(frame, reason)
{"ZHunterButtonAspect", "zButtonAspect"}, if not MTH_ZH_TRACE_ENABLED then
{"ZHunterButtonTrack", "zButtonTrack"}, return
{"ZHunterButtonTrap", "zButtonTrap"}, end
{"ZHunterButtonAmmo", "zButtonAmmo"}, if not frame then
{"ZHunterButtonPet", "zButtonPet"}, MTH_ZH_Trace("point " .. tostring(reason or "") .. " frame=nil")
{"ZHunterButtonMounts", "zButtonMounts"}, return
{"ZHunterButtonCompanions", "zButtonCompanions"}, end
{"ZHunterButtonToys", "zButtonToys"}, local name = frame.GetName and frame:GetName() or "<unnamed>"
} MTH_ZH_Trace("point " .. tostring(reason or "") .. " " .. tostring(name) .. " " .. MTH_ZH_DescribePoint(frame))
end
for i = 1, table.getn(mapping) do
local oldKey = mapping[i][1] function MTH_ZH_TraceAllButtonPoints(reason)
local newKey = mapping[i][2] if not MTH_ZH_TRACE_ENABLED then
if root[oldKey] ~= nil then return
root[newKey] = root[oldKey] end
root[oldKey] = nil local names = {
end "zButtonAspect",
end "zButtonAmmo",
end "zButtonTrack",
"zButtonTrap",
MTH_ZH_MigrateButtonSavedKeys_Replace() "zButtonRanged",
"zButtonPet",
function MTH_ZH_Print(message, severity) "zButtonMounts",
if type(MTH_Log) == "function" then "zButtonCompanions",
MTH_Log(message, severity) "zButtonToys",
return }
end MTH_ZH_Trace("snapshot begin reason=" .. tostring(reason or ""))
if MTH and MTH.Print then for i = 1, table.getn(names) do
MTH:Print(message, severity) local frame = getglobal(names[i])
return MTH_ZH_TraceButtonPoint(frame, tostring(reason or "") .. ":" .. tostring(names[i]))
end end
if DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then MTH_ZH_Trace("snapshot end reason=" .. tostring(reason or ""))
DEFAULT_CHAT_FRAME:AddMessage("[MetaHunt] " .. tostring(message or ""), 1, 0.9, 0.3) end
end
end function MTH_ZH_IsModuleEnabled()
if not (MTH and MTH.IsModuleEnabled) then
function MTH_ZH_HandleDisabledSlash(message, tableKey, fieldKey) return true
if MTH_ZH_IsModuleEnabled() then end
return false return MTH:IsModuleEnabled("zhunter", true)
end end
if type(tableKey) == "string" and tableKey ~= "" then function MTH_ZH_GetSavedRoot()
if fieldKey then if type(ZHunterMod_Saved) ~= "table" then
local tbl = MTH_ZH_GetSavedTable(tableKey) ZHunterMod_Saved = {}
tbl[fieldKey] = nil end
else return ZHunterMod_Saved
local root = MTH_ZH_GetSavedRoot() end
root[tableKey] = nil
end function MTH_ZH_GetSavedTable(key)
end local root = MTH_ZH_GetSavedRoot()
if type(key) ~= "string" or key == "" then
if message then return root
MTH_ZH_Print(message) end
end if type(root[key]) ~= "table" then
root[key] = {}
return true end
end return root[key]
end
function ZHunterMod_AlignButtons()
zButtonAmmo:ClearAllPoints() local function MTH_ZH_MigrateButtonSavedKeys_Replace()
zButtonAmmo:SetPoint("TOP", zButtonAspect, "BOTTOM", 0, -15) local root = MTH_ZH_GetSavedRoot()
zButtonTrack:ClearAllPoints() if type(root) ~= "table" then
zButtonTrack:SetPoint("TOP", zButtonAmmo, "BOTTOM", 0, -15) return
zButtonTrap:ClearAllPoints() end
zButtonTrap:SetPoint("TOP", zButtonTrack, "BOTTOM", 0, -15)
zButtonPet:ClearAllPoints() local mapping = {
zButtonPet:SetPoint("TOP", zButtonTrap, "BOTTOM", 0, -15) {"ZHunterButtonAspect", "zButtonAspect"},
zButtonMounts:ClearAllPoints() {"ZHunterButtonTrack", "zButtonTrack"},
zButtonMounts:SetPoint("TOP", zButtonPet, "BOTTOM", 0, -15) {"ZHunterButtonTrap", "zButtonTrap"},
zButtonCompanions:ClearAllPoints() {"ZHunterButtonAmmo", "zButtonAmmo"},
zButtonCompanions:SetPoint("TOP", zButtonMounts, "BOTTOM", 0, -15) {"ZHunterButtonPet", "zButtonPet"},
zButtonToys:ClearAllPoints() {"ZHunterButtonMounts", "zButtonMounts"},
zButtonToys:SetPoint("TOP", zButtonCompanions, "BOTTOM", 0, -15) {"ZHunterButtonCompanions", "zButtonCompanions"},
if AutoStripDisplay then {"ZHunterButtonToys", "zButtonToys"},
AutoStripDisplay:ClearAllPoints() }
AutoStripDisplay:SetPoint("TOP", zButtonToys, "BOTTOM", 0, -10)
end for i = 1, table.getn(mapping) do
end local oldKey = mapping[i][1]
local newKey = mapping[i][2]
function ZMarkTarget() if root[oldKey] ~= nil then
if not MTH_ZH_IsModuleEnabled() then root[newKey] = root[oldKey]
return root[oldKey] = nil
end end
end
if not UnitExists("target") then return end end
for i=1, 40 do
if not UnitDebuff("target", i) then break end MTH_ZH_MigrateButtonSavedKeys_Replace()
ZHunterModTooltip:SetOwner(UIParent, "ANCHOR_NONE")
ZHunterModTooltip:SetUnitDebuff("target", i) function MTH_ZH_Print(message, severity)
local spell = ZHunterModTooltipTextLeft1:GetText() if type(MTH_Log) == "function" then
if spell == ZHUNTER_HUNTERSMARK then MTH_Log(message, severity)
return return
end end
end if MTH and MTH.Print then
CastSpellByName(ZHUNTER_HUNTERSMARK) MTH:Print(message, severity)
return 1 return
end end
if DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then
SLASH_ZHunterMod1 = "/zhunter" DEFAULT_CHAT_FRAME:AddMessage("[MetaHunt] " .. tostring(message or ""), 1, 0.9, 0.3)
SlashCmdList["ZHunterMod"] = function(msg) end
MTH_ZH_Print("Possible Slash Commands: \"/zammo\", \"/zaspect\", \"/ztrack\", \"/ztrap\", \"/zpet\", \"/zmounts\", \"/zcompanions\", \"/zminipets\", \"/ztoys\", \"/zstrip\", \"/zantidaze\"") end
end
function MTH_ZH_HandleDisabledSlash(message, tableKey, fieldKey)
if MTH_ZH_IsModuleEnabled() then
return false
end
if type(tableKey) == "string" and tableKey ~= "" then
if fieldKey then
local tbl = MTH_ZH_GetSavedTable(tableKey)
tbl[fieldKey] = nil
else
local root = MTH_ZH_GetSavedRoot()
root[tableKey] = nil
end
end
if message then
MTH_ZH_Print(message)
end
return true
end
function ZHunterMod_AlignButtons()
MTH_ZH_TraceAllButtonPoints("AlignButtons:before")
zButtonAmmo:ClearAllPoints()
zButtonAmmo:SetPoint("TOP", zButtonAspect, "BOTTOM", 0, -15)
zButtonTrack:ClearAllPoints()
zButtonTrack:SetPoint("TOP", zButtonAmmo, "BOTTOM", 0, -15)
zButtonTrap:ClearAllPoints()
zButtonTrap:SetPoint("TOP", zButtonTrack, "BOTTOM", 0, -15)
zButtonPet:ClearAllPoints()
zButtonPet:SetPoint("TOP", zButtonTrap, "BOTTOM", 0, -15)
zButtonMounts:ClearAllPoints()
zButtonMounts:SetPoint("TOP", zButtonPet, "BOTTOM", 0, -15)
zButtonCompanions:ClearAllPoints()
zButtonCompanions:SetPoint("TOP", zButtonMounts, "BOTTOM", 0, -15)
zButtonToys:ClearAllPoints()
zButtonToys:SetPoint("TOP", zButtonCompanions, "BOTTOM", 0, -15)
if AutoStripDisplay then
AutoStripDisplay:ClearAllPoints()
AutoStripDisplay:SetPoint("TOP", zButtonToys, "BOTTOM", 0, -10)
end
MTH_ZH_TraceAllButtonPoints("AlignButtons:after")
end
function ZMarkTarget()
if not MTH_ZH_IsModuleEnabled() then
return
end
if not UnitExists("target") then return end
for i=1, 40 do
if not UnitDebuff("target", i) then break end
ZHunterModTooltip:SetOwner(UIParent, "ANCHOR_NONE")
ZHunterModTooltip:SetUnitDebuff("target", i)
local spell = ZHunterModTooltipTextLeft1:GetText()
if spell == ZHUNTER_HUNTERSMARK then
return
end
end
CastSpellByName(ZHUNTER_HUNTERSMARK)
return 1
end
SLASH_ZHunterMod1 = "/zhunter"
SlashCmdList["ZHunterMod"] = function(msg)
MTH_ZH_Print("Possible Slash Commands: \"/zammo\", \"/zaspect\", \"/ztrack\", \"/ztrap\", \"/zpet\", \"/zmounts\", \"/zcompanions\", \"/zminipets\", \"/ztoys\", \"/zstrip\", \"/zantidaze\"")
end
File diff suppressed because it is too large Load Diff
+114 -12
View File
@@ -8,10 +8,10 @@ MTH_ZH_MANAGED_HOOKS = true
local MTH_ZHunter = { local MTH_ZHunter = {
name = "zhunter", name = "zhunter",
enabled = true, enabled = true,
version = "1.0.4", version = "1.2.0",
events = { events = {
"VARIABLES_LOADED", "VARIABLES_LOADED",
"PLAYER_ENTERING_WORLD", -- PLAYER_ENTERING_WORLD handled by bootstrap frame + adjustment frames
"MTH_PET_LIVE_STATE_CHANGED", "MTH_PET_LIVE_STATE_CHANGED",
}, },
features = { features = {
@@ -31,7 +31,13 @@ local function MTH_ZH_Log(msg)
MTH:Print("[ZH MODULE] " .. tostring(msg), "debug") MTH:Print("[ZH MODULE] " .. tostring(msg), "debug")
end end
local MTH_ZH_PostLoginRestoreFrame = nil local function MTH_ZH_TraceLocal(msg)
if type(MTH_ZH_Trace) == "function" then
MTH_ZH_Trace(msg)
end
end
local MTH_ZH_PostLoginRestore = nil
local MTH_ZH_BootstrapFrame = nil local MTH_ZH_BootstrapFrame = nil
local MTH_ZH_SyncSavedVariables local MTH_ZH_SyncSavedVariables
local MTH_ZH_SetButtonsVisible local MTH_ZH_SetButtonsVisible
@@ -105,21 +111,20 @@ function MTH_ZH_OnDeferredInitComplete()
return return
end end
MTH_ZH_SyncSavedVariables() MTH_ZH_SyncSavedVariables()
MTH_ZH_ApplyDefaultWidgetSpawnLayoutOnce()
MTH_ZH_RestoreRuntimeFeatureFlags() MTH_ZH_RestoreRuntimeFeatureFlags()
MTH_ZH_QueuePostLoginRestore("deferred-init") MTH_ZH_QueuePostLoginRestore("deferred-init")
end end
MTH_ZH_QueuePostLoginRestore = function(tag) MTH_ZH_QueuePostLoginRestore = function(tag)
if not MTH_ZH_PostLoginRestoreFrame then if not MTH_ZH_PostLoginRestore then
MTH_ZH_PostLoginRestoreFrame = CreateFrame("Frame", "MTH_ZH_PostLoginRestoreFrame") MTH_ZH_PostLoginRestore = CreateFrame("Frame", "MTH_ZH_PostLoginRestore")
if not MTH_ZH_PostLoginRestoreFrame then if not MTH_ZH_PostLoginRestore then
return return
end end
end end
MTH_ZH_PostLoginRestoreFrame._mthElapsed = 0 MTH_ZH_PostLoginRestore._mthElapsed = 0
MTH_ZH_PostLoginRestoreFrame:SetScript("OnUpdate", function() MTH_ZH_PostLoginRestore:SetScript("OnUpdate", function()
this._mthElapsed = (this._mthElapsed or 0) + (arg1 or 0) this._mthElapsed = (this._mthElapsed or 0) + (arg1 or 0)
if this._mthElapsed < 0.2 then if this._mthElapsed < 0.2 then
return return
@@ -132,6 +137,9 @@ MTH_ZH_QueuePostLoginRestore = function(tag)
MTH_ZH_SyncSavedVariables() MTH_ZH_SyncSavedVariables()
MTH_ZH_RestoreRuntimeFeatureFlags() MTH_ZH_RestoreRuntimeFeatureFlags()
if type(MTH_ZH_TraceAllButtonPoints) == "function" then
MTH_ZH_TraceAllButtonPoints("post-login-restore:" .. tostring(tag))
end
MTH_ZH_Log("post-login restore applied: " .. tostring(tag)) MTH_ZH_Log("post-login restore applied: " .. tostring(tag))
end) end)
end end
@@ -141,7 +149,7 @@ local function MTH_ZH_EnsureBootstrapRestoreFrame()
return MTH_ZH_BootstrapFrame return MTH_ZH_BootstrapFrame
end end
MTH_ZH_BootstrapFrame = CreateFrame("Frame", "MTH_ZH_BootstrapRestoreFrame") MTH_ZH_BootstrapFrame = CreateFrame("Frame", "MTH_ZH_BootstrapRestore")
if not MTH_ZH_BootstrapFrame then if not MTH_ZH_BootstrapFrame then
return nil return nil
end end
@@ -170,10 +178,17 @@ local function MTH_ZH_EnsureBootstrapRestoreFrame()
end end
MTH_ZH_ApplyEnabledRuntimeState = function(source) MTH_ZH_ApplyEnabledRuntimeState = function(source)
MTH_ZH_TraceLocal("apply-enabled-runtime-state source=" .. tostring(source or ""))
if type(MTH_ZH_TraceAllButtonPoints) == "function" then
MTH_ZH_TraceAllButtonPoints("apply-enabled:before:" .. tostring(source or ""))
end
MTH_ZH_SyncSavedVariables() MTH_ZH_SyncSavedVariables()
MTH_ZH_SetButtonsVisible(true) MTH_ZH_SetButtonsVisible(true)
MTH_ZH_SetAuxFramesVisible(true) MTH_ZH_SetAuxFramesVisible(true)
MTH_ZH_RestoreRuntimeFeatureFlags() MTH_ZH_RestoreRuntimeFeatureFlags()
if type(MTH_ZH_TraceAllButtonPoints) == "function" then
MTH_ZH_TraceAllButtonPoints("apply-enabled:after:" .. tostring(source or ""))
end
end end
MTH_ZH_SyncSavedVariables = function() MTH_ZH_SyncSavedVariables = function()
@@ -182,17 +197,22 @@ MTH_ZH_SyncSavedVariables = function()
end end
local moduleStore = MTH:GetModuleCharSavedVariables("zhunter") local moduleStore = MTH:GetModuleCharSavedVariables("zhunter")
MTH_ZH_TraceLocal("sync-saved begin zhuntermod_saved=" .. tostring(type(ZHunterMod_Saved)))
if type(ZHunterMod_Saved) == "table" then if type(ZHunterMod_Saved) == "table" then
if MTH_CharSavedVariables and MTH_CharSavedVariables.modules then if MTH_CharSavedVariables and MTH_CharSavedVariables.modules then
MTH_CharSavedVariables.modules.zhunter = ZHunterMod_Saved MTH_CharSavedVariables.modules.zhunter = ZHunterMod_Saved
MTH_ZH_TraceLocal("sync-saved wrote ZHunterMod_Saved -> MTH_CharSavedVariables.modules.zhunter")
end end
elseif type(moduleStore) == "table" then elseif type(moduleStore) == "table" then
ZHunterMod_Saved = moduleStore ZHunterMod_Saved = moduleStore
MTH_ZH_TraceLocal("sync-saved loaded moduleStore -> ZHunterMod_Saved")
end end
MTH_ZH_TraceLocal("sync-saved end")
end end
MTH_ZH_SetButtonsVisible = function(visible) MTH_ZH_SetButtonsVisible = function(visible)
MTH_ZH_TraceLocal("set-buttons-visible visible=" .. tostring(visible and true or false))
local buttonNames = { local buttonNames = {
"zButtonAspect", "zButtonAspect",
"zButtonTrack", "zButtonTrack",
@@ -274,12 +294,34 @@ MTH_ZH_SetButtonsVisible = function(visible)
for _, buttonName in ipairs(buttonNames) do for _, buttonName in ipairs(buttonNames) do
local button = getglobal(buttonName) local button = getglobal(buttonName)
if button then if button then
MTH_ZH_SetChildButtonsVisible(button, buttonName, visible) if type(MTH_ZH_TraceButtonPoint) == "function" then
MTH_ZH_TraceButtonPoint(button, "set-buttons-visible:before:" .. tostring(buttonName))
end
if visible then if visible then
button:Show() -- Respect per-button enabled state
local getterName = buttonName .. "_GetSaved"
local getter = getglobal(getterName)
local shouldShow = true
if type(getter) == "function" then
local ok, saved = pcall(getter)
if ok and type(saved) == "table" and (saved["enabled"] == false or saved["enabled"] == 0) then
shouldShow = false
end
end
if shouldShow then
MTH_ZH_SetChildButtonsVisible(button, buttonName, true)
button:Show()
else
MTH_ZH_SetChildButtonsVisible(button, buttonName, false)
button:Hide()
end
else else
MTH_ZH_SetChildButtonsVisible(button, buttonName, false)
button:Hide() button:Hide()
end end
if type(MTH_ZH_TraceButtonPoint) == "function" then
MTH_ZH_TraceButtonPoint(button, "set-buttons-visible:after:" .. tostring(buttonName))
end
end end
end end
end end
@@ -288,6 +330,57 @@ MTH_ZH_SetAuxFramesVisible = function(visible)
return return
end end
local function MTH_ZH_SetAdjustmentHandlersActive(active)
local frameSpecs = {
{ frame = "MTH_ZH_AspectAdjust", handler = "MTH_ZH_AspectAdjust_OnEvent", getter = "zButtonAspect_GetSaved" },
{ frame = "MTH_ZH_TrackAdjust", handler = "MTH_ZH_TrackAdjust_OnEvent", getter = "zButtonTrack_GetSaved" },
{ frame = "MTH_ZH_TrapAdjust", handler = "MTH_ZH_TrapAdjust_OnEvent", getter = "zButtonTrap_GetSaved" },
{ frame = "MTH_ZH_RangedAdjust", handler = "MTH_ZH_RangedAdjust_OnEvent", getter = "zButtonRanged_GetSaved" },
{ frame = "MTH_ZH_AmmoAdjust", handler = "MTH_ZH_AmmoAdjust_OnEvent", getter = "zButtonAmmo_GetSaved" },
{ frame = "MTH_ZH_PetAdjust", handler = "MTH_ZH_PetAdjust_OnEvent", getter = "zButtonPet_GetSaved" },
{ 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" },
}
local function isFeatureEnabled(getterName)
local getter = getglobal(getterName)
if type(getter) ~= "function" then
return true
end
local ok, saved = pcall(getter)
if not ok or type(saved) ~= "table" then
return true
end
if saved["enabled"] == false or saved["enabled"] == 0 then
return false
end
return true
end
for _, spec in ipairs(frameSpecs) do
local frameName = spec.frame
local handlerName = spec.handler
local frame = getglobal(frameName)
if frame and frame.SetScript then
if active then
if isFeatureEnabled(spec.getter) then
local handler = getglobal(handlerName)
if type(handler) == "function" then
frame:SetScript("OnEvent", handler)
else
frame:SetScript("OnEvent", nil)
end
else
frame:SetScript("OnEvent", nil)
end
else
frame:SetScript("OnEvent", nil)
end
end
end
end
local function MTH_ZH_ClearRuntimeFeatureFlags() local function MTH_ZH_ClearRuntimeFeatureFlags()
return return
end end
@@ -307,14 +400,23 @@ function MTH_ZHunter:init()
end end
function MTH_ZHunter:setEnabled(enabled) function MTH_ZHunter:setEnabled(enabled)
MTH_ZH_TraceLocal("module setEnabled enabled=" .. tostring(enabled and true or false))
MTH_ZH_SyncSavedVariables() MTH_ZH_SyncSavedVariables()
if enabled then if enabled then
MTH_ZH_EnsureBootstrapRestoreFrame() MTH_ZH_EnsureBootstrapRestoreFrame()
MTH_ZH_SetAdjustmentHandlersActive(true)
MTH_ZH_ApplyEnabledRuntimeState("setEnabled") MTH_ZH_ApplyEnabledRuntimeState("setEnabled")
else else
MTH_ZH_ClearRuntimeFeatureFlags() MTH_ZH_ClearRuntimeFeatureFlags()
MTH_ZH_SetAdjustmentHandlersActive(false)
if type(MTH_ZH_TraceAllButtonPoints) == "function" then
MTH_ZH_TraceAllButtonPoints("setEnabled:false:before-hide")
end
MTH_ZH_SetButtonsVisible(false) MTH_ZH_SetButtonsVisible(false)
MTH_ZH_SetAuxFramesVisible(false) MTH_ZH_SetAuxFramesVisible(false)
if type(MTH_ZH_TraceAllButtonPoints) == "function" then
MTH_ZH_TraceAllButtonPoints("setEnabled:false:after-hide")
end
end end
end end
File diff suppressed because it is too large Load Diff
+392 -328
View File
@@ -1,329 +1,393 @@
local function zButtonAspect_GetRoot() local function zButtonAspect_GetRoot()
return MTH_ZH_GetSavedRoot() return MTH_ZH_GetSavedRoot()
end end
local root = zButtonAspect_GetRoot() local root = zButtonAspect_GetRoot()
if not root["zButtonAspect"] then if not root["zButtonAspect"] then
root["zButtonAspect"] = {} root["zButtonAspect"] = {}
root["zButtonAspect"]["spells"] = {1, 2, 3, 4, 5, 6, 7} root["zButtonAspect"]["spells"] = {1, 2, 3, 4, 5, 6, 7}
root["zButtonAspect"]["rows"] = 1 root["zButtonAspect"]["rows"] = 1
root["zButtonAspect"]["horizontal"] = nil root["zButtonAspect"]["horizontal"] = nil
root["zButtonAspect"]["vertical"] = nil root["zButtonAspect"]["vertical"] = nil
root["zButtonAspect"]["firstbutton"] = "RIGHT" root["zButtonAspect"]["firstbutton"] = "RIGHT"
root["zButtonAspect"]["enabled"] = 1 root["zButtonAspect"]["enabled"] = 1
root["zButtonAspect"]["tooltip"] = 1 root["zButtonAspect"]["tooltip"] = 1
root["zButtonAspect"]["parent"] = {} root["zButtonAspect"]["parent"] = {}
root["zButtonAspect"]["parent"]["size"] = 36 root["zButtonAspect"]["parent"]["size"] = 36
root["zButtonAspect"]["parent"]["hide"] = nil root["zButtonAspect"]["parent"]["hide"] = nil
root["zButtonAspect"]["parent"]["circle"] = 1 root["zButtonAspect"]["parent"]["circle"] = 1
root["zButtonAspect"]["children"] = {} root["zButtonAspect"]["children"] = {}
root["zButtonAspect"]["children"]["size"] = 36 root["zButtonAspect"]["children"]["size"] = 36
root["zButtonAspect"]["children"]["hideonclick"] = 1 root["zButtonAspect"]["children"]["hideonclick"] = 1
end end
ZHunterMod_Aspect_Spells = { ZHunterMod_Aspect_Spells = {
ZHUNTER_ASPECT_HAWK, ZHUNTER_ASPECT_HAWK,
ZHUNTER_ASPECT_MONKEY, ZHUNTER_ASPECT_MONKEY,
ZHUNTER_ASPECT_WOLF, ZHUNTER_ASPECT_WOLF,
ZHUNTER_ASPECT_CHEETAH, ZHUNTER_ASPECT_CHEETAH,
ZHUNTER_ASPECT_PACK, ZHUNTER_ASPECT_PACK,
ZHUNTER_ASPECT_WILD, ZHUNTER_ASPECT_WILD,
ZHUNTER_ASPECT_BEAST ZHUNTER_ASPECT_BEAST
} }
local ZHUNTER_ASPECT_MAX = table.getn(ZHunterMod_Aspect_Spells) local ZHUNTER_ASPECT_MAX = table.getn(ZHunterMod_Aspect_Spells)
local zButtonAspect_LastAuraUpdateAt = 0
local function zButtonAspect_GetSaved() local zButtonAspect_MinAuraInterval = 0.15
local currentRoot = zButtonAspect_GetRoot() local zButtonAspect_MinAuraIntervalCombat = 0.60
if not currentRoot["zButtonAspect"] then local zButtonAspect_LastAuraTexture = nil
currentRoot["zButtonAspect"] = {} local zButtonAspect_LastParentId = nil
end local zButtonAspect_AuraProbeTextLeft1 = nil
return currentRoot["zButtonAspect"]
end local function zButtonAspect_GetSaved()
local currentRoot = zButtonAspect_GetRoot()
local function zButtonAspect_EnsureConfig() if not currentRoot["zButtonAspect"] then
local saved = zButtonAspect_GetSaved() currentRoot["zButtonAspect"] = {}
saved["count"] = nil end
if saved["rows"] == nil then return currentRoot["zButtonAspect"]
saved["rows"] = 1 end
end
if saved["firstbutton"] == nil then local function zButtonAspect_EnsureConfig()
saved["firstbutton"] = "RIGHT" local saved = zButtonAspect_GetSaved()
end saved["count"] = nil
if saved["enabled"] == nil then if saved["rows"] == nil then
saved["enabled"] = 1 saved["rows"] = 1
end end
if saved["tooltip"] == nil then if saved["firstbutton"] == nil then
saved["tooltip"] = 1 saved["firstbutton"] = "RIGHT"
end end
if not saved["parent"] then if saved["enabled"] == nil then
saved["parent"] = {} saved["enabled"] = 1
end end
if saved["parent"]["size"] == nil then if saved["tooltip"] == nil then
saved["parent"]["size"] = 36 saved["tooltip"] = 1
end end
if saved["parent"]["circle"] == nil then if not saved["parent"] then
saved["parent"]["circle"] = 1 saved["parent"] = {}
end end
if not saved["children"] then if saved["parent"]["size"] == nil then
saved["children"] = {} saved["parent"]["size"] = 36
end end
if saved["children"]["size"] == nil then if saved["parent"]["circle"] == nil then
saved["children"]["size"] = 36 saved["parent"]["circle"] = 1
end end
if saved["children"]["hideonclick"] == nil then if not saved["children"] then
saved["children"]["hideonclick"] = 1 saved["children"] = {}
end end
if not saved["spells"] then if saved["children"]["size"] == nil then
saved["spells"] = {} saved["children"]["size"] = 36
end end
if not saved["visible"] then if saved["children"]["hideonclick"] == nil then
saved["visible"] = {} saved["children"]["hideonclick"] = 1
end end
for i = 1, ZHUNTER_ASPECT_MAX do if not saved["spells"] then
if not tonumber(saved["spells"][i]) then saved["spells"] = {}
saved["spells"][i] = i end
end if not saved["visible"] then
if saved["visible"][i] == nil then saved["visible"] = {}
saved["visible"][i] = 1 end
end for i = 1, ZHUNTER_ASPECT_MAX do
end if not tonumber(saved["spells"][i]) then
end saved["spells"][i] = i
end
local function zButtonAspect_ApplyRuntimeSettings() if saved["visible"][i] == nil then
if not zButtonAspect then saved["visible"][i] = 1
return end
end end
local saved = zButtonAspect_GetSaved() end
zButtonAspect.tooltip = saved["tooltip"] and true or false
zButtonAspect.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false local function zButtonAspect_ApplyRuntimeSettings()
end if not zButtonAspect then
return
local function zButtonAspect_IsKnownAspectSpellId(spellId) end
if not spellId then local saved = zButtonAspect_GetSaved()
return false zButtonAspect.tooltip = saved["tooltip"] and true or false
end zButtonAspect.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false
local spellName = GetSpellName(spellId, "spell") zButtonAspect.expandonhover = saved["children"] and saved["children"]["expandonhover"] and true or false
if not spellName or spellName == "" then zButtonAspect.fadetimer = saved["children"] and tonumber(saved["children"]["fadetimer"]) or 0
return false end
end
for i = 1, table.getn(ZHunterMod_Aspect_Spells) do local function zButtonAspect_IsKnownAspectSpellId(spellId)
if ZHunterMod_Aspect_Spells[i] == spellName then if not spellId then
return true return false
end end
end local spellName = GetSpellName(spellId, "spell")
return false if not spellName or spellName == "" then
end return false
end
local function zButtonAspect_EnsureValidParentId() for i = 1, table.getn(ZHunterMod_Aspect_Spells) do
if not (zButtonAspect and zButtonAspect.count) then if ZHunterMod_Aspect_Spells[i] == spellName then
return return true
end end
end
if zButtonAspect_IsKnownAspectSpellId(zButtonAspect.id) then return false
return end
end
local function zButtonAspect_EnsureValidParentId()
for i = 1, zButtonAspect.count do if not (zButtonAspect and zButtonAspect.count) then
local child = getglobal(zButtonAspect.name .. i) return
if child and child.id and zButtonAspect_IsKnownAspectSpellId(child.id) then end
zButtonAspect.id = child.id
zButtonAspect.isspell = 1 if zButtonAspect_IsKnownAspectSpellId(zButtonAspect.id) then
ZSpellButton_UpdateButton(zButtonAspect) return
ZSpellButton_UpdateCooldown(zButtonAspect) end
return
end for i = 1, zButtonAspect.count do
end local child = getglobal(zButtonAspect.name .. i)
end if child and child.id and zButtonAspect_IsKnownAspectSpellId(child.id) then
zButtonAspect.id = child.id
function zButtonAspect_OnLoad() zButtonAspect.isspell = 1
this:RegisterEvent("VARIABLES_LOADED") ZSpellButton_UpdateButton(zButtonAspect)
end ZSpellButton_UpdateCooldown(zButtonAspect)
return
function zButtonAspect_OnEvent() end
if event == "VARIABLES_LOADED" then end
if not zButtonAspect then end
return
end function zButtonAspect_OnLoad()
if UnitClass("player") ~= ZHUNTER_HUNTER then this:RegisterEvent("VARIABLES_LOADED")
zButtonAspect:UnregisterAllEvents() end
zButtonAspect:Hide()
return function zButtonAspect_OnEvent()
end if event == "VARIABLES_LOADED" then
zButtonAspect_CreateButtons() if not zButtonAspect then
zButtonAspectAdjustment = CreateFrame("Frame", "zButtonAspectAdjustment") return
zButtonAspectAdjustment:RegisterEvent("PLAYER_AURAS_CHANGED") end
zButtonAspectAdjustment:RegisterEvent("PLAYER_ENTERING_WORLD") if UnitClass("player") ~= ZHUNTER_HUNTER then
zButtonAspectAdjustment:RegisterEvent("SPELLS_CHANGED") zButtonAspect:UnregisterAllEvents()
zButtonAspectAdjustment:RegisterEvent("CHARACTER_POINTS_CHANGED") zButtonAspect:Hide()
zButtonAspectAdjustment:RegisterEvent("LEARNED_SPELL_IN_TAB") return
zButtonAspectAdjustment:SetScript("OnEvent", zButtonAspectAdjustment_OnEvent) end
zButtonAspect_Tooltip = CreateFrame("GameTooltip", "zButtonAspect_Tooltip", nil, "GameTooltipTemplate") zButtonAspect_CreateButtons()
zButtonAspect_SetupSizeAndPosition() MTH_ZH_AspectAdjust = CreateFrame("Frame", "MTH_ZH_AspectAdjust")
end MTH_ZH_AspectAdjust:RegisterEvent("PLAYER_AURAS_CHANGED")
end MTH_ZH_AspectAdjust:RegisterEvent("PLAYER_ENTERING_WORLD")
MTH_ZH_AspectAdjust:RegisterEvent("SPELLS_CHANGED")
function zButtonAspect_CreateButtons() MTH_ZH_AspectAdjust:RegisterEvent("CHARACTER_POINTS_CHANGED")
zButtonAspect_EnsureConfig() MTH_ZH_AspectAdjust:RegisterEvent("LEARNED_SPELL_IN_TAB")
local saved = zButtonAspect_GetSaved() MTH_ZH_AspectAdjust:SetScript("OnEvent", MTH_ZH_AspectAdjust_OnEvent)
zButtonAspect_Tooltip = CreateFrame("GameTooltip", "MTH_ZH_AspectProbe", nil, "GameTooltipTemplate")
ZSpellButton_CreateChildren(zButtonAspect, "zButtonAspect", ZHUNTER_ASPECT_MAX) if zButtonAspect_Tooltip and zButtonAspect_Tooltip.GetName then
local info = {} local tooltipName = zButtonAspect_Tooltip:GetName()
local infoIndex = 1 if tooltipName then
for i=1, table.getn(ZHunterMod_Aspect_Spells) do zButtonAspect_AuraProbeTextLeft1 = getglobal(tooltipName .. "TextLeft1")
if not tonumber(saved["spells"][i]) then end
info = ZHunterMod_Aspect_Spells end
saved["spells"] = {1, 2, 3, 4, 5, 6, 7} zButtonAspect_SetupSizeAndPosition()
break end
end end
local spellIndex = saved["spells"][i]
if saved["visible"][spellIndex] ~= false then function zButtonAspect_CreateButtons()
info[infoIndex] = ZHunterMod_Aspect_Spells[spellIndex] zButtonAspect_EnsureConfig()
infoIndex = infoIndex + 1 local saved = zButtonAspect_GetSaved()
end
end ZSpellButton_CreateChildren(zButtonAspect, "zButtonAspect", ZHUNTER_ASPECT_MAX)
zButtonAspect.found = ZSpellButton_SetButtons(zButtonAspect, info) local info = {}
zButtonAspect_ApplyRuntimeSettings() local infoIndex = 1
zButtonAspect_EnsureValidParentId() for i=1, table.getn(ZHunterMod_Aspect_Spells) do
end if not tonumber(saved["spells"][i]) then
info = ZHunterMod_Aspect_Spells
function zButtonAspect_SetupSizeAndPosition() saved["spells"] = {1, 2, 3, 4, 5, 6, 7}
zButtonAspect_EnsureConfig() break
local saved = zButtonAspect_GetSaved() end
if saved["enabled"] == false or saved["enabled"] == 0 then local spellIndex = saved["spells"][i]
if zButtonAspect and zButtonAspect.Hide then if saved["visible"][spellIndex] ~= false then
zButtonAspect:Hide() info[infoIndex] = ZHunterMod_Aspect_Spells[spellIndex]
end infoIndex = infoIndex + 1
return end
end end
local displayCount = zButtonAspect.found or ZHUNTER_ASPECT_MAX zButtonAspect.found = ZSpellButton_SetButtons(zButtonAspect, info)
if displayCount < 0 then zButtonAspect_ApplyRuntimeSettings()
displayCount = 0 zButtonAspect_EnsureValidParentId()
end end
ZSpellButton_SetSize(zButtonAspect, saved["parent"]["size"])
ZSpellButton_SetSize(zButtonAspect, saved["children"]["size"], 1) function zButtonAspect_SetupSizeAndPosition()
ZSpellButton_SetExpandDirection(zButtonAspect, saved["firstbutton"]) zButtonAspect_EnsureConfig()
ZSpellButton_ArrangeChildren(zButtonAspect, saved["rows"], local saved = zButtonAspect_GetSaved()
displayCount, saved["horizontal"], if saved["enabled"] == false or saved["enabled"] == 0 then
saved["vertical"]) if MTH_ZH_AspectAdjust and MTH_ZH_AspectAdjust.SetScript then
end MTH_ZH_AspectAdjust:SetScript("OnEvent", nil)
end
function zButtonAspect_Reset() if zButtonAspect and zButtonAspect.Hide then
local currentRoot = zButtonAspect_GetRoot() zButtonAspect:Hide()
currentRoot["zButtonAspect"] = {} end
local saved = zButtonAspect_GetSaved() return
saved["spells"] = {1, 2, 3, 4, 5, 6, 7} end
saved["rows"] = 1 if MTH_ZH_AspectAdjust and MTH_ZH_AspectAdjust.SetScript then
saved["horizontal"] = nil MTH_ZH_AspectAdjust:SetScript("OnEvent", MTH_ZH_AspectAdjust_OnEvent)
saved["vertical"] = nil end
saved["firstbutton"] = "RIGHT" local displayCount = zButtonAspect.found or ZHUNTER_ASPECT_MAX
saved["enabled"] = 1 if displayCount < 0 then
saved["tooltip"] = 1 displayCount = 0
saved["parent"] = {} end
saved["parent"]["size"] = 36 ZSpellButton_SetSize(zButtonAspect, saved["parent"]["size"])
saved["parent"]["hide"] = nil ZSpellButton_SetSize(zButtonAspect, saved["children"]["size"], 1)
saved["parent"]["circle"] = 1 ZSpellButton_SetExpandDirection(zButtonAspect, saved["firstbutton"])
saved["children"] = {} ZSpellButton_ArrangeChildren(zButtonAspect, saved["rows"],
saved["children"]["size"] = 36 displayCount, saved["horizontal"],
saved["children"]["hideonclick"] = 1 saved["vertical"])
saved["visible"] = {1, 1, 1, 1, 1, 1, 1} end
zButtonAspect_EnsureConfig()
end function zButtonAspect_Reset()
local currentRoot = zButtonAspect_GetRoot()
function zButtonAspectAdjustment_OnEvent() currentRoot["zButtonAspect"] = {}
if not zButtonAspect or not zButtonAspect.count then local saved = zButtonAspect_GetSaved()
return saved["spells"] = {1, 2, 3, 4, 5, 6, 7}
end saved["rows"] = 1
if event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" or event == "LEARNED_SPELL_IN_TAB" then saved["horizontal"] = nil
zButtonAspect_CreateButtons() saved["vertical"] = nil
zButtonAspect_SetupSizeAndPosition() saved["firstbutton"] = "RIGHT"
zButtonAspect_EnsureValidParentId() saved["enabled"] = 1
end saved["tooltip"] = 1
if event == "PLAYER_AURAS_CHANGED" or event == "PLAYER_ENTERING_WORLD" saved["parent"] = {}
or event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" or event == "LEARNED_SPELL_IN_TAB" then saved["parent"]["size"] = 36
zButtonAspect_EnsureValidParentId() saved["parent"]["hide"] = nil
if not zButtonAspect1.id then saved["parent"]["circle"] = 1
return saved["children"] = {}
end saved["children"]["size"] = 36
local buttontextures = {} saved["children"]["hideonclick"] = 1
local button saved["visible"] = {1, 1, 1, 1, 1, 1, 1}
for i=1, zButtonAspect.count do zButtonAspect_EnsureConfig()
button = getglobal(zButtonAspect.name..i) end
button.icon = nil
if button.id then function MTH_ZH_AspectAdjust_OnEvent()
buttontextures[GetSpellTexture(button.id, "spell")] = button if not zButtonAspect or not zButtonAspect.count then
end return
end end
local i = 1 if event == "PLAYER_AURAS_CHANGED" then
local texture = GetSpellTexture(zButtonAspect1.id, "spell") local now = GetTime and GetTime() or 0
local buff = UnitBuff("player", i) local minInterval = zButtonAspect_MinAuraInterval
local spellname, buffname if UnitAffectingCombat and UnitAffectingCombat("player") then
zButtonAspect.id = zButtonAspect1.id minInterval = zButtonAspect_MinAuraIntervalCombat
while buff do end
if texture == buff and zButtonAspect2.id then if now > 0 and zButtonAspect_LastAuraUpdateAt > 0 and (now - zButtonAspect_LastAuraUpdateAt) < minInterval then
zButtonAspect.id = zButtonAspect2.id return
end end
if buttontextures[buff] then zButtonAspect_LastAuraUpdateAt = now
zButtonAspect_Tooltip:SetOwner(this, "ANCHOR_NONE") end
zButtonAspect_Tooltip:SetUnitBuff("player", i) if event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" or event == "LEARNED_SPELL_IN_TAB" then
buffname = zButtonAspect_TooltipTextLeft1:GetText() zButtonAspect_CreateButtons()
spellname = GetSpellName(buttontextures[buff].id, "spell") zButtonAspect_SetupSizeAndPosition()
if buffname == spellname then zButtonAspect_EnsureValidParentId()
buttontextures[buff].icon = "Interface\\Icons\\Spell_Nature_WispSplode" end
end if event == "PLAYER_AURAS_CHANGED" or event == "PLAYER_ENTERING_WORLD"
end or event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" or event == "LEARNED_SPELL_IN_TAB" then
i = i + 1 zButtonAspect_EnsureValidParentId()
buff = UnitBuff("player", i) if not zButtonAspect1.id then
end return
ZSpellButton_UpdateButton(zButtonAspect) end
ZSpellButton_UpdateCooldown(zButtonAspect) local button
for i=1, zButtonAspect.count do local isParentTooltipOwned = GameTooltip and GameTooltip.IsOwned and GameTooltip:IsOwned(zButtonAspect)
button = getglobal(zButtonAspect.name..i) local childrenShown = zButtonAspect.children and zButtonAspect.children.IsShown and zButtonAspect.children:IsShown()
if button.id then local needChildIconScan = (event ~= "PLAYER_AURAS_CHANGED") or childrenShown or isParentTooltipOwned
ZSpellButton_UpdateButton(button) local buttontextures = nil
end local hasDuplicateChildTexture = nil
end if needChildIconScan then
if GameTooltip:IsOwned(zButtonAspect) then buttontextures = {}
ZSpellButtonParent_OnEnter(zButtonAspect) local textureSeen = {}
end for i=1, zButtonAspect.count do
end button = getglobal(zButtonAspect.name..i)
end button.icon = nil
if button.id then
function zButtonAspect_KeyBinding(index) local btnTexture = GetSpellTexture(button.id, "spell")
if MTH_ZH_IsModuleEnabled and not MTH_ZH_IsModuleEnabled() then if btnTexture then
return if textureSeen[btnTexture] then
end hasDuplicateChildTexture = true
elseif hasDuplicateChildTexture == nil then
local button hasDuplicateChildTexture = false
if index then end
button = getglobal("zButtonAspect"..index) textureSeen[btnTexture] = 1
else buttontextures[btnTexture] = button
button = zButtonAspect end
end end
if button.id then end
CastSpell(button.id, "spell") end
if zButtonAspect.hideonclick then local i = 1
if type(ZSpellButton_SetChildrenExpanded) == "function" then local texture = GetSpellTexture(zButtonAspect1.id, "spell")
ZSpellButton_SetChildrenExpanded(zButtonAspect, false) local buff = UnitBuff("player", i)
elseif zButtonAspect.children then local spellname, buffname
zButtonAspect.children:Hide() local newParentId = zButtonAspect1.id
end while buff do
end if texture == buff and zButtonAspect2.id then
end newParentId = zButtonAspect2.id
end end
if needChildIconScan and buttontextures[buff] then
SLASH_zButtonAspect1 = "/ZAspect" if hasDuplicateChildTexture then
SlashCmdList["zButtonAspect"] = function(msg) zButtonAspect_Tooltip:SetOwner(this, "ANCHOR_NONE")
if MTH_ZH_HandleDisabledSlash and MTH_ZH_HandleDisabledSlash("Aspect button is disabled while module 'zhunter' is disabled.") then zButtonAspect_Tooltip:SetUnitBuff("player", i)
return if zButtonAspect_AuraProbeTextLeft1 and zButtonAspect_AuraProbeTextLeft1.GetText then
end buffname = zButtonAspect_AuraProbeTextLeft1:GetText()
if msg == "reset" then else
zButtonAspect_Reset() buffname = nil
zButtonAspect:ClearAllPoints() end
zButtonAspect:SetPoint("CENTER", UIParent, "CENTER", -60, 0) spellname = GetSpellName(buttontextures[buff].id, "spell")
elseif msg == "options" then if buffname == spellname then
MTH_OpenOptions("Aspect") buttontextures[buff].icon = "Interface\\Icons\\Spell_Nature_WispSplode"
else end
MTH_ZH_Print("Possible Commands: \"options\", \"reset\"") else
end buttontextures[buff].icon = "Interface\\Icons\\Spell_Nature_WispSplode"
end
end
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
return
end
zButtonAspect_LastAuraTexture = texture
zButtonAspect_LastParentId = newParentId
zButtonAspect.id = newParentId
ZSpellButton_UpdateButton(zButtonAspect)
ZSpellButton_UpdateCooldown(zButtonAspect)
if needChildIconScan then
for i=1, zButtonAspect.count do
button = getglobal(zButtonAspect.name..i)
if button.id then
ZSpellButton_UpdateButton(button)
end
end
end
if isParentTooltipOwned then
ZSpellButtonParent_OnEnter(zButtonAspect)
end
end
end
function zButtonAspect_KeyBinding(index)
if MTH_ZH_IsModuleEnabled and not MTH_ZH_IsModuleEnabled() then
return
end
local button
if index then
button = getglobal("zButtonAspect"..index)
else
button = zButtonAspect
end
if button.id then
CastSpell(button.id, "spell")
if zButtonAspect.hideonclick then
if type(ZSpellButton_SetChildrenExpanded) == "function" then
ZSpellButton_SetChildrenExpanded(zButtonAspect, false)
elseif zButtonAspect.children then
zButtonAspect.children:Hide()
end
end
end
end
SLASH_zButtonAspect1 = "/ZAspect"
SlashCmdList["zButtonAspect"] = function(msg)
if MTH_ZH_HandleDisabledSlash and MTH_ZH_HandleDisabledSlash("Aspect button is disabled while module 'zhunter' is disabled.") then
return
end
if msg == "reset" then
zButtonAspect_Reset()
zButtonAspect:ClearAllPoints()
zButtonAspect:SetPoint("CENTER", UIParent, "CENTER", -60, 0)
elseif msg == "options" then
MTH_OpenOptions("Aspect")
else
MTH_ZH_Print("Possible Commands: \"options\", \"reset\"")
end
end end
+39 -5
View File
@@ -22,6 +22,20 @@ if not root["zButtonCompanions"] then
end end
local ZHUNTER_COMPANIONS_BUTTON_MAX = 80 local ZHUNTER_COMPANIONS_BUTTON_MAX = 80
local zButtonCompanions_LastSpellSignature = nil
local zButtonCompanions_LastRefreshAt = 0
local zButtonCompanions_MinRefreshInterval = 0.50
local function zButtonCompanions_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
local function zButtonCompanions_GetSaved() local function zButtonCompanions_GetSaved()
local currentRoot = zButtonCompanions_GetRoot() local currentRoot = zButtonCompanions_GetRoot()
@@ -79,6 +93,8 @@ local function zButtonCompanions_ApplyRuntimeSettings()
local saved = zButtonCompanions_GetSaved() local saved = zButtonCompanions_GetSaved()
zButtonCompanions.tooltip = saved["tooltip"] and true or false zButtonCompanions.tooltip = saved["tooltip"] and true or false
zButtonCompanions.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false zButtonCompanions.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false
zButtonCompanions.expandonhover = saved["children"] and saved["children"]["expandonhover"] and true or false
zButtonCompanions.fadetimer = saved["children"] and tonumber(saved["children"]["fadetimer"]) or 0
end end
local function zButtonCompanions_NormalizeTabName(value) local function zButtonCompanions_NormalizeTabName(value)
@@ -211,10 +227,10 @@ function zButtonCompanions_OnEvent()
return return
end end
zButtonCompanions_CreateButtons() zButtonCompanions_CreateButtons()
zButtonCompanionsAdjustment = CreateFrame("Frame", "zButtonCompanionsAdjustment") MTH_ZH_CompanionsAdjust = CreateFrame("Frame", "MTH_ZH_CompanionsAdjust")
zButtonCompanionsAdjustment:RegisterEvent("SPELLS_CHANGED") MTH_ZH_CompanionsAdjust:RegisterEvent("SPELLS_CHANGED")
zButtonCompanionsAdjustment:RegisterEvent("PLAYER_ENTERING_WORLD") MTH_ZH_CompanionsAdjust:RegisterEvent("PLAYER_ENTERING_WORLD")
zButtonCompanionsAdjustment:SetScript("OnEvent", zButtonCompanionsAdjustment_OnEvent) MTH_ZH_CompanionsAdjust:SetScript("OnEvent", MTH_ZH_CompanionsAdjust_OnEvent)
zButtonCompanions_SetupSizeAndPosition() zButtonCompanions_SetupSizeAndPosition()
end end
end end
@@ -233,11 +249,17 @@ end
function zButtonCompanions_SetupSizeAndPosition() function zButtonCompanions_SetupSizeAndPosition()
local saved = zButtonCompanions_GetSaved() local saved = zButtonCompanions_GetSaved()
if saved["enabled"] == false or saved["enabled"] == 0 then if saved["enabled"] == false or saved["enabled"] == 0 then
if MTH_ZH_CompanionsAdjust and MTH_ZH_CompanionsAdjust.SetScript then
MTH_ZH_CompanionsAdjust:SetScript("OnEvent", nil)
end
if zButtonCompanions and zButtonCompanions.Hide then if zButtonCompanions and zButtonCompanions.Hide then
zButtonCompanions:Hide() zButtonCompanions:Hide()
end end
return return
end end
if MTH_ZH_CompanionsAdjust and MTH_ZH_CompanionsAdjust.SetScript then
MTH_ZH_CompanionsAdjust:SetScript("OnEvent", MTH_ZH_CompanionsAdjust_OnEvent)
end
local displayCount = zButtonCompanions.found or 0 local displayCount = zButtonCompanions.found or 0
if displayCount < 0 then if displayCount < 0 then
displayCount = 0 displayCount = 0
@@ -271,10 +293,22 @@ function zButtonCompanions_Reset()
zButtonCompanions_EnsureConfig() zButtonCompanions_EnsureConfig()
end end
function zButtonCompanionsAdjustment_OnEvent() function MTH_ZH_CompanionsAdjust_OnEvent()
if not zButtonCompanions then if not zButtonCompanions then
return return
end end
if event == "SPELLS_CHANGED" then
local now = GetTime and GetTime() or 0
if now > 0 and zButtonCompanions_LastRefreshAt > 0 and (now - zButtonCompanions_LastRefreshAt) < zButtonCompanions_MinRefreshInterval then
return
end
local signature = zButtonCompanions_GetSpellSignature(zButtonCompanions_CollectTabSpellIds())
if signature == zButtonCompanions_LastSpellSignature and not GameTooltip:IsOwned(zButtonCompanions) then
return
end
zButtonCompanions_LastSpellSignature = signature
zButtonCompanions_LastRefreshAt = now
end
zButtonCompanions_RefreshSpells() zButtonCompanions_RefreshSpells()
zButtonCompanions_SetupSizeAndPosition() zButtonCompanions_SetupSizeAndPosition()
if GameTooltip:IsOwned(zButtonCompanions) then if GameTooltip:IsOwned(zButtonCompanions) then
+39 -5
View File
@@ -22,6 +22,20 @@ if not root["zButtonMounts"] then
end end
local ZHUNTER_MOUNTS_BUTTON_MAX = 80 local ZHUNTER_MOUNTS_BUTTON_MAX = 80
local zButtonMounts_LastSpellSignature = nil
local zButtonMounts_LastRefreshAt = 0
local zButtonMounts_MinRefreshInterval = 0.50
local function zButtonMounts_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
local function zButtonMounts_GetSaved() local function zButtonMounts_GetSaved()
local currentRoot = zButtonMounts_GetRoot() local currentRoot = zButtonMounts_GetRoot()
@@ -79,6 +93,8 @@ local function zButtonMounts_ApplyRuntimeSettings()
local saved = zButtonMounts_GetSaved() local saved = zButtonMounts_GetSaved()
zButtonMounts.tooltip = saved["tooltip"] and true or false zButtonMounts.tooltip = saved["tooltip"] and true or false
zButtonMounts.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false zButtonMounts.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false
zButtonMounts.expandonhover = saved["children"] and saved["children"]["expandonhover"] and true or false
zButtonMounts.fadetimer = saved["children"] and tonumber(saved["children"]["fadetimer"]) or 0
end end
local function zButtonMounts_NormalizeTabName(value) local function zButtonMounts_NormalizeTabName(value)
@@ -211,10 +227,10 @@ function zButtonMounts_OnEvent()
return return
end end
zButtonMounts_CreateButtons() zButtonMounts_CreateButtons()
zButtonMountsAdjustment = CreateFrame("Frame", "zButtonMountsAdjustment") MTH_ZH_MountsAdjust = CreateFrame("Frame", "MTH_ZH_MountsAdjust")
zButtonMountsAdjustment:RegisterEvent("SPELLS_CHANGED") MTH_ZH_MountsAdjust:RegisterEvent("SPELLS_CHANGED")
zButtonMountsAdjustment:RegisterEvent("PLAYER_ENTERING_WORLD") MTH_ZH_MountsAdjust:RegisterEvent("PLAYER_ENTERING_WORLD")
zButtonMountsAdjustment:SetScript("OnEvent", zButtonMountsAdjustment_OnEvent) MTH_ZH_MountsAdjust:SetScript("OnEvent", MTH_ZH_MountsAdjust_OnEvent)
zButtonMounts_SetupSizeAndPosition() zButtonMounts_SetupSizeAndPosition()
end end
end end
@@ -233,11 +249,17 @@ end
function zButtonMounts_SetupSizeAndPosition() function zButtonMounts_SetupSizeAndPosition()
local saved = zButtonMounts_GetSaved() local saved = zButtonMounts_GetSaved()
if saved["enabled"] == false or saved["enabled"] == 0 then if saved["enabled"] == false or saved["enabled"] == 0 then
if MTH_ZH_MountsAdjust and MTH_ZH_MountsAdjust.SetScript then
MTH_ZH_MountsAdjust:SetScript("OnEvent", nil)
end
if zButtonMounts and zButtonMounts.Hide then if zButtonMounts and zButtonMounts.Hide then
zButtonMounts:Hide() zButtonMounts:Hide()
end end
return return
end end
if MTH_ZH_MountsAdjust and MTH_ZH_MountsAdjust.SetScript then
MTH_ZH_MountsAdjust:SetScript("OnEvent", MTH_ZH_MountsAdjust_OnEvent)
end
local displayCount = zButtonMounts.found or 0 local displayCount = zButtonMounts.found or 0
if displayCount < 0 then if displayCount < 0 then
displayCount = 0 displayCount = 0
@@ -271,10 +293,22 @@ function zButtonMounts_Reset()
zButtonMounts_EnsureConfig() zButtonMounts_EnsureConfig()
end end
function zButtonMountsAdjustment_OnEvent() function MTH_ZH_MountsAdjust_OnEvent()
if not zButtonMounts then if not zButtonMounts then
return return
end end
if event == "SPELLS_CHANGED" then
local now = GetTime and GetTime() or 0
if now > 0 and zButtonMounts_LastRefreshAt > 0 and (now - zButtonMounts_LastRefreshAt) < zButtonMounts_MinRefreshInterval then
return
end
local signature = zButtonMounts_GetSpellSignature(zButtonMounts_CollectTabSpellIds())
if signature == zButtonMounts_LastSpellSignature and not GameTooltip:IsOwned(zButtonMounts) then
return
end
zButtonMounts_LastSpellSignature = signature
zButtonMounts_LastRefreshAt = now
end
zButtonMounts_RefreshSpells() zButtonMounts_RefreshSpells()
zButtonMounts_SetupSizeAndPosition() zButtonMounts_SetupSizeAndPosition()
if GameTooltip:IsOwned(zButtonMounts) then if GameTooltip:IsOwned(zButtonMounts) then
File diff suppressed because it is too large Load Diff
+55 -8
View File
@@ -27,6 +27,11 @@ ZHunterMod_Ranged_Weapons = ZHunterMod_Ranged_Weapons or {}
local ZHUNTER_RANGED_MAX_COUNT = 80 local ZHUNTER_RANGED_MAX_COUNT = 80
local zButtonRanged_Cache = {} local zButtonRanged_Cache = {}
local zButtonRanged_TooltipWarmed = false local zButtonRanged_TooltipWarmed = false
local zButtonRanged_LastRefreshAt = 0
local zButtonRanged_MinBagRefreshInterval = 0.75
local zButtonRanged_IdleBagRefreshInterval = 3.00
local zButtonRanged_BagDirty = false
local zButtonRanged_RefreshButtonsFromState
local function zButtonRanged_GetKnownItemSpeed(itemId) local function zButtonRanged_GetKnownItemSpeed(itemId)
local idNum = tonumber(itemId) local idNum = tonumber(itemId)
@@ -227,6 +232,8 @@ local function zButtonRanged_ApplyRuntimeSettings()
local saved = zButtonRanged_GetSaved() local saved = zButtonRanged_GetSaved()
zButtonRanged.tooltip = saved["tooltip"] and true or false zButtonRanged.tooltip = saved["tooltip"] and true or false
zButtonRanged.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false zButtonRanged.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false
zButtonRanged.expandonhover = saved["children"] and saved["children"]["expandonhover"] and true or false
zButtonRanged.fadetimer = saved["children"] and tonumber(saved["children"]["fadetimer"]) or 0
end end
local function zButtonRanged_UpdateDurabilityText(button) local function zButtonRanged_UpdateDurabilityText(button)
@@ -437,6 +444,15 @@ local function zButtonRanged_OnEnter(button)
if not button then if not button then
return return
end end
if zButtonRanged_BagDirty then
local previousFound = tonumber(zButtonRanged and zButtonRanged.found) or 0
zButtonRanged_RefreshButtonsFromState()
if (tonumber(zButtonRanged and zButtonRanged.found) or 0) ~= previousFound then
zButtonRanged_SetupSizeAndPosition()
else
zButtonRanged_UpdateButton(zButtonRanged)
end
end
if not (zButtonRanged and zButtonRanged.tooltip) then if not (zButtonRanged and zButtonRanged.tooltip) then
return return
end end
@@ -503,7 +519,7 @@ local function zButtonRanged_BeforeClick(button)
return true return true
end end
local function zButtonRanged_RefreshButtonsFromState() zButtonRanged_RefreshButtonsFromState = function()
if not zButtonRanged then if not zButtonRanged then
return return
end end
@@ -525,6 +541,7 @@ local function zButtonRanged_RefreshButtonsFromState()
end end
zButtonRanged.found = ZSpellButton_SetButtons(zButtonRanged, info) zButtonRanged.found = ZSpellButton_SetButtons(zButtonRanged, info)
zButtonRanged_BagDirty = false
zButtonRanged_ApplyRuntimeSettings() zButtonRanged_ApplyRuntimeSettings()
end end
@@ -587,11 +604,11 @@ function zButtonRanged_OnEvent()
zButtonRanged.customUpdateButton = zButtonRanged_UpdateButton zButtonRanged.customUpdateButton = zButtonRanged_UpdateButton
zButtonRanged.beforeclick = zButtonRanged_BeforeClick zButtonRanged.beforeclick = zButtonRanged_BeforeClick
zButtonRanged_CreateButtons() zButtonRanged_CreateButtons()
zButtonRangedAdjustment = CreateFrame("Frame", "zButtonRangedAdjustment") MTH_ZH_RangedAdjust = CreateFrame("Frame", "MTH_ZH_RangedAdjust")
zButtonRangedAdjustment:RegisterEvent("UNIT_INVENTORY_CHANGED") MTH_ZH_RangedAdjust:RegisterEvent("UNIT_INVENTORY_CHANGED")
zButtonRangedAdjustment:RegisterEvent("BAG_UPDATE") MTH_ZH_RangedAdjust:RegisterEvent("BAG_UPDATE")
zButtonRangedAdjustment:RegisterEvent("PLAYER_ENTERING_WORLD") MTH_ZH_RangedAdjust:RegisterEvent("PLAYER_ENTERING_WORLD")
zButtonRangedAdjustment:SetScript("OnEvent", zButtonRangedAdjustment_OnEvent) MTH_ZH_RangedAdjust:SetScript("OnEvent", MTH_ZH_RangedAdjust_OnEvent)
zButtonRanged_SetupSizeAndPosition() zButtonRanged_SetupSizeAndPosition()
end end
end end
@@ -620,11 +637,17 @@ end
function zButtonRanged_SetupSizeAndPosition() function zButtonRanged_SetupSizeAndPosition()
local saved = zButtonRanged_GetSaved() local saved = zButtonRanged_GetSaved()
if saved["enabled"] == false or saved["enabled"] == 0 then if saved["enabled"] == false or saved["enabled"] == 0 then
if MTH_ZH_RangedAdjust and MTH_ZH_RangedAdjust.SetScript then
MTH_ZH_RangedAdjust:SetScript("OnEvent", nil)
end
if zButtonRanged and zButtonRanged.Hide then if zButtonRanged and zButtonRanged.Hide then
zButtonRanged:Hide() zButtonRanged:Hide()
end end
return return
end end
if MTH_ZH_RangedAdjust and MTH_ZH_RangedAdjust.SetScript then
MTH_ZH_RangedAdjust:SetScript("OnEvent", MTH_ZH_RangedAdjust_OnEvent)
end
local displayCount = zButtonRanged.found or 0 local displayCount = zButtonRanged.found or 0
if displayCount < 0 then if displayCount < 0 then
displayCount = 0 displayCount = 0
@@ -658,15 +681,39 @@ function zButtonRanged_Reset()
zButtonRanged_EnsureConfig() zButtonRanged_EnsureConfig()
end end
function zButtonRangedAdjustment_OnEvent() function MTH_ZH_RangedAdjust_OnEvent()
if not zButtonRanged then if not zButtonRanged then
return return
end end
if event == "UNIT_INVENTORY_CHANGED" and arg1 and arg1 ~= "player" then if event == "UNIT_INVENTORY_CHANGED" and arg1 and arg1 ~= "player" then
return return
end end
if event == "BAG_UPDATE" then
local now = GetTime and GetTime() or 0
local isInspecting = false
if zButtonRanged.children and zButtonRanged.children.IsShown and zButtonRanged.children:IsShown() then
isInspecting = true
elseif GameTooltip and GameTooltip.IsOwned and GameTooltip:IsOwned(zButtonRanged) then
isInspecting = true
end
if not isInspecting then
zButtonRanged_BagDirty = true
return
end
local minInterval = isInspecting and zButtonRanged_MinBagRefreshInterval or zButtonRanged_IdleBagRefreshInterval
if now > 0 and zButtonRanged_LastRefreshAt > 0 and (now - zButtonRanged_LastRefreshAt) < minInterval then
return
end
end
zButtonRanged_LastRefreshAt = GetTime and GetTime() or 0
local previousFound = tonumber(zButtonRanged.found) or 0
zButtonRanged_RefreshButtonsFromState() zButtonRanged_RefreshButtonsFromState()
zButtonRanged_SetupSizeAndPosition() if (tonumber(zButtonRanged.found) or 0) ~= previousFound then
zButtonRanged_SetupSizeAndPosition()
else
zButtonRanged_UpdateButton(zButtonRanged)
end
if event == "PLAYER_ENTERING_WORLD" then if event == "PLAYER_ENTERING_WORLD" then
zButtonRanged_PrewarmTooltipOnce() zButtonRanged_PrewarmTooltipOnce()
end end
+39 -5
View File
@@ -22,6 +22,20 @@ if not root["zButtonToys"] then
end end
local ZHUNTER_TOYS_BUTTON_MAX = 80 local ZHUNTER_TOYS_BUTTON_MAX = 80
local zButtonToys_LastSpellSignature = nil
local zButtonToys_LastRefreshAt = 0
local zButtonToys_MinRefreshInterval = 0.50
local function zButtonToys_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
local function zButtonToys_GetSaved() local function zButtonToys_GetSaved()
local currentRoot = zButtonToys_GetRoot() local currentRoot = zButtonToys_GetRoot()
@@ -79,6 +93,8 @@ local function zButtonToys_ApplyRuntimeSettings()
local saved = zButtonToys_GetSaved() local saved = zButtonToys_GetSaved()
zButtonToys.tooltip = saved["tooltip"] and true or false zButtonToys.tooltip = saved["tooltip"] and true or false
zButtonToys.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false zButtonToys.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false
zButtonToys.expandonhover = saved["children"] and saved["children"]["expandonhover"] and true or false
zButtonToys.fadetimer = saved["children"] and tonumber(saved["children"]["fadetimer"]) or 0
end end
local function zButtonToys_NormalizeTabName(value) local function zButtonToys_NormalizeTabName(value)
@@ -211,10 +227,10 @@ function zButtonToys_OnEvent()
return return
end end
zButtonToys_CreateButtons() zButtonToys_CreateButtons()
zButtonToysAdjustment = CreateFrame("Frame", "zButtonToysAdjustment") MTH_ZH_ToysAdjust = CreateFrame("Frame", "MTH_ZH_ToysAdjust")
zButtonToysAdjustment:RegisterEvent("SPELLS_CHANGED") MTH_ZH_ToysAdjust:RegisterEvent("SPELLS_CHANGED")
zButtonToysAdjustment:RegisterEvent("PLAYER_ENTERING_WORLD") MTH_ZH_ToysAdjust:RegisterEvent("PLAYER_ENTERING_WORLD")
zButtonToysAdjustment:SetScript("OnEvent", zButtonToysAdjustment_OnEvent) MTH_ZH_ToysAdjust:SetScript("OnEvent", MTH_ZH_ToysAdjust_OnEvent)
zButtonToys_SetupSizeAndPosition() zButtonToys_SetupSizeAndPosition()
end end
end end
@@ -233,11 +249,17 @@ end
function zButtonToys_SetupSizeAndPosition() function zButtonToys_SetupSizeAndPosition()
local saved = zButtonToys_GetSaved() local saved = zButtonToys_GetSaved()
if saved["enabled"] == false or saved["enabled"] == 0 then if saved["enabled"] == false or saved["enabled"] == 0 then
if MTH_ZH_ToysAdjust and MTH_ZH_ToysAdjust.SetScript then
MTH_ZH_ToysAdjust:SetScript("OnEvent", nil)
end
if zButtonToys and zButtonToys.Hide then if zButtonToys and zButtonToys.Hide then
zButtonToys:Hide() zButtonToys:Hide()
end end
return return
end end
if MTH_ZH_ToysAdjust and MTH_ZH_ToysAdjust.SetScript then
MTH_ZH_ToysAdjust:SetScript("OnEvent", MTH_ZH_ToysAdjust_OnEvent)
end
local displayCount = zButtonToys.found or 0 local displayCount = zButtonToys.found or 0
if displayCount < 0 then if displayCount < 0 then
displayCount = 0 displayCount = 0
@@ -271,10 +293,22 @@ function zButtonToys_Reset()
zButtonToys_EnsureConfig() zButtonToys_EnsureConfig()
end end
function zButtonToysAdjustment_OnEvent() function MTH_ZH_ToysAdjust_OnEvent()
if not zButtonToys then if not zButtonToys then
return return
end end
if event == "SPELLS_CHANGED" then
local now = GetTime and GetTime() or 0
if now > 0 and zButtonToys_LastRefreshAt > 0 and (now - zButtonToys_LastRefreshAt) < zButtonToys_MinRefreshInterval then
return
end
local signature = zButtonToys_GetSpellSignature(zButtonToys_CollectTabSpellIds())
if signature == zButtonToys_LastSpellSignature and not GameTooltip:IsOwned(zButtonToys) then
return
end
zButtonToys_LastSpellSignature = signature
zButtonToys_LastRefreshAt = now
end
zButtonToys_RefreshSpells() zButtonToys_RefreshSpells()
zButtonToys_SetupSizeAndPosition() zButtonToys_SetupSizeAndPosition()
if GameTooltip:IsOwned(zButtonToys) then if GameTooltip:IsOwned(zButtonToys) then
+411 -260
View File
@@ -1,261 +1,412 @@
local function zButtonTrack_GetRoot() local function zButtonTrack_GetRoot()
return MTH_ZH_GetSavedRoot() return MTH_ZH_GetSavedRoot()
end end
local root = zButtonTrack_GetRoot() local root = zButtonTrack_GetRoot()
if not root["zButtonTrack"] then if not root["zButtonTrack"] then
root["zButtonTrack"] = {} root["zButtonTrack"] = {}
root["zButtonTrack"]["spells"] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} root["zButtonTrack"]["spells"] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
root["zButtonTrack"]["rows"] = 1 root["zButtonTrack"]["rows"] = 1
root["zButtonTrack"]["horizontal"] = nil root["zButtonTrack"]["horizontal"] = nil
root["zButtonTrack"]["vertical"] = nil root["zButtonTrack"]["vertical"] = nil
root["zButtonTrack"]["firstbutton"] = "RIGHT" root["zButtonTrack"]["firstbutton"] = "RIGHT"
root["zButtonTrack"]["enabled"] = 1 root["zButtonTrack"]["enabled"] = 1
root["zButtonTrack"]["tooltip"] = 1 root["zButtonTrack"]["tooltip"] = 1
root["zButtonTrack"]["parent"] = {} root["zButtonTrack"]["parent"] = {}
root["zButtonTrack"]["parent"]["size"] = 36 root["zButtonTrack"]["parent"]["size"] = 36
root["zButtonTrack"]["parent"]["hide"] = nil root["zButtonTrack"]["parent"]["hide"] = nil
root["zButtonTrack"]["parent"]["circle"] = 1 root["zButtonTrack"]["parent"]["circle"] = 1
root["zButtonTrack"]["children"] = {} root["zButtonTrack"]["children"] = {}
root["zButtonTrack"]["children"]["size"] = 36 root["zButtonTrack"]["children"]["size"] = 36
root["zButtonTrack"]["children"]["hideonclick"] = 1 root["zButtonTrack"]["children"]["hideonclick"] = 1
end end
ZHunterMod_Track_Spells = { ZHunterMod_Track_Spells = {
ZHUNTER_TRACK_HIDDEN, ZHUNTER_TRACK_HIDDEN,
ZHUNTER_TRACK_HUMANOIDS, ZHUNTER_TRACK_HUMANOIDS,
ZHUNTER_TRACK_UNDEAD, ZHUNTER_TRACK_UNDEAD,
ZHUNTER_TRACK_BEASTS, ZHUNTER_TRACK_BEASTS,
ZHUNTER_TRACK_DEMONS, ZHUNTER_TRACK_DEMONS,
ZHUNTER_TRACK_ELEMENTALS, ZHUNTER_TRACK_ELEMENTALS,
ZHUNTER_TRACK_DRAGONKIN, ZHUNTER_TRACK_DRAGONKIN,
ZHUNTER_TRACK_GIANTS, ZHUNTER_TRACK_GIANTS,
ZHUNTER_TRACK_MINERALS, ZHUNTER_TRACK_MINERALS,
ZHUNTER_TRACK_HERBS, ZHUNTER_TRACK_HERBS,
ZHUNTER_TRACK_TREASURE ZHUNTER_TRACK_TREASURE
} }
local ZHUNTER_TRACK_MAX = table.getn(ZHunterMod_Track_Spells) local ZHUNTER_TRACK_MAX = table.getn(ZHunterMod_Track_Spells)
local zButtonTrack_LastTrackingTexture = nil
local function zButtonTrack_GetSaved() local zButtonTrack_SyncActiveChild
local currentRoot = zButtonTrack_GetRoot() local zButtonTrack_GetSaved
if not currentRoot["zButtonTrack"] then
currentRoot["zButtonTrack"] = {} local function zButtonTrack_NormalizeTexture(texture)
end if not texture then
return currentRoot["zButtonTrack"] return ""
end end
local value = string.lower(tostring(texture))
local function zButtonTrack_EnsureConfig() value = string.gsub(value, "\\", "/")
local saved = zButtonTrack_GetSaved() local _, _, basename = string.find(value, "([^/]+)$")
saved["count"] = nil return basename or value
if saved["rows"] == nil then end
saved["rows"] = 1
end local function zButtonTrack_FindSpellIdByTrackingTexture(trackingTexture)
if saved["firstbutton"] == nil then if not trackingTexture or not zButtonTrack or not zButtonTrack.count then
saved["firstbutton"] = "RIGHT" return nil
end end
if saved["enabled"] == nil then local wanted = zButtonTrack_NormalizeTexture(trackingTexture)
saved["enabled"] = 1 for i = 1, zButtonTrack.count do
end local child = getglobal("zButtonTrack" .. i)
if saved["tooltip"] == nil then if child and child.id then
saved["tooltip"] = 1 local spellTexture = GetSpellTexture and GetSpellTexture(child.id, "spell") or nil
end if zButtonTrack_NormalizeTexture(spellTexture) == wanted then
if not saved["parent"] then return child.id
saved["parent"] = {} end
end if child.icon and zButtonTrack_NormalizeTexture(child.icon) == wanted then
if saved["parent"]["size"] == nil then return child.id
saved["parent"]["size"] = 36 end
end if child.icontexture and child.icontexture.GetTexture then
if saved["parent"]["circle"] == nil then local childTexture = child.icontexture:GetTexture()
saved["parent"]["circle"] = 1 if zButtonTrack_NormalizeTexture(childTexture) == wanted then
end return child.id
if not saved["children"] then end
saved["children"] = {} end
end end
if saved["children"]["size"] == nil then end
saved["children"]["size"] = 36 return nil
end end
if saved["children"]["hideonclick"] == nil then
saved["children"]["hideonclick"] = 1 local function zButtonTrack_FindSpellIdByTrackingName(trackingName)
end if not trackingName or trackingName == "" or not zButtonTrack or not zButtonTrack.count then
if not saved["spells"] then return nil
saved["spells"] = {} end
end for i = 1, zButtonTrack.count do
if not saved["visible"] then local child = getglobal("zButtonTrack" .. i)
saved["visible"] = {} if child and child.id then
end local spellName = GetSpellName and GetSpellName(child.id, "spell") or nil
for i = 1, ZHUNTER_TRACK_MAX do if spellName == trackingName then
if not tonumber(saved["spells"][i]) then return child.id
saved["spells"][i] = i end
end end
if saved["visible"][i] == nil then end
saved["visible"][i] = 1 return nil
end end
end
end local function zButtonTrack_GetActiveTrackingSpellId()
local activeName = nil
local function zButtonTrack_ApplyRuntimeSettings() local activeTexture = nil
if not zButtonTrack then if GetNumTrackingTypes and GetTrackingInfo then
return local numTracking = GetNumTrackingTypes() or 0
end for i = 1, numTracking do
local saved = zButtonTrack_GetSaved() local name, texture, active = GetTrackingInfo(i)
zButtonTrack.tooltip = saved["tooltip"] and true or false if active then
zButtonTrack.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false activeName = name
end activeTexture = texture
break
end
function zButtonTrack_OnLoad() end
this:RegisterEvent("VARIABLES_LOADED") end
end local byName = zButtonTrack_FindSpellIdByTrackingName(activeName)
if byName then
function zButtonTrack_OnEvent() return byName, activeTexture
if event == "VARIABLES_LOADED" then end
if not zButtonTrack then if activeTexture then
return return zButtonTrack_FindSpellIdByTrackingTexture(activeTexture), activeTexture
end end
if UnitClass("player") ~= ZHUNTER_HUNTER then local buff = GetTrackingTexture and GetTrackingTexture() or nil
zButtonTrack:UnregisterAllEvents() return zButtonTrack_FindSpellIdByTrackingTexture(buff), buff
zButtonTrack:Hide() end
return
end local function zButtonTrack_AfterClick(button)
zButtonTrack_CreateButtons() if not zButtonTrack then
zButtonTrackAdjustment = CreateFrame("Frame", "zButtonTrackAdjustment") return
zButtonTrackAdjustment:RegisterEvent("PLAYER_AURAS_CHANGED") end
zButtonTrackAdjustment:RegisterEvent("PLAYER_ENTERING_WORLD") if button and button.id then
zButtonTrackAdjustment:RegisterEvent("SPELLS_CHANGED") zButtonTrack.id = button.id
zButtonTrackAdjustment:RegisterEvent("CHARACTER_POINTS_CHANGED") ZSpellButton_UpdateButton(zButtonTrack)
zButtonTrackAdjustment:SetScript("OnEvent", zButtonTrackAdjustment_OnEvent) ZSpellButton_UpdateCooldown(zButtonTrack)
zButtonTrack_SetupSizeAndPosition() zButtonTrack_SyncActiveChild(button.id)
end if GetSpellTexture then
end zButtonTrack_LastTrackingTexture = GetSpellTexture(button.id, "spell") or zButtonTrack_LastTrackingTexture
end
function zButtonTrack_CreateButtons() local isOwned = GameTooltip and GameTooltip.IsOwned and GameTooltip:IsOwned(zButtonTrack)
zButtonTrack_EnsureConfig() if isOwned then
local saved = zButtonTrack_GetSaved() ZSpellButtonParent_OnEnter(zButtonTrack)
end
ZSpellButton_CreateChildren(zButtonTrack, "zButtonTrack", ZHUNTER_TRACK_MAX) end
local info = {} end
local infoIndex = 1
for i=1, table.getn(ZHunterMod_Track_Spells) do zButtonTrack_SyncActiveChild = function(activeId)
if not tonumber(saved["spells"][i]) then if not zButtonTrack or not zButtonTrack.count then
info = ZHunterMod_Track_Spells return
saved["spells"] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} end
break for i = 1, zButtonTrack.count do
end local child = getglobal("zButtonTrack" .. i)
local spellIndex = saved["spells"][i] if child and child.SetChecked then
if saved["visible"][spellIndex] ~= false then child:SetChecked((activeId and child.id == activeId) and 1 or 0)
info[infoIndex] = ZHunterMod_Track_Spells[spellIndex] end
infoIndex = infoIndex + 1 end
end if zButtonTrack.SetChecked then
end zButtonTrack:SetChecked(0)
zButtonTrack.found = ZSpellButton_SetButtons(zButtonTrack, info) end
zButtonTrack_ApplyRuntimeSettings() end
end
local function zButtonTrack_RefreshTrackingState()
function zButtonTrack_SetupSizeAndPosition() if not zButtonTrack or not zButtonTrack.count then
zButtonTrack_EnsureConfig() return
local saved = zButtonTrack_GetSaved() end
if saved["enabled"] == false or saved["enabled"] == 0 then local newId, trackingTexture = zButtonTrack_GetActiveTrackingSpellId()
if zButtonTrack and zButtonTrack.Hide then local buff = trackingTexture or (GetTrackingTexture and GetTrackingTexture() or nil)
zButtonTrack:Hide() if not newId and not buff then
end if zButtonTrack.id then
return zButtonTrack_SyncActiveChild(zButtonTrack.id)
end else
local displayCount = zButtonTrack.found or ZHUNTER_TRACK_MAX zButtonTrack_LastTrackingTexture = nil
if displayCount < 0 then zButtonTrack_SyncActiveChild(nil)
displayCount = 0 end
end return
ZSpellButton_SetSize(zButtonTrack, saved["parent"]["size"]) end
ZSpellButton_SetSize(zButtonTrack, saved["children"]["size"], 1) if not newId then
ZSpellButton_SetExpandDirection(zButtonTrack, saved["firstbutton"]) newId = zButtonTrack.id or nil
ZSpellButton_ArrangeChildren(zButtonTrack, saved["rows"], end
displayCount, saved["horizontal"], if not newId then
saved["vertical"]) return
end end
if zButtonTrack_NormalizeTexture(zButtonTrack_LastTrackingTexture) == zButtonTrack_NormalizeTexture(buff) and zButtonTrack.id == newId then
function zButtonTrack_Reset() zButtonTrack_SyncActiveChild(newId)
local currentRoot = zButtonTrack_GetRoot() return
currentRoot["zButtonTrack"] = {} end
local saved = zButtonTrack_GetSaved()
saved["spells"] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} local isOwned = GameTooltip and GameTooltip.IsOwned and GameTooltip:IsOwned(zButtonTrack)
saved["rows"] = 1 zButtonTrack_LastTrackingTexture = buff
saved["horizontal"] = nil zButtonTrack.id = newId
saved["vertical"] = nil ZSpellButton_UpdateButton(zButtonTrack)
saved["firstbutton"] = "RIGHT" ZSpellButton_UpdateCooldown(zButtonTrack)
saved["enabled"] = 1 zButtonTrack_SyncActiveChild(newId)
saved["tooltip"] = 1 if isOwned then
saved["parent"] = {} ZSpellButtonParent_OnEnter(zButtonTrack)
saved["parent"]["size"] = 36 end
saved["parent"]["hide"] = nil end
saved["parent"]["circle"] = 1
saved["children"] = {} zButtonTrack_GetSaved = function()
saved["children"]["size"] = 36 local currentRoot = zButtonTrack_GetRoot()
saved["children"]["hideonclick"] = 1 if not currentRoot["zButtonTrack"] then
saved["visible"] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} currentRoot["zButtonTrack"] = {}
zButtonTrack_EnsureConfig() end
end return currentRoot["zButtonTrack"]
end
function zButtonTrackAdjustment_OnEvent()
if not zButtonTrack or not zButtonTrack.count then local function zButtonTrack_EnsureConfig()
return local saved = zButtonTrack_GetSaved()
end saved["count"] = nil
if event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" then if saved["rows"] == nil then
zButtonTrack_CreateButtons() saved["rows"] = 1
zButtonTrack_SetupSizeAndPosition() end
end if saved["firstbutton"] == nil then
if event == "PLAYER_AURAS_CHANGED" or event == "PLAYER_ENTERING_WORLD" saved["firstbutton"] = "RIGHT"
or event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" then end
local i = 1 if saved["enabled"] == nil then
local texture = zButtonTrack1IconTexture:GetTexture() saved["enabled"] = 1
local buff = GetTrackingTexture() end
if texture == buff and zButtonTrack2.id then if saved["tooltip"] == nil then
zButtonTrack.id = zButtonTrack2.id saved["tooltip"] = 1
else end
zButtonTrack.id = zButtonTrack1.id if not saved["parent"] then
end saved["parent"] = {}
ZSpellButton_UpdateButton(zButtonTrack) end
ZSpellButton_UpdateCooldown(zButtonTrack) if saved["parent"]["size"] == nil then
if GameTooltip:IsOwned(zButtonTrack) then saved["parent"]["size"] = 36
ZSpellButtonParent_OnEnter(zButtonTrack) end
end if saved["parent"]["circle"] == nil then
end saved["parent"]["circle"] = 1
end end
if not saved["children"] then
function zButtonTrack_KeyBinding(index) saved["children"] = {}
if MTH_ZH_IsModuleEnabled and not MTH_ZH_IsModuleEnabled() then end
return if saved["children"]["size"] == nil then
end saved["children"]["size"] = 36
end
local button if saved["children"]["hideonclick"] == nil then
if index then saved["children"]["hideonclick"] = 1
button = getglobal("zButtonTrack"..index) end
else if not saved["spells"] then
button = zButtonTrack saved["spells"] = {}
end end
if button.id then if not saved["visible"] then
CastSpell(button.id, "spell") saved["visible"] = {}
if zButtonTrack.hideonclick then end
if type(ZSpellButton_SetChildrenExpanded) == "function" then for i = 1, ZHUNTER_TRACK_MAX do
ZSpellButton_SetChildrenExpanded(zButtonTrack, false) if not tonumber(saved["spells"][i]) then
elseif zButtonTrack.children then saved["spells"][i] = i
zButtonTrack.children:Hide() end
end if saved["visible"][i] == nil then
end saved["visible"][i] = 1
end end
end end
end
SLASH_zButtonTrack1 = "/ZTrack"
SlashCmdList["zButtonTrack"] = function(msg) local function zButtonTrack_ApplyRuntimeSettings()
if MTH_ZH_HandleDisabledSlash and MTH_ZH_HandleDisabledSlash("Track button is disabled while module 'zhunter' is disabled.") then if not zButtonTrack then
return return
end end
if msg == "reset" then local saved = zButtonTrack_GetSaved()
zButtonTrack_Reset() zButtonTrack.tooltip = saved["tooltip"] and true or false
zButtonTrack:ClearAllPoints() zButtonTrack.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false
zButtonTrack:SetPoint("CENTER", UIParent, "CENTER", 0, 0) zButtonTrack.expandonhover = saved["children"] and saved["children"]["expandonhover"] and true or false
elseif msg == "options" then zButtonTrack.fadetimer = saved["children"] and tonumber(saved["children"]["fadetimer"]) or 0
MTH_OpenOptions("Track") end
else
MTH_ZH_Print("Possible Commands: \"options\", \"reset\"")
end function zButtonTrack_OnLoad()
this:RegisterEvent("VARIABLES_LOADED")
end
function zButtonTrack_OnEvent()
if event == "VARIABLES_LOADED" then
if not zButtonTrack then
return
end
if UnitClass("player") ~= ZHUNTER_HUNTER then
zButtonTrack:UnregisterAllEvents()
zButtonTrack:Hide()
return
end
zButtonTrack_CreateButtons()
zButtonTrack.afterclick = zButtonTrack_AfterClick
MTH_ZH_TrackAdjust = CreateFrame("Frame", "MTH_ZH_TrackAdjust")
MTH_ZH_TrackAdjust:RegisterEvent("MINIMAP_UPDATE_TRACKING")
MTH_ZH_TrackAdjust:RegisterEvent("PLAYER_ENTERING_WORLD")
MTH_ZH_TrackAdjust:RegisterEvent("SPELLS_CHANGED")
MTH_ZH_TrackAdjust:RegisterEvent("CHARACTER_POINTS_CHANGED")
MTH_ZH_TrackAdjust:RegisterEvent("LEARNED_SPELL_IN_TAB")
MTH_ZH_TrackAdjust:SetScript("OnEvent", MTH_ZH_TrackAdjust_OnEvent)
zButtonTrack_SetupSizeAndPosition()
end
end
function zButtonTrack_CreateButtons()
zButtonTrack_EnsureConfig()
local saved = zButtonTrack_GetSaved()
ZSpellButton_CreateChildren(zButtonTrack, "zButtonTrack", ZHUNTER_TRACK_MAX)
local info = {}
local infoIndex = 1
for i=1, table.getn(ZHunterMod_Track_Spells) do
if not tonumber(saved["spells"][i]) then
info = ZHunterMod_Track_Spells
saved["spells"] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
break
end
local spellIndex = saved["spells"][i]
if saved["visible"][spellIndex] ~= false then
info[infoIndex] = ZHunterMod_Track_Spells[spellIndex]
infoIndex = infoIndex + 1
end
end
zButtonTrack.found = ZSpellButton_SetButtons(zButtonTrack, info)
zButtonTrack_ApplyRuntimeSettings()
end
function zButtonTrack_SetupSizeAndPosition()
zButtonTrack_EnsureConfig()
local saved = zButtonTrack_GetSaved()
if saved["enabled"] == false or saved["enabled"] == 0 then
if MTH_ZH_TrackAdjust and MTH_ZH_TrackAdjust.SetScript then
MTH_ZH_TrackAdjust:SetScript("OnEvent", nil)
end
if zButtonTrack and zButtonTrack.Hide then
zButtonTrack:Hide()
end
return
end
if MTH_ZH_TrackAdjust and MTH_ZH_TrackAdjust.SetScript then
MTH_ZH_TrackAdjust:SetScript("OnEvent", MTH_ZH_TrackAdjust_OnEvent)
end
local displayCount = zButtonTrack.found or ZHUNTER_TRACK_MAX
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"])
zButtonTrack_RefreshTrackingState()
end
function zButtonTrack_Reset()
local currentRoot = zButtonTrack_GetRoot()
currentRoot["zButtonTrack"] = {}
local saved = zButtonTrack_GetSaved()
saved["spells"] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
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
saved["visible"] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
zButtonTrack_EnsureConfig()
end
function MTH_ZH_TrackAdjust_OnEvent()
if not zButtonTrack or not zButtonTrack.count then
return
end
if event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" or event == "LEARNED_SPELL_IN_TAB" then
zButtonTrack_CreateButtons()
zButtonTrack_SetupSizeAndPosition()
end
if event == "MINIMAP_UPDATE_TRACKING" or event == "PLAYER_ENTERING_WORLD"
or event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" or event == "LEARNED_SPELL_IN_TAB" then
zButtonTrack_RefreshTrackingState()
end
end
function zButtonTrack_KeyBinding(index)
if MTH_ZH_IsModuleEnabled and not MTH_ZH_IsModuleEnabled() then
return
end
local button
if index then
button = getglobal("zButtonTrack"..index)
else
button = zButtonTrack
end
if button.id then
CastSpell(button.id, "spell")
if zButtonTrack.hideonclick then
if type(ZSpellButton_SetChildrenExpanded) == "function" then
ZSpellButton_SetChildrenExpanded(zButtonTrack, false)
elseif zButtonTrack.children then
zButtonTrack.children:Hide()
end
end
end
end
SLASH_zButtonTrack1 = "/ZTrack"
SlashCmdList["zButtonTrack"] = function(msg)
if MTH_ZH_HandleDisabledSlash and MTH_ZH_HandleDisabledSlash("Track button is disabled while module 'zhunter' is disabled.") then
return
end
msg = tostring(msg or "")
if msg == "reset" then
zButtonTrack_Reset()
zButtonTrack:ClearAllPoints()
zButtonTrack:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
elseif msg == "options" then
MTH_OpenOptions("Track")
else
MTH_ZH_Print("Possible Commands: \"options\", \"reset\"")
end
end end
+280 -262
View File
@@ -1,263 +1,281 @@
local function zButtonTrap_GetRoot() local function zButtonTrap_GetRoot()
return MTH_ZH_GetSavedRoot() return MTH_ZH_GetSavedRoot()
end end
local root = zButtonTrap_GetRoot() local root = zButtonTrap_GetRoot()
if not root["zButtonTrap"] then if not root["zButtonTrap"] then
root["zButtonTrap"] = {} root["zButtonTrap"] = {}
root["zButtonTrap"]["spells"] = {1, 2, 3, 4} root["zButtonTrap"]["spells"] = {1, 2, 3, 4}
root["zButtonTrap"]["rows"] = 1 root["zButtonTrap"]["rows"] = 1
root["zButtonTrap"]["horizontal"] = nil root["zButtonTrap"]["horizontal"] = nil
root["zButtonTrap"]["vertical"] = nil root["zButtonTrap"]["vertical"] = nil
root["zButtonTrap"]["firstbutton"] = "RIGHT" root["zButtonTrap"]["firstbutton"] = "RIGHT"
root["zButtonTrap"]["enabled"] = 1 root["zButtonTrap"]["enabled"] = 1
root["zButtonTrap"]["tooltip"] = 1 root["zButtonTrap"]["tooltip"] = 1
root["zButtonTrap"]["parent"] = {} root["zButtonTrap"]["parent"] = {}
root["zButtonTrap"]["parent"]["size"] = 36 root["zButtonTrap"]["parent"]["size"] = 36
root["zButtonTrap"]["parent"]["hide"] = nil root["zButtonTrap"]["parent"]["hide"] = nil
root["zButtonTrap"]["parent"]["circle"] = 1 root["zButtonTrap"]["parent"]["circle"] = 1
root["zButtonTrap"]["children"] = {} root["zButtonTrap"]["children"] = {}
root["zButtonTrap"]["children"]["size"] = 36 root["zButtonTrap"]["children"]["size"] = 36
root["zButtonTrap"]["children"]["hideonclick"] = 1 root["zButtonTrap"]["children"]["hideonclick"] = 1
end end
ZHunterMod_Trap_Spells = { ZHunterMod_Trap_Spells = {
ZHUNTER_TRAP_FREEZING, ZHUNTER_TRAP_FREEZING,
ZHUNTER_TRAP_FROST, ZHUNTER_TRAP_FROST,
ZHUNTER_TRAP_IMMOLATION, ZHUNTER_TRAP_IMMOLATION,
ZHUNTER_TRAP_EXPLOSIVE ZHUNTER_TRAP_EXPLOSIVE
} }
local ZHUNTER_TRAP_MAX = table.getn(ZHunterMod_Trap_Spells) local ZHUNTER_TRAP_MAX = table.getn(ZHunterMod_Trap_Spells)
local zButtonTrap_LastParentId = nil
local function zButtonTrap_GetSaved() local zButtonTrap_LastCombatState = nil
local currentRoot = zButtonTrap_GetRoot()
if not currentRoot["zButtonTrap"] then local function zButtonTrap_GetSaved()
currentRoot["zButtonTrap"] = {} local currentRoot = zButtonTrap_GetRoot()
end if not currentRoot["zButtonTrap"] then
return currentRoot["zButtonTrap"] currentRoot["zButtonTrap"] = {}
end end
return currentRoot["zButtonTrap"]
local function zButtonTrap_EnsureConfig() end
local saved = zButtonTrap_GetSaved()
saved["count"] = nil local function zButtonTrap_EnsureConfig()
if saved["rows"] == nil then local saved = zButtonTrap_GetSaved()
saved["rows"] = 1 saved["count"] = nil
end if saved["rows"] == nil then
if saved["firstbutton"] == nil then saved["rows"] = 1
saved["firstbutton"] = "RIGHT" end
end if saved["firstbutton"] == nil then
if saved["enabled"] == nil then saved["firstbutton"] = "RIGHT"
saved["enabled"] = 1 end
end if saved["enabled"] == nil then
if saved["tooltip"] == nil then saved["enabled"] = 1
saved["tooltip"] = 1 end
end if saved["tooltip"] == nil then
if not saved["parent"] then saved["tooltip"] = 1
saved["parent"] = {} end
end if not saved["parent"] then
if saved["parent"]["size"] == nil then saved["parent"] = {}
saved["parent"]["size"] = 36 end
end if saved["parent"]["size"] == nil then
if saved["parent"]["circle"] == nil then saved["parent"]["size"] = 36
saved["parent"]["circle"] = 1 end
end if saved["parent"]["circle"] == nil then
if not saved["children"] then saved["parent"]["circle"] = 1
saved["children"] = {} end
end if not saved["children"] then
if saved["children"]["size"] == nil then saved["children"] = {}
saved["children"]["size"] = 36 end
end if saved["children"]["size"] == nil then
if saved["children"]["hideonclick"] == nil then saved["children"]["size"] = 36
saved["children"]["hideonclick"] = 1 end
end if saved["children"]["hideonclick"] == nil then
if not saved["spells"] then saved["children"]["hideonclick"] = 1
saved["spells"] = {} end
end if not saved["spells"] then
if not saved["visible"] then saved["spells"] = {}
saved["visible"] = {} end
end if not saved["visible"] then
for i = 1, ZHUNTER_TRAP_MAX do saved["visible"] = {}
if not tonumber(saved["spells"][i]) then end
saved["spells"][i] = i for i = 1, ZHUNTER_TRAP_MAX do
end if not tonumber(saved["spells"][i]) then
if saved["visible"][i] == nil then saved["spells"][i] = i
saved["visible"][i] = 1 end
end if saved["visible"][i] == nil then
end saved["visible"][i] = 1
end end
end
local function zButtonTrap_ApplyRuntimeSettings() end
if not zButtonTrap then
return local function zButtonTrap_ApplyRuntimeSettings()
end if not zButtonTrap then
local saved = zButtonTrap_GetSaved() return
zButtonTrap.tooltip = saved["tooltip"] and true or false end
zButtonTrap.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false local saved = zButtonTrap_GetSaved()
end zButtonTrap.tooltip = saved["tooltip"] and true or false
zButtonTrap.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false
zButtonTrap.expandonhover = saved["children"] and saved["children"]["expandonhover"] and true or false
function zButtonTrap_OnLoad() zButtonTrap.fadetimer = saved["children"] and tonumber(saved["children"]["fadetimer"]) or 0
this:RegisterEvent("VARIABLES_LOADED") end
end
function zButtonTrap_OnEvent() function zButtonTrap_OnLoad()
if event == "VARIABLES_LOADED" then this:RegisterEvent("VARIABLES_LOADED")
if not zButtonTrap then end
return
end function zButtonTrap_OnEvent()
if UnitClass("player") ~= ZHUNTER_HUNTER then if event == "VARIABLES_LOADED" then
zButtonTrap:UnregisterAllEvents() if not zButtonTrap then
zButtonTrap:Hide() return
return end
end if UnitClass("player") ~= ZHUNTER_HUNTER then
zButtonTrap_CreateButtons() zButtonTrap:UnregisterAllEvents()
zButtonTrapAdjustment = CreateFrame("Frame", "zButtonTrapAdjustment") zButtonTrap:Hide()
zButtonTrapAdjustment:RegisterEvent("PLAYER_REGEN_ENABLED") return
zButtonTrapAdjustment:RegisterEvent("PLAYER_REGEN_DISABLED") end
zButtonTrapAdjustment:RegisterEvent("PLAYER_ENTERING_WORLD") zButtonTrap_CreateButtons()
zButtonTrapAdjustment:RegisterEvent("SPELLS_CHANGED") MTH_ZH_TrapAdjust = CreateFrame("Frame", "MTH_ZH_TrapAdjust")
zButtonTrapAdjustment:RegisterEvent("CHARACTER_POINTS_CHANGED") MTH_ZH_TrapAdjust:RegisterEvent("PLAYER_REGEN_ENABLED")
zButtonTrapAdjustment:SetScript("OnEvent", zButtonTrapAdjustment_OnEvent) MTH_ZH_TrapAdjust:RegisterEvent("PLAYER_REGEN_DISABLED")
zButtonTrap_SetupSizeAndPosition() MTH_ZH_TrapAdjust:RegisterEvent("PLAYER_ENTERING_WORLD")
end MTH_ZH_TrapAdjust:RegisterEvent("SPELLS_CHANGED")
end MTH_ZH_TrapAdjust:RegisterEvent("CHARACTER_POINTS_CHANGED")
MTH_ZH_TrapAdjust:SetScript("OnEvent", MTH_ZH_TrapAdjust_OnEvent)
function zButtonTrap_CreateButtons() zButtonTrap_SetupSizeAndPosition()
zButtonTrap_EnsureConfig() end
local saved = zButtonTrap_GetSaved() end
ZSpellButton_CreateChildren(zButtonTrap, "zButtonTrap", ZHUNTER_TRAP_MAX) function zButtonTrap_CreateButtons()
local info = {} zButtonTrap_EnsureConfig()
local infoIndex = 1 local saved = zButtonTrap_GetSaved()
for i=1, table.getn(ZHunterMod_Trap_Spells) do
if not tonumber(saved["spells"][i]) then ZSpellButton_CreateChildren(zButtonTrap, "zButtonTrap", ZHUNTER_TRAP_MAX)
info = ZHunterMod_Trap_Spells local info = {}
saved["spells"] = {1, 2, 3, 4} local infoIndex = 1
break for i=1, table.getn(ZHunterMod_Trap_Spells) do
end if not tonumber(saved["spells"][i]) then
local spellIndex = saved["spells"][i] info = ZHunterMod_Trap_Spells
if saved["visible"][spellIndex] ~= false then saved["spells"] = {1, 2, 3, 4}
info[infoIndex] = ZHunterMod_Trap_Spells[spellIndex] break
infoIndex = infoIndex + 1 end
end local spellIndex = saved["spells"][i]
end if saved["visible"][spellIndex] ~= false then
zButtonTrap.found = ZSpellButton_SetButtons(zButtonTrap, info) info[infoIndex] = ZHunterMod_Trap_Spells[spellIndex]
zButtonTrap_ApplyRuntimeSettings() infoIndex = infoIndex + 1
end end
end
function zButtonTrap_SetupSizeAndPosition() zButtonTrap.found = ZSpellButton_SetButtons(zButtonTrap, info)
zButtonTrap_EnsureConfig() zButtonTrap_ApplyRuntimeSettings()
local saved = zButtonTrap_GetSaved() end
if saved["enabled"] == false or saved["enabled"] == 0 then
if zButtonTrap and zButtonTrap.Hide then function zButtonTrap_SetupSizeAndPosition()
zButtonTrap:Hide() zButtonTrap_EnsureConfig()
end local saved = zButtonTrap_GetSaved()
return if saved["enabled"] == false or saved["enabled"] == 0 then
end if MTH_ZH_TrapAdjust and MTH_ZH_TrapAdjust.SetScript then
local displayCount = zButtonTrap.found or ZHUNTER_TRAP_MAX MTH_ZH_TrapAdjust:SetScript("OnEvent", nil)
if displayCount < 0 then end
displayCount = 0 if zButtonTrap and zButtonTrap.Hide then
end zButtonTrap:Hide()
ZSpellButton_SetSize(zButtonTrap, saved["parent"]["size"]) end
ZSpellButton_SetSize(zButtonTrap, saved["children"]["size"], 1) return
ZSpellButton_SetExpandDirection(zButtonTrap, saved["firstbutton"]) end
ZSpellButton_ArrangeChildren(zButtonTrap, saved["rows"], if MTH_ZH_TrapAdjust and MTH_ZH_TrapAdjust.SetScript then
displayCount, saved["horizontal"], MTH_ZH_TrapAdjust:SetScript("OnEvent", MTH_ZH_TrapAdjust_OnEvent)
saved["vertical"]) end
end local displayCount = zButtonTrap.found or ZHUNTER_TRAP_MAX
if displayCount < 0 then
function zButtonTrap_Reset() displayCount = 0
local currentRoot = zButtonTrap_GetRoot() end
currentRoot["zButtonTrap"] = {} ZSpellButton_SetSize(zButtonTrap, saved["parent"]["size"])
local saved = zButtonTrap_GetSaved() ZSpellButton_SetSize(zButtonTrap, saved["children"]["size"], 1)
saved["spells"] = {1, 2, 3, 4} ZSpellButton_SetExpandDirection(zButtonTrap, saved["firstbutton"])
saved["rows"] = 1 ZSpellButton_ArrangeChildren(zButtonTrap, saved["rows"],
saved["horizontal"] = nil displayCount, saved["horizontal"],
saved["vertical"] = nil saved["vertical"])
saved["firstbutton"] = "RIGHT" end
saved["enabled"] = 1
saved["tooltip"] = 1 function zButtonTrap_Reset()
saved["parent"] = {} local currentRoot = zButtonTrap_GetRoot()
saved["parent"]["size"] = 36 currentRoot["zButtonTrap"] = {}
saved["parent"]["hide"] = nil local saved = zButtonTrap_GetSaved()
saved["parent"]["circle"] = 1 saved["spells"] = {1, 2, 3, 4}
saved["children"] = {} saved["rows"] = 1
saved["children"]["size"] = 36 saved["horizontal"] = nil
saved["children"]["hideonclick"] = 1 saved["vertical"] = nil
saved["visible"] = {1, 1, 1, 1} saved["firstbutton"] = "RIGHT"
zButtonTrap_EnsureConfig() saved["enabled"] = 1
end saved["tooltip"] = 1
saved["parent"] = {}
function zButtonTrapAdjustment_OnEvent() saved["parent"]["size"] = 36
if not zButtonTrap or not zButtonTrap.count then saved["parent"]["hide"] = nil
return saved["parent"]["circle"] = 1
end saved["children"] = {}
if event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" then saved["children"]["size"] = 36
zButtonTrap_CreateButtons() saved["children"]["hideonclick"] = 1
zButtonTrap_SetupSizeAndPosition() saved["visible"] = {1, 1, 1, 1}
end zButtonTrap_EnsureConfig()
local nextbutton end
local button
local combat = event == "PLAYER_REGEN_DISABLED" function MTH_ZH_TrapAdjust_OnEvent()
for i=1, zButtonTrap.count do if not zButtonTrap or not zButtonTrap.count then
button = getglobal(zButtonTrap.name..i) return
button.customcolor = nil end
if button.id then local rebuild = false
if not nextbutton then if event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" then
nextbutton = button zButtonTrap_CreateButtons()
end zButtonTrap_SetupSizeAndPosition()
if combat then rebuild = true
button.icontexture:SetVertexColor(0.4, 0.4, 0.4) end
button.customcolor = 1 local nextbutton
else local button
button.icontexture:SetVertexColor(1.0, 1.0, 1.0) local combat = event == "PLAYER_REGEN_DISABLED"
end for i=1, zButtonTrap.count do
end button = getglobal(zButtonTrap.name..i)
end button.customcolor = nil
zButtonTrap.id = nextbutton and nextbutton.id or zButtonTrap1.id if button.id then
ZSpellButton_UpdateButton(zButtonTrap) if not nextbutton then
ZSpellButton_UpdateCooldown(zButtonTrap) nextbutton = button
if GameTooltip:IsOwned(zButtonTrap) then end
ZSpellButtonParent_OnEnter(zButtonTrap) if combat then
end button.icontexture:SetVertexColor(0.4, 0.4, 0.4)
end button.customcolor = 1
else
function zButtonTrap_KeyBinding(index) button.icontexture:SetVertexColor(1.0, 1.0, 1.0)
if MTH_ZH_IsModuleEnabled and not MTH_ZH_IsModuleEnabled() then end
return end
end end
local newParentId = nextbutton and nextbutton.id or zButtonTrap1.id
local button if (not rebuild) and zButtonTrap_LastParentId == newParentId and zButtonTrap_LastCombatState == combat and not GameTooltip:IsOwned(zButtonTrap) then
if index then return
button = getglobal("zButtonTrap"..index) end
else zButtonTrap_LastParentId = newParentId
button = zButtonTrap zButtonTrap_LastCombatState = combat
end zButtonTrap.id = newParentId
if button.id then ZSpellButton_UpdateButton(zButtonTrap)
CastSpell(button.id, "spell") ZSpellButton_UpdateCooldown(zButtonTrap)
if zButtonTrap.hideonclick then if GameTooltip:IsOwned(zButtonTrap) then
if type(ZSpellButton_SetChildrenExpanded) == "function" then ZSpellButtonParent_OnEnter(zButtonTrap)
ZSpellButton_SetChildrenExpanded(zButtonTrap, false) end
elseif zButtonTrap.children then end
zButtonTrap.children:Hide()
end function zButtonTrap_KeyBinding(index)
end if MTH_ZH_IsModuleEnabled and not MTH_ZH_IsModuleEnabled() then
end return
end end
SLASH_zButtonTrap1 = "/ZTrap" local button
SlashCmdList["zButtonTrap"] = function(msg) if index then
if MTH_ZH_HandleDisabledSlash and MTH_ZH_HandleDisabledSlash("Trap button is disabled while module 'zhunter' is disabled.") then button = getglobal("zButtonTrap"..index)
return else
end button = zButtonTrap
if msg == "reset" then end
zButtonTrap_Reset() if button.id then
zButtonTrap:ClearAllPoints() CastSpell(button.id, "spell")
zButtonTrap:SetPoint("CENTER", UIParent, "CENTER", 60, 0) if zButtonTrap.hideonclick then
elseif msg == "options" then if type(ZSpellButton_SetChildrenExpanded) == "function" then
MTH_OpenOptions("Trap") ZSpellButton_SetChildrenExpanded(zButtonTrap, false)
else elseif zButtonTrap.children then
MTH_ZH_Print("Possible Commands: \"options\", \"reset\"") zButtonTrap.children:Hide()
end end
end
end
end
SLASH_zButtonTrap1 = "/ZTrap"
SlashCmdList["zButtonTrap"] = function(msg)
if MTH_ZH_HandleDisabledSlash and MTH_ZH_HandleDisabledSlash("Trap button is disabled while module 'zhunter' is disabled.") then
return
end
if msg == "reset" then
zButtonTrap_Reset()
zButtonTrap:ClearAllPoints()
zButtonTrap:SetPoint("CENTER", UIParent, "CENTER", 60, 0)
elseif msg == "options" then
MTH_OpenOptions("Trap")
else
MTH_ZH_Print("Possible Commands: \"options\", \"reset\"")
end
end end