Page 1 of 1
entity.minable.results = random?
Posted: Thu May 25, 2023 7:50 pm
by hackamod
TLDR: myEntity.minable.results = randomLoot(myEntity.lootList or {name="raw-fish", amounnt=1})
I want to add a variety of fish but do not see the need to create a bunch of different dark blobs in the water.
My plan was to randomize the results:
Code: Select all
myEntity["minable"] =
{
mining_time = 0.8,
results =
{
{
name = "option-one",
probability = 0.3,
amount = 2
},
{
name = "option-one",
probability = 0.3,
amount = 1
},
{
name = "option-two",
probability = 0.3,
amount = 1
},
{
name = "option-three",
probability = 0.1,
amount = 1
}
}
}
but this gives a 30% chance for (2) option-one AND a 30% chance for (1) option-one AND a 30% chance for (1) option-two AND a 10% chance for (1) option-three.
This makes it possible to get all options at once, or none at all.
What I wanted was a varied chance to get one of them 100% of the time, but always only one option.
How do I go about adding many new fish types without filling the water with a bunch of different fish?
Re: entity.minable.results = random?
Posted: Fri May 26, 2023 3:27 am
by DaveMcW
entity.minable.results does not support this.
You could use the control.lua event
on_player_mined_entity to do whatever you want when a fish is mined.
Re: entity.minable.results = random?
Posted: Fri May 26, 2023 3:42 am
by hackamod
Thanks, that will work just fine. I will do that.
On another note, I assumed the thing I wanted was the default behavior for the probability based on the way uranium processing is set up:
Code: Select all
results =
{
{
name = "uranium-235",
probability = 0.007,
amount = 1
},
{
name = "uranium-238",
probability = 0.993,
amount = 1
}
}
}
where 0.007 and 0.993 add up to 1.000
With 5 different result items, that is 5 calls to random for the probability of each.
The way I want it to work would be only one call to random for any number of possible choices.
A boolean could be used to determine AND or OR for the results list.
Perhaps make this thread a feature request? It should be easy enough to add
Re: entity.minable.results = random?
Posted: Fri May 26, 2023 6:51 am
by SoShootMe
hackamod wrote: Fri May 26, 2023 3:42 am
On another note, I assumed the thing I wanted was the default behavior for the probability based on the way uranium processing is set up
[...]
A boolean could be used to determine AND or OR for the results list.
Perhaps make this thread a feature request? It should be easy enough to add
A setting on recipes to only output 1 item suggests exactly this.
Re: entity.minable.results = random?
Posted: Fri May 26, 2023 7:19 am
by Pi-C
hackamod wrote: Fri May 26, 2023 3:42 am
Thanks, that will work just fine. I will do that.
On another note, I assumed the thing I wanted was the default behavior for the probability based on the way uranium processing is set up:
Code: Select all
results =
{
{
name = "uranium-235",
probability = 0.007,
amount = 1
},
{
name = "uranium-238",
probability = 0.993,
amount = 1
}
}
}
where 0.007 and 0.993 add up to 1.000
With 5 different result items, that is 5 calls to random for the probability of each.
The way I want it to work would be only one call to random for any number of possible choices.
You could use something like this:
Code: Select all
-- Precalculate thresholds in on_init and on_configuration_changed and store them in global table
myresults = {
{
name = "option-one",
probability = 0.3,
amount = 2
},
{
name = "option-one",
probability = 0.3,
amount = 1
},
{
name = "option-two",
probability = 0.3,
amount = 1
},
{
name = "option-three",
probability = 0.1,
amount = 1
}
}
for r, result in ipairs(myresults) do
result.min = (myresults[r-1] and myresults[r-1].max or 0)
result.max = result.min + result.probability
end
-- In on_player_mined_entity
local chance = math.random()
local pick
-- Optimization for big tables: Search forwards or backwards, depending on the random number
local start, step, target
if chance > .5 then
start, step, target = #myresults, -1, 1
else
start, step, target = 1, 1, #myresults
end
local result
for r = start, target, step do
result = myresults[r]
if chance > result.min and chance <= result.max then
pick = {result.name, result.amount}
break
end
end
The first part should be run in your handlers for on_init and on_configuration_changed. It assumes that you have a predefined table myresults containing entity name, amount, and probability. The sum of all probabilities must be 1. Use these events to precalculate thresholds for the random function, and store the resulting table in global.
The second part is run in response to on_entity_mined. You calculate just one random number and pick the element in your table where that number is within the range defined by min and max.
Re: entity.minable.results = random?
Posted: Fri May 26, 2023 3:16 pm
by hackamod
This thread is basically people asking for the same thing (with no results)
The peak of this mountain to overcome is that it is too easy to get no loot.
With the probabilities set low, for multiple result options, tests show that you can mine 10 fish from the water and still have 0 loot.
On the other hand, when you do get loot, it is very common to get more than one loot result.
(This is exactly the behavior I thought I would have to invent for casting a net to catch fish while fishing with a hook or by hand should yield only 1 fish)
Pi-C wrote: Fri May 26, 2023 7:19 am
You could use something like this:
...
Yes totally.
But this feels like a very hacky way for people to overcome something that could be implemented so very cleanly, without disturbing existing saves, by simply adding a boolean, that when present in results, the results are treated as "One of the group" rather than "Chance from each group" (the current way)
That way existing things do not change, and the (more common?) behavior for random loot is available as an option
* This is very easy to implement pre-mod
* Usually with "random loot" the desire is "one of the group", and not the current implementation
Re: entity.minable.results = random?
Posted: Fri May 26, 2023 4:19 pm
by hackamod
...the more you know....
Because factorio already works this way:
"You can specify result OR results"
Maybe a better plan going forward is not to add a boolean but to add a new loot option, if you do not specify result and you do not specify results, then specify "oneOf" or something.... works like results, but you always get exactly one of the loot options, which can then have a probability of their own. That makes it very flexible
Re: entity.minable.results = random?
Posted: Fri May 26, 2023 7:14 pm
by hackamod
Pi-C wrote: Fri May 26, 2023 7:19 am
The second part is run in response to on_entity_mined.
I was
looking for that in the search box and did not find it
... to compare with
on_pre_player_mined_item
...and I thought there was one for the bots too.
I am probably confused
Does on_entity_mined get called before the entity is removed?
More specifically, can I still set results for an entity, and catch it in on_entity_mined before the default system gives out the results? Or will this cause the normal results to be done anyway?
I am trying to avoid giving the wrong loot and taking it away to give the random loot.
I amd also not yet quite sure how bots mining fish (or other things that may have randomized loot) work into the mix
Re: entity.minable.results = random?
Posted: Fri May 26, 2023 7:47 pm
by Pi-C
Sorry, my mistake! The relevant events are
on_player_mined_entity and
on_robot_mined_entity.
Does on_entity_mined get called before the entity is removed?
- on_player_mined_entity: Called after the results of an entity being mined are collected just before the entity is destroyed. After this event any items in the buffer will be transferred into the player as if they came from mining the entity. Can be filtered using LuaPlayerMinedEntityEventFilter.
- on_robot_mined_entity: Called after the results of an entity being mined are collected just before the entity is destroyed. After this event any items in the buffer will be transferred into the robot as if they came from mining the entity. Can be filtered using LuaRobotMinedEntityEventFilter.
More specifically, can I still set results for an entity, and catch it in on_entity_mined before the default system gives out the results?
Yes, you can manipulate event.buffer.