I was testing a few things in lua and learnt it through trial-error and also copying other mods scripts. I decided to move forward and make some default game recipes more difficult to make by changing ingredients or adding more to them. For "Normal" difficulty games I dont want to change any recipe but for "Expensive" difficulty games I want to change some recipes. Some of the recipes I want to change do not have expensive mode, ex: Advanced Oil Processing.
I did the change with a dirty work but I am asking if there is a simplier and better way to do:
I copy-pasted the default recipe ingredients to "normal.ingredients=". I dont want to do this for every recipe I want to change for expensive mode.
Is there an easy way to copy recipe ingredients to ".normal.ingredients=" and also results from to data.raw.recipe["advanced-oil-processing"].results to data.raw.recipe["advanced-oil-processing"].expensive.results ?
I dont want to change results of recipes but only inputs (amount or/and type).
-- make expensive
function double_ingredients (handler)
if handler.ingredients then
for i, ingredient in pairs (handler.ingredients) do
if ingredient[2] then ingredient[2] = ingredient[2]*2 end
if ingredient.amount then ingredient[2] = ingredient.amount*2 end
end
end
end
function double_time (handler)
if handler.energy_required then
if handler.energy_required then
handler.energy_required = handler.energy_required * 2
end
else
handler.energy_required = 1 -- default energy_required is 0.5
end
end
for recipe_name, recipe in pairs (data.raw.recipe) do
if not recipe.expensive then
local normal = {}
-- ingredients
if recipe.ingredients then
normal.ingredients = table.deepcopy(recipe.ingredients)
recipe.ingredients = nil
else
log ('no ingredients by '..recipe_name)
end
-- result and results
if recipe.result then
normal.result = recipe.result -- not a table
recipe.result = nil
else
log ('no result by '..recipe_name)
end
if recipe.results then
normal.results = table.deepcopy(recipe.results)
recipe.results = nil
else
log ('no results by '..recipe_name)
end
-- other stuff
if recipe.enabled or recipe.enabled == false then
normal.enabled = recipe.enabled -- not a table
recipe.enabled = nil
else
log ('no enabled by '..recipe_name)
end
if recipe.energy_required then
normal.energy_required = recipe.energy_required -- not a table
recipe.energy_required = nil
else
log ('no energy_required by '..recipe_name)
end
if recipe.result_count then
normal.result_count = recipe.result_count -- not a table
recipe.result_count = nil
else
log ('no result_count by '..recipe_name)
end
recipe.normal = normal
recipe.expensive = table.deepcopy(normal)
double_ingredients (recipe.expensive)
double_time (recipe.expensive)
end
end
Re: Expensive mode recipes for vanilla recipes
Posted: Mon Nov 19, 2018 9:05 pm
by eradicator
You should write a function for it. Here's a basic example how that could look like:
local function overwrite_expensive(name,ingredients)
local recipe = data.raw.recipe[name]
recipe.normal = {
enabled = false,
ingredients = recipe.normal.ingredients or recipe.ingredients,
results = recipe.normal.results or recipe.results,
result = recipe.normal.result or recipe.result,
},
recipe.expensive = {
enabled = false,
ingredients = ingredients,
results = table.deepcopy(recipe.results or recipe.normal.results),
result = table.deepcopy(recipe.result or recipe.normal.result),
}
end
local function overwrite_expensive(name,myingredients)
-- get game recipe
local recipe = data.raw.recipe[name]
-- already has expensive mode?
if recipe.expensive then
recipe.expensive.ingredients = myingredients
-- no expensive mode, need to copy stuff
else
-- copy normal recipe from game's default
recipe.normal ={
enabled = recipe.enabled,
energy_required = recipe.energy_required,
result = recipe.result,
results = recipe.results,
result_count = recipe.result_count,
ingredients = recipe.ingredients
}
-- copy expensive recipe from game's default but use my ingredients
recipe.expensive ={
enabled = recipe.enabled,
energy_required = recipe.energy_required,
result = recipe.result,
results = recipe.results,
result_count = recipe.result_count,
ingredients = myingredients
}
end
-- reset stuff
recipe.results = nil
recipe.result = nil
recipe.ingredients =nil
end
overwrite_expensive( "advanced-oil-processing",
{
{type="fluid", name="sulfuric-acid", amount=20},
{type="fluid", name="crude-oil", amount=100}
})
overwrite_expensive( "processing-unit",
{
{"arithmetic-combinator",2},
{"decider-combinator",2},
{"advanced-circuit", 2},
{"electronic-circuit",2},
{type="fluid", name="sulfuric-acid", amount=5},
})
overwrite_expensive( "production-science-pack",
{
{"electric-engine-unit", 1},
{"electric-furnace", 1},
{"productivity-module", 1}
})
above workds like a charm.
cheers
Re: Expensive mode recipes for vanilla recipes
Posted: Tue Nov 20, 2018 1:32 pm
by eradicator
From a quick look that will instantly break as soon as a recipe you're altering already has a .normal= node, but no direct definition. There are three possible locations for recipe definitions
E.g. ingredients can be:
recipe.ingredients (direct)
recipe.normal.ingredients (normal node)
recipe.expensive.ingredients (expensive node)
In that case recipe.ingredients will be treated as "normal" difficulty. If both recipe.ingredients and recipe.normal.ingredients exist i think the engine will ignore the recipe.normal node (or is it the other way around?). In any case there's no need to create a .normal= node, a recipe with direct and expensive nodes is perfectly valid. [Edit: see below post.]
Additionally by removing the direct definition you might break someone elses mod if they doesn't properly check for direct/normal.
(Yes, recipe modding is far more complicated and annoying to do right that one might expect :p.)
Re: Expensive mode recipes for vanilla recipes
Posted: Wed Nov 21, 2018 3:13 pm
by rhynex
thanks for the info. I will probably not publish the mod for some time. I need a test run to see if it is really fun or not. expensive mod is already a challenge for me.
code works fine completely. normal mode recipes are not broken at all (only rocket part was broken because "hidden" was forgotten in my script posted)
recipe.ingredients (direct) << this is ignored if it normal/expensive exists
recipe.normal.ingredients (normal node)
recipe.expensive.ingredients (expensive node)
I remember game checks ".normal.ingredients" first even if ".ingredients" exist. I was not aware blue circuit had an expensive recipe. I changed the "normal" mod recipes first and realized how recipes worked. I decided to move all of the changes to expensive mode so I could also enjoy vanilla saves without restarting game after toggling my mod.
mod compatibility might be compromised I agree but if two mods are changing same game's default recipe then I would expect incompatibility. I do not have any other mod that changes game default mods
if someone does not check normal/expensive properly, is it my fault then ?
edit: I was idiot for not testing if game needed .normal for .expensive recipes, honestly I have no idea. maybe it will run fine. ex: Advanced Oil Processing
I would love to have some kind of complete recipe tree to be selected on map start to avoid mod complications. I used expensive mod for this reason (to be able to play both normal and expensive mod games without restarting, mod toggle)
Re: Expensive mode recipes for vanilla recipes
Posted: Wed Nov 21, 2018 4:34 pm
by eradicator
rhynex wrote: Wed Nov 21, 2018 3:13 pm
if someone does not check normal/expensive properly, is it my fault then ? :)
The rather more important question is: Do your potential users care if it's your fault or not? I could run my recipe normalizer on all recipes at startup if i wanted to, but i know it would break too many other mods, so i don't. (My normalizer converts all recipes to a full definition with normal/expensive and all ingredients/results as full tables instead of strings for items.) I try to do the minimal changes nessecary. And for a naive mod it's definetly unexpected to have a base recipe without direct definitions. Is that their bug? Sure. Can you avoid the bug on your side? Yes. It's a style question. And cross-compatibility is difficult.[Edit: see post below.]
rhynex wrote: Wed Nov 21, 2018 3:13 pm
edit: I was idiot for not testing if game needed .normal for .expensive recipes,
It does not. [Edit: game will use expensive even in normal mode if normal doesn't exist]direct+expensive works fine. But many people don't know this and make stuff more complicated than it needs to be ;)
rhynex wrote: Wed Nov 21, 2018 3:13 pm
edit: I was idiot for not testing if game needed .normal for .expensive recipes,
It does not. direct+expensive works fine. But many people don't know this and make stuff more complicated than it needs to be
direct+expensive does not work fine. which game version are you checking this? can you give me a mod example?
just tested using below script. both normal and expensive mod requires electric engine unit
edit: am I misunderstood? I do nto want to change normal difficulty recipes
Re: Expensive mode recipes for vanilla recipes
Posted: Wed Nov 21, 2018 8:19 pm
by eradicator
You're right. Expensive overrides direct when normal isn't present. Must've changed somewhere down the line or my memory is shitty. (Or both :p.). Sorry for the fuzz. Will edit old posts so nobody else gets confused.