PyroFire wrote: ↑Wed Aug 21, 2019 3:10 am
slippycheeze wrote: ↑Tue Aug 20, 2019 5:38 pm
If that is actually what you want, it is impossible. Factorio only has a Perlin noise source, implemented in C++, and you can't add or change sources of noise. No mod can, though -- it is just as impossible for them as it would be for you. So I'm pretty sure that isn't what you want.
well, from what i've seen it is actually possible.
You just need to have a script that actually implements the noise type.
Sorry, yes, you are right: I didn't make it clear that is true only for the built-in map generator. You can absolutely do anything by overriding the `on_chunk_generated` event and writing it in Lua, as dangOreus, RSO, etc, do.
What you can't do is use `map_gen_settings` for that. You would just need to check the surface you were generating on in your `on_chunk_generated` and use whatever custom noise generator you wanted.
If that is what you want, just check the `surface` value in your `on_chunk_generated` handler, and dispatch to whatever you want for each individual surface. So your mod would work with the dangOreus integration mod to establish that a surface uses a Lua handler for resource generation, and (a) set the map_gen_settings to not place stuff, and (b) dispatch to the appropriate code, when that surface was the one live in `on_chunk_generated`.
Since it sounds like you need that at least some of the time, are you clear on how both those steps would be done?
PyroFire wrote: ↑Wed Aug 21, 2019 3:10 am
slippycheeze wrote: ↑Tue Aug 20, 2019 5:38 pm
1. When is the noise expression evaluated? As in, when, exactly, during the life of the game, is the math done? During the data phase? Control phase?
To be honest i'm not entirely sure when the expression is evaluated, but i'm pretty sure the timing is irrelevant - at least for my purposes.
Basically, differing math formulas and equations is needed for *some* different planets (but not all).
Cool. They evaluate during the C++ equivalent of `on_chunk_generated`, using the named noise expression that is set in the `map_gen_settings` for that specific surface. During the data phase the *equation* is configured, but it isn't evaluated. So you can't build a new equation on the fly, for the built-in generator. You can only change which one the C++ code uses for each surface, individually.
[/quote]
PyroFire wrote: ↑Wed Aug 21, 2019 3:10 am
slippycheeze wrote: ↑Tue Aug 20, 2019 5:38 pm
2. How is wavlet based noise generator different to the perlin noise generator, in terms of what you could do with it in the game? (or, more briefly, why do you want to use wavlet noise generation instead?)
It's actually more about the noise math than the type of noise.
The peaks and the valleys as well as their distributions.
In terms of what needs to be done in the game -
See the first post, there are 2 pictures of the green water being used, and they are made by 2 different sets of noise math.
The first one has large smooth lakes.
The second one has messy green water patches scattered all over the place.
What i'm asking about is how to switch between these 2 "outcomes" on an as-needed, per-surface basis.
So the idea is for Planet A to have the large green lakes, but Planet B has the scattered green water.
These 2 planets use the same tile (graphics and such), but will use different autoplace noise expressions.
Cool. OK. So, I think I do understand what you need here, and I just need to figure out how to communicate effectively about how to achieve that.
In
Types/AutoplaceSpecification in the wiki, there is a list of properties, right?
Two of those have associated noise expressions, `probability_expression`, and `richness_expression`.
Those are the two fundamental noise equations that are used in placing resources by the C++ version of `on_chunk_generated`.
To override those two properties for a specific surface you can change the map_gen_settings for it as I showed before:
Code: Select all
map_gen_settings.property_expression_names["{tile|entity|decorative}:" .. prototype_name .. ":{probability|richness}"]
The value of that argument is a "named noise expression" defined during the data phase. So, if you do nothing the "green water" tile -- water-green, IIRC -- uses the values set during the data phase.
To change that for one surface, and one surface only, you do it by changing the map_gen_settings for that surface. The best way is setting it via the argument to `game.create_surface`, but you can fiddle it any time, and it'll apply to any new chunks generated.
That is, in the AutoplaceSpecification type the property field `probability_expression` corresponds to the control stage setting `map_gen_settings.property_expression_names["tile:water-green:probability"]`, and the property field `richness_expression` corresponds to `map_gen_settings.property_expression_names["tile:water-green:richness"]`.
Inside the C++ code the `on_chunk_generated` logic is evaluated for every surface individually, and uses the map_gen_settings for the individual surface to check for an override. If there isn't an override in property_expression_names, it goes back to the values in the autoplace specification prototype for the entity.
So, each surface has a unique and distinct `map_gen_settings`, which include a `seed` property -- the PRNG seed used for generating chunks on that surface, which also controls the perlin noise generator output. That means that even if two surfaces have the same map_gen_settings equations, as long as the seed is different they will generate different noise, and that flows through to different placement.
(If you don't specify the map_gen_settings in game.create_surface, it'll get an automatic copy of the "default" values, as in, surface[1], aka "navius", but they still have their own set of map_gen_settings.)
In summary:
- if you need to generate noise from a non-perlin source, you can only do that in lua, ignoring the default map generation tools.
- if you need to override the equations for any autoplaced entity, tile, or decorative, you can do that with the `map_gen_settings.property_expression_names` on a per-surface basis.
I believe that should allow you to achieve your goal: you can tell the map generation system in C++ to use a different noise expression for the various properties found in the "autoplace specification" type for the resource via those per-surface overrides.
Does it?
how to apply those rules on a per-surface basis
Since you have to have lua code calling `game.create_surface` to make a new surface, you need to apply your logic to work out which type of surface -- planet -- the next one will be *before* you create it, and then apply the overrides from it when you call `game.create_surface`, and it should behave as you want.
Oh, and if you check the examples at the bottom of
MapGenSettings in the API docs they include two concrete examples: one for changing the probability a tile is a specific type of grass, and one for making deep water always have a probability of -1,000, aka "never gonna place you", which show how to implement this exactly.
autoplace controls
An autoplace control is a way of telling the game engine to add a widget during the "new game" map generation setup page, before you hit "play", that lets the player adjust the values as documented
in Types/AutoplaceSpecification#Controls in the wiki.
You can completely ignore them on new surfaces if you want to have player customizations (like resource frequency/richness) apply, or you can configure them in Lua for a planet using the `autoplace_controls` field in `map_gen_settings` -- that'll override the player choices, but of course, only for the surface using that specific set of `map_gen_settings`.
no richness_expression is set in the prototype for a resource, only a probability_expression
Per the wiki, if there is no richness_expression, probability_expression is used instead.
what are the default placement expressions?
https://github.com/wube/factorio-data/b ... s.lua#L274
https://github.com/wube/factorio-data/b ... .lua#L1078
Tile placement expressions are big. Shockingly huge, in fact. Those functions end up generating some wildly huge expressions.
Resource placement stuff is much more trivial.
anything else?
Are there any other properties of tile, entity (resource, rocks), or decorative placement you need to control, and which this doesn't explain how to adjust?