1 Commits

Author SHA1 Message Date
DuvelCorp 233899b2a0 v1.0.6 2026-03-05 12:30:24 +01:00
19 changed files with 818 additions and 124 deletions
+15
View File
@@ -2,6 +2,21 @@
All notable changes to MetaHunt will be documented in this file.
## [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
View File
@@ -1,5 +1,5 @@
## Interface: 11200
## Version: 1.0.5
## Version: 1.0.6
## 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 -1
View File
@@ -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.0.6"
MTH_CONST.WEAPON_TYPES = {
BOWS = "Bows",
+2 -1
View File
@@ -1,5 +1,5 @@
MTH = MTH or {
version = "1.0.5",
version = "1.0.6",
name = "MetaHunt",
modules = {},
config = {},
@@ -16,6 +16,7 @@ local MTH_MESSAGE_DEFAULTS = {
spellbookScan = false,
petRanAway = true,
mapMarkers = true,
stableScan = true,
}
local function MTH_ClassGateTrace(_step, _detail)
+407 -39
View File
@@ -4,7 +4,6 @@ end
local MTH_PETS_SCHEMA_VERSION = 2
local MTH_PETS_CORE_HOOK_BOUNDARY_KEY = "core-pet-rename-hook"
local MTH_PETS_TRACE_RUNAWAY = false
MTH_PETS_TRACE_CONSISTENCY = false
local MTH_StableFrame = nil
@@ -17,7 +16,6 @@ local MTH_PETS_LiveStateSeq = 0
local MTH_PETS_LiveStateSubscribers = {}
local MTH_PETS_LiveStateEventName = "MTH_PET_LIVE_STATE_CHANGED"
local MTH_PETS_EventThrottle = {}
local MTH_PETS_TRACE_TAME = false
MTH_PETS_CoreOriginal_PetRename = MTH_PETS_CoreOriginal_PetRename or nil
@@ -390,6 +388,17 @@ local function MTH_PETS_NormalizeSystemMessage(rawMessage)
return message
end
local function MTH_PETS_NormalizeSystemMessageKey(rawMessage)
local message = MTH_PETS_NormalizeSystemMessage(rawMessage)
message = string.lower(tostring(message or ""))
message = string.gsub(message, "%%s", " ")
message = string.gsub(message, "[^%w%s]", " ")
message = string.gsub(message, "%s+", " ")
message = string.gsub(message, "^%s+", "")
message = string.gsub(message, "%s+$", "")
return message
end
local function MTH_PETS_IsRunawaySystemMessage(rawMessage)
local message = MTH_PETS_NormalizeSystemMessage(rawMessage)
if message == "" then
@@ -397,8 +406,20 @@ local function MTH_PETS_IsRunawaySystemMessage(rawMessage)
end
local lostPetMessage = _G and _G["PETTAME_LOSTPET"]
if type(lostPetMessage) == "string" and lostPetMessage ~= "" and message == lostPetMessage then
return true
if type(lostPetMessage) == "string" and lostPetMessage ~= "" then
if message == lostPetMessage then
return true
end
local messageKey = MTH_PETS_NormalizeSystemMessageKey(message)
local lostKey = MTH_PETS_NormalizeSystemMessageKey(lostPetMessage)
if messageKey ~= "" and lostKey ~= "" then
if messageKey == lostKey then
return true
end
if string.find(messageKey, lostKey, 1, true) then
return true
end
end
end
local lower = string.lower(message)
@@ -406,14 +427,12 @@ local function MTH_PETS_IsRunawaySystemMessage(rawMessage)
if string.find(lower, "pet ran away", 1, true) then return true end
if string.find(lower, "pet has fled", 1, true) then return true end
if string.find(lower, "pet fled", 1, true) then return true end
if string.find(lower, "pet has left", 1, true) then return true end
if string.find(lower, "pet left", 1, true) then return true end
return false
end
local function MTH_PETS_TraceRunawayEvent(evt, rawMessage, matched)
return
end
local function MTH_PETS_ParseCreatureIdFromGuid(guid)
local guidText = tostring(guid or "")
if guidText == "" then
@@ -717,6 +736,38 @@ local function MTH_PETS_GetPendingTameBeastId(snapshot)
return nil
end
local function MTH_PETS_ResolveTameBeastIdForRow(row, snapshot)
if type(row) ~= "table" then
return nil
end
local pendingResolved = MTH_PETS_GetPendingTameBeastId(snapshot)
if pendingResolved and pendingResolved > 0 then
return pendingResolved
end
local fromSnapshot = snapshot and tonumber(snapshot.beastId) or nil
if fromSnapshot and fromSnapshot > 0 then
return fromSnapshot
end
local fromRow = tonumber(row.beastId)
if fromRow and fromRow > 0 then
return fromRow
end
local lookup = MTH_PETS_FindBeastIdByDataset(
tostring((snapshot and snapshot.name) or row.name or ""),
tostring((snapshot and snapshot.family) or row.family or ""),
tonumber((snapshot and snapshot.level) or row.level)
)
if lookup and lookup > 0 then
return lookup
end
return nil
end
local function MTH_PETS_MakeSignature(name, family, level)
local cleanName = MTH_PETS_SafeLower(MTH_PETS_NormalizeText(name))
local cleanFamily = MTH_PETS_SafeLower(MTH_PETS_NormalizeText(family))
@@ -724,6 +775,114 @@ local function MTH_PETS_MakeSignature(name, family, level)
return cleanName .. "|" .. cleanFamily .. "|" .. tostring(numericLevel)
end
local function MTH_PETS_RowHasTameRecord(row)
if type(row) ~= "table" then
return false
end
if row.tameRecorded == true then
return true
end
if tonumber(row.tamedAt) and tonumber(row.tamedAt) > 0 then
return true
end
if tonumber(row.tameBeastId) and tonumber(row.tameBeastId) > 0 then
return true
end
if type(row.tameZone) == "string" and row.tameZone ~= "" then
return true
end
return false
end
local function MTH_PETS_BackfillTameMetadataFromEvents(row)
if type(row) ~= "table" then
return false
end
if MTH_PETS_RowHasTameRecord(row) then
return false
end
if type(row.events) ~= "table" then
return false
end
local bestEvent = nil
local stableFirstSeenAt = tonumber(row.stableFirstSeenAt) or tonumber(row.stabledAt) or 0
for i = 1, table.getn(row.events) do
local ev = row.events[i]
if type(ev) == "table" and tostring(ev.type or "") == "pet-acquired" then
local evAt = tonumber(ev.at) or 0
local timelineOk = true
if stableFirstSeenAt > 0 and evAt > 0 and evAt > stableFirstSeenAt then
-- If we only saw this pet as stabled before the acquire event, it was likely a call-out, not a tame.
timelineOk = false
end
if timelineOk then
if not bestEvent then
bestEvent = ev
else
local bestAt = tonumber(bestEvent.at) or 0
if bestAt <= 0 or (evAt > 0 and evAt < bestAt) then
bestEvent = ev
end
end
end
end
end
if type(bestEvent) ~= "table" then
return false
end
local context = type(bestEvent.context) == "table" and bestEvent.context or nil
local changed = false
if row.tamedAt == nil or tonumber(row.tamedAt) == nil or tonumber(row.tamedAt) <= 0 then
local candidateAt = tonumber(bestEvent.at) or (context and tonumber(context.timestamp) or nil) or tonumber(row.createdAt)
if candidateAt and candidateAt > 0 then
row.tamedAt = candidateAt
changed = true
end
end
if context then
if row.tameHunterLevel == nil and context.hunterLevel ~= nil then
row.tameHunterLevel = context.hunterLevel
changed = true
end
if (row.tameZone == nil or row.tameZone == "") and context.zone ~= nil and tostring(context.zone) ~= "" then
row.tameZone = context.zone
changed = true
end
if (row.tameSubZone == nil or row.tameSubZone == "") and context.subZone ~= nil and tostring(context.subZone) ~= "" then
row.tameSubZone = context.subZone
changed = true
end
if row.tameX == nil and context.x ~= nil then
row.tameX = context.x
changed = true
end
if row.tameY == nil and context.y ~= nil then
row.tameY = context.y
changed = true
end
end
if (row.tameBeastId == nil or tonumber(row.tameBeastId) == nil) and row.beastId ~= nil then
local beastId = tonumber(row.beastId)
if beastId and beastId > 0 then
row.tameBeastId = beastId
changed = true
end
end
if changed then
row.tameRecorded = true
row.lastUpdated = time()
end
return changed
end
local function MTH_PETS_EnsurePetStoreSchema(pets)
if type(pets.petStore) ~= "table" then
pets.petStore = {}
@@ -767,6 +926,7 @@ local function MTH_PETS_EnsurePetStoreSchema(pets)
end
row.stableInfo.loyalty = nil
end
MTH_PETS_BackfillTameMetadataFromEvents(row)
end
end
end
@@ -919,6 +1079,9 @@ local function MTH_PETS_EnsureSchema(pets)
if pets.updatedAt == nil then
pets.updatedAt = 0
end
if pets.createdAt == nil or tonumber(pets.createdAt) == nil or tonumber(pets.createdAt) <= 0 then
pets.createdAt = now
end
if pets.currentPetId == nil then
local cpId = (type(pets.currentPet) == "table") and pets.currentPet.id or nil
pets.currentPetId = MTH_PETS_NormalizePetId(cpId)
@@ -1244,8 +1407,11 @@ local function MTH_PETS_ApplySnapshotToRow(row, snapshot, source, context)
row.guid = snapshot.guid or row.guid
row.beastId = snapshot.beastId or row.beastId
local hasPendingTame = type(MTH_PETS_LastTameAttempt) == "table"
if hasPendingTame and snapshot.beastId and (row.tameBeastId == nil or tonumber(row.tameBeastId) == nil) then
row.tameBeastId = snapshot.beastId
if hasPendingTame and (row.tameBeastId == nil or tonumber(row.tameBeastId) == nil) then
local resolvedTameBeastId = MTH_PETS_ResolveTameBeastIdForRow(row, snapshot)
if resolvedTameBeastId and resolvedTameBeastId > 0 then
row.tameBeastId = resolvedTameBeastId
end
end
if hasPendingTame and (source == "unit-pet-acquire" or source == "refresh-current-pet") and type(context) == "table" then
row.tameRecorded = true
@@ -1294,8 +1460,11 @@ local function MTH_PETS_ApplySnapshotToRow(row, snapshot, source, context)
row.tameSubZone = row.tameSubZone or context.subZone
row.tameX = row.tameX or context.x
row.tameY = row.tameY or context.y
if snapshot.beastId and tonumber(row.tameBeastId) == nil then
row.tameBeastId = snapshot.beastId
if tonumber(row.tameBeastId) == nil then
local resolvedTameBeastId = MTH_PETS_ResolveTameBeastIdForRow(row, snapshot)
if resolvedTameBeastId and resolvedTameBeastId > 0 then
row.tameBeastId = resolvedTameBeastId
end
end
end
end
@@ -1950,6 +2119,7 @@ function MTH_PETS_RefreshCurrentPet()
local cp = pets.currentPet
local previousCurrentId = cp and cp.id or nil
local hadPetBeforeRefresh = MTH_ST_LastUnitPetHadPet and true or false
local now = time()
local snapshot = MTH_PETS_MakeSnapshotFromLivePet()
if pets.currentPetSuppressed == true and pets.currentPetSuppressedAwaitNoLive == true then
@@ -1993,6 +2163,7 @@ function MTH_PETS_RefreshCurrentPet()
MTH_PETS_SetCurrentPetId(pets, keepCurrentId)
MTH_PETS_LogConsistency("RefreshCurrentPet no-live result current=" .. MTH_PETS_FormatCurrentConsistency(cp)
.. " activeCurrentId=" .. tostring(petStore and petStore.activeCurrentId or nil))
MTH_ST_LastUnitPetHadPet = false
pets.updatedAt = now
return
end
@@ -2029,11 +2200,54 @@ function MTH_PETS_RefreshCurrentPet()
if cp.id and cp.id ~= previousCurrentId then
MTH_PETS_RequestPetSpellScan("refresh-current-change")
end
local row = MTH_PETS_GetPetById(pets, petId)
if type(row) == "table" then
if type(row.events) ~= "table" then
row.events = {}
end
local eventType = "pet-updated"
if created and (not hadPetBeforeRefresh) then
eventType = "pet-acquired"
end
local eventContext = MTH_PETS_CaptureContext()
table.insert(row.events, {
type = eventType,
source = "refresh-current-pet",
at = now,
context = eventContext,
})
if eventType == "pet-acquired" then
local hasTameRecord = (row.tameRecorded == true)
or (tonumber(row.tamedAt) and tonumber(row.tamedAt) > 0)
or (type(row.tameZone) == "string" and row.tameZone ~= "")
if not hasTameRecord and type(eventContext) == "table" then
row.tameRecorded = true
row.tamedAt = row.tamedAt or eventContext.timestamp or now
row.tameHunterLevel = row.tameHunterLevel or eventContext.hunterLevel
row.tameZone = row.tameZone or eventContext.zone
row.tameSubZone = row.tameSubZone or eventContext.subZone
row.tameX = row.tameX or eventContext.x
row.tameY = row.tameY or eventContext.y
if tonumber(row.tameBeastId) == nil then
local resolvedTameBeastId = MTH_PETS_ResolveTameBeastIdForRow(row, snapshot)
if resolvedTameBeastId and resolvedTameBeastId > 0 then
row.tameBeastId = resolvedTameBeastId
end
end
end
end
end
if hadPendingTame and cp.id and cp.id ~= previousCurrentId then
MTH_PETS_LogTame("RefreshCurrentPet acquire/change completed; clearing pending tame attempt")
MTH_PETS_LastTameAttempt = nil
end
MTH_PETS_LogConsistency("RefreshCurrentPet live result current=" .. MTH_PETS_FormatCurrentConsistency(cp))
MTH_ST_LastUnitPetHadPet = true
pets.updatedAt = now
end
@@ -2300,6 +2514,7 @@ function MTH_ST_Scan(reason)
local slotCount = tonumber(GetNumStableSlots()) or 0
local store = MTH_ST_GetStore()
local petsRoot = MTH_PETS_GetRootStore()
MTH_PETS_RefreshCurrentPet()
local scanContext = MTH_PETS_CaptureContext()
local scanStableMasterName = MTH_PETS_GetStableMasterName()
store.lastScan = time()
@@ -2331,6 +2546,28 @@ function MTH_ST_Scan(reason)
}
end
local c1, c2, c3, c4, c5, c6, c7, c8 = GetStablePetInfo(0)
local currentPetId = (type(petsRoot) == "table" and type(petsRoot.currentPet) == "table") and petsRoot.currentPet.id or nil
if currentPetId and type(petsRoot.petStore) == "table" and type(petsRoot.petStore.activeById) == "table" then
local currentRow = petsRoot.petStore.activeById[currentPetId]
if type(currentRow) == "table" then
local currentIcon = tostring(c1 or "")
if currentIcon ~= "" then
currentRow.icon = currentIcon
currentRow.lastUpdated = time()
end
end
end
store.current = {
petId = currentPetId,
icon = c1,
name = c2,
level = c3,
family = c4,
loyalty = c5,
raw = { c1, c2, c3, c4, c5, c6, c7, c8 },
}
MTH_PETS_MarkStableVisited(petsRoot, tostring(reason or "stable-scan"))
MTH_PETS_RefreshCurrentPet()
@@ -2541,6 +2778,54 @@ local function MTH_ST_DebugDumpLine(line)
end
end
local MTH_PETS_DebugBaselineSnapshot = nil
local function MTH_ST_DebugCloneValue(value, seen)
if type(value) ~= "table" then
return value
end
seen = seen or {}
if seen[value] then
return seen[value]
end
local clone = {}
seen[value] = clone
for key, child in pairs(value) do
clone[MTH_ST_DebugCloneValue(key, seen)] = MTH_ST_DebugCloneValue(child, seen)
end
return clone
end
local function MTH_PETS_CaptureDebugSnapshot(targetPetId)
local pets = MTH_PETS_GetRootStore()
if type(pets) ~= "table" then
return nil, "pets datastore unavailable"
end
MTH_PETS_RefreshCurrentPet()
local cp = (type(pets.currentPet) == "table") and pets.currentPet or nil
local petId = targetPetId or (cp and cp.id) or pets.currentPetId
if petId == nil or tostring(petId) == "" then
return nil, "no current pet id"
end
local row = MTH_PETS_GetPetById(pets, petId)
if type(row) ~= "table" then
return nil, "active row missing for pet id=" .. tostring(petId)
end
local snapshot = {
capturedAt = time(),
petId = tostring(petId),
currentPetId = pets.currentPetId,
currentPet = MTH_ST_DebugCloneValue(cp or {}),
row = MTH_ST_DebugCloneValue(row),
stableScan = MTH_ST_DebugCloneValue(pets.stableScan or {}),
}
return snapshot, nil
end
local function MTH_ST_DebugSortKeys(tbl)
local keys = {}
for k in pairs(tbl or {}) do
@@ -2770,6 +3055,64 @@ function MTH_CommandPetsDump()
end
end
function MTH_CommandPetsSnap()
local snapshot, err = MTH_PETS_CaptureDebugSnapshot(nil)
if not snapshot then
MTH:Print("Pet snapshot failed: " .. tostring(err or "unknown"))
return false
end
MTH_PETS_DebugBaselineSnapshot = snapshot
MTH:Print("Pet snapshot saved for id=" .. tostring(snapshot.petId) .. ". Run /mth petsdiff after reproducing the issue.")
MTH_ST_DebugDumpLine("[PETSNAP] BASELINE BEGIN")
MTH_ST_DebugDumpValue("[PETSNAP].baseline", snapshot, 0, 5, {})
MTH_ST_DebugDumpLine("[PETSNAP] BASELINE END")
return true
end
function MTH_CommandPetsDiff()
if type(MTH_PETS_DebugBaselineSnapshot) ~= "table" then
MTH:Print("No pet snapshot baseline found. Run /mth petssnap first.")
return false
end
local baseline = MTH_PETS_DebugBaselineSnapshot
local current, err = MTH_PETS_CaptureDebugSnapshot(baseline.petId)
if not current then
MTH:Print("Pet snapshot compare failed: " .. tostring(err or "unknown"))
return false
end
MTH:Print("Pet snapshot compare for id=" .. tostring(current.petId) .. ".")
MTH_ST_DebugDumpLine("[PETSNAP] BEFORE BEGIN")
MTH_ST_DebugDumpValue("[PETSNAP].before", baseline, 0, 5, {})
MTH_ST_DebugDumpLine("[PETSNAP] BEFORE END")
MTH_ST_DebugDumpLine("[PETSNAP] AFTER BEGIN")
MTH_ST_DebugDumpValue("[PETSNAP].after", current, 0, 5, {})
MTH_ST_DebugDumpLine("[PETSNAP] AFTER END")
local diffKeys = {
"name", "family", "level", "beastId", "icon",
"tameRecorded", "tamedAt", "tameZone", "tameSubZone", "tameX", "tameY", "tameBeastId",
"stableSlot", "stabledAt", "stableFirstSeenAt", "lastUnstabledAt", "lastSource", "lastUpdated",
}
local diffCount = 0
for i = 1, table.getn(diffKeys) do
local key = diffKeys[i]
local beforeValue = baseline.row and baseline.row[key] or nil
local afterValue = current.row and current.row[key] or nil
if tostring(beforeValue) ~= tostring(afterValue) then
diffCount = diffCount + 1
MTH_ST_DebugDumpLine("[PETSNAP] DIFF row." .. tostring(key) .. ": " .. tostring(beforeValue) .. " -> " .. tostring(afterValue))
end
end
if diffCount <= 0 then
MTH_ST_DebugDumpLine("[PETSNAP] DIFF none")
end
MTH_PETS_DebugBaselineSnapshot = current
return true
end
function MTH_CommandStableScan()
if UnitClass then
local _, classToken = UnitClass("player")
@@ -2790,9 +3133,10 @@ function MTH_CommandStableScan()
MTH:Print("Stable scan captured " .. tostring(slotCount) .. " slot(s).")
end
local function MTH_ST_OnEvent(_, evt, eventArg1)
local function MTH_ST_OnEvent(_, evt, eventArg1, eventArg2)
evt = evt or event
eventArg1 = eventArg1 or arg1
eventArg2 = eventArg2 or arg2
if not evt then
return
end
@@ -2805,41 +3149,39 @@ local function MTH_ST_OnEvent(_, evt, eventArg1)
return
end
if evt == "SPELLCAST_CHANNEL_START" then
MTH_PETS_RecordTameAttempt(evt, eventArg1)
local isUnitSpellcast = (evt == "UNIT_SPELLCAST_START" or evt == "UNIT_SPELLCAST_STOP"
or evt == "UNIT_SPELLCAST_FAILED" or evt == "UNIT_SPELLCAST_INTERRUPTED"
or evt == "UNIT_SPELLCAST_CHANNEL_START" or evt == "UNIT_SPELLCAST_CHANNEL_STOP")
local castSpellName = eventArg1
if isUnitSpellcast then
if eventArg1 ~= "player" then
return
end
castSpellName = eventArg2
end
if evt == "SPELLCAST_START" or evt == "SPELLCAST_CHANNEL_START"
or evt == "UNIT_SPELLCAST_START" or evt == "UNIT_SPELLCAST_CHANNEL_START" then
MTH_PETS_RecordTameAttempt(evt, castSpellName)
return
end
if evt == "SPELLCAST_STOP" or evt == "SPELLCAST_CHANNEL_STOP" or evt == "SPELLCAST_FAILED" or evt == "SPELLCAST_INTERRUPTED" then
if MTH_PETS_TRACE_TAME then
MTH_PETS_LogTame("Spell terminal evt=" .. tostring(evt) .. " spell='" .. tostring(eventArg1 or "") .. "' pending=" .. tostring(type(MTH_PETS_LastTameAttempt) == "table"))
end
local terminalIsTame = MTH_PETS_IsTameBeastSpellName(eventArg1)
if evt == "SPELLCAST_STOP" or evt == "SPELLCAST_CHANNEL_STOP" or evt == "SPELLCAST_FAILED" or evt == "SPELLCAST_INTERRUPTED"
or evt == "UNIT_SPELLCAST_STOP" or evt == "UNIT_SPELLCAST_CHANNEL_STOP"
or evt == "UNIT_SPELLCAST_FAILED" or evt == "UNIT_SPELLCAST_INTERRUPTED" then
local terminalIsTame = MTH_PETS_IsTameBeastSpellName(castSpellName)
if not terminalIsTame and type(MTH_PETS_LastTameAttempt) == "table" then
terminalIsTame = true
if MTH_PETS_TRACE_TAME then
MTH_PETS_LogTame("Treating terminal event as tame because pending attempt exists")
end
end
if not terminalIsTame then
local fallbackName, fallbackSource = MTH_PETS_GetCurrentPlayerCastOrChannelName()
if fallbackName and MTH_PETS_IsTameBeastSpellName(fallbackName) then
terminalIsTame = true
if MTH_PETS_TRACE_TAME then
MTH_PETS_LogTame("Resolved terminal spell via " .. tostring(fallbackSource) .. " => '" .. tostring(fallbackName) .. "'")
end
end
end
if terminalIsTame then
if evt == "SPELLCAST_FAILED" or evt == "SPELLCAST_INTERRUPTED" then
if MTH_PETS_TRACE_TAME then
MTH_PETS_LogTame("Tame ended with failure/interruption; clearing pending attempt")
end
MTH_PETS_LastTameAttempt = nil
elseif evt == "SPELLCAST_CHANNEL_STOP" or evt == "SPELLCAST_STOP" then
if MTH_PETS_TRACE_TAME then
MTH_PETS_LogTame("Tame channel ended; awaiting UNIT_PET to confirm acquire")
end
end
end
return
@@ -2884,9 +3226,10 @@ local function MTH_ST_OnEvent(_, evt, eventArg1)
return
end
if evt == "CHAT_MSG_SYSTEM" or evt == "UI_ERROR_MESSAGE" then
if evt == "CHAT_MSG_SYSTEM" or evt == "UI_ERROR_MESSAGE"
or evt == "CHAT_MSG_SPELL_PET_INFO" or evt == "CHAT_MSG_SPELL_PET_DAMAGE"
or evt == "CHAT_MSG_COMBAT_PET_HITS" or evt == "CHAT_MSG_COMBAT_PET_MISSES" then
local matchedRunaway = MTH_PETS_IsRunawaySystemMessage(eventArg1)
MTH_PETS_TraceRunawayEvent(evt, eventArg1, matchedRunaway)
if matchedRunaway then
MTH_PETS_RecordPetRunaway(evt, eventArg1)
MTH_PETS_RefreshCurrentPet()
@@ -2896,7 +3239,18 @@ local function MTH_ST_OnEvent(_, evt, eventArg1)
end
if evt == "PET_STABLE_SHOW" then
MTH_ST_RunScanThrottled(evt, 1)
local scanned = MTH_ST_RunScanThrottled(evt, 1)
if scanned and MTH and MTH.Print then
local shouldPrint = true
if MTH.IsMessageEnabled then
shouldPrint = MTH:IsMessageEnabled("stableScan", true)
end
if shouldPrint then
local store = MTH_ST_GetStore()
local slotCount = tonumber(store and store.slotCount) or 0
MTH:Print("Stable scan complete: " .. tostring(slotCount) .. " slot(s).")
end
end
return
end
@@ -2925,16 +3279,28 @@ function MTH_ST_InitService()
MTH_StableFrame = CreateFrame("Frame", "MTHStableScanFrame")
MTH_StableFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
MTH_StableFrame:RegisterEvent("SPELLCAST_START")
MTH_StableFrame:RegisterEvent("SPELLCAST_STOP")
MTH_StableFrame:RegisterEvent("SPELLCAST_CHANNEL_START")
MTH_StableFrame:RegisterEvent("SPELLCAST_CHANNEL_STOP")
MTH_StableFrame:RegisterEvent("SPELLCAST_FAILED")
MTH_StableFrame:RegisterEvent("SPELLCAST_INTERRUPTED")
MTH_StableFrame:RegisterEvent("UNIT_SPELLCAST_START")
MTH_StableFrame:RegisterEvent("UNIT_SPELLCAST_STOP")
MTH_StableFrame:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START")
MTH_StableFrame:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP")
MTH_StableFrame:RegisterEvent("UNIT_SPELLCAST_FAILED")
MTH_StableFrame:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED")
MTH_StableFrame:RegisterEvent("UNIT_PET")
MTH_StableFrame:RegisterEvent("PET_BAR_UPDATE")
MTH_StableFrame:RegisterEvent("UNIT_HAPPINESS")
MTH_StableFrame:RegisterEvent("CHAT_MSG_COMBAT_XP_GAIN")
MTH_StableFrame:RegisterEvent("PLAYER_XP_UPDATE")
MTH_StableFrame:RegisterEvent("CHAT_MSG_SYSTEM")
MTH_StableFrame:RegisterEvent("CHAT_MSG_SPELL_PET_INFO")
MTH_StableFrame:RegisterEvent("CHAT_MSG_SPELL_PET_DAMAGE")
MTH_StableFrame:RegisterEvent("CHAT_MSG_COMBAT_PET_HITS")
MTH_StableFrame:RegisterEvent("CHAT_MSG_COMBAT_PET_MISSES")
MTH_StableFrame:RegisterEvent("UI_ERROR_MESSAGE")
MTH_StableFrame:RegisterEvent("PET_STABLE_SHOW")
MTH_StableFrame:RegisterEvent("PET_STABLE_UPDATE")
@@ -2960,15 +3326,17 @@ function MTH_ST_InitBootstrap()
if not frame then
return
end
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
frame:RegisterEvent("PET_STABLE_SHOW")
frame:RegisterEvent("PET_STABLE_UPDATE")
frame:SetScript("OnEvent", function(self, evt)
evt = evt or event
if evt ~= "PET_STABLE_SHOW" then
if evt ~= "PLAYER_ENTERING_WORLD" and evt ~= "PET_STABLE_SHOW" and evt ~= "PET_STABLE_UPDATE" then
return
end
MTH_ST_InitService()
if type(MTH_ST_Scan) == "function" then
MTH_ST_Scan("bootstrap:PET_STABLE_SHOW")
if (evt == "PET_STABLE_SHOW" or evt == "PET_STABLE_UPDATE") and type(MTH_ST_Scan) == "function" then
MTH_ST_Scan("bootstrap:" .. tostring(evt))
end
if self and self.UnregisterAllEvents then
self:UnregisterAllEvents()
+26
View File
@@ -284,12 +284,37 @@ function SlashCmdList.MTH(msg, editbox)
local lowerMsg = string.lower(msg)
if msg == "" then
MTH:Print("Available: /mth options, /mth book")
MTH:Print("Debug: /mth petsstate, /mth petsdump, /mth petssnap, /mth petsdiff")
elseif lowerMsg == "options" then
MTH_CommandOptions()
elseif lowerMsg == "book" or lowerMsg == "hunterbook" then
MTH_CommandBook()
elseif lowerMsg == "peers" or lowerMsg == "who" then
MTH_CommandPeers()
elseif lowerMsg == "petsstate" then
if type(MTH_CommandPetsState) == "function" then
MTH_CommandPetsState()
else
MTH:Print("Pets state command is not available yet")
end
elseif lowerMsg == "petsdump" then
if type(MTH_CommandPetsDump) == "function" then
MTH_CommandPetsDump()
else
MTH:Print("Pets dump command is not available yet")
end
elseif lowerMsg == "petssnap" then
if type(MTH_CommandPetsSnap) == "function" then
MTH_CommandPetsSnap()
else
MTH:Print("Pets snapshot command is not available yet")
end
elseif lowerMsg == "petsdiff" then
if type(MTH_CommandPetsDiff) == "function" then
MTH_CommandPetsDiff()
else
MTH:Print("Pets diff command is not available yet")
end
elseif lowerMsg == "err" then
if MTH_DebugFrame and type(MTH_DebugFrame.Toggle) == "function" then
MTH_DebugFrame:Toggle()
@@ -299,6 +324,7 @@ function SlashCmdList.MTH(msg, editbox)
else
MTH:Print("Unknown command: " .. tostring(msg))
MTH:Print("Available: /mth options, /mth book")
MTH:Print("Debug: /mth petsstate, /mth petsdump, /mth petssnap, /mth petsdiff")
end
end
+77 -35
View File
@@ -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()
+2 -2
View File
@@ -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, ",", ".")
+7 -1
View File
@@ -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
+54 -8
View File
@@ -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
View File
@@ -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)",
+1 -1
View File
@@ -6,7 +6,7 @@
local MTH_AutoBuy = {
name = "autobuy",
enabled = false,
version = "1.0.5",
version = "1.0.6",
events = {
"VARIABLES_LOADED",
"MERCHANT_SHOW",
+1 -1
View File
@@ -1,7 +1,7 @@
local MTH_ChronometerModule = {
name = "chronometer",
enabled = true,
version = "1.0.5",
version = "1.0.6",
events = {},
initialized = false,
}
+1 -1
View File
@@ -6,7 +6,7 @@
local MTH_FeedOMatic = {
name = "feedomatic",
enabled = false,
version = "1.0.5",
version = "1.0.6",
events = {
"VARIABLES_LOADED",
"MERCHANT_SHOW",
+1 -1
View File
@@ -7,7 +7,7 @@ MTH_SA_MANAGED_HOOKS = true
local MTH_SmartAmmo = {
name = "smartammo",
enabled = true,
version = "1.0.5",
version = "1.0.6",
events = {
"VARIABLES_LOADED",
"PLAYER_ENTERING_WORLD",
+138 -13
View File
@@ -6,7 +6,7 @@
local MTH_Tooltips = {
name = "tooltips",
enabled = true,
version = "1.0.5",
version = "1.0.6",
events = {
"UPDATE_MOUSEOVER_UNIT",
"UNIT_NAME_UPDATE",
@@ -864,7 +864,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 +903,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 +935,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 +950,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 +980,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 +988,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 +1000,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 +1167,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
+58 -4
View File
@@ -384,9 +384,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
@@ -488,11 +515,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
+1 -1
View File
@@ -8,7 +8,7 @@ MTH_ZH_MANAGED_HOOKS = true
local MTH_ZHunter = {
name = "zhunter",
enabled = true,
version = "1.0.5",
version = "1.0.6",
events = {
"VARIABLES_LOADED",
"PLAYER_ENTERING_WORLD",
+11 -2
View File
@@ -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()