(Ensure Technologies are Title Cased (Curse you Polymer chemical engineering!)) |
(Add Dark Fog drop to list of recipes making items) |
||
(13 intermediate revisions by the same user not shown) | |||
Line 11: | Line 11: | ||
Fractionate='Fractionator', | Fractionate='Fractionator', | ||
Research='Matrix Lab', | Research='Matrix Lab', | ||
Mine='Mining Machine', | |||
Gas='Orbital Collector', | |||
Ocean='Water Pump', | |||
Oil='Oil Extractor', | |||
} | } | ||
local OilSeepID = 7 | |||
-- exported functions | |||
-- recipesMaking | |||
-- print out table rows of all recipes making an item with full information | |||
-- the recipe, the building, technology to unlock it, etc. | |||
function funcs.recipesMaking(frame) | function funcs.recipesMaking(frame) | ||
return recipesMakingName(frame:getParent().args[1], frame) | |||
end | end | ||
function funcs.recipesMakingDirect(frame) | function funcs.recipesMakingDirect(frame) | ||
return recipesMakingName(frame.args[1], frame) | |||
end | end | ||
function recipesMakingName(name, frame) | |||
local rtable = { | |||
frame:expandTemplate{title='ProductionChainTable/head', args={}}, | |||
} | |||
local item = itemByName(name) | |||
for _, recipe in ipairs(recipesMakingByID(item.ID)) do | |||
table.insert(rtable, recipeRow(recipe, frame)) | |||
end | |||
local vein = veinMakingByID(item.ID) | |||
if vein ~= nil then | |||
table.insert(rtable, veinRow(item, vein, frame)) | |||
end | |||
for _, giant in ipairs(deduplicateGiants(gasGiantsMakingByID(item.ID))) do | |||
table.insert(rtable, gasGiantRow(item, giant, frame)) | |||
end | |||
if isItemOcean(item.ID) then | |||
table.insert(rtable, oceanRow(item, frame)) | |||
end | |||
if isItemFogDrop(item) then | |||
table.insert(rtable, fogDropRow(item, frame)) | |||
end | |||
table.insert(rtable, '|}') | |||
return table.concat(rtable, '\n') | |||
end | |||
-- recipesUsing | |||
-- print out table rows of all recipes using an item with full information, like recipesMaking | |||
-- split output into components and buildings | |||
function funcs.recipesUsing(frame) | function funcs.recipesUsing(frame) | ||
output = {} | return recipesUsingName(frame:getParent().args[1], frame) | ||
end | |||
item = itemByName(name) | |||
components | function funcs.recipesUsingDirect(frame) | ||
return recipesUsingName(frame.args[1], frame) | |||
end | |||
function recipesUsingName(name, frame) | |||
local output = {} | |||
local header = frame:expandTemplate{title='ProductionChainTable/head', args={}} | |||
local item = itemByName(name) | |||
local components = {} | |||
local buildings = {} | |||
for _, r in ipairs(recipesUsingByID(item.ID)) do | |||
if r.GridIndex >= 2000 then | |||
table.insert(buildings, r) | |||
else | |||
table.insert(components, r) | |||
end | |||
end | |||
if next(components) then | if next(components) then | ||
table.insert(output, '=== Components ===') | if next(buildings) then | ||
table.insert(output, | table.insert(output, '=== Components ===') | ||
end | |||
table.insert(output, header) | |||
for _, recipe in ipairs(components) do | |||
table.insert(output, recipeRow(recipe, frame)) | |||
end | |||
table.insert(output, '|}') | |||
end | end | ||
if next(buildings) then | if next(buildings) then | ||
table.insert(output, '=== Buildings ===') | if next(components) then | ||
table.insert(output, | table.insert(output, '=== Buildings ===') | ||
end | |||
table.insert(output, header) | |||
for _, recipe in ipairs(buildings) do | |||
table.insert(output, recipeRow(recipe, frame)) | |||
end | |||
table.insert(output, '|}') | |||
end | end | ||
return table.concat(output, '\n') | return table.concat(output, '\n') | ||
end | end | ||
function funcs. | -- itemRecipes | ||
-- print out just recipe information on how to make an item | |||
-- intended for use in ItemInfo boxes | |||
item = itemByName(name) | |||
function funcs.itemRecipes(frame) | |||
if | return itemRecipesForName(frame:getParent().args[1], frame) | ||
table.insert(output, | end | ||
table.insert(output, | function funcs.itemRecipesDirect(frame) | ||
return itemRecipesForName(frame.args[1], frame) | |||
end | |||
function itemRecipesForName(name, frame) | |||
local item = itemByName(name) | |||
local output = {} | |||
for _, r in ipairs(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 ipairs(deduplicateGiants(gasGiantsMakingByID(item.ID))) do | |||
table.insert(output, gasGiantRecipe(giant, frame)) | |||
end | end | ||
if | if isItemOcean(item.ID) then | ||
table.insert(output, | table.insert(output, oceanRecipe(item, frame)) | ||
end | end | ||
return table.concat(output, '\n') | return table.concat(output, '\n') | ||
end | end | ||
function | -- itemField | ||
-- print a field from an item | |||
for | -- used to extract details about an item | ||
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) | |||
end | local item = itemByName(itemname) | ||
return item[fieldname] | |||
Building = | end | ||
Recipe = frame:expandTemplate{title=' | |||
-- make full rows and recipe data for tables | |||
function recipeRow(recipe, frame) | |||
local rdata = { | |||
Building = titleCase(machines[recipe.Type]), | |||
} | |||
if recipe.Type == 'Fractionate' then | |||
rdata.Recipe = fractionateRecipe(recipe, frame) | |||
else | |||
rdata.Recipe = itemRecipe(recipe, frame) | |||
end | |||
if recipe.Handcraft then | |||
rdata.Replicator = 'Yes' | |||
else | |||
rdata.Replicator = 'No' | |||
end | |||
local tech = technologyForRecipeID(recipe.ID) | |||
if tech ~= nil then | |||
rdata.Technology = titleCase(tech.Name) | |||
else | |||
rdata.Technology = '' | |||
end | |||
local productive = not recipe.NonProductive | |||
for i, itemid in ipairs(recipe.Items) do | |||
productive = productive and itemByID(itemid).Productive | |||
end | |||
if productive then | |||
rdata.Proliferator = 'Yes' | |||
else | |||
rdata.Proliferator = 'Speed' | |||
end | |||
return '|-\n| ' .. frame:expandTemplate{title='ProductionChain', args=rdata} | |||
end | |||
function itemRecipe(recipe, frame) | |||
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 veinRow(item, vein, frame) | |||
if 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), | |||
Proliferator='No', | |||
} | |||
return '|-\n| ' .. frame:expandTemplate{title='ProductionChain', args=oildata} | |||
else | |||
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), | |||
Proliferator='No', | |||
} | } | ||
return '|-\n| ' .. frame:expandTemplate{title='ProductionChain', args=veindata} | |||
end | |||
end | |||
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 gasGiantRow(item, giant, frame) | |||
local collector = itemByName(machines.Gas) | |||
local collectorTech = technologyForRecipeID(recipesMakingByID(collector.ID)[1].ID) | |||
local giantdata = { | |||
Building = titleCase(collector.Name), | |||
Replicator = 'Mine', | |||
Technology = titleCase(collectorTech.Name), | |||
Recipe = gasGiantRecipe(giant, frame), | |||
Proliferator='No', | |||
} | |||
return '|-\n| ' .. frame:expandTemplate{title='ProductionChain', args=giantdata} | |||
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 | end | ||
return frame:expandTemplate{title='ItemRecipe', args=gdata} | |||
end | end | ||
function fogDropRow(item, frame) | |||
local fogdata = { | |||
Building = 'Raider', | |||
Replicator = 'No', | |||
Recipe = fogDropRecipe(item, frame), | |||
Proliferator = 'No', | |||
} | |||
return '|-\n| ' .. frame:expandTemplate{title='ProductionChain', args=fogdata} | |||
end | |||
function fogDropRecipe(item, frame) | |||
local prob = item.EnemyDropRange.y * 300 | |||
local level = item.EnemyDropLevel * 3 | |||
local dropMin = item.EnemyDropCount * 2 * (item.EnemyDropLevel / 10 + 1) | |||
local dropMax = item.EnemyDropCount * 4 | |||
local fogdata = { | |||
CraftTime = string.format('%.2f%%', prob), | |||
Out1 = item.Name, | |||
Out1Qty = string.format('%.1f-%.1f', dropMin, dropMax), | |||
In1 = 'Raider', | |||
In1Qty = string.format('Lvl %d+', level), | |||
} | |||
return frame:expandTemplate{title='ItemRecipe', args=fogdata} | |||
end | |||
function oceanRow(item, frame) | |||
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), | |||
Proliferator='No', | |||
} | |||
return '|-\n| ' .. frame:expandTemplate{title='ProductionChain', args=oceandata} | |||
end | |||
function oceanRecipe(item, frame) | |||
local odata = { | |||
CraftTime = '1.2 s', | |||
Out1 = titleCase(item.Name), | |||
Out1Qty = 1, | |||
In1 = titleCase(item.MiningFrom), | |||
In1Qty = '', | |||
} | |||
return frame:expandTemplate{title='ItemRecipe', args=odata} | |||
end | |||
-- get data from protosets | |||
function itemByName(name) | function itemByName(name) | ||
for _, item in | local lame = string.lower(name) | ||
if item.Name == | for _, item in ipairs(protosets.ItemProtoSet.dataArray) do | ||
if string.lower(item.Name) == lame then | |||
return item | return item | ||
end | end | ||
Line 102: | Line 353: | ||
end | end | ||
function itemByID(id) | function itemByID(id) | ||
for _, item in | for _, item in ipairs(protosets.ItemProtoSet.dataArray) do | ||
if item.ID == id then | if item.ID == id then | ||
return item | return item | ||
Line 111: | Line 362: | ||
function recipesMakingByID(id) | function recipesMakingByID(id) | ||
result = {} | local result = {} | ||
for _, recipe in | for _, recipe in ipairs(protosets.RecipeProtoSet.dataArray) do | ||
for _, itemid in | for _, itemid in ipairs(recipe.Results) do | ||
if itemid == id then | if itemid == id then | ||
table.insert(result, recipe) | table.insert(result, recipe) | ||
Line 123: | Line 374: | ||
end | end | ||
function recipesUsingByID(id) | function recipesUsingByID(id) | ||
local recipes = {} | |||
for _, recipe in ipairs(protosets.RecipeProtoSet.dataArray) do | |||
for _, recipe in | for _, itemid in ipairs(recipe.Items) do | ||
for _, itemid in | |||
if itemid == id then | if itemid == id then | ||
table.insert(recipes, recipe) | |||
break | break | ||
end | end | ||
end | end | ||
end | end | ||
return | return recipes | ||
end | end | ||
function technologyForRecipeID(id) | function technologyForRecipeID(id) | ||
for _, tech in | for _, tech in ipairs(protosets.TechProtoSet.dataArray) do | ||
for _, recipeid in | for _, recipeid in ipairs(tech.UnlockRecipes) do | ||
if recipeid == id then | if recipeid == id then | ||
return tech | return tech | ||
Line 150: | Line 396: | ||
return nil | return nil | ||
end | end | ||
function veinMakingByID(id) | |||
for _, vein in ipairs(protosets.VeinProtoSet.dataArray) do | |||
if vein.MiningItem == id then | |||
return vein | |||
end | |||
end | |||
return nil | |||
end | |||
function gasGiantsMakingByID(id) | |||
local giants = {} | |||
for _, planet in ipairs(protosets.ThemeProtoSet.dataArray) do | |||
for _, item in ipairs(planet.GasItems) do | |||
if item == id then | |||
table.insert(giants, planet) | |||
break | |||
end | |||
end | |||
end | |||
return giants | |||
end | |||
function isItemOcean(id) | |||
for _, planet in ipairs(protosets.ThemeProtoSet.dataArray) do | |||
if id == planet.WaterItemId then | |||
return true | |||
end | |||
end | |||
return false | |||
end | |||
function isItemFogDrop(item) | |||
return item.EnemyDropRange.y > 0 | |||
end | |||
-- sorting/deduplication | |||
function deduplicateGiants(giants) | |||
local dedup = {} | |||
for _, planet in ipairs(giants) do | |||
new = true | |||
for _, exist in ipairs(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 | |||
-- display formatting | |||
function titleCase(str) | function titleCase(str) | ||
start | local start = string.gsub(str, '^%l', string.upper) | ||
title | local title = string.gsub(start, '[-%s]%l', string.upper) | ||
return | local mk = string.gsub(title, 'MK.I', 'Mk.I') | ||
return mk | |||
end | end | ||
return funcs | return funcs |
Latest revision as of 00:07, 19 July 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
-- exported functions
-- recipesMaking
-- print out table rows of all recipes making an item with full information
-- the recipe, the building, technology to unlock it, etc.
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 rtable = {
frame:expandTemplate{title='ProductionChainTable/head', args={}},
}
local item = itemByName(name)
for _, recipe in ipairs(recipesMakingByID(item.ID)) do
table.insert(rtable, recipeRow(recipe, frame))
end
local vein = veinMakingByID(item.ID)
if vein ~= nil then
table.insert(rtable, veinRow(item, vein, frame))
end
for _, giant in ipairs(deduplicateGiants(gasGiantsMakingByID(item.ID))) do
table.insert(rtable, gasGiantRow(item, giant, frame))
end
if isItemOcean(item.ID) then
table.insert(rtable, oceanRow(item, frame))
end
if isItemFogDrop(item) then
table.insert(rtable, fogDropRow(item, frame))
end
table.insert(rtable, '|}')
return table.concat(rtable, '\n')
end
-- recipesUsing
-- print out table rows of all recipes using an item with full information, like recipesMaking
-- split output into components and buildings
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 header = frame:expandTemplate{title='ProductionChainTable/head', args={}}
local item = itemByName(name)
local components = {}
local buildings = {}
for _, r in ipairs(recipesUsingByID(item.ID)) do
if r.GridIndex >= 2000 then
table.insert(buildings, r)
else
table.insert(components, r)
end
end
if next(components) then
if next(buildings) then
table.insert(output, '=== Components ===')
end
table.insert(output, header)
for _, recipe in ipairs(components) do
table.insert(output, recipeRow(recipe, frame))
end
table.insert(output, '|}')
end
if next(buildings) then
if next(components) then
table.insert(output, '=== Buildings ===')
end
table.insert(output, header)
for _, recipe in ipairs(buildings) do
table.insert(output, recipeRow(recipe, frame))
end
table.insert(output, '|}')
end
return table.concat(output, '\n')
end
-- itemRecipes
-- print out just recipe information on how to make an item
-- intended for use in ItemInfo boxes
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 ipairs(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 ipairs(deduplicateGiants(gasGiantsMakingByID(item.ID))) do
table.insert(output, gasGiantRecipe(giant, frame))
end
if isItemOcean(item.ID) then
table.insert(output, oceanRecipe(item, frame))
end
return table.concat(output, '\n')
end
-- itemField
-- print a field from an item
-- used to extract details about an item
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
-- make full rows and recipe data for tables
function recipeRow(recipe, frame)
local rdata = {
Building = titleCase(machines[recipe.Type]),
}
if recipe.Type == 'Fractionate' then
rdata.Recipe = fractionateRecipe(recipe, frame)
else
rdata.Recipe = itemRecipe(recipe, frame)
end
if recipe.Handcraft then
rdata.Replicator = 'Yes'
else
rdata.Replicator = 'No'
end
local tech = technologyForRecipeID(recipe.ID)
if tech ~= nil then
rdata.Technology = titleCase(tech.Name)
else
rdata.Technology = ''
end
local productive = not recipe.NonProductive
for i, itemid in ipairs(recipe.Items) do
productive = productive and itemByID(itemid).Productive
end
if productive then
rdata.Proliferator = 'Yes'
else
rdata.Proliferator = 'Speed'
end
return '|-\n| ' .. frame:expandTemplate{title='ProductionChain', args=rdata}
end
function itemRecipe(recipe, frame)
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 veinRow(item, vein, frame)
if 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),
Proliferator='No',
}
return '|-\n| ' .. frame:expandTemplate{title='ProductionChain', args=oildata}
else
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),
Proliferator='No',
}
return '|-\n| ' .. frame:expandTemplate{title='ProductionChain', args=veindata}
end
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 gasGiantRow(item, giant, frame)
local collector = itemByName(machines.Gas)
local collectorTech = technologyForRecipeID(recipesMakingByID(collector.ID)[1].ID)
local giantdata = {
Building = titleCase(collector.Name),
Replicator = 'Mine',
Technology = titleCase(collectorTech.Name),
Recipe = gasGiantRecipe(giant, frame),
Proliferator='No',
}
return '|-\n| ' .. frame:expandTemplate{title='ProductionChain', args=giantdata}
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 fogDropRow(item, frame)
local fogdata = {
Building = 'Raider',
Replicator = 'No',
Recipe = fogDropRecipe(item, frame),
Proliferator = 'No',
}
return '|-\n| ' .. frame:expandTemplate{title='ProductionChain', args=fogdata}
end
function fogDropRecipe(item, frame)
local prob = item.EnemyDropRange.y * 300
local level = item.EnemyDropLevel * 3
local dropMin = item.EnemyDropCount * 2 * (item.EnemyDropLevel / 10 + 1)
local dropMax = item.EnemyDropCount * 4
local fogdata = {
CraftTime = string.format('%.2f%%', prob),
Out1 = item.Name,
Out1Qty = string.format('%.1f-%.1f', dropMin, dropMax),
In1 = 'Raider',
In1Qty = string.format('Lvl %d+', level),
}
return frame:expandTemplate{title='ItemRecipe', args=fogdata}
end
function oceanRow(item, frame)
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),
Proliferator='No',
}
return '|-\n| ' .. frame:expandTemplate{title='ProductionChain', args=oceandata}
end
function oceanRecipe(item, frame)
local odata = {
CraftTime = '1.2 s',
Out1 = titleCase(item.Name),
Out1Qty = 1,
In1 = titleCase(item.MiningFrom),
In1Qty = '',
}
return frame:expandTemplate{title='ItemRecipe', args=odata}
end
-- get data from protosets
function itemByName(name)
local lame = string.lower(name)
for _, item in ipairs(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 ipairs(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 ipairs(protosets.RecipeProtoSet.dataArray) do
for _, itemid in ipairs(recipe.Results) do
if itemid == id then
table.insert(result, recipe)
break
end
end
end
return result
end
function recipesUsingByID(id)
local recipes = {}
for _, recipe in ipairs(protosets.RecipeProtoSet.dataArray) do
for _, itemid in ipairs(recipe.Items) do
if itemid == id then
table.insert(recipes, recipe)
break
end
end
end
return recipes
end
function technologyForRecipeID(id)
for _, tech in ipairs(protosets.TechProtoSet.dataArray) do
for _, recipeid in ipairs(tech.UnlockRecipes) do
if recipeid == id then
return tech
end
end
end
return nil
end
function veinMakingByID(id)
for _, vein in ipairs(protosets.VeinProtoSet.dataArray) do
if vein.MiningItem == id then
return vein
end
end
return nil
end
function gasGiantsMakingByID(id)
local giants = {}
for _, planet in ipairs(protosets.ThemeProtoSet.dataArray) do
for _, item in ipairs(planet.GasItems) do
if item == id then
table.insert(giants, planet)
break
end
end
end
return giants
end
function isItemOcean(id)
for _, planet in ipairs(protosets.ThemeProtoSet.dataArray) do
if id == planet.WaterItemId then
return true
end
end
return false
end
function isItemFogDrop(item)
return item.EnemyDropRange.y > 0
end
-- sorting/deduplication
function deduplicateGiants(giants)
local dedup = {}
for _, planet in ipairs(giants) do
new = true
for _, exist in ipairs(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
-- display formatting
function titleCase(str)
local start = string.gsub(str, '^%l', string.upper)
local title = string.gsub(start, '[-%s]%l', string.upper)
local mk = string.gsub(title, 'MK.I', 'Mk.I')
return mk
end
return funcs