mirror of
https://codeberg.org/Duvelcorp/MetaHunt.git
synced 2026-09-25 09:06:07 +00:00
440 lines
14 KiB
Lua
440 lines
14 KiB
Lua
if type(MTH_HUNTERBOOK_TABS) ~= "table" then MTH_HUNTERBOOK_TABS = {} end
|
|
|
|
MTH_HUNTERBOOK_TABS.families = {
|
|
headerLabel = "Families",
|
|
columnLabels = { "Family", "Named", "Coords", "Abilities", "Diet" },
|
|
columnLayout = {
|
|
{ x = 10, width = 106, align = "LEFT" },
|
|
{ x = 122, width = 52, align = "LEFT" },
|
|
{ x = 176, width = 52, align = "LEFT" },
|
|
{ x = 232, width = 364, align = "LEFT" },
|
|
{ x = 532, width = 112, align = "LEFT" },
|
|
},
|
|
}
|
|
|
|
local function MTH_BOOKTAB_FamiliesTrace(message)
|
|
return
|
|
end
|
|
|
|
local function MTH_BOOKTAB_FamiliesSafeLower(value)
|
|
return string.lower(tostring(value or ""))
|
|
end
|
|
|
|
local function MTH_BOOKTAB_FamiliesTrim(value)
|
|
local text = tostring(value or "")
|
|
text = string.gsub(text, "^%s+", "")
|
|
text = string.gsub(text, "%s+$", "")
|
|
return text
|
|
end
|
|
|
|
local function MTH_BOOKTAB_ShouldDisplayAllDiet(familyName)
|
|
local token = MTH_BOOKTAB_FamiliesSafeLower(MTH_BOOKTAB_FamiliesTrim(familyName))
|
|
return token == "bears" or token == "boars"
|
|
end
|
|
|
|
local function MTH_BOOKTAB_FindAbilityBundle(abilityName)
|
|
if not (MTH_DS_PetSpells and type(MTH_DS_PetSpells.byAbility) == "table") then
|
|
return nil
|
|
end
|
|
local direct = MTH_DS_PetSpells.byAbility[abilityName]
|
|
if type(direct) == "table" then
|
|
return direct
|
|
end
|
|
local wanted = MTH_BOOKTAB_FamiliesSafeLower(abilityName)
|
|
for key, bundle in pairs(MTH_DS_PetSpells.byAbility) do
|
|
if MTH_BOOKTAB_FamiliesSafeLower(key) == wanted then
|
|
return bundle
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
function MTH_BOOKTAB_BuildFamiliesRows()
|
|
local results = {}
|
|
local families = MTH_DS_Families
|
|
if type(families) ~= "table" then
|
|
return results
|
|
end
|
|
|
|
local abilityCounts = {}
|
|
local canonicalMap = {}
|
|
|
|
for _, familyRow in pairs(families) do
|
|
if type(familyRow) == "table" and type(familyRow.abilities) == "table" then
|
|
local seenInFamily = {}
|
|
for i = 1, table.getn(familyRow.abilities) do
|
|
local rawName = MTH_BOOKTAB_FamiliesTrim(familyRow.abilities[i])
|
|
if rawName ~= "" then
|
|
local bundle = MTH_BOOKTAB_FindAbilityBundle(rawName)
|
|
local canonical = rawName
|
|
if type(bundle) == "table" and type(bundle.ability) == "string" and bundle.ability ~= "" then
|
|
canonical = bundle.ability
|
|
end
|
|
local token = MTH_BOOKTAB_FamiliesSafeLower(canonical)
|
|
if token ~= "" and not seenInFamily[token] then
|
|
seenInFamily[token] = true
|
|
abilityCounts[token] = (abilityCounts[token] or 0) + 1
|
|
canonicalMap[token] = canonical
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
for familyName, familyRow in pairs(families) do
|
|
if type(familyRow) == "table" then
|
|
local abilities = {}
|
|
local seen = {}
|
|
|
|
if type(familyRow.abilities) == "table" then
|
|
for i = 1, table.getn(familyRow.abilities) do
|
|
local rawName = MTH_BOOKTAB_FamiliesTrim(familyRow.abilities[i])
|
|
if rawName ~= "" then
|
|
local bundle = MTH_BOOKTAB_FindAbilityBundle(rawName)
|
|
local canonical = rawName
|
|
if type(bundle) == "table" and type(bundle.ability) == "string" and bundle.ability ~= "" then
|
|
canonical = bundle.ability
|
|
end
|
|
|
|
local token = MTH_BOOKTAB_FamiliesSafeLower(canonical)
|
|
if token ~= "" and not seen[token] then
|
|
seen[token] = true
|
|
local spellRows = (type(bundle) == "table" and type(bundle.spells) == "table") and bundle.spells or {}
|
|
local firstAnySpell = nil
|
|
local firstBeastSpell = nil
|
|
local beastRankMin = nil
|
|
local beastRankMax = nil
|
|
local beastRankMap = {}
|
|
local anyRankMin = nil
|
|
local anyRankMax = nil
|
|
local anyRankMap = {}
|
|
for s = 1, table.getn(spellRows) do
|
|
local spell = spellRows[s]
|
|
if type(spell) == "table" then
|
|
if not firstAnySpell then
|
|
firstAnySpell = spell
|
|
end
|
|
local rank = tonumber(spell.rankNumber)
|
|
if rank and rank > 0 then
|
|
anyRankMap[rank] = true
|
|
if not anyRankMin or rank < anyRankMin then anyRankMin = rank end
|
|
if not anyRankMax or rank > anyRankMax then anyRankMax = rank end
|
|
end
|
|
if MTH_BOOKTAB_FamiliesSafeLower(spell.learnMethod or "beast") ~= "trainer" then
|
|
if not firstBeastSpell then
|
|
firstBeastSpell = spell
|
|
end
|
|
if rank and rank > 0 then
|
|
beastRankMap[rank] = true
|
|
if not beastRankMin or rank < beastRankMin then beastRankMin = rank end
|
|
if not beastRankMax or rank > beastRankMax then beastRankMax = rank end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local displaySpell = firstBeastSpell or firstAnySpell
|
|
local rankMap = beastRankMap
|
|
local rankMin = beastRankMin
|
|
local rankMax = beastRankMax
|
|
if not firstBeastSpell then
|
|
rankMap = anyRankMap
|
|
rankMin = anyRankMin
|
|
rankMax = anyRankMax
|
|
end
|
|
|
|
local rankCount = 0
|
|
for _ in pairs(rankMap) do
|
|
rankCount = rankCount + 1
|
|
end
|
|
|
|
table.insert(abilities, {
|
|
name = canonicalMap[token] or canonical,
|
|
token = token,
|
|
isUnique = (abilityCounts[token] or 0) == 1,
|
|
icon = displaySpell and displaySpell.icon or nil,
|
|
description = displaySpell and displaySpell.description or "",
|
|
rankMin = rankMin,
|
|
rankMax = rankMax,
|
|
rankCount = rankCount,
|
|
})
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
table.sort(abilities, function(a, b)
|
|
if a.isUnique ~= b.isUnique then
|
|
return a.isUnique and true or false
|
|
end
|
|
return MTH_BOOKTAB_FamiliesSafeLower(a.name) < MTH_BOOKTAB_FamiliesSafeLower(b.name)
|
|
end)
|
|
|
|
local dietText = ""
|
|
if MTH_BOOKTAB_ShouldDisplayAllDiet(familyName) then
|
|
dietText = "ALL"
|
|
else
|
|
local dietItems = {}
|
|
if type(familyRow.food) == "table" then
|
|
for i = 1, table.getn(familyRow.food) do
|
|
local food = MTH_BOOKTAB_FamiliesTrim(familyRow.food[i])
|
|
if food ~= "" then
|
|
table.insert(dietItems, string.upper(string.sub(food, 1, 1)) .. string.sub(food, 2))
|
|
end
|
|
end
|
|
table.sort(dietItems, function(a, b)
|
|
return MTH_BOOKTAB_FamiliesSafeLower(a) < MTH_BOOKTAB_FamiliesSafeLower(b)
|
|
end)
|
|
end
|
|
dietText = table.concat(dietItems, ", ")
|
|
end
|
|
|
|
table.insert(results, {
|
|
family = tostring(familyName),
|
|
named = tonumber(familyRow.named) or 0,
|
|
coords = tonumber(familyRow.coords) or 0,
|
|
abilities = abilities,
|
|
dietText = dietText,
|
|
})
|
|
end
|
|
end
|
|
|
|
table.sort(results, function(a, b)
|
|
return MTH_BOOKTAB_FamiliesSafeLower(a.family) < MTH_BOOKTAB_FamiliesSafeLower(b.family)
|
|
end)
|
|
|
|
return results
|
|
end
|
|
|
|
function MTH_BOOKTAB_ShowFamilyAbilityTooltip(anchor, abilityEntry)
|
|
if not anchor or type(abilityEntry) ~= "table" then return end
|
|
local tooltip = MTH_BOOK_GetSpellTooltip and MTH_BOOK_GetSpellTooltip() or GameTooltip
|
|
if not tooltip then return end
|
|
|
|
tooltip:SetOwner(anchor, "ANCHOR_RIGHT")
|
|
tooltip:ClearLines()
|
|
if MTH_BOOK_SetSpellTooltipIcon then
|
|
MTH_BOOK_SetSpellTooltipIcon(tooltip, abilityEntry.icon)
|
|
end
|
|
tooltip:AddLine(tostring(abilityEntry.name or "Unknown"), 1.00, 0.82, 0.00)
|
|
tooltip:AddLine(" ")
|
|
tooltip:AddLine("Baseline", 1.00, 0.82, 0.00)
|
|
if abilityEntry.rankCount and abilityEntry.rankCount > 0 then
|
|
if abilityEntry.rankMin and abilityEntry.rankMax then
|
|
if abilityEntry.rankMin == abilityEntry.rankMax then
|
|
tooltip:AddDoubleLine("Ranks", tostring(abilityEntry.rankMin), 0.85, 0.85, 0.85, 1, 1, 1)
|
|
else
|
|
tooltip:AddDoubleLine("Ranks", tostring(abilityEntry.rankMin) .. "-" .. tostring(abilityEntry.rankMax), 0.85, 0.85, 0.85, 1, 1, 1)
|
|
end
|
|
end
|
|
else
|
|
tooltip:AddDoubleLine("Ranks", "Unranked", 0.85, 0.85, 0.85, 1, 1, 1)
|
|
end
|
|
tooltip:AddDoubleLine("Family-Unique", abilityEntry.isUnique and "Yes" or "No", 0.85, 0.85, 0.85, 1, 1, 1)
|
|
if abilityEntry.description and abilityEntry.description ~= "" then
|
|
tooltip:AddLine(" ")
|
|
tooltip:AddLine(tostring(abilityEntry.description), 0.90, 0.90, 0.90, true)
|
|
end
|
|
tooltip:Show()
|
|
end
|
|
|
|
function MTH_BOOKTAB_EnsureFamiliesUI()
|
|
if MTH_BOOK_STATE.familiesUI then return end
|
|
local listParent = getglobal("MTH_BOOK_ListBackdrop")
|
|
if not listParent then
|
|
MTH_BOOKTAB_FamiliesTrace("EnsureFamiliesUI failed: missing MTH_BOOK_ListBackdrop")
|
|
return
|
|
end
|
|
|
|
local ui = {}
|
|
ui.frame = CreateFrame("Frame", nil, listParent)
|
|
ui.frame:SetPoint("TOPLEFT", listParent, "TOPLEFT", 6, -6)
|
|
ui.frame:SetPoint("BOTTOMRIGHT", listParent, "BOTTOMRIGHT", -6, 6)
|
|
ui.frame:Hide()
|
|
|
|
ui.headerFamily = ui.frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
|
ui.headerFamily:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 4, -2)
|
|
ui.headerFamily:SetTextColor(1.00, 0.82, 0.00)
|
|
ui.headerFamily:SetText("Family")
|
|
|
|
ui.headerNamed = ui.frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
|
ui.headerNamed:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 122, -2)
|
|
ui.headerNamed:SetTextColor(1.00, 0.82, 0.00)
|
|
ui.headerNamed:SetText("Named")
|
|
|
|
ui.headerCoords = ui.frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
|
ui.headerCoords:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 176, -2)
|
|
ui.headerCoords:SetTextColor(1.00, 0.82, 0.00)
|
|
ui.headerCoords:SetText("Coords")
|
|
|
|
ui.headerAbilities = ui.frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
|
ui.headerAbilities:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 232, -2)
|
|
ui.headerAbilities:SetTextColor(1.00, 0.82, 0.00)
|
|
ui.headerAbilities:SetText("Abilities")
|
|
|
|
ui.headerDiet = ui.frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
|
ui.headerDiet:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 532, -2)
|
|
ui.headerDiet:SetTextColor(1.00, 0.82, 0.00)
|
|
ui.headerDiet:SetText("Diet")
|
|
|
|
ui.rows = {}
|
|
for i = 1, 28 do
|
|
local row = CreateFrame("Frame", nil, ui.frame)
|
|
row:SetHeight(18)
|
|
if i == 1 then
|
|
row:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 0, -18)
|
|
row:SetPoint("TOPRIGHT", ui.frame, "TOPRIGHT", 0, -18)
|
|
else
|
|
row:SetPoint("TOPLEFT", ui.rows[i - 1], "BOTTOMLEFT", 0, -1)
|
|
row:SetPoint("TOPRIGHT", ui.rows[i - 1], "BOTTOMRIGHT", 0, -1)
|
|
end
|
|
|
|
row.family = row:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
|
row.family:SetPoint("LEFT", row, "LEFT", 4, 0)
|
|
row.family:SetWidth(106)
|
|
row.family:SetJustifyH("LEFT")
|
|
|
|
row.named = row:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
|
row.named:SetPoint("LEFT", row, "LEFT", 122, 0)
|
|
row.named:SetWidth(52)
|
|
row.named:SetJustifyH("LEFT")
|
|
|
|
row.coords = row:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
|
row.coords:SetPoint("LEFT", row, "LEFT", 176, 0)
|
|
row.coords:SetWidth(52)
|
|
row.coords:SetJustifyH("LEFT")
|
|
|
|
row.diet = row:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
|
row.diet:SetPoint("LEFT", row, "LEFT", 532, 0)
|
|
row.diet:SetWidth(112)
|
|
row.diet:SetJustifyH("LEFT")
|
|
|
|
row.abilityButtons = {}
|
|
for b = 1, 16 do
|
|
local button = CreateFrame("Button", nil, row)
|
|
button:SetHeight(14)
|
|
button.icon = button:CreateTexture(nil, "ARTWORK")
|
|
button.icon:SetPoint("LEFT", button, "LEFT", 0, 0)
|
|
button.icon:SetWidth(12)
|
|
button.icon:SetHeight(12)
|
|
button.text = button:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
|
button.text:SetPoint("LEFT", button.icon, "RIGHT", 2, 0)
|
|
button.text:SetJustifyH("LEFT")
|
|
button.text:SetTextColor(0.90, 0.90, 0.90)
|
|
button.entry = nil
|
|
button:SetScript("OnEnter", function()
|
|
if this and this.entry then
|
|
MTH_BOOKTAB_ShowFamilyAbilityTooltip(this, this.entry)
|
|
end
|
|
end)
|
|
button:SetScript("OnLeave", function()
|
|
if type(MTH_BOOK_HideSpellTooltip) == "function" then
|
|
MTH_BOOK_HideSpellTooltip()
|
|
end
|
|
end)
|
|
button:Hide()
|
|
row.abilityButtons[b] = button
|
|
end
|
|
|
|
row.divider = row:CreateTexture(nil, "BORDER")
|
|
row.divider:SetTexture("Interface\\Buttons\\WHITE8X8")
|
|
row.divider:SetVertexColor(0.28, 0.28, 0.28, 0.45)
|
|
row.divider:SetPoint("BOTTOMLEFT", row, "BOTTOMLEFT", 0, 0)
|
|
row.divider:SetPoint("BOTTOMRIGHT", row, "BOTTOMRIGHT", 0, 0)
|
|
row.divider:SetHeight(1)
|
|
|
|
ui.rows[i] = row
|
|
end
|
|
|
|
MTH_BOOK_STATE.familiesUI = ui
|
|
MTH_BOOKTAB_FamiliesTrace("EnsureFamiliesUI created rows=" .. tostring(table.getn(ui.rows or {})))
|
|
end
|
|
|
|
function MTH_BOOKTAB_SetFamiliesUIVisible(visible)
|
|
local ui = MTH_BOOK_STATE.familiesUI
|
|
if visible then
|
|
if not ui then
|
|
MTH_BOOKTAB_EnsureFamiliesUI()
|
|
ui = MTH_BOOK_STATE.familiesUI
|
|
end
|
|
if not ui then return end
|
|
else
|
|
if not ui then return end
|
|
end
|
|
|
|
local listParent = getglobal("MTH_BOOK_ListBackdrop")
|
|
local detailParent = getglobal("MTH_BOOK_DetailBackdrop")
|
|
local detailText = getglobal("MTH_BOOK_DetailBackdropDetailText")
|
|
local openMapButton = getglobal("MTH_BOOK_OpenMapButton")
|
|
|
|
if visible then
|
|
if listParent then listParent:Show() end
|
|
if detailParent then detailParent:Hide() end
|
|
if detailText then detailText:Hide() end
|
|
if openMapButton then openMapButton:Hide() end
|
|
ui.frame:Show()
|
|
else
|
|
ui.frame:Hide()
|
|
if listParent then listParent:Show() end
|
|
if detailParent then detailParent:Show() end
|
|
if detailText then detailText:Show() end
|
|
end
|
|
end
|
|
|
|
function MTH_BOOKTAB_RenderFamiliesList()
|
|
local ui = MTH_BOOK_STATE.familiesUI
|
|
if not ui then return end
|
|
local rows = MTH_BOOK_STATE.results or {}
|
|
MTH_BOOKTAB_FamiliesTrace("RenderFamiliesList rows=" .. tostring(table.getn(rows)))
|
|
|
|
for i = 1, table.getn(ui.rows) do
|
|
local rowFrame = ui.rows[i]
|
|
local row = rows[i]
|
|
if row then
|
|
rowFrame:Show()
|
|
rowFrame.family:SetText(tostring(row.family or "-"))
|
|
rowFrame.named:SetText(tostring(row.named or 0))
|
|
rowFrame.coords:SetText(tostring(row.coords or 0))
|
|
rowFrame.diet:SetText(tostring(row.dietText or "-"))
|
|
|
|
local offsetX = 232
|
|
local abilityMaxRight = 526
|
|
for b = 1, table.getn(rowFrame.abilityButtons) do
|
|
local button = rowFrame.abilityButtons[b]
|
|
local ability = row.abilities and row.abilities[b] or nil
|
|
if ability then
|
|
local nameText = tostring(ability.name or "")
|
|
if b < table.getn(row.abilities) then
|
|
nameText = nameText .. ","
|
|
end
|
|
button.entry = ability
|
|
button.text:SetText(nameText)
|
|
local textW = button.text:GetStringWidth() or 40
|
|
if textW < 24 then textW = 24 end
|
|
local buttonWidth = 14 + textW
|
|
if (offsetX + buttonWidth) > abilityMaxRight then
|
|
button.entry = nil
|
|
button:Hide()
|
|
else
|
|
button:SetWidth(buttonWidth)
|
|
button:ClearAllPoints()
|
|
button:SetPoint("LEFT", rowFrame, "LEFT", offsetX, 0)
|
|
local iconPath = ability.icon and MTH_BOOK_ResolveIconPath and MTH_BOOK_ResolveIconPath(ability.icon) or nil
|
|
if iconPath then
|
|
button.icon:SetTexture(iconPath)
|
|
else
|
|
button.icon:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark")
|
|
end
|
|
button:Show()
|
|
offsetX = offsetX + button:GetWidth() + 6
|
|
end
|
|
else
|
|
button.entry = nil
|
|
button:Hide()
|
|
end
|
|
end
|
|
else
|
|
rowFrame:Hide()
|
|
end
|
|
end
|
|
end |