- 欢迎光临Satisfactory国区BWIKI。请登录您的B站账号,方可使用页面编辑与评论功能。
全站通知:
模块:RenderCraftingRecipesTable
刷
历
编
跳到导航
跳到搜索
此模块的文档可以在模块:RenderCraftingRecipesTable/doc创建
local cargo = mw.ext.cargo
local moduleTooltips = require('Module:ItemTooltip')
local p = {}
local buildings = {}
local experimental_style = 'position:absolute; font-variant:all-small-caps; font-size:small; font-weight:bold; left:0; top:0; transform: rotate(-45deg) translate(-15px, -5px); background:red; color:white; padding: 1px 20px;'
local unreleased_style = 'position: absolute; font-variant: all-small-caps; font-size: smaller; left: 0; width: 100%; font-weight: bold; background: repeating-linear-gradient( -45deg, yellow, yellow 8px, black 8px, black 16px); color: black; text-shadow: -1px -1px 0 #fff, -1px 1px 0 #fff, 1px -1px 0 #fff, 1px 1px 0 #fff; padding-bottom: 2px;'
local function loadBuildingsPower()
local tables = 'buildings'
local fields = 'name, powerUsage'
local args = { where = 'powerUsage > 0' }
local result = cargo.query(tables, fields, args)
buildings = {}
for _, building in pairs(result) do
buildings[building.name] = tonumber(building.powerUsage)
end
end
local function round(num, numDecimalPlaces)
local mult = 10^(numDecimalPlaces or 0)
return math.floor(num * mult + 0.5) / mult
end
local function generateRecipeTableRow(recipe, useItemTooltips)
local html = ''
-- fix some parameters
recipe.alternateRecipe = (tonumber(recipe.alternateRecipe) or 0) > 0
recipe.inCraftBench = (tonumber(recipe.inCraftBench) or 0) > 0
recipe.inWorkShop = (tonumber(recipe.inWorkShop) or 0) > 0
recipe.craftingTime = tonumber(recipe.craftingTime) or 0
if recipe.craftedIn == nil or #tostring(recipe.craftedIn) <= 1 then -- <=1 instead of ==0 just in case of \n or single space characters; normally craftedIn is a long word
if recipe.inWorkShop then
recipe.craftedIn = 'Equipment Workshop'
elseif recipe.inCraftBench then
recipe.craftedIn = 'Craft Bench'
else
recipe.craftedIn = 'Build Gun'
end
end
-- split ingredients and products from recipe into separate arrays
local ingredients = {}
for i=1, 9, 1 do
local item = recipe["ingredient" .. i]
if item ~= nil and #item > 0 then
ingredients[i] = { name = item, amount = tonumber(recipe["quantity" .. i]) or 1 }
end
end
local products = {}
for i=1, 4, 1 do
local item = recipe["product" .. i]
if item ~= nil and #item > 0 then
products[i] = { name = item, amount = tonumber(recipe["productCount" .. i]) or 1 }
end
end
-- calculations for table cells
local ingredientsCols = #ingredients <= 1 and 1 or math.max(2, math.ceil(#ingredients/2))
local ingredientsRows = math.ceil(#ingredients/ingredientsCols)
local ingredientsColspan = 12 / ingredientsCols -- ingredients column is 12 columns wide (with colspan) to be divisible by 1, 2, 3 or 4
local productsCols = #products <= 1 and 1 or math.max(2, math.ceil(#products/2))
local productsRows = math.ceil(#products/productsCols)
local productsColspan = 2 / productsCols
local maxRows = math.max(ingredientsRows, productsRows)
local ingredientsRowspan = maxRows / ingredientsRows
local productsRowspan = maxRows / productsRows
local ingredientCells = {}
local productCells = {}
-- function generates HTML for ingredients/products cells and stores generated code in targetTable array
local function generateCells(list, rowspan, colspan, targetTable, addEnergyPerItem)
for i=1, #list, 1 do
local td = '<td style="border:0; line-height:1; padding:0.5em" rowspan="' .. rowspan .. '" colspan="' .. colspan .. '">'
local ipm = 60 / recipe.craftingTime * list[i].amount
if useItemTooltips then
--td = td .. mw.getCurrentFrame():expandTemplate{title = 'ItemTooltip', args = { list[i].name, list[i].amount }}
td = td .. moduleTooltips.getTooltip{ args = { item = list[i].name, amount = list[i].amount, size = 40 } }
else
td = td .. '<div style="line-height:1"><div style="font-size:medium; display:inline-table">' .. list[i].amount .. ' × [[Image:' .. list[i].name .. '.png|40px|link=' .. list[i].name .. ']]</br>'
td = td .. '<div style="font-size:x-small; text-align:right">' .. list[i].name .. '</div></div></div>'
end
if recipe.craftingTime > 0 then
td = td .. '<div style="font-weight:bold; line-height:2">' .. ipm .. ' / min</div>'
-- calculate energy per item
if addEnergyPerItem then
buildingPower = buildings[recipe.craftedIn]
if buildingPower ~= nil then
local displayText = round(recipe.craftingTime * buildingPower / list[i].amount, 2) .. ' MJ / item'
local tooltipText = 'The energy consumed by ' .. recipe.craftedIn .. ' to craft 1 item at 100% clock'
td = td .. '<div style="font-size:x-small; line-height:1; border:solid 1px cornflowerblue; border-radius:0.5em; background-color:aliceblue; padding:0.08em 0.4em; display:inline">' .. mw.getCurrentFrame():expandTemplate{title='Tooltip', args={[1]=displayText, [2]=tooltipText, [3]='no underline'}} .. '</div>'
end
end
else
-- if no craftingTime and no ipm to display then add some empty block for proper spacing
td = td .. '<div style="font-weight:bold; line-height:2"> </div>'
end
td = td .. '</td>'
targetTable[i] = td
end
-- odd amount of ingredients/products leaves one empty cell in the column, which should be filled by a blank cell
-- also generate one empty cell when there's no ingredients/products at all
if #list == 0 or #list > 1 and #list % 2 == 1 then
targetTable[#targetTable+1] = '<td style="border:0" rowspan="' .. rowspan .. '" colspan="' .. colspan .. '"> </td>'
end
end
-- generate all ingredients and products cells
generateCells(ingredients, ingredientsRowspan, ingredientsColspan, ingredientCells)
generateCells(products, productsRowspan, productsColspan, productCells, true) -- for products add energy per item
-- assemble the table
for i=1, maxRows, 1 do
-- recipe name column
if i == 1 then
recipeName = recipe.recipeName
if (recipeName == Null or recipeName == '') then recipeName = recipe.product1 end
if (recipeName == Null or recipeName == '') then recipeName = 'Not specified' end
if recipe.alternateRecipe then
recipeName = recipeName .. '</br>' .. '<span style="text-transform:uppercase; font-size:x-small; background-color:cornsilk; padding:0.1em 0.4em; border-radius:0;border:solid 1px orange">[[Hard Drive|Alternate]]</span>'
end
local stripe = ''
if recipe.experimental == '1' then
stripe = '<div style="' .. experimental_style .. '">'
.. mw.getCurrentFrame():expandTemplate{title='Tooltip', args={[1]='Exp', [2]='This recipe is available only in Experimental version of Satisfactory', [3]='no underline'}}
.. '</div>'
elseif recipe.unreleased == '1' then
stripe = '<div style="' .. unreleased_style .. ' top:0;">'
.. mw.getCurrentFrame():expandTemplate{title='Tooltip', args={[1]='Unreleased', [2]='This recipe is not obtainable ingame. It was either datamined or removed from the game.', [3]='no underline'}}
.. '</div>'
.. '<div style="' .. unreleased_style .. ' bottom:0;"> </div>'
end
html = html
.. '<tr class="firstRow" style="border-top: 2px solid #575757">'
.. '<td rowspan="' .. maxRows .. '" style="line-height:1; position:relative; overflow:hidden;">'
.. recipeName
.. stripe
.. '</td>'
else
html = html .. '<tr>'
end
-- ingredients column
for j=1, ingredientsCols, 1 do
local index = (i-1)*ingredientsCols+j
if index <= #ingredientCells then
html = html .. ingredientCells[index]
end
end
-- building column
if i == 1 then
html = html .. '<td rowspan="' .. maxRows .. '"><span style="font-size:large">[[' .. recipe.craftedIn .. ']]</span>'
if recipe.craftingTime > 0 then
html = html .. '</br>' .. recipe.craftingTime .. ' sec'
end
if recipe.inCraftBench or recipe.inWorkShop then
local displayText = '[[File:Manual crafting.png|16px]] × ' .. recipe.craftingClicks
local tooltipText = 'Manual crafting speed : ' .. 240 / (tonumber(recipe.craftingClicks) or 0) * (tonumber(recipe.productCount1) or 1) .. ' / min'
html = html ..'</br>' .. mw.getCurrentFrame():expandTemplate{title='Tooltip', args={[1]=displayText, [2]=tooltipText, [3]='no underline'}}
end
html = html .. '</td>'
end
-- products column
for j=1, productsCols, 1 do
local index = (i-1)*productsCols+j
if index <= #productCells then
html = html .. productCells[index]
end
end
-- prerequisites column
if i == 1 then
html = html .. '<td rowspan="' .. maxRows .. '"><span style="text-align:left;">' .. recipe.researchTier .. '</span></td>'
end
html = html .. '</tr>'
end
return html
end
local fields = 'recipeName, alternateRecipe, mainRecipe, craftedIn, inCraftBench, inWorkShop, craftingTime, craftingClicks, researchTier, unreleased, experimental, product=product1, product2, product3, product4, productCount=productCount1, productCount2, productCount3, productCount4, ingredient1, quantity1, ingredient2, quantity2, ingredient3, quantity3, ingredient4, quantity4, ingredient5, quantity5, ingredient6, quantity6, ingredient7, quantity7, ingredient8, quantity8'
local function generateTable(recipes, useItemTooltips)
local html = '<table class="wikitable" style="text-align:center"><tr><th>Recipe</th><th colspan="12">Ingredients</th><th>Building</th><th colspan="2">Products</th><th>Prerequisites</th></tr>'
for i=1, #recipes, 1 do
html = html .. generateRecipeTableRow(recipes[i], useItemTooltips)
end
html = html .. '</table>'
return html
end
function p.generateCraftingRecipes(frame)
local itemName = frame.args.item or frame.args[1]
local useItemTooltips = frame.args.tooltips and (#frame.args.tooltips > 0) or false
local experimental = frame.args.experimental and (#frame.args.experimental > 0) or false
local experimentalCondition = experimental and ' and (experimental=True)' or ' and (experimental is null or experimental=False)'
local tables = 'crafting_recipes'
local args = { where = '(product="' .. itemName .. '" or product2="' .. itemName .. '" or product3="' .. itemName .. '" or product4="' .. itemName .. '")' .. experimentalCondition,
orderBy = 'mainRecipe DESC, alternateRecipe ASC' }
local recipes = cargo.query(tables, fields, args)
if #recipes > 0 then
loadBuildingsPower()
return generateTable(recipes, useItemTooltips)
else
return "'''" .. itemName .. "''' can't be crafted."
end
end
function p.generateCraftingUsage(frame)
local itemName = frame.args.item or frame.args[1]
local useItemTooltips = frame.args.tooltips and (#frame.args.tooltips > 0) or false
local experimental = frame.args.experimental and (#frame.args.experimental > 0) or false
local unreleased = frame.args.unreleased and (#frame.args.unreleased > 0) or false
local experimentalCondition = experimental and ' and (experimental=True)' or ' and (experimental is null or experimental=False)'
local unreleasedCondition = unreleased and '' or ' and (unreleased is null or unreleased=False)'
local tables = 'crafting_recipes'
local args = { where = 'product IS NOT NULL and _pageName NOT LIKE "%/%" and (ingredient1="' .. itemName .. '" or ingredient2="' .. itemName .. '" or ingredient3="' .. itemName .. '" or ingredient4="' .. itemName .. '" or ingredient5="' .. itemName .. '" or ingredient6="' .. itemName .. '" or ingredient7="' .. itemName .. '" or ingredient8="' .. itemName .. '" or ingredient9="' .. itemName .. '" or ingredient10="' .. itemName .. '")' .. experimentalCondition .. unreleasedCondition,
orderBy = '(craftedIn IS NOT NULL or inWorkShop or inCraftBench) DESC, product ASC, alternateRecipe ASC' }
local recipes = cargo.query(tables, fields, args)
if #recipes > 0 then
loadBuildingsPower()
return generateTable(recipes, useItemTooltips)
else
return "'''" .. itemName .. "''' isn't used to craft anything."
end
end
return p