Module:Vaults

local p = {}

local utils = require("Module:Utils")

local loreColors = { grail = "fe6150", moth = "f2e9c2", lantern = "ffe300", forge = "ff8e3e", heart = "fe7e8b", edge = "d7dd49", winter = "beeeff", knock = "b54efc", secrethistories = "fe43f0" }

local orderedLocations = { "vaultcapital", "vaultshires", "vaultcontinent", "vaultlandbeyondforest", "vaultrendingmountains", "vaultloneandlevelsands", "vaulteveningisles" }

local locationToFragment = { vaultcapital = "fragmentsecrethistories", vaultshires = "fragmentsecrethistoriesb", vaultcontinent = "fragmentsecrethistoriesc", vaultlandbeyondforest = "fragmentsecrethistoriesd", vaultrendingmountains = "fragmentsecrethistoriese", vaultloneandlevelsands = "fragmentsecrethistoriesf", vaulteveningisles = "fragmentsecrethistoriesg" }

local floatingVaultChance = { {id = "fragmentsecrethistories", chance = 2}, {id = "fragmentsecrethistoriesb", chance = 5}, {id = "fragmentsecrethistoriesc", chance = 10}, {id = "fragmentsecrethistoriesd", chance = 25}, {id = "fragmentsecrethistoriese", chance = 50}, {id = "fragmentsecrethistoriesf", chance = 50}, {id = "fragmentsecrethistoriesg", chance = 50} }

local function renderFragment(fragment) local aspects = mw.loadData("Module:Aspects/data") for aspect, value in pairs(fragment.aspects) do       if loreColors[aspect] then local namePart = string.format(               ' %s ',                aspects[aspect].label,                loreColors[aspect],                fragment.label            ) local fragmentPart = string.format(               ' %s ',                aspects[aspect].label,                loreColors[aspect],                aspects[aspect].label            ) return string.format("%s (%s %s)", namePart, fragmentPart, value) end end end

local function renderLoreAspect(aspect) local aspects = mw.loadData("Module:Aspects/data") return string.format(       ' %s ',        aspects[aspect].label,        loreColors[aspect],        aspects[aspect].label    ) end

local function renderElementLink(element) for aspect in pairs(element.aspects) do       if loreColors[aspect] then return string.format(               ' %s ',                element.label,                loreColors[aspect],                element.label            ) end end

return string.format("%s", element.label) end

local function filterTable(t, f)   local result = {} for k, v in pairs(t) do       if f(k, v) then result[k] = v       end end

return result end

local function mapTableToArray(t, f)   local a = {} for k, v in pairs(t) do       table.insert(a, f(k, v)) end return a end

local function getTableSize(t) local size = 0 for _ in pairs(t) do       size = size + 1 end return size end

local books local function loadBooks if books then return books end

local booksData = mw.loadData("Module:Books/data") local t = {} for k, v in pairs(booksData) do       t[k] = v        if v.translatedId then t[v.translatedId] = v       end end books = t   return t end

local function renderTableVault(t, vault) local obstacles = mw.loadData("Module:Obstacles/data") local book = loadBooks local tools = mw.loadData("Module:Tools/data") local ingredients = mw.loadData("Module:Ingredients/data") local mundane = mw.loadData("Module:Mundane/data") local influences = mw.loadData("Module:Influences/data") local vaultRewards = mw.loadData("Module:Vaults/rewardsData") local locations = mw.loadData("Module:Locations/data")

local first = true local rowspan = getTableSize(vault.obstacles) for _, obstacleId in ipairs(vault.obstacles) do       if first then table.insert(t, '|-style="border-top: 2px solid white;"') table.insert(t, '|rowspan="' .. rowspan .. '"|' .. vault.label .. "") else table.insert(t, "|-") end local obstacle = obstacles[obstacleId] table.insert(t, "|" .. obstacle.label .. "") for _, aspect in ipairs(obstacle.requirements) do           table.insert(t, "|" .. renderLoreAspect(aspect)) end if getTableSize(obstacle.requirements) < 3 then table.insert(t, "|") end if first then first = false local bookLinks = mapTableToArray(               filterTable( vault.rewards, function(id) return books[id] ~= nil end ),               function(id)                    return "" .. books[id].label .. ""                end            ) table.insert(t, '|rowspan="' .. rowspan .. '"|' .. table.concat(bookLinks, " \n"))

local toolLinks = mapTableToArray(               filterTable( vault.rewards, function(id) return tools[id] ~= nil end ),               function(id, amount)                    return renderElementLink(tools[id])                end            ) table.insert(t, '|rowspan="' .. rowspan .. '"|' .. table.concat(toolLinks, " \n"))

local ingredientLinks = mapTableToArray(               filterTable( vault.rewards, function(id) return ingredients[id] ~= nil end ),               function(id, amount)                    local amountPrefix = amount > 1 and (amount .. " ") or ""                   return amountPrefix .. renderElementLink(ingredients[id])                end            ) table.insert(t, '|rowspan="' .. rowspan .. '"|' .. table.concat(ingredientLinks, " \n"))

table.insert(t, '|rowspan="' .. rowspan .. '"|') local otherLinks = mapTableToArray(               filterTable( vault.rewards, function(id) return books[id] == nil and tools[id] == nil and ingredients[id] == nil end ),               function(id, amount)                    local amountPrefix = amount > 1 and (amount .. " ") or ""                   local element = mundane[id] or influences[id] or locations[id]                    if element then                        return amountPrefix .. renderElementLink(element)                    elseif id == "erudition" then                        return "Erudition"                    else                        return amountPrefix .. id                    end                end            ) table.insert(t, table.concat(otherLinks, " \n")) if vault.randomRewards and getTableSize(vault.randomRewards) > 0 then if otherLinks[1] then table.insert(t, " ") end for randomRewardsId, amount in pairs(vault.randomRewards) do                   table.insert(t, amount .. " random") table.insert(t, ' ') local sortedIds = {} for k, v in ipairs(vaultRewards[randomRewardsId].items) do                       sortedIds[k] = v                    end local function getValue(id) return (books[id] and 1) or (tools[id] and 2) or (ingredients[id] and 3) or (mundane[id] and 4) or                           (influences[id] and 5) or                            6 end table.sort(                       sortedIds,                        function(a, b)                            return getValue(a) < getValue(b)                        end                    ) for _, id in ipairs(sortedIds) do                       local element = books[id] or tools[id] or ingredients[id] or mundane[id] or influences[id] if element then table.insert(t, renderElementLink(element) .. " ") else table.insert(t, id .. " ") end end table.insert(t, " ") end end end end end

function p.list(frame) local aspects = mw.loadData("Module:Aspects/data") local vaults = mw.loadData("Module:Vaults/data")

local t = {} table.insert(t, '{| class="wikitable"') table.insert(t, "|+") table.insert(t, "!Location") table.insert(t, "!Obstacles") table.insert(t, '!colspan="3"|Aspects') table.insert(t, "!Books") table.insert(t, "!Tools") table.insert(t, "!Ingredients") table.insert(t, "!Other")

for _, location in ipairs(orderedLocations) do       table.insert(t, "|-") table.insert(t, '!colspan="9"|' .. aspects[location].label .. "") local filteredVaults = mapTableToArray(           filterTable( vaults, function(_, v)                   return v.location == location end ),           function(k, v)                return v            end        ) table.sort(           filteredVaults,            function(a, b)                local ae = a.randomRewards ~= nil                local be = b.randomRewards ~= nil                if be and not ae then                    return true                elseif ae and not be then                    return false                end                return a.label < b.label            end        ) for _, vault in pairs(filteredVaults) do           renderTableVault(t, vault) end end

table.insert(t, "|-") table.insert(t, '!colspan="9"|Floating') for _, vault in pairs(       filterTable( vaults, function(_, v)               return not v.location end )   ) do        renderTableVault(t, vault) end

table.insert(t, "|}")

return table.concat(t, "\n") end

local function renderVaultInfoBox(id, vault) local aspectsData = mw.loadData("Module:Aspects/data") local aspects = { string.format("%s", aspectsData["vault"].label), string.format("%s", aspectsData["location"].label) }   if vault.location then table.insert(aspects, string.format("%s", aspectsData[vault.location].label)) end if vault.unique then table.insert(aspects, "Unique") end return string.format(       ' ',        vault.label,        vault.label,        table.concat(aspects, " "),        id    ) end

function p.byName(frame) local vaults = mw.loadData("Module:Vaults/data") local obstacles = mw.loadData("Module:Obstacles/data") local books = loadBooks local tools = mw.loadData("Module:Tools/data") local ingredients = mw.loadData("Module:Ingredients/data") local mundane = mw.loadData("Module:Mundane/data") local influences = mw.loadData("Module:Influences/data") local vaultRewards = mw.loadData("Module:Vaults/rewardsData") local fragments = mw.loadData("Module:Fragments/data") local locations = mw.loadData("Module:Locations/data")

frame = frame or {args = {}} local pageTitle = frame.args[1] or frame.args["name"] or mw.title.getCurrentTitle.text local extraHeader = frame.args["header"] or ""

-- for debugging; if it's on the module page set the title to something known if pageTitle == "Vaults" then pageTitle = "Hunter's Pits" end

local vaultId, vault = utils.findByLabel(vaults, pageTitle)

local t = {}

table.insert(t, renderVaultInfoBox(vaultId, vault))

table.insert(t, "" .. pageTitle .. " is a Vault. " .. extraHeader)

table.insert(t, "== Text ==") table.insert(t, "* Description:") table.insert(t, "::" .. utils.addReferenceLinks(vault.description)) table.insert(t, "* Start Description:") table.insert(t, "::" .. utils.addReferenceLinks(vault.startDescription)) table.insert(t, "* Success Description:") table.insert(t, "::" .. utils.addReferenceLinks(vault.successDescription)) table.insert(t, "* End Description:") table.insert(t, "::" .. utils.addReferenceLinks(vault.endDescription))

table.insert(t, "== How to acquire ==") if vault.location then local fragmentId = locationToFragment[vault.location] local fragment = fragments[fragmentId] table.insert(t, string.format("It is randomly awarded for exploring %s.", renderFragment(fragment))) if not vault.unique and fragmentId ~= "fragmentsecrethistories" and fragmentId ~= "fragmentsecrethistoriese" then table.insert(               t,                string.format( "\nIt is always awarded for talking to Sulochana Amavasya about %s.", renderFragment(fragment) )           )        end else table.insert(t, "There is a chance to aquire for exploring one of the following fragments:") for _, it in pairs(floatingVaultChance) do           table.insert(t, string.format("* %s: %s%%", renderFragment(fragments[it.id]), it.chance)) end end

table.insert(t, "== Obstacles ==") for _, obstacleId in ipairs(vault.obstacles) do       local obstacle = obstacles[obstacleId] local obstacleRequirements = mapTableToArray(           obstacle.requirements,            function(_, v)                return renderLoreAspect(v)            end        ) table.insert(           t,            string.format( "* %s - overcome with one of: %s", obstacle.label, table.concat(obstacleRequirements, ", ") )       )    end

table.insert(t, "== Rewards ==") local function getSortValue(id) return (locations[id] and 0) or (books[id] and 1) or (tools[id] and 2) or (ingredients[id] and 3) or           (mundane[id] and 4) or            (influences[id] and 5) or            6 end local ids = {} for k, _ in pairs(vault.rewards) do       table.insert(ids, k)    end table.sort(       ids,        function(a, b)            return getSortValue(a) < getSortValue(b)        end    ) local function getRewardType(id) if books[id] ~= nil then return "Book" elseif tools[id] ~= nil then return "Tool" elseif ingredients[id] ~= nil then return "Ingredient" elseif influences[id] ~= nil then return "Influence" elseif locations[id] ~= nil then return "HQ potential location" else return "" end end for _, id in ipairs(ids) do       local element = books[id] or tools[id] or ingredients[id] or mundane[id] or influences[id] or locations[id] local amount = vault.rewards[id] local amountPrefix = amount > 1 and (amount .. " ") or "" if element then local rewardType = getRewardType(id) if rewardType ~= "" then rewardType = string.format(" (%s)", rewardType) end table.insert(t, "* " .. amountPrefix .. renderElementLink(element) .. rewardType) elseif id == "erudition" then table.insert(t, "* Erudition") else table.insert(t, "* " .. amountPrefix .. id) end end if vault.randomRewards and getTableSize(vault.randomRewards) > 0 then for randomRewardsId, amount in pairs(vault.randomRewards) do           table.insert(t, "* " .. amount .. " random") local sortedIds = {} for k, v in ipairs(vaultRewards[randomRewardsId].items) do               sortedIds[k] = v            end table.sort(               sortedIds,                function(a, b)                    return getSortValue(a) < getSortValue(b)                end            ) for _, id in ipairs(sortedIds) do               local element = books[id] or tools[id] or ingredients[id] or mundane[id] or influences[id] if element then table.insert(t, "** " .. renderElementLink(element)) else table.insert(t, "** " .. id) end end end end

table.insert(t, "") table.insert(t, "") table.insert(t, "") if vault.unique then table.insert(t, "") end

return table.concat(t, "\n") end

return p