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

904 lines
29 KiB
Lua

if type(MTH_HUNTERBOOK_TABS) ~= "table" then MTH_HUNTERBOOK_TABS = {} end
MTH_HUNTERBOOK_TABS.petabilities = {
headerLabel = "Pet Abilities",
columnLabels = { "Ability Name", "Ranks", "Families" },
columnLayout = {
{ x = 8, width = 160, align = "LEFT" },
{ x = 170, width = 52, align = "LEFT" },
{ x = 224, width = 328, align = "LEFT" },
},
}
MTH_HUNTERBOOK_TABS.abilities = {
headerLabel = "Pet Abilities",
columnLabels = { "Ability", "Lvl", "Family", "Beast", "Rare" },
columnLayout = {
{ 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" },
},
}
function MTH_BOOK_AbilitySort(a, b)
if a.ability ~= b.ability then return a.ability < b.ability end
if a.level ~= b.level then return a.level < b.level end
if a.name ~= b.name then return a.name < b.name end
return a.beastId < b.beastId
end
function MTH_BOOK_PetAbilitySort(a, b)
local aa = MTH_BOOK_SafeLower(a and a.ability)
local ab = MTH_BOOK_SafeLower(b and b.ability)
if aa ~= ab then return aa < ab end
local ra = tonumber(a and a.rankCount) or 0
local rb = tonumber(b and b.rankCount) or 0
if ra ~= rb then return ra > rb end
local fa = tonumber(a and a.familyCount) or 0
local fb = tonumber(b and b.familyCount) or 0
if fa ~= fb then return fa > fb end
return tostring(a and a.familyList or "") < tostring(b and b.familyList or "")
end
function MTH_BOOK_GetSpellRowsForAbility(abilityName)
if not abilityName or abilityName == "" then return 0 end
if not (MTH_DS_PetSpells and MTH_DS_PetSpells.byAbility) then return 0 end
local row = MTH_DS_PetSpells.byAbility[abilityName]
if not row or not row.spells then return 0 end
return table.getn(row.spells)
end
function MTH_BOOK_GetSpellCoverageForAbility(abilityName)
local coverage = {
ability = abilityName,
icon = nil,
spellRows = 0,
hasBeastLearned = false,
hasTrainerLearned = false,
rankCount = 0,
minRank = nil,
maxRank = nil,
minTrainLevel = nil,
maxTrainLevel = nil,
}
if not abilityName or abilityName == "" then return coverage end
if not (MTH_DS_PetSpells and MTH_DS_PetSpells.byAbility) then return coverage end
local row = MTH_DS_PetSpells.byAbility[abilityName]
if not row or not row.spells then return coverage end
local rankMap = {}
local hasPositiveRank = false
for i = 1, table.getn(row.spells) do
local spell = row.spells[i]
if spell then
local rankNumber = tonumber(spell.rankNumber)
if rankNumber and rankNumber > 0 then
hasPositiveRank = true
break
end
end
end
coverage.spellRows = 0
for i = 1, table.getn(row.spells) do
local spell = row.spells[i]
if spell then
local rankNumber = tonumber(spell.rankNumber)
if hasPositiveRank and ((not rankNumber) or rankNumber <= 0) then
-- Ignore legacy/unranked rows when proper ranked variants exist.
else
coverage.spellRows = coverage.spellRows + 1
local learnMethod = MTH_BOOK_SafeLower(spell.learnMethod)
if learnMethod == "trainer" then
coverage.hasTrainerLearned = true
else
coverage.hasBeastLearned = true
end
if not coverage.icon and spell.icon and spell.icon ~= "" then
coverage.icon = spell.icon
end
if rankNumber and rankNumber > 0 then
rankMap[rankNumber] = true
if not coverage.minRank or rankNumber < coverage.minRank then coverage.minRank = rankNumber end
if not coverage.maxRank or rankNumber > coverage.maxRank then coverage.maxRank = rankNumber end
end
local trainLevel = tonumber(spell.trainLevel)
if trainLevel then
if not coverage.minTrainLevel or trainLevel < coverage.minTrainLevel then coverage.minTrainLevel = trainLevel end
if not coverage.maxTrainLevel or trainLevel > coverage.maxTrainLevel then coverage.maxTrainLevel = trainLevel end
end
end
end
end
for _ in pairs(rankMap) do
coverage.rankCount = coverage.rankCount + 1
end
if coverage.rankCount == 0 and coverage.spellRows > 0 then
coverage.rankCount = 1
end
return coverage
end
function MTH_BOOK_GetKnownSpellMap()
if not MTH_CharSavedVariables then return nil end
if not MTH_CharSavedVariables.petTraining then return nil end
local petTraining = MTH_CharSavedVariables.petTraining
if petTraining.hunterKnownMap and petTraining.spellMap then
for token, isKnown in pairs(petTraining.hunterKnownMap) do
if isKnown == true then
local _, _, baseToken = string.find(tostring(token), "^(.-)#%d+$")
if baseToken and baseToken ~= "" then
local baseRow = petTraining.spellMap[baseToken]
if baseRow and ((tonumber(baseRow.rankNumber) or 0) <= 0) then
baseRow.isKnown = true
end
end
end
end
end
return MTH_CharSavedVariables.petTraining.spellMap
end
function MTH_BOOK_GetKnownRankCountForAbility(abilityName)
local spellMap = MTH_BOOK_GetKnownSpellMap()
if not spellMap or not abilityName or abilityName == "" then return 0 end
local abilityLower = MTH_BOOK_SafeLower(abilityName)
if abilityLower == "" then return 0 end
local knownRanks = {}
for _, row in pairs(spellMap) do
if row and row.name and (row.isKnown ~= false) then
if MTH_BOOK_SafeLower(row.name) == abilityLower then
local rankNumber = tonumber(row.rankNumber) or 0
knownRanks[rankNumber] = true
end
end
end
local count = 0
for _ in pairs(knownRanks) do
count = count + 1
end
return count
end
function MTH_BOOK_IsKnownRankForAbility(abilityName, rankNumber)
local spellMap = MTH_BOOK_GetKnownSpellMap()
if not spellMap then return false end
if not abilityName or abilityName == "" then return false end
local rankValue = tonumber(rankNumber)
local abilityLower = MTH_BOOK_SafeLower(abilityName)
for _, row in pairs(spellMap) do
if row and row.name and (row.isKnown ~= false) then
if MTH_BOOK_SafeLower(row.name) == abilityLower then
local rowRank = tonumber(row.rankNumber)
if rankValue and rankValue > 0 then
if rowRank == rankValue then
return true
end
else
return true
end
end
end
end
return false
end
function MTH_BOOK_BuildPetAbilitiesRows(ignoreSearch)
local spellRows = {}
if MTH_DS_PetSpells and MTH_DS_PetSpells.byAbility then
for abilityName in pairs(MTH_DS_PetSpells.byAbility) do
local ability = tostring(abilityName or "")
if ability ~= "" then
local key = MTH_BOOK_SafeLower(ability)
if key ~= "" then
spellRows[key] = {
ability = ability,
familiesMap = {},
}
end
end
end
end
local function ensureRow(abilityName)
local ability = tostring(abilityName or "")
if ability == "" then return nil end
local key = MTH_BOOK_SafeLower(ability)
if key == "" then return nil end
return spellRows[key], key
end
if MTH_DS_Families then
for familyName, row in pairs(MTH_DS_Families) do
if familyName and familyName ~= "" and row and row.abilities then
for i = 1, table.getn(row.abilities) do
local ability = row.abilities[i]
local spellRow = ensureRow(ability)
if spellRow then
spellRow.familiesMap[familyName] = true
end
end
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 tokens = MTH_BOOK_SplitAbilities(beast.abilities)
for i = 1, table.getn(tokens) do
local _, abilityName = MTH_BOOK_ParseAbilityToken(tokens[i])
local spellRow = ensureRow(abilityName)
if spellRow then
spellRow.familiesMap[beast.family] = true
end
end
end
end
end
local results = {}
for _, row in pairs(spellRows) do
local coverage = MTH_BOOK_GetSpellCoverageForAbility(row.ability)
local families = {}
for familyName in pairs(row.familiesMap or {}) do
table.insert(families, familyName)
end
table.sort(families, function(a, b)
return MTH_BOOK_SafeLower(a) < MTH_BOOK_SafeLower(b)
end)
local rankCount = tonumber(coverage.rankCount) or 0
local knownRankCount = MTH_BOOK_GetKnownRankCountForAbility(row.ability)
local minRank = coverage.minRank
local maxRank = coverage.maxRank
local minTrainLevel = coverage.minTrainLevel
local maxTrainLevel = coverage.maxTrainLevel
if MTH_BOOK_STATE.petOnlyMyLevel then
knownRankCount, rankCount, minRank, maxRank, minTrainLevel, maxTrainLevel = MTH_BOOK_GetScopedRankSummary(row.ability)
end
if knownRankCount > rankCount then knownRankCount = rankCount end
local rankText = tostring(knownRankCount) .. "/" .. tostring(rankCount)
local sourceFilter = tostring(MTH_BOOK_STATE.petLearnSource or "all")
local sourceMatch = true
if sourceFilter == "beast" then
sourceMatch = coverage.hasBeastLearned and true or false
elseif sourceFilter == "trainer" then
sourceMatch = coverage.hasTrainerLearned and true or false
end
local familyList = table.concat(families, ", ")
local searchable = MTH_BOOK_SafeLower(tostring(row.ability or "") .. " " .. familyList)
if sourceMatch and rankCount > 0 and (ignoreSearch or MTH_BOOK_STATE.search == "" or string.find(searchable, MTH_BOOK_STATE.search, 1, true) ~= nil) then
table.insert(results, {
ability = row.ability,
icon = coverage.icon,
knownRankCount = knownRankCount,
rankCount = rankCount,
rankText = rankText,
families = families,
familyCount = table.getn(families),
familyList = familyList,
spellRows = coverage.spellRows or 0,
minRank = minRank,
maxRank = maxRank,
minTrainLevel = minTrainLevel,
maxTrainLevel = maxTrainLevel,
hasBeastLearned = coverage.hasBeastLearned,
hasTrainerLearned = coverage.hasTrainerLearned,
})
end
end
table.sort(results, MTH_BOOK_PetAbilitySort)
return results
end
function MTH_BOOK_BuildPetAbilityRankRows(entry)
local rows = {}
if not entry or not entry.ability then return rows end
if not (MTH_DS_PetSpells and MTH_DS_PetSpells.byAbility) then return rows end
local spellBucket = MTH_DS_PetSpells.byAbility[entry.ability]
if not spellBucket or not spellBucket.spells then return rows end
local hasPositiveRank = false
for i = 1, table.getn(spellBucket.spells) do
local spell = spellBucket.spells[i]
if spell then
local rankNumber = tonumber(spell.rankNumber)
if rankNumber and rankNumber > 0 then
hasPositiveRank = true
break
end
end
end
for i = 1, table.getn(spellBucket.spells) do
local spell = spellBucket.spells[i]
if spell 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 hasPositiveRank and ((not rankNumber) or rankNumber <= 0) then
-- Ignore legacy/unranked rows when proper ranked variants exist.
elseif MTH_BOOK_IsSpellInLevelScope(tonumber(spell.trainLevel)) then
table.insert(rows, {
id = spell.id,
ability = entry.ability,
icon = spell.icon or spell.iconName or spell.texture or spell.iconTexture or entry.icon,
rankNumber = rankNumber,
isKnown = MTH_BOOK_IsKnownRankForAbility(entry.ability, rankNumber),
trainLevel = tonumber(spell.trainLevel),
description = spell.description,
cost = spell.cost,
castTime = spell.castTime,
range = spell.range,
school = spell.school,
effects = spell.effects,
sourceUrl = spell.sourceUrl,
})
end
end
end
table.sort(rows, function(a, b)
local ra = a.rankNumber or 0
local rb = b.rankNumber or 0
if ra ~= rb then return ra < rb end
local la = a.trainLevel or 0
local lb = b.trainLevel or 0
if la ~= lb then return la < lb end
return (tonumber(a.id) or 0) < (tonumber(b.id) or 0)
end)
return rows
end
function MTH_BOOK_GetRankLabel(rankNumber, includePrefix)
local rankValue = tonumber(rankNumber)
if rankValue and rankValue > 0 then
if includePrefix then
return "Rank " .. tostring(rankValue)
end
return tostring(rankValue)
end
if includePrefix then
return "Unranked"
end
return "None"
end
function MTH_BOOKTAB_EnsurePetAbilitiesUI(listParent, detailParent)
if MTH_BOOK_STATE.petUI then return end
if not listParent or not detailParent then return end
local ui = {}
ui.leftPane = CreateFrame("Frame", nil, listParent)
ui.leftPane:SetPoint("TOPLEFT", listParent, "TOPLEFT", 4, -4)
ui.leftPane:SetWidth(162)
ui.leftPane:SetHeight(346)
ui.rightPane = CreateFrame("Frame", nil, listParent)
ui.rightPane:SetPoint("TOPLEFT", ui.leftPane, "TOPRIGHT", 8, 0)
ui.rightPane:SetWidth(390)
ui.rightPane:SetHeight(346)
ui.vSplit = listParent:CreateTexture(nil, "BORDER")
ui.vSplit:SetTexture("Interface\\Buttons\\WHITE8X8")
ui.vSplit:SetVertexColor(0.30, 0.30, 0.30, 0.60)
ui.vSplit:SetPoint("TOPLEFT", ui.leftPane, "TOPRIGHT", 4, -2)
ui.vSplit:SetPoint("BOTTOMLEFT", ui.leftPane, "BOTTOMRIGHT", 4, 2)
ui.vSplit:SetWidth(1)
ui.leftHeaderAbility = ui.leftPane:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
ui.leftHeaderAbility:SetPoint("TOPLEFT", ui.leftPane, "TOPLEFT", 24, -6)
ui.leftHeaderAbility:SetWidth(102)
ui.leftHeaderAbility:SetJustifyH("LEFT")
ui.leftHeaderAbility:SetTextColor(1.00, 0.82, 0.00)
ui.leftHeaderAbility:SetText("Ability")
ui.leftHeaderRank = ui.leftPane:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
ui.leftHeaderRank:SetPoint("TOPLEFT", ui.leftPane, "TOPLEFT", 126, -6)
ui.leftHeaderRank:SetWidth(28)
ui.leftHeaderRank:SetJustifyH("LEFT")
ui.leftHeaderRank:SetTextColor(1.00, 0.82, 0.00)
ui.leftHeaderRank:SetText("K/T")
ui.rightHeaderRank = ui.rightPane:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
ui.rightHeaderRank:SetPoint("TOPLEFT", ui.rightPane, "TOPLEFT", 2, -6)
ui.rightHeaderRank:SetWidth(36)
ui.rightHeaderRank:SetJustifyH("LEFT")
ui.rightHeaderRank:SetTextColor(1.00, 0.82, 0.00)
ui.rightHeaderRank:SetText("Rank")
ui.rightHeaderLevel = ui.rightPane:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
ui.rightHeaderKnown = ui.rightPane:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
ui.rightHeaderKnown:SetPoint("TOPLEFT", ui.rightPane, "TOPLEFT", 34, -6)
ui.rightHeaderKnown:SetWidth(22)
ui.rightHeaderKnown:SetJustifyH("LEFT")
ui.rightHeaderKnown:SetTextColor(1.00, 0.82, 0.00)
ui.rightHeaderKnown:SetText("K?")
ui.rightHeaderLevel:SetPoint("TOPLEFT", ui.rightPane, "TOPLEFT", 58, -6)
ui.rightHeaderLevel:SetWidth(40)
ui.rightHeaderLevel:SetJustifyH("LEFT")
ui.rightHeaderLevel:SetTextColor(1.00, 0.82, 0.00)
ui.rightHeaderLevel:SetText("Lvl")
ui.rightHeaderDesc = ui.rightPane:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
ui.rightHeaderDesc:SetPoint("TOPLEFT", ui.rightPane, "TOPLEFT", 98, -6)
ui.rightHeaderDesc:SetWidth(286)
ui.rightHeaderDesc:SetJustifyH("LEFT")
ui.rightHeaderDesc:SetTextColor(1.00, 0.82, 0.00)
ui.rightHeaderDesc:SetText("Description")
ui.leftRowsVisible = 20
ui.leftScroll = CreateFrame("Slider", "MTH_BOOK_PetLeftScroll", ui.leftPane, "UIPanelScrollBarTemplate")
ui.leftScroll:SetPoint("TOPRIGHT", ui.leftPane, "TOPRIGHT", -2, -22)
ui.leftScroll:SetPoint("BOTTOMRIGHT", ui.leftPane, "BOTTOMRIGHT", -2, 20)
ui.leftScroll:SetWidth(16)
if not getglobal("MTH_BOOK_PetLeftScrollScrollFrame") then
local leftScrollShim = CreateFrame("ScrollFrame", "MTH_BOOK_PetLeftScrollScrollFrame", ui.leftPane)
leftScrollShim:SetPoint("TOPLEFT", ui.leftPane, "TOPLEFT", 0, 0)
leftScrollShim:SetWidth(1)
leftScrollShim:SetHeight(1)
leftScrollShim:Hide()
end
ui.leftScroll:SetScript("OnValueChanged", function()
local val = this:GetValue() or 0
val = math.floor(val + 0.5)
if val ~= MTH_BOOK_STATE.petLeftOffset then
MTH_BOOK_STATE.petLeftOffset = val
MTH_BOOK_UpdatePetAbilitiesLists()
end
end)
ui.leftScroll:SetMinMaxValues(0, 0)
ui.leftScroll:SetValueStep(1)
ui.leftScroll:SetValue(0)
ui.leftPane:EnableMouseWheel(true)
ui.leftPane:SetScript("OnMouseWheel", function()
local delta = arg1 or 0
if delta == 0 then return end
local current = tonumber(MTH_BOOK_STATE.petLeftOffset or 0) or 0
if delta < 0 then
current = current + 1
else
current = current - 1
end
if current < 0 then current = 0 end
local maxOffset = 0
if MTH_BOOK_STATE.results then
maxOffset = math.max(0, table.getn(MTH_BOOK_STATE.results) - table.getn(ui.leftButtons or {}))
end
if current > maxOffset then current = maxOffset end
MTH_BOOK_STATE.petLeftOffset = current
if ui.leftScroll then
ui.leftScroll:SetValue(current)
end
MTH_BOOK_UpdatePetAbilitiesLists()
end)
ui.leftButtons = {}
local leftY = -24
for i = 1, ui.leftRowsVisible do
local btn = CreateFrame("Button", nil, ui.leftPane)
btn:SetPoint("TOPLEFT", ui.leftPane, "TOPLEFT", 0, leftY)
btn:SetWidth(144)
btn:SetHeight(19)
btn.entry = nil
btn.selected = btn:CreateTexture(nil, "BACKGROUND")
btn.selected:SetAllPoints(btn)
btn.selected:SetTexture("Interface\\Buttons\\WHITE8X8")
btn.selected:SetVertexColor(0.18, 0.35, 0.55, 0.35)
btn.selected:Hide()
local hl = btn:CreateTexture(nil, "HIGHLIGHT")
hl:SetAllPoints(btn)
hl:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
hl:SetBlendMode("ADD")
hl:SetAlpha(0.30)
btn.ability = btn:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
btn.ability:SetPoint("LEFT", btn, "LEFT", 24, 0)
btn.ability:SetWidth(100)
btn.ability:SetJustifyH("LEFT")
btn.rank = btn:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
btn.rank:SetPoint("LEFT", btn, "LEFT", 126, 0)
btn.rank:SetWidth(26)
btn.rank:SetJustifyH("LEFT")
btn.icon = btn:CreateTexture(nil, "ARTWORK")
btn.icon:SetPoint("LEFT", btn, "LEFT", 2, 0)
btn.icon:SetWidth(16)
btn.icon:SetHeight(16)
btn:SetScript("OnClick", function()
if not this.entry then return end
MTH_BOOK_STATE.selectedEntry = this.entry
MTH_BOOK_STATE.selectedPetRankEntry = nil
MTH_BOOK_STATE.petRankRows = MTH_BOOK_BuildPetAbilityRankRows(this.entry)
MTH_BOOK_UpdateResults()
end)
btn:SetScript("OnEnter", function()
if this and this.entry then
MTH_BOOK_ShowBaselineTooltip(this, this.entry)
end
end)
btn:SetScript("OnLeave", function()
MTH_BOOK_HideSpellTooltip()
end)
ui.leftButtons[i] = btn
leftY = leftY - 20
end
local footerParent = listParent:GetParent() or listParent
ui.recapText = footerParent:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
ui.recapText:SetPoint("TOPLEFT", footerParent, "TOPLEFT", 20, -530)
ui.recapText:SetWidth(190)
ui.recapText:SetJustifyH("LEFT")
ui.recapText:SetTextColor(1.00, 0.82, 0.00)
ui.recapText:SetText("Abilities 0 | Known 0/0")
ui.progressBackdrop = CreateFrame("Frame", nil, footerParent)
ui.progressBackdrop:SetPoint("LEFT", ui.recapText, "RIGHT", 8, 0)
ui.progressBackdrop:SetWidth(320)
ui.progressBackdrop:SetHeight(14)
ui.progressBackdrop:SetFrameLevel(footerParent:GetFrameLevel() + 3)
ui.progressBackdrop:SetBackdrop({
bgFile = "Interface\\Buttons\\WHITE8X8",
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
tile = true,
tileSize = 8,
edgeSize = 8,
insets = { left = 2, right = 2, top = 2, bottom = 2 },
})
ui.progressBackdrop:SetBackdropColor(0.08, 0.08, 0.08, 0.95)
ui.progressBackdrop:SetBackdropBorderColor(0.24, 0.24, 0.24, 0.90)
ui.progressBar = CreateFrame("StatusBar", nil, ui.progressBackdrop)
ui.progressBar:SetPoint("TOPLEFT", ui.progressBackdrop, "TOPLEFT", 2, -2)
ui.progressBar:SetPoint("BOTTOMRIGHT", ui.progressBackdrop, "BOTTOMRIGHT", -2, 2)
ui.progressBar:SetStatusBarTexture("Interface\\Buttons\\WHITE8X8")
ui.progressBar:SetStatusBarColor(0.18, 0.75, 0.22, 0.9)
ui.progressBar:SetMinMaxValues(0, 1)
ui.progressBar:SetValue(0)
ui.progressText = ui.progressBackdrop:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
ui.progressText:SetPoint("CENTER", ui.progressBackdrop, "CENTER", 0, 0)
ui.progressText:SetTextColor(1.00, 1.00, 1.00)
ui.progressText:SetText("0%")
ui.rightButtons = {}
local rightRowsVisible = 10
local rightRowHeight = 36
local rightRowStep = 37
local rightY = -24
for i = 1, rightRowsVisible do
local btn = CreateFrame("Button", nil, ui.rightPane)
btn:SetPoint("TOPLEFT", ui.rightPane, "TOPLEFT", 0, rightY)
btn:SetWidth(388)
btn:SetHeight(rightRowHeight)
btn.entry = nil
btn.selected = btn:CreateTexture(nil, "BACKGROUND")
btn.selected:SetAllPoints(btn)
btn.selected:SetTexture("Interface\\Buttons\\WHITE8X8")
btn.selected:SetVertexColor(0.18, 0.35, 0.55, 0.35)
btn.selected:Hide()
local hl = btn:CreateTexture(nil, "HIGHLIGHT")
hl:SetAllPoints(btn)
hl:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
hl:SetBlendMode("ADD")
hl:SetAlpha(0.28)
btn.rank = btn:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
btn.rank:SetPoint("LEFT", btn, "LEFT", 2, 1)
btn.rank:SetWidth(30)
btn.rank:SetJustifyH("LEFT")
btn.knownIcon = btn:CreateTexture(nil, "ARTWORK")
btn.knownIcon:SetPoint("LEFT", btn, "LEFT", 38, 1)
btn.knownIcon:SetWidth(12)
btn.knownIcon:SetHeight(12)
btn.knownIcon:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
btn.knownIcon:SetVertexColor(0.18, 0.90, 0.18, 1.00)
btn.knownIcon:Hide()
btn.level = btn:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
btn.level:SetPoint("LEFT", btn, "LEFT", 58, 1)
btn.level:SetWidth(40)
btn.level:SetJustifyH("LEFT")
btn.desc = btn:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
btn.desc:SetPoint("LEFT", btn, "LEFT", 98, 1)
btn.desc:SetWidth(286)
btn.desc:SetJustifyH("LEFT")
btn:SetScript("OnClick", function()
if not this.entry then return end
MTH_BOOK_STATE.selectedPetRankEntry = this.entry
MTH_BOOK_UpdateDetail()
MTH_BOOK_UpdateResults()
end)
btn:SetScript("OnEnter", function()
if this and this.entry then
MTH_BOOK_ShowRankTooltip(this, this.entry)
end
end)
btn:SetScript("OnLeave", function()
MTH_BOOK_HideSpellTooltip()
end)
ui.rightButtons[i] = btn
rightY = rightY - rightRowStep
end
ui.detailTitleTop = detailParent:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
ui.detailTitleTop:SetPoint("TOPLEFT", detailParent, "TOPLEFT", 8, -8)
ui.detailTitleTop:SetWidth(120)
ui.detailTitleTop:SetJustifyH("LEFT")
ui.detailTitleTop:SetTextColor(1.00, 0.82, 0.00)
ui.detailTitleTop:SetText("Spell baseline")
ui.detailTop = CreateFrame("EditBox", nil, detailParent)
ui.detailTop:SetMultiLine(true)
ui.detailTop:SetAutoFocus(false)
ui.detailTop:SetPoint("TOPLEFT", ui.detailTitleTop, "BOTTOMLEFT", 0, -4)
ui.detailTop:SetWidth(120)
ui.detailTop:SetHeight(132)
ui.detailTopIcon = detailParent:CreateTexture(nil, "ARTWORK")
ui.detailTopIcon:SetPoint("TOPRIGHT", ui.detailTop, "TOPRIGHT", -4, -4)
ui.detailTopIcon:SetWidth(16)
ui.detailTopIcon:SetHeight(16)
ui.detailTopIcon:Hide()
ui.detailTitleBottom = detailParent:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
ui.detailTitleBottom:SetPoint("TOPLEFT", ui.detailTop, "BOTTOMLEFT", 0, -8)
ui.detailTitleBottom:SetWidth(120)
ui.detailTitleBottom:SetJustifyH("LEFT")
ui.detailTitleBottom:SetTextColor(1.00, 0.82, 0.00)
ui.detailTitleBottom:SetText("Current Rank")
ui.detailBottom = CreateFrame("EditBox", nil, detailParent)
ui.detailBottom:SetMultiLine(true)
ui.detailBottom:SetAutoFocus(false)
ui.detailBottom:SetPoint("TOPLEFT", ui.detailTitleBottom, "BOTTOMLEFT", 0, -4)
ui.detailBottom:SetWidth(120)
ui.detailBottom:SetHeight(116)
MTH_BOOK_ConfigureReadOnlyEditBox(ui.detailTop)
MTH_BOOK_ConfigureReadOnlyEditBox(ui.detailBottom)
if ui.detailTop.SetTextColor then ui.detailTop:SetTextColor(1.00, 1.00, 1.00) end
if ui.detailBottom.SetTextColor then ui.detailBottom:SetTextColor(1.00, 1.00, 1.00) end
MTH_BOOK_STATE.petUI = ui
end
function MTH_BOOKTAB_SetPetAbilitiesUIVisible(visible)
local ui = MTH_BOOK_STATE.petUI
if not ui then return end
local detail = getglobal("MTH_BOOK_DetailBackdropDetailText")
if detail then
if visible then detail:Hide() else detail:Show() end
end
local widgets = {
ui.leftPane,
ui.leftScroll,
ui.rightPane,
ui.vSplit,
ui.leftHeaderAbility,
ui.leftHeaderRank,
ui.rightHeaderRank,
ui.rightHeaderKnown,
ui.rightHeaderLevel,
ui.rightHeaderDesc,
ui.recapText,
ui.progressBackdrop,
ui.detailTop,
ui.detailBottom,
ui.detailTitleTop,
ui.detailTitleBottom,
}
for i = 1, table.getn(widgets) do
local widget = widgets[i]
if widget and widget.Show and widget.Hide then
if visible then widget:Show() else widget:Hide() end
end
end
if ui.detailTopIcon and not visible then
ui.detailTopIcon:Hide()
end
if not visible then
MTH_BOOK_HideSpellTooltip()
end
end
function MTH_BOOKTAB_UpdatePetAbilitiesLists()
local ui = MTH_BOOK_STATE.petUI
if not ui then return end
local resultCount = table.getn(MTH_BOOK_STATE.results)
local visibleRows = table.getn(ui.leftButtons)
local maxOffset = math.max(0, resultCount - visibleRows)
if MTH_BOOK_STATE.petLeftOffset < 0 then MTH_BOOK_STATE.petLeftOffset = 0 end
if MTH_BOOK_STATE.petLeftOffset > maxOffset then MTH_BOOK_STATE.petLeftOffset = maxOffset end
if ui.leftScroll then
ui.leftScroll:SetMinMaxValues(0, maxOffset)
ui.leftScroll:SetValueStep(1)
ui.leftScroll:SetValue(MTH_BOOK_STATE.petLeftOffset)
local upButton = getglobal("MTH_BOOK_PetLeftScrollScrollUpButton")
local downButton = getglobal("MTH_BOOK_PetLeftScrollScrollDownButton")
if upButton then
if MTH_BOOK_STATE.petLeftOffset > 0 then
upButton:EnableMouse(true)
upButton:SetAlpha(1)
else
upButton:EnableMouse(false)
upButton:SetAlpha(0.35)
end
end
if downButton then
if MTH_BOOK_STATE.petLeftOffset < maxOffset then
downButton:EnableMouse(true)
downButton:SetAlpha(1)
else
downButton:EnableMouse(false)
downButton:SetAlpha(0.35)
end
end
if maxOffset > 0 then
ui.leftScroll:SetAlpha(1)
ui.leftScroll:Show()
else
ui.leftScroll:SetAlpha(1)
ui.leftScroll:Hide()
end
end
local startIndex = MTH_BOOK_STATE.petLeftOffset + 1
for i = 1, visibleRows do
local btn = ui.leftButtons[i]
if btn then
local rowIndex = startIndex + i - 1
local entry = MTH_BOOK_STATE.results[rowIndex]
btn.entry = entry
if entry then
if btn.icon then
if entry.icon and entry.icon ~= "" then
if string.find(entry.icon, "\\", 1, true) then
btn.icon:SetTexture(entry.icon)
else
btn.icon:SetTexture("Interface\\Icons\\" .. tostring(entry.icon))
end
btn.icon:Show()
else
btn.icon:Hide()
end
end
btn.ability:SetText(tostring(entry.ability or "?"))
btn.rank:SetText(tostring(entry.rankText or ""))
btn.ability:SetTextColor(0.92, 0.92, 0.92)
btn.rank:SetTextColor(0.92, 0.92, 0.92)
if btn.icon then btn.icon:SetVertexColor(1, 1, 1, 1) end
if MTH_BOOK_STATE.selectedEntry and MTH_BOOK_STATE.selectedEntry.ability == entry.ability then
btn.selected:Show()
else
btn.selected:Hide()
end
btn:Show()
else
if btn.icon then btn.icon:Hide() end
btn.ability:SetText("")
btn.rank:SetText("")
btn.selected:Hide()
btn:Hide()
end
end
end
local totalKnown = 0
local totalRanks = 0
for i = 1, resultCount do
local entry = MTH_BOOK_STATE.results[i]
if entry then
totalKnown = totalKnown + (tonumber(entry.knownRankCount) or 0)
totalRanks = totalRanks + (tonumber(entry.rankCount) or 0)
end
end
if ui.recapText then
ui.recapText:SetText("Abilities " .. tostring(resultCount) .. " | Known " .. tostring(totalKnown) .. "/" .. tostring(totalRanks))
end
if ui.progressBar then
ui.progressBar:SetMinMaxValues(0, math.max(1, totalRanks))
ui.progressBar:SetValue(totalKnown)
end
if ui.progressText then
local pct = 0
if totalRanks > 0 then
pct = math.floor((totalKnown / totalRanks) * 100 + 0.5)
end
ui.progressText:SetText(tostring(pct) .. "%")
end
if MTH_BOOK_STATE.selectedEntry then
local keep = false
for i = 1, table.getn(MTH_BOOK_STATE.results) do
local row = MTH_BOOK_STATE.results[i]
if row and row.ability == MTH_BOOK_STATE.selectedEntry.ability then
MTH_BOOK_STATE.selectedEntry = row
keep = true
break
end
end
if not keep then
MTH_BOOK_STATE.selectedEntry = nil
MTH_BOOK_STATE.selectedPetRankEntry = nil
end
end
MTH_BOOK_STATE.petRankRows = MTH_BOOK_BuildPetAbilityRankRows(MTH_BOOK_STATE.selectedEntry)
for i = 1, table.getn(ui.rightButtons) do
local btn = ui.rightButtons[i]
if btn then
local entry = MTH_BOOK_STATE.petRankRows[i]
btn.entry = entry
if entry then
btn.rank:SetText(MTH_BOOK_GetRankLabel(entry.rankNumber, false))
if btn.knownIcon then
if entry.isKnown then
btn.knownIcon:Show()
else
btn.knownIcon:Hide()
end
end
btn.level:SetText(entry.trainLevel and tostring(entry.trainLevel) or "-")
btn.desc:SetText(tostring(entry.description or "-"))
if MTH_BOOK_STATE.selectedPetRankEntry and MTH_BOOK_STATE.selectedPetRankEntry.id == entry.id then
btn.selected:Show()
else
btn.selected:Hide()
end
btn:Show()
else
btn.rank:SetText("")
if btn.knownIcon then btn.knownIcon:Hide() end
btn.level:SetText("")
btn.desc:SetText("")
btn.selected:Hide()
btn:Hide()
end
end
end
end