Module:Companion table
Jump to navigation
Jump to search
This module implements {{Companion table}}.
-- Module:CompanionTable
-- Renders one or more companion/NPC info tables, splitting into multiple
-- tables when the number of NPCs exceeds |maxcols| (default 4).
--
-- Template usage example:
-- {{#invoke:CompanionTable|main
-- | maxcols = 4
-- | imgwidth = 160px
-- | npc1 = Wuk Lamat | image1 = DS Wuk Lamat.png
-- | class1 = {{WAR}} [[File:Red warrior.png|Warrior|20px|link=]] Intrepid
-- | role1 = Tank or DPS
-- | npc2 = G'raha Tia | image2 = DS G'raha Tia1.png
-- | class2 = {{PLD}} {{WHM}} All-rounder
-- | role2 = Tank or Healer
-- | ...
-- }}
local p = {}
-- Default image width. Override globally with |imgwidth=, or per-image with |imgwidthN=.
local DEFAULT_IMG_WIDTH = "150px"
-- Default maximum columns per table.
local DEFAULT_MAX_COLS = 4
-- Names whose wiki article differs from their display name.
-- Key: display name (as passed in |npcN=)
-- Value: article title to link to
local DISAMBIG = {
["Sphene"] = "Sphene (NPC)",
}
-------------------------------------------------------------------------------
-- Helper: return a wikilink for an NPC, using DISAMBIG when needed.
-- Produces [[Target|Display]] when the article title differs, else [[Name]].
-------------------------------------------------------------------------------
local function npcLink(name, isTrust)
if name == "" then return "" end
local target = DISAMBIG[name] or name
local display = isTrust and (name .. "'s Avatar") or name
if display ~= target then
return "[[" .. target .. "|" .. display .. "]]"
else
return "[[" .. target .. "]]"
end
end
-------------------------------------------------------------------------------
-- Helper: collect NPC data from frame args into an ordered list.
-- Each entry: { name, image, class, role }
-------------------------------------------------------------------------------
local function collectNPCs(args, globalImgWidth)
local npcs = {}
local i = 1
while args["npc" .. i] or args["image" .. i] do
npcs[#npcs + 1] = {
name = args["npc" .. i] or "",
image = args["image" .. i] or "",
imgwidth = args["imgwidth" .. i] or globalImgWidth,
class = args["class" .. i] or "",
role = args["role" .. i] or "",
}
i = i + 1
end
return npcs
end
-------------------------------------------------------------------------------
-- Helper: render a single wiki-table for a slice of NPCs.
-------------------------------------------------------------------------------
local function renderTable(slice, isTrust)
local lines = {}
-- Table open
lines[#lines + 1] = '{| {{STDT|npc align-left}}'
-- Header row: blank lead cell + one cell per NPC name
local headerCells = { "!" } -- blank corner
for _, npc in ipairs(slice) do
headerCells[#headerCells + 1] = "! " .. npcLink(npc.name, isTrust)
end
lines[#lines + 1] = table.concat(headerCells, "\n")
-- Image row
lines[#lines + 1] = "|-"
local imgCells = { "|" } -- blank lead cell
for _, npc in ipairs(slice) do
local fileLink
if npc.image ~= "" then
fileLink = "[[File:" .. npc.image .. "|" .. npc.imgwidth .. "]]"
else
fileLink = ""
end
imgCells[#imgCells + 1] = "| " .. fileLink
end
lines[#lines + 1] = table.concat(imgCells, "\n")
-- Class row
lines[#lines + 1] = "|-"
local classCells = { "| '''Class'''" }
for _, npc in ipairs(slice) do
classCells[#classCells + 1] = "| " .. npc.class
end
lines[#lines + 1] = table.concat(classCells, "\n")
-- Role row
lines[#lines + 1] = "|-"
local roleCells = { "| '''Role'''" }
for _, npc in ipairs(slice) do
roleCells[#roleCells + 1] = "| " .. npc.role
end
lines[#lines + 1] = table.concat(roleCells, "\n")
-- Table close
lines[#lines + 1] = "|}"
return table.concat(lines, "\n")
end
-------------------------------------------------------------------------------
-- Main entry point.
-------------------------------------------------------------------------------
function p.main(frame)
-- Merge parent template args with direct invocation args
local args = {}
for k, v in pairs(frame.args) do
args[k] = mw.text.trim(v)
end
-- Also pull in parent frame args so the module works when called from a
-- template that received the parameters.
if frame:getParent() then
for k, v in pairs(frame:getParent().args) do
if args[k] == nil then
args[k] = mw.text.trim(v)
end
end
end
-- Configuration
local maxCols = tonumber(args["maxcols"]) or DEFAULT_MAX_COLS
local imgWidth = args["imgwidth"] or DEFAULT_IMG_WIDTH
local isTrust = args["is-trust"] and args["is-trust"] ~= ""
-- Collect all NPCs (global imgwidth used as per-NPC fallback)
local npcs = collectNPCs(args, imgWidth)
if #npcs == 0 then
return "<!-- Module:CompanionTable: no NPC parameters found -->"
end
-- Split into chunks of maxCols and render each as a separate table
local tables = {}
local i = 1
while i <= #npcs do
local slice = {}
for j = i, math.min(i + maxCols - 1, #npcs) do
slice[#slice + 1] = npcs[j]
end
tables[#tables + 1] = renderTable(slice, isTrust)
i = i + maxCols
end
-- Join tables with a blank line between them so they render as separate blocks
return frame:preprocess(table.concat(tables, "\n"))
end
return p