Difference between revisions of "Module:Loot table"
Jump to navigation
Jump to search
Demcookies (talk | contribs) (Feature sort rows/drops from specific leagues to the bottom and darken their background. Initial sort by rarity) |
Demcookies (talk | contribs) (Update split main, junk and league drops to seperate tables. Add captions to the tables. Change Vendor value from single item value to quantity * value range.) |
||
| Line 44: | Line 44: | ||
end | end | ||
| − | + | ---Finds the first item in the drop table that matches the given item ID. | |
| − | + | ---@param drop table The drop table from Module:Loot/data. | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | ---Finds the first item in the | ||
| − | ---@param | ||
---@param id string|number The ID of the item to find. | ---@param id string|number The ID of the item to find. | ||
---@return Item|nil The item data, or nil if the item is not found. | ---@return Item|nil The item data, or nil if the item is not found. | ||
---@return string|nil # The monsterId where the item was found ("-1" for locations), or nil if the item is not found. | ---@return string|nil # The monsterId where the item was found ("-1" for locations), or nil if the item is not found. | ||
---@return string|nil # The locationId where the item was found, or nil if the item is not found. | ---@return string|nil # The locationId where the item was found, or nil if the item is not found. | ||
| − | local function getFirstLootMatch( | + | local function getFirstLootMatch(drop, id) |
id = tostring(id) | id = tostring(id) | ||
| − | for locationId, location in pairs( | + | for locationId, location in pairs(drop) do |
for sourceId, source in pairs(location) do | for sourceId, source in pairs(location) do | ||
for _, item in ipairs(source) do | for _, item in ipairs(source) do | ||
| Line 70: | Line 63: | ||
end | end | ||
| − | ---Finds the first source in the | + | ---Finds the first source in the drop table that matches the given sourceId. |
| − | ---@param | + | ---@param drop table|Drop The drop table from Module:Loot/data. |
---@param id string|number The ID of the source to find. | ---@param id string|number The ID of the source to find. | ||
---@param sourceType string String representing the type of the source ("monster" or "location"). | ---@param sourceType string String representing the type of the source ("monster" or "location"). | ||
| Line 77: | Line 70: | ||
---@return Item[]|nil # The source data, or nil if the source is not found. | ---@return Item[]|nil # The source data, or nil if the source is not found. | ||
---@return string|nil # The locationId where the source was found (`id` if `sourceType` is "location"), or nil if the source is not found. | ---@return string|nil # The locationId where the source was found (`id` if `sourceType` is "location"), or nil if the source is not found. | ||
| − | local function getFirstSourceMatch( | + | local function getFirstSourceMatch(drop, id, sourceType, locationId) |
id = tostring(id) | id = tostring(id) | ||
locationId = locationId and tostring(locationId) or nil | locationId = locationId and tostring(locationId) or nil | ||
if sourceType == "location" then | if sourceType == "location" then | ||
| − | local location = | + | local location = drop[id] |
if not location then | if not location then | ||
return | return | ||
| Line 96: | Line 89: | ||
-- otherwise the loot would be from first matching ID and could be wrong | -- otherwise the loot would be from first matching ID and could be wrong | ||
if locationId then | if locationId then | ||
| − | local location = | + | local location = drop[locationId] |
for sourceId, source in pairs(location) do | for sourceId, source in pairs(location) do | ||
if sourceId == id then | if sourceId == id then | ||
| Line 105: | Line 98: | ||
end | end | ||
| − | for | + | for locationId2, location in pairs(drop) do |
for sourceId, source in pairs(location) do | for sourceId, source in pairs(location) do | ||
if sourceId == id then | if sourceId == id then | ||
| − | return source, | + | return source, locationId2 |
end | end | ||
end | end | ||
| Line 244: | Line 237: | ||
---Formats the value of an item as string. | ---Formats the value of an item as string. | ||
| − | ---@param item table Item table from Module:Items/data | + | ---@param item table|Item Item table from Module:Items/data |
| + | ---@param drop table|Drop Drop table from Module:Loot/data | ||
---@return string # The formatted value of the item as string, or '-' if no value. | ---@return string # The formatted value of the item as string, or '-' if no value. | ||
| − | local function createValueText(item) | + | local function createValueText(item, drop) |
local lang = mw.language.getContentLanguage() | local lang = mw.language.getContentLanguage() | ||
| − | + | local value = item.id == 1 and 1 or item.value | |
| − | return " | + | if value then |
| + | local minValue = drop.minAmount and drop.minAmount * value | ||
| + | local maxValue = drop.maxAmount and drop.maxAmount * value | ||
| + | if minValue == maxValue then | ||
| + | return lang:formatNum(minValue) | ||
| + | elseif minValue and maxValue then | ||
| + | return lang:formatNum(minValue) .. "–" .. lang:formatNum(maxValue) | ||
| + | elseif minValue or maxValue then | ||
| + | return lang:formatNum(minValue or maxValue) | ||
| + | end | ||
end | end | ||
| − | return | + | return "NA" |
end | end | ||
---Formats the Item drop quantities as string. | ---Formats the Item drop quantities as string. | ||
| − | ---@param | + | ---@param drop table|Drop Item drop table from Module:Loot/data |
---@return string # The formatted quantity range as string. | ---@return string # The formatted quantity range as string. | ||
| − | local function createQuantityText( | + | local function createQuantityText(drop) |
local lang = mw.language.getContentLanguage() | local lang = mw.language.getContentLanguage() | ||
| − | if | + | if drop.minAmount == drop.maxAmount then |
| − | return lang:formatNum( | + | return lang:formatNum(drop.minAmount) |
end | end | ||
| − | return lang:formatNum( | + | return lang:formatNum(drop.minAmount) .. "–" .. lang:formatNum(drop.maxAmount) |
end | end | ||
| Line 317: | Line 320: | ||
end) | end) | ||
| − | |||
local imageWidth = args.width == nil and 30 or args.width | local imageWidth = args.width == nil and 30 or args.width | ||
local imageHeight = args.height == nil and imageWidth or args.height | local imageHeight = args.height == nil and imageWidth or args.height | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
--TODO: Add option to show percentages as fractions (open options from the gear icon) | --TODO: Add option to show percentages as fractions (open options from the gear icon) | ||
-- Saving preferences would require special permissions? MAybe with mw.user or javascript to localStorage? | -- Saving preferences would require special permissions? MAybe with mw.user or javascript to localStorage? | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | for _, | + | local rows = { |
| − | local | + | ["Normal drops"] = {}, |
| + | ["Junk drops"] = {}, | ||
| + | ["League specific drops"] = {} | ||
| + | } | ||
| + | |||
| + | for _, drop in ipairs(loot) do | ||
| + | local item = itemsData[tostring(drop.id)] | ||
--IS itemList.ts has some incorrect URIs, e.g. for Feather | --IS itemList.ts has some incorrect URIs, e.g. for Feather | ||
| − | local src = | + | local src = item.itemImage |
src = src:sub(1, 1) ~= "/" and "/" .. src or src | src = src:sub(1, 1) ~= "/" and "/" .. src or src | ||
local imageHtml = mw.html.create("td") | local imageHtml = mw.html.create("td") | ||
:wikitext(createWikitextImage( | :wikitext(createWikitextImage( | ||
| − | + | item.name, | |
{ | { | ||
src = "https://www.play.idlescape.com" .. src, | src = "https://www.play.idlescape.com" .. src, | ||
| − | alt = | + | alt = item.name .. (item.extraTooltip and ". " .. item.extraTooltip or ""), |
width = imageWidth, | width = imageWidth, | ||
height = imageHeight | height = imageHeight | ||
| Line 427: | Line 348: | ||
)) | )) | ||
local itemHtml = mw.html.create("td") | local itemHtml = mw.html.create("td") | ||
| − | :wikitext('[[' .. | + | :wikitext('[[' .. item.name .. ']]') |
local quantityHtml = mw.html.create("td") | local quantityHtml = mw.html.create("td") | ||
:css("text-align", "center") | :css("text-align", "center") | ||
| − | :wikitext(createQuantityText( | + | :wikitext(createQuantityText(drop)) |
local chanceHtml = mw.html.create("td") | local chanceHtml = mw.html.create("td") | ||
:css("text-align", "center") | :css("text-align", "center") | ||
| − | :wikitext(toFixed( | + | :wikitext(toFixed(drop.chance * 100, 3) .. "%") |
| − | local | + | local valueHtml = mw.html.create("td") |
:css("text-align", "right") | :css("text-align", "right") | ||
| − | :wikitext(createValueText( | + | :wikitext(createValueText(item, drop)) |
local tradeableHtml = mw.html.create("td") | local tradeableHtml = mw.html.create("td") | ||
:css("text-align", "center") | :css("text-align", "center") | ||
| − | :wikitext(( | + | :wikitext((item.id == 1 or item.tradeable) and "Yes" or "No") --Gold is tradeable |
| − | local leagueHtml | + | local leagueHtml |
| − | |||
--TODO: Add indicator if league is inactive, the field is present in | --TODO: Add indicator if league is inactive, the field is present in | ||
-- leagueList.ts / Module:Leagues/data but some are incorrect | -- leagueList.ts / Module:Leagues/data but some are incorrect | ||
| − | if | + | if drop.allowedLeagues then |
| − | for _, leagueId in ipairs( | + | leagueHtml = mw.html.create("td") |
| + | :css("text-align", "center") | ||
| + | for _, leagueId in ipairs(drop.allowedLeagues) do | ||
local league = leaguesData[tostring(leagueId)] | local league = leaguesData[tostring(leagueId)] | ||
if league then | if league then | ||
| Line 461: | Line 383: | ||
end | end | ||
end | end | ||
| − | |||
| − | |||
end | end | ||
| − | local | + | local row = mw.html.create("tr") |
:node(imageHtml) | :node(imageHtml) | ||
:node(itemHtml) | :node(itemHtml) | ||
:node(quantityHtml) | :node(quantityHtml) | ||
:node(chanceHtml) | :node(chanceHtml) | ||
| − | :node( | + | :node(valueHtml) |
:node(tradeableHtml) | :node(tradeableHtml) | ||
| − | |||
| − | if | + | if leagueHtml then |
| − | + | row:node(leagueHtml) | |
| + | end | ||
| + | |||
| + | local caption = "Normal drops" | ||
| + | if drop.allowedLeagues then | ||
| + | caption = "League specific drops" | ||
| + | elseif item.class == "junk" then | ||
| + | caption = "Junk drops" | ||
end | end | ||
| − | tableHtml:node( | + | table.insert(rows[caption], row) |
| + | end | ||
| + | |||
| + | ---@param caption string|nil Optional caption for the table. | ||
| + | ---@param isLeagues boolean|nil If true, show leagues in the table. | ||
| + | ---@return table|mw.html # mw.html TABLE element. | ||
| + | local function createTable(caption, isLeagues) | ||
| + | local columns = { | ||
| + | " ", | ||
| + | "Item", | ||
| + | "Quantity", | ||
| + | "Rarity", | ||
| + | "Vendor value", | ||
| + | "Tradeable", | ||
| + | isLeagues and "Leagues" or nil | ||
| + | } | ||
| + | local element = mw.html.create("table") | ||
| + | :addClass("wikitable sortable jquery-tablesorter mw-collapsible") | ||
| + | if caption then | ||
| + | element | ||
| + | :tag("caption") | ||
| + | :css("width", "fit-content") --Might not be needed, depends on the wiki css | ||
| + | :wikitext(caption .. " ") | ||
| + | :done() | ||
| + | end | ||
| + | return element:node(createThs(columns)) | ||
| + | end | ||
| + | |||
| + | local tableHtml = mw.html.create() | ||
| + | |||
| + | for caption, rowList in pairs(rows) do | ||
| + | if next(rowList) ~= nil then | ||
| + | local isLeagues = caption == "League specific drops" | ||
| + | local tableHtml2 = createTable(caption, isLeagues) | ||
| + | for _, row in ipairs(rowList) do | ||
| + | tableHtml2:node(row) | ||
| + | end | ||
| + | tableHtml:node(tableHtml2) | ||
| + | end | ||
end | end | ||
Revision as of 21:15, 27 April 2025
local p = {}
local findId = require("Module:FindId")
local lootData = mw.loadData("Module:Loot/data")
local itemsData = mw.loadData("Module:Items/data")
local leaguesData = mw.loadData("Module:Leagues/data")
---Creates a deep copy of a table.
---@param t table
---@return table
local function copyTable(t)
local copy = {}
for k, v in pairs(t) do
if type(v) == "table" then
copy[k] = copyTable(v)
else
copy[k] = v
end
end
return copy
end
---Creates a mw.html 'DIV' element containing an "error" message.
---@param message string Message as wikitext.
---@return mw.html # The message wrapped in a mw.html DIV element as red text.
local function createErrorMessage(message)
local e = mw.html.create("div")
:css("color", "red")
:wikitext(message)
return e
end
---Finds the source ID for a given name.
---@param name string The name of the source.
---@return number|nil # The source ID (monsterID or locationID), or nil if the source is not found.
---@return string|nil # The source type ("monster" or "location"), or nil if the source is not found.
local function findSourceId(name)
for _, source in ipairs({ "monster", "location" }) do
local id = findId._findId({ name, source })
if id ~= "id not found" then
return id, source
end
end
end
---Finds the first item in the drop table that matches the given item ID.
---@param drop table The drop table from Module:Loot/data.
---@param id string|number The ID of the item to find.
---@return Item|nil The item data, or nil if the item is not found.
---@return string|nil # The monsterId where the item was found ("-1" for locations), or nil if the item is not found.
---@return string|nil # The locationId where the item was found, or nil if the item is not found.
local function getFirstLootMatch(drop, id)
id = tostring(id)
for locationId, location in pairs(drop) do
for sourceId, source in pairs(location) do
for _, item in ipairs(source) do
if item.id == id then
return item, sourceId, locationId
end
end
end
end
end
---Finds the first source in the drop table that matches the given sourceId.
---@param drop table|Drop The drop table from Module:Loot/data.
---@param id string|number The ID of the source to find.
---@param sourceType string String representing the type of the source ("monster" or "location").
---@param locationId string|number|nil Optional ID for the location to find the source from. Use `id` and `sourceType` for location loot.
---@return Item[]|nil # The source data, or nil if the source is not found.
---@return string|nil # The locationId where the source was found (`id` if `sourceType` is "location"), or nil if the source is not found.
local function getFirstSourceMatch(drop, id, sourceType, locationId)
id = tostring(id)
locationId = locationId and tostring(locationId) or nil
if sourceType == "location" then
local location = drop[id]
if not location then
return
end
local source = location["-1"]
if not source then
return
end
return source, id
end
--Needed for 'override' monsters that share ID with other monsters
-- otherwise the loot would be from first matching ID and could be wrong
if locationId then
local location = drop[locationId]
for sourceId, source in pairs(location) do
if sourceId == id then
return source, locationId
end
end
return
end
for locationId2, location in pairs(drop) do
for sourceId, source in pairs(location) do
if sourceId == id then
return source, locationId2
end
end
end
end
--TODO: Add option to show percentages as fractions
---Converts a floating-point number to a approximation of fraction.
---@param num number The floating-point number to convert.
---@param maxDenominator number The maximum denominator for the fraction.
---@return number # The numerator of the fraction.
---@return number # The denominator of the fraction.
local function floatToFraction(num, maxDenominator)
local sign = num < 0 and -1 or 1
num = math.abs(num)
local bestNumerator, bestDenominator = 1, 1
local minDifference = math.huge
for d = 1, maxDenominator do
local n = math.floor(num * d + 0.5)
local approx = n / d
local difference = math.abs(num - approx)
if difference < minDifference then
bestNumerator, bestDenominator = n, d
minDifference = difference
end
end
return sign * bestNumerator, bestDenominator
end
---Converts a floating-point number to a approximation of fraction as string.
---@param num number The floating-point number to convert.
---@param maxDenominator number The maximum denominator for the fraction.
---@return string # The fraction as string ('numerator/denominator').
local function floatToFractionString(num, maxDenominator)
local numerator, denominator = floatToFraction(num, maxDenominator)
if denominator == 1 then
return tostring(numerator)
end
return string.format("%d/%d", numerator, denominator)
end
---Formats a number up to a given number of decimal places, removing trailing zeros.
---@param num number The number to format.
---@param digits number The number of decimal places to include (must be a non-negative integer).
---@return string # The formatted number as a string.
local function toFixed(num, digits)
digits = math.max(0, math.floor(digits))
local formatted = string.format("%." .. digits .. "f", num):gsub("%.?0+$", "")
return formatted
end
---Finds the ID of a monster that is overridden by another monster with the given name.
---@param name string The name of the monster that overrides another monster.
---@return string|nil # The ID of the monster that is overridden, or nil if not found.
local function findIdByOverrideName(name)
local monsterStatsData = mw.loadData("Module:Monsters_stats/data")
for id, monster in pairs(monsterStatsData) do
for overrideName, overrideMonster in pairs(monster.overrides or {}) do
if overrideName == name then
return id
end
end
end
end
---@param name string Wikitext.
---@return mw.html # mw.html TH element.
local function createTh(name)
local th = mw.html.create("th")
:addClass("headerSort")
:attr("tabindex", 0)
:attr("title", "Sort ascending")
:wikitext(name)
return th
end
---@param names string[] Array of wikitext.
---@return mw.html # TR element containing names as TH elements.
local function createThs(names)
local tr = mw.html.create("tr")
for _, name in ipairs(names) do
tr:node(createTh(name))
end
return tr
end
---Creates a mw.html A element containing an image.
---@param name string The name of the item.
---@param src string The URI to the item image.
---@param width? string|integer The width of the item image as integer.
---@param height? string|integer The height of the item image as integer.
---@return mw.html # mw.html A element containing an image.
local function createImg(name, src, alt, width, height)
local e = mw.html.create("a")
:attr("href", tostring(mw.uri.localUrl(name)))
:attr("title", name)
:tag("img")
:attr("src", src)
:attr("alt", alt)
if width then
e:attr("width", width)
end
if height then
e:attr("height", height)
end
return e:done()
end
local function createImgText(name, src, alt, width, height)
return string.format(
'[[%s|<img src="%s" alt="%s"%s%s>]]',
name,
src,
alt,
width and ' width="' .. width .. '"' or "",
height and ' height="' .. height .. '"' or ""
)
end
---Creates an Wikitext link with an image.
---@param title string The title of the link.
---@param imageAttributes table The html attributes for the image.
---@return string # Wikitext link with the image.
local function createWikitextImage(title, imageAttributes)
local img = mw.html.create("img")
:attr(imageAttributes)
img = tostring(img):gsub("<img(.-) */>", "<img%1>")
return string.format('[[%s|%s]]', title, img)
end
---Formats the value of an item as string.
---@param item table|Item Item table from Module:Items/data
---@param drop table|Drop Drop table from Module:Loot/data
---@return string # The formatted value of the item as string, or '-' if no value.
local function createValueText(item, drop)
local lang = mw.language.getContentLanguage()
local value = item.id == 1 and 1 or item.value
if value then
local minValue = drop.minAmount and drop.minAmount * value
local maxValue = drop.maxAmount and drop.maxAmount * value
if minValue == maxValue then
return lang:formatNum(minValue)
elseif minValue and maxValue then
return lang:formatNum(minValue) .. "–" .. lang:formatNum(maxValue)
elseif minValue or maxValue then
return lang:formatNum(minValue or maxValue)
end
end
return "NA"
end
---Formats the Item drop quantities as string.
---@param drop table|Drop Item drop table from Module:Loot/data
---@return string # The formatted quantity range as string.
local function createQuantityText(drop)
local lang = mw.language.getContentLanguage()
if drop.minAmount == drop.maxAmount then
return lang:formatNum(drop.minAmount)
end
return lang:formatNum(drop.minAmount) .. "–" .. lang:formatNum(drop.maxAmount)
end
function p.lootTable(frame)
local args = frame:getParent().args
return tostring(p._lootTable(args))
end
function p._lootTable(args)
local sourceName = args.name or args.title or mw.title.getCurrentTitle().text
--Some monsters use same id as other monsters so we need to specify location for them
local locationId = args["zone"] and findSourceId(args["zone"])
local sourceId
local sourceType
if locationId then
sourceId = findIdByOverrideName(sourceName)
sourceType = "monster"
else
sourceId, sourceType = findSourceId(sourceName)
end
if not sourceId then
return locationId and
createErrorMessage(
"Found no monsters overridden by '" .. sourceName ..
"'. The Modules: Monsters_stats/data or Loot/data may be outdated."
) or
createErrorMessage(
"No monster or location named '" .. sourceName ..
"'. The Module:Loot/data may be outdated. <br>Try adding parameter 'location' to the template, e.g.:" ..
"<br><code>{{Loot_table|location=Palace of Flame}}</code>."
)
end
---@diagnostic disable-next-line: param-type-mismatch
local loot = getFirstSourceMatch(lootData, sourceId, sourceType, locationId)
if not loot then
return createErrorMessage(
"No loot found for monster or location named '" .. sourceName ..
"'. The Module:Loot/data may be outdated. <br>Please add loot drops to Module:Loot/data " ..
"if possible or try manually making a table.</div>"
)
end
--loot data is read-only from Module so we need to copy it
loot = copyTable(loot)
table.sort(loot, function(a, b)
if a.allowedLeagues and not b.allowedLeagues then
return false
elseif not a.allowedLeagues and b.allowedLeagues then
return true
else
return a.chance > b.chance
end
end)
local imageWidth = args.width == nil and 30 or args.width
local imageHeight = args.height == nil and imageWidth or args.height
--TODO: Add option to show percentages as fractions (open options from the gear icon)
-- Saving preferences would require special permissions? MAybe with mw.user or javascript to localStorage?
local rows = {
["Normal drops"] = {},
["Junk drops"] = {},
["League specific drops"] = {}
}
for _, drop in ipairs(loot) do
local item = itemsData[tostring(drop.id)]
--IS itemList.ts has some incorrect URIs, e.g. for Feather
local src = item.itemImage
src = src:sub(1, 1) ~= "/" and "/" .. src or src
local imageHtml = mw.html.create("td")
:wikitext(createWikitextImage(
item.name,
{
src = "https://www.play.idlescape.com" .. src,
alt = item.name .. (item.extraTooltip and ". " .. item.extraTooltip or ""),
width = imageWidth,
height = imageHeight
}
))
local itemHtml = mw.html.create("td")
:wikitext('[[' .. item.name .. ']]')
local quantityHtml = mw.html.create("td")
:css("text-align", "center")
:wikitext(createQuantityText(drop))
local chanceHtml = mw.html.create("td")
:css("text-align", "center")
:wikitext(toFixed(drop.chance * 100, 3) .. "%")
local valueHtml = mw.html.create("td")
:css("text-align", "right")
:wikitext(createValueText(item, drop))
local tradeableHtml = mw.html.create("td")
:css("text-align", "center")
:wikitext((item.id == 1 or item.tradeable) and "Yes" or "No") --Gold is tradeable
local leagueHtml
--TODO: Add indicator if league is inactive, the field is present in
-- leagueList.ts / Module:Leagues/data but some are incorrect
if drop.allowedLeagues then
leagueHtml = mw.html.create("td")
:css("text-align", "center")
for _, leagueId in ipairs(drop.allowedLeagues) do
local league = leaguesData[tostring(leagueId)]
if league then
leagueHtml:wikitext(createWikitextImage(
league.name,
{
src = "https://www.play.idlescape.com" .. league.icon,
alt = league.name,
width = imageWidth,
height = imageHeight
}
))
else
leagueHtml:wikitext("?")
end
end
end
local row = mw.html.create("tr")
:node(imageHtml)
:node(itemHtml)
:node(quantityHtml)
:node(chanceHtml)
:node(valueHtml)
:node(tradeableHtml)
if leagueHtml then
row:node(leagueHtml)
end
local caption = "Normal drops"
if drop.allowedLeagues then
caption = "League specific drops"
elseif item.class == "junk" then
caption = "Junk drops"
end
table.insert(rows[caption], row)
end
---@param caption string|nil Optional caption for the table.
---@param isLeagues boolean|nil If true, show leagues in the table.
---@return table|mw.html # mw.html TABLE element.
local function createTable(caption, isLeagues)
local columns = {
" ",
"Item",
"Quantity",
"Rarity",
"Vendor value",
"Tradeable",
isLeagues and "Leagues" or nil
}
local element = mw.html.create("table")
:addClass("wikitable sortable jquery-tablesorter mw-collapsible")
if caption then
element
:tag("caption")
:css("width", "fit-content") --Might not be needed, depends on the wiki css
:wikitext(caption .. " ")
:done()
end
return element:node(createThs(columns))
end
local tableHtml = mw.html.create()
for caption, rowList in pairs(rows) do
if next(rowList) ~= nil then
local isLeagues = caption == "League specific drops"
local tableHtml2 = createTable(caption, isLeagues)
for _, row in ipairs(rowList) do
tableHtml2:node(row)
end
tableHtml:node(tableHtml2)
end
end
return tableHtml
end
return p