mirror of
https://codeberg.org/Duvelcorp/MetaHunt.git
synced 2026-09-23 16:16:58 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 233899b2a0 |
@@ -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
@@ -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
@@ -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",
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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, ",", ".")
|
||||
|
||||
@@ -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)",
|
||||
|
||||
@@ -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,7 +1,7 @@
|
||||
local MTH_ChronometerModule = {
|
||||
name = "chronometer",
|
||||
enabled = true,
|
||||
version = "1.0.5",
|
||||
version = "1.0.6",
|
||||
events = {},
|
||||
initialized = false,
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
local MTH_FeedOMatic = {
|
||||
name = "feedomatic",
|
||||
enabled = false,
|
||||
version = "1.0.5",
|
||||
version = "1.0.6",
|
||||
events = {
|
||||
"VARIABLES_LOADED",
|
||||
"MERCHANT_SHOW",
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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