Advent of Ascension Wiki

The wiki asks that you give your feedback about the wiki and the mod in this quick poll.

READ MORE

Advent of Ascension Wiki
Advertisement
Advent of Ascension Wiki

This module implements Template:LootTable.


local p = {}

-- Background colours of pool blocks in template
local poolColours = {
    "#EEEEEE",
    "#FEEFCD",
    "#E8F3D8",
    "#EAE9E1",
    "#F9E6FF",
    "#F6FFCC",
    "#E6FFEE",
    "#FFE6E6",
    "#E6FCFF",
    "#F2F2F2"
}

-- Default table titles by loot table type for easy lookup
local tableTypeTitles = {
    advancement_entity = "Rewards",
    advancement_reward = "Rewards",
    command = "Rewards",
    barter = "Barter results",
    block = "Block drops",
    chest = "Chest loot",
    empty = "No loot",
    entity = "Entity loot",
    fishing = "Fishing loot",
    generic = "Unique drops",
    gift = "Gifts",
    selector = "Unique drops"
}

-- Parse loot entries from text to in-memory data.
local function parseLootEntries(args)
    local pools = {} -- Container for nested tables which represent each pool
    local poolWeights = {} -- Container for each pool's loot entry weights for calculation

    -- Default values for optional additional columns
    pools.hasNotes = false;
    pools.hasLooting = false;

    -- Loop over pools to parse data, caps at 10 pools to prevent malicious wiki editing
    for poolIndex = 1, 10 do
        local poolData = args["pool" .. poolIndex]

        -- End pool parsing when reaching non-existent pool
        if not poolData then
            break
        else
            local pool = {}
            poolWeights[poolIndex] = 0

            -- Prep base pool data and variables
            pool.items = {}
            pool.poolNumber = poolIndex
            pool.rolls = args["rolls" .. poolIndex] or "1"
            pool.bonusRolls = args["bonusrolls" .. poolIndex]
            pool.notes = args["notes" .. poolIndex]

            -- Append newline indicator to poolData so the following loop can identify lines properly
            poolData = poolData .. "\n"

            -- Loop over pool data line by line, delineating by newline markers
            for line in string.gmatch(poolData, "[^\r\n]+[\r\n]") do
                local entry = {}

                -- Split entry lines into data groups of approximate format key:value
                for key, value in string.gmatch(line, "([%a]+)%s*:%s*(.-)%s*[;\r\n]") do
                    if value ~= "" then
                        entry[key:lower()] = value
                    end
                end

                -- Ensure a weight value is present for calculation purposes in numeric format
                -- Update table-wide variables based on current entry
                entry.weight = tonumber(entry.weight or 1) or 1
                poolWeights[poolIndex] = poolWeights[poolIndex] + entry.weight
                pools.hasLooting = pools.hasLooting or entry.looting ~= nil
                pools.hasNotes = pools.hasNotes or entry.notes ~= nil

                table.insert(pool.items, entry)
            end

            table.insert(pools, pool)
        end
    end

    return pools, poolWeights
end

local function generateLootLines(pools, poolWeights, columnCount)
    local output = {}

    -- Loop over pools in pool collection for individual formatting
    for _, pool in ipairs(pools) do
        local backgroundColour = poolColours[pool.poolNumber] or ""

        if backgroundColour ~= "" then
            backgroundColour = "background-color:" .. backgroundColour .. ";"
        end

        -- Loop over entries in current pool for individual formatting
        for _, entry in ipairs(pool.items) do
            -- Prep base variables for entry
            local itemLink = "Nothing"
            local quantity = entry.quantity or "-"
            local looting = ""
            local notes = ""
            local chance = "100%"

            -- Skip empty entries
            if entry.item ~= nil and string.lower(entry.item) ~= "nothing" then
                local image = entry.image or (entry.item .. ".png")
                local imageLink = ""

                -- Process image link with formatting
                if image:lower() ~= "none" then
                    imageLink = "[[File:" .. image .. "|" .. (entry.imagesize or "32px") .. "|link=" .. entry.item .. "]]"
                end

                -- Compile item link with processed image link
                itemLink = imageLink .. "[[" .. entry.item .. "]]"
            end

            -- Format looting column value if applicable
            if entry.looting then
                looting = " || +" .. entry.looting .. " per level"
            elseif pools.hasLooting then
                looting = " || -"
            end

            -- Format chance column value if applicable, calculated by entry's weight over the total pool weight
            if entry.weight and poolWeights[pool.poolNumber] then
                chance = string.format("%.1f", (entry.weight / poolWeights[pool.poolNumber]) * 100) .. "%"
            end

            -- Add notes if applicable or empty column value if required
            if entry.notes then
                notes = " || style=\"text-align:left;\" | " .. entry.notes
            elseif pools.hasNotes then
                notes = " || "
            end

            table.insert(output, "|- style=\"text-align:center;" .. backgroundColour .. "\"") -- Add colour to entry row
            table.insert(output, "| " .. itemLink .. " || " .. quantity .. looting .. " || " .. chance .. notes) -- Insert formatted data for entry
        end

        local poolDescription = "| colspan=" .. columnCount .. " | " -- Begin bottom row text

        -- Add background colour to pool if applicable
        if backgroundColour ~= "" then
            table.insert(output, "|- style=\"" .. backgroundColour .. "\"")
        else
            table.insert(output, "|-")
        end

        -- Begin adding pool roll count to description
        poolDescription = poolDescription .. "The above pool is rolled "

        if pool.rolls == "1" then
            poolDescription = poolDescription .. "1 time"
        else
            poolDescription = poolDescription .. pool.rolls .. " times"
        end

        -- Add bonus rolls text to pool description if applicable
        if pool.bonusRolls then
            poolDescription = poolDescription .. ", with an additional "

            if pool.bonusRolls == "1" then
                poolDescription = poolDescription .. "roll per point of [[mcw:Luck|Luck]]"
            else
                poolDescription = poolDescription .. pool.bonusRolls .. " rolls per point of [[mcw:Luck|Luck]]"
            end
        end

        -- Add notes if present in pool data
        if pool.notes then
            poolDescription = poolDescription .. "<br/>" .. pool.notes
        end

        table.insert(output, poolDescription)
    end

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

function p.lootTable(frame)
    local data = frame

    -- Process arguments from template block on page
    if frame == mw.getCurrentFrame() then
        data = require("Module:ProcessArgs").merge(true)
    else
        frame = mw.getCurrentFrame()
    end

    -- Prep base data for final printout
    local columnCount = 3
    local linesOut = {} -- Container for per-line text for output
    local pools, poolWeights = parseLootEntries(data)
    local title = ""
    local columnHeader = "|-\n! Item !! Quantity !! " -- Start column header line with base columns

    -- Set default value to table type titles. This acts as a safety if we somehow have an invalid table type
    setmetatable(tableTypeTitles, {__index = function() return "Unique drops" end})

    -- Set table title based on specified title in template or default for loot table type
    title = data.title or tableTypeTitles[data.type]

    -- Add looting column if required
    if pools.hasLooting then
        columnHeader = columnHeader .. frame:expandTemplate{title = "tooltip", args = {"Looting", "The amount of extra items obtainable with the Looting enchantment."}} .. " !! "
        columnCount = columnCount + 1
    end

    -- Insert chance column
    columnHeader = columnHeader .. "Chance"

    -- Add notes column if required
    if pools.hasNotes then
        columnHeader = columnHeader .. " !! Notes "
        columnCount = columnCount + 1
    end

    -- Append newline and next line starter after columns header line compiled
    columnHeader = columnHeader .. "\n|-"

    -- Compile final output
    table.insert(linesOut, "{| class = \"wikitable loottable\"\n|-")
    table.insert(linesOut, "! colspan = " .. columnCount .. " | " .. title)
    table.insert(linesOut, columnHeader)
    table.insert(linesOut, generateLootLines(pools, poolWeights, columnCount))
    table.insert(linesOut, "|}")

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

return p
Advertisement