No edit summary |
No edit summary |
||
Line 71: | Line 71: | ||
for _, f in ipairs(numericFields) do | for _, f in ipairs(numericFields) do | ||
row[f] = tonumber(row[f]) or 0 | row[f] = tonumber(row[f]) or 0 | ||
end | |||
if row.numProduced == 0 then | |||
row.numProduced = 1 | |||
end | end | ||
Line 85: | Line 88: | ||
local ing = tech["ingredient" .. i] | local ing = tech["ingredient" .. i] | ||
---@type integer | ---@type integer | ||
local amt = (tech["amount" .. i]) * | local amt = (tech["amount" .. i]) * multiply | ||
if not ing or ing == "" then | if not ing or ing == "" then | ||
Line 122: | Line 125: | ||
local dataRow = recipeTable:tag("tr") | local dataRow = recipeTable:tag("tr") | ||
for i = 1, 4 do | for i = 1, 4 do | ||
local row = m.ingredient_cell(tech, i, | local row = m.ingredient_cell(tech, i, multiply) | ||
if row then | if row then | ||
dataRow:node(row[1]) | dataRow:node(row[1]) | ||
Line 162: | Line 165: | ||
m.table_header(table, tech) | m.table_header(table, tech) | ||
m.ingredients_row(table, tech, tech.progressCount) | m.ingredients_row(table, tech, tech.progressCount) -- / could be round_up(tech.progressCount / tech.numProduced), but numProduced seems to be always 1 | ||
return tostring(table) | return tostring(table) | ||
end | end | ||
Line 190: | Line 193: | ||
--[[ | --[[ | ||
Debugging: | Debugging: | ||
Return m instead of p if you want to debug those private functions | |||
local frame = { args = { name = "Ultra-tech Framework" } } | local frame = { args = { name = "Ultra-tech Framework" } } |
Revision as of 00:35, 12 August 2025
Description
The recipe part of the tech pages.
If new research components are added to the game, UPLINK_REPLACEMENTS
needs be extended to enable replacing the component with the related building. Otherwise it will just show the new component instead.
Usage
Example
{{#invoke:TechRecipe|render|name=<techName>}}
Example
The following call:
{{#invoke:TechRecipe|render|name=Ultra-tech Framework}}
Results in:
Fused Electrodes | IC Chip | Robotics Research | Ultra-tech Framework | |
---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() |
Fused Electrodes | IC Chip | Robotics Research | Ultra-tech Framework | |
---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() |
local p = {}
local m = {} -- you can use this one for debugging without exposing functions, return this instead of p
---@type any
---@diagnostic disable-next-line: lowercase-global
mw = mw
-- Mirror tech cargo table
---@class TechCargo
---@field name string
---@field luaId string
---@field description string
---@field category string
---@field texture string
---@field requiredTech1 string
---@field requiredTech2 string
---@field requiredTech3 string
---@field progressCount integer
---@field ingredient1 string
---@field amount1 integer
---@field ingredient2 string
---@field amount2 integer
---@field ingredient3 string
---@field amount3 integer
---@field ingredient4 string
---@field amount4 integer
---@field producer1 string
---@field time1 number
---@field producer2 string
---@field time2 number
---@field producer3 string
---@field time3 number
---@field producer4 string
---@field time4 number
---@field recipeType string
---@field numProduced integer
---@param name string
function m.get_tech_cargo_data(name)
local fields = "name, luaId, description, category, texture, " ..
"requiredTech1, requiredTech2, requiredTech3, " ..
"progressCount, " ..
"ingredient1, amount1, " ..
"ingredient2, amount2, " ..
"ingredient3, amount3, " ..
"ingredient4, amount4, " ..
"producer1, time1, " ..
"producer2, time2, " ..
"producer3, time3, " ..
"producer4, time4, " ..
"recipeType, numProduced"
local results = mw.ext.cargo.query(
"tech", -- table name
fields, -- fields list
{ where = string.format("name = '%s'", name) }
)
if not results or not results[1] then
return nil
end
local row = results[1]
local numericFields = {
"progressCount",
"amount1", "amount2", "amount3", "amount4",
"time1", "time2", "time3", "time4",
"numProduced"
}
for _, f in ipairs(numericFields) do
row[f] = tonumber(row[f]) or 0
end
if row.numProduced == 0 then
row.numProduced = 1
end
---@cast row TechCargo
return row
end
-- Helper: creates a table cell for an ingredient
---@param tech TechCargo The tech cargo object
---@param i integer Ingredient index (1–4)
---@param multiply integer Amount multiplier
---@return table|nil An html <td> element or nil if no ingredient
m.ingredient_cell = function(tech, i, multiply)
local ing = tech["ingredient" .. i]
---@type integer
local amt = (tech["amount" .. i]) * multiply
if not ing or ing == "" then
return nil
end
return {
mw.html.create("td")
:wikitext(string.format(
"[[File:%s.png|64x64px|link=%s|alt=%s]] %i",
ing, ing, ing, amt
))
}
end
-- Insert a 6 cells header
---@param recipeTable table
---@param tech TechCargo
m.table_header = function(recipeTable, tech)
local headerRow = recipeTable:tag("tr")
for i = 1, 4 do
if tech["ingredient"..i] and tech["ingredient"..i] ~= "" then
headerRow:tag("th"):wikitext(string.format("[[%s]]", tech["ingredient"..i])):done()
end
end
-- Empty cell, for arrow under it
headerRow:tag("th"):done()
headerRow:tag("th"):wikitext(tech.name):done()
end
-- Insert a 6 cells row
---@param recipeTable table
---@param tech TechCargo
---@param multiply integer Multiply all counts by this
m.ingredients_row = function(recipeTable, tech, multiply)
local dataRow = recipeTable:tag("tr")
for i = 1, 4 do
local row = m.ingredient_cell(tech, i, multiply)
if row then
dataRow:node(row[1])
end
end
dataRow:tag("td"):wikitext("[[File:Arrow_Right.png|link=Arrow Right|alt=Arrow Right|32x32px]]"):done()
dataRow:tag("td"):wikitext(string.format("[[File:%s.png|64x64px|link=Technology/%s|alt=%s]]",
tech.name, tech.name, tech.name)):done()
end
---@param tech TechCargo
m.recipe_table = function(tech)
local table = mw.html.create("table")
table
:addClass("wikitable")
:tag("caption"):wikitext("Recipe"):done()
m.table_header(table, tech)
m.ingredients_row(table, tech, 1)
return tostring(table)
end
---@param tech TechCargo
m.produced_by_table = function(tech)
local table = mw.html.create("table")
table
:addClass("wikitable")
:tag("caption"):wikitext("Produced by"):done()
return tostring(table)
end
---@param tech TechCargo
m.total_requirements_table = function(tech)
local table = mw.html.create("table")
table
:addClass("wikitable")
:tag("caption"):wikitext("Total Requirements"):done()
m.table_header(table, tech)
m.ingredients_row(table, tech, tech.progressCount) -- / could be round_up(tech.progressCount / tech.numProduced), but numProduced seems to be always 1
return tostring(table)
end
--- Main function
---@param name string
m.render = function(name)
local tech = m.get_tech_cargo_data(name)
if not tech then
return "(Recipe not found)"
end
local result =
m.recipe_table(tech)
.. m.produced_by_table(tech)
.. m.total_requirements_table(tech)
return result
end
p.render = function (frame)
return m.render(frame.args.name)
end
return p
--[[
Debugging:
Return m instead of p if you want to debug those private functions
local frame = { args = { name = "Ultra-tech Framework" } }
(enter)
= p.render(frame)
(enter)
--]]