ID:2012024
 
Ok so im trying to figure out how can i make it so a map would be populated with random foilage via turf without it overriding the turf it puts it on.

EX:not needing to make 50 different types of the same flower with the different ground BGs but just the flower alone randomly populated on the map over the different grounds

My other problem is I need a way for it to do this population 1 time without it doing it every time i reboot or host or login so people don't wonder why stuff keeps shifting around everytime and its just static.

So the overall Idea is a way to populate the map randomly with foilage without having to manually map it myself to save time and to save it somehow so it doesn't keep changing until I preform some kind of wipe of that generation of foilage for the map.

You could use a seeded random number generator during map initialization and generate a single random number for each turf on the map. This would prevent map changes from affecting where the turfs are randomized so long as the positions are constant. The reason that we do this for each turf on the map is because if you have some turfs that don't use the randomizer, changing the map even slightly will change the position of decorations. Whereas the only thing that will currently change the position of decorations is changing the size of the map on the x or y coordinates, or moving an entire map layer up or down.

This approach will not work for maps that dynamically change their size during runtime, but should work for individual turfs being replaced during runtime.

//we'll use this to convert the random floats to an int later
#define randfloat2int(F,L,H) round(F*(H-L)+L)

var
map_loading = 1
map_manager/map_manager = new/map_manager() //we're only going to use this to initialize the PRNG seed
stored_randomize = 0 //this will be used to restore the randomized value after a turf is deleted

map_manager
New()
PreLoad() //this datum initializes before the world begins loading the map.

proc
PreLoad()
rand_seed(8675309) //choose whatever number you want for this. Changing it will change the results. CALL ME, JENNY!

PostLoad()
map_loading = 0
rand_seed(world.realtime) //reset the PRNG's seed to the system clock's time. This will result in more unpredictable randomness after the world has loaded.

world
//this is called after the map is finished loading
New()
map_mapager.PostLoad()

turf
var
randomize = 0
New()
if(map_loading)
randomize = rand() //this will generate a number between 0 and 1 as a float.
else
randomize = stored_randomize
stored_randomize = 0
Del()
stored_randomize = randomize
..()


You can use this to generate turf randomness like so:

obj
turf_deco
layer = FLOAT_LAYER //this is important. It's so you can force this overlay to obey the turf's layer, not be on a separate layer

New()
if(loc&&isturf(loc))
loc.overlays += src
loc = null

flower
icon = 'lovelyflower.dmi'

turf
grass
icon = 'lovelygrass.dmi'
New()
..() //perform the supercall
if(randfloat2int(randomize,0,100)>90) //1 in 10 chance to have a decoration
overlays += /obj/turf_deco/flower //add the turf decoration


Random seeds don't change, so as long as the general order that you are pulling numbers from the random number generator does not change at startup, the map's results should always be the same. Avoid using any random number generators for anything other than turfs before map initialization and you should be able to have a consistent set of map decorations that never move between reboots.
so basically i would just make say a new turf and add the code for the turf decorations if i want decoration to be put on them right? so if i want sand to have the 1 out of 10 chance i just copy paste the grass code and change the overlays for the decorations then paint the map with the special sand turf right?
Basically, yeah. You'd just want to make sure that any turf that had a chance to be decorated had a New() proc that looked something like the New() proc I showed above.

I would definitely recommend mixing up the percentages and using a top-bottom-middle distribution as well for different turf types. You don't necessarily want every turf to have a decoration if it's got a high roll when the type changes. For instance:

turf
grass
New()
..()
if(randfloat2int(randomize,0,100)>90)
overlays += /obj/turf_deco/flower
sand
New()
..()
if(randfloat2int(randomize,0,100)<10)
overlays += /obj/turf_deco/driftwood
dirt
New()
..()
var/r = randfloat2int(randomize,0,100)
if(r>50&&r<=60)
overlays += /obj/turf_deco/stone


If you mix up the sweet spot, but keep the range the same, when you create a new dirt turf on top of a grass turf with a decoration, it won't necessarily have a decoration on the dirt turf, but a turf without a decoration may have one on the new turf because the sweet spots are different per type.
only weird problem im having is when i add a new decoration below the flower it keeps freaking out about wrong indentation even though it should be right

obj
turf_deco
layer = FLOAT_LAYER //this is important. It's so you can force this overlay to obey the turf's layer, not be on a separate layer

New()
if(loc&&isturf(loc))
loc.overlays += src
loc = null

flower
icon ='flower.dmi'

rock
icon='rock.dmi'


why is this?
Make sure you aren't mixing spaces and tabs.