Module:Building infobox: Difference between revisions

From Beyond These Stars Official Wiki
Add resource icons and change layout of construction resources
adds generic category too
 
(11 intermediate revisions by the same user not shown)
Line 1: Line 1:
--[[
Test in Scribunto console with:
=p.render({ args = { page_name = "Ore Smelter" } })
]]--
local p = {}
local p = {}


Line 16: Line 20:
local HEADER_CLASS = INFOBOX_CLASS .. "-header"
local HEADER_CLASS = INFOBOX_CLASS .. "-header"
local HEADER_ICON_CLASS = HEADER_CLASS .. "-icon"
local HEADER_ICON_CLASS = HEADER_CLASS .. "-icon"
local TITLE_CLASS = INFOBOX_CLASS .. "-title"
local SUBTITLE_CLASS = INFOBOX_CLASS .. "-subtitle"
local SUBHEADER_CLASS = INFOBOX_CLASS .. "-subheader"


local DESCRIPTION_CLASS = INFOBOX_CLASS .. "-description"
local DESCRIPTION_CLASS = INFOBOX_CLASS .. "-description"
local TECH_TREE_CLASS = INFOBOX_CLASS .. "-techtree"


local CONSTRUCTION_CLASS = INFOBOX_CLASS .. "-construction"
local CONSTRUCTION_CLASS = INFOBOX_CLASS .. "-construction"
Line 24: Line 34:
local RESOURCE_ICON_CLASS = "bts-resource-icon"
local RESOURCE_ICON_CLASS = "bts-resource-icon"


local LARGE_ICON_SIZE = "168px"
local MEDIUM_ICON_SIZE = "96px"
local SMALL_ICON_SIZE = "32px"
local SMALL_ICON_SIZE = "32px"


local TASKS_CLASS = INFOBOX_CLASS .. "-tasks"
local TASKS_CLASS = INFOBOX_CLASS .. "-tasks"
local TASKS_TABLE_CLASS = TASKS_CLASS .. "-table"




Line 34: Line 47:
---@return string wikitext
---@return string wikitext
local function render_icon_markup(building)
local function render_icon_markup(building)
   local icon_filename = building.portrait_icon .. ".png"
   local icon_filename
   local image_markup = "[[File:" .. icon_filename .. "|256px]]"
  local size = LARGE_ICON_SIZE
  if building.portrait_icon then
    icon_filename = building.portrait_icon .. ".png"
  elseif building.icon then
    icon_filename = building.icon .. ".png"
    size = MEDIUM_ICON_SIZE
  else
    return ""
  end
   local image_markup = "[[File:" .. icon_filename .. "|".. size .. "|" .. building.name .. "|link=]]"
   return image_markup
   return image_markup
end
end
Line 44: Line 66:
local function add_header(div, building)
local function add_header(div, building)
   local header = div:tag("div"):addClass(HEADER_CLASS)
   local header = div:tag("div"):addClass(HEADER_CLASS)
   header:tag("h2"):wikitext(building.display_name):done()
   header:tag("div"):addClass(TITLE_CLASS):wikitext(building.display_name)
   header:tag("div"):addClass(HEADER_ICON_CLASS):wikitext(render_icon_markup(building))
   header:tag("div"):addClass(HEADER_ICON_CLASS):wikitext(render_icon_markup(building))
   header:tag("h3"):wikitext(building.category):done()
   if building.category and building.category ~= "" then
    header:tag("div"):addClass(SUBTITLE_CLASS):wikitext(building.category .. " Building")
  end
end
end


Line 55: Line 79:
---@param building Building
---@param building Building
local function add_description(div, building)
local function add_description(div, building)
   local description = div:tag("div"):addClass(DESCRIPTION_CLASS)
   local inner_div = div:tag("div"):addClass(DESCRIPTION_CLASS)
   building.description = building.description:gsub("<hb>", ""):gsub("</hb>", "")
   local description = building.description:gsub("<hb>", ""):gsub("</hb>", "")
   description:tag("p"):wikitext(building.description):done()
   description = description:gsub("\n", "<br />")
   return description
  inner_div:wikitext(description)
  return inner_div
end
 
 
 
--- Adds a subheader to the provided html node.
---@param div HtmlNode enclosing infobox div
---@param text string
local function add_subheader(div, text)
  div:tag("div"):addClass(SUBHEADER_CLASS):wikitext(text)
end
 
 
 
--- Adds the building's tech prerequisite to the provided html node.
---@param div HtmlNode enclosing infobox div
---@param building Building
local function add_tech_prerequisite(div, building)
  local inner_div = div:tag("div"):addClass(TECH_TREE_CLASS)
   local check_icon = "[[File:UI teal open checkmark.png|x16px|link=]]"
  local link_markup = check_icon .. " [[" .. Building_Data_Module.get_name_by_id(building.tech_tree_previous) .. "]]"
  inner_div:tag("div"):wikitext(link_markup)
end
end


Line 65: Line 111:
--- Adds an icon for a resource to the provided html table row.
--- Adds an icon for a resource to the provided html table row.
---@param tr HtmlNode tr
---@param tr HtmlNode tr
---@param resource ResourceRecord
---@param resource Resource
local function add_resource_icon(tr, resource)
local function add_resource_icon(tr, resource)
   local icon_markup = ""
   local icon_markup = ""
Line 75: Line 121:
     icon_markup = "[[" .. file_name .. "|" .. icon_size .. "|" .. name .. "|" .. link_attr .. "]]"
     icon_markup = "[[" .. file_name .. "|" .. icon_size .. "|" .. name .. "|" .. link_attr .. "]]"
   end
   end
   tr:tag("td"):tag("span"):addClass(RESOURCE_ICON_CLASS):wikitext(icon_markup):done():done()
   tr:tag("td"):tag("span"):addClass(RESOURCE_ICON_CLASS)
      :wikitext(icon_markup)
end
end


--- Adds a link for a resource to the provided html table row.
--- Adds a link for a resource to the provided html table row.
---@param tr HtmlNode tr
---@param tr HtmlNode tr
---@param resource ResourceRecord
---@param resource Resource
local function add_resource_link(tr, resource)
local function add_resource_link(tr, resource)
   local link_markup = ""
   local link_markup = ""
Line 86: Line 133:
     link_markup = "[[" .. resource.display_name .. "]]"
     link_markup = "[[" .. resource.display_name .. "]]"
   end
   end
   tr:tag("td"):wikitext(link_markup):done()
   tr:tag("td"):wikitext(link_markup)
end
end


Line 93: Line 140:
---@param building Building
---@param building Building
local function add_construction(div, building)
local function add_construction(div, building)
  if not building.construction_resources or building.construction_resources == {} then return end
   local tbl = div:tag("div"):addClass(CONSTRUCTION_CLASS)
   local tbl = div:tag("div"):addClass(CONSTRUCTION_CLASS):tag("table"):addClass(CONSTRUCTION_TABLE_CLASS)
      :tag("table"):addClass(CONSTRUCTION_TABLE_CLASS)
   for _, pair in ipairs(building.construction_resources) do
   for _, pair in ipairs(building.construction_resources) do
     local tr = tbl:tag("tr")
     local tr = tbl:tag("tr")
     tr:tag("td"):wikitext(pair.amount):done()
     tr:tag("td"):wikitext(pair.amount)
     local resource = Resource_Data_Module.get_resource(pair.name)
     local resource = Resource_Data_Module.get_resource(pair.name)
     add_resource_icon(tr, resource)
     add_resource_icon(tr, resource)
     add_resource_link(tr, resource)
     add_resource_link(tr, resource)
    tr:done()
   end
   end
  return tbl
end
end


Line 112: Line 157:
---@param building Building
---@param building Building
local function add_tasks(div, building)
local function add_tasks(div, building)
   if not building.tasks or building.tasks == {} then return end
   local tbl = div:tag("div"):addClass(TASKS_CLASS)
  div:tag("div"):addClass(TASKS_CLASS)
      :tag("table"):addClass(TASKS_TABLE_CLASS)
  tbl:tag("tr")
          :tag("th"):wikitext("Task"):done()
          :tag("th"):wikitext("(Time)"):done()
      :done()
  for _, task in ipairs(building.tasks) do
    local tr = tbl:tag("tr")
    tr:tag("td"):wikitext(task.task_name)
    tr:tag("td"):wikitext("(" .. task.time .. "s)")
  end
end
end


Line 126: Line 180:
   div:addClass(INFOBOX_CLASS)
   div:addClass(INFOBOX_CLASS)
   add_header(div, building)
   add_header(div, building)
   add_description(div, building)
   if building.description and building.description ~= "" then
   add_construction(div, building)
    add_description(div, building)
   add_tasks(div, building)
   end
  if building.tech_tree_previous and building.tech_tree_previous ~= "" then
    add_subheader(div, "Tech tree prerequisite")
    add_tech_prerequisite(div, building)
  end
  if building.construction_resources and #building.construction_resources > 0 then
    add_subheader(div, "Construction costs")
    add_construction(div, building)
   end
  if building.tasks and #building.tasks > 0 then
    add_subheader(div, "Work")
    add_tasks(div, building)
  end
   return tostring(div)
   return tostring(div)
end
end
--- Appends the wiki category to the provided wikitext.
---@param wikitext string
---@param building Building
---@return string wikitext
local function append_wiki_category(wikitext, building)
  wikitext = wikitext .. "\n[[Category:Buildings]]"
  if building.category and building.category ~= "" then
    wikitext = wikitext .. "\n[[Category:" .. building.category .. " Buildings]]"
  end
  return wikitext
end


--#endregion
--#endregion
Line 147: Line 229:
   if not building then return "" end
   if not building then return "" end
   local wikitext = build_infobox(building)
   local wikitext = build_infobox(building)
  wikitext = append_wiki_category(wikitext, building)
   return wikitext
   return wikitext
end
end

Latest revision as of 00:09, 11 October 2026

Documentation for this module may be created at Module:Building infobox/doc

--[[ 
Test in Scribunto console with:
=p.render({ args = { page_name = "Ore Smelter" } })
]]--
local p = {}



local Building_Data_Module = require("Module:Building_data")
local Resource_Data_Module = require("Module:Resource_data")



--#region html building helper functions

---@diagnostic disable-next-line: duplicate-doc-alias
---@alias HtmlNode table

local INFOBOX_CLASS = "bts-infobox-building"
local HEADER_CLASS = INFOBOX_CLASS .. "-header"
local HEADER_ICON_CLASS = HEADER_CLASS .. "-icon"

local TITLE_CLASS = INFOBOX_CLASS .. "-title"
local SUBTITLE_CLASS = INFOBOX_CLASS .. "-subtitle"
local SUBHEADER_CLASS = INFOBOX_CLASS .. "-subheader"

local DESCRIPTION_CLASS = INFOBOX_CLASS .. "-description"

local TECH_TREE_CLASS = INFOBOX_CLASS .. "-techtree"

local CONSTRUCTION_CLASS = INFOBOX_CLASS .. "-construction"
local CONSTRUCTION_TABLE_CLASS = CONSTRUCTION_CLASS .. "-table"

local RESOURCE_ICON_CLASS = "bts-resource-icon"

local LARGE_ICON_SIZE = "168px"
local MEDIUM_ICON_SIZE = "96px"
local SMALL_ICON_SIZE = "32px"

local TASKS_CLASS = INFOBOX_CLASS .. "-tasks"
local TASKS_TABLE_CLASS = TASKS_CLASS .. "-table"



--- Renders wikitext for the building's icon.
---@param building Building
---@return string wikitext
local function render_icon_markup(building)
  local icon_filename
  local size = LARGE_ICON_SIZE
  if building.portrait_icon then
    icon_filename = building.portrait_icon .. ".png"
  elseif building.icon then
    icon_filename = building.icon .. ".png"
    size = MEDIUM_ICON_SIZE
  else
    return ""
  end
  local image_markup = "[[File:" .. icon_filename .. "|".. size .. "|" .. building.name .. "|link=]]"
  return image_markup
end

--- Adds the header of the infobox to the provided html node.
---@param div HtmlNode enclosing infobox div
---@param building Building
local function add_header(div, building)
  local header = div:tag("div"):addClass(HEADER_CLASS)
  header:tag("div"):addClass(TITLE_CLASS):wikitext(building.display_name)
  header:tag("div"):addClass(HEADER_ICON_CLASS):wikitext(render_icon_markup(building))
  if building.category and building.category ~= "" then
    header:tag("div"):addClass(SUBTITLE_CLASS):wikitext(building.category .. " Building")
  end
end



--- Adds the building's description to the provided html node.
---@param div HtmlNode enclosing infobox div
---@param building Building
local function add_description(div, building)
  local inner_div = div:tag("div"):addClass(DESCRIPTION_CLASS)
  local description = building.description:gsub("<hb>", ""):gsub("</hb>", "")
  description = description:gsub("\n", "<br />")
  inner_div:wikitext(description)
  return inner_div
end



--- Adds a subheader to the provided html node.
---@param div HtmlNode enclosing infobox div
---@param text string
local function add_subheader(div, text)
  div:tag("div"):addClass(SUBHEADER_CLASS):wikitext(text)
end



--- Adds the building's tech prerequisite to the provided html node.
---@param div HtmlNode enclosing infobox div
---@param building Building
local function add_tech_prerequisite(div, building)
  local inner_div = div:tag("div"):addClass(TECH_TREE_CLASS)
  local check_icon = "[[File:UI teal open checkmark.png|x16px|link=]]"
  local link_markup = check_icon .. " [[" .. Building_Data_Module.get_name_by_id(building.tech_tree_previous) .. "]]"
  inner_div:tag("div"):wikitext(link_markup)
end



--- Adds an icon for a resource to the provided html table row.
---@param tr HtmlNode tr
---@param resource Resource
local function add_resource_icon(tr, resource)
  local icon_markup = ""
  if resource and resource.icon then
    local file_name = "File:" .. resource.icon .. ".png"
    local icon_size = "x" .. SMALL_ICON_SIZE
    local name = resource.display_name
    local link_attr = "link=" .. resource.display_name
    icon_markup = "[[" .. file_name .. "|" .. icon_size .. "|" .. name .. "|" .. link_attr .. "]]"
  end
  tr:tag("td"):tag("span"):addClass(RESOURCE_ICON_CLASS)
      :wikitext(icon_markup)
end

--- Adds a link for a resource to the provided html table row.
---@param tr HtmlNode tr
---@param resource Resource
local function add_resource_link(tr, resource)
  local link_markup = ""
  if resource and resource.display_name then
    link_markup = "[[" .. resource.display_name .. "]]"
  end
  tr:tag("td"):wikitext(link_markup)
end

--- Lays out the construction resources in the provided html node.
---@param div HtmlNode enclosing infobox div
---@param building Building
local function add_construction(div, building)
  local tbl = div:tag("div"):addClass(CONSTRUCTION_CLASS)
      :tag("table"):addClass(CONSTRUCTION_TABLE_CLASS)
  for _, pair in ipairs(building.construction_resources) do
    local tr = tbl:tag("tr")
    tr:tag("td"):wikitext(pair.amount)
    local resource = Resource_Data_Module.get_resource(pair.name)
    add_resource_icon(tr, resource)
    add_resource_link(tr, resource)
  end
end



--- Lays out the building's tasks in the provided html node.
---@param div HtmlNode enclosing infobox div
---@param building Building
local function add_tasks(div, building)
  local tbl = div:tag("div"):addClass(TASKS_CLASS)
      :tag("table"):addClass(TASKS_TABLE_CLASS)
  tbl:tag("tr")
          :tag("th"):wikitext("Task"):done()
          :tag("th"):wikitext("(Time)"):done()
      :done()
  for _, task in ipairs(building.tasks) do
    local tr = tbl:tag("tr")
    tr:tag("td"):wikitext(task.task_name)
    tr:tag("td"):wikitext("(" .. task.time .. "s)")
  end
end



--- Builds the infobox wikitext and html for the given building.
---@param building Building
---@return string wikitext
local function build_infobox(building)
  ---@type HtmlNode
  local div = mw.html.create("div")
  div:addClass(INFOBOX_CLASS)
  add_header(div, building)
  if building.description and building.description ~= "" then
    add_description(div, building)
  end
  if building.tech_tree_previous and building.tech_tree_previous ~= "" then
    add_subheader(div, "Tech tree prerequisite")
    add_tech_prerequisite(div, building)
  end
  if building.construction_resources and #building.construction_resources > 0 then
    add_subheader(div, "Construction costs")
    add_construction(div, building)
  end
  if building.tasks and #building.tasks > 0 then
    add_subheader(div, "Work")
    add_tasks(div, building)
  end
  return tostring(div)
end



--- Appends the wiki category to the provided wikitext.
---@param wikitext string
---@param building Building
---@return string wikitext
local function append_wiki_category(wikitext, building)
  wikitext = wikitext .. "\n[[Category:Buildings]]"
  if building.category and building.category ~= "" then
    wikitext = wikitext .. "\n[[Category:" .. building.category .. " Buildings]]"
  end
  return wikitext
end



--#endregion



--- `#invoke` entry point. Reads `page_name` from invoke args (not the parent 
--- template); falls back to the current page title.
---@param frame table Scribunto frame from `#invoke`.
---@return string wikitext Infobox code or empty string if no building exists.
function p.render(frame)
  local args = frame.args or {}
  ---@type string
  local name = args[1] or args.page_name or mw.title.getCurrentTitle().fullText
  local building = Building_Data_Module.get_building(name)
  if not building then return "" end
  local wikitext = build_infobox(building)
  wikitext = append_wiki_category(wikitext, building)
  return wikitext
end



return p