mirror of
https://codeberg.org/Duvelcorp/MetaHunt.git
synced 2026-09-22 07:36:58 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ab34946775 | |||
| d41703949d | |||
| 27d37564ce | |||
| 4aed1174dd | |||
| 233899b2a0 | |||
| 89fd8e079c |
@@ -2,6 +2,53 @@
|
||||
|
||||
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
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
## Interface: 11200
|
||||
## Version: 1.0.5
|
||||
## 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.5"
|
||||
MTH_CONST.version = MTH_CONST.version or "1.1.0"
|
||||
|
||||
MTH_CONST.WEAPON_TYPES = {
|
||||
BOWS = "Bows",
|
||||
|
||||
+103
-9
@@ -944,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,
|
||||
@@ -1117,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
|
||||
@@ -1127,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
|
||||
@@ -1141,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
|
||||
@@ -1148,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
|
||||
@@ -1157,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
|
||||
@@ -1179,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
|
||||
@@ -1186,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
|
||||
@@ -1245,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
|
||||
@@ -1261,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
|
||||
@@ -1284,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
|
||||
|
||||
+25
-1
@@ -1,5 +1,5 @@
|
||||
MTH = MTH or {
|
||||
version = "1.0.5",
|
||||
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)
|
||||
@@ -433,6 +441,9 @@ local function MTH_GetPersistedModuleEnabled(name, defaultEnabled)
|
||||
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_SavedVariables = {}
|
||||
@@ -444,6 +455,19 @@ local function MTH_GetPersistedModuleEnabled(name, defaultEnabled)
|
||||
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
|
||||
|
||||
@@ -8,6 +8,24 @@ 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
|
||||
@@ -207,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
|
||||
@@ -256,16 +309,16 @@ local function MTH_PS_OnEvent(_, evt, eventArg1)
|
||||
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
|
||||
local minInterval = 1
|
||||
if evt == "PET_BAR_UPDATE" then
|
||||
minInterval = 2
|
||||
minInterval = 4
|
||||
elseif evt == "SPELLS_CHANGED" then
|
||||
minInterval = 2.5
|
||||
minInterval = 4
|
||||
elseif evt == "LEARNED_SPELL_IN_TAB" then
|
||||
minInterval = 0.75
|
||||
minInterval = 1.5
|
||||
elseif evt == "UNIT_PET" then
|
||||
minInterval = 0.5
|
||||
minInterval = 1
|
||||
end
|
||||
if MTH_PS_ShouldHandleEvent(evt, minInterval) then
|
||||
MTH_PSP_RequestScan(evt, 1)
|
||||
MTH_PSP_RequestScan(evt, minInterval)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -278,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")
|
||||
@@ -295,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
|
||||
|
||||
|
||||
+1353
-151
File diff suppressed because it is too large
Load Diff
+29
-6
@@ -240,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()
|
||||
@@ -282,6 +310,7 @@ 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
|
||||
@@ -290,12 +319,6 @@ function SlashCmdList.MTH(msg, editbox)
|
||||
MTH_CommandBook()
|
||||
elseif lowerMsg == "peers" or lowerMsg == "who" then
|
||||
MTH_CommandPeers()
|
||||
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
|
||||
else
|
||||
MTH:Print("Unknown command: " .. tostring(msg))
|
||||
MTH:Print("Available: /mth options, /mth book")
|
||||
|
||||
@@ -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,
|
||||
|
||||
+16
-7
@@ -53,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
|
||||
@@ -92,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
|
||||
@@ -510,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)
|
||||
@@ -653,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
|
||||
@@ -711,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
|
||||
@@ -726,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
|
||||
@@ -765,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
|
||||
@@ -843,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
|
||||
@@ -307,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")
|
||||
@@ -380,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
|
||||
@@ -460,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
|
||||
@@ -485,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
|
||||
|
||||
@@ -495,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
|
||||
|
||||
@@ -505,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
|
||||
|
||||
@@ -515,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
|
||||
@@ -600,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
|
||||
@@ -611,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",
|
||||
|
||||
+35
-27
@@ -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
|
||||
@@ -1158,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
|
||||
@@ -1175,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
|
||||
@@ -1191,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
|
||||
@@ -1205,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
|
||||
@@ -1219,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
|
||||
@@ -4,6 +4,7 @@ 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
|
||||
@@ -290,7 +291,12 @@ 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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -632,7 +632,7 @@ 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 = {}
|
||||
@@ -647,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
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
local MTH_AutoBuy = {
|
||||
name = "autobuy",
|
||||
enabled = false,
|
||||
version = "1.0.5",
|
||||
version = "1.1.0",
|
||||
events = {
|
||||
"VARIABLES_LOADED",
|
||||
"MERCHANT_SHOW",
|
||||
|
||||
@@ -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,8 +43,9 @@ 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["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 })
|
||||
|
||||
@@ -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 },
|
||||
@@ -156,22 +195,67 @@ end
|
||||
|
||||
local function ensureProfile()
|
||||
if not MTH or not MTH.GetModuleCharSavedVariables then
|
||||
MTH_CHRON_Trace("ensureProfile fallback defaults (no MTH store)")
|
||||
return shallowCopy(DEFAULTS)
|
||||
end
|
||||
|
||||
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
|
||||
@@ -198,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
|
||||
@@ -272,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
|
||||
@@ -314,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 = {
|
||||
@@ -324,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)
|
||||
|
||||
@@ -332,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
|
||||
@@ -371,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 = {}
|
||||
@@ -450,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
|
||||
@@ -563,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
|
||||
|
||||
@@ -958,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)
|
||||
@@ -970,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)
|
||||
@@ -995,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)
|
||||
|
||||
@@ -1122,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.5",
|
||||
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.5",
|
||||
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
|
||||
|
||||
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)
|
||||
@@ -7,7 +7,7 @@ MTH_SA_MANAGED_HOOKS = true
|
||||
local MTH_SmartAmmo = {
|
||||
name = "smartammo",
|
||||
enabled = true,
|
||||
version = "1.0.5",
|
||||
version = "1.1.0",
|
||||
events = {
|
||||
"VARIABLES_LOADED",
|
||||
"PLAYER_ENTERING_WORLD",
|
||||
|
||||
+377
-14
@@ -6,7 +6,7 @@
|
||||
local MTH_Tooltips = {
|
||||
name = "tooltips",
|
||||
enabled = true,
|
||||
version = "1.0.5",
|
||||
version = "1.1.0",
|
||||
events = {
|
||||
"UPDATE_MOUSEOVER_UNIT",
|
||||
"UNIT_NAME_UPDATE",
|
||||
@@ -115,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)
|
||||
@@ -558,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
|
||||
@@ -864,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
|
||||
@@ -873,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
|
||||
@@ -903,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
|
||||
@@ -918,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
|
||||
|
||||
@@ -944,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
|
||||
@@ -952,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
|
||||
@@ -964,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
|
||||
@@ -1050,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
|
||||
@@ -1126,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) .. "'")
|
||||
@@ -1134,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
|
||||
|
||||
@@ -14,6 +14,71 @@ BINDING_HEADER_ZToysHeader = "ZToys Buttons"
|
||||
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
|
||||
return true
|
||||
@@ -105,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()
|
||||
@@ -123,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.5",
|
||||
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
|
||||
@@ -358,6 +384,7 @@ 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()
|
||||
@@ -366,8 +393,14 @@ function MTH_ZHunter:setEnabled(enabled)
|
||||
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
|
||||
|
||||
|
||||
@@ -30,13 +30,14 @@ local ZHUNTER_AMMO_MAX_COUNT = math.max(table.getn(MTH_AMMO_ARROWS or {}), table
|
||||
local zButtonAmmo_Cache = {}
|
||||
local zButtonAmmo_LastCacheSignature = nil
|
||||
local zButtonAmmo_LastRefreshAt = 0
|
||||
local zButtonAmmo_MinRefreshInterval = 0.20
|
||||
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)
|
||||
@@ -947,6 +948,14 @@ function zButtonAmmoAdjustment_OnEvent()
|
||||
|
||||
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)
|
||||
@@ -1070,6 +1079,7 @@ function zButtonAmmoAdjustment_OnEvent()
|
||||
-- Save the currently equipped ammo for restoration on next reload
|
||||
if equippedAmmoName then
|
||||
zButtonAmmo_SaveEquippedAmmo(equippedAmmoName)
|
||||
zButtonAmmo_LastEquippedAmmoSeen = equippedAmmoName
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -38,6 +38,7 @@ 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_NormalizeTexture(texture)
|
||||
if not texture then
|
||||
@@ -187,7 +188,7 @@ local function zButtonTrack_RefreshTrackingState()
|
||||
end
|
||||
end
|
||||
|
||||
local function zButtonTrack_GetSaved()
|
||||
zButtonTrack_GetSaved = function()
|
||||
local currentRoot = zButtonTrack_GetRoot()
|
||||
if not currentRoot["zButtonTrack"] then
|
||||
currentRoot["zButtonTrack"] = {}
|
||||
@@ -273,6 +274,9 @@ function zButtonTrack_OnEvent()
|
||||
zButtonTrackAdjustment = CreateFrame("Frame", "zButtonTrackAdjustment")
|
||||
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
|
||||
@@ -355,8 +359,12 @@ function zButtonTrackAdjustment_OnEvent()
|
||||
if not zButtonTrack or not zButtonTrack.count then
|
||||
return
|
||||
end
|
||||
if event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" or event == "LEARNED_SPELL_IN_TAB" then
|
||||
zButtonTrack_CreateButtons()
|
||||
zButtonTrack_SetupSizeAndPosition()
|
||||
end
|
||||
if event == "MINIMAP_UPDATE_TRACKING" or event == "PLAYER_ENTERING_WORLD"
|
||||
then
|
||||
or event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" or event == "LEARNED_SPELL_IN_TAB" then
|
||||
zButtonTrack_RefreshTrackingState()
|
||||
end
|
||||
end
|
||||
@@ -389,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()
|
||||
|
||||
Reference in New Issue
Block a user