Module:GameData: Difference between revisions
More actions
Show fractionator percentage instead of time, possibly add infobox recipes? |
Add support for oil seeps and oceans (water pumps) |
||
Line 13: | Line 13: | ||
Mine='Mining Machine', |
Mine='Mining Machine', |
||
Gas='Orbital Collector', |
Gas='Orbital Collector', |
||
Ocean='Water Pump', |
|||
Oil='Oil Extractor', |
|||
} |
} |
||
local OilSeepID = 7 |
|||
function funcs.recipesMaking(frame) |
function funcs.recipesMaking(frame) |
||
Line 28: | Line 31: | ||
local vein = veinMakingByID(item.ID) |
local vein = veinMakingByID(item.ID) |
||
local gas = deduplicateGiants(gasGiantsMakingByID(item.ID)) |
local gas = deduplicateGiants(gasGiantsMakingByID(item.ID)) |
||
local isocean = isItemOcean(item.ID) |
|||
return tableRecipes(item, recipes, vein, gas, frame) |
return tableRecipes(item, recipes, vein, gas, isocean, frame) |
||
end |
end |
||
Line 45: | Line 49: | ||
if next(components) then |
if next(components) then |
||
table.insert(output, '=== Components ===') |
table.insert(output, '=== Components ===') |
||
table.insert(output, tableRecipes(item, components, nil, nil, frame)) |
table.insert(output, tableRecipes(item, components, nil, nil, false, frame)) |
||
end |
end |
||
if next(buildings) then |
if next(buildings) then |
||
table.insert(output, '=== Buildings ===') |
table.insert(output, '=== Buildings ===') |
||
table.insert(output, tableRecipes(item, buildings, nil, nil, frame)) |
table.insert(output, tableRecipes(item, buildings, nil, nil, false, frame)) |
||
end |
end |
||
return table.concat(output, '\n') |
return table.concat(output, '\n') |
||
Line 77: | Line 81: | ||
end |
end |
||
function |
function funcs.itemField(frame) |
||
return itemFieldByName(frame:getParent().args[1], frame:getParent().args[2]) |
|||
end |
|||
function funcs.itemFieldDirect(frame) |
|||
return itemFieldByName(frame.args[1], frame.args[2]) |
|||
end |
|||
function itemFieldByName(itemname, fieldname) |
|||
local item = itemByName(itemname) |
|||
return item[fieldname] |
|||
end |
|||
function tableRecipes(item, recipes, vein, gas, isocean, frame) |
|||
local result = {} |
local result = {} |
||
for _, recipe in pairs(recipes) do |
for _, recipe in pairs(recipes) do |
||
Line 97: | Line 113: | ||
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=data}) |
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=data}) |
||
end |
end |
||
if vein and vein.ID == OilSeepID then -- I don't have a better test for oil right now |
|||
⚫ | |||
local extractor = itemByName(machines.Oil) |
|||
local extractorTech = technologyForRecipeID(recipesMakingByID(extractor.ID)[1].ID) |
|||
local oildata = { |
|||
Building = titleCase(extractor.Name), |
|||
Replicator = 'No', |
|||
Technology = titleCase(extractorTech.Name), |
|||
Recipe = oilRecipe(item, vein, frame), |
|||
} |
|||
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=oildata}) |
|||
⚫ | |||
local miner = itemByName(machines.Mine) |
local miner = itemByName(machines.Mine) |
||
local minerTech = technologyForRecipeID(recipesMakingByID(miner.ID)[1].ID) |
local minerTech = technologyForRecipeID(recipesMakingByID(miner.ID)[1].ID) |
||
Line 120: | Line 146: | ||
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=gasdata}) |
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=gasdata}) |
||
end |
end |
||
end |
|||
if isocean then |
|||
local pump = itemByName(machines.Ocean) |
|||
local pumpTech = technologyForRecipeID(recipesMakingByID(pump.ID)[1].ID) |
|||
local oceandata = { |
|||
Building = titleCase(pump.Name), |
|||
Replicator = 'No', |
|||
Technology = titleCase(pumpTech.Name), |
|||
Recipe = oceanRecipe(item, frame) |
|||
} |
|||
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=oceandata}) |
|||
end |
end |
||
local prefix = frame:expandTemplate{title='ProductionChainTable/head', args={}} |
local prefix = frame:expandTemplate{title='ProductionChainTable/head', args={}} |
||
Line 169: | Line 206: | ||
} |
} |
||
return frame:expandTemplate{title='ItemRecipe', args=idata} |
return frame:expandTemplate{title='ItemRecipe', args=idata} |
||
end |
|||
function oilRecipe(item, vein, frame) |
|||
local odata = { |
|||
In1 = titleCase(vein.Name), |
|||
In1Qty = '', |
|||
Out1 = titleCase(item.Name), |
|||
Out1Qty = '1', |
|||
CraftTime = '?', |
|||
} |
|||
return frame:expandTemplate{title='ItemRecipe', args=odata} |
|||
end |
end |
||
Line 183: | Line 231: | ||
end |
end |
||
return frame:expandTemplate{title='ItemRecipe', args=gdata} |
return frame:expandTemplate{title='ItemRecipe', args=gdata} |
||
end |
|||
function oceanRecipe(item, frame) |
|||
local odata = { |
|||
CraftTime = '1.2 s', |
|||
Out1 = titleCase(item.Name), |
|||
Out1Qty = 1, |
|||
} |
|||
return frame:expandTemplate{title='ItemRecipe', args=odata} |
|||
end |
end |
||
Line 264: | Line 321: | ||
end |
end |
||
return giants |
return giants |
||
end |
|||
function isItemOcean(id) |
|||
for _, planet in pairs(protosets.ThemeProtoSet.dataArray) do |
|||
if id == planet.WaterItemId then |
|||
return true |
|||
end |
|||
end |
|||
return false |
|||
end |
end |
||
Revision as of 00:32, 28 April 2024
Source data for this module is stored at Module:GameData/protosets.json
Exported Functions
Each function in this module is exported twice: one as-is for use in templates, and once with a Direct suffix for use directly on pages using {{#invoke|GameData|functionDirect|...}}.
recipesMaking
Arguments: Item Name
Print recipes making an item, given by name. This produces a full table with headers.
Example invocation:
{{#invoke:GameData|recipesMakingDirect|Sulfuric Acid}}
Recipe | Building | Replicator? | Technology |
---|---|---|---|
![]() ![]() |
✖ | ||
![]() |
✖ |
recipesUsing
Arguments: Item Name
Print recipes using an item as an ingredient. Output is separated into two full tables: recipes which create components, and recipes which create buildings. This is selected by the CanBuild property of the produced items.
Example invocation:
{{#invoke:GameData|recipesUsingDirect|Copper Ingot}}
Components
Recipe | Building | Replicator? | Technology |
---|---|---|---|
![]() ![]() ![]() ![]() |
✔ | ||
![]() ![]() ![]() ![]() |
✔ | N/A | |
![]() ![]() ![]() ![]() |
✔ | ||
![]() ![]() ![]() ![]() |
✔ | ||
![]() ![]() ![]() ![]() |
✔ | N/A | |
![]() ![]() ![]() ![]() |
✖ | ||
![]() ![]() ![]() ![]() |
✔ | ||
![]() ![]() ![]() ![]() |
✔ | ||
![]() ![]() ![]() ![]() |
✔ | ||
![]() ![]() ![]() ![]() |
✔ |
Buildings
Recipe | Building | Replicator? | Technology |
---|---|---|---|
![]() ![]() ![]() ![]() |
✔ | ||
![]() ![]() ![]() ![]() |
✔ | ||
![]() ![]() ![]() ![]() |
✔ |
itemRecipes
Arguments: Item Name
Print recipes making an item. This does not produce a full table, and is intended for use in ItemInfo boxes such as at Graphene/ItemInfo.
itemField
Arguments: Item Name, Field Name
Print a field from an item, with the field to print as an argument. You can look at Module:GameData/protosets.json and scroll down or search (Ctrl+F) to the ItemProtoSet to browse fields.
Example invocation:
{{#invoke:GameData|itemFieldDirect|Magnetic Coil|Description}}
It is an extremely useful basic electromagnetic component.
{{#invoke:GameData|itemFieldDirect|Hydrogen|StackSize}}
20
local funcs = {}
local protosets = mw.loadJsonData('Module:GameData/protosets.json')
local machines = {
Smelt='Smelter',
Assemble='Assembling Machine',
Refine='Oil Refinery',
Chemical='Chemical Plant',
Exchange='Energy Exchanger',
Particle='Miniature Particle Collider',
PhotonStore='Ray Receiver',
Fractionate='Fractionator',
Research='Matrix Lab',
Mine='Mining Machine',
Gas='Orbital Collector',
Ocean='Water Pump',
Oil='Oil Extractor',
}
local OilSeepID = 7
function funcs.recipesMaking(frame)
return recipesMakingName(frame:getParent().args[1], frame)
end
function funcs.recipesMakingDirect(frame)
return recipesMakingName(frame.args[1], frame)
end
function recipesMakingName(name, frame)
local item = itemByName(name)
local recipes = recipesMakingByID(item.ID)
local vein = veinMakingByID(item.ID)
local gas = deduplicateGiants(gasGiantsMakingByID(item.ID))
local isocean = isItemOcean(item.ID)
return tableRecipes(item, recipes, vein, gas, isocean, frame)
end
function funcs.recipesUsing(frame)
return recipesUsingName(frame:getParent().args[1], frame)
end
function funcs.recipesUsingDirect(frame)
return recipesUsingName(frame.args[1], frame)
end
function recipesUsingName(name, frame)
local output = {}
local item = itemByName(name)
local components, buildings = recipesUsingByID(item.ID)
if next(components) then
table.insert(output, '=== Components ===')
table.insert(output, tableRecipes(item, components, nil, nil, false, frame))
end
if next(buildings) then
table.insert(output, '=== Buildings ===')
table.insert(output, tableRecipes(item, buildings, nil, nil, false, frame))
end
return table.concat(output, '\n')
end
function funcs.itemRecipes(frame)
return itemRecipesForName(frame:getParent().args[1], frame)
end
function funcs.itemRecipesDirect(frame)
return itemRecipesForName(frame.args[1], frame)
end
function itemRecipesForName(name, frame)
local item = itemByName(name)
local output = {}
for _, r in pairs(recipesMakingByID(item.ID)) do
table.insert(output, itemRecipe(r, frame))
end
local vein = veinMakingByID(item.ID)
if vein then
table.insert(output, veinRecipe(item, vein, frame))
end
for _, giant in pairs(deduplicateGiants(gasGiantsMakingByID(item.ID))) do
table.insert(output, gasGiantRecipe(giant, frame))
end
return table.concat(output, '\n')
end
function funcs.itemField(frame)
return itemFieldByName(frame:getParent().args[1], frame:getParent().args[2])
end
function funcs.itemFieldDirect(frame)
return itemFieldByName(frame.args[1], frame.args[2])
end
function itemFieldByName(itemname, fieldname)
local item = itemByName(itemname)
return item[fieldname]
end
function tableRecipes(item, recipes, vein, gas, isocean, frame)
local result = {}
for _, recipe in pairs(recipes) do
local data = {
Building = titleCase(machines[recipe.Type]),
Recipe = itemRecipe(recipe, frame)
}
if recipe.Handcraft then
data.Replicator = 'Yes'
else
data.Replicator = 'No'
end
local tech = technologyForRecipeID(recipe.ID)
if tech ~= nil then
data.Technology = titleCase(tech.Name)
else
data.Technology = ''
end
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=data})
end
if vein and vein.ID == OilSeepID then -- I don't have a better test for oil right now
local extractor = itemByName(machines.Oil)
local extractorTech = technologyForRecipeID(recipesMakingByID(extractor.ID)[1].ID)
local oildata = {
Building = titleCase(extractor.Name),
Replicator = 'No',
Technology = titleCase(extractorTech.Name),
Recipe = oilRecipe(item, vein, frame),
}
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=oildata})
elseif vein then
local miner = itemByName(machines.Mine)
local minerTech = technologyForRecipeID(recipesMakingByID(miner.ID)[1].ID)
local veindata = {
Building = titleCase(miner.Name),
Replicator = 'Mine',
Technology = titleCase(minerTech.Name),
Recipe = veinRecipe(item, vein, frame),
}
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=veindata})
end
if gas then
local collector = itemByName(machines.Gas)
local collectorTech = technologyForRecipeID(recipesMakingByID(collector.ID)[1].ID)
for _, giant in pairs(gas) do
local gasdata = {
Building = titleCase(collector.Name),
Replicator = 'Mine',
Technology = titleCase(collectorTech.Name),
Recipe = gasGiantRecipe(giant, frame)
}
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=gasdata})
end
end
if isocean then
local pump = itemByName(machines.Ocean)
local pumpTech = technologyForRecipeID(recipesMakingByID(pump.ID)[1].ID)
local oceandata = {
Building = titleCase(pump.Name),
Replicator = 'No',
Technology = titleCase(pumpTech.Name),
Recipe = oceanRecipe(item, frame)
}
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=oceandata})
end
local prefix = frame:expandTemplate{title='ProductionChainTable/head', args={}}
return string.format('%s\n%s\n|}', prefix, table.concat(result, '\n|-\n'))
end
function itemRecipe(recipe, frame)
if recipe.Type == 'Fractionate' then
return fractionateRecipe(recipe, frame)
end
local rdata = {
CraftTime = string.format('%s s', tostring(recipe.TimeSpend/60)),
}
for i, itemid in ipairs(recipe.Results) do
rdata[string.format('Out%d', i)] = titleCase(itemByID(itemid).Name)
rdata[string.format('Out%dQty', i)] = tostring(recipe.ResultCounts[i])
end
for i, itemid in ipairs(recipe.Items) do
rdata[string.format('In%d', i)] = titleCase(itemByID(itemid).Name)
rdata[string.format('In%dQty', i)] = tostring(recipe.ItemCounts[i])
end
return frame:expandTemplate{title='ItemRecipe', args=rdata}
end
function fractionateRecipe(recipe, frame)
local ratio = 100 * recipe.ResultCounts[1] / recipe.ItemCounts[1]
local rdata = {
CraftTime = tostring(ratio) .. '%',
}
for i, itemid in ipairs(recipe.Results) do
rdata[string.format('Out%d', i)] = titleCase(itemByID(itemid).Name)
rdata[string.format('Out%dQty', i)] = '1'
end
for i, itemid in ipairs(recipe.Items) do
rdata[string.format('In%d', i)] = titleCase(itemByID(itemid).Name)
rdata[string.format('In%dQty', i)] = '1'
end
return frame:expandTemplate{title='ItemRecipe', args=rdata}
end
function veinRecipe(item, vein, frame)
local vname = string.gsub(vein.Name, '%sVeins$', ' Vein')
local idata = {
In1 = titleCase(vname),
In1Qty = '1',
Out1 = titleCase(item.Name),
Out1Qty = '1',
CraftTime = '2 s',
}
return frame:expandTemplate{title='ItemRecipe', args=idata}
end
function oilRecipe(item, vein, frame)
local odata = {
In1 = titleCase(vein.Name),
In1Qty = '',
Out1 = titleCase(item.Name),
Out1Qty = '1',
CraftTime = '?',
}
return frame:expandTemplate{title='ItemRecipe', args=odata}
end
function gasGiantRecipe(gas, frame)
local gdata = {
CraftTime = '?',
In1 = titleCase(gas.DisplayName),
In1Qty = '',
}
for i, productID in ipairs(gas.GasItems) do
local product = itemByID(productID)
gdata[string.format('Out%d', i)] = titleCase(product.Name)
gdata[string.format('Out%dQty', i)] = '1'
end
return frame:expandTemplate{title='ItemRecipe', args=gdata}
end
function oceanRecipe(item, frame)
local odata = {
CraftTime = '1.2 s',
Out1 = titleCase(item.Name),
Out1Qty = 1,
}
return frame:expandTemplate{title='ItemRecipe', args=odata}
end
function itemByName(name)
local lame = string.lower(name)
for _, item in pairs(protosets.ItemProtoSet.dataArray) do
if string.lower(item.Name) == lame then
return item
end
end
error('No item named ' .. name)
end
function itemByID(id)
for _, item in pairs(protosets.ItemProtoSet.dataArray) do
if item.ID == id then
return item
end
end
error('No item with ID ' .. id)
end
function recipesMakingByID(id)
local result = {}
for _, recipe in pairs(protosets.RecipeProtoSet.dataArray) do
for _, itemid in pairs(recipe.Results) do
if itemid == id then
table.insert(result, recipe)
break
end
end
end
return result
end
function recipesUsingByID(id)
local components = {}
local buildings = {}
for _, recipe in pairs(protosets.RecipeProtoSet.dataArray) do
for _, itemid in pairs(recipe.Items) do
if itemid == id then
if itemByID(recipe.Results[1]).CanBuild then
table.insert(buildings, recipe)
else
table.insert(components, recipe)
end
break
end
end
end
return components, buildings
end
function technologyForRecipeID(id)
for _, tech in pairs(protosets.TechProtoSet.dataArray) do
for _, recipeid in pairs(tech.UnlockRecipes) do
if recipeid == id then
return tech
end
end
end
return nil
end
function veinMakingByID(id)
for _, vein in pairs(protosets.VeinProtoSet.dataArray) do
if vein.MiningItem == id then
return vein
end
end
return nil
end
function gasGiantsMakingByID(id)
local giants = {}
for _, planet in pairs(protosets.ThemeProtoSet.dataArray) do
for _, item in pairs(planet.GasItems) do
if item == id then
table.insert(giants, planet)
break
end
end
end
return giants
end
function isItemOcean(id)
for _, planet in pairs(protosets.ThemeProtoSet.dataArray) do
if id == planet.WaterItemId then
return true
end
end
return false
end
function deduplicateGiants(giants)
local dedup = {}
for _, planet in pairs(giants) do
new = true
for _, exist in pairs(dedup) do
if string.lower(planet.DisplayName) == string.lower(exist.DisplayName) then
new = false
break
end
end
if new then table.insert(dedup, planet) end
end
return dedup
end
function titleCase(str)
local start = string.gsub(str, '^%l', string.upper)
local title = string.gsub(start, '[-%s]%l', string.upper)
return title
end
return funcs