Files
MetaHunt/api/hunterbook.lua
T
2026-02-24 23:00:59 +01:00

4947 lines
166 KiB
Lua

-- MetaHunt standalone Hunter Book UI (XML + Lua)
MTH_HUNTERBOOK_LOADED = true
MTH_HUNTERBOOK_TABS = MTH_HUNTERBOOK_TABS or {}
local function MTH_BOOK_GetTabDefinition(mode)
if type(MTH_HUNTERBOOK_TABS) ~= "table" then return nil end
return MTH_HUNTERBOOK_TABS[tostring(mode or "")]
end
MTH_BOOK_Browser = nil
local MTH_BOOK_RefreshFilter
local MTH_BOOK_UpdateResults
local MTH_BOOK_GetZoneName
local MTH_BOOK_GetPlayerLevelValue
local MTH_BOOK_IsSpellInLevelScope
local MTH_BOOK_GetScopedRankSummary
local MTH_BOOK_BEAST_DATABASE_URL = "https://database.turtlecraft.gg/?npc=%d"
local MTH_BOOK_NPC_DATABASE_URL = "https://database.turtlecraft.gg/?npc=%d"
local MTH_BOOK_ITEM_DATABASE_URL = "https://database.turtlecraft.gg/?item=%d"
local MTH_BOOK_STABLE_CURRENT_ID_CACHE = nil
local function MTH_BOOK_FamiliesTrace(message)
return
end
local MTH_BOOK_STATE = {
mode = "stable",
search = "",
quick = "all",
minLevel = nil,
maxLevel = nil,
flag1 = false,
flag2 = false,
flag3 = false,
petAbility = "all",
petRank = "all",
petLearnSource = "beast",
petOnlyMyLevel = true,
itemOnlyMyLevel = false,
petInZoneOnly = false,
itemSubtype = "all",
npcFunction = "all",
npcZone = "all",
npcInZoneOnly = false,
npcHideNoZone = true,
petHideNoAbilities = true,
petHideUnknown = true,
forcedBeastId = nil,
page = 1,
pageSize = 16,
petLeftOffset = 0,
results = {},
selectedEntry = nil,
selectedPetRankEntry = nil,
petRankRows = {},
petUI = nil,
stableUI = nil,
buttons = {},
headerCols = {},
headerButtons = {},
sortByMode = {
pets = { col = nil, asc = true },
families = { col = nil, asc = true },
abilities = { col = nil, asc = true },
items = { col = nil, asc = true },
npcs = { col = nil, asc = true },
stable = { col = nil, asc = true },
pethistory = { col = 5, asc = false },
},
sliderDragging = false,
}
_G.MTH_BOOK_STATE = MTH_BOOK_STATE
local function MTH_HB_ReportGuard(message)
local text = "[MTH HUNTERBOOK] " .. tostring(message)
if MTH and MTH.Print then
MTH:Print(text, "error")
elseif type(MTH_Log) == "function" then
MTH_Log(text, "error")
elseif DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then
DEFAULT_CHAT_FRAME:AddMessage(text)
end
end
function MTH_BOOK_DebugTrace(message)
return
end
local function MTH_BOOK_GetLoyaltyNameByLevel(level)
local resolvedLevel = tonumber(level)
if not resolvedLevel or resolvedLevel < 1 or resolvedLevel > 6 then
return "-"
end
local key = "PET_LOYALTY" .. tostring(resolvedLevel)
local name = (_G and _G[key]) or (type(getglobal) == "function" and getglobal(key))
name = tostring(name or "")
if name == "" then
local defaults = {
[1] = "Rebellious",
[2] = "Unruly",
[3] = "Submissive",
[4] = "Dependable",
[5] = "Faithful",
[6] = "Best Friend",
}
name = defaults[resolvedLevel] or "-"
end
return tostring(name)
end
local function MTH_HB_RequireOpenDeps()
if type(MTH_BOOK_RefreshFilter) ~= "function" then
MTH_HB_ReportGuard("Missing dependency: MTH_BOOK_RefreshFilter")
return false
end
return true
end
local MTH_BOOK_MAX_COLS = 9
local MTH_BOOK_MAX_ROWS = 20
local MTH_BOOK_PetFamilyOptions = {
{ value = "all", label = "All Families" },
}
local MTH_BOOK_PetAbilityOptions = {
{ value = "all", label = "All Abilities" },
}
local MTH_BOOK_PetRankOptions = {
{ value = "all", label = "All Ranks" },
}
local MTH_BOOK_PetLearnSourceOptions = {
{ value = "all", label = "All Abilities" },
{ value = "beast", label = "Beast Learned" },
{ value = "trainer", label = "Trainer Learned" },
}
local MTH_BOOK_NPCFunctionOptions = {
{ value = "all", label = "All Hunter Friends" },
{ value = "huntertrainer", label = "Hunter Trainer" },
{ value = "pettrainer", label = "Pet Trainer" },
{ value = "vendor", label = "Ammo Vendor" },
}
local MTH_BOOK_NPCZoneOptions = {
{ value = "all", label = "All Zones" },
}
local MTH_BOOK_ItemSubtypeOptions = {
{ value = "all", label = "All Ranged" },
{ value = "bow", label = "Bow" },
{ value = "gun", label = "Gun" },
{ value = "crossbow", label = "Crossbow" },
}
local MTH_BOOK_PetAbilityRanks = {}
local MTH_BOOK_CONTENT_LAYOUT_DEFAULT = {
listX = 16,
listY = -166,
listW = 564,
listH = 354,
detailX = 608,
detailY = -166,
detailW = 136,
detailH = 324,
}
local MTH_BOOK_CONTENT_LAYOUT_ITEMS = {
listX = 16,
listY = -124,
listW = 564,
listH = 396,
detailX = 608,
detailY = -124,
detailW = 136,
detailH = 366,
}
local MTH_BOOK_CONTENT_LAYOUT_PETABILITIES = {
listX = 16,
listY = -106,
listW = 564,
listH = 424,
detailX = 608,
detailY = -106,
detailW = 136,
detailH = 424,
}
local MTH_BOOK_CONTENT_LAYOUT_NPCS = {
listX = 16,
listY = -142,
listW = 564,
listH = 378,
detailX = 608,
detailY = -142,
detailW = 136,
detailH = 348,
}
local MTH_BOOK_CONTENT_LAYOUT_STABLE = {
listX = 16,
listY = -74,
listW = 728,
listH = 456,
detailX = 748,
detailY = -74,
detailW = 1,
detailH = 1,
}
local MTH_BOOK_CONTENT_LAYOUT_FAMILIES = {
listX = 16,
listY = -74,
listW = 728,
listH = 376,
detailX = 748,
detailY = -74,
detailW = 1,
detailH = 1,
}
local MTH_BOOK_CONTENT_LAYOUT_HISTORY = {
listX = 16,
listY = -74,
listW = 520,
listH = 446,
detailX = 564,
detailY = -74,
detailW = 180,
detailH = 446,
}
local function MTH_BOOK_ApplyContentLayoutForMode()
local listParent = getglobal("MTH_BOOK_ListBackdrop")
local detailParent = getglobal("MTH_BOOK_DetailBackdrop")
local detailText = getglobal("MTH_BOOK_DetailBackdropDetailText")
local sliderBackdrop = getglobal("MTH_BOOK_ListSliderBackdrop")
local listSlider = getglobal("MTH_BOOK_ListSlider")
if not (listParent and detailParent) then return end
local layout = MTH_BOOK_CONTENT_LAYOUT_DEFAULT
if MTH_BOOK_STATE.mode == "petabilities" then
layout = MTH_BOOK_CONTENT_LAYOUT_PETABILITIES
elseif MTH_BOOK_STATE.mode == "items" then
layout = MTH_BOOK_CONTENT_LAYOUT_ITEMS
elseif MTH_BOOK_STATE.mode == "npcs" then
layout = MTH_BOOK_CONTENT_LAYOUT_NPCS
elseif MTH_BOOK_STATE.mode == "families" then
layout = MTH_BOOK_CONTENT_LAYOUT_FAMILIES
elseif MTH_BOOK_STATE.mode == "stable" then
layout = MTH_BOOK_CONTENT_LAYOUT_STABLE
elseif MTH_BOOK_STATE.mode == "pethistory" then
layout = MTH_BOOK_CONTENT_LAYOUT_HISTORY
end
local browserFrame = listParent:GetParent()
listParent:ClearAllPoints()
listParent:SetPoint("TOPLEFT", browserFrame, "TOPLEFT", layout.listX, layout.listY)
listParent:SetWidth(layout.listW)
listParent:SetHeight(layout.listH)
detailParent:ClearAllPoints()
detailParent:SetPoint("TOPLEFT", browserFrame, "TOPLEFT", layout.detailX, layout.detailY)
detailParent:SetWidth(layout.detailW)
detailParent:SetHeight(layout.detailH)
if detailText then
detailText:ClearAllPoints()
detailText:SetPoint("TOPLEFT", detailParent, "TOPLEFT", 6, -6)
detailText:SetWidth(layout.detailW - 12)
detailText:SetHeight(layout.detailH - 12)
end
local sliderHeight = layout.listH - 32
if sliderHeight < 120 then sliderHeight = 120 end
if sliderBackdrop then
sliderBackdrop:SetHeight(sliderHeight)
end
if listSlider then
listSlider:SetHeight(sliderHeight)
end
if MTH_BOOK_STATE.petUI then
local paneHeight = layout.listH - 8
if paneHeight < 200 then paneHeight = 200 end
if MTH_BOOK_STATE.petUI.leftPane then MTH_BOOK_STATE.petUI.leftPane:SetHeight(paneHeight) end
if MTH_BOOK_STATE.petUI.rightPane then MTH_BOOK_STATE.petUI.rightPane:SetHeight(paneHeight) end
local detailAvailable = layout.detailH - 60
if detailAvailable < 120 then detailAvailable = 120 end
local topHeight = math.floor(detailAvailable * 0.54)
local bottomHeight = detailAvailable - topHeight
if MTH_BOOK_STATE.petUI.detailTop then MTH_BOOK_STATE.petUI.detailTop:SetHeight(topHeight) end
if MTH_BOOK_STATE.petUI.detailBottom then MTH_BOOK_STATE.petUI.detailBottom:SetHeight(bottomHeight) end
end
end
local function MTH_BOOK_UpdateCheckboxLayoutByMode()
local controls = {
getglobal("MTH_BOOK_RequireVendor"),
getglobal("MTH_BOOK_RequireDrop"),
getglobal("MTH_BOOK_RequireObject"),
getglobal("MTH_BOOK_HideNoAbilities"),
getglobal("MTH_BOOK_HideUnknown"),
}
local xOffsets = { 18, 86, 154, 232, 372 }
local yOffset = -140
if MTH_BOOK_STATE.mode == "npcs" then
yOffset = -116
end
for i = 1, table.getn(controls) do
local control = controls[i]
if control then
control:ClearAllPoints()
control:SetPoint("TOPLEFT", control:GetParent(), "TOPLEFT", xOffsets[i], yOffset)
end
end
end
local function MTH_BOOK_DropdownSetText(frame, text)
local value = text or ""
if frame and frame.GetName then
local frameName = frame:GetName()
local txt = getglobal(frameName .. "Text")
if txt and txt.SetText then
txt:SetText(value)
end
local button = getglobal(frameName .. "Button")
if button and button.GetFontString and button:GetFontString() and button:GetFontString().SetText then
button:GetFontString():SetText(value)
end
local buttonText = getglobal(frameName .. "ButtonNormalText")
if buttonText and buttonText.SetText then
buttonText:SetText(value)
end
end
if frame and frame.Text and frame.Text.SetText then
frame.Text:SetText(value)
end
end
local function MTH_BOOK_DropdownCreateInfo()
local createInfo = _G["UIDropDownMenu_CreateInfo"]
if createInfo then return createInfo() end
return {}
end
local function MTH_BOOK_SetSliderFromCursor(slider)
if not slider then return end
local minValue, maxValue = slider:GetMinMaxValues()
if not minValue or not maxValue then return end
if maxValue <= minValue then
slider:SetValue(minValue)
return
end
local cursorX, cursorY = GetCursorPosition()
local scale = slider:GetEffectiveScale() or 1
local y = cursorY / scale
local bottom = slider:GetBottom()
local top = slider:GetTop()
if not bottom or not top or top <= bottom then return end
local pct = (y - bottom) / (top - bottom)
if pct < 0 then pct = 0 end
if pct > 1 then pct = 1 end
local value = minValue + (maxValue - minValue) * (1 - pct)
slider:SetValue(value)
end
local function MTH_BOOK_UpdateSliderMarker(slider)
if not slider then return end
local lane = getglobal("MTH_BOOK_ListSliderBackdrop")
if not lane then return end
if not lane._mthMarker then
lane._mthMarker = lane:CreateTexture(nil, "ARTWORK")
lane._mthMarker:SetTexture("Interface\\Buttons\\WHITE8X8")
lane._mthMarker:SetWidth(14)
lane._mthMarker:SetHeight(3)
lane._mthMarker:SetVertexColor(1.00, 0.82, 0.00, 0.90)
end
local marker = lane._mthMarker
local minValue, maxValue = slider:GetMinMaxValues()
local value = slider:GetValue() or minValue or 1
if not minValue or not maxValue or maxValue <= minValue then
marker:ClearAllPoints()
marker:SetPoint("TOP", lane, "TOP", 0, -4)
marker:Show()
return
end
local pct = (value - minValue) / (maxValue - minValue)
if pct < 0 then pct = 0 end
if pct > 1 then pct = 1 end
local travel = lane:GetHeight() - 8 - 8
if travel < 0 then travel = 0 end
marker:ClearAllPoints()
marker:SetPoint("BOTTOM", lane, "BOTTOM", 0, 4 + (travel * (1 - pct)))
marker:Show()
end
local function MTH_BOOK_HideSliderTemplateTexts()
local sliderLow = getglobal("MTH_BOOK_ListSliderLow")
local sliderHigh = getglobal("MTH_BOOK_ListSliderHigh")
local sliderText = getglobal("MTH_BOOK_ListSliderText")
if sliderLow then sliderLow:Hide() end
if sliderHigh then sliderHigh:Hide() end
if sliderText then sliderText:Hide() end
end
local function MTH_BOOK_SetFontSizeDelta(fontString, delta)
if not (fontString and fontString.GetFont and fontString.SetFont) then return end
local baseFont = fontString._mthBaseFont
local baseSize = fontString._mthBaseSize
local baseFlags = fontString._mthBaseFlags
if not baseFont or not baseSize then
local currentFont, currentSize, currentFlags = fontString:GetFont()
if not currentFont or not currentSize then return end
baseFont = currentFont
baseSize = currentSize
baseFlags = currentFlags
fontString._mthBaseFont = baseFont
fontString._mthBaseSize = baseSize
fontString._mthBaseFlags = baseFlags
end
fontString:SetFont(baseFont, baseSize + (delta or 0), baseFlags)
end
local function MTH_BOOK_SetFamiliesListVisualScale(enabled)
local rowHeight = enabled and 20 or 19
local textHeight = enabled and 15 or 14
local iconSize = enabled and 15 or 14
local chipHeight = enabled and 15 or 14
local chipIcon = enabled and 13 or 12
local fontDelta = enabled and 1 or 0
for i = 1, MTH_BOOK_MAX_COLS do
local header = MTH_BOOK_STATE.headerCols and MTH_BOOK_STATE.headerCols[i] or nil
if header then
header:SetHeight(textHeight)
MTH_BOOK_SetFontSizeDelta(header, fontDelta)
end
end
for i = 1, table.getn(MTH_BOOK_STATE.buttons or {}) do
local button = MTH_BOOK_STATE.buttons[i]
if button then
button:SetHeight(rowHeight)
if button.bookLinkButton then button.bookLinkButton:SetHeight(rowHeight) end
if button.nameHoverButton then button.nameHoverButton:SetHeight(rowHeight) end
if button.itemLinkButton then button.itemLinkButton:SetHeight(rowHeight) end
if button.itemIcon then
button.itemIcon:SetWidth(iconSize)
button.itemIcon:SetHeight(iconSize)
end
for c = 1, table.getn(button.cols or {}) do
local col = button.cols[c]
if col then
col:SetHeight(textHeight)
MTH_BOOK_SetFontSizeDelta(col, fontDelta)
end
end
for chipIndex = 1, table.getn(button.familyAbilityButtons or {}) do
local chip = button.familyAbilityButtons[chipIndex]
if chip then
chip:SetHeight(chipHeight)
if chip.icon then
chip.icon:SetWidth(chipIcon)
chip.icon:SetHeight(chipIcon)
end
if chip.text then
MTH_BOOK_SetFontSizeDelta(chip.text, fontDelta)
end
end
end
end
end
end
local function MTH_BOOK_OpenNPCLink(npcId)
local id = tonumber(npcId)
if not id then return end
local url = string.format(MTH_BOOK_NPC_DATABASE_URL, id)
local chatEditBox = _G["ChatFrameEditBox"]
if chatEditBox then
chatEditBox:Show()
chatEditBox:SetText(url)
chatEditBox:HighlightText()
end
if DEFAULT_CHAT_FRAME then
MTH:Print("[MetaHunt Book] " .. url)
end
end
local function MTH_BOOK_OpenItemDatabaseLink(itemId)
local id = tonumber(itemId)
if not id then return end
local url = string.format(MTH_BOOK_ITEM_DATABASE_URL, id)
local chatEditBox = _G["ChatFrameEditBox"]
if chatEditBox then
chatEditBox:Show()
chatEditBox:SetText(url)
chatEditBox:HighlightText()
end
if DEFAULT_CHAT_FRAME then
MTH:Print("[MetaHunt Book] " .. url)
end
end
local function MTH_BOOK_InsertItemLinkToChat(itemId)
local id = tonumber(itemId)
if not id then return false end
local itemName = nil
local items = _G["MTH_DS_Items"] or MTH_DS_AmmoItems
if items and items[id] and items[id].name then
itemName = items[id].name
end
local itemLink = nil
if type(MTH_GetClickableItemLink) == "function" then
itemLink = MTH_GetClickableItemLink(id, itemName, true)
end
if not itemLink or itemLink == "" then return false end
if type(MTH_InsertLinkToChat) == "function" then
return MTH_InsertLinkToChat(itemLink)
end
local chatEditBox = _G["ChatFrameEditBox"]
if chatEditBox then
chatEditBox:Show()
chatEditBox:SetText(itemLink)
chatEditBox:HighlightText()
return true
end
return false
end
local function MTH_BOOK_ShowItemTooltip(anchorFrame, itemId)
local id = tonumber(itemId)
if not id then return end
if not GameTooltip then return end
if type(MTH_PrimeItemCache) == "function" then
MTH_PrimeItemCache(id)
end
GameTooltip:SetOwner(anchorFrame or UIParent, "ANCHOR_CURSOR")
GameTooltip:SetHyperlink("item:" .. tostring(id) .. ":0:0:0")
GameTooltip:Show()
end
local function MTH_BOOK_HideItemTooltip()
if GameTooltip then
GameTooltip:Hide()
end
end
local function MTH_BOOK_GetSelectedBeastForMap()
if MTH_BOOK_STATE.mode ~= "pets" then return nil, nil end
local selected = MTH_BOOK_STATE.selectedEntry
if not selected or not selected.beastId then return nil, nil end
local beastId = tonumber(selected.beastId)
if not beastId then return nil, nil end
local beast = MTH_DS_Beasts and MTH_DS_Beasts[beastId]
if not beast then return nil, nil end
local coords = beast and beast.coords
if not coords or table.getn(coords) == 0 then return nil, nil end
return beastId, beast
end
local function MTH_BOOK_GetSelectedNPCForMap()
if MTH_BOOK_STATE.mode ~= "npcs" then return nil, nil end
local selected = MTH_BOOK_STATE.selectedEntry
if not selected or not selected.npcId then return nil, nil end
local npcId = tonumber(selected.npcId)
if not npcId then return nil, nil end
local npc = MTH_DS_Vendors and MTH_DS_Vendors[npcId]
if not npc then return nil, nil end
local coords = npc.coords
if not coords or table.getn(coords) == 0 then return nil, nil end
return npcId, npc
end
local function MTH_BOOK_UpdateOpenMapButton()
local openMapButton = getglobal("MTH_BOOK_OpenMapButton")
if not openMapButton then return end
local beastId = MTH_BOOK_GetSelectedBeastForMap()
local npcId = MTH_BOOK_GetSelectedNPCForMap()
if beastId or npcId then
openMapButton:Show()
openMapButton:Enable()
else
openMapButton:Hide()
end
end
local function MTH_BOOK_OpenSelectedBeastOnMap()
local beastId, beast = MTH_BOOK_GetSelectedBeastForMap()
if not beastId then
local npcId, npc = MTH_BOOK_GetSelectedNPCForMap()
if not npcId then return end
if not MTH_Map or not MTH_Map.FocusVendor then return end
local okNpc = MTH_Map:FocusVendor(npcId, npc)
if not okNpc then return end
if DEFAULT_CHAT_FRAME then
local npcName = npc and npc.name or "Unknown"
MTH:Print("Focused map markers for " .. tostring(npcName) .. " (" .. tostring(npcId) .. ")")
end
return
end
if not MTH_Map or not MTH_Map.FocusBeast then
return
end
local ok = MTH_Map:FocusBeast(beastId, beast)
if not ok then
return
end
if DEFAULT_CHAT_FRAME then
local beastName = beast and beast.name or "Unknown"
MTH:Print("Focused map markers for " .. tostring(beastName) .. " (" .. tostring(beastId) .. ")")
end
end
function MTH_BOOK_OpenTamePointOnMap(zoneId, x, y, title, detail)
local zid = tonumber(zoneId)
local nx = tonumber(x)
local ny = tonumber(y)
if not (zid and nx and ny) then
return false
end
if nx > 0 and nx <= 1 then
nx = nx * 100
end
if ny > 0 and ny <= 1 then
ny = ny * 100
end
if not (MTH_Map and MTH_Map.SetSource and MTH_Map.UpdateWorldMap and MTH_Map.UpdateMinimap) then
return false
end
MTH_Map.focusNodes = {
{
zoneId = zid,
x = nx,
y = ny,
title = tostring(title or "Tame Location"),
detail = tostring(detail or ""),
color = { 0.95, 0.82, 0.10 },
}
}
if not MTH_Map:SetSource("focus") then
return false
end
if MTH_Map.OpenWorldMapForZone then
MTH_Map:OpenWorldMapForZone(zid)
end
MTH_Map:UpdateWorldMap()
MTH_Map:UpdateMinimap()
return true
end
local function MTH_BOOK_ShouldShowAllOnMapButton()
return MTH_BOOK_STATE.mode == "pets" and MTH_BOOK_STATE.petInZoneOnly and true or false
end
local function MTH_BOOK_UpdateShowAllOnMapButton()
local showAllButton = getglobal("MTH_BOOK_ShowAllOnMapButton")
if not showAllButton then return end
if MTH_BOOK_ShouldShowAllOnMapButton() then
showAllButton:Show()
else
showAllButton:Hide()
end
end
local function MTH_BOOK_ShowAllFilteredBeastsOnMap()
if not MTH_BOOK_ShouldShowAllOnMapButton() then
return
end
if not (MTH_Map and MTH_Map.SetSource and MTH_Map.UpdateWorldMap and MTH_Map.UpdateMinimap) then
return
end
local nodes = {}
local firstZoneId = nil
for i = 1, table.getn(MTH_BOOK_STATE.results or {}) do
local beastId = tonumber(MTH_BOOK_STATE.results[i])
local beast = beastId and MTH_DS_Beasts and MTH_DS_Beasts[beastId]
if beast and beast.coords then
for j = 1, table.getn(beast.coords) do
local c = beast.coords[j]
if c and c[1] and c[2] and c[3] then
local x = tonumber(c[1])
local y = tonumber(c[2])
local zoneId = tonumber(c[3])
if x and y and zoneId then
if not firstZoneId then
firstZoneId = zoneId
end
local details = string.format("Family: %s\nLevel: %s\nAbilities: %s", beast.family or "?", beast.lvl or "?", beast.abilities or "None")
table.insert(nodes, {
zoneId = zoneId,
x = x,
y = y,
title = string.format("%s (%d)", beast.name or "Unknown", beastId),
detail = details,
beastId = beastId,
color = { 0.95, 0.82, 0.10 },
})
end
end
end
end
end
if table.getn(nodes) == 0 then
return
end
MTH_Map.focusNodes = nodes
if not MTH_Map:SetSource("focus") then
return
end
if firstZoneId and MTH_Map.OpenWorldMapForZone then
MTH_Map:OpenWorldMapForZone(firstZoneId)
end
MTH_Map:UpdateWorldMap()
MTH_Map:UpdateMinimap()
if MTH and MTH.Print then
MTH:Print("Focused map markers for " .. tostring(table.getn(nodes)) .. " beasts in this zone.")
end
end
local function MTH_BOOK_TryTargetSelectedEntry()
local entry = MTH_BOOK_STATE and MTH_BOOK_STATE.selectedEntry
if not entry then return false end
local name = entry.name
if not name or name == "" then return false end
local targetByName = _G["TargetByName"]
if type(targetByName) == "function" then
targetByName(name, true)
return true
end
return false
end
local function MTH_BOOK_SyncTopAreaColorWithSelectedTab()
local topAreaBackdrop = getglobal("MTH_BOOK_TopAreaBackdrop")
if not topAreaBackdrop then return end
topAreaBackdrop:SetBackdropColor(0.10, 0.10, 0.10, 1.00)
topAreaBackdrop:SetBackdropBorderColor(0.28, 0.28, 0.28, 1.00)
end
function MTH_BOOK_GetItemsTable()
local items = _G["MTH_DS_Items"]
if items then return items end
return MTH_DS_AmmoItems
end
local function MTH_BOOK_CountMap(map)
local count = 0
if not map then return 0 end
for _ in pairs(map) do count = count + 1 end
return count
end
function MTH_BOOK_HasEntries(map)
if not map then return false end
for _ in pairs(map) do return true end
return false
end
function MTH_BOOK_SafeLower(text)
if not text then return "" end
return string.lower(text)
end
local function MTH_BOOK_ParseBoxNumber(name)
local box = getglobal(name)
if not box then return nil end
local txt = box:GetText() or ""
txt = string.gsub(txt, "^%s+", "")
txt = string.gsub(txt, "%s+$", "")
if txt == "" then return nil end
return tonumber(txt)
end
function MTH_BOOK_ParseLevel(value)
if not value then return nil end
if type(value) == "number" then return value end
if type(value) ~= "string" then return nil end
local _, _, first = string.find(value, "(%d+)")
if not first then return nil end
return tonumber(first)
end
local function MTH_BOOK_GetItemQualityColorCode(quality)
local q = tonumber(quality)
if q == 2 then return "FFAA66FF" end
if q == 3 then return "FF0070DD" end
if q == 4 then return "FF1EFF00" end
if q == 5 then return "FFFFFFFF" end
if q == 6 then return "FF9D9D9D" end
return "FFFFFFFF"
end
local function MTH_BOOK_GetPlayerReactDefaults()
local faction = UnitFactionGroup and UnitFactionGroup("player")
if faction == "Alliance" then
return true, false, true
end
if faction == "Horde" then
return false, true, true
end
return true, true, true
end
local function MTH_BOOK_GetNPCReactBucket(fac)
if type(MTH_BOOKTAB_GetNPCReactBucket) == "function" then
return MTH_BOOKTAB_GetNPCReactBucket(fac)
end
return "AH"
end
local function MTH_BOOK_GetNPCFunctionLabel(key)
if type(MTH_BOOKTAB_GetNPCFunctionLabel) == "function" then
return MTH_BOOKTAB_GetNPCFunctionLabel(key)
end
return tostring(key or "")
end
local function MTH_BOOK_GetNPCFunctions(vendor)
if type(MTH_BOOKTAB_GetNPCFunctions) == "function" then
return MTH_BOOKTAB_GetNPCFunctions(vendor)
end
return {}
end
local function MTH_BOOK_GetNPCFunctionSummary(vendor)
if type(MTH_BOOKTAB_GetNPCFunctionSummary) == "function" then
return MTH_BOOKTAB_GetNPCFunctionSummary(vendor)
end
return "-", {}
end
local function MTH_BOOK_GetNPCZoneSummary(vendor)
if type(MTH_BOOKTAB_GetNPCZoneSummary) == "function" then
return MTH_BOOKTAB_GetNPCZoneSummary(vendor)
end
return "-", "-", {}
end
MTH_BOOK_GetZoneName = function(zoneId)
local normalizedId = tonumber(zoneId) or zoneId
if not normalizedId then return "Zone " .. tostring(zoneId or "?") end
if MTH_DS_ZoneNamesFallback and MTH_DS_ZoneNamesFallback[normalizedId] then
return MTH_DS_ZoneNamesFallback[normalizedId]
end
if not MTH_DS_Zones then return "Zone " .. tostring(zoneId or "?") end
local row = MTH_DS_Zones[normalizedId] or MTH_DS_Zones[tostring(normalizedId)]
if not row then return "Zone " .. tostring(normalizedId) end
local names = row.names
if not names then return "Zone " .. tostring(normalizedId) end
return names.enUS or names[GetLocale()] or names.deDE or names.frFR or ("Zone " .. tostring(normalizedId))
end
_G.MTH_BOOK_GetZoneName = MTH_BOOK_GetZoneName
function MTH_BOOK_NormalizeZoneLookupName(name)
if not name then return "" end
local lowered = string.lower(tostring(name))
return string.gsub(lowered, "[^%w]", "")
end
function MTH_BOOK_GetCurrentZoneId()
local zoneName = nil
if type(GetRealZoneText) == "function" then
zoneName = GetRealZoneText()
end
if (not zoneName or zoneName == "") and type(GetZoneText) == "function" then
zoneName = GetZoneText()
end
if not zoneName or zoneName == "" then
return nil
end
if MTH_Map and type(MTH_Map.GetMapIDByName) == "function" then
local mapId = MTH_Map:GetMapIDByName(zoneName)
if mapId then
return tonumber(mapId) or mapId
end
end
local normalized = MTH_BOOK_NormalizeZoneLookupName(zoneName)
if normalized == "" then
return nil
end
if MTH_DS_Zones then
for zoneId, row in pairs(MTH_DS_Zones) do
if row and row.names then
for _, value in pairs(row.names) do
if MTH_BOOK_NormalizeZoneLookupName(value) == normalized then
return tonumber(zoneId) or zoneId
end
end
end
end
end
if MTH_DS_ZoneNamesFallback then
for zoneId, value in pairs(MTH_DS_ZoneNamesFallback) do
if MTH_BOOK_NormalizeZoneLookupName(value) == normalized then
return tonumber(zoneId) or zoneId
end
end
end
return nil
end
function MTH_BOOK_BeastHasZoneId(beast, zoneId)
local zid = tonumber(zoneId)
if not zid or not beast or not beast.coords then
return false
end
for i = 1, table.getn(beast.coords) do
local c = beast.coords[i]
if c and tonumber(c[3]) == zid then
return true
end
end
return false
end
function MTH_BOOK_IsUnknownText(value)
local text = MTH_BOOK_SafeLower(value)
if text == "" then return true end
if text == "unknown" then return true end
if text == "?" or text == "??" or text == "???" then return true end
return false
end
local function MTH_BOOK_GetSortState()
local mode = MTH_BOOK_STATE.mode or "pets"
if not MTH_BOOK_STATE.sortByMode[mode] then
MTH_BOOK_STATE.sortByMode[mode] = { col = nil, asc = true }
end
return MTH_BOOK_STATE.sortByMode[mode]
end
function MTH_BOOK_GetPetDatastore()
if type(MTH_GetPetDatastoreSnapshot) == "function" then
local snapshot = MTH_GetPetDatastoreSnapshot()
if type(snapshot) == "table" then
return snapshot
end
end
if type(MTH_PETS_GetRootStore) == "function" then
local pets = MTH_PETS_GetRootStore()
if type(pets) == "table" and type(pets.petStore) == "table" then
return pets.petStore
end
end
return nil
end
function MTH_BOOK_GetPetStoreRow(petId)
local store = MTH_BOOK_GetPetDatastore()
if type(store) ~= "table" then return nil end
if MTH_BOOK_STATE.mode == "stable" and type(store.activeById) == "table" then
return store.activeById[petId]
end
if MTH_BOOK_STATE.mode == "pethistory" and type(store.historyById) == "table" then
return store.historyById[petId]
end
return nil
end
function MTH_BOOK_IsCurrentActivePetId(store, petId)
if type(store) ~= "table" then return false end
if petId == nil then return false end
if MTH_BOOK_STABLE_CURRENT_ID_CACHE and tostring(petId) == tostring(MTH_BOOK_STABLE_CURRENT_ID_CACHE) then
return true
end
return tostring(store.activeCurrentId or "") == tostring(petId)
end
function MTH_BOOK_ResolveCurrentPetId(store)
if type(store) == "table" and store.activeCurrentId ~= nil and tostring(store.activeCurrentId) ~= "" then
local activeId = tostring(store.activeCurrentId)
if type(store.activeById) == "table" and type(store.activeById[activeId]) == "table" then
return activeId
end
end
if type(MTH_PETS_GetRootStore) == "function" then
local pets = MTH_PETS_GetRootStore()
if type(pets) == "table" and pets.currentPetSuppressed == true then
return nil
end
local persistedCurrentId = pets and pets.currentPetId
if persistedCurrentId ~= nil and tostring(persistedCurrentId) ~= "" then
local currentId = tostring(persistedCurrentId)
if type(store) == "table" and type(store.activeById) == "table" and type(store.activeById[currentId]) == "table" then
return currentId
end
end
local cp = pets and pets.currentPet
if type(cp) == "table" and cp.id ~= nil and tostring(cp.id) ~= "" then
local currentId = tostring(cp.id)
if type(store) == "table" and type(store.activeById) == "table" and type(store.activeById[currentId]) == "table" then
return currentId
end
end
end
return nil
end
function MTH_BOOK_GetStableDisplaySlot(petId, row, store)
if type(row) ~= "table" then return nil end
if type(store) ~= "table" then
store = MTH_BOOK_GetPetDatastore()
end
if MTH_BOOK_IsCurrentActivePetId(store, petId) then
return 0
end
local slotNumber = tonumber(row.stableSlot)
if slotNumber and slotNumber > 0 then
return slotNumber
end
return nil
end
local function MTH_BOOK_IsStableListPet(petId, row, store)
return MTH_BOOK_GetStableDisplaySlot(petId, row, store) ~= nil
end
local function MTH_BOOK_StableSort(a, b)
if type(MTH_BOOKTAB_StableSort) == "function" then
return MTH_BOOKTAB_StableSort(a, b)
end
return tostring(a) < tostring(b)
end
local function MTH_BOOK_GetSortKey(entry, col)
if MTH_BOOK_STATE.mode == "pets" then
local beast = MTH_DS_Beasts and MTH_DS_Beasts[entry]
if not beast then return nil end
local traits = MTH_BOOK_ParseBeastTraits(beast)
if col == 1 then return tonumber(entry) or 0 end
if col == 2 then return MTH_BOOK_ParseLevel(beast.lvl) or 0 end
if col == 3 then return MTH_BOOK_SafeLower(beast.family) end
if col == 4 then return MTH_BOOK_SafeLower(beast.name) end
if col == 5 then return MTH_BOOK_SafeLower(MTH_BOOK_GetBeastAbilitiesSummary(beast)) end
if col == 6 then return MTH_BOOK_SafeLower(MTH_BOOK_GetBeastZoneSummary(beast)) end
if col == 7 then return traits.rare and 1 or 0 end
if col == 8 then return traits.elite and 1 or 0 end
if col == 9 then return traits.unique and 1 or 0 end
end
if MTH_BOOK_STATE.mode == "abilities" then
if col == 1 then return MTH_BOOK_SafeLower(entry.abilityToken) end
if col == 2 then return tonumber(entry.level) or 0 end
if col == 3 then return MTH_BOOK_SafeLower(entry.family) end
if col == 4 then return MTH_BOOK_SafeLower(entry.name) end
if col == 5 then return entry.rare and 1 or 0 end
end
if MTH_BOOK_STATE.mode == "petabilities" then
if col == 1 then return MTH_BOOK_SafeLower(entry.ability) end
if col == 2 then return tonumber(entry.rankCount) or 0 end
if col == 3 then
local familyCount = tonumber(entry.familyCount) or 0
return (familyCount * 10000) + string.len(MTH_BOOK_SafeLower(entry.familyList or ""))
end
end
if MTH_BOOK_STATE.mode == "families" then
if col == 1 then return MTH_BOOK_SafeLower(entry.family) end
if col == 2 then return tonumber(entry.named) or 0 end
if col == 3 then return tonumber(entry.coords) or 0 end
if col == 4 then return tonumber(entry.abilities and table.getn(entry.abilities) or 0) end
if col == 5 then return MTH_BOOK_SafeLower(entry.dietText or "") end
end
if MTH_BOOK_STATE.mode == "npcs" then
local vendors = MTH_DS_Vendors
local npc = vendors and vendors[entry]
if not npc then return nil end
local react = MTH_BOOK_GetNPCReactBucket(npc.fac)
local functionSummary = MTH_BOOK_GetNPCFunctionSummary(npc)
local zoneName = MTH_BOOK_GetNPCZoneSummary(npc)
if col == 1 then return tonumber(entry) or 0 end
if col == 2 then return MTH_BOOK_SafeLower(npc.name) end
if col == 3 then return react end
if col == 4 then return MTH_BOOK_SafeLower(functionSummary) end
if col == 5 then return MTH_BOOK_SafeLower(zoneName) end
end
if MTH_BOOK_STATE.mode == "stable" then
local store = MTH_BOOK_GetPetDatastore()
local row = MTH_BOOK_GetPetStoreRow(entry)
if not row then return nil end
if col == 1 then return tostring(entry) end
if col == 2 then return MTH_BOOK_GetStableDisplaySlot(entry, row, store) or 9999 end
if col == 3 then return MTH_BOOK_SafeLower(row.name) end
if col == 4 then return MTH_BOOK_SafeLower(row.family) end
if col == 5 then return tonumber(row.level) or 0 end
if col == 6 then return tonumber(row.loyaltyLevel) or (row.stableInfo and tonumber(row.stableInfo.loyaltyLevel)) or 0 end
if col == 7 then return tonumber(row.lastSeen) or 0 end
end
if MTH_BOOK_STATE.mode == "pethistory" then
local row = MTH_BOOK_GetPetStoreRow(entry)
if not row then return nil end
if col == 1 then return tostring(entry) end
if col == 2 then return MTH_BOOK_SafeLower(row.name) end
if col == 3 then return MTH_BOOK_SafeLower(row.family) end
if col == 4 then return tonumber(row.level) or 0 end
if col == 5 then return tonumber(row.abandonedAt) or 0 end
if col == 6 then return MTH_BOOK_SafeLower(tostring(row.abandonReason or "")) end
end
local items = MTH_BOOK_GetItemsTable()
local item = items and items[entry]
if not item then return nil end
if col == 1 then return tonumber(entry) or 0 end
if col == 2 then return tonumber(item.reqlevel) or 0 end
if col == 3 then return tonumber(item.level) or 0 end
if col == 4 then return MTH_BOOK_SafeLower(item.subtype) end
if col == 5 then return MTH_BOOK_SafeLower(item.name) end
if col == 6 then return tonumber(item.dps) or 0 end
if col == 7 then return tonumber(item.speed) or 0 end
return nil
end
local function MTH_BOOK_DefaultCompare(a, b)
if MTH_BOOK_STATE.mode == "pets" then return MTH_BOOK_BeastSort(a, b) end
if MTH_BOOK_STATE.mode == "families" then
local fa = MTH_BOOK_SafeLower(a and a.family)
local fb = MTH_BOOK_SafeLower(b and b.family)
if fa ~= fb then return fa < fb end
return tostring(a and a.family or "") < tostring(b and b.family or "")
end
if MTH_BOOK_STATE.mode == "abilities" then return MTH_BOOK_AbilitySort(a, b) end
if MTH_BOOK_STATE.mode == "petabilities" then return MTH_BOOK_PetAbilitySort(a, b) end
if MTH_BOOK_STATE.mode == "npcs" then return MTH_BOOK_NPCSort(a, b) end
if MTH_BOOK_STATE.mode == "stable" then return MTH_BOOK_StableSort(a, b) end
if MTH_BOOK_STATE.mode == "pethistory" then return MTH_BOOK_PetHistorySort(a, b) end
return MTH_BOOK_ItemSort(a, b)
end
local function MTH_BOOK_ApplyActiveSort(results)
local state = MTH_BOOK_GetSortState()
if not state.col then return end
table.sort(results, function(a, b)
local ka = MTH_BOOK_GetSortKey(a, state.col)
local kb = MTH_BOOK_GetSortKey(b, state.col)
if ka ~= kb then
if ka == nil then return not state.asc end
if kb == nil then return state.asc end
if state.asc then
return ka < kb
end
return ka > kb
end
return MTH_BOOK_DefaultCompare(a, b)
end)
end
local function MTH_BOOK_BuildResults()
local results = {}
if MTH_BOOK_STATE.mode == "pets" then
if not MTH_DS_Beasts then return results end
for beastId, beast in pairs(MTH_DS_Beasts) do
if MTH_BOOK_BeastMatches(beastId, beast) then
table.insert(results, beastId)
end
end
table.sort(results, MTH_BOOK_BeastSort)
MTH_BOOK_ApplyActiveSort(results)
return results
end
if MTH_BOOK_STATE.mode == "abilities" then
if not MTH_DS_Beasts then return results end
for beastId, beast in pairs(MTH_DS_Beasts) do
local beastLevel = MTH_BOOK_ParseLevel(beast.lvl)
if (not MTH_BOOK_STATE.minLevel or (beastLevel and beastLevel >= MTH_BOOK_STATE.minLevel))
and (not MTH_BOOK_STATE.maxLevel or (beastLevel and beastLevel <= MTH_BOOK_STATE.maxLevel))
and (not MTH_BOOK_STATE.flag2 or beast.rare)
and (not MTH_BOOK_STATE.flag3 or (beast.coords and table.getn(beast.coords) > 0))
then
local abilities = MTH_BOOK_SplitAbilities(beast.abilities)
for _, abilityToken in ipairs(abilities) do
local abilityLower = MTH_BOOK_SafeLower(abilityToken)
local _, _, rank = string.find(abilityToken, "(%d+)$")
local abilityName = abilityToken
if rank then
abilityName = string.gsub(abilityToken, "%s*%d+$", "")
end
local abilityNameLower = MTH_BOOK_SafeLower(abilityName)
if (MTH_BOOK_STATE.quick == "all" or string.find(abilityNameLower, MTH_BOOK_STATE.quick, 1, true) ~= nil)
and (not MTH_BOOK_STATE.flag1 or rank ~= nil)
then
if MTH_BOOK_STATE.search == ""
or string.find(abilityLower, MTH_BOOK_STATE.search, 1, true) ~= nil
or string.find(MTH_BOOK_SafeLower(beast.name), MTH_BOOK_STATE.search, 1, true) ~= nil
or string.find(MTH_BOOK_SafeLower(beast.family), MTH_BOOK_STATE.search, 1, true) ~= nil
then
table.insert(results, {
beastId = beastId,
name = beast.name or "Unknown",
family = beast.family or "?",
level = beastLevel or 0,
rare = beast.rare and true or false,
ability = abilityName,
rank = rank,
abilityToken = abilityToken,
})
end
end
end
end
end
table.sort(results, MTH_BOOK_AbilitySort)
MTH_BOOK_ApplyActiveSort(results)
return results
end
if MTH_BOOK_STATE.mode == "petabilities" then
results = MTH_BOOK_BuildPetAbilitiesRows(false)
MTH_BOOK_ApplyActiveSort(results)
return results
end
if MTH_BOOK_STATE.mode == "families" then
if type(MTH_BOOKTAB_BuildFamiliesRows) == "function" then
results = MTH_BOOKTAB_BuildFamiliesRows()
MTH_BOOK_FamiliesTrace("BuildResults families rows=" .. tostring(table.getn(results or {})))
else
MTH_BOOK_FamiliesTrace("BuildResults families missing MTH_BOOKTAB_BuildFamiliesRows")
end
MTH_BOOK_ApplyActiveSort(results)
return results
end
if MTH_BOOK_STATE.mode == "npcs" then
if not MTH_DS_Vendors then return results end
for npcId, vendor in pairs(MTH_DS_Vendors) do
if MTH_BOOK_NPCMatches(npcId, vendor) then
table.insert(results, npcId)
end
end
table.sort(results, MTH_BOOK_NPCSort)
MTH_BOOK_ApplyActiveSort(results)
return results
end
if MTH_BOOK_STATE.mode == "stable" then
local store = MTH_BOOK_GetPetDatastore()
if type(store) ~= "table" or type(store.activeById) ~= "table" then return results end
MTH_BOOK_STABLE_CURRENT_ID_CACHE = MTH_BOOK_ResolveCurrentPetId(store)
local activeCount = MTH_BOOK_CountMap(store.activeById)
MTH_BOOK_DebugTrace("BuildResults stable: activeById=" .. tostring(activeCount) .. " activeCurrentId=" .. tostring(store.activeCurrentId) .. " resolvedCurrentId=" .. tostring(MTH_BOOK_STABLE_CURRENT_ID_CACHE))
for petId, row in pairs(store.activeById) do
if type(row) == "table" and MTH_BOOK_IsStableListPet(petId, row, store) then
table.insert(results, petId)
end
end
MTH_BOOK_DebugTrace("BuildResults stable: included=" .. tostring(table.getn(results)))
table.sort(results, MTH_BOOK_StableSort)
MTH_BOOK_ApplyActiveSort(results)
return results
end
if MTH_BOOK_STATE.mode == "pethistory" then
local store = MTH_BOOK_GetPetDatastore()
if type(store) ~= "table" or type(store.historyById) ~= "table" then return results end
for petId, row in pairs(store.historyById) do
if type(row) == "table" then
table.insert(results, petId)
end
end
table.sort(results, MTH_BOOK_PetHistorySort)
MTH_BOOK_ApplyActiveSort(results)
return results
end
local items = MTH_BOOK_GetItemsTable()
if not items then return results end
for itemId, item in pairs(items) do
if MTH_BOOK_ItemMatches(itemId, item) then
table.insert(results, itemId)
end
end
table.sort(results, MTH_BOOK_ItemSort)
MTH_BOOK_ApplyActiveSort(results)
return results
end
local function MTH_BOOK_GetTotalCount()
if MTH_BOOK_STATE.mode == "pets" or MTH_BOOK_STATE.mode == "abilities" then
return MTH_DS_Beasts and MTH_BOOK_CountMap(MTH_DS_Beasts) or 0
end
if MTH_BOOK_STATE.mode == "petabilities" then
return table.getn(MTH_BOOK_BuildPetAbilitiesRows(true))
end
if MTH_BOOK_STATE.mode == "families" then
if type(MTH_BOOKTAB_BuildFamiliesRows) == "function" then
return table.getn(MTH_BOOKTAB_BuildFamiliesRows())
end
return 0
end
if MTH_BOOK_STATE.mode == "npcs" then
return MTH_DS_Vendors and MTH_BOOK_CountMap(MTH_DS_Vendors) or 0
end
if MTH_BOOK_STATE.mode == "stable" then
local store = MTH_BOOK_GetPetDatastore()
if type(store) ~= "table" or type(store.activeById) ~= "table" then return 0 end
local total = 0
for petId, row in pairs(store.activeById) do
if type(row) == "table" and MTH_BOOK_IsStableListPet(petId, row, store) then
total = total + 1
end
end
return total
end
if MTH_BOOK_STATE.mode == "pethistory" then
local store = MTH_BOOK_GetPetDatastore()
return (type(store) == "table" and type(store.historyById) == "table") and MTH_BOOK_CountMap(store.historyById) or 0
end
local items = MTH_BOOK_GetItemsTable()
return items and MTH_BOOK_CountMap(items) or 0
end
local function MTH_BOOK_BuildPetFamilyOptions()
local familyMap = {}
if MTH_DS_Families then
for familyName in pairs(MTH_DS_Families) do
if familyName and familyName ~= "" then
familyMap[MTH_BOOK_SafeLower(familyName)] = familyName
end
end
end
if MTH_DS_Beasts then
for _, beast in pairs(MTH_DS_Beasts) do
if beast and beast.family and beast.family ~= "" then
local lower = MTH_BOOK_SafeLower(beast.family)
if not familyMap[lower] then
familyMap[lower] = beast.family
end
end
end
end
local rows = {}
for value, label in pairs(familyMap) do
table.insert(rows, { value = value, label = label })
end
table.sort(rows, function(a, b)
return MTH_BOOK_SafeLower(a.label) < MTH_BOOK_SafeLower(b.label)
end)
MTH_BOOK_PetFamilyOptions = {
{ value = "all", label = "All Families" },
}
for i = 1, table.getn(rows) do
table.insert(MTH_BOOK_PetFamilyOptions, rows[i])
end
if MTH_BOOK_STATE.quick ~= "all" and not familyMap[MTH_BOOK_STATE.quick] then
MTH_BOOK_STATE.quick = "all"
end
end
local function MTH_BOOK_GetPetFamilyLabel(value)
for i = 1, table.getn(MTH_BOOK_PetFamilyOptions) do
local option = MTH_BOOK_PetFamilyOptions[i]
if option and option.value == value then
return option.label, i
end
end
return "All Families", 1
end
local function MTH_BOOK_BuildPetAbilityOptions()
local abilityMap = {}
local selectedFamily = MTH_BOOK_SafeLower(MTH_BOOK_STATE.quick)
if MTH_DS_Beasts then
for _, beast in pairs(MTH_DS_Beasts) do
local beastFamily = MTH_BOOK_SafeLower(beast and beast.family or "")
if selectedFamily == "all" or beastFamily == selectedFamily then
local abilities = MTH_BOOK_SplitAbilities(beast and beast.abilities)
for i = 1, table.getn(abilities) do
local abilityLower, abilityLabel, rank = MTH_BOOK_ParseAbilityToken(abilities[i])
if abilityLower ~= "" and abilityLower ~= "none" and abilityLower ~= "unknown" then
local row = abilityMap[abilityLower]
if not row then
row = { value = abilityLower, label = abilityLabel, ranks = {} }
abilityMap[abilityLower] = row
end
if rank then
row.ranks[rank] = true
end
end
end
end
end
end
if MTH_DS_PetSpells and MTH_DS_PetSpells.byAbility then
for abilityName, bucket in pairs(MTH_DS_PetSpells.byAbility) do
local abilityLabel = tostring(abilityName or "")
local abilityLower = MTH_BOOK_SafeLower(abilityLabel)
if abilityLower ~= "" and abilityLower ~= "none" and abilityLower ~= "unknown" then
local row = abilityMap[abilityLower]
if not row then
row = { value = abilityLower, label = abilityLabel, ranks = {} }
abilityMap[abilityLower] = row
end
if bucket and bucket.spells then
for i = 1, table.getn(bucket.spells) do
local spell = bucket.spells[i]
if spell then
local rank = tonumber(spell.rankNumber)
if rank and rank > 0 then
row.ranks[rank] = true
end
end
end
end
end
end
end
local rows = {}
for _, row in pairs(abilityMap) do
table.insert(rows, row)
end
table.sort(rows, function(a, b)
return MTH_BOOK_SafeLower(a.label) < MTH_BOOK_SafeLower(b.label)
end)
MTH_BOOK_PetAbilityOptions = {
{ value = "all", label = "All abilities" },
}
MTH_BOOK_PetAbilityRanks = {}
for i = 1, table.getn(rows) do
local row = rows[i]
table.insert(MTH_BOOK_PetAbilityOptions, { value = row.value, label = row.label })
MTH_BOOK_PetAbilityRanks[row.value] = row.ranks
end
if MTH_BOOK_STATE.petAbility ~= "all" and not abilityMap[MTH_BOOK_STATE.petAbility] then
MTH_BOOK_STATE.petAbility = "all"
MTH_BOOK_STATE.petRank = "all"
end
end
local function MTH_BOOK_BuildPetRankOptions()
MTH_BOOK_PetRankOptions = {
{ value = "all", label = "All ranks" },
}
if MTH_BOOK_STATE.petAbility == "all" then
MTH_BOOK_STATE.petRank = "all"
return false
end
local ranksMap = MTH_BOOK_PetAbilityRanks and MTH_BOOK_PetAbilityRanks[MTH_BOOK_STATE.petAbility]
if not ranksMap then
MTH_BOOK_STATE.petRank = "all"
return false
end
local ranks = {}
for rank in pairs(ranksMap) do
table.insert(ranks, tonumber(rank))
end
table.sort(ranks)
if table.getn(ranks) == 0 then
MTH_BOOK_STATE.petRank = "all"
return false
end
for i = 1, table.getn(ranks) do
local rank = ranks[i]
table.insert(MTH_BOOK_PetRankOptions, { value = tostring(rank), label = "Rank " .. tostring(rank) })
end
if MTH_BOOK_STATE.petRank ~= "all" then
local keep = false
for i = 1, table.getn(ranks) do
if tostring(ranks[i]) == tostring(MTH_BOOK_STATE.petRank) then
keep = true
break
end
end
if not keep then
MTH_BOOK_STATE.petRank = "all"
end
end
return true
end
local function MTH_BOOK_GetPetAbilityLabel(value)
for i = 1, table.getn(MTH_BOOK_PetAbilityOptions) do
local option = MTH_BOOK_PetAbilityOptions[i]
if option and option.value == value then
return option.label, i
end
end
return "All abilities", 1
end
local function MTH_BOOK_GetPetRankLabel(value)
for i = 1, table.getn(MTH_BOOK_PetRankOptions) do
local option = MTH_BOOK_PetRankOptions[i]
if option and option.value == value then
return option.label, i
end
end
return "All ranks", 1
end
local function MTH_BOOK_GetPetLearnSourceLabel(value)
for i = 1, table.getn(MTH_BOOK_PetLearnSourceOptions) do
local option = MTH_BOOK_PetLearnSourceOptions[i]
if option and option.value == value then
return option.label
end
end
return "All Abilities"
end
MTH_BOOK_GetPlayerLevelValue = function()
if type(UnitLevel) == "function" then
local lvl = tonumber(UnitLevel("player"))
if lvl and lvl > 0 then
return lvl
end
end
return nil
end
_G.MTH_BOOK_GetPlayerLevelValue = MTH_BOOK_GetPlayerLevelValue
MTH_BOOK_IsSpellInLevelScope = function(trainLevel)
if not MTH_BOOK_STATE.petOnlyMyLevel then
return true
end
local playerLevel = MTH_BOOK_GetPlayerLevelValue()
if not playerLevel then
return true
end
local req = tonumber(trainLevel)
if not req then
return true
end
return req <= playerLevel
end
_G.MTH_BOOK_IsSpellInLevelScope = MTH_BOOK_IsSpellInLevelScope
MTH_BOOK_GetScopedRankSummary = function(abilityName)
local rankMap = {}
local knownRankMap = {}
local minRank = nil
local maxRank = nil
local minTrainLevel = nil
local maxTrainLevel = nil
if not (MTH_DS_PetSpells and MTH_DS_PetSpells.byAbility) then
return 0, 0, nil, nil, nil, nil
end
local bucket = MTH_DS_PetSpells.byAbility[abilityName]
if not (bucket and bucket.spells) then
return 0, 0, nil, nil, nil, nil
end
for i = 1, table.getn(bucket.spells) do
local spell = bucket.spells[i]
if spell and MTH_BOOK_IsSpellInLevelScope(tonumber(spell.trainLevel)) then
local rankNumber = tonumber(spell.rankNumber)
if not rankNumber and spell.rank then
local _, _, parsed = string.find(tostring(spell.rank), "(%d+)")
rankNumber = tonumber(parsed)
end
if rankNumber and rankNumber > 0 then
rankMap[rankNumber] = true
if MTH_BOOK_IsKnownRankForAbility(abilityName, rankNumber) then
knownRankMap[rankNumber] = true
end
if not minRank or rankNumber < minRank then minRank = rankNumber end
if not maxRank or rankNumber > maxRank then maxRank = rankNumber end
end
local trainLevel = tonumber(spell.trainLevel)
if trainLevel then
if not minTrainLevel or trainLevel < minTrainLevel then minTrainLevel = trainLevel end
if not maxTrainLevel or trainLevel > maxTrainLevel then maxTrainLevel = trainLevel end
end
end
end
local rankCount = 0
for _ in pairs(rankMap) do rankCount = rankCount + 1 end
local knownCount = 0
for _ in pairs(knownRankMap) do knownCount = knownCount + 1 end
if rankCount == 0 then
local hasAnyScopedRows = false
for i = 1, table.getn(bucket.spells) do
local spell = bucket.spells[i]
if spell and MTH_BOOK_IsSpellInLevelScope(tonumber(spell.trainLevel)) then
hasAnyScopedRows = true
break
end
end
if hasAnyScopedRows then
rankCount = 1
if MTH_BOOK_IsKnownRankForAbility(abilityName, 0) then
knownCount = 1
end
end
end
if knownCount > rankCount then knownCount = rankCount end
return knownCount, rankCount, minRank, maxRank, minTrainLevel, maxTrainLevel
end
_G.MTH_BOOK_GetScopedRankSummary = MTH_BOOK_GetScopedRankSummary
local function MTH_BOOK_BuildNPCFunctionOptions()
MTH_BOOK_NPCFunctionOptions = {
{ value = "all", label = "All Hunter Friends" },
{ value = "huntertrainer", label = "Hunter Trainer" },
{ value = "pettrainer", label = "Pet Trainer" },
{ value = "vendor", label = "Ammo Vendor" },
}
local allowed = {
all = true,
huntertrainer = true,
pettrainer = true,
vendor = true,
}
if not allowed[MTH_BOOK_STATE.npcFunction] then
MTH_BOOK_STATE.npcFunction = "all"
end
end
local function MTH_BOOK_BuildNPCZoneOptions()
local seen = {}
local rows = {}
if MTH_DS_Vendors then
for _, vendor in pairs(MTH_DS_Vendors) do
local _, _, zones = MTH_BOOK_GetNPCZoneSummary(vendor)
for i = 1, table.getn(zones) do
local zone = zones[i]
if zone ~= "-" and not seen[zone] then
seen[zone] = true
table.insert(rows, { value = zone, label = zone })
end
end
end
end
table.sort(rows, function(a, b)
return MTH_BOOK_SafeLower(a.label) < MTH_BOOK_SafeLower(b.label)
end)
MTH_BOOK_NPCZoneOptions = {
{ value = "all", label = "All Zones" },
}
for i = 1, table.getn(rows) do
table.insert(MTH_BOOK_NPCZoneOptions, rows[i])
end
if MTH_BOOK_STATE.npcZone ~= "all" and not seen[MTH_BOOK_STATE.npcZone] then
MTH_BOOK_STATE.npcZone = "all"
end
end
local function MTH_BOOK_GetNPCFunctionLabelByValue(value)
for i = 1, table.getn(MTH_BOOK_NPCFunctionOptions) do
local option = MTH_BOOK_NPCFunctionOptions[i]
if option and option.value == value then
return option.label
end
end
return "All Hunter Friends"
end
local function MTH_BOOK_GetNPCZoneLabelByValue(value)
for i = 1, table.getn(MTH_BOOK_NPCZoneOptions) do
local option = MTH_BOOK_NPCZoneOptions[i]
if option and option.value == value then
return option.label
end
end
return "All Zones"
end
local function MTH_BOOK_UpdateFamilyDropdownText()
local familyDropdown = getglobal("MTH_BOOK_FamilyDropdown")
if not familyDropdown then return end
local label, index = MTH_BOOK_GetPetFamilyLabel(MTH_BOOK_STATE.quick)
MTH_BOOK_DropdownSetText(familyDropdown, label)
end
local function MTH_BOOK_UpdateAbilityDropdownText()
local abilityDropdown = getglobal("MTH_BOOK_AbilityDropdown")
if not abilityDropdown then return end
local label, index = MTH_BOOK_GetPetAbilityLabel(MTH_BOOK_STATE.petAbility)
MTH_BOOK_DropdownSetText(abilityDropdown, label)
end
local function MTH_BOOK_UpdateRankDropdownText()
local rankDropdown = getglobal("MTH_BOOK_RankDropdown")
if not rankDropdown then return end
local label, index = MTH_BOOK_GetPetRankLabel(MTH_BOOK_STATE.petRank)
MTH_BOOK_DropdownSetText(rankDropdown, label)
end
local function MTH_BOOK_UpdatePetLearnSourceDropdownText()
local sourceDropdown = getglobal("MTH_BOOK_PetLearnSourceDropdown")
if not sourceDropdown then return end
MTH_BOOK_DropdownSetText(sourceDropdown, MTH_BOOK_GetPetLearnSourceLabel(MTH_BOOK_STATE.petLearnSource))
end
local function MTH_BOOK_GetItemSubtypeLabelByValue(value)
for i = 1, table.getn(MTH_BOOK_ItemSubtypeOptions) do
local option = MTH_BOOK_ItemSubtypeOptions[i]
if option and option.value == value then
return option.label
end
end
return "All Ranged"
end
local function MTH_BOOK_UpdateItemSubtypeDropdownText()
local itemDropdown = getglobal("MTH_BOOK_ItemSubtypeDropdown")
if not itemDropdown then return end
MTH_BOOK_DropdownSetText(itemDropdown, MTH_BOOK_GetItemSubtypeLabelByValue(MTH_BOOK_STATE.itemSubtype))
end
local function MTH_BOOK_UpdateNPCDropdownTexts()
local functionDropdown = getglobal("MTH_BOOK_NPCFunctionDropdown")
local zoneDropdown = getglobal("MTH_BOOK_NPCZoneDropdown")
if functionDropdown then
MTH_BOOK_DropdownSetText(functionDropdown, MTH_BOOK_GetNPCFunctionLabelByValue(MTH_BOOK_STATE.npcFunction))
end
if zoneDropdown then
MTH_BOOK_DropdownSetText(zoneDropdown, MTH_BOOK_GetNPCZoneLabelByValue(MTH_BOOK_STATE.npcZone))
end
end
local function MTH_BOOK_UpdateQuickFilterControls()
MTH_BOOK_UpdateCheckboxLayoutByMode()
if MTH_BOOK_STATE.mode == "items" then
MTH_BOOK_STATE.pageSize = 18
elseif MTH_BOOK_STATE.mode == "families" then
MTH_BOOK_STATE.pageSize = 16
elseif MTH_BOOK_STATE.mode == "stable" then
MTH_BOOK_STATE.pageSize = 5
elseif MTH_BOOK_STATE.mode == "pethistory" then
MTH_BOOK_STATE.pageSize = 20
else
MTH_BOOK_STATE.pageSize = 16
end
local familyDropdown = getglobal("MTH_BOOK_FamilyDropdown")
local abilityDropdown = getglobal("MTH_BOOK_AbilityDropdown")
local rankDropdown = getglobal("MTH_BOOK_RankDropdown")
local petLearnSourceDropdown = getglobal("MTH_BOOK_PetLearnSourceDropdown")
local itemSubtypeDropdown = getglobal("MTH_BOOK_ItemSubtypeDropdown")
local npcFunctionDropdown = getglobal("MTH_BOOK_NPCFunctionDropdown")
local npcZoneDropdown = getglobal("MTH_BOOK_NPCZoneDropdown")
local searchLabel = getglobal("MTH_BOOK_SearchLabel")
local minLabel = getglobal("MTH_BOOK_MinLabel")
local maxLabel = getglobal("MTH_BOOK_MaxLabel")
local search = getglobal("MTH_BOOK_Search")
local applyButton = getglobal("MTH_BOOK_ApplyButton")
local scanButton = getglobal("MTH_BOOK_PetBookScanButton")
local hideNoAbilities = getglobal("MTH_BOOK_HideNoAbilities")
local hideUnknown = getglobal("MTH_BOOK_HideUnknown")
local petOnlyMyLevel = getglobal("MTH_BOOK_PetOnlyMyLevel")
local petInZoneOnly = getglobal("MTH_BOOK_PetInZoneOnly")
local npcInZoneOnly = getglobal("MTH_BOOK_NPCInZoneOnly")
local showAllOnMapButton = getglobal("MTH_BOOK_ShowAllOnMapButton")
local minLevel = getglobal("MTH_BOOK_MinLevel")
local maxLevel = getglobal("MTH_BOOK_MaxLevel")
local stats = getglobal("MTH_BOOK_StatsText")
local prevButton = getglobal("MTH_BOOK_PrevButton")
local nextButton = getglobal("MTH_BOOK_NextButton")
local listSlider = getglobal("MTH_BOOK_ListSlider")
local sliderBackdrop = getglobal("MTH_BOOK_ListSliderBackdrop")
if MTH_BOOK_STATE.mode == "petabilities" or MTH_BOOK_STATE.mode == "stable" then
if stats then stats:Hide() end
if prevButton then prevButton:Hide() end
if nextButton then nextButton:Hide() end
if listSlider then listSlider:Hide() end
if sliderBackdrop then sliderBackdrop:Hide() end
elseif MTH_BOOK_STATE.mode == "families" then
if stats then stats:Show() end
if prevButton then prevButton:Hide() end
if nextButton then nextButton:Hide() end
if listSlider then listSlider:Hide() end
if sliderBackdrop then sliderBackdrop:Hide() end
else
if stats then stats:Show() end
if prevButton then prevButton:Show() end
if nextButton then nextButton:Show() end
if listSlider then listSlider:Show() end
if sliderBackdrop then sliderBackdrop:Show() end
end
if MTH_BOOK_STATE.mode == "pets" then
if searchLabel then searchLabel:Show() end
if minLabel then minLabel:Show() end
if maxLabel then maxLabel:Show() end
if searchLabel then
searchLabel:ClearAllPoints()
searchLabel:SetPoint("TOPLEFT", searchLabel:GetParent(), "TOPLEFT", 18, -82)
end
if minLabel then
minLabel:ClearAllPoints()
minLabel:SetPoint("TOPLEFT", minLabel:GetParent(), "TOPLEFT", 248, -82)
end
if maxLabel then
maxLabel:ClearAllPoints()
maxLabel:SetPoint("TOPLEFT", maxLabel:GetParent(), "TOPLEFT", 356, -82)
end
if search then search:Show() end
if search then
search:ClearAllPoints()
search:SetPoint("TOPLEFT", search:GetParent(), "TOPLEFT", 66, -80)
search:SetWidth(160)
end
if minLevel then
minLevel:ClearAllPoints()
minLevel:SetPoint("TOPLEFT", minLevel:GetParent(), "TOPLEFT", 302, -80)
minLevel:Show()
end
if maxLevel then
maxLevel:ClearAllPoints()
maxLevel:SetPoint("TOPLEFT", maxLevel:GetParent(), "TOPLEFT", 414, -80)
maxLevel:Show()
end
if applyButton then applyButton:Show() end
if applyButton then
applyButton:ClearAllPoints()
applyButton:SetPoint("TOPLEFT", applyButton:GetParent(), "TOPLEFT", 478, -80)
end
local resetButton = getglobal("MTH_BOOK_ResetButton")
if resetButton then
resetButton:ClearAllPoints()
resetButton:SetPoint("TOPLEFT", resetButton:GetParent(), "TOPLEFT", 546, -80)
end
if scanButton then scanButton:Hide() end
MTH_BOOK_BuildPetAbilityOptions()
for i = 1, 6 do
local btn = getglobal("MTH_BOOK_Filter" .. i)
if btn then btn:Hide() end
end
if familyDropdown then
familyDropdown:Show()
MTH_BOOK_UpdateFamilyDropdownText()
end
if abilityDropdown then
abilityDropdown:Show()
MTH_BOOK_UpdateAbilityDropdownText()
end
local rankVisible = MTH_BOOK_BuildPetRankOptions()
if rankDropdown then
if rankVisible then
rankDropdown:Show()
MTH_BOOK_UpdateRankDropdownText()
else
rankDropdown:Hide()
end
end
if petInZoneOnly then
petInZoneOnly:Show()
petInZoneOnly:SetChecked(MTH_BOOK_STATE.petInZoneOnly and 1 or nil)
end
if showAllOnMapButton then
if MTH_BOOK_STATE.petInZoneOnly then
showAllOnMapButton:Show()
else
showAllOnMapButton:Hide()
end
end
if petLearnSourceDropdown then petLearnSourceDropdown:Hide() end
if itemSubtypeDropdown then itemSubtypeDropdown:Hide() end
if npcFunctionDropdown then npcFunctionDropdown:Hide() end
if npcZoneDropdown then npcZoneDropdown:Hide() end
MTH_BOOK_UpdateFamilyDropdownText()
MTH_BOOK_UpdateAbilityDropdownText()
if hideNoAbilities then hideNoAbilities:Show() end
if hideUnknown then hideUnknown:Show() end
if petOnlyMyLevel then petOnlyMyLevel:Hide() end
if npcInZoneOnly then npcInZoneOnly:Hide() end
local requireVendor = getglobal("MTH_BOOK_RequireVendor")
local requireDrop = getglobal("MTH_BOOK_RequireDrop")
local requireObject = getglobal("MTH_BOOK_RequireObject")
if requireVendor then requireVendor:Show() end
if requireDrop then requireDrop:Show() end
if requireObject then requireObject:Show() end
elseif MTH_BOOK_STATE.mode == "petabilities" then
if searchLabel then searchLabel:Hide() end
if minLabel then minLabel:Hide() end
if maxLabel then maxLabel:Hide() end
if search then search:Hide() end
if applyButton then applyButton:Hide() end
if scanButton then scanButton:Show() end
if minLevel then minLevel:Hide() end
if maxLevel then maxLevel:Hide() end
for i = 1, 6 do
local btn = getglobal("MTH_BOOK_Filter" .. i)
if btn then btn:Hide() end
end
if familyDropdown then familyDropdown:Hide() end
if abilityDropdown then abilityDropdown:Hide() end
if rankDropdown then rankDropdown:Hide() end
if petLearnSourceDropdown then
petLearnSourceDropdown:Show()
MTH_BOOK_UpdatePetLearnSourceDropdownText()
end
if itemSubtypeDropdown then itemSubtypeDropdown:Hide() end
if petOnlyMyLevel then
petOnlyMyLevel:ClearAllPoints()
petOnlyMyLevel:SetPoint("TOPLEFT", petOnlyMyLevel:GetParent(), "TOPLEFT", 228, -80)
petOnlyMyLevel:Show()
petOnlyMyLevel:SetChecked(MTH_BOOK_STATE.petOnlyMyLevel and 1 or nil)
end
if petInZoneOnly then petInZoneOnly:Hide() end
if npcInZoneOnly then npcInZoneOnly:Hide() end
if showAllOnMapButton then showAllOnMapButton:Hide() end
if npcFunctionDropdown then npcFunctionDropdown:Hide() end
if npcZoneDropdown then npcZoneDropdown:Hide() end
if hideNoAbilities then hideNoAbilities:Hide() end
if hideUnknown then hideUnknown:Hide() end
local requireVendor = getglobal("MTH_BOOK_RequireVendor")
local requireDrop = getglobal("MTH_BOOK_RequireDrop")
local requireObject = getglobal("MTH_BOOK_RequireObject")
if requireVendor then requireVendor:Hide() end
if requireDrop then requireDrop:Hide() end
if requireObject then requireObject:Hide() end
local resetButton = getglobal("MTH_BOOK_ResetButton")
if resetButton then
resetButton:ClearAllPoints()
resetButton:SetPoint("TOPLEFT", resetButton:GetParent(), "TOPLEFT", 546, -80)
end
elseif MTH_BOOK_STATE.mode == "npcs" then
if searchLabel then searchLabel:Show() end
if minLabel then minLabel:Hide() end
if maxLabel then maxLabel:Hide() end
if search then search:Show() end
if search then
search:ClearAllPoints()
search:SetPoint("TOPLEFT", search:GetParent(), "TOPLEFT", 54, -80)
search:SetWidth(180)
end
if applyButton then applyButton:Show() end
if applyButton then
applyButton:ClearAllPoints()
applyButton:SetPoint("TOPLEFT", applyButton:GetParent(), "TOPLEFT", 612, -80)
end
local resetButton = getglobal("MTH_BOOK_ResetButton")
if resetButton then
resetButton:ClearAllPoints()
resetButton:SetPoint("TOPLEFT", resetButton:GetParent(), "TOPLEFT", 678, -80)
end
if scanButton then scanButton:Hide() end
if minLevel then minLevel:Hide() end
if maxLevel then maxLevel:Hide() end
for i = 1, 6 do
local btn = getglobal("MTH_BOOK_Filter" .. i)
if btn then btn:Hide() end
end
if familyDropdown then familyDropdown:Hide() end
if abilityDropdown then abilityDropdown:Hide() end
if rankDropdown then rankDropdown:Hide() end
if petLearnSourceDropdown then petLearnSourceDropdown:Hide() end
if itemSubtypeDropdown then itemSubtypeDropdown:Hide() end
if npcFunctionDropdown then npcFunctionDropdown:Show() end
if npcZoneDropdown then npcZoneDropdown:Hide() end
MTH_BOOK_BuildNPCFunctionOptions()
MTH_BOOK_BuildNPCZoneOptions()
MTH_BOOK_UpdateNPCDropdownTexts()
if hideNoAbilities then hideNoAbilities:Hide() end
if hideUnknown then hideUnknown:Show() end
if petOnlyMyLevel then petOnlyMyLevel:Hide() end
if petInZoneOnly then petInZoneOnly:Hide() end
if npcInZoneOnly then
npcInZoneOnly:ClearAllPoints()
npcInZoneOnly:SetPoint("TOPLEFT", npcInZoneOnly:GetParent(), "TOPLEFT", 438, -82)
npcInZoneOnly:Show()
npcInZoneOnly:SetChecked(MTH_BOOK_STATE.npcInZoneOnly and 1 or nil)
end
if showAllOnMapButton then showAllOnMapButton:Hide() end
local requireVendor = getglobal("MTH_BOOK_RequireVendor")
local requireDrop = getglobal("MTH_BOOK_RequireDrop")
local requireObject = getglobal("MTH_BOOK_RequireObject")
if requireVendor then requireVendor:Show() end
if requireDrop then requireDrop:Show() end
if requireObject then requireObject:Show() end
elseif MTH_BOOK_STATE.mode == "items" then
if searchLabel then searchLabel:Show() end
if minLabel then minLabel:Hide() end
if maxLabel then maxLabel:Hide() end
if search then search:Show() end
if search then
search:ClearAllPoints()
search:SetPoint("TOPLEFT", search:GetParent(), "TOPLEFT", 54, -80)
search:SetWidth(180)
end
if applyButton then applyButton:Show() end
if applyButton then
applyButton:ClearAllPoints()
applyButton:SetPoint("TOPLEFT", applyButton:GetParent(), "TOPLEFT", 612, -80)
end
local resetButton = getglobal("MTH_BOOK_ResetButton")
if resetButton then
resetButton:ClearAllPoints()
resetButton:SetPoint("TOPLEFT", resetButton:GetParent(), "TOPLEFT", 678, -80)
end
if scanButton then scanButton:Hide() end
if minLevel then minLevel:Hide() end
if maxLevel then maxLevel:Hide() end
for i = 1, 6 do
local btn = getglobal("MTH_BOOK_Filter" .. i)
if btn then btn:Hide() end
end
if familyDropdown then familyDropdown:Hide() end
if abilityDropdown then abilityDropdown:Hide() end
if rankDropdown then rankDropdown:Hide() end
if petLearnSourceDropdown then petLearnSourceDropdown:Hide() end
if itemSubtypeDropdown then
itemSubtypeDropdown:ClearAllPoints()
itemSubtypeDropdown:SetPoint("TOPLEFT", itemSubtypeDropdown:GetParent(), "TOPLEFT", 238, -80)
itemSubtypeDropdown:Show()
MTH_BOOK_UpdateItemSubtypeDropdownText()
end
if npcFunctionDropdown then npcFunctionDropdown:Hide() end
if npcZoneDropdown then npcZoneDropdown:Hide() end
if hideNoAbilities then hideNoAbilities:Hide() end
if hideUnknown then hideUnknown:Hide() end
if petOnlyMyLevel then
petOnlyMyLevel:ClearAllPoints()
petOnlyMyLevel:SetPoint("TOPLEFT", petOnlyMyLevel:GetParent(), "TOPLEFT", 430, -82)
petOnlyMyLevel:Show()
petOnlyMyLevel:SetChecked(MTH_BOOK_STATE.itemOnlyMyLevel and 1 or nil)
end
if petInZoneOnly then petInZoneOnly:Hide() end
if npcInZoneOnly then npcInZoneOnly:Hide() end
if showAllOnMapButton then showAllOnMapButton:Hide() end
local requireVendor = getglobal("MTH_BOOK_RequireVendor")
local requireDrop = getglobal("MTH_BOOK_RequireDrop")
local requireObject = getglobal("MTH_BOOK_RequireObject")
if requireVendor then requireVendor:Hide() end
if requireDrop then requireDrop:Hide() end
if requireObject then requireObject:Hide() end
elseif MTH_BOOK_STATE.mode == "stable" then
if searchLabel then searchLabel:Hide() end
if minLabel then minLabel:Hide() end
if maxLabel then maxLabel:Hide() end
if search then search:Hide() end
if applyButton then applyButton:Hide() end
local resetButton = getglobal("MTH_BOOK_ResetButton")
if resetButton then resetButton:Hide() end
if scanButton then scanButton:Hide() end
if minLevel then minLevel:Hide() end
if maxLevel then maxLevel:Hide() end
for i = 1, 6 do
local btn = getglobal("MTH_BOOK_Filter" .. i)
if btn then btn:Hide() end
end
if familyDropdown then familyDropdown:Hide() end
if abilityDropdown then abilityDropdown:Hide() end
if rankDropdown then rankDropdown:Hide() end
if petLearnSourceDropdown then petLearnSourceDropdown:Hide() end
if itemSubtypeDropdown then itemSubtypeDropdown:Hide() end
if npcFunctionDropdown then npcFunctionDropdown:Hide() end
if npcZoneDropdown then npcZoneDropdown:Hide() end
if hideNoAbilities then hideNoAbilities:Hide() end
if hideUnknown then hideUnknown:Hide() end
if petOnlyMyLevel then petOnlyMyLevel:Hide() end
if petInZoneOnly then petInZoneOnly:Hide() end
if npcInZoneOnly then npcInZoneOnly:Hide() end
if showAllOnMapButton then showAllOnMapButton:Hide() end
local requireVendor = getglobal("MTH_BOOK_RequireVendor")
local requireDrop = getglobal("MTH_BOOK_RequireDrop")
local requireObject = getglobal("MTH_BOOK_RequireObject")
if requireVendor then requireVendor:Hide() end
if requireDrop then requireDrop:Hide() end
if requireObject then requireObject:Hide() end
elseif MTH_BOOK_STATE.mode == "families" then
if searchLabel then searchLabel:Hide() end
if minLabel then minLabel:Hide() end
if maxLabel then maxLabel:Hide() end
if search then search:Hide() end
if applyButton then applyButton:Hide() end
local resetButton = getglobal("MTH_BOOK_ResetButton")
if resetButton then resetButton:Hide() end
if scanButton then scanButton:Hide() end
if minLevel then minLevel:Hide() end
if maxLevel then maxLevel:Hide() end
for i = 1, 6 do
local btn = getglobal("MTH_BOOK_Filter" .. i)
if btn then btn:Hide() end
end
if familyDropdown then familyDropdown:Hide() end
if abilityDropdown then abilityDropdown:Hide() end
if rankDropdown then rankDropdown:Hide() end
if petLearnSourceDropdown then petLearnSourceDropdown:Hide() end
if itemSubtypeDropdown then itemSubtypeDropdown:Hide() end
if npcFunctionDropdown then npcFunctionDropdown:Hide() end
if npcZoneDropdown then npcZoneDropdown:Hide() end
if hideNoAbilities then hideNoAbilities:Hide() end
if hideUnknown then hideUnknown:Hide() end
if petOnlyMyLevel then petOnlyMyLevel:Hide() end
if petInZoneOnly then petInZoneOnly:Hide() end
if npcInZoneOnly then npcInZoneOnly:Hide() end
if showAllOnMapButton then showAllOnMapButton:Hide() end
local requireVendor = getglobal("MTH_BOOK_RequireVendor")
local requireDrop = getglobal("MTH_BOOK_RequireDrop")
local requireObject = getglobal("MTH_BOOK_RequireObject")
if requireVendor then requireVendor:Hide() end
if requireDrop then requireDrop:Hide() end
if requireObject then requireObject:Hide() end
elseif MTH_BOOK_STATE.mode == "pethistory" then
if searchLabel then searchLabel:Hide() end
if minLabel then minLabel:Hide() end
if maxLabel then maxLabel:Hide() end
if search then search:Hide() end
if applyButton then applyButton:Hide() end
local resetButton = getglobal("MTH_BOOK_ResetButton")
if resetButton then resetButton:Hide() end
if scanButton then scanButton:Hide() end
if minLevel then minLevel:Hide() end
if maxLevel then maxLevel:Hide() end
for i = 1, 6 do
local btn = getglobal("MTH_BOOK_Filter" .. i)
if btn then btn:Hide() end
end
if familyDropdown then familyDropdown:Hide() end
if abilityDropdown then abilityDropdown:Hide() end
if rankDropdown then rankDropdown:Hide() end
if petLearnSourceDropdown then petLearnSourceDropdown:Hide() end
if itemSubtypeDropdown then itemSubtypeDropdown:Hide() end
if npcFunctionDropdown then npcFunctionDropdown:Hide() end
if npcZoneDropdown then npcZoneDropdown:Hide() end
if hideNoAbilities then hideNoAbilities:Hide() end
if hideUnknown then hideUnknown:Hide() end
if petOnlyMyLevel then petOnlyMyLevel:Hide() end
if petInZoneOnly then petInZoneOnly:Hide() end
if npcInZoneOnly then npcInZoneOnly:Hide() end
if showAllOnMapButton then showAllOnMapButton:Hide() end
local requireVendor = getglobal("MTH_BOOK_RequireVendor")
local requireDrop = getglobal("MTH_BOOK_RequireDrop")
local requireObject = getglobal("MTH_BOOK_RequireObject")
if requireVendor then requireVendor:Hide() end
if requireDrop then requireDrop:Hide() end
if requireObject then requireObject:Hide() end
else
if itemSubtypeDropdown then itemSubtypeDropdown:Hide() end
end
if MTH_BOOK_STATE.mode ~= "petabilities" and MTH_BOOK_STATE.mode ~= "items" and petOnlyMyLevel then
petOnlyMyLevel:Hide()
end
if MTH_BOOK_STATE.mode ~= "pets" and petInZoneOnly then
petInZoneOnly:Hide()
end
if MTH_BOOK_STATE.mode ~= "npcs" and npcInZoneOnly then
npcInZoneOnly:Hide()
end
local resetButton = getglobal("MTH_BOOK_ResetButton")
if resetButton and MTH_BOOK_STATE.mode ~= "stable" and MTH_BOOK_STATE.mode ~= "families" and MTH_BOOK_STATE.mode ~= "pethistory" then
resetButton:Show()
end
MTH_BOOK_UpdateShowAllOnMapButton()
MTH_BOOK_ApplyContentLayoutForMode()
end
local function MTH_BOOK_InitFamilyDropdown()
local familyDropdown = getglobal("MTH_BOOK_FamilyDropdown")
if not familyDropdown then return end
MTH_BOOK_BuildPetFamilyOptions()
UIDropDownMenu_Initialize(familyDropdown, function()
for i = 1, table.getn(MTH_BOOK_PetFamilyOptions) do
local option = MTH_BOOK_PetFamilyOptions[i]
local value = option.value
local label = option.label
local index = i
local info = MTH_BOOK_DropdownCreateInfo()
info.text = label
info.func = function()
MTH_BOOK_STATE.quick = value
MTH_BOOK_STATE.page = 1
MTH_BOOK_STATE.selectedEntry = nil
MTH_BOOK_DropdownSetText(familyDropdown, label)
MTH_BOOK_RefreshFilter()
end
info.checked = (MTH_BOOK_STATE.quick == value)
UIDropDownMenu_AddButton(info)
end
end)
UIDropDownMenu_SetWidth(150, familyDropdown)
UIDropDownMenu_JustifyText("LEFT", familyDropdown)
MTH_BOOK_UpdateFamilyDropdownText()
end
local function MTH_BOOK_InitAbilityDropdown()
local abilityDropdown = getglobal("MTH_BOOK_AbilityDropdown")
if not abilityDropdown then return end
MTH_BOOK_BuildPetAbilityOptions()
UIDropDownMenu_Initialize(abilityDropdown, function()
for i = 1, table.getn(MTH_BOOK_PetAbilityOptions) do
local option = MTH_BOOK_PetAbilityOptions[i]
local value = option.value
local label = option.label
local index = i
local info = MTH_BOOK_DropdownCreateInfo()
info.text = label
info.func = function()
MTH_BOOK_STATE.petAbility = value
MTH_BOOK_STATE.petRank = "all"
MTH_BOOK_BuildPetRankOptions()
MTH_BOOK_STATE.page = 1
MTH_BOOK_STATE.selectedEntry = nil
MTH_BOOK_DropdownSetText(abilityDropdown, label)
MTH_BOOK_UpdateQuickFilterControls()
MTH_BOOK_RefreshFilter()
end
info.checked = (MTH_BOOK_STATE.petAbility == value)
UIDropDownMenu_AddButton(info)
end
end)
UIDropDownMenu_SetWidth(150, abilityDropdown)
UIDropDownMenu_JustifyText("LEFT", abilityDropdown)
MTH_BOOK_UpdateAbilityDropdownText()
end
local function MTH_BOOK_InitRankDropdown()
local rankDropdown = getglobal("MTH_BOOK_RankDropdown")
if not rankDropdown then return end
MTH_BOOK_BuildPetRankOptions()
UIDropDownMenu_Initialize(rankDropdown, function()
for i = 1, table.getn(MTH_BOOK_PetRankOptions) do
local option = MTH_BOOK_PetRankOptions[i]
local value = option.value
local label = option.label
local index = i
local info = MTH_BOOK_DropdownCreateInfo()
info.text = label
info.func = function()
MTH_BOOK_STATE.petRank = value
MTH_BOOK_STATE.page = 1
MTH_BOOK_STATE.selectedEntry = nil
MTH_BOOK_DropdownSetText(rankDropdown, label)
MTH_BOOK_RefreshFilter()
end
info.checked = (tostring(MTH_BOOK_STATE.petRank) == tostring(value))
UIDropDownMenu_AddButton(info)
end
end)
UIDropDownMenu_SetWidth(120, rankDropdown)
UIDropDownMenu_JustifyText("LEFT", rankDropdown)
MTH_BOOK_UpdateRankDropdownText()
end
local function MTH_BOOK_InitPetLearnSourceDropdown()
local sourceDropdown = getglobal("MTH_BOOK_PetLearnSourceDropdown")
if not sourceDropdown then return end
UIDropDownMenu_Initialize(sourceDropdown, function()
for i = 1, table.getn(MTH_BOOK_PetLearnSourceOptions) do
local option = MTH_BOOK_PetLearnSourceOptions[i]
local info = MTH_BOOK_DropdownCreateInfo()
info.text = option.label
info.func = function()
MTH_BOOK_STATE.petLearnSource = option.value
MTH_BOOK_STATE.page = 1
MTH_BOOK_STATE.selectedEntry = nil
MTH_BOOK_STATE.selectedPetRankEntry = nil
MTH_BOOK_STATE.petRankRows = {}
MTH_BOOK_DropdownSetText(sourceDropdown, option.label)
MTH_BOOK_RefreshFilter()
end
info.checked = (MTH_BOOK_STATE.petLearnSource == option.value)
UIDropDownMenu_AddButton(info)
end
end)
UIDropDownMenu_SetWidth(140, sourceDropdown)
UIDropDownMenu_JustifyText("LEFT", sourceDropdown)
MTH_BOOK_UpdatePetLearnSourceDropdownText()
end
local function MTH_BOOK_InitItemSubtypeDropdown()
local itemDropdown = getglobal("MTH_BOOK_ItemSubtypeDropdown")
if not itemDropdown then return end
UIDropDownMenu_Initialize(itemDropdown, function()
for i = 1, table.getn(MTH_BOOK_ItemSubtypeOptions) do
local option = MTH_BOOK_ItemSubtypeOptions[i]
local info = MTH_BOOK_DropdownCreateInfo()
info.text = option.label
info.func = function()
MTH_BOOK_STATE.itemSubtype = option.value
MTH_BOOK_STATE.page = 1
MTH_BOOK_STATE.selectedEntry = nil
MTH_BOOK_DropdownSetText(itemDropdown, option.label)
MTH_BOOK_RefreshFilter()
end
info.checked = (MTH_BOOK_STATE.itemSubtype == option.value)
UIDropDownMenu_AddButton(info)
end
end)
UIDropDownMenu_SetWidth(75, itemDropdown)
UIDropDownMenu_JustifyText("LEFT", itemDropdown)
MTH_BOOK_UpdateItemSubtypeDropdownText()
end
local function MTH_BOOK_InitNPCFunctionDropdown()
local functionDropdown = getglobal("MTH_BOOK_NPCFunctionDropdown")
if not functionDropdown then return end
MTH_BOOK_BuildNPCFunctionOptions()
UIDropDownMenu_Initialize(functionDropdown, function()
for i = 1, table.getn(MTH_BOOK_NPCFunctionOptions) do
local option = MTH_BOOK_NPCFunctionOptions[i]
local info = MTH_BOOK_DropdownCreateInfo()
info.text = option.label
info.func = function()
MTH_BOOK_STATE.npcFunction = option.value
MTH_BOOK_STATE.page = 1
MTH_BOOK_STATE.selectedEntry = nil
MTH_BOOK_DropdownSetText(functionDropdown, option.label)
MTH_BOOK_RefreshFilter()
end
info.checked = (MTH_BOOK_STATE.npcFunction == option.value)
UIDropDownMenu_AddButton(info)
end
end)
UIDropDownMenu_SetWidth(150, functionDropdown)
UIDropDownMenu_JustifyText("LEFT", functionDropdown)
MTH_BOOK_UpdateNPCDropdownTexts()
end
local function MTH_BOOK_AddDetailSection(lines, title)
table.insert(lines, "")
table.insert(lines, "|cFFFFD100" .. tostring(title) .. "|r")
end
local function MTH_BOOK_AddDetailKV(lines, label, value)
table.insert(lines, tostring(label) .. ": " .. tostring(value))
end
local function MTH_BOOK_AddStableStyleKV(lines, label, value)
table.insert(lines, "|cff9a9a9a" .. tostring(label or "") .. ":|r |cffffffff" .. tostring(value or "-") .. "|r")
end
local function MTH_BOOK_FormatDateTimeValue(value)
local ts = tonumber(value)
if not ts or ts <= 0 then
return "-"
end
if type(date) == "function" then
return date("%Y-%m-%d %H:%M:%S", ts)
end
return tostring(ts)
end
local function MTH_BOOK_GetPetHistoryLostCause(row)
local reason = MTH_BOOK_SafeLower(type(row) == "table" and row.abandonReason or "")
if reason == "pet-runaway" then
return "Ran Away"
end
if string.find(reason, "runaway", 1, true) or string.find(reason, "run away", 1, true) then
return "Ran Away"
end
return "Abandonned"
end
local function MTH_BOOK_FormatRespawnWindow(beast)
if not beast then return nil end
local minSec = tonumber(beast.respawnMinSeconds)
local maxSec = tonumber(beast.respawnMaxSeconds)
local samples = tonumber(beast.respawnSamples)
if not minSec and not maxSec then return nil end
if not minSec then minSec = maxSec end
if not maxSec then maxSec = minSec end
local function fmt(sec)
sec = math.floor((tonumber(sec) or 0) + 0.5)
if sec < 0 then sec = 0 end
if SecondsToTime then
return SecondsToTime(sec)
end
if sec >= 3600 then
return string.format("%.1fh", sec / 3600)
elseif sec >= 60 then
return string.format("%.1fm", sec / 60)
end
return tostring(sec) .. "s"
end
local value
if minSec == maxSec then
value = fmt(minSec)
else
value = fmt(minSec) .. " - " .. fmt(maxSec)
end
if samples and samples > 0 then
value = value .. " (" .. tostring(samples) .. " samples)"
end
return value
end
function MTH_BOOK_ResolveIconPath(icon)
if not icon or icon == "" then return nil end
local iconText = tostring(icon)
if string.find(iconText, "\\", 1, true) then
return iconText
end
return "Interface\\Icons\\" .. iconText
end
local MTH_BOOK_SpellTooltip = nil
function MTH_BOOK_GetSpellTooltip()
if MTH_BOOK_SpellTooltip then return MTH_BOOK_SpellTooltip end
if not CreateFrame then return GameTooltip end
MTH_BOOK_SpellTooltip = CreateFrame("GameTooltip", "MTH_BOOK_SpellTooltip", UIParent, "GameTooltipTemplate")
MTH_BOOK_SpellTooltip.mthIcon = MTH_BOOK_SpellTooltip:CreateTexture(nil, "ARTWORK")
MTH_BOOK_SpellTooltip.mthIcon:SetPoint("TOPRIGHT", MTH_BOOK_SpellTooltip, "TOPRIGHT", -8, -8)
MTH_BOOK_SpellTooltip.mthIcon:SetWidth(36)
MTH_BOOK_SpellTooltip.mthIcon:SetHeight(36)
MTH_BOOK_SpellTooltip.mthIcon:Hide()
return MTH_BOOK_SpellTooltip
end
function MTH_BOOK_SetSpellTooltipIcon(tooltip, icon)
if not tooltip then return end
if not tooltip.mthIcon then return end
local iconPath = MTH_BOOK_ResolveIconPath(icon)
if iconPath then
tooltip.mthIcon:SetTexture(iconPath)
tooltip.mthIcon:Show()
else
tooltip.mthIcon:Hide()
end
end
function MTH_BOOK_HideSpellTooltip()
local tooltip = MTH_BOOK_SpellTooltip
if tooltip and tooltip.mthIcon then
tooltip.mthIcon:Hide()
end
if tooltip and tooltip.Hide then
tooltip:Hide()
end
end
function MTH_BOOK_ShowBaselineTooltip(anchor, entry)
if not anchor or not entry then return end
local tooltip = MTH_BOOK_GetSpellTooltip()
if not tooltip then return end
tooltip:SetOwner(anchor, "ANCHOR_RIGHT")
tooltip:ClearLines()
MTH_BOOK_SetSpellTooltipIcon(tooltip, entry.icon)
tooltip:AddLine(tostring(entry.ability or "Unknown"), 1.00, 0.82, 0.00)
tooltip:AddLine(" ")
tooltip:AddLine("Spell Baseline", 1.00, 0.82, 0.00)
tooltip:AddDoubleLine("Known Ranks", tostring(entry.knownRankCount or 0) .. "/" .. tostring(entry.rankCount or 0), 0.85, 0.85, 0.85, 1, 1, 1)
tooltip:AddDoubleLine("Families", tostring(entry.familyCount or 0), 0.85, 0.85, 0.85, 1, 1, 1)
tooltip:AddDoubleLine("Spell Rows", tostring(entry.spellRows or 0), 0.85, 0.85, 0.85, 1, 1, 1)
if entry.minRank and entry.maxRank then
if entry.minRank == entry.maxRank then
tooltip:AddDoubleLine("Rank Span", tostring(entry.minRank), 0.85, 0.85, 0.85, 1, 1, 1)
else
tooltip:AddDoubleLine("Rank Span", tostring(entry.minRank) .. "-" .. tostring(entry.maxRank), 0.85, 0.85, 0.85, 1, 1, 1)
end
end
if entry.families and table.getn(entry.families) > 0 then
tooltip:AddLine(" ")
tooltip:AddLine("Families", 1.00, 0.82, 0.00)
for i = 1, table.getn(entry.families) do
tooltip:AddLine("- " .. tostring(entry.families[i]), 0.90, 0.90, 0.90)
if i >= 10 then
local remaining = table.getn(entry.families) - i
if remaining > 0 then
tooltip:AddLine("... +" .. tostring(remaining) .. " more", 0.70, 0.70, 0.70)
end
break
end
end
end
tooltip:Show()
end
function MTH_BOOK_ShowRankTooltip(anchor, rankEntry)
if not anchor or not rankEntry then return end
local tooltip = MTH_BOOK_GetSpellTooltip()
if not tooltip then return end
tooltip:SetOwner(anchor, "ANCHOR_RIGHT")
tooltip:ClearLines()
MTH_BOOK_SetSpellTooltipIcon(tooltip, rankEntry.icon)
local header = tostring(rankEntry.ability or "Spell")
header = header .. " (" .. MTH_BOOK_GetRankLabel(rankEntry.rankNumber, true) .. ")"
tooltip:AddLine(header, 1.00, 0.82, 0.00)
tooltip:AddLine(" ")
tooltip:AddLine("Current Rank", 1.00, 0.82, 0.00)
tooltip:AddDoubleLine("Rank", MTH_BOOK_GetRankLabel(rankEntry.rankNumber, true), 0.85, 0.85, 0.85, 1, 1, 1)
tooltip:AddDoubleLine("Known", rankEntry.isKnown and "v" or "-", 0.85, 0.85, 0.85, rankEntry.isKnown and 0.18 or 0.90, rankEntry.isKnown and 0.90 or 0.90, rankEntry.isKnown and 0.18 or 0.90)
tooltip:AddDoubleLine("Train Level", rankEntry.trainLevel and tostring(rankEntry.trainLevel) or "-", 0.85, 0.85, 0.85, 1, 1, 1)
tooltip:AddDoubleLine("Spell ID", rankEntry.id and tostring(rankEntry.id) or "-", 0.85, 0.85, 0.85, 1, 1, 1)
if rankEntry.cost and rankEntry.cost ~= "" then
tooltip:AddDoubleLine("Cost", tostring(rankEntry.cost), 0.85, 0.85, 0.85, 1, 1, 1)
end
if rankEntry.castTime and rankEntry.castTime ~= "" then
tooltip:AddDoubleLine("Cast", tostring(rankEntry.castTime), 0.85, 0.85, 0.85, 1, 1, 1)
end
if rankEntry.range and rankEntry.range ~= "" then
tooltip:AddDoubleLine("Range", tostring(rankEntry.range), 0.85, 0.85, 0.85, 1, 1, 1)
end
if rankEntry.school and rankEntry.school ~= "" then
tooltip:AddDoubleLine("School", tostring(rankEntry.school), 0.85, 0.85, 0.85, 1, 1, 1)
end
if rankEntry.description and rankEntry.description ~= "" then
tooltip:AddLine(" ")
tooltip:AddLine("Description", 1.00, 0.82, 0.00)
tooltip:AddLine(tostring(rankEntry.description), 0.90, 0.90, 0.90, true)
end
if rankEntry.effects then
local effectsType = type(rankEntry.effects)
if effectsType == "table" and table.getn(rankEntry.effects) > 0 then
tooltip:AddLine(" ")
tooltip:AddLine("Effects", 1.00, 0.82, 0.00)
for i = 1, table.getn(rankEntry.effects) do
tooltip:AddLine("- " .. tostring(rankEntry.effects[i]), 0.90, 0.90, 0.90, true)
end
elseif effectsType == "string" and rankEntry.effects ~= "" then
tooltip:AddLine(" ")
tooltip:AddLine("Effects", 1.00, 0.82, 0.00)
tooltip:AddLine(tostring(rankEntry.effects), 0.90, 0.90, 0.90, true)
end
end
tooltip:Show()
end
local function MTH_BOOK_WrapLine(text, maxChars)
local line = tostring(text or "")
if string.len(line) <= maxChars then return line end
local out = {}
local remaining = line
while string.len(remaining) > maxChars do
local chunk = string.sub(remaining, 1, maxChars)
local cut = nil
for i = maxChars, 1, -1 do
if string.sub(chunk, i, i) == " " then
cut = i
break
end
end
if not cut or cut < 8 then cut = maxChars end
table.insert(out, string.sub(remaining, 1, cut))
remaining = string.gsub(string.sub(remaining, cut + 1), "^%s+", "")
end
if remaining ~= "" then table.insert(out, remaining) end
return table.concat(out, "\n")
end
local function MTH_BOOK_WrapDetailText(text)
local src = tostring(text or "")
local lines = {}
local startPos = 1
while true do
local nl = string.find(src, "\n", startPos, true)
if not nl then
table.insert(lines, MTH_BOOK_WrapLine(string.sub(src, startPos), 28))
break
end
table.insert(lines, MTH_BOOK_WrapLine(string.sub(src, startPos, nl - 1), 28))
startPos = nl + 1
end
return table.concat(lines, "\n")
end
function MTH_BOOK_SetDetailText(detail, text)
if not detail then return end
local wrapped = tostring(text or "")
if MTH_BOOK_STATE.mode ~= "pethistory" then
wrapped = MTH_BOOK_WrapDetailText(wrapped)
end
detail._mthLocking = true
detail:SetText(wrapped)
detail._mthLockedText = wrapped
detail._mthLocking = false
end
function MTH_BOOK_ConfigureReadOnlyEditBox(detail)
if not detail then return end
if detail.SetFontObject then detail:SetFontObject(GameFontNormalSmall) end
if detail.SetJustifyH then detail:SetJustifyH("LEFT") end
if detail.SetJustifyV then detail:SetJustifyV("TOP") end
if detail.SetMultiLine then detail:SetMultiLine(true) end
if detail.SetAutoFocus then detail:SetAutoFocus(false) end
if detail.SetMaxLetters then detail:SetMaxLetters(0) end
if detail.SetTextInsets then detail:SetTextInsets(4, 4, 4, 4) end
if detail.EnableMouse then detail:EnableMouse(true) end
if detail.EnableKeyboard then detail:EnableKeyboard(true) end
if detail.SetScript then
detail:SetScript("OnChar", function()
if this._mthLockedText then
this._mthLocking = true
this:SetText(this._mthLockedText)
this._mthLocking = false
end
end)
detail:SetScript("OnKeyDown", function()
if this._mthLockedText then
this._mthLocking = true
this:SetText(this._mthLockedText)
this._mthLocking = false
end
end)
detail:SetScript("OnTextChanged", function()
if this._mthLocking then return end
local current = this:GetText() or ""
if this._mthLockedText and current ~= this._mthLockedText then
this._mthLocking = true
this:SetText(this._mthLockedText)
this._mthLocking = false
end
end)
detail:SetScript("OnEscapePressed", function() this:ClearFocus() end)
detail:SetScript("OnEnterPressed", function() this:ClearFocus() end)
end
detail._mthLockedText = detail:GetText() or ""
end
function MTH_BOOK_UpdateDetail()
local detail = getglobal("MTH_BOOK_DetailBackdropDetailText")
if not detail then return end
local petTop = MTH_BOOK_STATE.petUI and MTH_BOOK_STATE.petUI.detailTop
local petBottom = MTH_BOOK_STATE.petUI and MTH_BOOK_STATE.petUI.detailBottom
if not MTH_BOOK_STATE.selectedEntry then
if MTH_BOOK_STATE.mode == "petabilities" then
if petTop and petBottom then
MTH_BOOK_SetDetailText(petTop, "|cFFFFD100Baseline|r\n\nSelect a spell baseline from the left list.")
MTH_BOOK_SetDetailText(petBottom, "|cFFFFD100Rank|r\n\nSelect a rank from the right list.")
else
MTH_BOOK_SetDetailText(detail, "|cFFFFD100Pet Abilities|r\n\nSelect a spell baseline to inspect rank coverage and families.")
end
else
MTH_BOOK_SetDetailText(detail, "|cFFFFD100Inspector|r\n\nSelect an entry from the list to view identity, stats, sources and locations.")
end
MTH_BOOK_UpdateOpenMapButton()
return
end
if MTH_BOOK_STATE.mode == "npcs" then
local selected = MTH_BOOK_STATE.selectedEntry
if not selected or not selected.npcId then
MTH_BOOK_SetDetailText(detail, "|cFFFFD100Inspector|r\n\nSelect an NPC to view details and map locations.")
MTH_BOOK_UpdateOpenMapButton()
return
end
local npcId = selected.npcId
local npc = MTH_DS_Vendors and MTH_DS_Vendors[npcId]
if not npc then
MTH_BOOK_SetDetailText(detail, "|cFFFFD100Inspector|r\n\nSelect an NPC to view details and map locations.")
MTH_BOOK_UpdateOpenMapButton()
return
end
local functionSummary = MTH_BOOK_GetNPCFunctionSummary(npc)
local zoneName, subzoneName = MTH_BOOK_GetNPCZoneSummary(npc)
local lines = {}
table.insert(lines, "|cFFFFFF00" .. tostring(npc.name or "Unknown") .. "|r")
MTH_BOOK_AddDetailSection(lines, "Identity")
MTH_BOOK_AddDetailKV(lines, "ID", npcId)
MTH_BOOK_AddDetailKV(lines, "React", MTH_BOOK_GetNPCReactBucket(npc.fac))
MTH_BOOK_AddDetailKV(lines, "Function", functionSummary)
MTH_BOOK_AddDetailKV(lines, "Level", npc.lvl or "?")
MTH_BOOK_AddDetailSection(lines, "Location")
MTH_BOOK_AddDetailKV(lines, "Zone", zoneName)
MTH_BOOK_AddDetailKV(lines, "Subzone", subzoneName)
if npc.coords and table.getn(npc.coords) > 0 then
for i = 1, table.getn(npc.coords) do
local c = npc.coords[i]
if c then
local x = tonumber(c[1] or 0) or 0
local y = tonumber(c[2] or 0) or 0
table.insert(lines, string.format(" - %s (%.1f, %.1f)", MTH_BOOK_GetZoneName(c[3]), x, y))
end
if i >= 8 then break end
end
else
table.insert(lines, " - No coordinates")
end
MTH_BOOK_SetDetailText(detail, table.concat(lines, "\n"))
MTH_BOOK_UpdateOpenMapButton()
return
end
if MTH_BOOK_STATE.mode == "pets" then
local selected = MTH_BOOK_STATE.selectedEntry
if not selected or not selected.beastId then
MTH_BOOK_SetDetailText(detail, "|cFFFFD100Inspector|r\n\nSelect an entry from the list to view identity, stats, sources and locations.")
MTH_BOOK_UpdateOpenMapButton()
return
end
local beastId = selected.beastId
local beast = MTH_DS_Beasts and MTH_DS_Beasts[beastId]
if not beast then
MTH_BOOK_SetDetailText(detail, "|cFFFFD100Inspector|r\n\nSelect an entry from the list to view identity, stats, sources and locations.")
MTH_BOOK_UpdateOpenMapButton()
return
end
local lines = {}
table.insert(lines, "|cFFFFFF00" .. (beast.name or "Unknown") .. "|r")
MTH_BOOK_AddDetailSection(lines, "Identity")
MTH_BOOK_AddDetailKV(lines, "ID", beastId)
MTH_BOOK_AddDetailKV(lines, "Family", beast.family or "?")
MTH_BOOK_AddDetailSection(lines, "Stats")
MTH_BOOK_AddDetailKV(lines, "Level", beast.lvl or "?")
MTH_BOOK_AddDetailKV(lines, "Attack Speed", beast.attackSpeed or "?")
local respawnWindow = MTH_BOOK_FormatRespawnWindow(beast)
if respawnWindow then
MTH_BOOK_AddDetailKV(lines, "Respawn", respawnWindow)
end
MTH_BOOK_AddDetailKV(lines, "Rare", beast.rare and "Yes" or "No")
MTH_BOOK_AddDetailKV(lines, "Abilities", beast.abilities or "None")
local fam = MTH_DS_Families and beast.family and MTH_DS_Families[beast.family]
if fam and fam.abilities and table.getn(fam.abilities) > 0 then
MTH_BOOK_AddDetailSection(lines, "Family Pool")
table.insert(lines, " " .. table.concat(fam.abilities, ", "))
end
if beast.coords and table.getn(beast.coords) > 0 then
MTH_BOOK_AddDetailSection(lines, "Locations")
for i = 1, table.getn(beast.coords) do
local c = beast.coords[i]
if c then
local x = tonumber(c[1] or 0) or 0
local y = tonumber(c[2] or 0) or 0
local zoneId = c[3]
table.insert(lines, string.format(" - %s (%.1f, %.1f)", MTH_BOOK_GetZoneName(zoneId), x, y))
end
if i >= 8 then break end
end
end
MTH_BOOK_SetDetailText(detail, table.concat(lines, "\n"))
MTH_BOOK_UpdateOpenMapButton()
return
end
if MTH_BOOK_STATE.mode == "abilities" then
local entry = MTH_BOOK_STATE.selectedEntry
if not entry or not entry.beastId then
MTH_BOOK_SetDetailText(detail, "|cFFFFD100Inspector|r\n\nSelect an entry from the list to view identity, stats, sources and locations.")
MTH_BOOK_UpdateOpenMapButton()
return
end
local beast = MTH_DS_Beasts and MTH_DS_Beasts[entry.beastId]
if not beast then
MTH_BOOK_SetDetailText(detail, "|cFFFFD100Inspector|r\n\nSelect an entry from the list to view identity, stats, sources and locations.")
MTH_BOOK_UpdateOpenMapButton()
return
end
local lines = {}
table.insert(lines, "|cFFFFFF00" .. tostring(entry.abilityToken) .. "|r")
MTH_BOOK_AddDetailSection(lines, "Identity")
MTH_BOOK_AddDetailKV(lines, "Beast", tostring(beast.name or "Unknown") .. " (ID " .. tostring(entry.beastId) .. ")")
MTH_BOOK_AddDetailKV(lines, "Family", beast.family or "?")
MTH_BOOK_AddDetailSection(lines, "Stats")
MTH_BOOK_AddDetailKV(lines, "Level", beast.lvl or "?")
MTH_BOOK_AddDetailKV(lines, "Attack Speed", beast.attackSpeed or "?")
local respawnWindow = MTH_BOOK_FormatRespawnWindow(beast)
if respawnWindow then
MTH_BOOK_AddDetailKV(lines, "Respawn", respawnWindow)
end
MTH_BOOK_AddDetailKV(lines, "Rare", beast.rare and "Yes" or "No")
if beast.coords and table.getn(beast.coords) > 0 then
MTH_BOOK_AddDetailSection(lines, "Locations")
for i = 1, table.getn(beast.coords) do
local c = beast.coords[i]
if c then
local x = tonumber(c[1] or 0) or 0
local y = tonumber(c[2] or 0) or 0
local zoneId = c[3]
table.insert(lines, string.format(" - %s (%.1f, %.1f)", MTH_BOOK_GetZoneName(zoneId), x, y))
end
if i >= 8 then break end
end
end
MTH_BOOK_SetDetailText(detail, table.concat(lines, "\n"))
MTH_BOOK_UpdateOpenMapButton()
return
end
if MTH_BOOK_STATE.mode == "petabilities" then
local entry = MTH_BOOK_STATE.selectedEntry
if not entry then
if petTop and petBottom then
MTH_BOOK_SetDetailText(petTop, "Select a spell baseline from the left list.")
MTH_BOOK_SetDetailText(petBottom, "Select a rank from the right list.")
if MTH_BOOK_STATE.petUI and MTH_BOOK_STATE.petUI.detailTopIcon then
MTH_BOOK_STATE.petUI.detailTopIcon:Hide()
end
else
MTH_BOOK_SetDetailText(detail, "|cFFFFD100Pet Abilities|r\n\nSelect a spell baseline to inspect rank coverage and families.")
end
MTH_BOOK_UpdateOpenMapButton()
return
end
local topLines = {}
table.insert(topLines, tostring(entry.ability or "Unknown"))
table.insert(topLines, "")
table.insert(topLines, "Baseline")
MTH_BOOK_AddDetailKV(topLines, "Ranks", entry.rankText ~= "" and entry.rankText or "")
MTH_BOOK_AddDetailKV(topLines, "Families", entry.familyCount or 0)
MTH_BOOK_AddDetailKV(topLines, "Spell Rows", entry.spellRows or 0)
if entry.minRank and entry.maxRank then
if entry.minRank == entry.maxRank then
MTH_BOOK_AddDetailKV(topLines, "Rank Span", tostring(entry.minRank))
else
MTH_BOOK_AddDetailKV(topLines, "Rank Span", tostring(entry.minRank) .. "-" .. tostring(entry.maxRank))
end
end
table.insert(topLines, "")
table.insert(topLines, "Families")
if entry.families and table.getn(entry.families) > 0 then
for i = 1, table.getn(entry.families) do
table.insert(topLines, " - " .. tostring(entry.families[i]))
end
else
table.insert(topLines, " - None")
end
local rankEntry = MTH_BOOK_STATE.selectedPetRankEntry
local bottomLines = {}
if rankEntry then
table.insert(bottomLines, MTH_BOOK_GetRankLabel(rankEntry.rankNumber, true))
table.insert(bottomLines, "")
table.insert(bottomLines, "Rank Detail")
MTH_BOOK_AddDetailKV(bottomLines, "Train Level", rankEntry.trainLevel or "-")
MTH_BOOK_AddDetailKV(bottomLines, "Spell ID", rankEntry.id or "-")
if rankEntry.cost and rankEntry.cost ~= "" then MTH_BOOK_AddDetailKV(bottomLines, "Cost", rankEntry.cost) end
if rankEntry.castTime and rankEntry.castTime ~= "" then MTH_BOOK_AddDetailKV(bottomLines, "Cast", rankEntry.castTime) end
if rankEntry.range and rankEntry.range ~= "" then MTH_BOOK_AddDetailKV(bottomLines, "Range", rankEntry.range) end
if rankEntry.school and rankEntry.school ~= "" then MTH_BOOK_AddDetailKV(bottomLines, "School", rankEntry.school) end
table.insert(bottomLines, "")
table.insert(bottomLines, "Description")
table.insert(bottomLines, " " .. tostring(rankEntry.description or "-"))
else
table.insert(bottomLines, "Select a rank from the right list.")
end
if petTop and petBottom then
MTH_BOOK_SetDetailText(petTop, table.concat(topLines, "\n"))
MTH_BOOK_SetDetailText(petBottom, table.concat(bottomLines, "\n"))
if MTH_BOOK_STATE.petUI and MTH_BOOK_STATE.petUI.detailTopIcon then
if entry.icon and entry.icon ~= "" then
if string.find(entry.icon, "\\", 1, true) then
MTH_BOOK_STATE.petUI.detailTopIcon:SetTexture(entry.icon)
else
MTH_BOOK_STATE.petUI.detailTopIcon:SetTexture("Interface\\Icons\\" .. tostring(entry.icon))
end
MTH_BOOK_STATE.petUI.detailTopIcon:Show()
else
MTH_BOOK_STATE.petUI.detailTopIcon:Hide()
end
end
else
local fallback = table.concat(topLines, "\n") .. "\n\n" .. table.concat(bottomLines, "\n")
MTH_BOOK_SetDetailText(detail, fallback)
end
MTH_BOOK_UpdateOpenMapButton()
return
end
if MTH_BOOK_STATE.mode == "stable" then
local petId = MTH_BOOK_STATE.selectedEntry
local row = petId and MTH_BOOK_GetPetStoreRow(petId)
if not row then
MTH_BOOK_SetDetailText(detail, "|cFFFFD100Stable|r\n\nSelect a stable entry to inspect stored pet identity and latest stable scan fields.")
MTH_BOOK_UpdateOpenMapButton()
return
end
local lines = {}
table.insert(lines, "|cFFFFFF00" .. tostring(row.name or "Unknown") .. "|r")
MTH_BOOK_AddDetailSection(lines, "Identity")
MTH_BOOK_AddDetailKV(lines, "Pet ID", tostring(petId or "-"))
MTH_BOOK_AddDetailKV(lines, "Family", row.family or "-")
MTH_BOOK_AddDetailKV(lines, "Level", row.level or "-")
MTH_BOOK_AddDetailKV(lines, "Beast ID", row.beastId or "-")
MTH_BOOK_AddDetailSection(lines, "Stable")
MTH_BOOK_AddDetailKV(lines, "Slot", MTH_BOOK_GetStableDisplaySlot(petId, row) or "-")
MTH_BOOK_AddDetailKV(lines, "Loyalty", MTH_BOOK_GetLoyaltyNameByLevel(tonumber(row.loyaltyLevel) or (row.stableInfo and tonumber(row.stableInfo.loyaltyLevel)) or nil))
MTH_BOOK_AddDetailKV(lines, "Happiness", (row.stableInfo and row.stableInfo.happiness) or row.happiness or "-")
MTH_BOOK_AddDetailKV(lines, "State", row.state or "active")
MTH_BOOK_AddDetailKV(lines, "Last Seen", row.lastSeen or row.lastUpdated or "-")
if type(row.tameContext) == "table" then
MTH_BOOK_AddDetailSection(lines, "Tamed")
MTH_BOOK_AddDetailKV(lines, "At", row.tameContext.timestamp or "-")
MTH_BOOK_AddDetailKV(lines, "Zone", row.tameContext.zone or "-")
MTH_BOOK_AddDetailKV(lines, "Subzone", row.tameContext.subZone or "-")
MTH_BOOK_AddDetailKV(lines, "Coord", row.tameContext.coordinate or "-")
MTH_BOOK_AddDetailKV(lines, "Hunter Lvl", row.tameContext.hunterLevel or "-")
end
MTH_BOOK_SetDetailText(detail, table.concat(lines, "\n"))
MTH_BOOK_UpdateOpenMapButton()
return
end
if MTH_BOOK_STATE.mode == "pethistory" then
local selected = MTH_BOOK_STATE.selectedEntry
local petId = selected
if type(selected) == "table" then
petId = selected.petId or selected.id
end
local row = petId and MTH_BOOK_GetPetStoreRow(petId)
if not row then
MTH_BOOK_SetDetailText(detail, "|cFFFFD100Pet History|r\n\nSelect a history entry to inspect abandon context and archived pet data.")
MTH_BOOK_UpdateOpenMapButton()
return
end
local stableInfo = (type(row.stableInfo) == "table") and row.stableInfo or nil
local stabledAt = tonumber(row.stabledAt) or tonumber(row.stableFirstSeenAt) or (stableInfo and tonumber(stableInfo.stabledAt) or nil)
local stabledSince = "-"
local stableElapsedFormatter = _G and _G["MTH_BOOK_FormatElapsedStableInfo"] or nil
if type(stableElapsedFormatter) == "function" then
stabledSince = stableElapsedFormatter(stabledAt)
end
local stableZone = stableInfo and tostring(stableInfo.stableZone or "") or ""
local stableSubZone = stableInfo and tostring(stableInfo.stableSubZone or "") or ""
local stableMasterName = stableInfo and tostring(stableInfo.stableMasterName or "") or ""
local stableLocation = "-"
if stableSubZone ~= "" and stableZone ~= "" then
stableLocation = stableSubZone .. " (" .. stableZone .. ")"
elseif stableSubZone ~= "" then
stableLocation = stableSubZone
elseif stableZone ~= "" then
stableLocation = stableZone
end
if stableMasterName == "" then
stableMasterName = "-"
end
local legacyTameContext = type(row.tameContext) == "table" and row.tameContext or nil
local hasRecordedTame = row.tameRecorded == true
if not hasRecordedTame and legacyTameContext then
if legacyTameContext.name or legacyTameContext.zone or legacyTameContext.timestamp then
hasRecordedTame = true
end
end
local tamedAt = hasRecordedTame and (tonumber(row.tamedAt) or (legacyTameContext and tonumber(legacyTameContext.timestamp) or nil)) or nil
local tameZone = hasRecordedTame and tostring(row.tameZone or (legacyTameContext and legacyTameContext.zone) or "-") or "-"
local tameX = hasRecordedTame and (tonumber(row.tameX) or (legacyTameContext and tonumber(legacyTameContext.x) or nil)) or nil
local tameY = hasRecordedTame and (tonumber(row.tameY) or (legacyTameContext and tonumber(legacyTameContext.y) or nil)) or nil
local tameCoords = "-"
if tameX and tameY then
tameCoords = string.format("%.1f, %.1f", tameX, tameY)
end
local tameBeastId = hasRecordedTame and (tonumber(row.tameBeastId) or (legacyTameContext and tonumber(legacyTameContext.beastId) or nil)) or nil
local tameBeast = tameBeastId and MTH_DS_Beasts and MTH_DS_Beasts[tameBeastId] or nil
local tameBeastName = tostring((tameBeast and tameBeast.name) or (legacyTameContext and legacyTameContext.name) or "-")
local lines = {}
table.insert(lines, "|cFFFFFF00" .. tostring(row.name or "Unknown") .. "|r")
MTH_BOOK_AddDetailSection(lines, "Identity")
MTH_BOOK_AddStableStyleKV(lines, "Pet ID", tostring(petId or "-"))
MTH_BOOK_AddStableStyleKV(lines, "Name", row.name or "-")
MTH_BOOK_AddStableStyleKV(lines, "Family", row.family or "-")
MTH_BOOK_AddStableStyleKV(lines, "Level", row.level or "-")
MTH_BOOK_AddStableStyleKV(lines, "Loyalty", MTH_BOOK_GetLoyaltyNameByLevel(tonumber(row.loyaltyLevel) or (stableInfo and tonumber(stableInfo.loyaltyLevel)) or nil))
MTH_BOOK_AddDetailSection(lines, "Stable info")
MTH_BOOK_AddStableStyleKV(lines, "Stabled on", MTH_BOOK_FormatDateTimeValue(stabledAt))
MTH_BOOK_AddStableStyleKV(lines, "Stabled since", stabledSince)
MTH_BOOK_AddStableStyleKV(lines, "Stable Master", stableMasterName)
MTH_BOOK_AddStableStyleKV(lines, "Location", stableLocation)
MTH_BOOK_AddDetailSection(lines, "Taming info")
if hasRecordedTame then
MTH_BOOK_AddStableStyleKV(lines, "Tamed on", MTH_BOOK_FormatDateTimeValue(tamedAt))
MTH_BOOK_AddStableStyleKV(lines, "Tamed Beast", tameBeastName)
MTH_BOOK_AddStableStyleKV(lines, "Taming Loc", tameZone)
MTH_BOOK_AddStableStyleKV(lines, "Coords", tameCoords)
else
table.insert(lines, "|cffb0b0b0No info|r")
end
MTH_BOOK_AddDetailSection(lines, "Row info")
MTH_BOOK_AddStableStyleKV(lines, "ID", tostring(petId or "-"))
MTH_BOOK_AddStableStyleKV(lines, "Created", MTH_BOOK_FormatDateTimeValue(row.createdAt))
MTH_BOOK_AddStableStyleKV(lines, "Origin", row.origin or row.lastSource or "-")
MTH_BOOK_AddStableStyleKV(lines, "Updated", MTH_BOOK_FormatDateTimeValue(row.lastUpdated or row.updatedAt or row.lastSeen))
MTH_BOOK_AddStableStyleKV(lines, "Lost Date/Time", MTH_BOOK_FormatDateTimeValue(row.abandonedAt))
MTH_BOOK_AddStableStyleKV(lines, "Lost Cause", MTH_BOOK_GetPetHistoryLostCause(row))
MTH_BOOK_SetDetailText(detail, table.concat(lines, "\n"))
MTH_BOOK_UpdateOpenMapButton()
return
end
local selected = MTH_BOOK_STATE.selectedEntry
if not selected or not selected.itemId then
MTH_BOOK_SetDetailText(detail, "|cFFFFD100Inspector|r\n\nSelect an entry from the list to view identity, stats, sources and locations.")
MTH_BOOK_UpdateOpenMapButton()
return
end
local itemId = selected.itemId
local items = MTH_BOOK_GetItemsTable()
local item = items and items[itemId]
if not item then
MTH_BOOK_SetDetailText(detail, "|cFFFFD100Inspector|r\n\nSelect an entry from the list to view identity, stats, sources and locations.")
MTH_BOOK_UpdateOpenMapButton()
return
end
local v = MTH_BOOK_CountMap(item.vendors)
local d = MTH_BOOK_CountMap(item.drops)
local o = MTH_BOOK_CountMap(item.objects)
local atlas = item.atlas_sources or {}
local lines = {}
table.insert(lines, "|cFFFFFF00" .. (item.name or "Unknown") .. "|r")
MTH_BOOK_AddDetailSection(lines, "Identity")
MTH_BOOK_AddDetailKV(lines, "ID", itemId)
MTH_BOOK_AddDetailKV(lines, "Subtype", item.subtype or "?")
MTH_BOOK_AddDetailSection(lines, "Stats")
MTH_BOOK_AddDetailKV(lines, "Level", item.level or "?")
MTH_BOOK_AddDetailKV(lines, "Req Level", item.reqlevel or "-")
if item.quality then MTH_BOOK_AddDetailKV(lines, "Quality", item.quality) end
if item.dps then MTH_BOOK_AddDetailKV(lines, "DPS", item.dps) end
if item.speed then MTH_BOOK_AddDetailKV(lines, "Speed", item.speed) end
MTH_BOOK_AddDetailSection(lines, "Sources")
MTH_BOOK_AddDetailKV(lines, "Vendors", v)
MTH_BOOK_AddDetailKV(lines, "Creature Drops", d)
MTH_BOOK_AddDetailKV(lines, "Object Sources", o)
if atlas.boss or atlas.world or atlas.worlddrop or atlas.quest or atlas.vendor or atlas.pvp or atlas.crafted or atlas.event then
MTH_BOOK_AddDetailSection(lines, "Atlas Hints")
MTH_BOOK_AddDetailKV(lines, "Boss Loot", atlas.boss and "Yes" or "-")
MTH_BOOK_AddDetailKV(lines, "World Sources", atlas.world and "Yes" or "-")
MTH_BOOK_AddDetailKV(lines, "World Drop", atlas.worlddrop and "Yes" or "-")
MTH_BOOK_AddDetailKV(lines, "Quest Reward", atlas.quest and "Yes" or "-")
MTH_BOOK_AddDetailKV(lines, "Vendor / Faction", atlas.vendor and "Yes" or "-")
MTH_BOOK_AddDetailKV(lines, "PvP Reward", atlas.pvp and "Yes" or "-")
MTH_BOOK_AddDetailKV(lines, "Crafted", atlas.crafted and "Yes" or "-")
MTH_BOOK_AddDetailKV(lines, "Event", atlas.event and "Yes" or "-")
end
MTH_BOOK_SetDetailText(detail, table.concat(lines, "\n"))
MTH_BOOK_UpdateOpenMapButton()
end
local function MTH_BOOK_UpdateHeader()
local stats = getglobal("MTH_BOOK_StatsText")
if not stats then return end
local mode = MTH_BOOK_STATE.mode or "pets"
local tabDef = MTH_BOOK_GetTabDefinition(mode)
local modeLabel = (tabDef and tabDef.headerLabel) or "Beasts"
if not tabDef then
if mode == "families" then modeLabel = "Families" end
if mode == "petabilities" then modeLabel = "Pet Abilities" end
if mode == "items" then modeLabel = "Ranged Weapons" end
if mode == "npcs" then modeLabel = "NPC Finder" end
if mode == "stable" then modeLabel = "Stable" end
if mode == "pethistory" then modeLabel = "Pet History" end
end
local total = MTH_BOOK_GetTotalCount()
local filtered = table.getn(MTH_BOOK_STATE.results)
local pages = math.max(1, math.ceil(filtered / MTH_BOOK_STATE.pageSize))
if mode == "families" then
local namedTotal = 0
local coordsTotal = 0
for i = 1, table.getn(MTH_BOOK_STATE.results or {}) do
local row = MTH_BOOK_STATE.results[i]
if type(row) == "table" then
namedTotal = namedTotal + (tonumber(row.named) or 0)
coordsTotal = coordsTotal + (tonumber(row.coords) or 0)
end
end
stats:SetText("Named: " .. tostring(namedTotal) .. " | Coords: " .. tostring(coordsTotal))
return
end
stats:SetText(modeLabel .. ": " .. total .. " | Filtered: " .. filtered .. " | Page " .. MTH_BOOK_STATE.page .. "/" .. pages)
end
local function MTH_BOOK_GetColumnLabels()
local tabDef = MTH_BOOK_GetTabDefinition(MTH_BOOK_STATE.mode)
if tabDef and type(tabDef.columnLabels) == "table" then
return tabDef.columnLabels
end
if MTH_BOOK_STATE.mode == "pets" then
return { "ID", "Lvl", "Family", "Name", "Abilities", "Zone", "R", "E", "U" }
elseif MTH_BOOK_STATE.mode == "petabilities" then
return { "Ability Name", "Ranks", "Families" }
elseif MTH_BOOK_STATE.mode == "stable" then
return { "Pet ID", "Slot", "Name", "Family", "Lvl", "Loyalty", "Seen" }
elseif MTH_BOOK_STATE.mode == "pethistory" then
return { "Pet ID", "Name", "Family", "Lvl", "Lost Date/Time", "Lost Cause" }
elseif MTH_BOOK_STATE.mode == "abilities" then
return { "Ability", "Lvl", "Family", "Beast", "Rare" }
elseif MTH_BOOK_STATE.mode == "npcs" then
return { "ID", "Name", "React", "Function", "Zone" }
end
return { "ID", "Req", "Lvl", "Type", "Name", "DPS", "Speed", "Source" }
end
local function MTH_BOOK_GetColumnLayout()
local tabDef = MTH_BOOK_GetTabDefinition(MTH_BOOK_STATE.mode)
if tabDef and type(tabDef.columnLayout) == "table" then
return tabDef.columnLayout
end
if MTH_BOOK_STATE.mode == "pets" then
return {
{ x = 8, width = 28, align = "LEFT" },
{ x = 38, width = 30, align = "LEFT" },
{ x = 68, width = 74, align = "LEFT" },
{ x = 142, width = 130, align = "LEFT" },
{ x = 272, width = 180, align = "LEFT" },
{ x = 452, width = 68, align = "LEFT" },
{ x = 520, width = 10, align = "CENTER" },
{ x = 532, width = 10, align = "CENTER" },
{ x = 544, width = 10, align = "CENTER" },
}
elseif MTH_BOOK_STATE.mode == "petabilities" then
return {
{ x = 8, width = 160, align = "LEFT" },
{ x = 170, width = 52, align = "LEFT" },
{ x = 224, width = 328, align = "LEFT" },
}
elseif MTH_BOOK_STATE.mode == "stable" then
return {
{ x = 8, width = 78, align = "LEFT" },
{ x = 88, width = 34, align = "LEFT" },
{ x = 124, width = 118, align = "LEFT" },
{ x = 244, width = 92, align = "LEFT" },
{ x = 338, width = 34, align = "LEFT" },
{ x = 374, width = 114, align = "LEFT" },
{ x = 490, width = 52, align = "LEFT" },
}
elseif MTH_BOOK_STATE.mode == "pethistory" then
return {
{ x = 8, width = 66, align = "LEFT" },
{ x = 76, width = 104, align = "LEFT" },
{ x = 182, width = 84, align = "LEFT" },
{ x = 268, width = 30, align = "LEFT" },
{ x = 300, width = 128, align = "LEFT" },
{ x = 430, width = 78, align = "LEFT" },
}
elseif MTH_BOOK_STATE.mode == "abilities" then
return {
{ x = 8, width = 112, align = "LEFT" },
{ x = 120, width = 40, align = "LEFT" },
{ x = 160, width = 78, align = "LEFT" },
{ x = 238, width = 142, align = "LEFT" },
{ x = 380, width = 38, align = "LEFT" },
}
elseif MTH_BOOK_STATE.mode == "npcs" then
return {
{ x = 8, width = 52, align = "LEFT" },
{ x = 60, width = 140, align = "LEFT" },
{ x = 200, width = 40, align = "LEFT" },
{ x = 242, width = 160, align = "LEFT" },
{ x = 404, width = 148, align = "LEFT" },
}
end
return {
{ x = 8, width = 36, align = "LEFT" },
{ x = 44, width = 30, align = "LEFT" },
{ x = 74, width = 30, align = "LEFT" },
{ x = 104, width = 62, align = "LEFT" },
{ x = 166, width = 188, align = "LEFT" },
{ x = 356, width = 44, align = "LEFT" },
{ x = 402, width = 40, align = "LEFT" },
{ x = 444, width = 108, align = "LEFT" },
}
end
local function MTH_BOOK_ApplyColumnLayout(parent)
if not parent then return end
local layout = MTH_BOOK_GetColumnLayout()
for i = 1, MTH_BOOK_MAX_COLS do
local header = MTH_BOOK_STATE.headerCols[i]
local hit = MTH_BOOK_STATE.headerButtons[i]
local info = layout[i]
if header then
if info then
header:Show()
header:ClearAllPoints()
header:SetPoint("TOPLEFT", parent, "TOPLEFT", info.x, -8)
header:SetWidth(info.width)
header:SetJustifyH(info.align or "LEFT")
if hit then
hit:Show()
hit:ClearAllPoints()
hit:SetPoint("TOPLEFT", parent, "TOPLEFT", info.x, -8)
hit:SetWidth(info.width)
hit:SetHeight(14)
end
else
header:Hide()
header:SetText("")
if hit then hit:Hide() end
end
end
end
for row = 1, MTH_BOOK_STATE.pageSize do
local btn = MTH_BOOK_STATE.buttons[row]
if btn and btn.cols then
local parentWidth = tonumber(parent:GetWidth()) or 0
local rowWidth = parentWidth - 8
if rowWidth < 220 then rowWidth = 220 end
btn:SetWidth(rowWidth)
for i = 1, MTH_BOOK_MAX_COLS do
local col = btn.cols[i]
local info = layout[i]
if col then
if info then
col:Show()
col:ClearAllPoints()
col:SetPoint("LEFT", btn, "LEFT", info.x - 4, 0)
col:SetWidth(info.width)
col:SetJustifyH(info.align or "LEFT")
else
col:Hide()
col:SetText("")
end
end
end
if btn.bookLinkButton then
local info = layout[1]
if (MTH_BOOK_STATE.mode == "pets" or MTH_BOOK_STATE.mode == "npcs" or MTH_BOOK_STATE.mode == "items") and info then
btn.bookLinkButton:ClearAllPoints()
btn.bookLinkButton:SetPoint("LEFT", btn, "LEFT", info.x - 4, 0)
btn.bookLinkButton:SetWidth(info.width)
btn.bookLinkButton:SetHeight(btn:GetHeight())
btn.bookLinkButton:Show()
else
btn.bookLinkButton:Hide()
end
end
if btn.itemLinkButton then btn.itemLinkButton:Hide() end
if btn.nameHoverButton then
if MTH_BOOK_STATE.mode == "items" and layout[5] then
btn.nameHoverButton:ClearAllPoints()
btn.nameHoverButton:SetPoint("LEFT", btn, "LEFT", layout[5].x + 12, 0)
btn.nameHoverButton:SetWidth(layout[5].width - 16)
btn.nameHoverButton:SetHeight(btn:GetHeight())
btn.nameHoverButton:Show()
else
btn.nameHoverButton:Hide()
end
end
if btn.itemIcon then
if MTH_BOOK_STATE.mode == "items" and layout[5] then
btn.itemIcon:ClearAllPoints()
btn.itemIcon:SetPoint("LEFT", btn, "LEFT", layout[5].x - 4, 0)
btn.itemIcon:Show()
if btn.cols and btn.cols[5] then
btn.cols[5]:ClearAllPoints()
btn.cols[5]:SetPoint("LEFT", btn, "LEFT", layout[5].x + 12, 0)
btn.cols[5]:SetWidth(layout[5].width - 16)
end
else
btn.itemIcon:Hide()
end
end
end
end
end
local function MTH_BOOK_GetRowValues(entry)
if MTH_BOOK_STATE.mode == "pets" then
local beast = MTH_DS_Beasts and MTH_DS_Beasts[entry]
if not beast then return { "", "", "", "", "", "", "", "", "" } end
local traits = MTH_BOOK_ParseBeastTraits(beast)
local abilities = MTH_BOOK_GetBeastAbilitiesSummary(beast)
local zone = MTH_BOOK_GetBeastZoneSummary(beast)
return {
"|cFF33CCFF" .. tostring(entry) .. "|r",
tostring(beast.lvl or "?"),
tostring(beast.family or "?"),
tostring(beast.name or "Unknown"),
abilities,
zone,
(traits.rare and "R" or ""),
(traits.elite and "E" or ""),
(traits.unique and "U" or ""),
}
end
if MTH_BOOK_STATE.mode == "abilities" then
return {
tostring(entry.abilityToken or "?"),
tostring(entry.level or 0),
tostring(entry.family or "?"),
tostring(entry.name or "Unknown"),
(entry.rare and "R" or ""),
}
end
if MTH_BOOK_STATE.mode == "petabilities" then
local families = entry.familyList or ""
if families == "" then families = "-" end
return {
tostring(entry.ability or "Unknown"),
tostring(entry.rankText or ""),
families,
}
end
if MTH_BOOK_STATE.mode == "families" then
local names = {}
if type(entry.abilities) == "table" then
for i = 1, table.getn(entry.abilities) do
local ability = entry.abilities[i]
if type(ability) == "table" and ability.name and ability.name ~= "" then
table.insert(names, tostring(ability.name))
end
end
end
local abilitiesText = table.concat(names, ", ")
if abilitiesText == "" then abilitiesText = "-" end
local dietText = tostring(entry.dietText or "")
if dietText == "" then dietText = "-" end
return {
tostring(entry.family or "-"),
tostring(entry.named or 0),
tostring(entry.coords or 0),
abilitiesText,
dietText,
}
end
if MTH_BOOK_STATE.mode == "stable" then
local row = MTH_BOOK_GetPetStoreRow(entry)
if not row then return { "", "", "", "", "", "", "" } end
local slotDisplay = MTH_BOOK_GetStableDisplaySlot(entry, row) or "-"
local loyalty = MTH_BOOK_GetLoyaltyNameByLevel(tonumber(row.loyaltyLevel) or (row.stableInfo and tonumber(row.stableInfo.loyaltyLevel)) or nil)
return {
tostring(entry or ""),
tostring(slotDisplay),
tostring(row.name or "-"),
tostring(row.family or "-"),
tostring(row.level or "-"),
tostring(loyalty),
tostring(row.lastSeen or row.lastUpdated or 0),
}
end
if MTH_BOOK_STATE.mode == "pethistory" then
local row = MTH_BOOK_GetPetStoreRow(entry)
if not row then return { "", "", "", "", "", "" } end
local lostCause = MTH_BOOK_GetPetHistoryLostCause(row)
return {
tostring(entry or ""),
tostring(row.name or "-"),
tostring(row.family or "-"),
tostring(row.level or "-"),
MTH_BOOK_FormatDateTimeValue(row.abandonedAt),
tostring(lostCause),
}
end
if MTH_BOOK_STATE.mode == "npcs" then
local vendor = MTH_DS_Vendors and MTH_DS_Vendors[entry]
if not vendor then return { "", "", "", "", "" } end
local react = MTH_BOOK_GetNPCReactBucket(vendor.fac)
local functionSummary = MTH_BOOK_GetNPCFunctionSummary(vendor)
local zoneName = MTH_BOOK_GetNPCZoneSummary(vendor)
return {
"|cFF33CCFF" .. tostring(entry) .. "|r",
tostring(vendor.name or "Unknown"),
react,
functionSummary,
zoneName,
}
end
local items = MTH_BOOK_GetItemsTable()
local item = items and items[entry]
if not item then return { "", "", "", "", "", "", "", "" } end
local itemName = tostring(item.name or "Unknown")
local colorCode = MTH_BOOK_GetItemQualityColorCode(item.quality)
local sourceText = "-"
local hasVendors = MTH_BOOK_CountMap(item.vendors) > 0
local hasDrops = MTH_BOOK_CountMap(item.drops) > 0
local hasObjects = MTH_BOOK_CountMap(item.objects) > 0
local concreteCount = 0
if hasVendors then concreteCount = concreteCount + 1 end
if hasDrops then concreteCount = concreteCount + 1 end
if hasObjects then concreteCount = concreteCount + 1 end
if concreteCount > 1 then
sourceText = "Mixed"
elseif hasVendors then
sourceText = "Vendor"
elseif hasDrops then
sourceText = "Drop"
elseif hasObjects then
sourceText = "Object"
else
local atlas = item.atlas_sources
if atlas then
if atlas.boss then
sourceText = "Boss"
elseif atlas.quest then
sourceText = "Quest"
elseif atlas.vendor then
sourceText = "Vendor"
elseif atlas.pvp then
sourceText = "PvP"
elseif atlas.crafted then
sourceText = "Crafted"
elseif atlas.worlddrop then
sourceText = "World Drop"
elseif atlas.world then
sourceText = "World"
elseif atlas.event then
sourceText = "Event"
end
end
end
return {
"|cFF33CCFF" .. tostring(entry) .. "|r",
tostring(item.reqlevel or 0),
tostring(item.level or 0),
tostring(item.subtype or "?"),
"|c" .. colorCode .. itemName .. "|r",
(item.dps and tostring(item.dps) or "-"),
(item.speed and tostring(item.speed) or "-"),
sourceText,
}
end
local function MTH_BOOK_EnsurePetAbilitiesUI(listParent, detailParent)
if type(MTH_BOOKTAB_EnsurePetAbilitiesUI) == "function" then
return MTH_BOOKTAB_EnsurePetAbilitiesUI(listParent, detailParent)
end
end
local function MTH_BOOK_SetPetAbilitiesUIVisible(visible)
if type(MTH_BOOKTAB_SetPetAbilitiesUIVisible) == "function" then
return MTH_BOOKTAB_SetPetAbilitiesUIVisible(visible)
end
end
local function MTH_BOOK_SetFamiliesUIVisible(visible)
if type(MTH_BOOKTAB_SetFamiliesUIVisible) == "function" then
return MTH_BOOKTAB_SetFamiliesUIVisible(visible)
end
MTH_BOOK_FamiliesTrace("SetFamiliesUIVisible missing MTH_BOOKTAB_SetFamiliesUIVisible")
end
function MTH_BOOK_EnsureStableUI()
if type(MTH_BOOKTAB_EnsureStableUI) == "function" then
return MTH_BOOKTAB_EnsureStableUI()
end
end
function MTH_BOOK_SetStableUIVisible(visible)
if type(MTH_BOOKTAB_SetStableUIVisible) == "function" then
return MTH_BOOKTAB_SetStableUIVisible(visible)
end
end
function MTH_BOOK_RenderStableCards()
if type(MTH_BOOKTAB_RenderStableCards) == "function" then
return MTH_BOOKTAB_RenderStableCards()
end
end
MTH_BOOK_UpdatePetAbilitiesLists = function()
if type(MTH_BOOKTAB_UpdatePetAbilitiesLists) == "function" then
return MTH_BOOKTAB_UpdatePetAbilitiesLists()
end
end
_G.MTH_BOOK_UpdatePetAbilitiesLists = MTH_BOOK_UpdatePetAbilitiesLists
local function MTH_BOOK_UpdateListHeaders()
if MTH_BOOK_STATE.mode == "petabilities" or MTH_BOOK_STATE.mode == "stable" then
for i = 1, MTH_BOOK_MAX_COLS do
local header = MTH_BOOK_STATE.headerCols[i]
local hit = MTH_BOOK_STATE.headerButtons[i]
if header then header:SetText(""); header:Hide() end
if hit then hit:Hide() end
end
return
end
local labels = MTH_BOOK_GetColumnLabels()
local state = MTH_BOOK_GetSortState()
for i = 1, MTH_BOOK_MAX_COLS do
local header = MTH_BOOK_STATE.headerCols[i]
local hit = MTH_BOOK_STATE.headerButtons[i]
if header then
local label = labels[i] or ""
if label ~= "" and state and state.col == i then
label = label .. (state.asc and " ^" or " v")
end
header:SetText(label)
if hit then
hit:EnableMouse(labels[i] and labels[i] ~= "")
end
end
end
local listParent = getglobal("MTH_BOOK_ListBackdrop")
if listParent then
MTH_BOOK_ApplyColumnLayout(listParent)
end
end
local function MTH_BOOK_OnHeaderClick(col)
local labels = MTH_BOOK_GetColumnLabels()
if not labels[col] or labels[col] == "" then return end
local state = MTH_BOOK_GetSortState()
if state.col == col then
state.asc = not state.asc
else
state.col = col
state.asc = true
end
MTH_BOOK_STATE.page = 1
MTH_BOOK_STATE.selectedEntry = nil
MTH_BOOK_STATE.selectedPetRankEntry = nil
MTH_BOOK_STATE.petRankRows = {}
MTH_BOOK_STATE.forcedBeastId = nil
MTH_BOOK_RefreshFilter()
end
local function MTH_BOOK_AssignEntry(btn, entry)
btn.entry = nil
if MTH_BOOK_STATE.mode == "pets" then
btn.entry = { beastId = entry }
elseif MTH_BOOK_STATE.mode == "families" then
btn.entry = entry
elseif MTH_BOOK_STATE.mode == "npcs" then
btn.entry = { npcId = entry }
elseif MTH_BOOK_STATE.mode == "abilities" then
btn.entry = entry
elseif MTH_BOOK_STATE.mode == "petabilities" then
btn.entry = entry
elseif MTH_BOOK_STATE.mode == "pethistory" then
btn.entry = { petId = entry }
else
btn.entry = { itemId = entry }
end
end
MTH_BOOK_UpdateResults = function()
MTH_BOOK_SetFamiliesListVisualScale(MTH_BOOK_STATE.mode == "families")
local resultCount = table.getn(MTH_BOOK_STATE.results)
local totalPages = math.max(1, math.ceil(resultCount / MTH_BOOK_STATE.pageSize))
local buttonCount = table.getn(MTH_BOOK_STATE.buttons)
if MTH_BOOK_STATE.page < 1 then MTH_BOOK_STATE.page = 1 end
if MTH_BOOK_STATE.page > totalPages then MTH_BOOK_STATE.page = totalPages end
local slider = getglobal("MTH_BOOK_ListSlider")
local sliderBackdrop = getglobal("MTH_BOOK_ListSliderBackdrop")
if MTH_BOOK_STATE.mode == "stable" then
MTH_BOOK_DebugTrace("UpdateResults stable: resultCount=" .. tostring(resultCount))
if slider then slider:Hide() end
MTH_BOOK_SetPetAbilitiesUIVisible(false)
MTH_BOOK_SetFamiliesUIVisible(false)
MTH_BOOK_EnsureStableUI()
if not MTH_BOOK_STATE.stableUI then
MTH_BOOK_DebugTrace("UpdateResults stable: custom UI unavailable, fallback to list")
MTH_BOOK_SetStableUIVisible(false)
else
MTH_BOOK_DebugTrace("UpdateResults stable: custom UI active")
MTH_BOOK_SetStableUIVisible(true)
end
for i = 1, buttonCount do
local btn = MTH_BOOK_STATE.buttons[i]
if btn then
if MTH_BOOK_STATE.stableUI then
btn:Hide()
else
btn:Show()
end
end
end
if MTH_BOOK_STATE.stableUI then
MTH_BOOK_RenderStableCards()
local stableFrame = MTH_BOOK_STATE.stableUI.frame
if stableFrame and stableFrame.SetScript then
stableFrame:SetScript("OnUpdate", function()
stableFrame:SetScript("OnUpdate", nil)
if MTH_BOOK_STATE.mode == "stable" and MTH_BOOK_STATE.stableUI then
MTH_BOOK_RenderStableCards()
end
end)
end
end
MTH_BOOK_UpdateHeader()
if not MTH_BOOK_STATE.stableUI then
MTH_BOOK_SetStableUIVisible(false)
MTH_BOOK_SetPetAbilitiesUIVisible(false)
-- continue with generic list rendering
else
return
end
end
if MTH_BOOK_STATE.mode == "petabilities" then
if slider then slider:Hide() end
local listParent = getglobal("MTH_BOOK_ListBackdrop")
local detailParent = getglobal("MTH_BOOK_DetailBackdrop")
MTH_BOOK_SetStableUIVisible(false)
MTH_BOOK_EnsurePetAbilitiesUI(listParent, detailParent)
MTH_BOOK_SetPetAbilitiesUIVisible(true)
MTH_BOOK_SetFamiliesUIVisible(false)
for i = 1, buttonCount do
local btn = MTH_BOOK_STATE.buttons[i]
if btn then btn:Hide() end
end
MTH_BOOK_UpdatePetAbilitiesLists()
MTH_BOOK_UpdateHeader()
MTH_BOOK_UpdateDetail()
return
end
if MTH_BOOK_STATE.mode == "families" then
MTH_BOOK_FamiliesTrace("UpdateResults families using safe generic renderer")
MTH_BOOK_STATE.page = 1
if sliderBackdrop then sliderBackdrop:Hide() end
end
if slider then
if MTH_BOOK_STATE.mode == "families" then
slider:Hide()
else
if sliderBackdrop then sliderBackdrop:Show() end
slider:Show()
slider:SetMinMaxValues(1, totalPages)
slider:SetValueStep(1)
slider:SetValue(MTH_BOOK_STATE.page)
MTH_BOOK_HideSliderTemplateTexts()
MTH_BOOK_UpdateSliderMarker(slider)
end
end
MTH_BOOK_SetPetAbilitiesUIVisible(false)
MTH_BOOK_SetStableUIVisible(false)
MTH_BOOK_SetFamiliesUIVisible(false)
local startIndex = ((MTH_BOOK_STATE.page - 1) * MTH_BOOK_STATE.pageSize) + 1
for i = 1, buttonCount do
local btn = MTH_BOOK_STATE.buttons[i]
if btn then
local entry = nil
if i <= MTH_BOOK_STATE.pageSize then
local rowIndex = startIndex + i - 1
entry = MTH_BOOK_STATE.results[rowIndex]
end
if entry then
MTH_BOOK_AssignEntry(btn, entry)
local values = MTH_BOOK_GetRowValues(entry)
for c = 1, MTH_BOOK_MAX_COLS do
if btn.cols and btn.cols[c] then
btn.cols[c]:SetText(values[c] or "")
end
end
if btn.itemIcon then
if MTH_BOOK_STATE.mode == "items" then
local items = MTH_BOOK_GetItemsTable()
local item = items and items[entry]
if item and item.icon and item.icon ~= "" then
if string.find(tostring(item.icon), "\\", 1, true) then
btn.itemIcon:SetTexture(tostring(item.icon))
else
btn.itemIcon:SetTexture("Interface\\Icons\\" .. tostring(item.icon))
end
btn.itemIcon:Show()
else
btn.itemIcon:SetTexture(nil)
btn.itemIcon:Hide()
end
else
btn.itemIcon:SetTexture(nil)
btn.itemIcon:Hide()
end
end
if btn.familyAbilityButtons then
local abilityEntries = nil
local abilityColIndex = nil
local tooltipFunc = nil
if MTH_BOOK_STATE.mode == "families" and type(entry) == "table" and type(entry.abilities) == "table" then
abilityEntries = entry.abilities
abilityColIndex = 4
tooltipFunc = MTH_BOOKTAB_ShowFamilyAbilityTooltip
elseif MTH_BOOK_STATE.mode == "pets" then
local beast = MTH_DS_Beasts and MTH_DS_Beasts[entry]
if beast and type(MTH_BOOKTAB_BuildBeastAbilityEntries) == "function" then
abilityEntries = MTH_BOOKTAB_BuildBeastAbilityEntries(beast)
abilityColIndex = 5
tooltipFunc = MTH_BOOKTAB_ShowBeastAbilityTooltip
end
end
if type(abilityEntries) == "table" and table.getn(abilityEntries) > 0 then
if btn.cols and btn.cols[abilityColIndex] then btn.cols[abilityColIndex]:SetText("") end
local layout = MTH_BOOK_GetColumnLayout()
local col = layout and layout[abilityColIndex]
local startX = ((col and col.x) or 232) - 4
local maxWidth = (col and col.width) or 292
local usedWidth = 0
local abilitiesCount = table.getn(abilityEntries)
for chipIndex = 1, table.getn(btn.familyAbilityButtons) do
local chip = btn.familyAbilityButtons[chipIndex]
local ability = abilityEntries[chipIndex]
if chip and ability and type(ability) == "table" and ability.name and ability.name ~= "" then
local label = tostring(ability.name)
if chipIndex < abilitiesCount then
label = label .. ","
end
chip.text:SetText(label)
local textWidth = chip.text:GetStringWidth() or 24
if textWidth < 16 then textWidth = 16 end
local chipWidth = ((MTH_BOOK_STATE.mode == "families") and 15 or 14) + textWidth
if usedWidth + chipWidth > maxWidth then
chip:Hide()
else
chip:ClearAllPoints()
chip:SetPoint("LEFT", btn, "LEFT", startX + usedWidth, 0)
chip:SetWidth(chipWidth)
chip.abilityEntry = ability
chip.abilityTooltipFunc = tooltipFunc
local iconPath = MTH_BOOK_ResolveIconPath(ability.icon)
if iconPath then
chip.icon:SetTexture(iconPath)
else
chip.icon:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark")
end
chip:Show()
usedWidth = usedWidth + chipWidth + 4
end
else
if chip then
chip.abilityEntry = nil
chip.abilityTooltipFunc = nil
chip:Hide()
end
end
end
else
for chipIndex = 1, table.getn(btn.familyAbilityButtons) do
local chip = btn.familyAbilityButtons[chipIndex]
if chip then
chip.abilityEntry = nil
chip.abilityTooltipFunc = nil
chip:Hide()
end
end
end
end
btn:Show()
else
btn.entry = nil
for c = 1, MTH_BOOK_MAX_COLS do
if btn.cols and btn.cols[c] then
btn.cols[c]:SetText("")
end
end
if btn.itemIcon then
btn.itemIcon:SetTexture(nil)
btn.itemIcon:Hide()
end
if btn.familyAbilityButtons then
for chipIndex = 1, table.getn(btn.familyAbilityButtons) do
local chip = btn.familyAbilityButtons[chipIndex]
if chip then
chip.abilityEntry = nil
chip.abilityTooltipFunc = nil
chip:Hide()
end
end
end
btn:Hide()
end
end
end
MTH_BOOK_UpdateHeader()
MTH_BOOK_UpdateDetail()
end
MTH_BOOK_RefreshFilter = function()
MTH_BOOK_UpdateQuickFilterControls()
MTH_BOOK_UpdateListHeaders()
if MTH_BOOK_STATE.mode == "stable" and type(MTH_PETS_RefreshCurrentPet) == "function" then
MTH_PETS_RefreshCurrentPet()
end
MTH_BOOK_STATE.results = MTH_BOOK_BuildResults()
MTH_BOOK_UpdateResults()
end
local function MTH_BOOK_UpdateModeLabels()
local header = getglobal("MTH_BOOK_HeaderText")
if header then header:SetText("The Great Book of Huntards") end
local filterNames = {}
local check1 = ""
local check2 = ""
local check3 = ""
local searchLabel = getglobal("MTH_BOOK_SearchLabel")
local minLabel = getglobal("MTH_BOOK_MinLabel")
local maxLabel = getglobal("MTH_BOOK_MaxLabel")
if MTH_BOOK_STATE.mode == "pets" then
filterNames = { "All", "Cats", "Wolves", "Boars", "Spiders", "" }
check1 = "Rare"
check2 = "Elite"
check3 = "Unique"
elseif MTH_BOOK_STATE.mode == "families" then
filterNames = { "", "", "", "", "", "" }
check1 = ""
check2 = ""
check3 = ""
elseif MTH_BOOK_STATE.mode == "petabilities" then
filterNames = { "", "", "", "", "", "" }
check1 = ""
check2 = ""
check3 = ""
elseif MTH_BOOK_STATE.mode == "npcs" then
filterNames = { "", "", "", "", "", "" }
check1 = "Alliance"
check2 = "Horde"
check3 = "Neutral"
elseif MTH_BOOK_STATE.mode == "abilities" then
filterNames = { "All", "Bite", "Claw", "Dash", "Screech", "Charge" }
check1 = "Ranked only"
check2 = "Rare beasts"
check3 = "Has coords"
else
filterNames = { "", "", "", "", "", "" }
check1 = ""
check2 = ""
check3 = ""
end
for i = 1, 6 do
local btn = getglobal("MTH_BOOK_Filter" .. i)
if btn then btn:SetText(filterNames[i] or "") end
end
if getglobal("MTH_BOOK_RequireVendorText") then getglobal("MTH_BOOK_RequireVendorText"):SetText(check1) end
if getglobal("MTH_BOOK_RequireDropText") then getglobal("MTH_BOOK_RequireDropText"):SetText(check2) end
if getglobal("MTH_BOOK_RequireObjectText") then getglobal("MTH_BOOK_RequireObjectText"):SetText(check3) end
if searchLabel then
if MTH_BOOK_STATE.mode == "npcs" then
searchLabel:SetText("Name")
else
searchLabel:SetText("Search")
end
end
if minLabel then
if MTH_BOOK_STATE.mode == "npcs" or MTH_BOOK_STATE.mode == "items" or MTH_BOOK_STATE.mode == "stable" or MTH_BOOK_STATE.mode == "families" or MTH_BOOK_STATE.mode == "pethistory" then
minLabel:Hide()
else
minLabel:Show()
minLabel:SetText("Min Lvl")
end
end
if maxLabel then
if MTH_BOOK_STATE.mode == "npcs" or MTH_BOOK_STATE.mode == "items" or MTH_BOOK_STATE.mode == "stable" or MTH_BOOK_STATE.mode == "families" or MTH_BOOK_STATE.mode == "pethistory" then
maxLabel:Hide()
else
maxLabel:Show()
maxLabel:SetText("Max Lvl")
end
end
if getglobal("MTH_BOOK_HideNoAbilitiesText") then getglobal("MTH_BOOK_HideNoAbilitiesText"):SetText("Hide No Abilities") end
if getglobal("MTH_BOOK_PetOnlyMyLevelText") then
if MTH_BOOK_STATE.mode == "items" then
getglobal("MTH_BOOK_PetOnlyMyLevelText"):SetText("Show only my level")
else
getglobal("MTH_BOOK_PetOnlyMyLevelText"):SetText("Only my level")
end
local onlyMyLevel = getglobal("MTH_BOOK_PetOnlyMyLevel")
if onlyMyLevel then
getglobal("MTH_BOOK_PetOnlyMyLevelText"):ClearAllPoints()
getglobal("MTH_BOOK_PetOnlyMyLevelText"):SetPoint("LEFT", onlyMyLevel, "RIGHT", 1, 1)
end
end
if getglobal("MTH_BOOK_PetInZoneOnlyText") then
getglobal("MTH_BOOK_PetInZoneOnlyText"):SetText("In this zone only")
local zoneOnly = getglobal("MTH_BOOK_PetInZoneOnly")
if zoneOnly then
getglobal("MTH_BOOK_PetInZoneOnlyText"):ClearAllPoints()
getglobal("MTH_BOOK_PetInZoneOnlyText"):SetPoint("LEFT", zoneOnly, "RIGHT", 1, 1)
end
end
if getglobal("MTH_BOOK_NPCInZoneOnlyText") then
getglobal("MTH_BOOK_NPCInZoneOnlyText"):SetText("In this zone only")
local zoneOnlyNpc = getglobal("MTH_BOOK_NPCInZoneOnly")
if zoneOnlyNpc then
getglobal("MTH_BOOK_NPCInZoneOnlyText"):ClearAllPoints()
getglobal("MTH_BOOK_NPCInZoneOnlyText"):SetPoint("LEFT", zoneOnlyNpc, "RIGHT", 1, 1)
end
end
if getglobal("MTH_BOOK_HideUnknownText") then
if MTH_BOOK_STATE.mode == "npcs" then
getglobal("MTH_BOOK_HideUnknownText"):SetText("Hide no zone")
else
getglobal("MTH_BOOK_HideUnknownText"):SetText("Hide Unknown")
end
end
MTH_BOOK_UpdateQuickFilterControls()
end
local function MTH_BOOK_ApplyInputs()
local search = getglobal("MTH_BOOK_Search")
MTH_BOOK_STATE.search = MTH_BOOK_SafeLower(search and search:GetText() or "")
if MTH_BOOK_STATE.mode == "npcs" or MTH_BOOK_STATE.mode == "items" or MTH_BOOK_STATE.mode == "stable" or MTH_BOOK_STATE.mode == "families" or MTH_BOOK_STATE.mode == "pethistory" then
MTH_BOOK_STATE.minLevel = nil
MTH_BOOK_STATE.maxLevel = nil
else
MTH_BOOK_STATE.minLevel = MTH_BOOK_ParseBoxNumber("MTH_BOOK_MinLevel")
MTH_BOOK_STATE.maxLevel = MTH_BOOK_ParseBoxNumber("MTH_BOOK_MaxLevel")
end
local requireVendor = getglobal("MTH_BOOK_RequireVendor")
local requireDrop = getglobal("MTH_BOOK_RequireDrop")
local requireObject = getglobal("MTH_BOOK_RequireObject")
local hideNoAbilities = getglobal("MTH_BOOK_HideNoAbilities")
local hideUnknown = getglobal("MTH_BOOK_HideUnknown")
local petOnlyMyLevel = getglobal("MTH_BOOK_PetOnlyMyLevel")
local petInZoneOnly = getglobal("MTH_BOOK_PetInZoneOnly")
local npcInZoneOnly = getglobal("MTH_BOOK_NPCInZoneOnly")
local showAllOnMapButton = getglobal("MTH_BOOK_ShowAllOnMapButton")
MTH_BOOK_STATE.flag1 = requireVendor and requireVendor:GetChecked() == 1 or false
MTH_BOOK_STATE.flag2 = requireDrop and requireDrop:GetChecked() == 1 or false
MTH_BOOK_STATE.flag3 = requireObject and requireObject:GetChecked() == 1 or false
if MTH_BOOK_STATE.mode == "pets" then
MTH_BOOK_STATE.petHideNoAbilities = hideNoAbilities and hideNoAbilities:GetChecked() == 1 or false
MTH_BOOK_STATE.petHideUnknown = hideUnknown and hideUnknown:GetChecked() == 1 or false
MTH_BOOK_STATE.petInZoneOnly = petInZoneOnly and petInZoneOnly:GetChecked() == 1 or false
elseif MTH_BOOK_STATE.mode == "petabilities" then
MTH_BOOK_STATE.petOnlyMyLevel = petOnlyMyLevel and petOnlyMyLevel:GetChecked() == 1 or false
elseif MTH_BOOK_STATE.mode == "items" then
MTH_BOOK_STATE.itemOnlyMyLevel = petOnlyMyLevel and petOnlyMyLevel:GetChecked() == 1 or false
elseif MTH_BOOK_STATE.mode == "npcs" then
MTH_BOOK_STATE.npcHideNoZone = hideUnknown and hideUnknown:GetChecked() == 1 or false
MTH_BOOK_STATE.npcInZoneOnly = npcInZoneOnly and npcInZoneOnly:GetChecked() == 1 or false
end
MTH_BOOK_STATE.page = 1
MTH_BOOK_STATE.selectedEntry = nil
MTH_BOOK_STATE.selectedPetRankEntry = nil
MTH_BOOK_STATE.petRankRows = {}
MTH_BOOK_RefreshFilter()
end
local function MTH_BOOK_SetQuickFilter(index)
if MTH_BOOK_STATE.mode == "pets" then
local map = { [1] = "all", [2] = "cats", [3] = "wolves", [4] = "boars", [5] = "spiders", [6] = "all" }
MTH_BOOK_STATE.quick = map[index] or "all"
elseif MTH_BOOK_STATE.mode == "families" then
MTH_BOOK_STATE.quick = "all"
elseif MTH_BOOK_STATE.mode == "petabilities" then
MTH_BOOK_STATE.quick = "all"
elseif MTH_BOOK_STATE.mode == "npcs" then
MTH_BOOK_STATE.quick = "all"
elseif MTH_BOOK_STATE.mode == "abilities" then
local map = { [1] = "all", [2] = "bite", [3] = "claw", [4] = "dash", [5] = "screech", [6] = "charge" }
MTH_BOOK_STATE.quick = map[index] or "all"
else
local map = { [1] = "all", [2] = "arrow", [3] = "bullet", [4] = "bow", [5] = "gun", [6] = "crossbow" }
MTH_BOOK_STATE.quick = map[index] or "all"
end
MTH_BOOK_STATE.page = 1
MTH_BOOK_STATE.selectedEntry = nil
MTH_BOOK_STATE.forcedBeastId = nil
MTH_BOOK_RefreshFilter()
end
local function MTH_BOOK_StyleSectionTab(button)
if not button then return end
button:SetHeight(24)
button:SetScript("OnShow", nil)
end
local function MTH_BOOK_UpdateSectionTabs()
local sectionPets = getglobal("MTH_BOOK_SectionPets")
local sectionFamilies = getglobal("MTH_BOOK_SectionFamilies")
local sectionPetAbilities = getglobal("MTH_BOOK_SectionPetAbilities")
local sectionItems = getglobal("MTH_BOOK_SectionItems")
local sectionNPCs = getglobal("MTH_BOOK_SectionNPCs")
local sectionStable = getglobal("MTH_BOOK_SectionStable")
local sectionPetHistory = getglobal("MTH_BOOK_SectionPetHistory")
local function setState(button, selected)
if not button then return end
if selected then
PanelTemplates_SelectTab(button)
else
PanelTemplates_DeselectTab(button)
end
end
setState(sectionPets, MTH_BOOK_STATE.mode == "pets")
setState(sectionFamilies, MTH_BOOK_STATE.mode == "families")
setState(sectionPetAbilities, MTH_BOOK_STATE.mode == "petabilities")
setState(sectionItems, MTH_BOOK_STATE.mode == "items")
setState(sectionNPCs, MTH_BOOK_STATE.mode == "npcs")
setState(sectionStable, MTH_BOOK_STATE.mode == "stable")
setState(sectionPetHistory, MTH_BOOK_STATE.mode == "pethistory")
end
local function MTH_BOOK_LayoutSectionTabs()
local tabBar = getglobal("MTH_BOOK_TabBar")
local sectionPets = getglobal("MTH_BOOK_SectionPets")
local sectionFamilies = getglobal("MTH_BOOK_SectionFamilies")
local sectionPetAbilities = getglobal("MTH_BOOK_SectionPetAbilities")
local sectionItems = getglobal("MTH_BOOK_SectionItems")
local sectionNPCs = getglobal("MTH_BOOK_SectionNPCs")
local sectionStable = getglobal("MTH_BOOK_SectionStable")
local sectionPetHistory = getglobal("MTH_BOOK_SectionPetHistory")
if not (tabBar and sectionPets and sectionFamilies and sectionPetAbilities and sectionItems and sectionNPCs) then return end
if sectionStable then
sectionStable:ClearAllPoints()
sectionStable:SetPoint("TOPLEFT", tabBar, "TOPLEFT", 0, 0)
end
sectionPetAbilities:ClearAllPoints()
if sectionStable then
sectionPetAbilities:SetPoint("LEFT", sectionStable, "RIGHT", 2, 0)
else
sectionPetAbilities:SetPoint("TOPLEFT", tabBar, "TOPLEFT", 0, 0)
end
sectionPets:ClearAllPoints()
sectionPets:SetPoint("LEFT", sectionPetAbilities, "RIGHT", 2, 0)
sectionFamilies:ClearAllPoints()
sectionFamilies:SetPoint("LEFT", sectionPets, "RIGHT", 2, 0)
sectionNPCs:ClearAllPoints()
sectionNPCs:SetPoint("LEFT", sectionFamilies, "RIGHT", 2, 0)
sectionItems:ClearAllPoints()
sectionItems:SetPoint("LEFT", sectionNPCs, "RIGHT", 2, 0)
if sectionPetHistory then
sectionPetHistory:ClearAllPoints()
sectionPetHistory:SetPoint("LEFT", sectionItems, "RIGHT", 2, 0)
end
end
local function MTH_BOOK_GetFilterWidgets()
return {
search = getglobal("MTH_BOOK_Search"),
min = getglobal("MTH_BOOK_MinLevel"),
max = getglobal("MTH_BOOK_MaxLevel"),
requireVendor = getglobal("MTH_BOOK_RequireVendor"),
requireDrop = getglobal("MTH_BOOK_RequireDrop"),
requireObject = getglobal("MTH_BOOK_RequireObject"),
hideNoAbilities = getglobal("MTH_BOOK_HideNoAbilities"),
hideUnknown = getglobal("MTH_BOOK_HideUnknown"),
abilityDropdown = getglobal("MTH_BOOK_AbilityDropdown"),
rankDropdown = getglobal("MTH_BOOK_RankDropdown"),
npcFunctionDropdown = getglobal("MTH_BOOK_NPCFunctionDropdown"),
npcZoneDropdown = getglobal("MTH_BOOK_NPCZoneDropdown"),
petLearnSourceDropdown = getglobal("MTH_BOOK_PetLearnSourceDropdown"),
itemSubtypeDropdown = getglobal("MTH_BOOK_ItemSubtypeDropdown"),
petOnlyMyLevel = getglobal("MTH_BOOK_PetOnlyMyLevel"),
petInZoneOnly = getglobal("MTH_BOOK_PetInZoneOnly"),
npcInZoneOnly = getglobal("MTH_BOOK_NPCInZoneOnly"),
}
end
local function MTH_BOOK_ResetStateForMode(mode)
MTH_BOOK_STATE.search = ""
MTH_BOOK_STATE.quick = "all"
MTH_BOOK_STATE.minLevel = nil
MTH_BOOK_STATE.maxLevel = nil
MTH_BOOK_STATE.flag1 = false
MTH_BOOK_STATE.flag2 = false
MTH_BOOK_STATE.flag3 = false
MTH_BOOK_STATE.petAbility = "all"
MTH_BOOK_STATE.petRank = "all"
MTH_BOOK_STATE.petLearnSource = "all"
MTH_BOOK_STATE.petOnlyMyLevel = false
MTH_BOOK_STATE.itemOnlyMyLevel = false
MTH_BOOK_STATE.petInZoneOnly = false
MTH_BOOK_STATE.itemSubtype = "all"
MTH_BOOK_STATE.npcFunction = "all"
MTH_BOOK_STATE.npcZone = "all"
MTH_BOOK_STATE.npcInZoneOnly = false
MTH_BOOK_STATE.npcHideNoZone = true
MTH_BOOK_STATE.petHideNoAbilities = false
MTH_BOOK_STATE.petHideUnknown = false
MTH_BOOK_STATE.forcedBeastId = nil
MTH_BOOK_STATE.petLeftOffset = 0
if mode == "pets" then
MTH_BOOK_STATE.petHideNoAbilities = true
MTH_BOOK_STATE.petHideUnknown = true
elseif mode == "families" then
MTH_BOOK_STATE.quick = "all"
elseif mode == "petabilities" then
MTH_BOOK_STATE.petLearnSource = "beast"
MTH_BOOK_STATE.petOnlyMyLevel = true
elseif mode == "items" then
MTH_BOOK_STATE.itemSubtype = "all"
MTH_BOOK_STATE.itemOnlyMyLevel = false
elseif mode == "npcs" then
MTH_BOOK_STATE.flag1, MTH_BOOK_STATE.flag2, MTH_BOOK_STATE.flag3 = MTH_BOOK_GetPlayerReactDefaults()
MTH_BOOK_STATE.npcHideNoZone = true
end
MTH_BOOK_STATE.page = 1
MTH_BOOK_STATE.selectedEntry = nil
MTH_BOOK_STATE.selectedPetRankEntry = nil
MTH_BOOK_STATE.petRankRows = {}
end
local function MTH_BOOK_ApplyStateToWidgets(widgets)
if widgets.search then widgets.search:SetText("") end
if widgets.min then widgets.min:SetText("") end
if widgets.max then widgets.max:SetText("") end
if widgets.requireVendor then widgets.requireVendor:SetChecked(MTH_BOOK_STATE.flag1 and 1 or nil) end
if widgets.requireDrop then widgets.requireDrop:SetChecked(MTH_BOOK_STATE.flag2 and 1 or nil) end
if widgets.requireObject then widgets.requireObject:SetChecked(MTH_BOOK_STATE.flag3 and 1 or nil) end
if widgets.hideNoAbilities then
widgets.hideNoAbilities:SetChecked(MTH_BOOK_STATE.mode == "pets" and MTH_BOOK_STATE.petHideNoAbilities and 1 or nil)
end
if widgets.hideUnknown then
if MTH_BOOK_STATE.mode == "pets" then
widgets.hideUnknown:SetChecked(MTH_BOOK_STATE.petHideUnknown and 1 or nil)
elseif MTH_BOOK_STATE.mode == "npcs" then
widgets.hideUnknown:SetChecked(MTH_BOOK_STATE.npcHideNoZone and 1 or nil)
else
widgets.hideUnknown:SetChecked(nil)
end
end
if widgets.petOnlyMyLevel then
if MTH_BOOK_STATE.mode == "petabilities" then
widgets.petOnlyMyLevel:SetChecked(MTH_BOOK_STATE.petOnlyMyLevel and 1 or nil)
elseif MTH_BOOK_STATE.mode == "items" then
widgets.petOnlyMyLevel:SetChecked(MTH_BOOK_STATE.itemOnlyMyLevel and 1 or nil)
else
widgets.petOnlyMyLevel:SetChecked(nil)
end
end
if widgets.petInZoneOnly then
widgets.petInZoneOnly:SetChecked(MTH_BOOK_STATE.mode == "pets" and MTH_BOOK_STATE.petInZoneOnly and 1 or nil)
end
if widgets.npcInZoneOnly then
widgets.npcInZoneOnly:SetChecked(MTH_BOOK_STATE.mode == "npcs" and MTH_BOOK_STATE.npcInZoneOnly and 1 or nil)
end
end
local function MTH_BOOK_SetMode(mode)
if mode == "abilities" then mode = "pets" end
if MTH_BOOK_STATE.mode == mode then return end
if mode == "families" then
MTH_BOOK_FamiliesTrace("SetMode -> families")
end
MTH_BOOK_STATE.mode = mode
local widgets = MTH_BOOK_GetFilterWidgets()
MTH_BOOK_ResetStateForMode(mode)
MTH_BOOK_ApplyStateToWidgets(widgets)
MTH_BOOK_BuildPetAbilityOptions()
MTH_BOOK_BuildPetRankOptions()
MTH_BOOK_UpdatePetLearnSourceDropdownText()
MTH_BOOK_UpdateModeLabels()
MTH_BOOK_UpdateSectionTabs()
MTH_BOOK_RefreshFilter()
end
function MTH_BOOK_JumpToBeastById(beastId)
local id = tonumber(beastId)
if not id then
return false
end
local beast = MTH_DS_Beasts and MTH_DS_Beasts[id]
if type(beast) ~= "table" then
return false
end
MTH_BOOK_STATE.mode = "pets"
local widgets = MTH_BOOK_GetFilterWidgets()
MTH_BOOK_ResetStateForMode("pets")
MTH_BOOK_STATE.search = tostring(id)
MTH_BOOK_STATE.forcedBeastId = id
MTH_BOOK_ApplyStateToWidgets(widgets)
if widgets.search then widgets.search:SetText(MTH_BOOK_STATE.search) end
MTH_BOOK_BuildPetAbilityOptions()
MTH_BOOK_BuildPetRankOptions()
MTH_BOOK_UpdatePetLearnSourceDropdownText()
MTH_BOOK_UpdateModeLabels()
MTH_BOOK_UpdateSectionTabs()
MTH_BOOK_RefreshFilter()
MTH_BOOK_STATE.selectedEntry = {
beastId = id,
name = beast.name,
}
MTH_BOOK_UpdateResults()
MTH_BOOK_UpdateDetail()
return true
end
local function MTH_BOOK_CreateResultButtons(parent)
for i = 1, MTH_BOOK_MAX_COLS do
local colIndex = i
local headerButton = CreateFrame("Button", nil, parent)
headerButton:RegisterForClicks("LeftButtonUp")
headerButton:SetFrameLevel(parent:GetFrameLevel() + 10)
headerButton:SetScript("OnClick", function()
MTH_BOOK_OnHeaderClick(colIndex)
end)
headerButton:EnableMouse(true)
MTH_BOOK_STATE.headerButtons[i] = headerButton
local header = parent:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
header:SetHeight(14)
header:SetTextColor(1.00, 0.82, 0.00)
MTH_BOOK_STATE.headerCols[i] = header
end
MTH_BOOK_UpdateListHeaders()
local y = -24
for i = 1, MTH_BOOK_MAX_ROWS do
local btn = CreateFrame("Button", "MTH_BOOK_ResultButton" .. i, parent)
btn:RegisterForClicks("LeftButtonUp", "RightButtonUp")
btn:SetPoint("TOPLEFT", parent, "TOPLEFT", 4, y)
btn:SetWidth(556)
btn:SetHeight(19)
btn.entry = nil
btn.cols = {}
local highlight = btn:CreateTexture(nil, "HIGHLIGHT")
highlight:SetAllPoints(btn)
highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
highlight:SetBlendMode("ADD")
highlight:SetAlpha(0.35)
local line = btn:CreateTexture(nil, "BORDER")
line:SetTexture("Interface\\Buttons\\WHITE8X8")
line:SetVertexColor(0.30, 0.30, 0.30, 0.55)
line:SetPoint("BOTTOMLEFT", btn, "BOTTOMLEFT", 2, 0)
line:SetPoint("BOTTOMRIGHT", btn, "BOTTOMRIGHT", -2, 0)
line:SetHeight(1)
for c = 1, MTH_BOOK_MAX_COLS do
local col = btn:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
col:SetHeight(14)
col:SetTextColor(0.86, 0.86, 0.86)
col:SetJustifyH("LEFT")
btn.cols[c] = col
end
btn.bookLinkButton = CreateFrame("Button", nil, btn)
btn.bookLinkButton:Hide()
btn.bookLinkButton:SetScript("OnClick", function()
if this:GetParent() and this:GetParent().entry then
if this:GetParent().entry.beastId then
MTH_BOOK_OpenNPCLink(this:GetParent().entry.beastId)
elseif this:GetParent().entry.npcId then
MTH_BOOK_OpenNPCLink(this:GetParent().entry.npcId)
elseif this:GetParent().entry.itemId then
MTH_BOOK_OpenItemDatabaseLink(this:GetParent().entry.itemId)
end
end
end)
btn.bookLinkButton:SetScript("OnEnter", function()
return
end)
btn.bookLinkButton:SetScript("OnLeave", function()
return
end)
btn.itemLinkButton = CreateFrame("Button", nil, btn)
btn.itemLinkButton:Hide()
btn.itemLinkButton:SetScript("OnClick", nil)
btn.itemLinkButton:SetScript("OnEnter", nil)
btn.itemLinkButton:SetScript("OnLeave", nil)
btn.itemIcon = btn:CreateTexture(nil, "ARTWORK")
btn.itemIcon:SetWidth(14)
btn.itemIcon:SetHeight(14)
btn.itemIcon:Hide()
btn.nameHoverButton = CreateFrame("Button", nil, btn)
btn.nameHoverButton:Hide()
btn.nameHoverButton:SetScript("OnEnter", function()
if this:GetParent() and this:GetParent().entry and this:GetParent().entry.itemId then
MTH_BOOK_ShowItemTooltip(this, this:GetParent().entry.itemId)
end
end)
btn.nameHoverButton:SetScript("OnLeave", function()
MTH_BOOK_HideItemTooltip()
end)
btn.nameHoverButton:SetScript("OnClick", function()
if not this:GetParent() or not this:GetParent().entry then return end
if MTH_BOOK_STATE.mode == "items" and this:GetParent().entry.itemId and type(IsShiftKeyDown) == "function" and IsShiftKeyDown() then
if MTH_BOOK_InsertItemLinkToChat(this:GetParent().entry.itemId) then
return
end
end
MTH_BOOK_STATE.selectedEntry = this:GetParent().entry
MTH_BOOK_UpdateDetail()
if arg1 == "RightButton" then
MTH_BOOK_OpenSelectedBeastOnMap()
MTH_BOOK_TryTargetSelectedEntry()
end
end)
btn.familyAbilityButtons = {}
for chipIndex = 1, 12 do
local chip = CreateFrame("Button", nil, btn)
chip:SetHeight(14)
chip.abilityEntry = nil
chip.abilityTooltipFunc = nil
chip.icon = chip:CreateTexture(nil, "ARTWORK")
chip.icon:SetPoint("LEFT", chip, "LEFT", 0, 0)
chip.icon:SetWidth(12)
chip.icon:SetHeight(12)
chip.text = chip:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
chip.text:SetPoint("LEFT", chip.icon, "RIGHT", 2, 0)
chip.text:SetJustifyH("LEFT")
chip:SetScript("OnEnter", function()
if not this or not this.abilityEntry then return end
if type(this.abilityTooltipFunc) == "function" then
this.abilityTooltipFunc(this, this.abilityEntry)
elseif type(MTH_BOOKTAB_ShowFamilyAbilityTooltip) == "function" then
MTH_BOOKTAB_ShowFamilyAbilityTooltip(this, this.abilityEntry)
end
end)
chip:SetScript("OnLeave", function()
if type(MTH_BOOK_HideSpellTooltip) == "function" then
MTH_BOOK_HideSpellTooltip()
end
end)
chip:Hide()
btn.familyAbilityButtons[chipIndex] = chip
end
btn:SetScript("OnClick", function()
if this.entry then
if MTH_BOOK_STATE.mode == "items" and this.entry.itemId and type(IsShiftKeyDown) == "function" and IsShiftKeyDown() then
if MTH_BOOK_InsertItemLinkToChat(this.entry.itemId) then
return
end
end
MTH_BOOK_STATE.selectedEntry = this.entry
MTH_BOOK_UpdateDetail()
if arg1 == "RightButton" then
MTH_BOOK_OpenSelectedBeastOnMap()
MTH_BOOK_TryTargetSelectedEntry()
end
end
end)
btn:SetScript("OnEnter", function()
return
end)
btn:SetScript("OnLeave", function()
return
end)
MTH_BOOK_STATE.buttons[i] = btn
y = y - 20
end
MTH_BOOK_ApplyColumnLayout(parent)
end
local function MTH_BOOK_ScrollPage(delta)
if MTH_BOOK_STATE.mode == "petabilities" or MTH_BOOK_STATE.mode == "stable" or MTH_BOOK_STATE.mode == "families" then return end
if not delta or delta == 0 then return end
if delta > 0 then
MTH_BOOK_STATE.page = MTH_BOOK_STATE.page - 1
else
MTH_BOOK_STATE.page = MTH_BOOK_STATE.page + 1
end
MTH_BOOK_UpdateResults()
end
local function MTH_BOOK_ResetAllFiltersAndRefresh()
local widgets = MTH_BOOK_GetFilterWidgets()
MTH_BOOK_ResetStateForMode(MTH_BOOK_STATE.mode)
MTH_BOOK_ApplyStateToWidgets(widgets)
MTH_BOOK_BuildPetAbilityOptions()
MTH_BOOK_BuildPetRankOptions()
MTH_BOOK_BuildNPCFunctionOptions()
MTH_BOOK_BuildNPCZoneOptions()
if widgets.abilityDropdown then MTH_BOOK_UpdateAbilityDropdownText() end
if widgets.rankDropdown then MTH_BOOK_UpdateRankDropdownText() end
if widgets.petLearnSourceDropdown then MTH_BOOK_UpdatePetLearnSourceDropdownText() end
if widgets.itemSubtypeDropdown then MTH_BOOK_UpdateItemSubtypeDropdownText() end
if widgets.npcFunctionDropdown or widgets.npcZoneDropdown then MTH_BOOK_UpdateNPCDropdownTexts() end
MTH_BOOK_UpdateModeLabels()
MTH_BOOK_RefreshFilter()
end
local function MTH_BOOK_WireUI(frame)
if frame and frame.SetBackdropColor then
frame:SetBackdropColor(0.05, 0.05, 0.05, 1.00)
frame:SetBackdropBorderColor(0.35, 0.35, 0.35, 1.00)
end
local closeButton = getglobal("MTH_BOOK_CloseButton")
local applyButton = getglobal("MTH_BOOK_ApplyButton")
local resetButton = getglobal("MTH_BOOK_ResetButton")
local sectionPets = getglobal("MTH_BOOK_SectionPets")
local sectionFamilies = getglobal("MTH_BOOK_SectionFamilies")
local sectionPetAbilities = getglobal("MTH_BOOK_SectionPetAbilities")
local sectionItems = getglobal("MTH_BOOK_SectionItems")
local sectionNPCs = getglobal("MTH_BOOK_SectionNPCs")
local sectionStable = getglobal("MTH_BOOK_SectionStable")
local sectionPetHistory = getglobal("MTH_BOOK_SectionPetHistory")
local requireVendor = getglobal("MTH_BOOK_RequireVendor")
local requireDrop = getglobal("MTH_BOOK_RequireDrop")
local requireObject = getglobal("MTH_BOOK_RequireObject")
local abilityDropdown = getglobal("MTH_BOOK_AbilityDropdown")
local rankDropdown = getglobal("MTH_BOOK_RankDropdown")
local petLearnSourceDropdown = getglobal("MTH_BOOK_PetLearnSourceDropdown")
local itemSubtypeDropdown = getglobal("MTH_BOOK_ItemSubtypeDropdown")
local npcFunctionDropdown = getglobal("MTH_BOOK_NPCFunctionDropdown")
local npcZoneDropdown = getglobal("MTH_BOOK_NPCZoneDropdown")
local petBookScanButton = getglobal("MTH_BOOK_PetBookScanButton")
local hideNoAbilities = getglobal("MTH_BOOK_HideNoAbilities")
local hideUnknown = getglobal("MTH_BOOK_HideUnknown")
local petOnlyMyLevel = getglobal("MTH_BOOK_PetOnlyMyLevel")
local petInZoneOnly = getglobal("MTH_BOOK_PetInZoneOnly")
local npcInZoneOnly = getglobal("MTH_BOOK_NPCInZoneOnly")
local showAllOnMapButton = getglobal("MTH_BOOK_ShowAllOnMapButton")
local prevButton = getglobal("MTH_BOOK_PrevButton")
local nextButton = getglobal("MTH_BOOK_NextButton")
local openMapButton = getglobal("MTH_BOOK_OpenMapButton")
local listSlider = getglobal("MTH_BOOK_ListSlider")
local search = getglobal("MTH_BOOK_Search")
local min = getglobal("MTH_BOOK_MinLevel")
local max = getglobal("MTH_BOOK_MaxLevel")
if closeButton then
closeButton:ClearAllPoints()
closeButton:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -8, -8)
closeButton:SetWidth(22)
closeButton:SetHeight(22)
closeButton:SetText("X")
closeButton:SetScript("OnClick", function() this:GetParent():Hide() end)
end
if applyButton then applyButton:SetScript("OnClick", MTH_BOOK_ApplyInputs) end
if resetButton then
resetButton:SetScript("OnClick", MTH_BOOK_ResetAllFiltersAndRefresh)
end
if sectionPets then sectionPets:SetScript("OnClick", function() MTH_BOOK_SetMode("pets") end) end
if sectionFamilies then sectionFamilies:SetScript("OnClick", function() MTH_BOOK_SetMode("families") end) end
if sectionPetAbilities then sectionPetAbilities:SetScript("OnClick", function() MTH_BOOK_SetMode("petabilities") end) end
if sectionItems then sectionItems:SetScript("OnClick", function() MTH_BOOK_SetMode("items") end) end
if sectionNPCs then sectionNPCs:SetScript("OnClick", function() MTH_BOOK_SetMode("npcs") end) end
if sectionStable then sectionStable:SetScript("OnClick", function() MTH_BOOK_SetMode("stable") end) end
if sectionPetHistory then sectionPetHistory:SetScript("OnClick", function() MTH_BOOK_SetMode("pethistory") end) end
MTH_BOOK_StyleSectionTab(sectionPets)
MTH_BOOK_StyleSectionTab(sectionFamilies)
MTH_BOOK_StyleSectionTab(sectionPetAbilities)
MTH_BOOK_StyleSectionTab(sectionItems)
MTH_BOOK_StyleSectionTab(sectionNPCs)
MTH_BOOK_StyleSectionTab(sectionStable)
MTH_BOOK_StyleSectionTab(sectionPetHistory)
MTH_BOOK_LayoutSectionTabs()
for i = 1, 6 do
local filterBtn = getglobal("MTH_BOOK_Filter" .. i)
if filterBtn then
filterBtn:SetScript("OnClick", function() MTH_BOOK_SetQuickFilter(i) end)
end
end
MTH_BOOK_InitFamilyDropdown()
MTH_BOOK_InitAbilityDropdown()
MTH_BOOK_InitRankDropdown()
MTH_BOOK_InitPetLearnSourceDropdown()
MTH_BOOK_InitItemSubtypeDropdown()
MTH_BOOK_InitNPCFunctionDropdown()
if petBookScanButton then
petBookScanButton:SetScript("OnClick", function()
local function getRowCount()
local getNumCrafts = (type(getglobal) == "function" and getglobal("GetNumCrafts")) or (_G and _G["GetNumCrafts"])
if type(getNumCrafts) == "function" then
return tonumber(getNumCrafts()) or 0
end
return 0
end
local function isTrainingVisible()
local beastTraining = (type(getglobal) == "function" and getglobal("BeastTrainingFrame")) or (_G and _G["BeastTrainingFrame"])
local petTraining = (type(getglobal) == "function" and getglobal("PetTrainingFrame")) or (_G and _G["PetTrainingFrame"])
if beastTraining and ((beastTraining.IsVisible and beastTraining:IsVisible()) or (beastTraining.IsShown and beastTraining:IsShown())) then
return true
end
if petTraining and ((petTraining.IsVisible and petTraining:IsVisible()) or (petTraining.IsShown and petTraining:IsShown())) then
return true
end
return false
end
local function runScanNow()
if MTH and MTH.Print then
MTH:Print("Beast Training opened. Running scan...")
end
if SlashCmdList and SlashCmdList.MTH then
SlashCmdList.MTH("trainscan")
end
end
if not isTrainingVisible() then
local castSpellByName = (type(getglobal) == "function" and getglobal("CastSpellByName")) or (_G and _G["CastSpellByName"])
if type(castSpellByName) == "function" then
castSpellByName("Beast Training")
end
end
if isTrainingVisible() then
runScanNow()
return
end
if getRowCount() > 0 then
runScanNow()
return
end
local waitFrame = CreateFrame("Frame")
local elapsed = 0
local done = false
waitFrame:RegisterEvent("PET_TRAINING_SHOW")
waitFrame:SetScript("OnEvent", function()
if done then return end
done = true
this:UnregisterEvent("PET_TRAINING_SHOW")
this:SetScript("OnEvent", nil)
this:SetScript("OnUpdate", nil)
runScanNow()
end)
waitFrame:SetScript("OnUpdate", function()
if done then
this:SetScript("OnUpdate", nil)
return
end
elapsed = elapsed + (arg1 or 0)
local rows = getRowCount()
if rows > 0 then
done = true
this:UnregisterEvent("PET_TRAINING_SHOW")
this:SetScript("OnEvent", nil)
this:SetScript("OnUpdate", nil)
runScanNow()
return
end
if isTrainingVisible() then
done = true
this:UnregisterEvent("PET_TRAINING_SHOW")
this:SetScript("OnEvent", nil)
this:SetScript("OnUpdate", nil)
runScanNow()
return
end
if elapsed >= 6 then
done = true
this:UnregisterEvent("PET_TRAINING_SHOW")
this:SetScript("OnEvent", nil)
this:SetScript("OnUpdate", nil)
if MTH and MTH.Print then
MTH:Print("Could not open Beast Training automatically. Open Beast Training manually.")
end
end
end)
end)
end
if requireVendor then requireVendor:SetScript("OnClick", MTH_BOOK_ApplyInputs) end
if requireDrop then requireDrop:SetScript("OnClick", MTH_BOOK_ApplyInputs) end
if requireObject then requireObject:SetScript("OnClick", MTH_BOOK_ApplyInputs) end
if hideNoAbilities then hideNoAbilities:SetScript("OnClick", MTH_BOOK_ApplyInputs) end
if hideUnknown then hideUnknown:SetScript("OnClick", MTH_BOOK_ApplyInputs) end
if petOnlyMyLevel then petOnlyMyLevel:SetScript("OnClick", MTH_BOOK_ApplyInputs) end
if petInZoneOnly then petInZoneOnly:SetScript("OnClick", MTH_BOOK_ApplyInputs) end
if npcInZoneOnly then npcInZoneOnly:SetScript("OnClick", MTH_BOOK_ApplyInputs) end
if showAllOnMapButton then showAllOnMapButton:SetScript("OnClick", MTH_BOOK_ShowAllFilteredBeastsOnMap) end
if prevButton then
prevButton:SetScript("OnClick", function()
MTH_BOOK_STATE.page = MTH_BOOK_STATE.page - 1
MTH_BOOK_UpdateResults()
end)
end
if nextButton then
nextButton:SetScript("OnClick", function()
MTH_BOOK_STATE.page = MTH_BOOK_STATE.page + 1
MTH_BOOK_UpdateResults()
end)
end
if openMapButton then
openMapButton:SetScript("OnClick", MTH_BOOK_OpenSelectedBeastOnMap)
end
if listSlider then
listSlider:SetMinMaxValues(1, 1)
listSlider:SetValueStep(1)
listSlider:SetValue(1)
listSlider:Show()
local sliderThumb = getglobal("MTH_BOOK_ListSliderThumbTexture")
if sliderThumb then
sliderThumb:SetTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical")
sliderThumb:SetWidth(20)
sliderThumb:SetHeight(24)
end
MTH_BOOK_HideSliderTemplateTexts()
listSlider:SetScript("OnShow", function()
MTH_BOOK_HideSliderTemplateTexts()
end)
listSlider:SetScript("OnMouseDown", function()
MTH_BOOK_STATE.sliderDragging = true
MTH_BOOK_SetSliderFromCursor(this)
end)
listSlider:SetScript("OnMouseUp", function()
MTH_BOOK_SetSliderFromCursor(this)
MTH_BOOK_STATE.sliderDragging = false
end)
listSlider:SetScript("OnUpdate", function()
if MTH_BOOK_STATE.sliderDragging then
if IsMouseButtonDown and not IsMouseButtonDown("LeftButton") then
MTH_BOOK_STATE.sliderDragging = false
else
MTH_BOOK_SetSliderFromCursor(this)
end
end
end)
listSlider:SetScript("OnValueChanged", function()
local value = this:GetValue()
if not value then return end
value = math.floor(value + 0.5)
MTH_BOOK_HideSliderTemplateTexts()
MTH_BOOK_UpdateSliderMarker(this)
if value ~= MTH_BOOK_STATE.page then
MTH_BOOK_STATE.page = value
MTH_BOOK_UpdateResults()
end
end)
MTH_BOOK_UpdateSliderMarker(listSlider)
end
if search then
search:SetAutoFocus(false)
search:SetScript("OnEnterPressed", function() this:ClearFocus(); MTH_BOOK_ApplyInputs() end)
search:SetScript("OnEscapePressed", function() this:ClearFocus() end)
end
if min then
min:SetNumeric(true)
min:SetAutoFocus(false)
min:SetScript("OnEnterPressed", function() this:ClearFocus(); MTH_BOOK_ApplyInputs() end)
min:SetScript("OnEscapePressed", function() this:ClearFocus() end)
end
if max then
max:SetNumeric(true)
max:SetAutoFocus(false)
max:SetScript("OnEnterPressed", function() this:ClearFocus(); MTH_BOOK_ApplyInputs() end)
max:SetScript("OnEscapePressed", function() this:ClearFocus() end)
end
local listParent = getglobal("MTH_BOOK_ListBackdrop")
local topAreaBackdrop = getglobal("MTH_BOOK_TopAreaBackdrop")
local sliderBackdrop = getglobal("MTH_BOOK_ListSliderBackdrop")
local detailParent = getglobal("MTH_BOOK_DetailBackdrop")
if topAreaBackdrop then
topAreaBackdrop:SetBackdropColor(0.10, 0.10, 0.10, 1.00)
topAreaBackdrop:SetBackdropBorderColor(0.28, 0.28, 0.28, 1.00)
topAreaBackdrop:EnableMouse(false)
topAreaBackdrop:SetFrameLevel(1)
end
local topWidgets = {
getglobal("MTH_BOOK_StatsText"),
getglobal("MTH_BOOK_SearchLabel"),
getglobal("MTH_BOOK_MinLabel"),
getglobal("MTH_BOOK_MaxLabel"),
getglobal("MTH_BOOK_Search"),
getglobal("MTH_BOOK_MinLevel"),
getglobal("MTH_BOOK_MaxLevel"),
getglobal("MTH_BOOK_ApplyButton"),
getglobal("MTH_BOOK_ResetButton"),
getglobal("MTH_BOOK_RequireVendor"),
getglobal("MTH_BOOK_RequireDrop"),
getglobal("MTH_BOOK_RequireObject"),
getglobal("MTH_BOOK_AbilityDropdown"),
getglobal("MTH_BOOK_RankDropdown"),
getglobal("MTH_BOOK_PetLearnSourceDropdown"),
getglobal("MTH_BOOK_ItemSubtypeDropdown"),
getglobal("MTH_BOOK_PetBookScanButton"),
getglobal("MTH_BOOK_NPCFunctionDropdown"),
getglobal("MTH_BOOK_NPCZoneDropdown"),
getglobal("MTH_BOOK_HideNoAbilities"),
getglobal("MTH_BOOK_HideUnknown"),
getglobal("MTH_BOOK_PetOnlyMyLevel"),
}
for i = 1, table.getn(topWidgets) do
local widget = topWidgets[i]
if widget and widget.Show then widget:Show() end
end
if listParent then
listParent:SetBackdropColor(0.09, 0.09, 0.09, 1.00)
listParent:SetBackdropBorderColor(0.24, 0.24, 0.24, 1.00)
listParent:SetFrameLevel(2)
if listParent.SetClipsChildren then listParent:SetClipsChildren(true) end
if listSlider then
listSlider:SetFrameStrata("HIGH")
listSlider:SetFrameLevel(listParent:GetFrameLevel() + 8)
end
if sliderBackdrop then
sliderBackdrop:SetFrameStrata("DIALOG")
sliderBackdrop:SetFrameLevel(listParent:GetFrameLevel() + 6)
end
listParent:EnableMouseWheel(true)
listParent:SetScript("OnMouseWheel", function()
MTH_BOOK_ScrollPage(arg1)
end)
MTH_BOOK_CreateResultButtons(listParent)
end
if sliderBackdrop then
sliderBackdrop:SetBackdropColor(0.01, 0.01, 0.01, 1.00)
sliderBackdrop:SetBackdropBorderColor(0.30, 0.30, 0.30, 1.00)
sliderBackdrop:EnableMouse(true)
if listSlider then
sliderBackdrop:SetScript("OnMouseDown", function()
MTH_BOOK_STATE.sliderDragging = true
MTH_BOOK_SetSliderFromCursor(listSlider)
end)
sliderBackdrop:SetScript("OnMouseUp", function()
MTH_BOOK_SetSliderFromCursor(listSlider)
MTH_BOOK_STATE.sliderDragging = false
end)
sliderBackdrop:SetScript("OnUpdate", function()
if MTH_BOOK_STATE.sliderDragging then
if IsMouseButtonDown and not IsMouseButtonDown("LeftButton") then
MTH_BOOK_STATE.sliderDragging = false
else
MTH_BOOK_SetSliderFromCursor(listSlider)
end
end
end)
end
end
local detail = getglobal("MTH_BOOK_DetailBackdropDetailText")
if detail then MTH_BOOK_ConfigureReadOnlyEditBox(detail) end
if detailParent then
detailParent:SetBackdropColor(0.09, 0.09, 0.09, 1.00)
detailParent:SetBackdropBorderColor(0.24, 0.24, 0.24, 1.00)
detailParent:SetFrameLevel(2)
if detailParent.SetClipsChildren then detailParent:SetClipsChildren(true) end
end
if listParent and detailParent then
MTH_BOOK_EnsurePetAbilitiesUI(listParent, detailParent)
MTH_BOOK_SetPetAbilitiesUIVisible(false)
end
MTH_BOOK_UpdateModeLabels()
MTH_BOOK_UpdateListHeaders()
MTH_BOOK_SyncTopAreaColorWithSelectedTab()
MTH_BOOK_UpdateSectionTabs()
MTH_BOOK_UpdateOpenMapButton()
if requireVendor then requireVendor:SetChecked(MTH_BOOK_STATE.flag1 and 1 or nil) end
if requireDrop then requireDrop:SetChecked(MTH_BOOK_STATE.flag2 and 1 or nil) end
if requireObject then requireObject:SetChecked(MTH_BOOK_STATE.flag3 and 1 or nil) end
if hideNoAbilities then hideNoAbilities:SetChecked(MTH_BOOK_STATE.mode == "pets" and MTH_BOOK_STATE.petHideNoAbilities and 1 or nil) end
if hideUnknown then hideUnknown:SetChecked(MTH_BOOK_STATE.mode == "pets" and MTH_BOOK_STATE.petHideUnknown and 1 or nil) end
if petOnlyMyLevel then
if MTH_BOOK_STATE.mode == "petabilities" then
petOnlyMyLevel:SetChecked(MTH_BOOK_STATE.petOnlyMyLevel and 1 or nil)
elseif MTH_BOOK_STATE.mode == "items" then
petOnlyMyLevel:SetChecked(MTH_BOOK_STATE.itemOnlyMyLevel and 1 or nil)
else
petOnlyMyLevel:SetChecked(nil)
end
end
if petInZoneOnly then petInZoneOnly:SetChecked(MTH_BOOK_STATE.mode == "pets" and MTH_BOOK_STATE.petInZoneOnly and 1 or nil) end
if npcInZoneOnly then npcInZoneOnly:SetChecked(MTH_BOOK_STATE.mode == "npcs" and MTH_BOOK_STATE.npcInZoneOnly and 1 or nil) end
end
local function MTH_BOOK_EnsureWindow()
if MTH_BOOK_Browser then return MTH_BOOK_Browser end
local frame = CreateFrame("Frame", "MTH_BOOK_", UIParent, "MTH_BOOK_Template")
if not frame then
MTH_HB_ReportGuard("Failed to create MTH_BOOK_ frame")
return nil
end
if UISpecialFrames then
local already = false
for i = 1, table.getn(UISpecialFrames) do
if UISpecialFrames[i] == "MTH_BOOK_" then
already = true
break
end
end
if not already then
table.insert(UISpecialFrames, "MTH_BOOK_")
end
end
MTH_BOOK_Browser = frame
MTH_BOOK_WireUI(frame)
return frame
end
_G.MTH_BOOK_GetZoneName = MTH_BOOK_GetZoneName
_G.MTH_BOOK_GetPlayerLevelValue = MTH_BOOK_GetPlayerLevelValue
_G.MTH_BOOK_IsSpellInLevelScope = MTH_BOOK_IsSpellInLevelScope
_G.MTH_BOOK_GetScopedRankSummary = MTH_BOOK_GetScopedRankSummary
_G.MTH_BOOK_UpdateResults = MTH_BOOK_UpdateResults
_G.MTH_BOOK_RefreshFilter = MTH_BOOK_RefreshFilter
function MTH_OpenHunterBook()
if not MTH_HB_RequireOpenDeps() then return end
local frame = MTH_BOOK_EnsureWindow()
if not frame then return end
frame:Show()
MTH_BOOK_RefreshFilter()
end
function MTH_ToggleHunterBook()
if not MTH_HB_RequireOpenDeps() then return end
local frame = MTH_BOOK_EnsureWindow()
if not frame then return end
if frame:IsShown() then
frame:Hide()
else
frame:Show()
MTH_BOOK_RefreshFilter()
end
end