Page 1 of 1
Is it possible to get two resources when mining one?
Posted: Tue Dec 17, 2024 9:00 pm
by Keysivi
I have an idea - to add a new resource "breed" to the game, which is mined simultaneously with any other resource.
Can anyone tell me - is it possible to add a second resource when mining one?
Here is an example of code from the file __base__/prototypes/entity/resources.lua
Code: Select all
type = "resource",
name = "uranium-ore",
minable =
{
mining_particle = "stone-particle",
mining_time = 2,
result = "uranium-ore",
fluid_amount = 10,
required_fluid = "sulfuric-acid"
},
I want to do something like this:
Code: Select all
type = "resource",
name = "uranium-ore",
minable =
{
mining_particle = "stone-particle",
mining_time = 2,
result = {"uranium-ore", "stone"},
fluid_amount = 10,
required_fluid = "sulfuric-acid"
},
I write the following code:
Code: Select all
table.insert(data.raw.resource["iron-ore"].minable.result, {type = "resource", name = "stone", amount = 1})
And I get an error:
Code: Select all
Failed to load mods: __My_add_pack_updated__/data-updates.lua:52: bad argument #1 of 3 to 'insert' (table expected, got string)
stack traceback:
[C]: in function 'insert'
__My_add_pack_updated__/data-updates.lua:52: in main chunk
I understand that I am a "teapot" in terms of programming, but maybe there is some solution?
Re: Is it possible to get two resources when mining one?
Posted: Tue Dec 17, 2024 9:06 pm
by Silari
Result only allows for ONE item. If you want more than one, use
results instead.
Far as I know it works perfectly fine for resource entities.
Re: Is it possible to get two resources when mining one?
Posted: Wed Dec 18, 2024 4:21 am
by Keysivi
Silari wrote: Tue Dec 17, 2024 9:06 pm
Result only allows for ONE item. If you want more than one, use
results instead.
Far as I know it works perfectly fine for resource entities.
Thanks for the advice! I made a couple of edits:
Code: Select all
table.insert(data.raw.resource["iron-ore"].minable.results, {type = "item", name = "stone", amount = 1})
But as a result, only the content of the error changed:
Code: Select all
Failed to load mods: __My_add_pack_updated__/data-updates.lua:52: bad argument #1 of 3 to 'insert' (table expected, got nil)
stack traceback:
[C]: in function 'insert'
__My_add_pack_updated__/data-updates.lua:52: in main chunk
Perhaps a more detailed definition is required?
Re: Is it possible to get two resources when mining one?
Posted: Wed Dec 18, 2024 8:26 am
by Pi-C
Keysivi wrote: Wed Dec 18, 2024 4:21 am
I made a couple of edits:
Code: Select all
table.insert(data.raw.resource["iron-ore"].minable.results, {type = "item", name = "stone", amount = 1})
But as a result, only the content of the error changed:
Code: Select all
Failed to load mods: __My_add_pack_updated__/data-updates.lua:52: bad argument #1 of 3 to 'insert' (table expected, got nil)
stack traceback:
[C]: in function 'insert'
__My_add_pack_updated__/data-updates.lua:52: in main chunk
Perhaps a more detailed definition is required?
Look at the error message, the solution is right there:
bad argument #1 of 3 to 'insert' (table expected, got nil)
Table 'results' is not defined because 'result' was set. (Actually, both 'result' and 'results' could exist if other mods already had modified the resource; if both exist, only 'results' will be used.)
So, you've got to make sure that results is defined before writing to it:
Code: Select all
data.raw.resource["iron-ore"].minable.results = data.raw.resource["iron-ore"].minable.results or {}
table.insert(data.raw.resource["iron-ore"].minable.results, {type = "item", name = "stone", amount = 1})
However, unless you've just created/modified something yourself in the current stage (data, data-updates, or data-final-fixed) you can't really know what properties it has. For example, if you create a prototype in data.lua you can trust that it will have the properties you've set as long as your mod is still acting on data.lua – but by the time you work on the same prototype again in data-updates, other mods may have changed your prototype, so you can't really trust it's still the same.
Therefore, the proper thing to do is to check whether data.raw.resource["iron-ore"].minable.results already contains the item you want to add and either (a) increase the amount if it already is in the list, (b) skip inserting the item if it already is in the list, or (c) add the stack if the item isn't in the list yet. Something like this:
Code: Select all
data.raw.resource["iron-ore"].minable.results = data.raw.resource["iron-ore"].minable.results or {}
local results = data.raw.resource["iron-ore"].minable.results
local stack = {type = "item", name = "stone", amount = 1}
local add_this = true
for r, result in pairs(results) do
if result.name == stack.name then
add_this = false
-- Optionally increase amount:
result.amount = result.amount + stack.amount
end
end
if add_this then
table.insert(results, stack)
end
Re: Is it possible to get two resources when mining one?
Posted: Thu Dec 19, 2024 6:32 am
by Keysivi
Pi-C wrote: Wed Dec 18, 2024 8:26 am
However, unless you've just created/modified something yourself in the current stage (data, data-updates, or data-final-fixed) you can't really know what properties it has. For example, if you create a prototype in data.lua you can trust that it will have the properties you've set as long as your mod is still acting on data.lua – but by the time you work on the same prototype again in data-updates, other mods may have changed your prototype, so you can't really trust it's still the same.
Therefore, the proper thing to do is to check whether data.raw.resource["iron-ore"].minable.results already contains the item you want to add and either (a) increase the amount if it already is in the list, (b) skip inserting the item if it already is in the list, or (c) add the stack if the item isn't in the list yet. Something like this:
Code: Select all
data.raw.resource["iron-ore"].minable.results = data.raw.resource["iron-ore"].minable.results or {}
local results = data.raw.resource["iron-ore"].minable.results
local stack = {type = "item", name = "stone", amount = 1}
local add_this = true
for r, result in pairs(results) do
if result.name == stack.name then
add_this = false
-- Optionally increase amount:
result.amount = result.amount + stack.amount
end
end
if add_this then
table.insert(results, stack)
end
Thanks for the advice!
Sorry for the delay. I had a lot of urgent matters. Only today I managed to test it.
Unfortunately, the script you suggested simply replaces iron-ore with "stone"
I replaced iron-ore with uranium-ore - the result is the same.
Re: Is it possible to get two resources when mining one?
Posted: Thu Dec 19, 2024 9:39 am
by Keysivi
It seems there is no solution. When I wrote the following directly in the game file
__base___/prototypes/entity/resources.lua:
Code: Select all
minable =
{
mining_particle = "stone-particle",
mining_time = 2,
results = {"uranium-ore", "stone"},
fluid_amount = 10,
required_fluid = "sulfuric-acid"
},
I got an error:
Code: Select all
Failed to load mods: Error while loading entity prototype "uranium-ore" (resource): Value must be a dictionary in property tree at ROOT.resource.uranium-ore.minable.results[0]
Accordingly, as I understand it, the game itself does not support the ability to mine more than one entity....
Re: Is it possible to get two resources when mining one?
Posted: Thu Dec 19, 2024 3:38 pm
by Pi-C
Keysivi wrote: Thu Dec 19, 2024 9:39 am
It seems there is no solution. When I wrote the following directly in the game file
__base___/prototypes/entity/resources.lua:
Code: Select all
minable =
{
…,
results = {"uranium-ore", "stone"},
…,
},
I got an error:
Code: Select all
Failed to load mods: Error while loading entity prototype "uranium-ore" (resource): Value must be a dictionary in property tree at ROOT.resource.uranium-ore.minable.results[0]
Your mistake is that you've set results to an array of strings while it should be an array of
ProductPrototype – in your case, this should be
ItemProductPrototype. The message specifies that the error occurred for the first item: ROOT.resource.uranium-ore.minable.results[0].
It definitely would help if you'd post your entire mod in its current state, not just snippets.
Re: Is it possible to get two resources when mining one?
Posted: Thu Dec 19, 2024 4:27 pm
by Keysivi
Thank you for paying attention to me! At the moment, this is not a mod, but just an idea.
I want to create an entity called "breed", which should be mined in parallel with the main resource, as it happens in real life... And which should then be filtered from the total mass of mined ore and used as the main ingredient for filling water.
Creating an entity is not a problem for me. The main problem is to make it mined simultaneously with the main resources.
I am testing it inside my mod All kinds of things (updated)
https://mods.factorio.com/mod/My_add_pack_updated
At the stage of practical development of the idea, the entity option is not critical. You can use any of the existing ones: stone, steel plate, gear, copper wire. The main thing is that this could be done in principle....
Re: Is it possible to get two resources when mining one?
Posted: Thu Dec 19, 2024 4:30 pm
by Keysivi
If this is critical to you. I will sketch this mod today. This is approximately it:
Code: Select all
data:extend(
{
{
type = "item",
name = "breed",
icon = "__hardcorio__/graphics/breed/icon.png",
icon_size = 64,
subgroup = "raw-material",
order = "c[breed]",
place_result = "breed",
stack_size = 100
}
})
data.raw.resource["iron-ore"].minable.results = data.raw.resource["iron-ore"].minable.results or {}
local results = data.raw.resource["iron-ore"].minable.results
local stack = {type = "item", name = "breed", amount = 1}
local add_this = true
for r, result in pairs(results) do
if result.name == stack.name then
add_this = false
-- Optionally increase amount:
result.amount = result.amount + stack.amount
end
end
if add_this then
table.insert(results, stack)
end
table.insert(data.raw["recipe"]["landfill"].ingredients, {type="item", name="breed", amount=50})
I plan to develop the mod further. But in a somewhat specific direction... I want to try to implement the idea of intermediate modules.
For example, to create a "gun-turret" not from primitive ingredients, like iron plates and gears - but full-fledged modules: "barbette", "combat-gun module", "control module"....
Re: Is it possible to get two resources when mining one?
Posted: Fri Dec 20, 2024 11:22 am
by IsaacOscar
I think your problem is that by setting result
s it ignores the value of
result (as described here
https://lua-api.factorio.com/latest/typ ... rties.html)
Now, minable.result is an ItemID, but minable.results taks an array of
ProductPrototypes (see
https://lua-api.factorio.com/latest/typ ... otype.html).
Now as your only dealing with items, that means you need to put ItemProductPrototypes (
https://lua-api.factorio.com/latest/typ ... otype.html) in your results list, including iron.
So to do that:
Code: Select all
data.raw.resource["iron-ore"].minable.results = {
{ type="item", name = data.raw.resource["iron-ore"].minable.result, amount = 1 },
{ type="item", name = "breed", amount = 5 }}
(Assuming you want it to give you 5 breed per mining operation. There are many other properties for ItemProduct, for e.g. if you want the amount to vary randomly, check the documentation).
What Pi-C was trying to suggest is to make your code automatically work with other potential mods, but that's more complicated, so it's probably best to get it working first before worrying about that! (In this case, you have have the source code of "iro-ore" so you know exactly what changes to make)
If you really want to do it Pi-C's way, here is what to do:
Code: Select all
local minable = if data.raw.resource["iron-ore"].minable
local found = false
if minable.results then
for _, value in pairs(minable.results) do
if value.name == "breed" then
found = true
if value.amount ~= nil then
value.amount = value.amount + 5
else
value.amount_min = value.amount_min + 5
value.amount_max = value.amount_max + 5 end end end
else if minable.result then
minable.results = {{ type="item", name = minable.result, amount = 1 }}
else
minable.results = {} end
if not found then
table.insert(minable.results, { type="item", name = "breed", amount = 5 }) end
minable.result = nil -- delete unnecessary field
Don't do that though, it likely has lots of syntax errors and bugs, but I just wanted to give you an idea as to how complicated it would be.
Re: Is it possible to get two resources when mining one?
Posted: Fri Dec 20, 2024 11:57 am
by Keysivi
Thank you very much for your answer. An attempt is not torture. I will try both options.... It will not make anyone worse....