Files
MetaHunt/api/hunterbook-tab-trainers.lua
2026-09-11 13:45:58 +02:00

225 lines
10 KiB
Lua

if type(MTH_HUNTERBOOK_TABS) ~= "table" then MTH_HUNTERBOOK_TABS = {} end
local trainerColumns = {
{ x = 28, width = 150, align = "LEFT" },
{ x = 180, width = 62, align = "LEFT" },
{ x = 244, width = 43, align = "LEFT" },
{ x = 289, width = 80, align = "LEFT" },
{ x = 371, width = 105, align = "LEFT" },
{ x = 478, width = 74, align = "LEFT" },
}
MTH_HUNTERBOOK_TABS.hunterspells = {
headerLabel = "Hunter Spells",
columnLabels = { "Spell", "Rank", "Level", "Price", "Branch", "Status" },
columnLayout = trainerColumns,
}
MTH_HUNTERBOOK_TABS.petspells = {
headerLabel = "Pet Spells",
columnLabels = { "Spell", "Rank", "Level", "Price", "Branch", "Status" },
columnLayout = trainerColumns,
}
function MTH_BOOKTAB_IsTrainerSpellMode(mode)
return mode == "hunterspells" or mode == "petspells"
end
local function MTH_BOOKTAB_GetTrainerKind()
if MTH_BOOK_STATE and MTH_BOOK_STATE.mode == "petspells" then return "pet" end
return "hunter"
end
function MTH_BOOKTAB_FormatTrainerCost(copper)
local value = tonumber(copper) or 0
local gold = math.floor(value / 10000)
value = value - gold * 10000
local silver = math.floor(value / 100)
local bronze = value - silver * 100
local parts = {}
if gold > 0 then table.insert(parts, "|cffffd100" .. tostring(gold) .. "g|r") end
if silver > 0 or gold > 0 then table.insert(parts, "|cffc7c7cf" .. tostring(silver) .. "s|r") end
table.insert(parts, "|cffeda55f" .. tostring(bronze) .. "c|r")
return table.concat(parts, " ")
end
function MTH_BOOKTAB_GetTrainerDisplayCost(copper)
if type(MTH_TrainerPlan_GetPrice) == "function" then
return MTH_TrainerPlan_GetPrice({ trainerCost = copper }, MTH_BOOK_STATE and MTH_BOOK_STATE.trainerHonoredDiscount)
end
return tonumber(copper) or 0
end
function MTH_BOOKTAB_GetTrainerSpellStatus(row)
local kind = MTH_BOOKTAB_GetTrainerKind()
local playerLevel = MTH_BOOK_GetPlayerLevelValue and MTH_BOOK_GetPlayerLevelValue() or nil
local status = type(MTH_TrainerPlan_GetStatus) == "function" and MTH_TrainerPlan_GetStatus(kind, row, playerLevel) or "notyet"
if status == "known" then return "Known", "|cff40ff40" end
if status == "notlearned" then return "Not learned", "|cffffa500" end
return "Not yet learnable", "|cffff4040"
end
function MTH_BOOKTAB_BuildTrainerSpellResults()
local results = {}
local kind = MTH_BOOKTAB_GetTrainerKind()
local plan = type(MTH_TrainerPlan_Build) == "function" and MTH_TrainerPlan_Build(kind, {
playerLevel = MTH_BOOK_GetPlayerLevelValue and MTH_BOOK_GetPlayerLevelValue() or nil,
honored = MTH_BOOK_STATE and MTH_BOOK_STATE.trainerHonoredDiscount,
}) or nil
if type(plan) ~= "table" or type(plan.rows) ~= "table" then return results end
local search = MTH_BOOK_SafeLower(MTH_BOOK_STATE.search or "")
for _, planned in ipairs(plan.rows) do
local row = planned.row
local level = tonumber(row.requiredLevel) or 0
local haystack = tostring(row.name or "") .. " " .. tostring(row.rank or "") .. " " .. tostring(row.section or "") .. " " .. tostring(row.description or "")
if type(row.prerequisites) == "table" then
for _, prerequisite in ipairs(row.prerequisites) do
haystack = haystack .. " " .. tostring(prerequisite)
end
end
haystack = MTH_BOOK_SafeLower(haystack)
if (search == "" or string.find(haystack, search, 1, true) ~= nil)
and (not MTH_BOOK_STATE.minLevel or level >= MTH_BOOK_STATE.minLevel)
and (not MTH_BOOK_STATE.maxLevel or level <= MTH_BOOK_STATE.maxLevel)
and (type(MTH_TrainerPlan_MatchesQuick) ~= "function" or MTH_TrainerPlan_MatchesQuick(planned.status, MTH_BOOK_STATE.quick))
then
table.insert(results, row)
end
end
return results
end
function MTH_BOOKTAB_UpdateTrainerPlanPanel(detail)
local parent = detail and detail:GetParent()
if not parent then return end
if not parent.mthTrainerPlan then
local panel = CreateFrame("Frame", nil, parent)
panel:SetPoint("TOPLEFT", parent, "TOPLEFT", 0, -238)
panel:SetWidth(136)
panel:SetHeight(128)
panel:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8X8", edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", tile = true, tileSize = 16, edgeSize = 12, insets = { left = 3, right = 3, top = 3, bottom = 3 } })
panel:SetBackdropColor(0.06, 0.06, 0.06, 1)
panel:SetBackdropBorderColor(0.28, 0.28, 0.28, 1)
panel.text = panel:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
panel.text:SetPoint("TOPLEFT", panel, "TOPLEFT", 7, -7)
panel.text:SetWidth(122)
panel.text:SetJustifyH("LEFT")
panel.text:SetJustifyV("TOP")
parent.mthTrainerPlan = panel
end
local plan = type(MTH_TrainerPlan_Build) == "function" and MTH_TrainerPlan_Build(MTH_BOOKTAB_GetTrainerKind(), {
playerLevel = MTH_BOOK_GetPlayerLevelValue and MTH_BOOK_GetPlayerLevelValue() or nil,
honored = MTH_BOOK_STATE.trainerHonoredDiscount,
}) or nil
if not plan then return end
local nextLevel = plan.nextLevel.level
local nextLabel = "Next"
if nextLevel then nextLabel = "At level " .. tostring(nextLevel) end
local function formatBlock(label, summary)
return "|cffffffff" .. label .. "|r\n"
.. "|cff4da6ff" .. tostring(summary.count) .. "|r |cff9a9a9aspells|r |cffffffff| |r"
.. MTH_BOOKTAB_FormatTrainerCost(summary.cost)
end
parent.mthTrainerPlan.text:SetText("|cffffd100Training Plan|r\n"
.. formatBlock("Now", plan.now)
.. "\n\n" .. formatBlock(nextLabel, plan.nextLevel)
.. "\n\n" .. formatBlock("Remaining", plan.remaining))
parent.mthTrainerPlan:Show()
end
function MTH_BOOKTAB_GetTrainerSpellTotal()
local catalog = MTH_DS_TrainerCatalog
local rows = catalog and catalog[MTH_BOOKTAB_GetTrainerKind()] or nil
return type(rows) == "table" and table.getn(rows) or 0
end
function MTH_BOOKTAB_TrainerSpellSort(a, b)
local al = tonumber(a and a.requiredLevel) or 0
local bl = tonumber(b and b.requiredLevel) or 0
if al ~= bl then return al < bl end
local an = MTH_BOOK_SafeLower(a and a.name)
local bn = MTH_BOOK_SafeLower(b and b.name)
if an ~= bn then return an < bn end
return MTH_BOOK_SafeLower(a and a.rank) < MTH_BOOK_SafeLower(b and b.rank)
end
function MTH_BOOKTAB_GetTrainerSpellSortKey(row, col)
if col == 1 then return MTH_BOOK_SafeLower(row and row.name) end
if col == 2 then return MTH_BOOK_SafeLower(row and row.rank) end
if col == 3 then return tonumber(row and row.requiredLevel) or 0 end
if col == 4 then return tonumber(row and row.trainerCost) or 0 end
if col == 5 then return MTH_BOOK_SafeLower(row and row.section) end
if col == 6 then
local status = MTH_BOOKTAB_GetTrainerSpellStatus(row)
return MTH_BOOK_SafeLower(status)
end
return nil
end
function MTH_BOOKTAB_GetTrainerSpellRowValues(row)
local requiredLevel = tonumber(row and row.requiredLevel) or 0
local playerLevel = MTH_BOOK_GetPlayerLevelValue and MTH_BOOK_GetPlayerLevelValue() or nil
local levelColor = (playerLevel and playerLevel >= requiredLevel) and "|cff40ff40" or "|cffff4040"
local status, statusColor = MTH_BOOKTAB_GetTrainerSpellStatus(row)
return {
tostring(row and row.name or "-"),
tostring(row and row.rank or "-"),
levelColor .. tostring(row and row.requiredLevel or "-") .. "|r",
MTH_BOOKTAB_FormatTrainerCost(MTH_BOOKTAB_GetTrainerDisplayCost(row and row.trainerCost)),
tostring(row and row.section or "-"),
statusColor .. status .. "|r",
}
end
function MTH_BOOKTAB_UpdateTrainerSpellDetail(detail, selected)
if not MTH_BOOKTAB_IsTrainerSpellMode(MTH_BOOK_STATE and MTH_BOOK_STATE.mode) then return false end
MTH_BOOKTAB_UpdateTrainerPlanPanel(detail)
if not selected then
MTH_BOOK_SetDetailText(detail, "|cFFFFD100Trainer Spells|r\n\nSelect a spell rank to inspect its trainer level, undiscounted cost, and prerequisites.")
return true
end
local lines = {}
table.insert(lines, "|cffffff00" .. tostring(selected.name or "Unknown") .. "|r")
if selected.rank and selected.rank ~= "" then table.insert(lines, "|cffaaaaaa" .. tostring(selected.rank) .. "|r") end
table.insert(lines, "")
table.insert(lines, "|cff9a9a9aBranch:|r |cffffffff" .. tostring(selected.section or "-") .. "|r")
local requiredLevel = tonumber(selected.requiredLevel) or 0
local playerLevel = MTH_BOOK_GetPlayerLevelValue and MTH_BOOK_GetPlayerLevelValue() or nil
local levelColor = (playerLevel and playerLevel >= requiredLevel) and "|cff40ff40" or "|cffff4040"
table.insert(lines, "|cff9a9a9aRequired Level:|r " .. levelColor .. tostring(selected.requiredLevel or "-") .. "|r")
local status, statusColor = MTH_BOOKTAB_GetTrainerSpellStatus(selected)
table.insert(lines, "|cff9a9a9aStatus:|r " .. statusColor .. status .. "|r")
table.insert(lines, "|cff9a9a9aBase Price:|r " .. MTH_BOOKTAB_FormatTrainerCost(selected.trainerCost))
table.insert(lines, "|cff9a9a9aHonored Price:|r " .. MTH_BOOKTAB_FormatTrainerCost(math.floor((tonumber(selected.trainerCost) or 0) * 0.90)))
if type(selected.prerequisites) == "table" and table.getn(selected.prerequisites) > 0 then
table.insert(lines, "")
table.insert(lines, "|cffffd100Prerequisites|r")
for _, prerequisite in ipairs(selected.prerequisites) do
table.insert(lines, " " .. tostring(prerequisite))
end
end
if selected.description and selected.description ~= "" then
table.insert(lines, "")
table.insert(lines, "|cffffd100Description|r")
table.insert(lines, "|cffffffff " .. tostring(selected.description) .. "|r")
end
local detailFrame = detail.mthTrainerDetailParent or detail:GetParent()
if not detail.mthTrainerIcon then
detail.mthTrainerIcon = detail:CreateTexture(nil, "ARTWORK")
detail.mthTrainerIcon:SetWidth(28)
detail.mthTrainerIcon:SetHeight(28)
end
detail.mthTrainerIcon:SetParent(detail)
detail.mthTrainerIcon:ClearAllPoints()
detail.mthTrainerIcon:SetPoint("TOPLEFT", detail, "TOPLEFT", 0, 0)
detail.mthTrainerIcon:SetTexture(MTH_BOOK_ResolveIconPath(selected.icon) or "Interface\\Icons\\INV_Misc_QuestionMark")
detail.mthTrainerIcon:Show()
if detail.SetTextInsets then detail:SetTextInsets(4, 4, 36, 4) end
if not detail.mthTrainerDetailScroll then
detail:ClearAllPoints()
detail:SetPoint("TOPLEFT", detailFrame, "TOPLEFT", 8, -42)
detail:SetWidth(detailFrame:GetWidth() - 16)
end
MTH_BOOK_SetDetailText(detail, table.concat(lines, "\n"))
return true
end