Add class Recipe

This commit is contained in:
Simon Brodtmann 2025-02-15 13:29:43 +01:00
parent 22c5f9ddc7
commit b84902ce6a
2 changed files with 155 additions and 0 deletions

153
cf-lib/data/Recipe.lua Normal file
View file

@ -0,0 +1,153 @@
---- Utility class for a single recipe
---- @class Recipe
local Recipe = {}
---- Pass a recipe name or a recipe table to get a Recipe object
---- @param value string|table The name of the recipe or the recipe table
function Recipe:new(value)
local name
local recipe
if type(value) == "string" then
name = value
recipe = data.raw.recipe[name]
elseif type(value) == "table" then
name = value.name
recipe = value
end
if not recipe then
log("Recipe not found: " .. name)
return nil
end
local obj = {
prototype = recipe
}
setmetatable(obj, self)
self.__index = self
return obj
end
---- Applies the recipe to the game
function Recipe:apply()
data:extend({ self.prototype })
end
---- Assigns data to the recipe
---- Shorthand for table.assign(recipe.prototype, data)
---- @param data table The data to assign
function Recipe:assign(data)
table.assign(self.prototype, data)
end
--- Adds an ingredient to the recipe
--- @param ingredientName string The name of the ingredient
--- @param amount number The amount of the ingredient
function Recipe:addIngredient(ingredientName, amount)
local ingredientType = data.raw.item[ingredientName] and "item"
or data.raw.module[ingredientName] and "item"
or data.raw.fluid[ingredientName] and "fluid"
or nil
if not ingredientType then
log("Unknown ingredient: " .. ingredientName)
return
end
self.prototype.ingredients = self.prototype.ingredients or {}
for _, ingredient in pairs(self.prototype.ingredients) do
if ingredient.name == ingredientName then
ingredient.amount = amount
ingredient.amount_min = nil
ingredient.amount_max = nil
ingredient.probability = nil
return
end
end
table.insert(self.prototype.ingredients, { name = ingredientName, amount = amount, type = ingredientType })
end
--- Replaces an existing ingredient by name with a new ingredient or adjusts the amount
--- @param old string The name of the existing ingredient
--- @param new? string The name of the new ingredient
--- @param amount? number The amount of the new ingredient
function Recipe:replaceIngredient(old, new, amount)
if type(new) == "number" then
amount = new
new = old
end
if self.prototype.ingredients then
for _, result in pairs(self.prototype.ingredients) do
if result.name == old then
result.name = new
result.amount = amount or result.amount
return
end
end
end
end
--- Removes an existing ingredient by name
--- @param ingredientName string The name of the ingredient
function Recipe:removeIngredient(ingredientName)
if self.prototype.ingredients then
for i, result in pairs(self.prototype.ingredients) do
if result.name == ingredientName then
self.prototype.ingredients[i] = nil
return
end
end
end
end
--- Replaces an existing result by name with a new result
--- @param old string The name of the existing result
--- @param new? string The name of the new result
--- @param amount? number The amount of the new result (keeps the old value if not set)
--- @param expensiveAmount? number The amount of the new result for the expensive recipe (uses amount if not set)
function Recipe:replaceResult(old, new, amount, expensiveAmount)
if type(new) == "number" then
expensiveAmount = amount
amount = new
new = old
end
if self.prototype.results then
for _, result in pairs(self.prototype.results) do
if result.name == old then
result.name = new
result.amount = amount or result.amount
end
end
if table.main_product == old then
table.main_product = new
end
end
end
--- Adds the recipe to a technology
--- @param technology string|table The name of the technology or the technology table
function Recipe:unlockedByTechnology(technology)
if not technology then
return
end
technology = type(technology) == "table" and technology or data.raw.technology[technology]
if (not technology.effects) then
technology.effects = {}
end
for _, effect in pairs(technology.effects) do
if effect.type == "unlock-recipe" and effect.recipe == self.prototype.name then
return
end
end
table.insert(technology.effects, { type = "unlock-recipe", recipe = self.prototype.name })
end
---- Clones the recipe
---- @param name string The name of the new recipe
function Recipe:clone(name)
local clone = table.deepcopy(self.prototype)
clone.name = name
return Recipe:new(clone)
end
return Recipe

View file

@ -59,6 +59,7 @@ end
--- @param prerequisite string|table The name of the prerequisite or the prerequisite Technology instance --- @param prerequisite string|table The name of the prerequisite or the prerequisite Technology instance
function Technology:addPrerequisite(prerequisite) function Technology:addPrerequisite(prerequisite)
local _prerequisite = prerequisiteName(prerequisite) local _prerequisite = prerequisiteName(prerequisite)
self.prototype.prerequisites = self.prototype.prerequisites or {}
if (not table.contains(self.prototype.prerequisites, _prerequisite)) then if (not table.contains(self.prototype.prerequisites, _prerequisite)) then
table.insert(self.prototype.prerequisites, _prerequisite) table.insert(self.prototype.prerequisites, _prerequisite)
end end
@ -67,6 +68,7 @@ end
--- Adds multiple prerequisites to the technology --- Adds multiple prerequisites to the technology
--- @param prerequisites table The names of the prerequisite or the prerequisite Technology instances --- @param prerequisites table The names of the prerequisite or the prerequisite Technology instances
function Technology:addPrerequisites(prerequisites) function Technology:addPrerequisites(prerequisites)
self.prototype.prerequisites = self.prototype.prerequisites or {}
for _, prerequisite in pairs(prerequisites) do for _, prerequisite in pairs(prerequisites) do
local _prerequisite = prerequisiteName(prerequisite) local _prerequisite = prerequisiteName(prerequisite)
if (not table.contains(self.prototype.prerequisites, _prerequisite)) then if (not table.contains(self.prototype.prerequisites, _prerequisite)) then