Module:Ship infobox: Difference between revisions
From Corsair Cove Official Wiki
Uses Ships_data to generate an infobox for the named ship. |
Landlubber path banner gray and unlocked by default |
||
| Line 25: | Line 25: | ||
local function CSS_RECOLOR_PATH(path) | local function CSS_RECOLOR_PATH(path) | ||
if (not path) or (type(path) ~= "string") or (path == "") or (path == "None") then | |||
return "cc-panel-recolor-gray" | |||
end | |||
return "cc-panel-recolor-" .. path:lower() | return "cc-panel-recolor-" .. path:lower() | ||
end | end | ||
| Line 384: | Line 387: | ||
local function build_unlock_section(ship, callTemplate) | local function build_unlock_section(ship, callTemplate) | ||
local unlock_section = mw.html.create("div"):addClass(CSS_U) | local unlock_section = mw.html.create("div"):addClass(CSS_U) | ||
unlock_section | if #ship.unlock_points == 0 then | ||
unlock_section | |||
:tag("div"):addClass(CSS_U_TITLE) | |||
:wikitext("Unlock") | |||
:done() | |||
:tag("hr") | |||
:done() | |||
:tag("div"):addClass(CSS_U_REQ) | |||
:tag("div") | |||
:wikitext("Unlocked by building first pier.") | |||
:done() | |||
:done() | |||
else | |||
unlock_section | |||
:tag("div"):addClass(CSS_U_TITLE) | |||
:wikitext("Unlock") | |||
:done() | |||
:tag("hr") | |||
:done() | |||
:tag("div"):addClass(CSS_U_REQ) | |||
:tag("div") | |||
:wikitext("Spend points:") | |||
:done() | |||
:node(build_unlock_points_block(ship.unlock_points, callTemplate)) | |||
:done() | |||
end | |||
return unlock_section | return unlock_section | ||
end | end | ||
Revision as of 19:16, 7 August 2026
This module builds the ship infobox HTML. It is invoked from Template:Ship infobox.
Usage
| Method invoked by template | Argument from template | Description of argument |
|---|---|---|
main() |
name |
Canonical ship name, as seen in-game (e.g. Bedlam, Wrath Bringer).
|
Template Examples
With a named argument:
{{#invoke:Ship infobox|main|name=Bedlam}}
Or a positional argument:
{{#invoke:Ship infobox|main|Bedlam}}
API
main()- Entry point. Looks up the ship, builds the infobox, and returns HTML.
No other functions are exported.
Errors
- Ship name is required —
nameor positional arg missing or empty. - Ship not found — name not in Module:Ships_data.
Dependencies
- Module:Ships_data — ship stats, crew, construction, unlock data
- Module:ResourceData — construction resource icons
Templates called at runtime
- Template:Ship tier icon
- Template:Pirate icon
- Template:Health
- Template:Crew
- Template:Supplies
- Template:Gun Damage icon
- Template:Boarding Damage icon
- Template:Speed icon
- Template:Manoeuvrability icon
- Template:Armour icon
--[[
Generates the infobox for Template:Ship infobox.
For testing on the debug console, copy and paste this line of code:
=p.main({args = {name = "Bedlam"}, expandTemplate = function (_, t) return mw.getCurrentFrame():expandTemplate(t) end})
]]
---@type ShipsDataModule
local ships_data = require("Module:Ships_data")
---@diagnostic disable: undefined-field
local resourceData = mw.loadData("Module:ResourceData")
local CSS_INFOBOX = "cc-infobox-ship"
local CSS_H = CSS_INFOBOX .. "-header"
local CSS_H_TIER = CSS_H .. "-tier"
local CSS_H_NAME = CSS_H .. "-name"
local CSS_H_CLASS = CSS_H .. "-class"
local CSS_H_ICON = CSS_H .. "-icon"
local CSS_H_DESCRIPTION = CSS_H .. "-description"
local function CSS_RECOLOR_PATH(path)
if (not path) or (type(path) ~= "string") or (path == "") or (path == "None") then
return "cc-panel-recolor-gray"
end
return "cc-panel-recolor-" .. path:lower()
end
local CSS_S = CSS_INFOBOX .. "-stats"
local CSS_S_TITLE = CSS_S .. "-title"
local CSS_S_FULLROW = CSS_S .. "-fullrow"
local CSS_S_ROW = CSS_S .. "-row"
local CSS_S_ROW_COL = CSS_S_ROW .. "-col"
local CSS_STAT_MAX = "cc-ship-stat-max"
local CSS_W = CSS_INFOBOX .. "-crew"
local CSS_W_TITLE = CSS_W .. "-title"
local CSS_W_ROW = CSS_W .. "-row"
local CSS_W_ROW_COL = CSS_W_ROW .. "-col"
local CSS_W_ROW_COL_ADV = CSS_W_ROW_COL .. "-advanced"
local CSS_C = CSS_INFOBOX .. "-construction"
local CSS_C_TITLE = CSS_C .. "-title"
local CSS_C_PIER = CSS_C .. "-pier"
local CSS_C_TABLE = CSS_C .. "-table"
local CSS_C_TABLE_QTY = CSS_C_TABLE .. "-qty"
local CSS_U = CSS_INFOBOX .. "-unlock"
local CSS_U_TITLE = CSS_U .. "-title"
local CSS_U_REQ = CSS_U .. "-requirements"
local CSS_U_REQ_POINTS = CSS_U_REQ .. "-points"
local function CSS_U_REQ_POINTS_PATH(path)
return CSS_U_REQ_POINTS .. "-" .. path:lower()
end
--#region Private helper functions
--- Retrieves the specified value from the given stats array.
---@param stats ShipStatAmount[]
---@param stat_name string
---@return number
local function get_stat_value(stats, stat_name)
for _, pair in ipairs(stats) do
if pair.stat == stat_name then
return pair.qty
end
end
return 0
end
---@alias ExpandTemplateFunction fun(title: string, args: table): string
--- Hides dependency on the frame object from template expansion.
---@return ExpandTemplateFunction
local function make_template_expander(frame)
return function(title, args)
return frame:expandTemplate({ title = title, args = args })
end
end
--#region Private helper functions for header section
--- Builds the header section.
---@param ship ShipRecord
---@param callTemplate ExpandTemplateFunction
---@return HtmlNode
local function build_header_section(ship, callTemplate)
local tier_icon = callTemplate("Ship tier icon", { ship.tier, path = ship.principle_path, size = "md" })
local header_section = mw.html.create("div"):addClass(CSS_H)
header_section
:tag("div"):addClass(CSS_H_TIER)
:wikitext(tier_icon)
:done()
:tag("div"):addClass(CSS_H_NAME)
:tag("span")
:wikitext(ship.name)
:done()
:done()
:tag("div"):addClass(CSS_H_CLASS):addClass(CSS_RECOLOR_PATH(ship.principle_path))
:tag("span")
:wikitext(ship.class .. " Tier " .. ship.tier)
:done()
:done()
:tag("div"):addClass(CSS_H_ICON)
:wikitext("[[File:" .. ship.icon_filename .. "|x128px]]")
:done()
:tag("div"):addClass(CSS_H_DESCRIPTION)
:wikitext(ship.description)
:done()
return header_section
end
--#endregion
--#region Private helper functions for stats section
--- Builds one full-row stat with name and base value (only).
---@param stats ShipStatAmount[]
---@param stat_name string
---@param callTemplate ExpandTemplateFunction
---@return HtmlNode
local function build_stats_fullrow(stats, stat_name, callTemplate)
local stat_fullrow = mw.html.create("div"):addClass(CSS_S_FULLROW)
stat_fullrow
:tag("div"):addClass(CSS_S_ROW_COL)
:wikitext(callTemplate(stat_name, { size = "sm" }))
:done()
:tag("div")
:wikitext(tostring(get_stat_value(stats, stat_name)))
:done()
return stat_fullrow
end
--- Builds one stat column with icon, base, and max value.
---@param stats_base ShipStatAmount[]
---@param stats_max ShipStatAmount[]
---@param stat_name string
---@param callTemplate ExpandTemplateFunction
---@return HtmlNode
local function build_stats_column(stats_base, stats_max, stat_name, callTemplate)
local stat_column = mw.html.create("div"):addClass(CSS_S_ROW_COL)
stat_column
:tag("div")
:wikitext(callTemplate(stat_name .. " icon", { size = "sm" }))
:done()
:tag("div")
:wikitext(tostring(get_stat_value(stats_base, stat_name)))
:done()
:tag("div"):addClass(CSS_STAT_MAX)
:wikitext(tostring(get_stat_value(stats_max, stat_name)))
:done()
return stat_column
end
--- Builds the stats section.
---@param ship ShipRecord
---@param callTemplate ExpandTemplateFunction
---@return HtmlNode
local function build_stats_section(ship, callTemplate)
local stats_section = mw.html.create("div"):addClass(CSS_S)
stats_section
:tag("div"):addClass(CSS_S_TITLE)
:wikitext("Stats")
:done()
:tag("hr")
:done()
:node(build_stats_fullrow(ship.stats_base, "Health", callTemplate))
:node(build_stats_fullrow(ship.stats_base, "Crew", callTemplate))
:node(build_stats_fullrow(ship.stats_base, "Supplies", callTemplate))
:tag("div"):addClass(CSS_S_ROW)
:tag("div"):addClass(CSS_S_ROW_COL)
:tag("div")
:wikitext("Base")
:done()
:tag("div"):addClass(CSS_STAT_MAX)
:wikitext("Max")
:done()
:done()
:node(build_stats_column(ship.stats_base, ship.stats_max, "Gun damage", callTemplate))
:node(build_stats_column(ship.stats_base, ship.stats_max, "Boarding damage", callTemplate))
:node(build_stats_column(ship.stats_base, ship.stats_max, "Speed", callTemplate))
:node(build_stats_column(ship.stats_base, ship.stats_max, "Manoeuvrability", callTemplate))
:node(build_stats_column(ship.stats_base, ship.stats_max, "Armour", callTemplate))
:done()
return stats_section
end
--#endregion
--#region Private helper functions for crew section
--- Builds one crew column with label, icon, and quantity.
---@param crew_type string
---@param qty number
---@param callTemplate ExpandTemplateFunction
---@return HtmlNode
local function build_crew_column(crew_type, qty, callTemplate)
local is_crew_advanced = {
["Swabbies"] = false,
["Scallywags"] = true,
["Picaroons"] = true,
["Bombardiers"] = true,
["Crow's Eyes"] = true,
["Buccaneers"] = true,
["Navigators"] = true,
["Renegades"] = true,
["Marauders"] = true,
["Corsairs"] = true,
}
local column = mw.html.create("div"):addClass(CSS_W_ROW_COL)
column
:tag("div")
:wikitext(crew_type)
:done()
:tag("div"):addClass()
:wikitext(callTemplate("Pirate icon", { crew_type, size = "md" } ))
:done()
:tag("div")
:wikitext(tostring(qty))
:done()
return column
end
--- Builds the crew section.
---@param ship ShipRecord
---@param callTemplate ExpandTemplateFunction
---@return HtmlNode
local function build_crew_section(ship, callTemplate)
local crew_section = mw.html.create("div"):addClass(CSS_W)
crew_section
:tag("div"):addClass(CSS_W_TITLE)
:wikitext("Crew")
:done()
:tag("hr")
:done()
local crew_row = mw.html.create("div"):addClass(CSS_W_ROW)
for _, crew in ipairs(ship.crew_types) do
crew_row:node(build_crew_column(crew.type, crew.qty, callTemplate))
end
crew_section:node(crew_row)
return crew_section
end
--#endregion
--#region Private helper functions for construction section
--- Appends the construction pier wikitext.
---@param pier string
---@param callTemplate ExpandTemplateFunction
---@return string
local function write_construction_pier_wikitext(pier, callTemplate)
local pier_icons = {
["Shallow Pier"] = "T ICO Pier lvl 1.png",
["Trade Pier"] = "T ICO Pier lvl 2.png",
["Deep-water Pier"] = "T ICO Pier lvl 3.png",
}
return "[[File:" .. pier_icons[pier] .. "|x32px|link=" .. pier .. "|" .. pier .. "]] [[" .. pier .. "]]"
end
--- Appends qty, icon, and name cells for one construction cost to a table row.
---@param row HtmlNode
---@param resource string
---@param qty number
---@param callTemplate ExpandTemplateFunction
local function append_construction_cost(row, resource, qty, callTemplate)
local icon_file = resourceData[resource]["icon_file"]
row
:tag("td"):addClass(CSS_C_TABLE_QTY)
:tag("span")
:wikitext(tostring(qty))
:done()
:done()
:tag("td")
:tag("span")
:wikitext("[[File:" .. icon_file .. "|x32px|link=" .. resource .. "|" .. resource .. "]]")
:done()
:done()
:tag("td")
:tag("span")
:wikitext(resource)
:done()
:done()
end
--- Builds the construction table.
---@param construction_costs ShipResourceAmount[]
---@param callTemplate ExpandTemplateFunction
---@return HtmlNode
local function build_construction_table(construction_costs, callTemplate)
local construction_table = mw.html.create("table")
local row
for index, cost in ipairs(construction_costs) do
if index % 2 == 1 then
row = mw.html.create("tr")
end
if index % 2 == 0 then
row:tag("td"):attr("style", "min-width: 16px;"):wikitext(" "):done()
end
append_construction_cost(row, cost.resource, cost.qty, callTemplate)
if index % 2 == 0 or index == #construction_costs then
construction_table:node(row)
end
end
return construction_table
end
--- Builds the construction section.
---@param ship ShipRecord
---@param callTemplate ExpandTemplateFunction
---@return HtmlNode
local function build_construction_section(ship, callTemplate)
local construction_section = mw.html.create("div"):addClass(CSS_C)
construction_section
:tag("div"):addClass(CSS_C_TITLE)
:wikitext("Construction")
:done()
:tag("hr")
:done()
:tag("div"):addClass(CSS_C_PIER)
:wikitext(write_construction_pier_wikitext(ship.pier, callTemplate))
:done()
:tag("div"):addClass(CSS_C_TABLE)
:node(build_construction_table(ship.construction_costs, callTemplate))
:done()
return construction_section
end
--#endregion
--#region Private helper functions for unlock section
--- Builds one unlock points block with icon, color block, and quantity.
---@param path string
---@param qty number
---@param callTemplate ExpandTemplateFunction
---@return HtmlNode
local function append_points_block(path, qty, callTemplate)
local path_icons = {
Notoriety = "T_ICO_VEC_P_Notoriety1.png",
Empire = "T_ICO_VEC_P_Empire2.png",
Seafaring = "T_ICO_VEC_P_Sea.png",
Wealth = "T_ICO_VEC_P_Wealth.png",
}
local block = mw.html.create("div"):addClass(CSS_U_REQ_POINTS_PATH(path))
:wikitext("[[File:" .. path_icons[path] .. "|x24px|link=" .. path .. "|" .. path .. "]]")
:tag("span")
:wikitext(tostring(qty))
:done()
return block
end
--- Builds the unlock points blocks.
---@param unlock_points ShipUnlockAmount[]
---@param callTemplate ExpandTemplateFunction
---@return HtmlNode
local function build_unlock_points_block(unlock_points, callTemplate)
local row = mw.html.create("div"):addClass(CSS_U_REQ_POINTS)
for _, point in ipairs(unlock_points) do
row:node(append_points_block(point.path, point.qty, callTemplate))
end
return row
end
--- Builds the unlock section.
---@param ship ShipRecord
---@param callTemplate ExpandTemplateFunction
---@return HtmlNode
local function build_unlock_section(ship, callTemplate)
local unlock_section = mw.html.create("div"):addClass(CSS_U)
if #ship.unlock_points == 0 then
unlock_section
:tag("div"):addClass(CSS_U_TITLE)
:wikitext("Unlock")
:done()
:tag("hr")
:done()
:tag("div"):addClass(CSS_U_REQ)
:tag("div")
:wikitext("Unlocked by building first pier.")
:done()
:done()
else
unlock_section
:tag("div"):addClass(CSS_U_TITLE)
:wikitext("Unlock")
:done()
:tag("hr")
:done()
:tag("div"):addClass(CSS_U_REQ)
:tag("div")
:wikitext("Spend points:")
:done()
:node(build_unlock_points_block(ship.unlock_points, callTemplate))
:done()
end
return unlock_section
end
--#endregion
--- Orchestrates the infobox.
---@param ship ShipRecord
---@param callTemplate ExpandTemplateFunction
---@return HtmlNode
local function build_infobox_for_ship(ship, callTemplate)
local html = mw.html.create("div"):addClass("cc-infobox-ship")
html:node(build_header_section(ship, callTemplate))
html:node(build_stats_section(ship, callTemplate))
html:node(build_crew_section(ship, callTemplate))
html:node(build_construction_section(ship, callTemplate))
html:node(build_unlock_section(ship, callTemplate))
return html
end
--#endregion
--#region Infobox main
local p = {}
--- Entry point for {{#invoke:Ship infobox|main|name=...}}.
function p.main(frame)
local args = frame.args
local name = args.name or args[1]
if name == "" then
return "'''Ship name is required'''"
end
local ship = ships_data.get_ship_by_name(name)
if not ship then
return "'''Ship not found'''"
end
local callTemplate = make_template_expander(frame)
local html = build_infobox_for_ship(ship, callTemplate)
return html
end
return p
--#endregion


