entity.minable.results = random?

Place to get help with not working mods / modding interface.
hackamod
Long Handed Inserter
Long Handed Inserter
Posts: 62
Joined: Mon Apr 25, 2022 2:39 pm
Contact:

entity.minable.results = random?

Post 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?
User avatar
DaveMcW
Smart Inserter
Smart Inserter
Posts: 3714
Joined: Tue May 13, 2014 11:06 am
Contact:

Re: entity.minable.results = random?

Post 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.
hackamod
Long Handed Inserter
Long Handed Inserter
Posts: 62
Joined: Mon Apr 25, 2022 2:39 pm
Contact:

Re: entity.minable.results = random?

Post 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
SoShootMe
Filter Inserter
Filter Inserter
Posts: 517
Joined: Mon Aug 03, 2020 4:16 pm
Contact:

Re: entity.minable.results = random?

Post 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.
Pi-C
Smart Inserter
Smart Inserter
Posts: 1725
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: entity.minable.results = random?

Post 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.
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!
hackamod
Long Handed Inserter
Long Handed Inserter
Posts: 62
Joined: Mon Apr 25, 2022 2:39 pm
Contact:

Re: entity.minable.results = random?

Post by hackamod »

SoShootMe wrote: Fri May 26, 2023 6:51 am A setting on recipes to only output 1 item suggests exactly this.
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
hackamod
Long Handed Inserter
Long Handed Inserter
Posts: 62
Joined: Mon Apr 25, 2022 2:39 pm
Contact:

Re: entity.minable.results = random?

Post 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
hackamod
Long Handed Inserter
Long Handed Inserter
Posts: 62
Joined: Mon Apr 25, 2022 2:39 pm
Contact:

Re: entity.minable.results = random?

Post 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 :lol:
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
Pi-C
Smart Inserter
Smart Inserter
Posts: 1725
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: entity.minable.results = random?

Post by Pi-C »

hackamod wrote: Fri May 26, 2023 7:14 pm
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
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.
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!
Post Reply

Return to “Modding help”