mirror of
https://codeberg.org/Duvelcorp/MetaHunt.git
synced 2026-09-22 07:36:58 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ab34946775 | |||
| d41703949d | |||
| 27d37564ce | |||
| 4aed1174dd | |||
| 233899b2a0 | |||
| 89fd8e079c | |||
| 1a28d95b87 |
@@ -9,4 +9,3 @@
|
||||
tools/
|
||||
LOC*.md
|
||||
LOCALIZATION*.md
|
||||
CHANGELOG.md
|
||||
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to MetaHunt will be documented in this file.
|
||||
|
||||
## [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
@@ -1,5 +1,5 @@
|
||||
## Interface: 11200
|
||||
## Version: 1.0.4
|
||||
## Version: 1.1.0
|
||||
## Title: MetaHunt - |cff00ff00Hunter
|
||||
## 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.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# MetaHunt
|
||||
|
||||
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 provides usefull tools for all hunters, wheter they are still leveling, lone-wolf, or HL raider.
|
||||
It is a modern modular addon that combines never-seen features, and improves/fixes a few old hunter add-ons.
|
||||
It provides a bunch useful tools for all huntards, wheter they are still levelling, lone-wolf, or HL raider.
|
||||
|
||||
## 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 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
|
||||
- zTrack: 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.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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 your stabled pets
|
||||
- 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.
|
||||
|
||||
@@ -6,6 +6,29 @@ local function AutoStrip_Print(msg)
|
||||
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()
|
||||
if type(MTH_CharSavedVariables) ~= "table" then
|
||||
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_WasInCombat = 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", "AutoStripRestoreFrame")
|
||||
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()
|
||||
local icon = getglobal("AutoStripDisplayIcon") or getglobal("AutoStripDisplayIconTexture")
|
||||
@@ -35,6 +142,11 @@ end
|
||||
|
||||
function AutoStrip_SetAutoStripToggle(enabled, silent)
|
||||
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
|
||||
saved["autostrip"] = 1
|
||||
AutoStrip_On = 1
|
||||
@@ -54,10 +166,17 @@ function AutoStrip_SetAutoStripToggle(enabled, silent)
|
||||
AutoStrip_Print("Auto-Strip disabled.")
|
||||
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
|
||||
|
||||
function AutoStrip_SetDisplayToggle(enabled, silent)
|
||||
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
|
||||
saved["display"] = 1
|
||||
if AutoStripDisplay then
|
||||
@@ -79,9 +198,15 @@ function AutoStrip_SetDisplayToggle(enabled, silent)
|
||||
AutoStrip_Print("AutoStrip button is now hidden.")
|
||||
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
|
||||
|
||||
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
|
||||
if AutoStripDisplayAutoCast then
|
||||
AutoStripDisplayAutoCast:Hide()
|
||||
@@ -102,6 +227,7 @@ function AutoStrip_UnequipAll(weaponsOnly)
|
||||
|
||||
if not hasEmptySlot then
|
||||
AutoStrip_Print("You need at least one empty bag slot to auto-strip.")
|
||||
AutoStrip_Trace("UnequipAll aborted no-empty-slot")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -121,19 +247,36 @@ function AutoStrip_UnequipAll(weaponsOnly)
|
||||
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
|
||||
|
||||
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
|
||||
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_RestoreDisplayPosition("VARIABLES_LOADED")
|
||||
AutoStrip_SetDisplayToggle(saved["display"] and true or false, 1)
|
||||
AutoStrip_SetAutoStripToggle(saved["autostrip"] and true or false, 1)
|
||||
AutoStrip_QueueDeferredRestore("VARIABLES_LOADED")
|
||||
return
|
||||
end
|
||||
|
||||
if event == "PLAYER_ENTERING_WORLD" then
|
||||
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
|
||||
end
|
||||
|
||||
@@ -144,6 +287,7 @@ local function AutoStrip_OnEvent()
|
||||
|
||||
if event == "PLAYER_REGEN_ENABLED" then
|
||||
if AutoStrip_On and AutoStrip_WasInCombat then
|
||||
AutoStrip_Trace("PLAYER_REGEN_ENABLED triggering auto strip")
|
||||
AutoStrip_UnequipAll()
|
||||
end
|
||||
AutoStrip_WasInCombat = nil
|
||||
@@ -152,6 +296,8 @@ end
|
||||
|
||||
local function AutoStrip_HandleSlash(msg)
|
||||
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
|
||||
AutoStrip_SetDisplayToggle(not (saved["display"] and true or false))
|
||||
elseif msg == "toggle" then
|
||||
@@ -176,6 +322,7 @@ if AutoStrip_Frame then
|
||||
AutoStrip_Frame:RegisterEvent("PLAYER_REGEN_DISABLED")
|
||||
AutoStrip_Frame:RegisterEvent("PLAYER_REGEN_ENABLED")
|
||||
AutoStrip_Frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
AutoStrip_Frame:RegisterEvent("PLAYER_LOGOUT")
|
||||
AutoStrip_Frame:SetScript("OnEvent", AutoStrip_OnEvent)
|
||||
end
|
||||
|
||||
@@ -187,3 +334,8 @@ SLASH_AUTOSTRIP1 = "/autostrip"
|
||||
SlashCmdList["AUTOSTRIP"] = AutoStrip_HandleSlash
|
||||
SLASH_ZSTRIP1 = "/zstrip"
|
||||
SlashCmdList["ZSTRIP"] = AutoStrip_HandleSlash
|
||||
SLASH_AUTOSTRIPTRACE1 = "/autostriptrace"
|
||||
SLASH_AUTOSTRIPTRACE2 = "/astrace"
|
||||
SlashCmdList["AUTOSTRIPTRACE"] = function(msg)
|
||||
AutoStrip_CommandTrace(msg)
|
||||
end
|
||||
|
||||
@@ -68,6 +68,9 @@
|
||||
if ( this.isMoving ) then
|
||||
this:StopMovingOrSizing()
|
||||
this.isMoving = false
|
||||
if AutoStrip_SaveDisplayPosition then
|
||||
AutoStrip_SaveDisplayPosition("mouse-up-stop")
|
||||
end
|
||||
end
|
||||
</OnMouseUp>
|
||||
<OnDragStart>
|
||||
@@ -79,6 +82,9 @@
|
||||
<OnDragStop>
|
||||
this:StopMovingOrSizing()
|
||||
this.isMoving = false
|
||||
if AutoStrip_SaveDisplayPosition then
|
||||
AutoStrip_SaveDisplayPosition("drag-stop")
|
||||
end
|
||||
</OnDragStop>
|
||||
</Scripts>
|
||||
<NormalTexture name="$parentNormalTexture" file="Interface\Buttons\UI-Quickslot2">
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
MTH_CONST = MTH_CONST or {}
|
||||
MTH_CONST.version = MTH_CONST.version or "1.0.4"
|
||||
MTH_CONST.version = MTH_CONST.version or "1.1.0"
|
||||
|
||||
MTH_CONST.WEAPON_TYPES = {
|
||||
BOWS = "Bows",
|
||||
|
||||
+109
-12
@@ -526,6 +526,7 @@ local function MTH_FEED_CoreDropItemOnUnitHook(unit)
|
||||
end
|
||||
|
||||
if target == "pet" and CursorHasItem and CursorHasItem() then
|
||||
MTH_FEED_EnsureTrackerFrame()
|
||||
local itemId, itemName, itemLink, itemIcon = MTH_FEED_GetCursorItemSnapshot()
|
||||
local pet = MTH_FEED_GetCurrentPetContext()
|
||||
if not itemId then
|
||||
@@ -608,7 +609,6 @@ function MTH_FEED_DebugStatus()
|
||||
end
|
||||
|
||||
function MTH_FEED_ReinstallCoreTracking()
|
||||
MTH_FEED_EnsureTrackerFrame()
|
||||
local ok = MTH_FEED_InstallCoreHooks()
|
||||
return ok and true or false
|
||||
end
|
||||
@@ -624,8 +624,12 @@ local function MTH_FEED_EnsureBootstrapFrame()
|
||||
frame:RegisterEvent("VARIABLES_LOADED")
|
||||
frame:RegisterEvent("PLAYER_LOGIN")
|
||||
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
frame:SetScript("OnEvent", function()
|
||||
frame:SetScript("OnEvent", function(self)
|
||||
MTH_FEED_ReinstallCoreTracking()
|
||||
if self and self.UnregisterAllEvents then
|
||||
self:UnregisterAllEvents()
|
||||
self:SetScript("OnEvent", nil)
|
||||
end
|
||||
end)
|
||||
MTH_FEED_BootstrapFrame = frame
|
||||
return frame
|
||||
@@ -940,9 +944,6 @@ function MTH_FEED_BeginAttempt(payload)
|
||||
itemIcon = infoTexture
|
||||
end
|
||||
end
|
||||
if (not itemIcon or itemIcon == "") then
|
||||
itemIcon = MTH_FEED_FindItemIconInBags(itemId, payload and payload.itemName)
|
||||
end
|
||||
|
||||
MTH_FEED_Runtime.attempts[attemptId] = {
|
||||
id = attemptId,
|
||||
@@ -1113,7 +1114,7 @@ function MTH_FEED_IsFoodCompatible(petLevel, foodLevel)
|
||||
return true
|
||||
end
|
||||
|
||||
function MTH_FEED_IsExceptionReject(itemId)
|
||||
function MTH_FEED_IsExceptionReject(itemId, petLevel)
|
||||
local key = tonumber(itemId)
|
||||
if not key then
|
||||
return false
|
||||
@@ -1123,6 +1124,11 @@ function MTH_FEED_IsExceptionReject(itemId)
|
||||
if type(row) ~= "table" then
|
||||
return false
|
||||
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
|
||||
return false
|
||||
end
|
||||
@@ -1137,6 +1143,17 @@ function MTH_FEED_IsExceptionReject(itemId)
|
||||
if not reasons then
|
||||
return false
|
||||
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
|
||||
if wrongFoodCount < 2 then
|
||||
return false
|
||||
@@ -1144,6 +1161,49 @@ function MTH_FEED_IsExceptionReject(itemId)
|
||||
return true
|
||||
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)
|
||||
local key = tostring(petId or "")
|
||||
if key == "" then
|
||||
@@ -1153,7 +1213,7 @@ function MTH_FEED_GetPetFeedStats(petId)
|
||||
return store.byPetId[key]
|
||||
end
|
||||
|
||||
local function MTH_FEED_UpsertException(store, itemId, reason)
|
||||
local function MTH_FEED_UpsertException(store, itemId, reason, petLevel)
|
||||
if not itemId then
|
||||
return
|
||||
end
|
||||
@@ -1175,6 +1235,16 @@ local function MTH_FEED_UpsertException(store, itemId, reason)
|
||||
row.reasons.wrongFood = (tonumber(row.reasons.wrongFood) or 0) + 1
|
||||
elseif reason == "low-level" then
|
||||
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
|
||||
row.reasons.unknown = (tonumber(row.reasons.unknown) or 0) + 1
|
||||
end
|
||||
@@ -1182,6 +1252,36 @@ local function MTH_FEED_UpsertException(store, itemId, reason)
|
||||
row.lastObservedAt = MTH_FEED_Now()
|
||||
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)
|
||||
local row = MTH_FEED_Runtime.attempts[attemptId]
|
||||
if type(row) ~= "table" then
|
||||
@@ -1241,6 +1341,7 @@ function MTH_FEED_FinalizeAttempt(attemptId, payload)
|
||||
if itemRow then
|
||||
itemRow.accepted = itemRow.accepted + 1
|
||||
end
|
||||
MTH_FEED_ClearStaleExceptionOnAccept(store, row.itemId)
|
||||
local petKey = tostring((petRow and petRow.petId) or row.petId or "")
|
||||
if petKey ~= "" then
|
||||
MTH_FEED_Runtime.sessionFeedsByPetId[petKey] = (tonumber(MTH_FEED_Runtime.sessionFeedsByPetId[petKey]) or 0) + 1
|
||||
@@ -1257,7 +1358,7 @@ function MTH_FEED_FinalizeAttempt(attemptId, payload)
|
||||
if itemRow then
|
||||
itemRow.rejected = itemRow.rejected + 1
|
||||
end
|
||||
MTH_FEED_UpsertException(store, row.itemId, reason)
|
||||
MTH_FEED_UpsertException(store, row.itemId, reason, row.petLevel)
|
||||
end
|
||||
|
||||
if itemRow then
|
||||
@@ -1280,9 +1381,6 @@ function MTH_FEED_FinalizeAttempt(attemptId, payload)
|
||||
persistedIcon = directTexture
|
||||
end
|
||||
end
|
||||
if (not persistedIcon or persistedIcon == "") then
|
||||
persistedIcon = MTH_FEED_FindItemIconInBags(row.itemId, row.itemName)
|
||||
end
|
||||
if persistedIcon and persistedIcon ~= "" then
|
||||
itemRow.itemIcon = persistedIcon
|
||||
end
|
||||
@@ -1542,6 +1640,5 @@ function MTH_FEED_DebugDumpCurrentPet(limit)
|
||||
return true
|
||||
end
|
||||
|
||||
MTH_FEED_EnsureTrackerFrame()
|
||||
MTH_FEED_InstallCoreHooks()
|
||||
MTH_FEED_EnsureBootstrapFrame()
|
||||
|
||||
+74
-44
@@ -1,5 +1,5 @@
|
||||
MTH = MTH or {
|
||||
version = "1.0.4",
|
||||
version = "1.1.0",
|
||||
name = "MetaHunt",
|
||||
modules = {},
|
||||
config = {},
|
||||
@@ -16,6 +16,14 @@ local MTH_MESSAGE_DEFAULTS = {
|
||||
spellbookScan = false,
|
||||
petRanAway = true,
|
||||
mapMarkers = true,
|
||||
stableScan = true,
|
||||
}
|
||||
|
||||
local MTH_MODULE_DEFAULT_STATES = {
|
||||
autoquest = false,
|
||||
autobuy = false,
|
||||
feedomatic = false,
|
||||
icu = false,
|
||||
}
|
||||
|
||||
local function MTH_ClassGateTrace(_step, _detail)
|
||||
@@ -424,9 +432,53 @@ local function MTH_GetPersistedModuleEnabled(name, defaultEnabled)
|
||||
local resolvedName = MTH_NormalizeModuleName(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
|
||||
MTH_ModuleStateDebug("read " .. tostring(name) .. " no-savedvars fallback-default=" .. tostring(defaultEnabled and true or false))
|
||||
return defaultEnabled and true or false
|
||||
MTH_SavedVariables = {}
|
||||
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
|
||||
|
||||
if type(MTH_SavedVariables.moduleStates) == "table" then
|
||||
@@ -435,25 +487,11 @@ local function MTH_GetPersistedModuleEnabled(name, defaultEnabled)
|
||||
if MTH_SavedVariables.moduleStates[key] ~= nil then
|
||||
local resolved = MTH_SavedVariables.moduleStates[key] and true or false
|
||||
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
|
||||
if type(MTH_CharSavedVariables.modules[resolvedName]) ~= "table" then
|
||||
MTH_CharSavedVariables.modules[resolvedName] = {}
|
||||
end
|
||||
MTH_CharSavedVariables.modules[resolvedName].enabled = resolved
|
||||
return resolved
|
||||
end
|
||||
end
|
||||
@@ -465,9 +503,11 @@ local function MTH_GetPersistedModuleEnabled(name, defaultEnabled)
|
||||
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
|
||||
MTH_ModuleStateDebug("read " .. tostring(name) .. " from modules." .. tostring(key) .. ".enabled=" .. tostring(resolved))
|
||||
if type(MTH_SavedVariables.modules[resolvedName]) ~= "table" then
|
||||
MTH_SavedVariables.modules[resolvedName] = MTH_SavedVariables.modules[key]
|
||||
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
|
||||
end
|
||||
end
|
||||
@@ -478,16 +518,11 @@ local function MTH_GetPersistedModuleEnabled(name, defaultEnabled)
|
||||
if type(MTH_SavedVariables[key]) == "table" and MTH_SavedVariables[key].enabled ~= nil then
|
||||
local resolved = MTH_SavedVariables[key].enabled and true or false
|
||||
MTH_ModuleStateDebug("read " .. tostring(name) .. " from legacy-top-level." .. tostring(key) .. ".enabled=" .. tostring(resolved))
|
||||
if type(MTH_SavedVariables.modules) ~= "table" then
|
||||
MTH_SavedVariables.modules = {}
|
||||
MTH_CharSavedVariables.moduleStates[resolvedName] = resolved
|
||||
if type(MTH_CharSavedVariables.modules[resolvedName]) ~= "table" then
|
||||
MTH_CharSavedVariables.modules[resolvedName] = {}
|
||||
end
|
||||
if type(MTH_SavedVariables.modules[resolvedName]) ~= "table" then
|
||||
MTH_SavedVariables.modules[resolvedName] = MTH_SavedVariables[key]
|
||||
end
|
||||
if type(MTH_SavedVariables.moduleStates) ~= "table" then
|
||||
MTH_SavedVariables.moduleStates = {}
|
||||
end
|
||||
MTH_SavedVariables.moduleStates[resolvedName] = resolved
|
||||
MTH_CharSavedVariables.modules[resolvedName].enabled = resolved
|
||||
return resolved
|
||||
end
|
||||
end
|
||||
@@ -506,27 +541,22 @@ local function MTH_SetPersistedModuleEnabled(name, enabled)
|
||||
if type(MTH_SavedVariables) ~= "table" then
|
||||
MTH_SavedVariables = {}
|
||||
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
|
||||
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[name]) ~= "table" then
|
||||
MTH_CharSavedVariables.modules[name] = {}
|
||||
end
|
||||
|
||||
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.modules[name].enabled = enabled
|
||||
MTH_ModuleStateDebug("write " .. tostring(name) .. " enabled=" .. tostring(enabled))
|
||||
end
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ end
|
||||
local MTH_PT_ApplyScan
|
||||
local MTH_PT_AbilityHasPositiveRanks
|
||||
local MTH_PT_PromoteUnrankedKnownAliases
|
||||
local MTH_PT_BootstrapFrame = nil
|
||||
|
||||
local MTH_PT_VERBOSE_SCAN_LOGS = false
|
||||
|
||||
@@ -846,6 +847,38 @@ function MTH_PT_InitService()
|
||||
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(self, evt)
|
||||
evt = evt or event
|
||||
if evt ~= "PET_TRAINING_SHOW" and evt ~= "CRAFT_SHOW" then
|
||||
return
|
||||
end
|
||||
MTH_PT_InitService()
|
||||
if type(MTH_PT_OnEvent) == "function" then
|
||||
MTH_PT_OnEvent(MTH_PetTrainingFrame, evt)
|
||||
end
|
||||
if self and self.UnregisterAllEvents then
|
||||
self:UnregisterAllEvents()
|
||||
self:SetScript("OnEvent", nil)
|
||||
end
|
||||
MTH_PT_BootstrapFrame = nil
|
||||
end)
|
||||
MTH_PT_BootstrapFrame = frame
|
||||
end
|
||||
|
||||
function MTH_PT_ShutdownService(_reason)
|
||||
if not MTH_PetTrainingFrame then
|
||||
return
|
||||
@@ -929,3 +962,4 @@ end
|
||||
|
||||
MTH_TR_InitService = MTH_PT_InitService
|
||||
MTH_TR_ShutdownService = MTH_PT_ShutdownService
|
||||
MTH_TR_InitBootstrap = MTH_PT_InitBootstrap
|
||||
|
||||
@@ -7,6 +7,25 @@ local MTH_PS_LastScanAt = 0
|
||||
local MTH_PS_VERBOSE_LOGS = false
|
||||
local MTH_PS_ForceScanUntil = 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()
|
||||
MTH_PS_ForceScanUntil = 0
|
||||
@@ -26,9 +45,25 @@ end
|
||||
local function MTH_PS_IsFollowupEventTrigger(trigger)
|
||||
local t = tostring(trigger or "")
|
||||
return t == "event:UNIT_PET"
|
||||
or t == "UNIT_PET"
|
||||
or t == "event:PET_BAR_UPDATE"
|
||||
or t == "PET_BAR_UPDATE"
|
||||
or t == "event:SPELLS_CHANGED"
|
||||
or t == "SPELLS_CHANGED"
|
||||
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
|
||||
|
||||
local function MTH_PS_IsPriorityTrigger(trigger)
|
||||
@@ -190,6 +225,41 @@ function MTH_PSP_RequestScan(trigger, minIntervalSeconds)
|
||||
local minInterval = tonumber(minIntervalSeconds) or 1
|
||||
local bypassThrottle = false
|
||||
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
|
||||
bypassThrottle = true
|
||||
@@ -237,7 +307,19 @@ local function MTH_PS_OnEvent(_, evt, eventArg1)
|
||||
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
|
||||
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
|
||||
|
||||
@@ -249,7 +331,7 @@ function MTH_PS_InitService()
|
||||
return
|
||||
end
|
||||
|
||||
MTH_PS_Frame = CreateFrame("Frame", "MTHPetSpellScanFrame")
|
||||
MTH_PS_Frame = CreateFrame("Frame", "MTHPetSpellbookEventFrame")
|
||||
MTH_PS_Frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
MTH_PS_Frame:RegisterEvent("UNIT_PET")
|
||||
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 = nil
|
||||
MTH_PS_LastScanAt = 0
|
||||
MTH_PS_LastNoPetScanAt = 0
|
||||
MTH_PS_ClearForceWindow()
|
||||
end
|
||||
|
||||
|
||||
+1402
-133
File diff suppressed because it is too large
Load Diff
+80
-12
@@ -129,6 +129,49 @@ local function MTH_CommandOptions()
|
||||
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 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"])
|
||||
@@ -197,6 +240,34 @@ local function MTH_CommandPetSpellScanFallback()
|
||||
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
|
||||
function MTH_PS_ScanNow(trigger)
|
||||
local ok, count = MTH_CommandPetSpellScanFallback()
|
||||
@@ -239,18 +310,15 @@ function SlashCmdList.MTH(msg, editbox)
|
||||
msg = string.gsub(tostring(msg), "^%s+", "")
|
||||
msg = string.gsub(msg, "%s+$", "")
|
||||
local lowerMsg = string.lower(msg)
|
||||
local _, _, lowerCmd, lowerArg = string.find(lowerMsg, "^(%S+)%s*(.-)%s*$")
|
||||
if msg == "" then
|
||||
MTH:Print("Available: /mth options, /mth book")
|
||||
elseif lowerMsg == "options" then
|
||||
MTH_CommandOptions()
|
||||
elseif lowerMsg == "book" or lowerMsg == "hunterbook" then
|
||||
MTH_CommandBook()
|
||||
elseif lowerMsg == "err" then
|
||||
if MTH_DebugFrame and type(MTH_DebugFrame.Toggle) == "function" then
|
||||
MTH_DebugFrame:Toggle()
|
||||
else
|
||||
MTH:Print("Debug frame is not available yet")
|
||||
end
|
||||
elseif lowerMsg == "peers" or lowerMsg == "who" then
|
||||
MTH_CommandPeers()
|
||||
else
|
||||
MTH:Print("Unknown command: " .. tostring(msg))
|
||||
MTH:Print("Available: /mth options, /mth book")
|
||||
@@ -259,13 +327,13 @@ end
|
||||
|
||||
-- Initialize on load
|
||||
MTH:InitSavedVariables()
|
||||
if type(MTH_ST_InitService) == "function" then
|
||||
MTH_ST_InitService()
|
||||
if type(MTH_ST_InitBootstrap) == "function" then
|
||||
MTH_ST_InitBootstrap()
|
||||
end
|
||||
if type(MTH_TR_InitService) == "function" then
|
||||
MTH_TR_InitService()
|
||||
elseif type(MTH_PT_InitService) == "function" then
|
||||
MTH_PT_InitService()
|
||||
if type(MTH_TR_InitBootstrap) == "function" then
|
||||
MTH_TR_InitBootstrap()
|
||||
elseif type(MTH_PT_InitBootstrap) == "function" then
|
||||
MTH_PT_InitBootstrap()
|
||||
end
|
||||
if type(MTH_PS_InitService) == "function" then
|
||||
MTH_PS_InitService()
|
||||
|
||||
@@ -7,8 +7,8 @@ MTH_HUNTERBOOK_TABS.families = {
|
||||
{ x = 10, width = 106, align = "LEFT" },
|
||||
{ x = 122, width = 52, align = "LEFT" },
|
||||
{ x = 176, width = 52, align = "LEFT" },
|
||||
{ x = 232, width = 292, align = "LEFT" },
|
||||
{ x = 460, width = 184, align = "LEFT" },
|
||||
{ x = 232, width = 364, align = "LEFT" },
|
||||
{ x = 532, width = 112, align = "LEFT" },
|
||||
},
|
||||
}
|
||||
|
||||
@@ -27,6 +27,11 @@ local function MTH_BOOKTAB_FamiliesTrim(value)
|
||||
return text
|
||||
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)
|
||||
if not (MTH_DS_PetSpells and type(MTH_DS_PetSpells.byAbility) == "table") then
|
||||
return nil
|
||||
@@ -95,25 +100,49 @@ function MTH_BOOKTAB_BuildFamiliesRows()
|
||||
if token ~= "" and not seen[token] then
|
||||
seen[token] = true
|
||||
local spellRows = (type(bundle) == "table" and type(bundle.spells) == "table") and bundle.spells or {}
|
||||
local firstAnySpell = nil
|
||||
local firstBeastSpell = nil
|
||||
local rankMin = nil
|
||||
local rankMax = nil
|
||||
local rankMap = {}
|
||||
local beastRankMin = nil
|
||||
local beastRankMax = nil
|
||||
local beastRankMap = {}
|
||||
local anyRankMin = nil
|
||||
local anyRankMax = nil
|
||||
local anyRankMap = {}
|
||||
for s = 1, table.getn(spellRows) do
|
||||
local spell = spellRows[s]
|
||||
if type(spell) == "table" and MTH_BOOKTAB_FamiliesSafeLower(spell.learnMethod or "beast") ~= "trainer" then
|
||||
if not firstBeastSpell then
|
||||
firstBeastSpell = spell
|
||||
if type(spell) == "table" then
|
||||
if not firstAnySpell then
|
||||
firstAnySpell = spell
|
||||
end
|
||||
local rank = tonumber(spell.rankNumber)
|
||||
if rank and rank > 0 then
|
||||
rankMap[rank] = true
|
||||
if not rankMin or rank < rankMin then rankMin = rank end
|
||||
if not rankMax or rank > rankMax then rankMax = rank end
|
||||
anyRankMap[rank] = true
|
||||
if not anyRankMin or rank < anyRankMin then anyRankMin = 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
|
||||
|
||||
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
|
||||
for _ in pairs(rankMap) do
|
||||
rankCount = rankCount + 1
|
||||
@@ -123,8 +152,8 @@ function MTH_BOOKTAB_BuildFamiliesRows()
|
||||
name = canonicalMap[token] or canonical,
|
||||
token = token,
|
||||
isUnique = (abilityCounts[token] or 0) == 1,
|
||||
icon = firstBeastSpell and firstBeastSpell.icon or nil,
|
||||
description = firstBeastSpell and firstBeastSpell.description or "",
|
||||
icon = displaySpell and displaySpell.icon or nil,
|
||||
description = displaySpell and displaySpell.description or "",
|
||||
rankMin = rankMin,
|
||||
rankMax = rankMax,
|
||||
rankCount = rankCount,
|
||||
@@ -141,17 +170,23 @@ function MTH_BOOKTAB_BuildFamiliesRows()
|
||||
return MTH_BOOKTAB_FamiliesSafeLower(a.name) < MTH_BOOKTAB_FamiliesSafeLower(b.name)
|
||||
end)
|
||||
|
||||
local dietItems = {}
|
||||
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))
|
||||
local dietText = ""
|
||||
if MTH_BOOKTAB_ShouldDisplayAllDiet(familyName) then
|
||||
dietText = "ALL"
|
||||
else
|
||||
local dietItems = {}
|
||||
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
|
||||
table.sort(dietItems, function(a, b)
|
||||
return MTH_BOOKTAB_FamiliesSafeLower(a) < MTH_BOOKTAB_FamiliesSafeLower(b)
|
||||
end)
|
||||
end
|
||||
table.sort(dietItems, function(a, b)
|
||||
return MTH_BOOKTAB_FamiliesSafeLower(a) < MTH_BOOKTAB_FamiliesSafeLower(b)
|
||||
end)
|
||||
dietText = table.concat(dietItems, ", ")
|
||||
end
|
||||
|
||||
table.insert(results, {
|
||||
@@ -159,7 +194,7 @@ function MTH_BOOKTAB_BuildFamiliesRows()
|
||||
named = tonumber(familyRow.named) or 0,
|
||||
coords = tonumber(familyRow.coords) or 0,
|
||||
abilities = abilities,
|
||||
dietText = table.concat(dietItems, ", "),
|
||||
dietText = dietText,
|
||||
})
|
||||
end
|
||||
end
|
||||
@@ -238,7 +273,7 @@ function MTH_BOOKTAB_EnsureFamiliesUI()
|
||||
ui.headerAbilities:SetText("Abilities")
|
||||
|
||||
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:SetText("Diet")
|
||||
|
||||
@@ -270,8 +305,8 @@ function MTH_BOOKTAB_EnsureFamiliesUI()
|
||||
row.coords:SetJustifyH("LEFT")
|
||||
|
||||
row.diet = row:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
||||
row.diet:SetPoint("LEFT", row, "LEFT", 460, 0)
|
||||
row.diet:SetWidth(184)
|
||||
row.diet:SetPoint("LEFT", row, "LEFT", 532, 0)
|
||||
row.diet:SetWidth(112)
|
||||
row.diet:SetJustifyH("LEFT")
|
||||
|
||||
row.abilityButtons = {}
|
||||
@@ -363,6 +398,7 @@ function MTH_BOOKTAB_RenderFamiliesList()
|
||||
rowFrame.diet:SetText(tostring(row.dietText or "-"))
|
||||
|
||||
local offsetX = 232
|
||||
local abilityMaxRight = 526
|
||||
for b = 1, table.getn(rowFrame.abilityButtons) do
|
||||
local button = rowFrame.abilityButtons[b]
|
||||
local ability = row.abilities and row.abilities[b] or nil
|
||||
@@ -375,17 +411,23 @@ function MTH_BOOKTAB_RenderFamiliesList()
|
||||
button.text:SetText(nameText)
|
||||
local textW = button.text:GetStringWidth() or 40
|
||||
if textW < 24 then textW = 24 end
|
||||
button:SetWidth(14 + textW)
|
||||
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)
|
||||
local buttonWidth = 14 + textW
|
||||
if (offsetX + buttonWidth) > abilityMaxRight then
|
||||
button.entry = nil
|
||||
button:Hide()
|
||||
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
|
||||
button:Show()
|
||||
offsetX = offsetX + button:GetWidth() + 6
|
||||
else
|
||||
button.entry = nil
|
||||
button:Hide()
|
||||
|
||||
+82
-20
@@ -55,7 +55,7 @@ local function MTH_BOOK_FamiliesTrace(message)
|
||||
end
|
||||
|
||||
local MTH_BOOK_STATE = {
|
||||
mode = "stable",
|
||||
mode = "pets",
|
||||
search = "",
|
||||
quick = "all",
|
||||
minLevel = nil,
|
||||
@@ -1002,9 +1002,9 @@ end
|
||||
local function MTH_BOOK_ParseProjectileDPSFromText(text)
|
||||
if type(text) ~= "string" or text == "" then return nil end
|
||||
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
|
||||
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
|
||||
if not raw then return nil end
|
||||
local normalized = string.gsub(raw, ",", ".")
|
||||
@@ -1537,13 +1537,75 @@ local function MTH_BOOK_BuildResults()
|
||||
if MTH_BOOK_STATE.mode == "pethistory" then
|
||||
local store = MTH_BOOK_GetPetDatastore()
|
||||
if type(store) ~= "table" or type(store.historyById) ~= "table" then return results end
|
||||
|
||||
local cached = {}
|
||||
for petId, row in pairs(store.historyById) do
|
||||
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
|
||||
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
|
||||
end
|
||||
|
||||
@@ -4379,23 +4441,14 @@ local function MTH_BOOK_LayoutSectionTabs()
|
||||
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 sectionStable then
|
||||
sectionStable:ClearAllPoints()
|
||||
sectionStable:SetPoint("TOPLEFT", tabBar, "TOPLEFT", 0, 0)
|
||||
end
|
||||
sectionPets:ClearAllPoints()
|
||||
sectionPets:SetPoint("TOPLEFT", tabBar, "TOPLEFT", 0, 0)
|
||||
|
||||
sectionPetAbilities:ClearAllPoints()
|
||||
if sectionStable then
|
||||
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)
|
||||
sectionPetAbilities:SetPoint("LEFT", sectionPets, "RIGHT", 2, 0)
|
||||
|
||||
sectionFamilies:ClearAllPoints()
|
||||
sectionFamilies:SetPoint("LEFT", sectionPets, "RIGHT", 2, 0)
|
||||
sectionFamilies:SetPoint("LEFT", sectionPetAbilities, "RIGHT", 2, 0)
|
||||
|
||||
sectionNPCs:ClearAllPoints()
|
||||
sectionNPCs:SetPoint("LEFT", sectionFamilies, "RIGHT", 2, 0)
|
||||
@@ -4409,9 +4462,18 @@ local function MTH_BOOK_LayoutSectionTabs()
|
||||
sectionAmmoBags:ClearAllPoints()
|
||||
sectionAmmoBags:SetPoint("LEFT", sectionProjectiles, "RIGHT", 2, 0)
|
||||
|
||||
if sectionStable then
|
||||
sectionStable:ClearAllPoints()
|
||||
sectionStable:SetPoint("LEFT", sectionAmmoBags, "RIGHT", 2, 0)
|
||||
end
|
||||
|
||||
if sectionPetHistory then
|
||||
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
|
||||
|
||||
|
||||
@@ -198,6 +198,9 @@ local MTH_SPELL_ID_BY_TOKEN = {
|
||||
["Counterattack"] = 19306,
|
||||
["Clever Traps"] = 19239,
|
||||
["Deterrence"] = 19263,
|
||||
["Entrapment"] = 19184,
|
||||
["Entrapment (Rank 2)"] = 19387,
|
||||
["Entrapment (Rank 3)"] = 19388,
|
||||
["Explosive Trap"] = 13813,
|
||||
["Explosive Trap Effect"] = 13812,
|
||||
["Feed Pet"] = 6991,
|
||||
|
||||
+93
-41
@@ -2,7 +2,7 @@ MTH_Map = {
|
||||
enabled = true,
|
||||
showWorld = true,
|
||||
showMinimap = true,
|
||||
activeSource = "beasts",
|
||||
activeSource = "focus",
|
||||
providers = {},
|
||||
nodesByZone = {},
|
||||
worldPins = {},
|
||||
@@ -21,6 +21,10 @@ MTH_Map = {
|
||||
lastWorldReason = "n/a",
|
||||
lastMiniReason = "n/a",
|
||||
nodeRevision = 0,
|
||||
minimapForceRefreshInterval = 1.0,
|
||||
verboseMiniReasons = false,
|
||||
minimapTickActive = 0.20,
|
||||
minimapTickIdle = 0.75,
|
||||
}
|
||||
|
||||
local MTH_MAP_MINIMAP_ZOOM = {
|
||||
@@ -468,7 +472,18 @@ local function MTH_Map_ClearPendingZoneOpen()
|
||||
MTH_Map.pendingZoneOpenNextAttemptAt = 0
|
||||
end
|
||||
|
||||
function MTH_Map:EnsureInitialized()
|
||||
if self.controller then
|
||||
return true
|
||||
end
|
||||
self:Init()
|
||||
return self.controller ~= nil
|
||||
end
|
||||
|
||||
function MTH_Map:SetSource(key)
|
||||
if not self:EnsureInitialized() then
|
||||
return false
|
||||
end
|
||||
if not self.providers[key] then
|
||||
return false
|
||||
end
|
||||
@@ -672,6 +687,9 @@ function MTH_Map:SetEnabled(enabled)
|
||||
if not self.enabled then
|
||||
self:HideAllPins()
|
||||
else
|
||||
if not self:EnsureInitialized() then
|
||||
return
|
||||
end
|
||||
self:UpdateWorldMap()
|
||||
self:UpdateMinimap()
|
||||
end
|
||||
@@ -682,6 +700,9 @@ function MTH_Map:SetWorldEnabled(enabled)
|
||||
if not self.showWorld then
|
||||
self:HideWorldPins()
|
||||
else
|
||||
if not self:EnsureInitialized() then
|
||||
return
|
||||
end
|
||||
self:UpdateWorldMap()
|
||||
end
|
||||
end
|
||||
@@ -691,6 +712,9 @@ function MTH_Map:SetMinimapEnabled(enabled)
|
||||
if not self.showMinimap then
|
||||
self:HideMinimapPins()
|
||||
else
|
||||
if not self:EnsureInitialized() then
|
||||
return
|
||||
end
|
||||
self:UpdateMinimap()
|
||||
end
|
||||
end
|
||||
@@ -952,22 +976,21 @@ function MTH_Map:UpdateMinimap()
|
||||
end
|
||||
|
||||
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._lastMiniState = nil
|
||||
self:HideMinimapPins()
|
||||
return
|
||||
end
|
||||
|
||||
local minimapSizes = MTH_DS_MinimapSizes or (pfDB and pfDB["minimap"])
|
||||
local mapSize = minimapSizes and minimapSizes[mapId]
|
||||
if not mapSize then
|
||||
self.lastMiniReason = "missing-minimap-size"
|
||||
if table.getn(nodes) <= 0 then
|
||||
self.lastMiniReason = "no-nodes-in-zone"
|
||||
self._lastMiniState = nil
|
||||
self:HideMinimapPins()
|
||||
return
|
||||
end
|
||||
|
||||
local now = GetTime() or 0
|
||||
local xPlayer, yPlayer = GetPlayerMapPosition("player")
|
||||
if not xPlayer or not yPlayer or (xPlayer == 0 and yPlayer == 0) then
|
||||
self.lastMiniReason = "player-position-unavailable"
|
||||
@@ -980,10 +1003,33 @@ function MTH_Map:UpdateMinimap()
|
||||
yPlayer = yPlayer * 100
|
||||
|
||||
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 zoomSet = MTH_MAP_MINIMAP_ZOOM[indoor]
|
||||
if not zoomSet then
|
||||
self.lastMiniReason = "missing-zoomset"
|
||||
self.lastMiniReason = self.verboseMiniReasons and "missing-zoomset" or "missing-zoomset"
|
||||
self._lastMiniState = nil
|
||||
self:HideMinimapPins()
|
||||
return
|
||||
@@ -991,7 +1037,7 @@ function MTH_Map:UpdateMinimap()
|
||||
|
||||
local mapZoom = zoomSet[zoom]
|
||||
if not mapZoom then
|
||||
self.lastMiniReason = "missing-mapzoom"
|
||||
self.lastMiniReason = self.verboseMiniReasons and "missing-mapzoom" or "missing-zoom"
|
||||
self._lastMiniState = nil
|
||||
self:HideMinimapPins()
|
||||
return
|
||||
@@ -1000,33 +1046,16 @@ function MTH_Map:UpdateMinimap()
|
||||
local mapWidth = mapSize[1]
|
||||
local mapHeight = mapSize[2]
|
||||
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:HideMinimapPins()
|
||||
return
|
||||
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 yScale = mapZoom / mapHeight
|
||||
local xDraw = Minimap:GetWidth() / xScale / 100
|
||||
local yDraw = Minimap:GetHeight() / yScale / 100
|
||||
|
||||
local nodes = self.nodesByZone[mapId]
|
||||
local shown = 0
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
self._lastMiniState = {
|
||||
mapId = mapId,
|
||||
zoom = zoom,
|
||||
indoor = indoor,
|
||||
xPlayer = xPlayer,
|
||||
yPlayer = yPlayer,
|
||||
nodeRevision = self.nodeRevision or 0,
|
||||
}
|
||||
local lastState = self._lastMiniState or {}
|
||||
lastState.mapId = mapId
|
||||
lastState.zoom = zoom
|
||||
lastState.indoor = indoor
|
||||
lastState.xPlayer = xPlayer
|
||||
lastState.yPlayer = yPlayer
|
||||
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
|
||||
|
||||
function MTH_Map:RegisterDefaultProviders()
|
||||
@@ -1202,9 +1236,12 @@ function MTH_Map:RegisterDefaultProviders()
|
||||
end
|
||||
|
||||
function MTH_Map:Init()
|
||||
if self.controller then
|
||||
return
|
||||
end
|
||||
self:BuildZoneLookup()
|
||||
self:RegisterDefaultProviders()
|
||||
self:RebuildNodes()
|
||||
self.nodesByZone = self.nodesByZone or {}
|
||||
|
||||
if not self.controller then
|
||||
self.controller = CreateFrame("Frame", "MTHMapController", UIParent)
|
||||
@@ -1230,7 +1267,6 @@ function MTH_Map:Init()
|
||||
if not frame then return end
|
||||
local now = GetTime() or 0
|
||||
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.pendingZoneOpenNextAttemptAt or 0) <= now then
|
||||
@@ -1259,12 +1295,28 @@ function MTH_Map:Init()
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
MTH_Map_Log("Map system initialized")
|
||||
end
|
||||
|
||||
MTH_Map:Init()
|
||||
|
||||
@@ -169,10 +169,14 @@ end
|
||||
|
||||
local loader = CreateFrame("Frame", "MTH_MinimapButtonLoader")
|
||||
loader:RegisterEvent("ADDON_LOADED")
|
||||
loader:SetScript("OnEvent", function(_, eventName, addonName)
|
||||
loader:SetScript("OnEvent", function(self, eventName, addonName)
|
||||
eventName = eventName or event
|
||||
addonName = addonName or arg1
|
||||
if eventName == "ADDON_LOADED" and addonName == "MetaHunt" then
|
||||
MTH_MinimapButton:Initialize()
|
||||
if self and self.UnregisterAllEvents then
|
||||
self:UnregisterAllEvents()
|
||||
self:SetScript("OnEvent", nil)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
+19
-9
@@ -44,6 +44,8 @@ local MTH_AB_STATE = {
|
||||
},
|
||||
}
|
||||
|
||||
local MTH_AB_TRANSIENT_STORE = {}
|
||||
|
||||
local function MTH_AB_SetCheckedNoClick(check, checked)
|
||||
if not check then return end
|
||||
MTH_AB_STATE.syncing = true
|
||||
@@ -51,6 +53,14 @@ local function MTH_AB_SetCheckedNoClick(check, checked)
|
||||
MTH_AB_STATE.syncing = false
|
||||
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()
|
||||
return MTH_AutoBuyEngine
|
||||
end
|
||||
@@ -60,8 +70,7 @@ local function MTH_AB_GetStore()
|
||||
if engine and engine.EnsureDefaults then
|
||||
return engine:EnsureDefaults()
|
||||
end
|
||||
MTH_AutoBuy_Saved = MTH_AutoBuy_Saved or {}
|
||||
return MTH_AutoBuy_Saved
|
||||
return MTH_AB_TRANSIENT_STORE
|
||||
end
|
||||
|
||||
local function MTH_AB_NormalizeRule(rule)
|
||||
@@ -91,10 +100,10 @@ end
|
||||
|
||||
local function MTH_AB_EnsureConfig()
|
||||
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.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.stacks == nil then store.petFood.stacks = 1 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 moduleEnabled = true
|
||||
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
|
||||
|
||||
MTH_AB_SetCheckedNoClick(MTH_AB_STATE.controls.moduleEnabled, moduleEnabled)
|
||||
@@ -652,7 +661,7 @@ local function MTH_AB_CreateRow(container, subtype, index, xBase, yOffset)
|
||||
self = self or this
|
||||
if not self or MTH_AB_STATE.syncing then return end
|
||||
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(self))
|
||||
MTH_AB_RefreshOptionsUI()
|
||||
end)
|
||||
end
|
||||
@@ -710,7 +719,7 @@ local function MTH_AB_BuildUI(container)
|
||||
self = self or this
|
||||
if not self or MTH_AB_STATE.syncing then return end
|
||||
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(self))
|
||||
if not ok and MTH and MTH.Print then
|
||||
MTH:Print("Failed to change Auto Buy state: " .. tostring(err), "error")
|
||||
end
|
||||
@@ -725,7 +734,7 @@ local function MTH_AB_BuildUI(container)
|
||||
self = self or this
|
||||
if not self or MTH_AB_STATE.syncing then return end
|
||||
local store = MTH_AB_EnsureConfig()
|
||||
store.projectiles.enabled = self:GetChecked() and true or false
|
||||
store.projectiles.enabled = MTH_AB_IsChecked(self)
|
||||
MTH_AB_RefreshOptionsUI()
|
||||
end)
|
||||
end
|
||||
@@ -764,7 +773,7 @@ local function MTH_AB_BuildUI(container)
|
||||
self = self or this
|
||||
if not self or MTH_AB_STATE.syncing then return end
|
||||
local store = MTH_AB_EnsureConfig()
|
||||
store.petFood.enabled = self:GetChecked() and true or false
|
||||
store.petFood.enabled = MTH_AB_IsChecked(self)
|
||||
MTH_AB_RefreshOptionsUI()
|
||||
end)
|
||||
end
|
||||
@@ -842,6 +851,7 @@ local function MTH_AB_BuildUI(container)
|
||||
text:SetText("")
|
||||
controls.petFoodPetLines[i] = { icon = icon, text = text }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function MTH_SetupAutoBuyOptions()
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
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(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
local enabled = MTH_AQ_IsChecked(self)
|
||||
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
|
||||
self: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(self)
|
||||
self = self or this
|
||||
local enabled = MTH_AQ_IsChecked(self)
|
||||
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(self)
|
||||
self = self or this
|
||||
local enabled = MTH_AQ_IsChecked(self)
|
||||
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(self)
|
||||
self = self or this
|
||||
local enabled = MTH_AQ_IsChecked(self)
|
||||
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
|
||||
+32
-10
@@ -98,11 +98,20 @@ local function MTH_CHRON_CopyTable(source)
|
||||
end
|
||||
|
||||
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)
|
||||
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
|
||||
store.profile = {}
|
||||
end
|
||||
@@ -298,6 +307,14 @@ local function MTH_CHRON_MakeSmall(parent, name, text, x, y)
|
||||
return label
|
||||
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 edit = CreateFrame("EditBox", name, parent, "InputBoxTemplate")
|
||||
@@ -371,11 +388,16 @@ local function MTH_CHRON_RenderTimerSection(container, profile, title, items, bu
|
||||
check:SetScript("OnClick", function(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
if self:GetChecked() then
|
||||
local currentlyDisabled = profile.disabledSpells[bucket][timerName] ~= nil
|
||||
if currentlyDisabled then
|
||||
profile.disabledSpells[bucket][timerName] = nil
|
||||
self:SetChecked(true)
|
||||
else
|
||||
profile.disabledSpells[bucket][timerName] = {}
|
||||
self:SetChecked(nil)
|
||||
end
|
||||
|
||||
MTH_CHRON_ApplyLiveProfile(profile)
|
||||
end)
|
||||
end
|
||||
timerY = timerY - 20
|
||||
@@ -451,7 +473,7 @@ function MTH_SetupChronometerOptions(tabKey)
|
||||
moduleCheck:SetScript("OnClick", function(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
local enabled = self:GetChecked() and true or false
|
||||
local enabled = MTH_CHRON_IsChecked(self)
|
||||
if MTH and MTH.SetModuleEnabled then
|
||||
MTH:SetModuleEnabled("chronometer", enabled)
|
||||
end
|
||||
@@ -476,7 +498,7 @@ function MTH_SetupChronometerOptions(tabKey)
|
||||
killCheck:SetScript("OnClick", function(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
profile.fadeonkill = self:GetChecked() and true or false
|
||||
profile.fadeonkill = MTH_CHRON_IsChecked(self)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -486,7 +508,7 @@ function MTH_SetupChronometerOptions(tabKey)
|
||||
fadeCheck:SetScript("OnClick", function(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
profile.fadeonfade = self:GetChecked() and true or false
|
||||
profile.fadeonfade = MTH_CHRON_IsChecked(self)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -496,7 +518,7 @@ function MTH_SetupChronometerOptions(tabKey)
|
||||
selfCheck:SetScript("OnClick", function(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
profile.selfbars = self:GetChecked() and true or false
|
||||
profile.selfbars = MTH_CHRON_IsChecked(self)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -506,7 +528,7 @@ function MTH_SetupChronometerOptions(tabKey)
|
||||
onlySelfCheck:SetScript("OnClick", function(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
profile.onlyself = self:GetChecked() and true or false
|
||||
profile.onlyself = MTH_CHRON_IsChecked(self)
|
||||
end)
|
||||
end
|
||||
elseif section == "bar" then
|
||||
@@ -591,7 +613,7 @@ function MTH_SetupChronometerOptions(tabKey)
|
||||
growCheck:SetScript("OnClick", function(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
profile.growup = self:GetChecked() and true or false
|
||||
profile.growup = MTH_CHRON_IsChecked(self)
|
||||
MTH_CHRON_ApplyLiveProfile(profile)
|
||||
end)
|
||||
end
|
||||
@@ -602,7 +624,7 @@ function MTH_SetupChronometerOptions(tabKey)
|
||||
reverseCheck:SetScript("OnClick", function(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
profile.reverse = self:GetChecked() and true or false
|
||||
profile.reverse = MTH_CHRON_IsChecked(self)
|
||||
MTH_CHRON_ApplyLiveProfile(profile)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -159,6 +159,16 @@ function MTH_SetupCreditsOptions()
|
||||
cursor,
|
||||
-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,
|
||||
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)
|
||||
|
||||
@@ -0,0 +1,598 @@
|
||||
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(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
if MTH and MTH.SetModuleEnabled then
|
||||
local ok, err = MTH:SetModuleEnabled("icu", self: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(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
local store = MTH_ICU_GetStore()
|
||||
store.mouseOver = self: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(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
local store = MTH_ICU_GetStore()
|
||||
store.EXPAND_UP = self: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(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
local store = MTH_ICU_GetStore()
|
||||
store.SHOW_GUILD_NAME = self: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(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
local store = MTH_ICU_GetStore()
|
||||
store.SHOW_PLAYER_CLASS = self: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(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
local store = MTH_ICU_GetStore()
|
||||
store.SHOW_PLAYER_RACE = self: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(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
local store = MTH_ICU_GetStore()
|
||||
store.SHOW_CUSTOM_TITLES = self: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(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
local store = MTH_ICU_GetStore()
|
||||
store.REACTION_ONLY_PVP_PLAYERS = self: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
|
||||
@@ -195,6 +195,21 @@ function MTH_SelectOptionsTab(tabKey)
|
||||
else
|
||||
MTH_SetupAutoBuyOptions()
|
||||
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
|
||||
local setupCredits = _G and _G["MTH_SetupCreditsOptions"]
|
||||
if type(setupCredits) == "function" then
|
||||
|
||||
@@ -41,6 +41,8 @@ MTH_OPTIONS_TABS = MTH_OPTIONS_TABS or {
|
||||
{ key = "SmartAmmo", label = "Smart Ammo", frame = "MetaHuntOptionsSmartAmmo" },
|
||||
{ key = "FeedOMatic", label = "FeedOMatic", frame = "MetaHuntOptionsFeedOMatic" },
|
||||
{ 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 = "ChronometerBar", label = "Bar", 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 = "Messages", key = "Messages" },
|
||||
{ label = "Auto Buy", key = "AutoBuy" },
|
||||
{ label = "Auto Quest", key = "AutoQuest" },
|
||||
{ label = "Feed-O-Matic", key = "FeedOMatic" },
|
||||
{ label = "ICU", key = "ICU" },
|
||||
{
|
||||
label = "zButtons",
|
||||
node = "zButtons",
|
||||
|
||||
+52
-28
@@ -21,6 +21,14 @@ local function MTH_ZB_RefreshTab(tabName)
|
||||
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)
|
||||
if not (buttonName and buttonObj and itemList and maxButtons) then return end
|
||||
local info = {}
|
||||
@@ -328,7 +336,7 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
|
||||
enableButton:SetScript("OnClick", function(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
local checked = self:GetChecked() and true or false
|
||||
local checked = MTH_ZB_IsChecked(self)
|
||||
MTH_SetButtonEnabledState(self.buttonName, self.buttonObj, checked)
|
||||
end)
|
||||
end
|
||||
@@ -387,7 +395,7 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
|
||||
expandLeft:SetScript("OnClick", function(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
local checked = self:GetChecked() and true or false
|
||||
local checked = MTH_ZB_IsChecked(self)
|
||||
local btnName = self.buttonName
|
||||
if not btnName or not (ZHunterMod_Saved and ZHunterMod_Saved[btnName]) then return end
|
||||
ZHunterMod_Saved[btnName]["firstbutton"] = checked and "LEFT" or "RIGHT"
|
||||
@@ -409,7 +417,7 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
|
||||
hideClick:SetScript("OnClick", function(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
local checked = self:GetChecked() and true or false
|
||||
local checked = MTH_ZB_IsChecked(self)
|
||||
ZHunterMod_Saved[self.buttonName]["children"]["hideonclick"] = checked
|
||||
local btnObj = self.buttonObj or getglobal(self.buttonName)
|
||||
if btnObj then btnObj.hideonclick = checked end
|
||||
@@ -428,7 +436,7 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
|
||||
showTooltip:SetScript("OnClick", function(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
local checked = self:GetChecked() and true or false
|
||||
local checked = MTH_ZB_IsChecked(self)
|
||||
ZHunterMod_Saved[self.buttonName]["tooltip"] = checked
|
||||
local btnObj = self.buttonObj or getglobal(self.buttonName)
|
||||
if btnObj then btnObj.tooltip = checked end
|
||||
@@ -446,7 +454,7 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
|
||||
showAmmoName:SetScript("OnClick", function(self)
|
||||
self = self or this
|
||||
if not self then return end
|
||||
local checked = self:GetChecked() and true or false
|
||||
local checked = MTH_ZB_IsChecked(self)
|
||||
local btnName = self.buttonName
|
||||
ZHunterMod_Saved[btnName]["showammoname"] = checked
|
||||
local btnObj = self.buttonObj or getglobal(btnName)
|
||||
@@ -745,7 +753,7 @@ function MTH_SetupSmartAmmoOptions()
|
||||
self = self or this
|
||||
if not self then return end
|
||||
if MTH and MTH.SetModuleEnabled then
|
||||
MTH:SetModuleEnabled("smartammo", self:GetChecked() and true or false)
|
||||
MTH:SetModuleEnabled("smartammo", MTH_ZB_IsChecked(self))
|
||||
end
|
||||
MTH_SetupSmartAmmoOptions()
|
||||
end)
|
||||
@@ -762,7 +770,7 @@ function MTH_SetupSmartAmmoOptions()
|
||||
self = self or this
|
||||
if not self then return end
|
||||
if type(MTHSmartAmmo_SetSmartEnabled) == "function" then
|
||||
MTHSmartAmmo_SetSmartEnabled(self:GetChecked() and 1 or nil)
|
||||
MTHSmartAmmo_SetSmartEnabled(MTH_ZB_IsChecked(self) and 1 or nil)
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -781,7 +789,7 @@ function MTH_SetupSmartAmmoOptions()
|
||||
self = self or this
|
||||
if not self then return end
|
||||
if type(MTHSmartAmmo_SetReloadEnabled) == "function" then
|
||||
MTHSmartAmmo_SetReloadEnabled(self:GetChecked() and 1 or nil)
|
||||
MTHSmartAmmo_SetReloadEnabled(MTH_ZB_IsChecked(self) and 1 or nil)
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -821,7 +829,7 @@ function MTH_SetupMessagesOptions()
|
||||
self = self or this
|
||||
if not self then return end
|
||||
if MTH and MTH.SetMessageEnabled then
|
||||
MTH:SetMessageEnabled("initModulesLoaded", self:GetChecked() and true or false)
|
||||
MTH:SetMessageEnabled("initModulesLoaded", MTH_ZB_IsChecked(self))
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -833,7 +841,7 @@ function MTH_SetupMessagesOptions()
|
||||
self = self or this
|
||||
if not self then return end
|
||||
if MTH and MTH.SetMessageEnabled then
|
||||
MTH:SetMessageEnabled("initSarcasticWelcome", self:GetChecked() and true or false)
|
||||
MTH:SetMessageEnabled("initSarcasticWelcome", MTH_ZB_IsChecked(self))
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -845,7 +853,7 @@ function MTH_SetupMessagesOptions()
|
||||
self = self or this
|
||||
if not self then return end
|
||||
if MTH and MTH.SetMessageEnabled then
|
||||
MTH:SetMessageEnabled("petHungry", self:GetChecked() and true or false)
|
||||
MTH:SetMessageEnabled("petHungry", MTH_ZB_IsChecked(self))
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -857,7 +865,7 @@ function MTH_SetupMessagesOptions()
|
||||
self = self or this
|
||||
if not self then return end
|
||||
if MTH and MTH.SetMessageEnabled then
|
||||
MTH:SetMessageEnabled("beastTrainingScan", self:GetChecked() and true or false)
|
||||
MTH:SetMessageEnabled("beastTrainingScan", MTH_ZB_IsChecked(self))
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -869,7 +877,7 @@ function MTH_SetupMessagesOptions()
|
||||
self = self or this
|
||||
if not self then return end
|
||||
if MTH and MTH.SetMessageEnabled then
|
||||
MTH:SetMessageEnabled("spellbookScan", self:GetChecked() and true or false)
|
||||
MTH:SetMessageEnabled("spellbookScan", MTH_ZB_IsChecked(self))
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -881,7 +889,7 @@ function MTH_SetupMessagesOptions()
|
||||
self = self or this
|
||||
if not self then return end
|
||||
if MTH and MTH.SetMessageEnabled then
|
||||
MTH:SetMessageEnabled("petRanAway", self:GetChecked() and true or false)
|
||||
MTH:SetMessageEnabled("petRanAway", MTH_ZB_IsChecked(self))
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -893,7 +901,7 @@ function MTH_SetupMessagesOptions()
|
||||
self = self or this
|
||||
if not self then return end
|
||||
if MTH and MTH.SetMessageEnabled then
|
||||
MTH:SetMessageEnabled("mapMarkers", self:GetChecked() and true or false)
|
||||
MTH:SetMessageEnabled("mapMarkers", MTH_ZB_IsChecked(self))
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -1002,7 +1010,7 @@ function MTH_SetupGeneralOptions()
|
||||
local smartModuleToggle = ensureCheckbox(smartAmmoSection, "MetaHuntGeneralSmartAmmoModuleToggle", "Enable module", -10, smartModuleEnabled)
|
||||
if smartModuleToggle then
|
||||
smartModuleToggle:SetScript("OnClick", function()
|
||||
local enabled = this:GetChecked() and true or false
|
||||
local enabled = MTH_ZB_IsChecked(this)
|
||||
if MTH and MTH.SetModuleEnabled then
|
||||
local ok = MTH:SetModuleEnabled("smartammo", enabled)
|
||||
if not ok then
|
||||
@@ -1031,7 +1039,7 @@ function MTH_SetupGeneralOptions()
|
||||
end
|
||||
smartToggle:SetScript("OnClick", function()
|
||||
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
|
||||
@@ -1045,7 +1053,7 @@ function MTH_SetupGeneralOptions()
|
||||
end
|
||||
reloadToggle:SetScript("OnClick", function()
|
||||
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
|
||||
@@ -1059,7 +1067,7 @@ function MTH_SetupGeneralOptions()
|
||||
end
|
||||
weaponSwapToggle:SetScript("OnClick", function()
|
||||
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
|
||||
@@ -1072,7 +1080,7 @@ function MTH_SetupGeneralOptions()
|
||||
if autoStripToggle then
|
||||
autoStripToggle:SetScript("OnClick", function()
|
||||
if type(AutoStrip_SetAutoStripToggle) == "function" then
|
||||
AutoStrip_SetAutoStripToggle(this:GetChecked())
|
||||
AutoStrip_SetAutoStripToggle(MTH_ZB_IsChecked(this))
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -1081,7 +1089,7 @@ function MTH_SetupGeneralOptions()
|
||||
if displayToggle then
|
||||
displayToggle:SetScript("OnClick", function()
|
||||
if type(AutoStrip_SetDisplayToggle) == "function" then
|
||||
AutoStrip_SetDisplayToggle(this:GetChecked())
|
||||
AutoStrip_SetDisplayToggle(MTH_ZB_IsChecked(this))
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -1095,7 +1103,7 @@ function MTH_SetupGeneralOptions()
|
||||
local antiToggle = ensureCheckbox(antiSection, "MetaHuntGeneralAntiDazeToggle", "Enable Anti-Daze", -10, antiDazeEnabled)
|
||||
if antiToggle then
|
||||
antiToggle:SetScript("OnClick", function()
|
||||
local enabled = this:GetChecked() and true or false
|
||||
local enabled = MTH_ZB_IsChecked(this)
|
||||
if type(AntiDaze_SetEnabled) == "function" then
|
||||
AntiDaze_SetEnabled(enabled, 1)
|
||||
end
|
||||
@@ -1114,10 +1122,26 @@ function MTH_SetupGeneralOptions()
|
||||
|
||||
local tooltipsSection = ensureSection("MetaHuntGeneralTooltipsBox", "Tooltips", topY, 356, "right")
|
||||
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
|
||||
tooltipsStore = {}
|
||||
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
|
||||
tooltipsStore.beastTooltips = true
|
||||
end
|
||||
@@ -1142,7 +1166,7 @@ function MTH_SetupGeneralOptions()
|
||||
local moduleToggle = ensureCheckbox(tooltipsSection, "MetaHuntGeneralTooltipsModuleToggle", "Enable module", -10, moduleEnabled)
|
||||
if moduleToggle then
|
||||
moduleToggle:SetScript("OnClick", function()
|
||||
local enabled = this:GetChecked() and true or false
|
||||
local enabled = MTH_ZB_IsChecked(this)
|
||||
if MTH and MTH.SetModuleEnabled then
|
||||
local ok = MTH:SetModuleEnabled("tooltips", enabled)
|
||||
if not ok then
|
||||
@@ -1159,7 +1183,7 @@ function MTH_SetupGeneralOptions()
|
||||
local beastToggle = ensureCheckbox(tooltipsSection, "MetaHuntGeneralTooltipsBeastToggle", "Activate on Beasts", -86, tooltipsStore.beastTooltips and true or false)
|
||||
if beastToggle then
|
||||
beastToggle:SetScript("OnClick", function()
|
||||
local enabled = this:GetChecked() and true or false
|
||||
local enabled = MTH_ZB_IsChecked(this)
|
||||
tooltipsStore.beastTooltips = enabled
|
||||
local tooltipsModule = MTH and MTH.GetModule and MTH:GetModule("tooltips")
|
||||
if tooltipsModule and tooltipsModule.SetBeastTooltipsEnabled then
|
||||
@@ -1175,7 +1199,7 @@ function MTH_SetupGeneralOptions()
|
||||
local ownPetToggle = ensureCheckbox(tooltipsSection, "MetaHuntGeneralTooltipsOwnPetToggle", ownPetLabel, -158, tooltipsStore.ownPetTooltips and true or false)
|
||||
if ownPetToggle then
|
||||
ownPetToggle:SetScript("OnClick", function()
|
||||
local enabled = this:GetChecked() and true or false
|
||||
local enabled = MTH_ZB_IsChecked(this)
|
||||
tooltipsStore.ownPetTooltips = enabled
|
||||
local tooltipsModule = MTH and MTH.GetModule and MTH:GetModule("tooltips")
|
||||
if tooltipsModule and tooltipsModule.SetOwnPetTooltipsEnabled then
|
||||
@@ -1189,7 +1213,7 @@ function MTH_SetupGeneralOptions()
|
||||
local ammoToggle = ensureCheckbox(tooltipsSection, "MetaHuntGeneralTooltipsAmmoVendorToggle", "Activate on Vendors", -222, tooltipsStore.ammoVendorTooltips and true or false)
|
||||
if ammoToggle then
|
||||
ammoToggle:SetScript("OnClick", function()
|
||||
local enabled = this:GetChecked() and true or false
|
||||
local enabled = MTH_ZB_IsChecked(this)
|
||||
tooltipsStore.ammoVendorTooltips = enabled
|
||||
local tooltipsModule = MTH and MTH.GetModule and MTH:GetModule("tooltips")
|
||||
if tooltipsModule and tooltipsModule.SetAmmoVendorTooltipsEnabled then
|
||||
@@ -1203,7 +1227,7 @@ function MTH_SetupGeneralOptions()
|
||||
local foodToggle = ensureCheckbox(tooltipsSection, "MetaHuntGeneralTooltipsFoodToggle", foodLabel, -274, tooltipsStore.foodItemTooltips and true or false)
|
||||
if foodToggle then
|
||||
foodToggle:SetScript("OnClick", function()
|
||||
local enabled = this:GetChecked() and true or false
|
||||
local enabled = MTH_ZB_IsChecked(this)
|
||||
tooltipsStore.foodItemTooltips = enabled
|
||||
local tooltipsModule = MTH and MTH.GetModule and MTH:GetModule("tooltips")
|
||||
if tooltipsModule and tooltipsModule.SetFoodItemTooltipsEnabled then
|
||||
|
||||
@@ -79,6 +79,8 @@
|
||||
<Frame name="$parentSmartAmmo" hidden="true" enableMouse="true"/>
|
||||
<Frame name="$parentFeedOMatic" 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="$parentCredits" hidden="true" enableMouse="true"/>
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
+170
-6
@@ -4,10 +4,13 @@ MTH.VersionCheck = MTH.VersionCheck or {}
|
||||
local VC = MTH.VersionCheck
|
||||
VC.abbrev = "MTH"
|
||||
VC.channelName = "LFT"
|
||||
VC.updateUrl = "https://github.com/DuvelCorp/MetaHunt"
|
||||
VC.nextPublishAt = nil
|
||||
VC.joinAt = nil
|
||||
VC.notified = false
|
||||
VC._invalidVersionWarned = false
|
||||
VC.maxPersistedPeers = 200
|
||||
VC.seenPeers = VC.seenPeers or {}
|
||||
|
||||
local function VC_GetTimeNow()
|
||||
if type(time) == "function" then
|
||||
@@ -63,6 +66,158 @@ local function VC_IsOurChannel(name)
|
||||
return type(name) == "string" and string.lower(name) == string.lower(VC.channelName)
|
||||
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()
|
||||
self.nextPublishAt = VC_GetTimeNow() + math.random(10, 20)
|
||||
end
|
||||
@@ -96,13 +251,11 @@ function VC:TryPublish()
|
||||
end
|
||||
|
||||
function VC:HandleRemoteMessage(message, author, channelLabel)
|
||||
if self.notified then
|
||||
return
|
||||
end
|
||||
if not message or message == "" then
|
||||
return
|
||||
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
|
||||
end
|
||||
local channelName = string.gsub(tostring(channelLabel or ""), "^%d+%.%s*", "")
|
||||
@@ -121,6 +274,12 @@ function VC:HandleRemoteMessage(message, author, channelLabel)
|
||||
if not remoteNumber or remoteNumber <= 0 then
|
||||
return
|
||||
end
|
||||
|
||||
self:TrackPeer(normalizedAuthor or author, remoteNumber)
|
||||
|
||||
if self.notified then
|
||||
return
|
||||
end
|
||||
local localVersionNumber = self:GetLocalVersionNumber()
|
||||
if not localVersionNumber or localVersionNumber <= 0 then
|
||||
return
|
||||
@@ -132,11 +291,15 @@ function VC:HandleRemoteMessage(message, author, channelLabel)
|
||||
self.notified = true
|
||||
self.nextPublishAt = nil
|
||||
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
|
||||
|
||||
if VC.frame then
|
||||
VC.frame:UnregisterEvent("CHAT_MSG_CHANNEL")
|
||||
VC.frame:SetScript("OnUpdate", nil)
|
||||
end
|
||||
end
|
||||
@@ -149,6 +312,7 @@ if not VC.frame then
|
||||
frame:RegisterEvent("CHAT_MSG_CHANNEL")
|
||||
frame:SetScript("OnEvent", function()
|
||||
if event == "PLAYER_ENTERING_WORLD" then
|
||||
VC:LoadPersistedPeers()
|
||||
VC.joinAt = GetTime() + 6
|
||||
VC:ResetPublishDelay()
|
||||
elseif event == "CHAT_MSG_CHANNEL" then
|
||||
|
||||
@@ -13,8 +13,10 @@ MTH_DS_Families = {
|
||||
"fungus",
|
||||
},
|
||||
["abilities"] = {
|
||||
"Bite",
|
||||
"Cower",
|
||||
"Dive",
|
||||
"Growl",
|
||||
"Screech",
|
||||
},
|
||||
},
|
||||
@@ -23,14 +25,17 @@ MTH_DS_Families = {
|
||||
["coords"] = 45,
|
||||
["food"] = {
|
||||
"meat",
|
||||
"fruit",
|
||||
"fish",
|
||||
"fungus",
|
||||
"cheese",
|
||||
"bread",
|
||||
"cheese",
|
||||
"fruit",
|
||||
"fungus",
|
||||
},
|
||||
["abilities"] = {
|
||||
"Bite",
|
||||
"Claw",
|
||||
"Cower",
|
||||
"Growl",
|
||||
"Roar of Fortitude",
|
||||
},
|
||||
},
|
||||
@@ -39,15 +44,18 @@ MTH_DS_Families = {
|
||||
["coords"] = 87,
|
||||
["food"] = {
|
||||
"meat",
|
||||
"fruit",
|
||||
"fish",
|
||||
"fungus",
|
||||
"cheese",
|
||||
"bread",
|
||||
"cheese",
|
||||
"fruit",
|
||||
"fungus",
|
||||
},
|
||||
["abilities"] = {
|
||||
"Bite",
|
||||
"Charge",
|
||||
"Cower",
|
||||
"Dash",
|
||||
"Growl",
|
||||
},
|
||||
},
|
||||
["Carrion Birds"] = {
|
||||
@@ -57,7 +65,11 @@ MTH_DS_Families = {
|
||||
"meat",
|
||||
},
|
||||
["abilities"] = {
|
||||
"Bite",
|
||||
"Claw",
|
||||
"Cower",
|
||||
"Dive",
|
||||
"Growl",
|
||||
"Screech",
|
||||
},
|
||||
},
|
||||
@@ -69,9 +81,11 @@ MTH_DS_Families = {
|
||||
"fish",
|
||||
},
|
||||
["abilities"] = {
|
||||
"Bite",
|
||||
"Claw",
|
||||
"Cower",
|
||||
"Dash",
|
||||
"Growl",
|
||||
"Prowl",
|
||||
},
|
||||
},
|
||||
@@ -87,6 +101,8 @@ MTH_DS_Families = {
|
||||
["abilities"] = {
|
||||
"Bubble Barrier",
|
||||
"Claw",
|
||||
"Cower",
|
||||
"Growl",
|
||||
},
|
||||
},
|
||||
["Crocolisks"] = {
|
||||
@@ -97,10 +113,10 @@ MTH_DS_Families = {
|
||||
"fish",
|
||||
},
|
||||
["abilities"] = {
|
||||
"BIte",
|
||||
"Bite",
|
||||
"Claw",
|
||||
"Cower",
|
||||
"Death Roll",
|
||||
"Growl",
|
||||
},
|
||||
},
|
||||
["Foxes"] = {
|
||||
@@ -112,7 +128,10 @@ MTH_DS_Families = {
|
||||
},
|
||||
["abilities"] = {
|
||||
"Bite",
|
||||
"Cower",
|
||||
"Dash",
|
||||
"Grace",
|
||||
"Growl",
|
||||
},
|
||||
},
|
||||
["Gorillas"] = {
|
||||
@@ -123,6 +142,9 @@ MTH_DS_Families = {
|
||||
"fungus",
|
||||
},
|
||||
["abilities"] = {
|
||||
"Bite",
|
||||
"Cower",
|
||||
"Growl",
|
||||
"Thunderstomp",
|
||||
},
|
||||
},
|
||||
@@ -135,7 +157,9 @@ MTH_DS_Families = {
|
||||
},
|
||||
["abilities"] = {
|
||||
"Bite",
|
||||
"Cower",
|
||||
"Dash",
|
||||
"Growl",
|
||||
"Packleader",
|
||||
},
|
||||
},
|
||||
@@ -147,7 +171,9 @@ MTH_DS_Families = {
|
||||
},
|
||||
["abilities"] = {
|
||||
"Claw",
|
||||
"Cower",
|
||||
"Dive",
|
||||
"Growl",
|
||||
"Screech",
|
||||
},
|
||||
},
|
||||
@@ -158,6 +184,11 @@ MTH_DS_Families = {
|
||||
"meat",
|
||||
},
|
||||
["abilities"] = {
|
||||
"Bite",
|
||||
"Claw",
|
||||
"Cower",
|
||||
"Dash",
|
||||
"Growl",
|
||||
"Savage Rend",
|
||||
},
|
||||
},
|
||||
@@ -169,6 +200,8 @@ MTH_DS_Families = {
|
||||
},
|
||||
["abilities"] = {
|
||||
"Claw",
|
||||
"Cower",
|
||||
"Growl",
|
||||
"Scorpid Poison",
|
||||
},
|
||||
},
|
||||
@@ -181,6 +214,8 @@ MTH_DS_Families = {
|
||||
},
|
||||
["abilities"] = {
|
||||
"Bite",
|
||||
"Cower",
|
||||
"Growl",
|
||||
"Poison Spit",
|
||||
},
|
||||
},
|
||||
@@ -192,6 +227,8 @@ MTH_DS_Families = {
|
||||
},
|
||||
["abilities"] = {
|
||||
"Bite",
|
||||
"Cower",
|
||||
"Growl",
|
||||
"Web",
|
||||
},
|
||||
},
|
||||
@@ -206,6 +243,8 @@ MTH_DS_Families = {
|
||||
["abilities"] = {
|
||||
"Bite",
|
||||
"Cower",
|
||||
"Dash",
|
||||
"Growl",
|
||||
"Strider Presence",
|
||||
},
|
||||
},
|
||||
@@ -219,6 +258,8 @@ MTH_DS_Families = {
|
||||
},
|
||||
["abilities"] = {
|
||||
"Bite",
|
||||
"Cower",
|
||||
"Growl",
|
||||
"Shell Shield",
|
||||
},
|
||||
},
|
||||
@@ -231,7 +272,10 @@ MTH_DS_Families = {
|
||||
"bread",
|
||||
},
|
||||
["abilities"] = {
|
||||
"Bite",
|
||||
"Cower",
|
||||
"Dive",
|
||||
"Growl",
|
||||
"Lightning Breath",
|
||||
},
|
||||
},
|
||||
@@ -243,8 +287,10 @@ MTH_DS_Families = {
|
||||
},
|
||||
["abilities"] = {
|
||||
"Bite",
|
||||
"Cower",
|
||||
"Dash",
|
||||
"Furious Howl",
|
||||
"Growl",
|
||||
},
|
||||
},
|
||||
}
|
||||
+14
-12
@@ -1355,14 +1355,15 @@ MTH_DS_PetSpells = {
|
||||
{
|
||||
["ability"] = "Roar of Fortitude",
|
||||
["castTime"] = "Instant",
|
||||
["categoryCooldown"] = "180 seconds",
|
||||
["cooldown"] = "n/a",
|
||||
["cost"] = "None",
|
||||
["description"] = "Increases max hitpoints of allies in your party by 200 for 120 sec",
|
||||
["categoryCooldown"] = "n/a",
|
||||
["cooldown"] = "120 seconds",
|
||||
["cost"] = "50 mana",
|
||||
["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"] = {
|
||||
"(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,
|
||||
["name"] = "Roar of Fortitude",
|
||||
["range"] = "0 yards (Self Only)",
|
||||
@@ -3245,14 +3246,15 @@ MTH_DS_PetSpells = {
|
||||
{
|
||||
["ability"] = "Roar of Fortitude",
|
||||
["castTime"] = "Instant",
|
||||
["categoryCooldown"] = "180 seconds",
|
||||
["cooldown"] = "n/a",
|
||||
["cost"] = "None",
|
||||
["description"] = "Increases max hitpoints of allies in your party by 200 for 120 sec",
|
||||
["categoryCooldown"] = "n/a",
|
||||
["cooldown"] = "120 seconds",
|
||||
["cost"] = "50 mana",
|
||||
["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"] = {
|
||||
"(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,
|
||||
["name"] = "Roar of Fortitude",
|
||||
["range"] = "0 yards (Self Only)",
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
<Include file="..\api\options-chronometer.lua"/>
|
||||
<Include file="..\api\options-credits.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-zbuttons.lua"/>
|
||||
<Include file="..\api\options-feedomatic.lua"/>
|
||||
@@ -30,6 +32,10 @@
|
||||
<Include file="..\api\map-markers.lua"/>
|
||||
<Include file="..\api\core-framework.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-spellbookpet.lua"/>
|
||||
<Include file="..\api\core.lua"/>
|
||||
|
||||
@@ -20,4 +20,10 @@ MetaHunt Module Loader
|
||||
|
||||
<!-- AutoBuy Module - ENABLED -->
|
||||
<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>
|
||||
|
||||
+69
-11
@@ -9,6 +9,10 @@ local Engine = MTH_AutoBuyEngine
|
||||
local AB_AMMO_BY_NAME = nil
|
||||
local AB_FOOD_DIET_BY_ITEM_ID = nil
|
||||
|
||||
local function AB_Trace(message)
|
||||
return
|
||||
end
|
||||
|
||||
local function AB_ParseItemIdFromLink(link)
|
||||
if type(link) ~= "string" then
|
||||
return nil
|
||||
@@ -589,21 +593,46 @@ local function AB_EnsureRuleList(bucket)
|
||||
return bucket
|
||||
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()
|
||||
if MTH and MTH.GetModuleSavedVariables then
|
||||
local store = MTH:GetModuleSavedVariables("autobuy")
|
||||
if type(store) == "table" then
|
||||
return store
|
||||
if MTH and MTH.GetModuleCharSavedVariables then
|
||||
local charStore = MTH:GetModuleCharSavedVariables("autobuy")
|
||||
if type(charStore) == "table" then
|
||||
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
|
||||
MTH_AutoBuy_Saved = MTH_AutoBuy_Saved or {}
|
||||
return MTH_AutoBuy_Saved
|
||||
if MTH and MTH.GetModuleSavedVariables then
|
||||
local accountStore = MTH:GetModuleSavedVariables("autobuy")
|
||||
if type(accountStore) == "table" then
|
||||
return accountStore
|
||||
end
|
||||
end
|
||||
self._transientStore = self._transientStore or {}
|
||||
return self._transientStore
|
||||
end
|
||||
|
||||
function Engine:EnsureDefaults()
|
||||
local store = self:GetConfigStore()
|
||||
if store.enabled == nil then
|
||||
store.enabled = true
|
||||
store.enabled = false
|
||||
end
|
||||
if type(store.food) ~= "table" then
|
||||
store.food = {}
|
||||
@@ -618,13 +647,13 @@ function Engine:EnsureDefaults()
|
||||
store.petFood = {}
|
||||
end
|
||||
if store.food.enabled == nil then
|
||||
store.food.enabled = true
|
||||
store.food.enabled = false
|
||||
end
|
||||
if store.ammo.enabled == nil then
|
||||
store.ammo.enabled = true
|
||||
store.ammo.enabled = false
|
||||
end
|
||||
if store.projectiles.enabled == nil then
|
||||
store.projectiles.enabled = true
|
||||
store.projectiles.enabled = false
|
||||
end
|
||||
if store.petFood.enabled == nil then
|
||||
store.petFood.enabled = false
|
||||
@@ -1151,6 +1180,7 @@ end
|
||||
|
||||
function Engine:ExecutePlan(plan)
|
||||
if type(plan) ~= "table" or type(plan.actions) ~= "table" then
|
||||
AB_Trace("ExecutePlan skipped: invalid plan table")
|
||||
return 0, 0
|
||||
end
|
||||
local executedActions = 0
|
||||
@@ -1159,6 +1189,10 @@ function Engine:ExecutePlan(plan)
|
||||
if type(action) == "table" and action.index then
|
||||
local stacksToBuy = math.floor(tonumber(action.quantityStacks) or 0)
|
||||
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
|
||||
BuyMerchantItem(action.index)
|
||||
end
|
||||
@@ -1167,6 +1201,7 @@ function Engine:ExecutePlan(plan)
|
||||
end
|
||||
end
|
||||
end
|
||||
AB_Trace("ExecutePlan done actions=" .. tostring(executedActions) .. " stacks=" .. tostring(requestedStacks) .. " reason=" .. tostring(plan.reason or ""))
|
||||
return executedActions, requestedStacks
|
||||
end
|
||||
|
||||
@@ -1229,24 +1264,42 @@ local function AB_AnnouncePurchases(actions)
|
||||
end
|
||||
|
||||
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
|
||||
self._merchantSessionExecuted = false
|
||||
AB_Trace("MERCHANT_SHOW resets session execution flag")
|
||||
elseif eventName == "MERCHANT_UPDATE" and self._merchantSessionExecuted then
|
||||
AB_Trace("MERCHANT_UPDATE ignored: already executed this merchant session")
|
||||
return
|
||||
end
|
||||
|
||||
if not self:IsEnabled() then
|
||||
AB_Trace("event ignored: autobuy module disabled")
|
||||
return
|
||||
end
|
||||
|
||||
local snapshot = self:ScanMerchant()
|
||||
AB_Trace("snapshot rows=" .. tostring(snapshot and snapshot.count or 0))
|
||||
local foodPlan = self:BuildFoodPlan(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
|
||||
if table.getn(foodPlan.actions or {}) > 0 then
|
||||
local _, requestedStacks = self:ExecutePlan(foodPlan)
|
||||
totalRequestedStacks = totalRequestedStacks + requestedStacks
|
||||
AB_Trace("food plan executed requestedStacks=" .. tostring(requestedStacks))
|
||||
if requestedStacks > 0 then
|
||||
AB_AnnouncePurchases(foodPlan.actions)
|
||||
end
|
||||
@@ -1255,14 +1308,19 @@ function Engine:OnMerchantEvent(eventName)
|
||||
if table.getn(ammoPlan.actions or {}) > 0 then
|
||||
local _, requestedStacks = self:ExecutePlan(ammoPlan)
|
||||
totalRequestedStacks = totalRequestedStacks + requestedStacks
|
||||
AB_Trace("ammo plan executed requestedStacks=" .. tostring(requestedStacks))
|
||||
if requestedStacks > 0 then
|
||||
AB_MoveAmmoStacksToSpecialBags(300)
|
||||
local moved = AB_MoveAmmoStacksToSpecialBags(300)
|
||||
AB_Trace("ammo restack moved=" .. tostring(moved))
|
||||
AB_AnnouncePurchases(ammoPlan.actions)
|
||||
end
|
||||
end
|
||||
|
||||
if totalRequestedStacks > 0 then
|
||||
self._merchantSessionExecuted = true
|
||||
AB_Trace("session marked executed requestedStacks=" .. tostring(totalRequestedStacks))
|
||||
else
|
||||
AB_Trace("no purchases requested in this event")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
+32
-13
@@ -6,7 +6,7 @@
|
||||
local MTH_AutoBuy = {
|
||||
name = "autobuy",
|
||||
enabled = false,
|
||||
version = "1.0.4",
|
||||
version = "1.1.0",
|
||||
events = {
|
||||
"VARIABLES_LOADED",
|
||||
"MERCHANT_SHOW",
|
||||
@@ -39,7 +39,6 @@ local function AB_EnsureBridgeFrame(moduleRef)
|
||||
return nil
|
||||
end
|
||||
|
||||
frame:RegisterEvent("VARIABLES_LOADED")
|
||||
frame:RegisterEvent("MERCHANT_SHOW")
|
||||
frame:RegisterEvent("MERCHANT_UPDATE")
|
||||
frame:RegisterEvent("MERCHANT_CLOSED")
|
||||
@@ -51,14 +50,6 @@ local function AB_EnsureBridgeFrame(moduleRef)
|
||||
return
|
||||
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
|
||||
AB_Trace("bridge " .. tostring(eventName) .. " -> engine")
|
||||
engine:OnMerchantEvent(eventName)
|
||||
@@ -75,6 +66,34 @@ local function AB_EnsureBridgeFrame(moduleRef)
|
||||
return frame
|
||||
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()
|
||||
return MTH_AutoBuyEngine
|
||||
end
|
||||
@@ -87,8 +106,8 @@ function MTH_AutoBuy:init()
|
||||
return
|
||||
end
|
||||
engine:Init()
|
||||
AB_EnsureBridgeFrame(self)
|
||||
self.initialized = true
|
||||
AB_SetBridgeActive(self.enabled and true or false)
|
||||
AB_Trace("init done")
|
||||
if self.enabled then
|
||||
AB_Log("module initialized", "debug")
|
||||
@@ -106,7 +125,7 @@ function MTH_AutoBuy:setEnabled(enabled)
|
||||
end
|
||||
local store = engine:EnsureDefaults()
|
||||
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))
|
||||
end
|
||||
|
||||
@@ -125,7 +144,7 @@ function MTH_AutoBuy:onEvent(event)
|
||||
|
||||
if event == "VARIABLES_LOADED" then
|
||||
engine:Init()
|
||||
AB_EnsureBridgeFrame(self)
|
||||
AB_SetBridgeActive(self.enabled and true or false)
|
||||
AB_Log("onEvent VARIABLES_LOADED -> engine init", "debug")
|
||||
local store = engine:EnsureDefaults()
|
||||
AB_Trace("VARIABLES_LOADED module.enabled=" .. tostring(self.enabled)
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<!--
|
||||
MetaHunt Auto Quest Module Loader
|
||||
-->
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/">
|
||||
<Include file="module.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,987 @@
|
||||
------------------------------------------------------
|
||||
-- MetaHunt: Quest Automation Module
|
||||
-- SHIFT-rightclick automation for specific quest flows
|
||||
------------------------------------------------------
|
||||
|
||||
local MTH_AutoQuest = {
|
||||
name = "autoquest",
|
||||
enabled = false,
|
||||
version = "1.1.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_DirectEventFrame = nil
|
||||
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 itemId = tonumber(string.match(link, "item:(%d+)"))
|
||||
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(self)
|
||||
QA_AppendDrazialTooltip(self, "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(self)
|
||||
if type(previous) == "function" then
|
||||
previous(self)
|
||||
end
|
||||
QA_AppendDrazialTooltip(self, "script:setunit")
|
||||
end)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
if hasHookScript and onShowExists then
|
||||
pcall(function()
|
||||
GameTooltip:HookScript("OnShow", function(self)
|
||||
QA_AppendDrazialTooltip(self, "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(self)
|
||||
if type(previousShow) == "function" then
|
||||
previousShow(self)
|
||||
end
|
||||
QA_AppendDrazialTooltip(self, "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_AutoQuestTooltipPollFrame")
|
||||
if not frame then
|
||||
return
|
||||
end
|
||||
frame._mthElapsed = 0
|
||||
frame:SetScript("OnUpdate", function(self, elapsed)
|
||||
self._mthElapsed = (self._mthElapsed or 0) + (elapsed or arg1 or 0)
|
||||
if self._mthElapsed < 0.20 then
|
||||
return
|
||||
end
|
||||
self._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_AutoQuestTooltipRefreshFrame")
|
||||
if not QA_TooltipRefreshFrame then
|
||||
return
|
||||
end
|
||||
QA_TooltipRefreshFrame:SetScript("OnUpdate", function(self, elapsed)
|
||||
local frameRef = self or this or QA_TooltipRefreshFrame
|
||||
if not frameRef then
|
||||
return
|
||||
end
|
||||
frameRef._elapsed = (frameRef._elapsed or 0) + (elapsed or 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
|
||||
|
||||
local function QA_SetDirectEventFrameActive(active)
|
||||
if not QA_DirectEventFrame then
|
||||
return
|
||||
end
|
||||
if active then
|
||||
QA_DirectEventFrame:RegisterEvent("GOSSIP_SHOW")
|
||||
QA_DirectEventFrame:RegisterEvent("QUEST_GREETING")
|
||||
QA_DirectEventFrame:RegisterEvent("QUEST_DETAIL")
|
||||
QA_DirectEventFrame:RegisterEvent("QUEST_PROGRESS")
|
||||
QA_DirectEventFrame:RegisterEvent("QUEST_COMPLETE")
|
||||
else
|
||||
QA_DirectEventFrame:UnregisterAllEvents()
|
||||
end
|
||||
end
|
||||
|
||||
local function QA_EnsureDirectEventFrame(moduleRef)
|
||||
if QA_DirectEventFrame then
|
||||
return QA_DirectEventFrame
|
||||
end
|
||||
local frame = CreateFrame("Frame", "MTH_AutoQuestEventFrame")
|
||||
if not frame then
|
||||
QA_Debug("direct frame create failed")
|
||||
return nil
|
||||
end
|
||||
frame:SetScript("OnEvent", function(_, eventName)
|
||||
eventName = eventName or event
|
||||
if not (moduleRef and moduleRef.enabled) then
|
||||
return
|
||||
end
|
||||
QA_Debug("directEvent=" .. tostring(eventName))
|
||||
QA_RunProfileAutomation(eventName, QA_PROFILE_SCORPOK)
|
||||
QA_RunProfileAutomation(eventName, QA_PROFILE_SISSIES)
|
||||
end)
|
||||
QA_DirectEventFrame = frame
|
||||
return frame
|
||||
end
|
||||
|
||||
function MTH_AutoQuest:init()
|
||||
local store = QA_GetOptionsStore()
|
||||
self.initialized = true
|
||||
QA_EnsureDirectEventFrame(self)
|
||||
QA_SetDirectEventFrameActive(self.enabled and true or false)
|
||||
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
|
||||
QA_SetDirectEventFrameActive(self.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()
|
||||
QA_SetDirectEventFrameActive(false)
|
||||
end
|
||||
|
||||
MTH:RegisterModule("autoquest", MTH_AutoQuest)
|
||||
@@ -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["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 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["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["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" })
|
||||
|
||||
@@ -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 BAR_GROUP = "MTHChronometer"
|
||||
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 = {
|
||||
white = { 1.0, 1.0, 1.0 },
|
||||
@@ -143,15 +182,80 @@ local function shallowCopy(source)
|
||||
return dest
|
||||
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()
|
||||
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)
|
||||
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
|
||||
store.profile = {}
|
||||
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
|
||||
|
||||
for key, value in pairs(DEFAULTS) do
|
||||
@@ -178,9 +282,68 @@ local function ensureProfile()
|
||||
profile.disabledSpells.HUNTER = {}
|
||||
end
|
||||
|
||||
MTH_CHRON_Trace("ensureProfile result barposition=" .. MTH_CHRON_FormatBarPosition(profile))
|
||||
|
||||
return profile
|
||||
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()
|
||||
if MTH and MTH.IsModuleEnabled then
|
||||
return MTH:IsModuleEnabled("chronometer", true) and true or false
|
||||
@@ -252,6 +415,70 @@ local function parseRankNumber(text)
|
||||
return 0
|
||||
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)
|
||||
if GetActionText(slot) or not HasAction(slot) then
|
||||
return nil, 0
|
||||
@@ -294,6 +521,7 @@ function Chronometer:MTH_Initialize()
|
||||
end
|
||||
|
||||
self.profile = ensureProfile()
|
||||
MTH_CHRON_Trace("MTH_Initialize profile=" .. MTH_CHRON_FormatBarPosition(self.profile))
|
||||
self.parser = ParserLib:GetInstance("1.1")
|
||||
|
||||
self.COLOR_MAP = {
|
||||
@@ -304,6 +532,7 @@ function Chronometer:MTH_Initialize()
|
||||
}
|
||||
|
||||
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:SetCandyBarGroupPoint(BAR_GROUP, "TOP", self.anchor, "BOTTOM", 0, 0)
|
||||
|
||||
@@ -312,16 +541,19 @@ end
|
||||
|
||||
function Chronometer:MTH_Enable()
|
||||
self._mth_explicitEnable = true
|
||||
MTH_CHRON_Trace("MTH_Enable called")
|
||||
self:MTH_Initialize()
|
||||
self:OnEnable()
|
||||
self._mth_explicitEnable = nil
|
||||
end
|
||||
|
||||
function Chronometer:MTH_Disable()
|
||||
MTH_CHRON_Trace("MTH_Disable called")
|
||||
self:OnDisable()
|
||||
end
|
||||
|
||||
function Chronometer:OnEnable()
|
||||
MTH_CHRON_Trace("OnEnable begin enabled=" .. tostring(self._mth_enabled and true or false))
|
||||
if self._mth_enabled then
|
||||
return
|
||||
end
|
||||
@@ -351,8 +583,13 @@ function Chronometer:OnEnable()
|
||||
self._mth_enabled = true
|
||||
|
||||
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: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.timers = {}
|
||||
@@ -430,16 +667,39 @@ function Chronometer:OnEnable()
|
||||
self:RegisterEvent("SPELLCAST_INTERRUPTED")
|
||||
self:RegisterEvent("SPELLCAST_START")
|
||||
self:RegisterEvent("SPELLCAST_STOP")
|
||||
self:RegisterEvent("UNIT_AURA")
|
||||
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_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)
|
||||
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()
|
||||
if not self._mth_enabled then
|
||||
return
|
||||
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
|
||||
|
||||
if self.bars then
|
||||
@@ -543,9 +803,12 @@ function Chronometer:StartTimer(timer, name, target, rank, durmod)
|
||||
end
|
||||
end
|
||||
|
||||
local _, class = UnitClass("player")
|
||||
local timerClass = timer.x.cl == nil and class or timer.x.cl
|
||||
if self.profile.disabledSpells[timerClass] and self.profile.disabledSpells[timerClass][name] ~= nil then
|
||||
local timerClass = timer.x.cl
|
||||
if timerClass == nil then
|
||||
timerClass = resolvePlayerClassBucket(self.profile)
|
||||
end
|
||||
local blocked, reason = isTimerDisabled(self.profile, timerClass, name)
|
||||
if blocked then
|
||||
return
|
||||
end
|
||||
|
||||
@@ -938,11 +1201,22 @@ function Chronometer:CreateAnchor(text, r, g, b)
|
||||
|
||||
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 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 ppoint == "" then
|
||||
ppoint = "TOPLEFT"
|
||||
end
|
||||
if prelpoint == "" then
|
||||
prelpoint = ppoint
|
||||
end
|
||||
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
|
||||
frame:SetPoint("CENTER", UIParent, "CENTER", 0, 50)
|
||||
MTH_CHRON_Trace("CreateAnchor default point=" .. MTH_CHRON_DescribePoint(frame))
|
||||
end
|
||||
|
||||
frame:SetScript("OnDragStart", function(self)
|
||||
@@ -950,6 +1224,7 @@ function Chronometer:CreateAnchor(text, r, g, b)
|
||||
if not self or not self.StartMoving then
|
||||
return
|
||||
end
|
||||
MTH_CHRON_Trace("anchor drag-start point=" .. MTH_CHRON_DescribePoint(self))
|
||||
self:StartMoving()
|
||||
end)
|
||||
frame:SetScript("OnDragStop", function(self)
|
||||
@@ -975,8 +1250,12 @@ function Chronometer:CreateAnchor(text, r, g, b)
|
||||
self: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
|
||||
self.owner.profile.barposition.point = point or "TOPLEFT"
|
||||
self.owner.profile.barposition.relativePoint = point or "TOPLEFT"
|
||||
self.owner.profile.barposition.x = x
|
||||
self.owner.profile.barposition.y = y
|
||||
MTH_CHRON_Trace("anchor drag-stop saved profile=" .. MTH_CHRON_FormatBarPosition(self.owner.profile)
|
||||
.. " frame=" .. MTH_CHRON_DescribePoint(self))
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -1102,6 +1381,62 @@ function Chronometer:PLAYER_DEAD()
|
||||
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)
|
||||
local name, rank = getActionSpell(slot)
|
||||
if name then
|
||||
|
||||
@@ -1,13 +1,28 @@
|
||||
local MTH_ChronometerModule = {
|
||||
name = "chronometer",
|
||||
enabled = true,
|
||||
version = "1.0.4",
|
||||
version = "1.1.0",
|
||||
events = {},
|
||||
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)
|
||||
MTH_CHRON_ModuleTrace("module apply runtime enabled=" .. tostring(enabled and true or false))
|
||||
if not MTH_ChronometerHunter then
|
||||
MTH_CHRON_ModuleTrace("module apply runtime skipped (engine unavailable)")
|
||||
return
|
||||
end
|
||||
if enabled then
|
||||
@@ -22,14 +37,18 @@ local function MTH_CHRON_ApplyRuntimeEnabledState(enabled)
|
||||
end
|
||||
|
||||
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
|
||||
MTH_ChronometerHunter:MTH_Initialize()
|
||||
end
|
||||
MTH_CHRON_ApplyRuntimeEnabledState(self.enabled and true or false)
|
||||
self.initialized = true
|
||||
MTH_CHRON_ModuleTrace("module init end initialized=true")
|
||||
end
|
||||
|
||||
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
|
||||
self:init()
|
||||
end
|
||||
@@ -37,6 +56,7 @@ function MTH_ChronometerModule:setEnabled(enabled)
|
||||
end
|
||||
|
||||
function MTH_ChronometerModule:cleanup()
|
||||
MTH_CHRON_ModuleTrace("module cleanup")
|
||||
if MTH_ChronometerHunter and MTH_ChronometerHunter.MTH_Disable then
|
||||
MTH_ChronometerHunter:MTH_Disable()
|
||||
end
|
||||
|
||||
+957
-101
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@
|
||||
local MTH_FeedOMatic = {
|
||||
name = "feedomatic",
|
||||
enabled = false,
|
||||
version = "1.0.4",
|
||||
version = "1.1.0",
|
||||
events = {
|
||||
"VARIABLES_LOADED",
|
||||
"MERCHANT_SHOW",
|
||||
@@ -38,7 +38,7 @@ function MTH_FeedOMatic_OnUpdate(elapsed)
|
||||
if not elapsed then
|
||||
return
|
||||
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
|
||||
end
|
||||
if type(FOM_OnUpdate) == "function" then
|
||||
@@ -137,47 +137,31 @@ local function MTH_FeedOMatic_SyncSavedVariables()
|
||||
moduleStore.legacy = {}
|
||||
end
|
||||
|
||||
if type(FOM_Config) == "table" then
|
||||
moduleStore.legacy.FOM_Config = FOM_Config
|
||||
elseif type(moduleStore.legacy.FOM_Config) == "table" then
|
||||
FOM_Config = moduleStore.legacy.FOM_Config
|
||||
local function bindLegacyTable(globalName)
|
||||
local legacyValue = moduleStore.legacy[globalName]
|
||||
local globalValue = _G and _G[globalName] or nil
|
||||
|
||||
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
|
||||
|
||||
if type(FOM_FoodQuality) == "table" then
|
||||
moduleStore.legacy.FOM_FoodQuality = FOM_FoodQuality
|
||||
elseif type(moduleStore.legacy.FOM_FoodQuality) == "table" then
|
||||
FOM_FoodQuality = moduleStore.legacy.FOM_FoodQuality
|
||||
end
|
||||
|
||||
if type(FOM_AddedFoods) == "table" then
|
||||
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
|
||||
bindLegacyTable("FOM_Config")
|
||||
bindLegacyTable("FOM_FoodQuality")
|
||||
bindLegacyTable("FOM_AddedFoods")
|
||||
bindLegacyTable("FOM_RemovedFoods")
|
||||
bindLegacyTable("FOM_Cooking")
|
||||
bindLegacyTable("FOM_QuestFood")
|
||||
bindLegacyTable("FOM_LocaleInfo")
|
||||
end
|
||||
|
||||
local function MTH_FeedOMatic_Log(message, severity)
|
||||
@@ -231,6 +215,14 @@ local function MTH_FeedOMatic_DebugMerchantScan(sourceEvent)
|
||||
end
|
||||
|
||||
local function MTH_FeedOMatic_SetMerchantProbeEnabled(enabled)
|
||||
if not enabled then
|
||||
if MTH_FeedOMatic_MerchantProbeFrame then
|
||||
MTH_FeedOMatic_MerchantProbeFrame:UnregisterEvent("MERCHANT_SHOW")
|
||||
MTH_FeedOMatic_MerchantProbeFrame:UnregisterEvent("MERCHANT_UPDATE")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if not MTH_FeedOMatic_MerchantProbeFrame then
|
||||
MTH_FeedOMatic_MerchantProbeFrame = CreateFrame("Frame", "MTH_FeedOMatic_MerchantProbeFrame")
|
||||
MTH_FeedOMatic_MerchantProbeFrame:SetScript("OnEvent", function()
|
||||
@@ -242,14 +234,9 @@ local function MTH_FeedOMatic_SetMerchantProbeEnabled(enabled)
|
||||
end)
|
||||
end
|
||||
|
||||
if enabled then
|
||||
MTH_FeedOMatic_MerchantProbeFrame:RegisterEvent("MERCHANT_SHOW")
|
||||
MTH_FeedOMatic_MerchantProbeFrame:RegisterEvent("MERCHANT_UPDATE")
|
||||
MTH_FeedOMatic_Log("merchant probe enabled", "debug")
|
||||
else
|
||||
MTH_FeedOMatic_MerchantProbeFrame:UnregisterEvent("MERCHANT_SHOW")
|
||||
MTH_FeedOMatic_MerchantProbeFrame:UnregisterEvent("MERCHANT_UPDATE")
|
||||
end
|
||||
MTH_FeedOMatic_MerchantProbeFrame:RegisterEvent("MERCHANT_SHOW")
|
||||
MTH_FeedOMatic_MerchantProbeFrame:RegisterEvent("MERCHANT_UPDATE")
|
||||
MTH_FeedOMatic_Log("merchant probe enabled", "debug")
|
||||
end
|
||||
|
||||
function MTH_FeedOMatic:init()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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>
|
||||
@@ -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>
|
||||
@@ -0,0 +1,52 @@
|
||||
------------------------------------------------------
|
||||
-- MetaHunt: ICU Module Wrapper
|
||||
-- Safe wrapper for ICU minimap targeting utilities
|
||||
------------------------------------------------------
|
||||
|
||||
local MTH_ICU = {
|
||||
name = "icu",
|
||||
enabled = false,
|
||||
version = "1.1.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)
|
||||
@@ -155,7 +155,8 @@ MTH_SA_List = {}
|
||||
|
||||
MTH_SA_LastCheck = 0
|
||||
|
||||
MTH_SA_Tooltip = CreateFrame("GameTooltip", "MTH_SA_Tooltip", nil, "GameTooltipTemplate")
|
||||
MTH_SA_Tooltip = CreateFrame("GameTooltip", "MTH_SA_Scan", nil, "GameTooltipTemplate")
|
||||
MTH_SA_TooltipTextLeft1 = getglobal("MTH_SA_ScanTextLeft1")
|
||||
MTH_SA_Tooltip:Hide()
|
||||
|
||||
local _, class = UnitClass("player")
|
||||
|
||||
@@ -7,7 +7,7 @@ MTH_SA_MANAGED_HOOKS = true
|
||||
local MTH_SmartAmmo = {
|
||||
name = "smartammo",
|
||||
enabled = true,
|
||||
version = "1.0.4",
|
||||
version = "1.1.0",
|
||||
events = {
|
||||
"VARIABLES_LOADED",
|
||||
"PLAYER_ENTERING_WORLD",
|
||||
|
||||
+498
-24
@@ -6,7 +6,7 @@
|
||||
local MTH_Tooltips = {
|
||||
name = "tooltips",
|
||||
enabled = true,
|
||||
version = "1.0.4",
|
||||
version = "1.1.0",
|
||||
events = {
|
||||
"UPDATE_MOUSEOVER_UNIT",
|
||||
"UNIT_NAME_UPDATE",
|
||||
@@ -34,14 +34,33 @@ local MTH_Tooltips = {
|
||||
injectFrame = nil,
|
||||
pollFrame = nil,
|
||||
pollElapsed = 0,
|
||||
hintElapsed = 0,
|
||||
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()
|
||||
if MTH and MTH.GetModuleSavedVariables then
|
||||
local store = MTH:GetModuleSavedVariables("tooltips")
|
||||
if MTH and MTH.GetModuleCharSavedVariables then
|
||||
local store = MTH:GetModuleCharSavedVariables("tooltips")
|
||||
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
|
||||
store.beastTooltips = true
|
||||
end
|
||||
@@ -96,6 +115,55 @@ local function MTH_TT_IsOwnPetTooltipsEnabled()
|
||||
return false
|
||||
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)
|
||||
if MTH and MTH.GetLocalization then
|
||||
return MTH:GetLocalization(key, fallback)
|
||||
@@ -539,6 +607,191 @@ local function MTH_TT_ColorizeDigitsBlue(text)
|
||||
return string.gsub(source, "(%d+)", "|cff73bfff%1|r")
|
||||
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()
|
||||
if not (MTH_Tooltips and MTH_Tooltips.enabled) then
|
||||
return
|
||||
@@ -845,7 +1098,37 @@ local function MTH_TT_FindAbilityCanonicalName(abilityName)
|
||||
return nil
|
||||
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)
|
||||
if text == "" then
|
||||
return nil
|
||||
@@ -854,9 +1137,11 @@ local function MTH_TT_ParseRankFromText(value)
|
||||
if rankText then
|
||||
return tonumber(rankText)
|
||||
end
|
||||
local _, _, trailing = string.find(text, "(%d+)$")
|
||||
if trailing then
|
||||
return tonumber(trailing)
|
||||
if allowTrailingNumber == true then
|
||||
local _, _, trailing = string.find(text, "(%d+)$")
|
||||
if trailing then
|
||||
return tonumber(trailing)
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
@@ -884,10 +1169,10 @@ local function MTH_TT_GetTooltipSpellNameAndRank()
|
||||
if ok then
|
||||
if type(a) == "string" then
|
||||
spellName = a
|
||||
rankNumber = MTH_TT_ParseRankFromText(b)
|
||||
rankNumber = MTH_TT_ParseRankFromText(b, true)
|
||||
elseif type(b) == "string" then
|
||||
spellName = b
|
||||
rankNumber = MTH_TT_ParseRankFromText(a)
|
||||
rankNumber = MTH_TT_ParseRankFromText(a, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -899,24 +1184,28 @@ local function MTH_TT_GetTooltipSpellNameAndRank()
|
||||
end
|
||||
end
|
||||
|
||||
if not rankNumber then
|
||||
rankNumber = MTH_TT_ParseRankFromText(spellName, true)
|
||||
end
|
||||
|
||||
if not rankNumber then
|
||||
local right1 = getglobal("GameTooltipTextRight1")
|
||||
if right1 and right1.GetText then
|
||||
rankNumber = MTH_TT_ParseRankFromText(right1:GetText())
|
||||
rankNumber = MTH_TT_ParseRankFromText(right1:GetText(), false)
|
||||
end
|
||||
end
|
||||
|
||||
if not rankNumber then
|
||||
local left2 = getglobal("GameTooltipTextLeft2")
|
||||
if left2 and left2.GetText then
|
||||
rankNumber = MTH_TT_ParseRankFromText(left2:GetText())
|
||||
rankNumber = MTH_TT_ParseRankFromText(left2:GetText(), false)
|
||||
end
|
||||
end
|
||||
|
||||
if not rankNumber then
|
||||
local right2 = getglobal("GameTooltipTextRight2")
|
||||
if right2 and right2.GetText then
|
||||
rankNumber = MTH_TT_ParseRankFromText(right2:GetText())
|
||||
rankNumber = MTH_TT_ParseRankFromText(right2:GetText(), false)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -925,7 +1214,7 @@ local function MTH_TT_GetTooltipSpellNameAndRank()
|
||||
local left = getglobal("GameTooltipTextLeft" .. i)
|
||||
if left and left.GetText then
|
||||
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
|
||||
rankNumber = parsed
|
||||
break
|
||||
@@ -933,7 +1222,7 @@ local function MTH_TT_GetTooltipSpellNameAndRank()
|
||||
end
|
||||
local right = getglobal("GameTooltipTextRight" .. i)
|
||||
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
|
||||
rankNumber = parsedRight
|
||||
break
|
||||
@@ -945,6 +1234,87 @@ local function MTH_TT_GetTooltipSpellNameAndRank()
|
||||
return MTH_TT_CleanSpellName(spellName), rankNumber
|
||||
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()
|
||||
if not GameTooltip or type(GameTooltip.GetOwner) ~= "function" then
|
||||
return false
|
||||
@@ -1031,7 +1401,15 @@ local function MTH_TT_AddPetActionNotLearnedHint()
|
||||
return
|
||||
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
|
||||
return
|
||||
end
|
||||
@@ -1107,7 +1485,8 @@ local function MTH_TT_AddTooltip(unit)
|
||||
local ammoVendorTooltipsEnabled = MTH_TT_IsAmmoVendorTooltipsEnabled()
|
||||
local vendorInfo = ammoVendorTooltipsEnabled and MTH_TT_FindVendorInfo(name) or nil
|
||||
local row = beastTooltipsEnabled and MTH_TT_FindBeastRow(name) or nil
|
||||
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
|
||||
MTH_TT_StateSet("lookup-miss", name, normalized)
|
||||
MTH_TT_Log("lookup miss: unit='" .. tostring(name) .. "' normalized='" .. tostring(normalized) .. "'")
|
||||
@@ -1115,6 +1494,9 @@ local function MTH_TT_AddTooltip(unit)
|
||||
end
|
||||
|
||||
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.arrows and vendorInfo.bullets then
|
||||
@@ -1165,16 +1547,21 @@ local function MTH_TT_EnsureInjectFrame()
|
||||
end
|
||||
local frame = CreateFrame("Frame", "MTH_TooltipsInjectFrame")
|
||||
frame.pending = false
|
||||
frame:SetScript("OnUpdate", function(self)
|
||||
frame.onUpdate = function(self)
|
||||
self = self or this
|
||||
if not self or not self.pending then
|
||||
if not self then
|
||||
return
|
||||
end
|
||||
if not self.pending then
|
||||
self:SetScript("OnUpdate", nil)
|
||||
return
|
||||
end
|
||||
self.pending = false
|
||||
self:SetScript("OnUpdate", nil)
|
||||
if MTH_Tooltips and MTH_Tooltips.enabled then
|
||||
MTH_TT_AddTooltip("mouseover")
|
||||
end
|
||||
end)
|
||||
end
|
||||
MTH_Tooltips.injectFrame = frame
|
||||
return frame
|
||||
end
|
||||
@@ -1183,6 +1570,9 @@ local function MTH_TT_RequestInject()
|
||||
local frame = MTH_TT_EnsureInjectFrame()
|
||||
if frame then
|
||||
frame.pending = true
|
||||
if not frame:GetScript("OnUpdate") then
|
||||
frame:SetScript("OnUpdate", frame.onUpdate)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1197,14 +1587,18 @@ local function MTH_TT_EnsurePollFrame()
|
||||
return
|
||||
end
|
||||
|
||||
if GameTooltip and GameTooltip.IsShown and GameTooltip:IsShown() then
|
||||
MTH_TT_AddOwnPetTooltipHint()
|
||||
if not MTH_TT_HasExistingNotLearnedLine() then
|
||||
MTH_TT_AddPetActionNotLearnedHint()
|
||||
elapsed = elapsed or arg1
|
||||
MTH_Tooltips.hintElapsed = (MTH_Tooltips.hintElapsed or 0) + (elapsed 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
|
||||
|
||||
elapsed = elapsed or arg1
|
||||
MTH_Tooltips.pollElapsed = (MTH_Tooltips.pollElapsed or 0) + (elapsed or 0)
|
||||
if MTH_Tooltips.pollElapsed < 0.15 then
|
||||
return
|
||||
@@ -1242,6 +1636,75 @@ local function MTH_TT_EnsurePollFrame()
|
||||
return frame
|
||||
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(_, elapsed)
|
||||
if not (MTH_Tooltips and MTH_Tooltips.enabled) then
|
||||
return
|
||||
end
|
||||
|
||||
elapsed = elapsed or arg1
|
||||
MTH_Tooltips.hintElapsed = (MTH_Tooltips.hintElapsed or 0) + (elapsed 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()
|
||||
if MTH_Tooltips.hookInstalled then
|
||||
return
|
||||
@@ -1260,9 +1723,15 @@ local function MTH_TT_InstallTooltipHook()
|
||||
MTH_TT_RequestInject()
|
||||
end)
|
||||
GameTooltip:HookScript("OnTooltipSetItem", function()
|
||||
if not (MTH_Tooltips and MTH_Tooltips.enabled) then
|
||||
return
|
||||
end
|
||||
MTH_TT_AddFoodTooltipHint()
|
||||
end)
|
||||
GameTooltip:HookScript("OnTooltipSetSpell", function()
|
||||
if not (MTH_Tooltips and MTH_Tooltips.enabled) then
|
||||
return
|
||||
end
|
||||
MTH_TT_AddPetActionNotLearnedHint()
|
||||
end)
|
||||
end)
|
||||
@@ -1284,6 +1753,7 @@ function MTH_Tooltips:init()
|
||||
MTH_TT_InstallTooltipHook()
|
||||
MTH_TT_EnsureInjectFrame()
|
||||
MTH_TT_EnsurePollFrame()
|
||||
MTH_TT_SetRuntimeActive(self.enabled)
|
||||
MTH_TT_Log("module init complete")
|
||||
end
|
||||
|
||||
@@ -1307,6 +1777,9 @@ function MTH_Tooltips:setEnabled(enabled)
|
||||
elseif self.enabled then
|
||||
MTH_TT_EnsurePollFrame()
|
||||
MTH_TT_EnsureInjectFrame()
|
||||
MTH_TT_SetRuntimeActive(true)
|
||||
else
|
||||
MTH_TT_SetRuntimeActive(false)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1357,6 +1830,7 @@ end
|
||||
|
||||
function MTH_Tooltips:cleanup()
|
||||
self.enabled = false
|
||||
MTH_TT_SetRuntimeActive(false)
|
||||
end
|
||||
|
||||
function MTH_Tooltips:GetDebugSnapshot()
|
||||
|
||||
@@ -11,7 +11,73 @@ BINDING_HEADER_ZMountsHeader = "ZMounts Buttons"
|
||||
BINDING_HEADER_ZCompanionsHeader = "ZCompanions Buttons"
|
||||
BINDING_HEADER_ZToysHeader = "ZToys Buttons"
|
||||
|
||||
ZHunterModTooltip = CreateFrame("GameTooltip", "ZHunterModTooltip", nil, "GameTooltipTemplate")
|
||||
ZHunterModTooltip = CreateFrame("GameTooltip", "ZHunterModScan", nil, "GameTooltipTemplate")
|
||||
ZHunterModTooltipTextLeft1 = getglobal("ZHunterModScanTextLeft1")
|
||||
|
||||
MTH_ZH_TRACE_ENABLED = false
|
||||
|
||||
local function MTH_ZH_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 MTH_ZH_Trace(msg)
|
||||
if not MTH_ZH_TRACE_ENABLED then
|
||||
return
|
||||
end
|
||||
if MTH and MTH.Print then
|
||||
MTH:Print("[ZHTRACE] " .. tostring(msg), "debug")
|
||||
elseif DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("[ZHTRACE] " .. tostring(msg))
|
||||
end
|
||||
end
|
||||
|
||||
function MTH_ZH_TraceButtonPoint(frame, reason)
|
||||
if not MTH_ZH_TRACE_ENABLED then
|
||||
return
|
||||
end
|
||||
if not frame then
|
||||
MTH_ZH_Trace("point " .. tostring(reason or "") .. " frame=nil")
|
||||
return
|
||||
end
|
||||
local name = frame.GetName and frame:GetName() or "<unnamed>"
|
||||
MTH_ZH_Trace("point " .. tostring(reason or "") .. " " .. tostring(name) .. " " .. MTH_ZH_DescribePoint(frame))
|
||||
end
|
||||
|
||||
function MTH_ZH_TraceAllButtonPoints(reason)
|
||||
if not MTH_ZH_TRACE_ENABLED then
|
||||
return
|
||||
end
|
||||
local names = {
|
||||
"zButtonAspect",
|
||||
"zButtonAmmo",
|
||||
"zButtonTrack",
|
||||
"zButtonTrap",
|
||||
"zButtonRanged",
|
||||
"zButtonPet",
|
||||
"zButtonMounts",
|
||||
"zButtonCompanions",
|
||||
"zButtonToys",
|
||||
}
|
||||
MTH_ZH_Trace("snapshot begin reason=" .. tostring(reason or ""))
|
||||
for i = 1, table.getn(names) do
|
||||
local frame = getglobal(names[i])
|
||||
MTH_ZH_TraceButtonPoint(frame, tostring(reason or "") .. ":" .. tostring(names[i]))
|
||||
end
|
||||
MTH_ZH_Trace("snapshot end reason=" .. tostring(reason or ""))
|
||||
end
|
||||
|
||||
function MTH_ZH_IsModuleEnabled()
|
||||
if not (MTH and MTH.IsModuleEnabled) then
|
||||
@@ -104,6 +170,7 @@ function MTH_ZH_HandleDisabledSlash(message, tableKey, fieldKey)
|
||||
end
|
||||
|
||||
function ZHunterMod_AlignButtons()
|
||||
MTH_ZH_TraceAllButtonPoints("AlignButtons:before")
|
||||
zButtonAmmo:ClearAllPoints()
|
||||
zButtonAmmo:SetPoint("TOP", zButtonAspect, "BOTTOM", 0, -15)
|
||||
zButtonTrack:ClearAllPoints()
|
||||
@@ -122,6 +189,7 @@ function ZHunterMod_AlignButtons()
|
||||
AutoStripDisplay:ClearAllPoints()
|
||||
AutoStripDisplay:SetPoint("TOP", zButtonToys, "BOTTOM", 0, -10)
|
||||
end
|
||||
MTH_ZH_TraceAllButtonPoints("AlignButtons:after")
|
||||
end
|
||||
|
||||
function ZMarkTarget()
|
||||
|
||||
@@ -377,6 +377,94 @@ function ZSpellButton_ApplyChildrenExpanded(parent)
|
||||
ZSpellButton_SetChildrenExpanded(parent, ZSpellButton_GetChildrenExpanded(parent))
|
||||
end
|
||||
|
||||
local function ZSpellButton_SaveParentPosition(parent)
|
||||
if not (parent and parent.GetPoint) then
|
||||
return
|
||||
end
|
||||
if type(MTH_ZH_GetSavedTable) ~= "function" then
|
||||
return
|
||||
end
|
||||
local key = parent.name
|
||||
if (type(key) ~= "string" or key == "") and parent.GetName then
|
||||
key = parent:GetName()
|
||||
end
|
||||
if type(key) ~= "string" or key == "" then
|
||||
return
|
||||
end
|
||||
|
||||
local saved = MTH_ZH_GetSavedTable(key)
|
||||
if type(saved) ~= "table" then
|
||||
return
|
||||
end
|
||||
if type(saved["parent"]) ~= "table" then
|
||||
saved["parent"] = {}
|
||||
end
|
||||
|
||||
local point, _, relPoint, x, y = parent:GetPoint()
|
||||
x = tonumber(x)
|
||||
y = tonumber(y)
|
||||
if not (point and relPoint and x and y) then
|
||||
return
|
||||
end
|
||||
|
||||
saved["parent"]["point"] = tostring(point)
|
||||
saved["parent"]["relativePoint"] = tostring(relPoint)
|
||||
saved["parent"]["x"] = math.floor(x + 0.5)
|
||||
saved["parent"]["y"] = math.floor(y + 0.5)
|
||||
if type(MTH_ZH_Trace) == "function" then
|
||||
MTH_ZH_Trace("persist-parent-position key=" .. tostring(key)
|
||||
.. " point=" .. tostring(saved["parent"]["point"])
|
||||
.. " rel=" .. tostring(saved["parent"]["relativePoint"])
|
||||
.. " x=" .. tostring(saved["parent"]["x"])
|
||||
.. " y=" .. tostring(saved["parent"]["y"]))
|
||||
end
|
||||
end
|
||||
|
||||
local function ZSpellButton_RestoreParentPosition(parent)
|
||||
if not (parent and parent.ClearAllPoints and parent.SetPoint) then
|
||||
return false
|
||||
end
|
||||
if type(MTH_ZH_GetSavedTable) ~= "function" then
|
||||
return false
|
||||
end
|
||||
local key = parent.name
|
||||
if (type(key) ~= "string" or key == "") and parent.GetName then
|
||||
key = parent:GetName()
|
||||
end
|
||||
if type(key) ~= "string" or key == "" then
|
||||
return false
|
||||
end
|
||||
|
||||
local saved = MTH_ZH_GetSavedTable(key)
|
||||
if type(saved) ~= "table" or type(saved["parent"]) ~= "table" then
|
||||
return false
|
||||
end
|
||||
|
||||
local parentSaved = saved["parent"]
|
||||
local px = tonumber(parentSaved["x"])
|
||||
local py = tonumber(parentSaved["y"])
|
||||
local point = parentSaved["point"]
|
||||
local relPoint = parentSaved["relativePoint"]
|
||||
if not (px and py and type(point) == "string" and point ~= "") then
|
||||
return false
|
||||
end
|
||||
|
||||
if type(relPoint) ~= "string" or relPoint == "" then
|
||||
relPoint = point
|
||||
end
|
||||
|
||||
parent:ClearAllPoints()
|
||||
parent:SetPoint(point, UIParent, relPoint, px, py)
|
||||
if type(MTH_ZH_Trace) == "function" then
|
||||
MTH_ZH_Trace("restore-parent-position key=" .. tostring(key)
|
||||
.. " point=" .. tostring(point)
|
||||
.. " rel=" .. tostring(relPoint)
|
||||
.. " x=" .. tostring(px)
|
||||
.. " y=" .. tostring(py))
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function ZSpellButton_OnEnter()
|
||||
ZSpellButton_EnsureParentFlags(this.parent)
|
||||
if this.parent.tooltip then
|
||||
@@ -384,9 +472,36 @@ function ZSpellButton_OnEnter()
|
||||
if this.isspell then
|
||||
GameTooltip:SetSpell(this.id, "spell")
|
||||
else
|
||||
GameTooltip:SetText(this.ammocount .. " x "..this.ammolink, 1, 1, 1)
|
||||
--GameTooltip:AddLine("Q="..this.ammocount)
|
||||
local showedItemTooltip = nil
|
||||
if this.ammobag and this.ammoslot and type(GameTooltip.SetBagItem) == "function" then
|
||||
GameTooltip:ClearLines()
|
||||
GameTooltip:SetBagItem(this.ammobag, this.ammoslot)
|
||||
if type(GameTooltip.NumLines) == "function" and GameTooltip:NumLines() > 0 then
|
||||
local left1 = getglobal("GameTooltipTextLeft1")
|
||||
if left1 and left1.GetText and tostring(left1:GetText() or "") ~= "" then
|
||||
showedItemTooltip = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if (not showedItemTooltip) and this.ammolink and type(GameTooltip.SetHyperlink) == "function" then
|
||||
GameTooltip:ClearLines()
|
||||
GameTooltip:SetHyperlink(this.ammolink)
|
||||
if type(GameTooltip.NumLines) == "function" and GameTooltip:NumLines() > 0 then
|
||||
local left1 = getglobal("GameTooltipTextLeft1")
|
||||
if left1 and left1.GetText and tostring(left1:GetText() or "") ~= "" then
|
||||
showedItemTooltip = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if not showedItemTooltip then
|
||||
local label = this.ammoname or this.ammolink or "Ammo"
|
||||
if this.ammocount then
|
||||
label = tostring(this.ammocount) .. " x " .. tostring(label)
|
||||
end
|
||||
GameTooltip:SetText(label, 1, 1, 1)
|
||||
end
|
||||
end
|
||||
GameTooltip:Show()
|
||||
end
|
||||
end
|
||||
|
||||
@@ -452,6 +567,46 @@ function ZSpellButtonParent_OnLoad()
|
||||
this.circle = getglobal(name.."Circle")
|
||||
-- Keep enabled so empty buttons can be moved on low-level characters.
|
||||
this:Enable()
|
||||
ZSpellButton_RestoreParentPosition(this)
|
||||
if this.SetScript then
|
||||
this:SetScript("OnDragStart", function(self)
|
||||
self = self or this
|
||||
if IsAltKeyDown() then
|
||||
if type(MTH_ZH_TraceButtonPoint) == "function" then
|
||||
MTH_ZH_TraceButtonPoint(self, "drag-start")
|
||||
end
|
||||
self:StartMoving()
|
||||
self.isMoving = true
|
||||
end
|
||||
end)
|
||||
this:SetScript("OnDragStop", function(self)
|
||||
self = self or this
|
||||
if not self then
|
||||
return
|
||||
end
|
||||
if self.StopMovingOrSizing then
|
||||
self:StopMovingOrSizing()
|
||||
end
|
||||
ZSpellButton_SaveParentPosition(self)
|
||||
self.isMoving = false
|
||||
if type(MTH_ZH_TraceButtonPoint) == "function" then
|
||||
MTH_ZH_TraceButtonPoint(self, "drag-stop")
|
||||
end
|
||||
end)
|
||||
this:SetScript("OnMouseUp", function(self)
|
||||
self = self or this
|
||||
if self and self.isMoving then
|
||||
if self.StopMovingOrSizing then
|
||||
self:StopMovingOrSizing()
|
||||
end
|
||||
ZSpellButton_SaveParentPosition(self)
|
||||
self.isMoving = false
|
||||
if type(MTH_ZH_TraceButtonPoint) == "function" then
|
||||
MTH_ZH_TraceButtonPoint(self, "mouse-up-stop")
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function ZSpellButtonParent_OnEvent()
|
||||
@@ -488,11 +643,38 @@ function ZSpellButtonParent_OnEnter(frame)
|
||||
if string.len(rank) > 0 then
|
||||
msg = msg.." ("..rank..")"
|
||||
end
|
||||
GameTooltip:SetText(msg, 1, 1, 1)
|
||||
else
|
||||
msg = frame.ammoname
|
||||
local showedItemTooltip = nil
|
||||
if frame.ammobag and frame.ammoslot and type(GameTooltip.SetBagItem) == "function" then
|
||||
GameTooltip:ClearLines()
|
||||
GameTooltip:SetBagItem(frame.ammobag, frame.ammoslot)
|
||||
if type(GameTooltip.NumLines) == "function" and GameTooltip:NumLines() > 0 then
|
||||
local left1 = getglobal("GameTooltipTextLeft1")
|
||||
if left1 and left1.GetText and tostring(left1:GetText() or "") ~= "" then
|
||||
showedItemTooltip = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if (not showedItemTooltip) and frame.ammolink and type(GameTooltip.SetHyperlink) == "function" then
|
||||
GameTooltip:ClearLines()
|
||||
GameTooltip:SetHyperlink(frame.ammolink)
|
||||
if type(GameTooltip.NumLines) == "function" and GameTooltip:NumLines() > 0 then
|
||||
local left1 = getglobal("GameTooltipTextLeft1")
|
||||
if left1 and left1.GetText and tostring(left1:GetText() or "") ~= "" then
|
||||
showedItemTooltip = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if not showedItemTooltip then
|
||||
msg = frame.ammoname or frame.ammolink or "Ammo"
|
||||
if frame.ammocount then
|
||||
msg = tostring(frame.ammocount) .. " x " .. tostring(msg)
|
||||
end
|
||||
GameTooltip:SetText(msg, 1, 1, 1)
|
||||
end
|
||||
end
|
||||
|
||||
GameTooltip:SetText(msg, 1, 1, 1)
|
||||
GameTooltip:AddLine("Alt+Drag To Move This Button")
|
||||
GameTooltip:Show()
|
||||
end
|
||||
|
||||
@@ -8,7 +8,7 @@ MTH_ZH_MANAGED_HOOKS = true
|
||||
local MTH_ZHunter = {
|
||||
name = "zhunter",
|
||||
enabled = true,
|
||||
version = "1.0.4",
|
||||
version = "1.1.0",
|
||||
events = {
|
||||
"VARIABLES_LOADED",
|
||||
"PLAYER_ENTERING_WORLD",
|
||||
@@ -31,6 +31,12 @@ local function MTH_ZH_Log(msg)
|
||||
MTH:Print("[ZH MODULE] " .. tostring(msg), "debug")
|
||||
end
|
||||
|
||||
local function MTH_ZH_TraceLocal(msg)
|
||||
if type(MTH_ZH_Trace) == "function" then
|
||||
MTH_ZH_Trace(msg)
|
||||
end
|
||||
end
|
||||
|
||||
local MTH_ZH_PostLoginRestoreFrame = nil
|
||||
local MTH_ZH_BootstrapFrame = nil
|
||||
local MTH_ZH_SyncSavedVariables
|
||||
@@ -105,7 +111,6 @@ function MTH_ZH_OnDeferredInitComplete()
|
||||
return
|
||||
end
|
||||
MTH_ZH_SyncSavedVariables()
|
||||
MTH_ZH_ApplyDefaultWidgetSpawnLayoutOnce()
|
||||
MTH_ZH_RestoreRuntimeFeatureFlags()
|
||||
MTH_ZH_QueuePostLoginRestore("deferred-init")
|
||||
end
|
||||
@@ -132,6 +137,9 @@ MTH_ZH_QueuePostLoginRestore = function(tag)
|
||||
|
||||
MTH_ZH_SyncSavedVariables()
|
||||
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))
|
||||
end)
|
||||
end
|
||||
@@ -170,10 +178,17 @@ local function MTH_ZH_EnsureBootstrapRestoreFrame()
|
||||
end
|
||||
|
||||
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_SetButtonsVisible(true)
|
||||
MTH_ZH_SetAuxFramesVisible(true)
|
||||
MTH_ZH_RestoreRuntimeFeatureFlags()
|
||||
if type(MTH_ZH_TraceAllButtonPoints) == "function" then
|
||||
MTH_ZH_TraceAllButtonPoints("apply-enabled:after:" .. tostring(source or ""))
|
||||
end
|
||||
end
|
||||
|
||||
MTH_ZH_SyncSavedVariables = function()
|
||||
@@ -182,17 +197,22 @@ MTH_ZH_SyncSavedVariables = function()
|
||||
end
|
||||
|
||||
local moduleStore = MTH:GetModuleCharSavedVariables("zhunter")
|
||||
MTH_ZH_TraceLocal("sync-saved begin zhuntermod_saved=" .. tostring(type(ZHunterMod_Saved)))
|
||||
|
||||
if type(ZHunterMod_Saved) == "table" then
|
||||
if MTH_CharSavedVariables and MTH_CharSavedVariables.modules then
|
||||
MTH_CharSavedVariables.modules.zhunter = ZHunterMod_Saved
|
||||
MTH_ZH_TraceLocal("sync-saved wrote ZHunterMod_Saved -> MTH_CharSavedVariables.modules.zhunter")
|
||||
end
|
||||
elseif type(moduleStore) == "table" then
|
||||
ZHunterMod_Saved = moduleStore
|
||||
MTH_ZH_TraceLocal("sync-saved loaded moduleStore -> ZHunterMod_Saved")
|
||||
end
|
||||
MTH_ZH_TraceLocal("sync-saved end")
|
||||
end
|
||||
|
||||
MTH_ZH_SetButtonsVisible = function(visible)
|
||||
MTH_ZH_TraceLocal("set-buttons-visible visible=" .. tostring(visible and true or false))
|
||||
local buttonNames = {
|
||||
"zButtonAspect",
|
||||
"zButtonTrack",
|
||||
@@ -274,12 +294,18 @@ MTH_ZH_SetButtonsVisible = function(visible)
|
||||
for _, buttonName in ipairs(buttonNames) do
|
||||
local button = getglobal(buttonName)
|
||||
if button then
|
||||
if type(MTH_ZH_TraceButtonPoint) == "function" then
|
||||
MTH_ZH_TraceButtonPoint(button, "set-buttons-visible:before:" .. tostring(buttonName))
|
||||
end
|
||||
MTH_ZH_SetChildButtonsVisible(button, buttonName, visible)
|
||||
if visible then
|
||||
button:Show()
|
||||
else
|
||||
button:Hide()
|
||||
end
|
||||
if type(MTH_ZH_TraceButtonPoint) == "function" then
|
||||
MTH_ZH_TraceButtonPoint(button, "set-buttons-visible:after:" .. tostring(buttonName))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -288,6 +314,57 @@ MTH_ZH_SetAuxFramesVisible = function(visible)
|
||||
return
|
||||
end
|
||||
|
||||
local function MTH_ZH_SetAdjustmentHandlersActive(active)
|
||||
local frameSpecs = {
|
||||
{ frame = "zButtonAspectAdjustment", handler = "zButtonAspectAdjustment_OnEvent", getter = "zButtonAspect_GetSaved" },
|
||||
{ frame = "zButtonTrackAdjustment", handler = "zButtonTrackAdjustment_OnEvent", getter = "zButtonTrack_GetSaved" },
|
||||
{ frame = "zButtonTrapAdjustment", handler = "zButtonTrapAdjustment_OnEvent", getter = "zButtonTrap_GetSaved" },
|
||||
{ frame = "zButtonRangedAdjustment", handler = "zButtonRangedAdjustment_OnEvent", getter = "zButtonRanged_GetSaved" },
|
||||
{ frame = "zButtonAmmoAdjustment", handler = "zButtonAmmoAdjustment_OnEvent", getter = "zButtonAmmo_GetSaved" },
|
||||
{ frame = "zButtonPetAdjustment", handler = "zButtonPetAdjustment_OnEvent", getter = "zButtonPet_GetSaved" },
|
||||
{ frame = "zButtonMountsAdjustment", handler = "zButtonMountsAdjustment_OnEvent", getter = "zButtonMounts_GetSaved" },
|
||||
{ frame = "zButtonCompanionsAdjustment", handler = "zButtonCompanionsAdjustment_OnEvent", getter = "zButtonCompanions_GetSaved" },
|
||||
{ frame = "zButtonToysAdjustment", handler = "zButtonToysAdjustment_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()
|
||||
return
|
||||
end
|
||||
@@ -307,14 +384,23 @@ function MTH_ZHunter:init()
|
||||
end
|
||||
|
||||
function MTH_ZHunter:setEnabled(enabled)
|
||||
MTH_ZH_TraceLocal("module setEnabled enabled=" .. tostring(enabled and true or false))
|
||||
MTH_ZH_SyncSavedVariables()
|
||||
if enabled then
|
||||
MTH_ZH_EnsureBootstrapRestoreFrame()
|
||||
MTH_ZH_SetAdjustmentHandlersActive(true)
|
||||
MTH_ZH_ApplyEnabledRuntimeState("setEnabled")
|
||||
else
|
||||
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_SetAuxFramesVisible(false)
|
||||
if type(MTH_ZH_TraceAllButtonPoints) == "function" then
|
||||
MTH_ZH_TraceAllButtonPoints("setEnabled:false:after-hide")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
+248
-45
@@ -29,6 +29,70 @@ ZHunterMod_Ammo_Buttons = nil
|
||||
local ZHUNTER_AMMO_MAX_COUNT = math.max(table.getn(MTH_AMMO_ARROWS or {}), table.getn(MTH_AMMO_BULLETS or {}))
|
||||
local zButtonAmmo_Cache = {}
|
||||
local zButtonAmmo_LastCacheSignature = nil
|
||||
local zButtonAmmo_LastRefreshAt = 0
|
||||
local zButtonAmmo_MinRefreshInterval = 0.50
|
||||
local zButtonAmmo_MinBagRefreshInterval = 0.75
|
||||
local zButtonAmmo_KnownAmmoTypes = nil
|
||||
local zButtonAmmo_AmmoBags = {}
|
||||
local zButtonAmmo_LastFullScanAt = 0
|
||||
local zButtonAmmo_MinUnknownBagScanInterval = 5.0
|
||||
local zButtonAmmo_EmptyScanStreak = 0
|
||||
local zButtonAmmo_LastEquippedAmmoSeen = nil
|
||||
local zButtonAmmo_GetKnownAmmoTypes
|
||||
|
||||
local function zButtonAmmo_BagHasAmmoNow(bagId)
|
||||
local bag = tonumber(bagId)
|
||||
if not bag or bag < 0 or bag > 4 then
|
||||
return false
|
||||
end
|
||||
local knownAmmo = zButtonAmmo_GetKnownAmmoTypes and zButtonAmmo_GetKnownAmmoTypes() or nil
|
||||
for slot = 1, (GetContainerNumSlots(bag) or 0) do
|
||||
local link = GetContainerItemLink(bag, slot)
|
||||
if link then
|
||||
local _, _, linkName = string.find(link, "%[(.+)%]")
|
||||
if linkName and knownAmmo and knownAmmo[linkName] then
|
||||
return true
|
||||
end
|
||||
local _, _, id = string.find(link, "Hitem:((%d+).-)")
|
||||
if id then
|
||||
local itemName, _, _, _, _, itemSubtype, _, itemSlot = GetItemInfo(id)
|
||||
if itemSlot == "INVTYPE_AMMO" then
|
||||
return true
|
||||
end
|
||||
if itemName and knownAmmo and knownAmmo[itemName] then
|
||||
return true
|
||||
end
|
||||
if itemSubtype == "Arrow" or itemSubtype == "Bullet" then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function zButtonAmmo_UpdateParentCountFast()
|
||||
if zButtonAmmo and not zButtonAmmo.isspell and zButtonAmmo.ammoname then
|
||||
local ammoSlot = 0
|
||||
if GetInventorySlotInfo then
|
||||
local slotId = GetInventorySlotInfo("AmmoSlot")
|
||||
if slotId and slotId > 0 then
|
||||
ammoSlot = slotId
|
||||
end
|
||||
end
|
||||
local slotForCount = ammoSlot and ammoSlot ~= 0 and ammoSlot or 0
|
||||
if GetInventoryItemCount then
|
||||
local liveCount = GetInventoryItemCount("player", slotForCount)
|
||||
local cachedInfo = zButtonAmmo_Cache[zButtonAmmo.ammoname]
|
||||
if liveCount == 0 and cachedInfo and (tonumber(cachedInfo.count) or 0) > 0 then
|
||||
zButtonAmmo.ammocount = cachedInfo.count
|
||||
elseif liveCount ~= nil then
|
||||
zButtonAmmo.ammocount = liveCount
|
||||
end
|
||||
end
|
||||
zButtonAmmo_UpdateButton(zButtonAmmo)
|
||||
end
|
||||
end
|
||||
|
||||
local function zButtonAmmo_GetSaved()
|
||||
local currentRoot = zButtonAmmo_GetRoot()
|
||||
@@ -38,6 +102,21 @@ local function zButtonAmmo_GetSaved()
|
||||
return currentRoot["zButtonAmmo"]
|
||||
end
|
||||
|
||||
zButtonAmmo_GetKnownAmmoTypes = function()
|
||||
if zButtonAmmo_KnownAmmoTypes then
|
||||
return zButtonAmmo_KnownAmmoTypes
|
||||
end
|
||||
local knownAmmo = {}
|
||||
for i = 1, table.getn(MTH_AMMO_ARROWS or {}) do
|
||||
knownAmmo[(MTH_AMMO_ARROWS or {})[i]] = "Arrow"
|
||||
end
|
||||
for i = 1, table.getn(MTH_AMMO_BULLETS or {}) do
|
||||
knownAmmo[(MTH_AMMO_BULLETS or {})[i]] = "Bullet"
|
||||
end
|
||||
zButtonAmmo_KnownAmmoTypes = knownAmmo
|
||||
return knownAmmo
|
||||
end
|
||||
|
||||
local zButtonAmmo_ShortArrowLabels = {
|
||||
[ARROWS_ROUGH] = "Rough",
|
||||
[ARROWS_SHARP] = "Sharp",
|
||||
@@ -164,13 +243,7 @@ local function zButtonAmmo_GetEquippedAmmoLink()
|
||||
end
|
||||
|
||||
local function zButtonAmmo_RebuildCache()
|
||||
local knownAmmo = {}
|
||||
for i = 1, table.getn(MTH_AMMO_ARROWS or {}) do
|
||||
knownAmmo[(MTH_AMMO_ARROWS or {})[i]] = "Arrow"
|
||||
end
|
||||
for i = 1, table.getn(MTH_AMMO_BULLETS or {}) do
|
||||
knownAmmo[(MTH_AMMO_BULLETS or {})[i]] = "Bullet"
|
||||
end
|
||||
local knownAmmo = zButtonAmmo_GetKnownAmmoTypes()
|
||||
|
||||
local equippedAmmo = nil
|
||||
local equippedLink = zButtonAmmo_GetEquippedAmmoLink()
|
||||
@@ -185,11 +258,14 @@ local function zButtonAmmo_RebuildCache()
|
||||
end
|
||||
end
|
||||
|
||||
zButtonAmmo_Cache = {}
|
||||
local newCache = {}
|
||||
local newAmmoBags = {}
|
||||
local scannedLinkCount = 0
|
||||
for bag = 0, 4 do
|
||||
for slot = 1, GetContainerNumSlots(bag) do
|
||||
local link = GetContainerItemLink(bag, slot)
|
||||
if link then
|
||||
scannedLinkCount = scannedLinkCount + 1
|
||||
local _, _, id = string.find(link, "Hitem:((%d+).-)")
|
||||
if id then
|
||||
local _, _, linkName = string.find(link, "%[(.+)%]")
|
||||
@@ -208,7 +284,8 @@ local function zButtonAmmo_RebuildCache()
|
||||
end
|
||||
|
||||
if isAmmo and ammoName then
|
||||
local ammoInfo = zButtonAmmo_Cache[ammoName]
|
||||
newAmmoBags[bag] = true
|
||||
local ammoInfo = newCache[ammoName]
|
||||
if not ammoInfo then
|
||||
ammoInfo = {
|
||||
ammo = ammoName,
|
||||
@@ -224,7 +301,7 @@ local function zButtonAmmo_RebuildCache()
|
||||
count = 0,
|
||||
equip = nil,
|
||||
}
|
||||
zButtonAmmo_Cache[ammoName] = ammoInfo
|
||||
newCache[ammoName] = ammoInfo
|
||||
end
|
||||
ammoInfo.count = (ammoInfo.count or 0) + (itemCount or 0)
|
||||
if equippedAmmo and equippedAmmo == ammoName then
|
||||
@@ -235,6 +312,26 @@ local function zButtonAmmo_RebuildCache()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local hasAmmo = next(newCache) ~= nil
|
||||
local previousHadAmmo = next(zButtonAmmo_Cache) ~= nil
|
||||
if hasAmmo then
|
||||
zButtonAmmo_EmptyScanStreak = 0
|
||||
zButtonAmmo_Cache = newCache
|
||||
zButtonAmmo_AmmoBags = newAmmoBags
|
||||
else
|
||||
local reliableEmptyScan = scannedLinkCount > 0 and not equippedAmmo
|
||||
if reliableEmptyScan then
|
||||
zButtonAmmo_EmptyScanStreak = (zButtonAmmo_EmptyScanStreak or 0) + 1
|
||||
else
|
||||
zButtonAmmo_EmptyScanStreak = 0
|
||||
end
|
||||
if not previousHadAmmo or zButtonAmmo_EmptyScanStreak >= 3 then
|
||||
zButtonAmmo_Cache = newCache
|
||||
zButtonAmmo_AmmoBags = newAmmoBags
|
||||
end
|
||||
end
|
||||
zButtonAmmo_LastFullScanAt = GetTime and GetTime() or zButtonAmmo_LastFullScanAt
|
||||
end
|
||||
|
||||
local function zButtonAmmo_AssignButtonFromAmmoInfo(button, ammoInfo)
|
||||
@@ -257,15 +354,41 @@ local function zButtonAmmo_AssignButtonFromAmmoInfo(button, ammoInfo)
|
||||
return true
|
||||
end
|
||||
|
||||
local function zButtonAmmo_GetCacheSignature()
|
||||
local names = {}
|
||||
for ammoName, ammoInfo in pairs(zButtonAmmo_Cache or {}) do
|
||||
if ammoName and ammoInfo and (tonumber(ammoInfo.count) or 0) > 0 then
|
||||
table.insert(names, tostring(ammoName))
|
||||
local function zButtonAmmo_GetCacheSignature(ammoList)
|
||||
local hash = 17
|
||||
local list = ammoList or {}
|
||||
local mod = math.fmod or math.mod
|
||||
for i = 1, table.getn(list) do
|
||||
local ammoName = list[i]
|
||||
local ammoInfo = ammoName and zButtonAmmo_Cache[ammoName] or nil
|
||||
local ammoCount = (ammoInfo and tonumber(ammoInfo.count)) or 0
|
||||
local value = (hash * 131) + ammoCount + (string.len(tostring(ammoName or "")) * 17)
|
||||
if mod then
|
||||
hash = mod(value, 2147483647)
|
||||
else
|
||||
hash = value - (math.floor(value / 2147483647) * 2147483647)
|
||||
end
|
||||
end
|
||||
table.sort(names)
|
||||
return table.concat(names, "|")
|
||||
return hash
|
||||
end
|
||||
|
||||
local function zButtonAmmo_AssignParentFromChild(child)
|
||||
if not (zButtonAmmo and child) then
|
||||
return
|
||||
end
|
||||
zButtonAmmo.id = child.ammoid or child.id
|
||||
zButtonAmmo.icon = child.icon
|
||||
zButtonAmmo.isspell = nil
|
||||
zButtonAmmo.ammoname = child.ammoname
|
||||
zButtonAmmo.ammobrol = child.ammobrol
|
||||
zButtonAmmo.ammoqual = child.ammoqual
|
||||
zButtonAmmo.ammolvl = child.ammolvl
|
||||
zButtonAmmo.ammotype = child.ammotype
|
||||
zButtonAmmo.ammobag = child.ammobag
|
||||
zButtonAmmo.ammoslot = child.ammoslot
|
||||
zButtonAmmo.ammoid = child.ammoid or child.id
|
||||
zButtonAmmo.ammolink = child.ammolink
|
||||
zButtonAmmo.ammocount = child.ammocount
|
||||
end
|
||||
|
||||
local function zButtonAmmo_GetEquippedAmmoInfo()
|
||||
@@ -461,7 +584,7 @@ function zButtonAmmo_SetButtons(parent, ammoList)
|
||||
else
|
||||
parent:Show()
|
||||
end
|
||||
zButtonAmmo_LastCacheSignature = zButtonAmmo_GetCacheSignature()
|
||||
zButtonAmmo_LastCacheSignature = zButtonAmmo_GetCacheSignature(ammoList)
|
||||
return count - 1
|
||||
end
|
||||
|
||||
@@ -685,6 +808,8 @@ function zButtonAmmo_OnEvent()
|
||||
zButtonAmmoAdjustment = CreateFrame("Frame", "zButtonAmmoAdjustment")
|
||||
zButtonAmmoAdjustment:RegisterEvent("UNIT_INVENTORY_CHANGED")
|
||||
zButtonAmmoAdjustment:RegisterEvent("BAG_UPDATE")
|
||||
zButtonAmmoAdjustment:RegisterEvent("PLAYER_ALIVE")
|
||||
zButtonAmmoAdjustment:RegisterEvent("PLAYER_UNGHOST")
|
||||
zButtonAmmoAdjustment:SetScript("OnEvent", zButtonAmmoAdjustment_OnEvent)
|
||||
zButtonAmmo_SetupSizeAndPosition()
|
||||
zButtonAmmo_DeferredStartupSync()
|
||||
@@ -750,11 +875,17 @@ function zButtonAmmo_SetupSizeAndPosition()
|
||||
zButtonAmmo_EnsureSpellOrder(ZHunterMod_Ammo_Buttons or zButtonAmmo_GetAmmoList())
|
||||
local saved = zButtonAmmo_GetSaved()
|
||||
if saved["enabled"] == false or saved["enabled"] == 0 then
|
||||
if zButtonAmmoAdjustment and zButtonAmmoAdjustment.SetScript then
|
||||
zButtonAmmoAdjustment:SetScript("OnEvent", nil)
|
||||
end
|
||||
if zButtonAmmo and zButtonAmmo.Hide then
|
||||
zButtonAmmo:Hide()
|
||||
end
|
||||
return
|
||||
end
|
||||
if zButtonAmmoAdjustment and zButtonAmmoAdjustment.SetScript then
|
||||
zButtonAmmoAdjustment:SetScript("OnEvent", zButtonAmmoAdjustment_OnEvent)
|
||||
end
|
||||
local ammoList = ZHunterMod_Ammo_Buttons or zButtonAmmo_GetAmmoList()
|
||||
local arrangeCount = zButtonAmmo.found or table.getn(ammoList)
|
||||
if arrangeCount < 0 then
|
||||
@@ -801,14 +932,79 @@ function zButtonAmmoAdjustment_OnEvent()
|
||||
if not zButtonAmmo or not zButtonAmmo.count then
|
||||
return
|
||||
end
|
||||
if event == "UNIT_INVENTORY_CHANGED" and arg1 and arg1 ~= "player" then
|
||||
return
|
||||
end
|
||||
local saved = zButtonAmmo_GetSaved()
|
||||
if saved["enabled"] == false or saved["enabled"] == 0 then
|
||||
if zButtonAmmoAdjustment and zButtonAmmoAdjustment.SetScript then
|
||||
zButtonAmmoAdjustment:SetScript("OnEvent", nil)
|
||||
end
|
||||
if zButtonAmmo and zButtonAmmo.Hide then
|
||||
zButtonAmmo:Hide()
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if event == "UNIT_INVENTORY_CHANGED" or event == "BAG_UPDATE" then
|
||||
if event == "UNIT_INVENTORY_CHANGED" or event == "BAG_UPDATE" or event == "PLAYER_ALIVE" or event == "PLAYER_UNGHOST" then
|
||||
local now = GetTime and GetTime() or 0
|
||||
if event == "UNIT_INVENTORY_CHANGED" then
|
||||
local equippedNow = zButtonAmmo_GetEquippedAmmoName()
|
||||
if equippedNow == zButtonAmmo_LastEquippedAmmoSeen and now > 0 and zButtonAmmo_LastRefreshAt > 0 and (now - zButtonAmmo_LastRefreshAt) < 1.0 then
|
||||
zButtonAmmo_UpdateParentCountFast()
|
||||
return
|
||||
end
|
||||
zButtonAmmo_LastEquippedAmmoSeen = equippedNow
|
||||
end
|
||||
local bagIsAmmoRelated = false
|
||||
if event == "BAG_UPDATE" and arg1 ~= nil then
|
||||
local bagId = tonumber(arg1)
|
||||
local bagHasAmmoNow = nil
|
||||
if type(zButtonAmmo_BagHasAmmoNow) == "function" then
|
||||
bagHasAmmoNow = zButtonAmmo_BagHasAmmoNow
|
||||
elseif type(_G) == "table" and type(_G["zButtonAmmo_BagHasAmmoNow"]) == "function" then
|
||||
bagHasAmmoNow = _G["zButtonAmmo_BagHasAmmoNow"]
|
||||
end
|
||||
local unknownBagHasAmmo = false
|
||||
if bagId and bagHasAmmoNow then
|
||||
unknownBagHasAmmo = bagHasAmmoNow(bagId) and true or false
|
||||
end
|
||||
if bagId and (zButtonAmmo_AmmoBags[bagId] or unknownBagHasAmmo) then
|
||||
bagIsAmmoRelated = true
|
||||
end
|
||||
if bagId and not zButtonAmmo_AmmoBags[bagId] then
|
||||
if (not unknownBagHasAmmo) and now > 0 and zButtonAmmo_LastFullScanAt > 0 and (now - zButtonAmmo_LastFullScanAt) < zButtonAmmo_MinUnknownBagScanInterval then
|
||||
zButtonAmmo_UpdateParentCountFast()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
local minInterval = zButtonAmmo_MinRefreshInterval
|
||||
if event == "BAG_UPDATE" then
|
||||
if bagIsAmmoRelated then
|
||||
minInterval = 0
|
||||
else
|
||||
minInterval = zButtonAmmo_MinBagRefreshInterval
|
||||
end
|
||||
if UnitAffectingCombat and UnitAffectingCombat("player") then
|
||||
minInterval = 1.50
|
||||
if bagIsAmmoRelated then
|
||||
minInterval = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
if now > 0 and zButtonAmmo_LastRefreshAt > 0 and (now - zButtonAmmo_LastRefreshAt) < minInterval then
|
||||
zButtonAmmo_UpdateParentCountFast()
|
||||
return
|
||||
end
|
||||
zButtonAmmo_LastRefreshAt = now
|
||||
|
||||
local ammoList = zButtonAmmo_GetAmmoList()
|
||||
local listChanged = (ZHunterMod_Ammo_Buttons ~= ammoList)
|
||||
ZHunterMod_Ammo_Buttons = ammoList
|
||||
zButtonAmmo_RebuildCache()
|
||||
local cacheSignature = zButtonAmmo_GetCacheSignature()
|
||||
local cacheSignature = zButtonAmmo_GetCacheSignature(ammoList)
|
||||
local rebuiltButtons = false
|
||||
if listChanged or cacheSignature ~= zButtonAmmo_LastCacheSignature then
|
||||
zButtonAmmo_EnsureSpellOrder(ammoList)
|
||||
local info = {}
|
||||
@@ -822,15 +1018,10 @@ function zButtonAmmoAdjustment_OnEvent()
|
||||
end
|
||||
zButtonAmmo.found = ZSpellButton_SetButtons(zButtonAmmo, info)
|
||||
zButtonAmmo_SetupSizeAndPosition()
|
||||
zButtonAmmo_LastCacheSignature = zButtonAmmo_GetCacheSignature()
|
||||
end
|
||||
-- Update ammo counts for child buttons
|
||||
for i=1, zButtonAmmo.count do
|
||||
local button = getglobal("zButtonAmmo"..i)
|
||||
if button and button.ammoname and not button.isspell then
|
||||
zButtonAmmo_UpdateButton(button)
|
||||
end
|
||||
zButtonAmmo_LastCacheSignature = cacheSignature
|
||||
rebuiltButtons = true
|
||||
end
|
||||
|
||||
local equippedAmmoName = zButtonAmmo_GetEquippedAmmoName()
|
||||
local equippedInfo = nil
|
||||
if equippedAmmoName then
|
||||
@@ -839,44 +1030,56 @@ function zButtonAmmoAdjustment_OnEvent()
|
||||
for i=1, zButtonAmmo.count do
|
||||
local child = getglobal("zButtonAmmo"..i)
|
||||
if child and child.ammoname == equippedAmmoName and not child.isspell then
|
||||
equippedInfo = {
|
||||
ammo = child.ammoname,
|
||||
brol = child.ammobrol,
|
||||
quality = child.ammoqual,
|
||||
lvl = child.ammolvl,
|
||||
type = child.ammotype,
|
||||
bag = child.ammobag,
|
||||
slot = child.ammoslot,
|
||||
id = child.ammoid or child.id,
|
||||
link = child.ammolink,
|
||||
icon = child.icon,
|
||||
count = child.ammocount,
|
||||
}
|
||||
zButtonAmmo_AssignParentFromChild(child)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not equippedInfo then
|
||||
if not equippedInfo and event ~= "BAG_UPDATE" then
|
||||
equippedInfo = zButtonAmmo_GetEquippedAmmoInfo()
|
||||
if equippedInfo and equippedInfo.ammo and not equippedAmmoName then
|
||||
equippedAmmoName = equippedInfo.ammo
|
||||
end
|
||||
end
|
||||
|
||||
if not rebuiltButtons then
|
||||
for i=1, zButtonAmmo.count do
|
||||
local child = getglobal("zButtonAmmo"..i)
|
||||
if child and child.ammoname and not child.isspell then
|
||||
local cacheInfo = zButtonAmmo_Cache[child.ammoname]
|
||||
local newCount = cacheInfo and cacheInfo.count or 0
|
||||
if (child.ammocount or 0) ~= (newCount or 0) then
|
||||
if cacheInfo then
|
||||
child.ammobag = cacheInfo.bag
|
||||
child.ammoslot = cacheInfo.slot
|
||||
child.ammoqual = cacheInfo.quality
|
||||
child.ammobrol = cacheInfo.brol
|
||||
child.ammolvl = cacheInfo.lvl
|
||||
child.ammotype = cacheInfo.type
|
||||
child.ammoid = cacheInfo.id
|
||||
child.ammolink = cacheInfo.link
|
||||
child.icon = cacheInfo.icon
|
||||
end
|
||||
child.ammocount = newCount
|
||||
zButtonAmmo_UpdateButton(child)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if equippedInfo and equippedInfo.ammo and equippedInfo.ammo ~= zButtonAmmo.ammoname then
|
||||
zButtonAmmo_AssignButtonFromAmmoInfo(zButtonAmmo, equippedInfo)
|
||||
end
|
||||
|
||||
-- Also update parent if it's showing ammo (not a spell)
|
||||
if zButtonAmmo and not zButtonAmmo.isspell and zButtonAmmo.ammoname then
|
||||
zButtonAmmo_UpdateButton(zButtonAmmo)
|
||||
end
|
||||
zButtonAmmo_UpdateParentCountFast()
|
||||
|
||||
-- Save the currently equipped ammo for restoration on next reload
|
||||
if equippedAmmoName then
|
||||
zButtonAmmo_SaveEquippedAmmo(equippedAmmoName)
|
||||
zButtonAmmo_LastEquippedAmmoSeen = equippedAmmoName
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -32,6 +32,12 @@ ZHunterMod_Aspect_Spells = {
|
||||
}
|
||||
|
||||
local ZHUNTER_ASPECT_MAX = table.getn(ZHunterMod_Aspect_Spells)
|
||||
local zButtonAspect_LastAuraUpdateAt = 0
|
||||
local zButtonAspect_MinAuraInterval = 0.15
|
||||
local zButtonAspect_MinAuraIntervalCombat = 0.60
|
||||
local zButtonAspect_LastAuraTexture = nil
|
||||
local zButtonAspect_LastParentId = nil
|
||||
local zButtonAspect_AuraProbeTextLeft1 = nil
|
||||
|
||||
local function zButtonAspect_GetSaved()
|
||||
local currentRoot = zButtonAspect_GetRoot()
|
||||
@@ -158,7 +164,13 @@ function zButtonAspect_OnEvent()
|
||||
zButtonAspectAdjustment:RegisterEvent("CHARACTER_POINTS_CHANGED")
|
||||
zButtonAspectAdjustment:RegisterEvent("LEARNED_SPELL_IN_TAB")
|
||||
zButtonAspectAdjustment:SetScript("OnEvent", zButtonAspectAdjustment_OnEvent)
|
||||
zButtonAspect_Tooltip = CreateFrame("GameTooltip", "zButtonAspect_Tooltip", nil, "GameTooltipTemplate")
|
||||
zButtonAspect_Tooltip = CreateFrame("GameTooltip", "zButtonAspect_AuraProbeScan", nil, "GameTooltipTemplate")
|
||||
if zButtonAspect_Tooltip and zButtonAspect_Tooltip.GetName then
|
||||
local tooltipName = zButtonAspect_Tooltip:GetName()
|
||||
if tooltipName then
|
||||
zButtonAspect_AuraProbeTextLeft1 = getglobal(tooltipName .. "TextLeft1")
|
||||
end
|
||||
end
|
||||
zButtonAspect_SetupSizeAndPosition()
|
||||
end
|
||||
end
|
||||
@@ -191,11 +203,17 @@ function zButtonAspect_SetupSizeAndPosition()
|
||||
zButtonAspect_EnsureConfig()
|
||||
local saved = zButtonAspect_GetSaved()
|
||||
if saved["enabled"] == false or saved["enabled"] == 0 then
|
||||
if zButtonAspectAdjustment and zButtonAspectAdjustment.SetScript then
|
||||
zButtonAspectAdjustment:SetScript("OnEvent", nil)
|
||||
end
|
||||
if zButtonAspect and zButtonAspect.Hide then
|
||||
zButtonAspect:Hide()
|
||||
end
|
||||
return
|
||||
end
|
||||
if zButtonAspectAdjustment and zButtonAspectAdjustment.SetScript then
|
||||
zButtonAspectAdjustment:SetScript("OnEvent", zButtonAspectAdjustment_OnEvent)
|
||||
end
|
||||
local displayCount = zButtonAspect.found or ZHUNTER_ASPECT_MAX
|
||||
if displayCount < 0 then
|
||||
displayCount = 0
|
||||
@@ -234,6 +252,17 @@ function zButtonAspectAdjustment_OnEvent()
|
||||
if not zButtonAspect or not zButtonAspect.count then
|
||||
return
|
||||
end
|
||||
if event == "PLAYER_AURAS_CHANGED" then
|
||||
local now = GetTime and GetTime() or 0
|
||||
local minInterval = zButtonAspect_MinAuraInterval
|
||||
if UnitAffectingCombat and UnitAffectingCombat("player") then
|
||||
minInterval = zButtonAspect_MinAuraIntervalCombat
|
||||
end
|
||||
if now > 0 and zButtonAspect_LastAuraUpdateAt > 0 and (now - zButtonAspect_LastAuraUpdateAt) < minInterval then
|
||||
return
|
||||
end
|
||||
zButtonAspect_LastAuraUpdateAt = now
|
||||
end
|
||||
if event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" or event == "LEARNED_SPELL_IN_TAB" then
|
||||
zButtonAspect_CreateButtons()
|
||||
zButtonAspect_SetupSizeAndPosition()
|
||||
@@ -245,45 +274,78 @@ function zButtonAspectAdjustment_OnEvent()
|
||||
if not zButtonAspect1.id then
|
||||
return
|
||||
end
|
||||
local buttontextures = {}
|
||||
local button
|
||||
for i=1, zButtonAspect.count do
|
||||
button = getglobal(zButtonAspect.name..i)
|
||||
button.icon = nil
|
||||
if button.id then
|
||||
buttontextures[GetSpellTexture(button.id, "spell")] = button
|
||||
local isParentTooltipOwned = GameTooltip and GameTooltip.IsOwned and GameTooltip:IsOwned(zButtonAspect)
|
||||
local childrenShown = zButtonAspect.children and zButtonAspect.children.IsShown and zButtonAspect.children:IsShown()
|
||||
local needChildIconScan = (event ~= "PLAYER_AURAS_CHANGED") or childrenShown or isParentTooltipOwned
|
||||
local buttontextures = nil
|
||||
local hasDuplicateChildTexture = nil
|
||||
if needChildIconScan then
|
||||
buttontextures = {}
|
||||
local textureSeen = {}
|
||||
for i=1, zButtonAspect.count do
|
||||
button = getglobal(zButtonAspect.name..i)
|
||||
button.icon = nil
|
||||
if button.id then
|
||||
local btnTexture = GetSpellTexture(button.id, "spell")
|
||||
if btnTexture then
|
||||
if textureSeen[btnTexture] then
|
||||
hasDuplicateChildTexture = true
|
||||
elseif hasDuplicateChildTexture == nil then
|
||||
hasDuplicateChildTexture = false
|
||||
end
|
||||
textureSeen[btnTexture] = 1
|
||||
buttontextures[btnTexture] = button
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local i = 1
|
||||
local texture = GetSpellTexture(zButtonAspect1.id, "spell")
|
||||
local buff = UnitBuff("player", i)
|
||||
local spellname, buffname
|
||||
zButtonAspect.id = zButtonAspect1.id
|
||||
local newParentId = zButtonAspect1.id
|
||||
while buff do
|
||||
if texture == buff and zButtonAspect2.id then
|
||||
zButtonAspect.id = zButtonAspect2.id
|
||||
newParentId = zButtonAspect2.id
|
||||
end
|
||||
if buttontextures[buff] then
|
||||
zButtonAspect_Tooltip:SetOwner(this, "ANCHOR_NONE")
|
||||
zButtonAspect_Tooltip:SetUnitBuff("player", i)
|
||||
buffname = zButtonAspect_TooltipTextLeft1:GetText()
|
||||
spellname = GetSpellName(buttontextures[buff].id, "spell")
|
||||
if buffname == spellname then
|
||||
if needChildIconScan and buttontextures[buff] then
|
||||
if hasDuplicateChildTexture then
|
||||
zButtonAspect_Tooltip:SetOwner(this, "ANCHOR_NONE")
|
||||
zButtonAspect_Tooltip:SetUnitBuff("player", i)
|
||||
if zButtonAspect_AuraProbeTextLeft1 and zButtonAspect_AuraProbeTextLeft1.GetText then
|
||||
buffname = zButtonAspect_AuraProbeTextLeft1:GetText()
|
||||
else
|
||||
buffname = nil
|
||||
end
|
||||
spellname = GetSpellName(buttontextures[buff].id, "spell")
|
||||
if buffname == spellname then
|
||||
buttontextures[buff].icon = "Interface\\Icons\\Spell_Nature_WispSplode"
|
||||
end
|
||||
else
|
||||
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)
|
||||
for i=1, zButtonAspect.count do
|
||||
button = getglobal(zButtonAspect.name..i)
|
||||
if button.id then
|
||||
ZSpellButton_UpdateButton(button)
|
||||
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 GameTooltip:IsOwned(zButtonAspect) then
|
||||
if isParentTooltipOwned then
|
||||
ZSpellButtonParent_OnEnter(zButtonAspect)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -22,6 +22,20 @@ if not root["zButtonCompanions"] then
|
||||
end
|
||||
|
||||
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 currentRoot = zButtonCompanions_GetRoot()
|
||||
@@ -233,11 +247,17 @@ end
|
||||
function zButtonCompanions_SetupSizeAndPosition()
|
||||
local saved = zButtonCompanions_GetSaved()
|
||||
if saved["enabled"] == false or saved["enabled"] == 0 then
|
||||
if zButtonCompanionsAdjustment and zButtonCompanionsAdjustment.SetScript then
|
||||
zButtonCompanionsAdjustment:SetScript("OnEvent", nil)
|
||||
end
|
||||
if zButtonCompanions and zButtonCompanions.Hide then
|
||||
zButtonCompanions:Hide()
|
||||
end
|
||||
return
|
||||
end
|
||||
if zButtonCompanionsAdjustment and zButtonCompanionsAdjustment.SetScript then
|
||||
zButtonCompanionsAdjustment:SetScript("OnEvent", zButtonCompanionsAdjustment_OnEvent)
|
||||
end
|
||||
local displayCount = zButtonCompanions.found or 0
|
||||
if displayCount < 0 then
|
||||
displayCount = 0
|
||||
@@ -275,6 +295,18 @@ function zButtonCompanionsAdjustment_OnEvent()
|
||||
if not zButtonCompanions then
|
||||
return
|
||||
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_SetupSizeAndPosition()
|
||||
if GameTooltip:IsOwned(zButtonCompanions) then
|
||||
|
||||
@@ -22,6 +22,20 @@ if not root["zButtonMounts"] then
|
||||
end
|
||||
|
||||
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 currentRoot = zButtonMounts_GetRoot()
|
||||
@@ -233,11 +247,17 @@ end
|
||||
function zButtonMounts_SetupSizeAndPosition()
|
||||
local saved = zButtonMounts_GetSaved()
|
||||
if saved["enabled"] == false or saved["enabled"] == 0 then
|
||||
if zButtonMountsAdjustment and zButtonMountsAdjustment.SetScript then
|
||||
zButtonMountsAdjustment:SetScript("OnEvent", nil)
|
||||
end
|
||||
if zButtonMounts and zButtonMounts.Hide then
|
||||
zButtonMounts:Hide()
|
||||
end
|
||||
return
|
||||
end
|
||||
if zButtonMountsAdjustment and zButtonMountsAdjustment.SetScript then
|
||||
zButtonMountsAdjustment:SetScript("OnEvent", zButtonMountsAdjustment_OnEvent)
|
||||
end
|
||||
local displayCount = zButtonMounts.found or 0
|
||||
if displayCount < 0 then
|
||||
displayCount = 0
|
||||
@@ -275,6 +295,18 @@ function zButtonMountsAdjustment_OnEvent()
|
||||
if not zButtonMounts then
|
||||
return
|
||||
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_SetupSizeAndPosition()
|
||||
if GameTooltip:IsOwned(zButtonMounts) then
|
||||
|
||||
@@ -43,6 +43,11 @@ ZHunterMod_Pet_Spells = {
|
||||
|
||||
local ZHUNTER_PET_MAX = table.getn(ZHunterMod_Pet_Spells)
|
||||
local zButtonPet_SetButtons
|
||||
local zButtonPet_LastRefreshAt = 0
|
||||
local zButtonPet_MinRefreshInterval = 0.15
|
||||
local zButtonPet_MinCombatRefreshInterval = 0.30
|
||||
local zButtonPet_RuntimeSpellMap = nil
|
||||
local zButtonPet_LastStateKey = nil
|
||||
|
||||
local function zButtonPet_GetSaved()
|
||||
local currentRoot = zButtonPet_GetRoot()
|
||||
@@ -134,6 +139,40 @@ local function zButtonPet_ApplyRuntimeSettings()
|
||||
zButtonPet.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false
|
||||
end
|
||||
|
||||
local function zButtonPet_RebuildRuntimeSpellMap()
|
||||
if not zButtonPet or not zButtonPet.count then
|
||||
zButtonPet_RuntimeSpellMap = {}
|
||||
return zButtonPet_RuntimeSpellMap
|
||||
end
|
||||
local spells = {}
|
||||
for i=1, zButtonPet.count do
|
||||
local button = getglobal(zButtonPet.name..i)
|
||||
if button and button.id then
|
||||
local spellName = GetSpellName(button.id, "spell")
|
||||
if spellName and spellName ~= "" then
|
||||
spells[spellName] = button.id
|
||||
end
|
||||
end
|
||||
end
|
||||
zButtonPet_RuntimeSpellMap = spells
|
||||
return spells
|
||||
end
|
||||
|
||||
local function zButtonPet_GetPreferredDefaultParentId(spells)
|
||||
if zButtonPet1 and zButtonPet1.id then
|
||||
return zButtonPet1.id
|
||||
end
|
||||
if zButtonPet and zButtonPet.count then
|
||||
for i = 1, zButtonPet.count do
|
||||
local child = getglobal("zButtonPet" .. i)
|
||||
if child and child.id then
|
||||
return child.id
|
||||
end
|
||||
end
|
||||
end
|
||||
return spells[ZHUNTER_PET_EYES] or spells[ZHUNTER_PET_POSITION] or spells[ZHUNTER_PET_DISMISS]
|
||||
end
|
||||
|
||||
function zButtonPet_OnLoad()
|
||||
this:RegisterEvent("VARIABLES_LOADED")
|
||||
end
|
||||
@@ -161,7 +200,6 @@ function zButtonPet_OnEvent()
|
||||
zButtonPetAdjustment:RegisterEvent("SPELLS_CHANGED")
|
||||
zButtonPetAdjustment:RegisterEvent("LEARNED_SPELL_IN_TAB")
|
||||
zButtonPetAdjustment:SetScript("OnEvent", zButtonPetAdjustment_OnEvent)
|
||||
zButtonPet_Tooltip = CreateFrame("GameTooltip", "zButtonPet_Tooltip", nil, "GameTooltipTemplate")
|
||||
zButtonPet_SetupSizeAndPosition()
|
||||
zButtonPetAdjustment_OnEvent()
|
||||
end
|
||||
@@ -188,16 +226,24 @@ function zButtonPet_CreateButtons()
|
||||
end
|
||||
zButtonPet.found = ZSpellButton_SetButtons(zButtonPet, info)
|
||||
zButtonPet_ApplyRuntimeSettings()
|
||||
zButtonPet_RebuildRuntimeSpellMap()
|
||||
zButtonPet_LastStateKey = nil
|
||||
end
|
||||
|
||||
function zButtonPet_SetupSizeAndPosition()
|
||||
local saved = zButtonPet_GetSaved()
|
||||
if saved["enabled"] == false or saved["enabled"] == 0 then
|
||||
if zButtonPetAdjustment and zButtonPetAdjustment.SetScript then
|
||||
zButtonPetAdjustment:SetScript("OnEvent", nil)
|
||||
end
|
||||
if zButtonPet and zButtonPet.Hide then
|
||||
zButtonPet:Hide()
|
||||
end
|
||||
return
|
||||
end
|
||||
if zButtonPetAdjustment and zButtonPetAdjustment.SetScript then
|
||||
zButtonPetAdjustment:SetScript("OnEvent", zButtonPetAdjustment_OnEvent)
|
||||
end
|
||||
local displayCount = zButtonPet.found or ZHUNTER_PET_MAX
|
||||
if displayCount < 0 then
|
||||
displayCount = 0
|
||||
@@ -434,20 +480,12 @@ local function zButtonPet_RefreshParentSpell()
|
||||
zButtonPet_RefreshSavedPetState(saved, corePetInfo)
|
||||
|
||||
local status, happiness, dead
|
||||
local spells = {}
|
||||
local name
|
||||
local choice
|
||||
for i=1, zButtonPet.count do
|
||||
local button
|
||||
button = getglobal(zButtonPet.name..i)
|
||||
if button and button.id then
|
||||
name = GetSpellName(button.id, "spell")
|
||||
spells[name] = button
|
||||
if not choice and (name == ZHUNTER_PET_DISMISS or name == ZHUNTER_PET_EYES or name == ZHUNTER_PET_POSITION) then
|
||||
choice = button
|
||||
end
|
||||
end
|
||||
local spells = zButtonPet_RuntimeSpellMap
|
||||
if not spells then
|
||||
spells = zButtonPet_RebuildRuntimeSpellMap()
|
||||
end
|
||||
local name
|
||||
local choiceId = zButtonPet_GetPreferredDefaultParentId(spells)
|
||||
status = saved["pet"]["status"]
|
||||
happiness = saved["pet"]["happiness"]
|
||||
dead = saved["pet"]["dead"]
|
||||
@@ -464,22 +502,34 @@ local function zButtonPet_RefreshParentSpell()
|
||||
name = ZHUNTER_PET_MEND
|
||||
elseif happiness ~= 3 then
|
||||
name = ZHUNTER_PET_FEED
|
||||
elseif choice then
|
||||
id = choice.id
|
||||
elseif choiceId then
|
||||
id = choiceId
|
||||
end
|
||||
|
||||
if name and spells[name] then
|
||||
id = spells[name].id
|
||||
id = spells[name]
|
||||
elseif name then
|
||||
local fallbackId = zButtonPet_FindSpellIdByName(name)
|
||||
if fallbackId then
|
||||
spells[name] = fallbackId
|
||||
id = fallbackId
|
||||
end
|
||||
end
|
||||
local isOwned = GameTooltip and GameTooltip.IsOwned and GameTooltip:IsOwned(zButtonPet)
|
||||
local stateKey = tostring(hasCurrentPet and 1 or 0)
|
||||
..":"..tostring(hasLivePet and 1 or 0)
|
||||
..":"..tostring(status or "")
|
||||
..":"..tostring(happiness or "")
|
||||
..":"..tostring(dead or 0)
|
||||
..":"..tostring(id or 0)
|
||||
if zButtonPet.id == id and zButtonPet_LastStateKey == stateKey and not isOwned then
|
||||
return
|
||||
end
|
||||
zButtonPet_LastStateKey = stateKey
|
||||
zButtonPet.id = id
|
||||
ZSpellButton_UpdateButton(zButtonPet)
|
||||
ZSpellButton_UpdateCooldown(zButtonPet)
|
||||
if GameTooltip:IsOwned(zButtonPet) then
|
||||
if isOwned then
|
||||
ZSpellButtonParent_OnEnter(zButtonPet)
|
||||
end
|
||||
end
|
||||
@@ -503,6 +553,21 @@ function zButtonPetAdjustment_OnEvent()
|
||||
if event == "UNIT_PET" and arg1 and arg1 ~= "player" then
|
||||
return
|
||||
end
|
||||
if event == "SPELLS_CHANGED" or event == "LEARNED_SPELL_IN_TAB" then
|
||||
zButtonPet_CreateButtons()
|
||||
zButtonPet_SetupSizeAndPosition()
|
||||
end
|
||||
if event == "UNIT_HEALTH" or event == "UNIT_HAPPINESS" or event == "PET_BAR_UPDATE" then
|
||||
local now = GetTime and GetTime() or 0
|
||||
local minInterval = zButtonPet_MinRefreshInterval
|
||||
if UnitAffectingCombat and UnitAffectingCombat("player") then
|
||||
minInterval = zButtonPet_MinCombatRefreshInterval
|
||||
end
|
||||
if now > 0 and zButtonPet_LastRefreshAt > 0 and (now - zButtonPet_LastRefreshAt) < minInterval then
|
||||
return
|
||||
end
|
||||
zButtonPet_LastRefreshAt = now
|
||||
end
|
||||
zButtonPet_RefreshParentSpell()
|
||||
end
|
||||
|
||||
|
||||
@@ -27,6 +27,11 @@ ZHunterMod_Ranged_Weapons = ZHunterMod_Ranged_Weapons or {}
|
||||
local ZHUNTER_RANGED_MAX_COUNT = 80
|
||||
local zButtonRanged_Cache = {}
|
||||
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 idNum = tonumber(itemId)
|
||||
@@ -437,6 +442,15 @@ local function zButtonRanged_OnEnter(button)
|
||||
if not button then
|
||||
return
|
||||
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
|
||||
return
|
||||
end
|
||||
@@ -503,7 +517,7 @@ local function zButtonRanged_BeforeClick(button)
|
||||
return true
|
||||
end
|
||||
|
||||
local function zButtonRanged_RefreshButtonsFromState()
|
||||
zButtonRanged_RefreshButtonsFromState = function()
|
||||
if not zButtonRanged then
|
||||
return
|
||||
end
|
||||
@@ -525,6 +539,7 @@ local function zButtonRanged_RefreshButtonsFromState()
|
||||
end
|
||||
|
||||
zButtonRanged.found = ZSpellButton_SetButtons(zButtonRanged, info)
|
||||
zButtonRanged_BagDirty = false
|
||||
zButtonRanged_ApplyRuntimeSettings()
|
||||
end
|
||||
|
||||
@@ -620,11 +635,17 @@ end
|
||||
function zButtonRanged_SetupSizeAndPosition()
|
||||
local saved = zButtonRanged_GetSaved()
|
||||
if saved["enabled"] == false or saved["enabled"] == 0 then
|
||||
if zButtonRangedAdjustment and zButtonRangedAdjustment.SetScript then
|
||||
zButtonRangedAdjustment:SetScript("OnEvent", nil)
|
||||
end
|
||||
if zButtonRanged and zButtonRanged.Hide then
|
||||
zButtonRanged:Hide()
|
||||
end
|
||||
return
|
||||
end
|
||||
if zButtonRangedAdjustment and zButtonRangedAdjustment.SetScript then
|
||||
zButtonRangedAdjustment:SetScript("OnEvent", zButtonRangedAdjustment_OnEvent)
|
||||
end
|
||||
local displayCount = zButtonRanged.found or 0
|
||||
if displayCount < 0 then
|
||||
displayCount = 0
|
||||
@@ -665,8 +686,32 @@ function zButtonRangedAdjustment_OnEvent()
|
||||
if event == "UNIT_INVENTORY_CHANGED" and arg1 and arg1 ~= "player" then
|
||||
return
|
||||
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_SetupSizeAndPosition()
|
||||
if (tonumber(zButtonRanged.found) or 0) ~= previousFound then
|
||||
zButtonRanged_SetupSizeAndPosition()
|
||||
else
|
||||
zButtonRanged_UpdateButton(zButtonRanged)
|
||||
end
|
||||
if event == "PLAYER_ENTERING_WORLD" then
|
||||
zButtonRanged_PrewarmTooltipOnce()
|
||||
end
|
||||
|
||||
@@ -22,6 +22,20 @@ if not root["zButtonToys"] then
|
||||
end
|
||||
|
||||
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 currentRoot = zButtonToys_GetRoot()
|
||||
@@ -233,11 +247,17 @@ end
|
||||
function zButtonToys_SetupSizeAndPosition()
|
||||
local saved = zButtonToys_GetSaved()
|
||||
if saved["enabled"] == false or saved["enabled"] == 0 then
|
||||
if zButtonToysAdjustment and zButtonToysAdjustment.SetScript then
|
||||
zButtonToysAdjustment:SetScript("OnEvent", nil)
|
||||
end
|
||||
if zButtonToys and zButtonToys.Hide then
|
||||
zButtonToys:Hide()
|
||||
end
|
||||
return
|
||||
end
|
||||
if zButtonToysAdjustment and zButtonToysAdjustment.SetScript then
|
||||
zButtonToysAdjustment:SetScript("OnEvent", zButtonToysAdjustment_OnEvent)
|
||||
end
|
||||
local displayCount = zButtonToys.found or 0
|
||||
if displayCount < 0 then
|
||||
displayCount = 0
|
||||
@@ -275,6 +295,18 @@ function zButtonToysAdjustment_OnEvent()
|
||||
if not zButtonToys then
|
||||
return
|
||||
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_SetupSizeAndPosition()
|
||||
if GameTooltip:IsOwned(zButtonToys) then
|
||||
|
||||
@@ -36,8 +36,159 @@ ZHunterMod_Track_Spells = {
|
||||
}
|
||||
|
||||
local ZHUNTER_TRACK_MAX = table.getn(ZHunterMod_Track_Spells)
|
||||
local zButtonTrack_LastTrackingTexture = nil
|
||||
local zButtonTrack_SyncActiveChild
|
||||
local zButtonTrack_GetSaved
|
||||
|
||||
local function zButtonTrack_GetSaved()
|
||||
local function zButtonTrack_NormalizeTexture(texture)
|
||||
if not texture then
|
||||
return ""
|
||||
end
|
||||
local value = string.lower(tostring(texture))
|
||||
value = string.gsub(value, "\\", "/")
|
||||
local _, _, basename = string.find(value, "([^/]+)$")
|
||||
return basename or value
|
||||
end
|
||||
|
||||
local function zButtonTrack_FindSpellIdByTrackingTexture(trackingTexture)
|
||||
if not trackingTexture or not zButtonTrack or not zButtonTrack.count then
|
||||
return nil
|
||||
end
|
||||
local wanted = zButtonTrack_NormalizeTexture(trackingTexture)
|
||||
for i = 1, zButtonTrack.count do
|
||||
local child = getglobal("zButtonTrack" .. i)
|
||||
if child and child.id then
|
||||
local spellTexture = GetSpellTexture and GetSpellTexture(child.id, "spell") or nil
|
||||
if zButtonTrack_NormalizeTexture(spellTexture) == wanted then
|
||||
return child.id
|
||||
end
|
||||
if child.icon and zButtonTrack_NormalizeTexture(child.icon) == wanted then
|
||||
return child.id
|
||||
end
|
||||
if child.icontexture and child.icontexture.GetTexture then
|
||||
local childTexture = child.icontexture:GetTexture()
|
||||
if zButtonTrack_NormalizeTexture(childTexture) == wanted then
|
||||
return child.id
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function zButtonTrack_FindSpellIdByTrackingName(trackingName)
|
||||
if not trackingName or trackingName == "" or not zButtonTrack or not zButtonTrack.count then
|
||||
return nil
|
||||
end
|
||||
for i = 1, zButtonTrack.count do
|
||||
local child = getglobal("zButtonTrack" .. i)
|
||||
if child and child.id then
|
||||
local spellName = GetSpellName and GetSpellName(child.id, "spell") or nil
|
||||
if spellName == trackingName then
|
||||
return child.id
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function zButtonTrack_GetActiveTrackingSpellId()
|
||||
local activeName = nil
|
||||
local activeTexture = nil
|
||||
if GetNumTrackingTypes and GetTrackingInfo then
|
||||
local numTracking = GetNumTrackingTypes() or 0
|
||||
for i = 1, numTracking do
|
||||
local name, texture, active = GetTrackingInfo(i)
|
||||
if active then
|
||||
activeName = name
|
||||
activeTexture = texture
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
local byName = zButtonTrack_FindSpellIdByTrackingName(activeName)
|
||||
if byName then
|
||||
return byName, activeTexture
|
||||
end
|
||||
if activeTexture then
|
||||
return zButtonTrack_FindSpellIdByTrackingTexture(activeTexture), activeTexture
|
||||
end
|
||||
local buff = GetTrackingTexture and GetTrackingTexture() or nil
|
||||
return zButtonTrack_FindSpellIdByTrackingTexture(buff), buff
|
||||
end
|
||||
|
||||
local function zButtonTrack_AfterClick(button)
|
||||
if not zButtonTrack then
|
||||
return
|
||||
end
|
||||
if button and button.id then
|
||||
zButtonTrack.id = button.id
|
||||
ZSpellButton_UpdateButton(zButtonTrack)
|
||||
ZSpellButton_UpdateCooldown(zButtonTrack)
|
||||
zButtonTrack_SyncActiveChild(button.id)
|
||||
if GetSpellTexture then
|
||||
zButtonTrack_LastTrackingTexture = GetSpellTexture(button.id, "spell") or zButtonTrack_LastTrackingTexture
|
||||
end
|
||||
local isOwned = GameTooltip and GameTooltip.IsOwned and GameTooltip:IsOwned(zButtonTrack)
|
||||
if isOwned then
|
||||
ZSpellButtonParent_OnEnter(zButtonTrack)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
zButtonTrack_SyncActiveChild = function(activeId)
|
||||
if not zButtonTrack or not zButtonTrack.count then
|
||||
return
|
||||
end
|
||||
for i = 1, zButtonTrack.count do
|
||||
local child = getglobal("zButtonTrack" .. i)
|
||||
if child and child.SetChecked then
|
||||
child:SetChecked((activeId and child.id == activeId) and 1 or 0)
|
||||
end
|
||||
end
|
||||
if zButtonTrack.SetChecked then
|
||||
zButtonTrack:SetChecked(0)
|
||||
end
|
||||
end
|
||||
|
||||
local function zButtonTrack_RefreshTrackingState()
|
||||
if not zButtonTrack or not zButtonTrack.count then
|
||||
return
|
||||
end
|
||||
local newId, trackingTexture = zButtonTrack_GetActiveTrackingSpellId()
|
||||
local buff = trackingTexture or (GetTrackingTexture and GetTrackingTexture() or nil)
|
||||
if not newId and not buff then
|
||||
if zButtonTrack.id then
|
||||
zButtonTrack_SyncActiveChild(zButtonTrack.id)
|
||||
else
|
||||
zButtonTrack_LastTrackingTexture = nil
|
||||
zButtonTrack_SyncActiveChild(nil)
|
||||
end
|
||||
return
|
||||
end
|
||||
if not newId then
|
||||
newId = zButtonTrack.id or nil
|
||||
end
|
||||
if not newId then
|
||||
return
|
||||
end
|
||||
if zButtonTrack_NormalizeTexture(zButtonTrack_LastTrackingTexture) == zButtonTrack_NormalizeTexture(buff) and zButtonTrack.id == newId then
|
||||
zButtonTrack_SyncActiveChild(newId)
|
||||
return
|
||||
end
|
||||
|
||||
local isOwned = GameTooltip and GameTooltip.IsOwned and GameTooltip:IsOwned(zButtonTrack)
|
||||
zButtonTrack_LastTrackingTexture = buff
|
||||
zButtonTrack.id = newId
|
||||
ZSpellButton_UpdateButton(zButtonTrack)
|
||||
ZSpellButton_UpdateCooldown(zButtonTrack)
|
||||
zButtonTrack_SyncActiveChild(newId)
|
||||
if isOwned then
|
||||
ZSpellButtonParent_OnEnter(zButtonTrack)
|
||||
end
|
||||
end
|
||||
|
||||
zButtonTrack_GetSaved = function()
|
||||
local currentRoot = zButtonTrack_GetRoot()
|
||||
if not currentRoot["zButtonTrack"] then
|
||||
currentRoot["zButtonTrack"] = {}
|
||||
@@ -119,11 +270,13 @@ function zButtonTrack_OnEvent()
|
||||
return
|
||||
end
|
||||
zButtonTrack_CreateButtons()
|
||||
zButtonTrack.afterclick = zButtonTrack_AfterClick
|
||||
zButtonTrackAdjustment = CreateFrame("Frame", "zButtonTrackAdjustment")
|
||||
zButtonTrackAdjustment:RegisterEvent("PLAYER_AURAS_CHANGED")
|
||||
zButtonTrackAdjustment:RegisterEvent("MINIMAP_UPDATE_TRACKING")
|
||||
zButtonTrackAdjustment:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
zButtonTrackAdjustment:RegisterEvent("SPELLS_CHANGED")
|
||||
zButtonTrackAdjustment:RegisterEvent("CHARACTER_POINTS_CHANGED")
|
||||
zButtonTrackAdjustment:RegisterEvent("LEARNED_SPELL_IN_TAB")
|
||||
zButtonTrackAdjustment:SetScript("OnEvent", zButtonTrackAdjustment_OnEvent)
|
||||
zButtonTrack_SetupSizeAndPosition()
|
||||
end
|
||||
@@ -156,11 +309,17 @@ function zButtonTrack_SetupSizeAndPosition()
|
||||
zButtonTrack_EnsureConfig()
|
||||
local saved = zButtonTrack_GetSaved()
|
||||
if saved["enabled"] == false or saved["enabled"] == 0 then
|
||||
if zButtonTrackAdjustment and zButtonTrackAdjustment.SetScript then
|
||||
zButtonTrackAdjustment:SetScript("OnEvent", nil)
|
||||
end
|
||||
if zButtonTrack and zButtonTrack.Hide then
|
||||
zButtonTrack:Hide()
|
||||
end
|
||||
return
|
||||
end
|
||||
if zButtonTrackAdjustment and zButtonTrackAdjustment.SetScript then
|
||||
zButtonTrackAdjustment:SetScript("OnEvent", zButtonTrackAdjustment_OnEvent)
|
||||
end
|
||||
local displayCount = zButtonTrack.found or ZHUNTER_TRACK_MAX
|
||||
if displayCount < 0 then
|
||||
displayCount = 0
|
||||
@@ -171,6 +330,7 @@ function zButtonTrack_SetupSizeAndPosition()
|
||||
ZSpellButton_ArrangeChildren(zButtonTrack, saved["rows"],
|
||||
displayCount, saved["horizontal"],
|
||||
saved["vertical"])
|
||||
zButtonTrack_RefreshTrackingState()
|
||||
end
|
||||
|
||||
function zButtonTrack_Reset()
|
||||
@@ -199,25 +359,13 @@ function zButtonTrackAdjustment_OnEvent()
|
||||
if not zButtonTrack or not zButtonTrack.count then
|
||||
return
|
||||
end
|
||||
if event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" then
|
||||
if event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" or event == "LEARNED_SPELL_IN_TAB" then
|
||||
zButtonTrack_CreateButtons()
|
||||
zButtonTrack_SetupSizeAndPosition()
|
||||
end
|
||||
if event == "PLAYER_AURAS_CHANGED" or event == "PLAYER_ENTERING_WORLD"
|
||||
or event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" then
|
||||
local i = 1
|
||||
local texture = zButtonTrack1IconTexture:GetTexture()
|
||||
local buff = GetTrackingTexture()
|
||||
if texture == buff and zButtonTrack2.id then
|
||||
zButtonTrack.id = zButtonTrack2.id
|
||||
else
|
||||
zButtonTrack.id = zButtonTrack1.id
|
||||
end
|
||||
ZSpellButton_UpdateButton(zButtonTrack)
|
||||
ZSpellButton_UpdateCooldown(zButtonTrack)
|
||||
if GameTooltip:IsOwned(zButtonTrack) then
|
||||
ZSpellButtonParent_OnEnter(zButtonTrack)
|
||||
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
|
||||
|
||||
@@ -229,9 +377,9 @@ function zButtonTrack_KeyBinding(index)
|
||||
local button
|
||||
if index then
|
||||
button = getglobal("zButtonTrack"..index)
|
||||
else
|
||||
else
|
||||
button = zButtonTrack
|
||||
end
|
||||
end
|
||||
if button.id then
|
||||
CastSpell(button.id, "spell")
|
||||
if zButtonTrack.hideonclick then
|
||||
@@ -249,6 +397,7 @@ 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()
|
||||
|
||||
@@ -29,6 +29,8 @@ ZHunterMod_Trap_Spells = {
|
||||
}
|
||||
|
||||
local ZHUNTER_TRAP_MAX = table.getn(ZHunterMod_Trap_Spells)
|
||||
local zButtonTrap_LastParentId = nil
|
||||
local zButtonTrap_LastCombatState = nil
|
||||
|
||||
local function zButtonTrap_GetSaved()
|
||||
local currentRoot = zButtonTrap_GetRoot()
|
||||
@@ -150,11 +152,17 @@ function zButtonTrap_SetupSizeAndPosition()
|
||||
zButtonTrap_EnsureConfig()
|
||||
local saved = zButtonTrap_GetSaved()
|
||||
if saved["enabled"] == false or saved["enabled"] == 0 then
|
||||
if zButtonTrapAdjustment and zButtonTrapAdjustment.SetScript then
|
||||
zButtonTrapAdjustment:SetScript("OnEvent", nil)
|
||||
end
|
||||
if zButtonTrap and zButtonTrap.Hide then
|
||||
zButtonTrap:Hide()
|
||||
end
|
||||
return
|
||||
end
|
||||
if zButtonTrapAdjustment and zButtonTrapAdjustment.SetScript then
|
||||
zButtonTrapAdjustment:SetScript("OnEvent", zButtonTrapAdjustment_OnEvent)
|
||||
end
|
||||
local displayCount = zButtonTrap.found or ZHUNTER_TRAP_MAX
|
||||
if displayCount < 0 then
|
||||
displayCount = 0
|
||||
@@ -193,9 +201,11 @@ function zButtonTrapAdjustment_OnEvent()
|
||||
if not zButtonTrap or not zButtonTrap.count then
|
||||
return
|
||||
end
|
||||
local rebuild = false
|
||||
if event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" then
|
||||
zButtonTrap_CreateButtons()
|
||||
zButtonTrap_SetupSizeAndPosition()
|
||||
rebuild = true
|
||||
end
|
||||
local nextbutton
|
||||
local button
|
||||
@@ -215,7 +225,13 @@ function zButtonTrapAdjustment_OnEvent()
|
||||
end
|
||||
end
|
||||
end
|
||||
zButtonTrap.id = nextbutton and nextbutton.id or zButtonTrap1.id
|
||||
local newParentId = nextbutton and nextbutton.id or zButtonTrap1.id
|
||||
if (not rebuild) and zButtonTrap_LastParentId == newParentId and zButtonTrap_LastCombatState == combat and not GameTooltip:IsOwned(zButtonTrap) then
|
||||
return
|
||||
end
|
||||
zButtonTrap_LastParentId = newParentId
|
||||
zButtonTrap_LastCombatState = combat
|
||||
zButtonTrap.id = newParentId
|
||||
ZSpellButton_UpdateButton(zButtonTrap)
|
||||
ZSpellButton_UpdateCooldown(zButtonTrap)
|
||||
if GameTooltip:IsOwned(zButtonTrap) then
|
||||
|
||||
Reference in New Issue
Block a user