Jump to content

Recommended Posts

Hello everyone.

I want to start working with worldgen but I have no idea where to start. I looked for some publications talking about it and the ones I found were made 5 years ago and are out of date. Can someone show me, at least, the initial path of what needs to be done, for example, to create a world with a small piece of land just for me to start to understand and try to develop from there.

Thanks in advance.

Link to comment
https://forums.kleientertainment.com/forums/topic/121659-starting-worldgen/
Share on other sites

Hello again.
Looking at the 'Prison Island' mod, the terrain was built into the file inside the static_layouts folder, as shown in the code in the image below. If I want to build a map with a specific format, will I have to build it by adding the numbers within 'data', as was done in this mod, or is there another way to build a map with a specific format?

image.thumb.png.6a923c2e0627629af45d0e2fb7c5e4c0.png

 

Someone who has knowledge in worldgen and wants to help others, could update and improve this tutorial (link below) from 5 years ago. It will help a lot.

 

Edited by Deicon

worldgen is very difficult, I know some stuff, but this is still only a tiny bit. You can look at my mods (teleportato and increase animals+setpieces and adventure) for some code:
https://steamcommunity.com/profiles/76561198102311542/myworkshopfiles/?appid=322330

Also the Do Your Map mod alters the world, but the author also does not know everything, he is learning by doing and looking at the game code. (tasks/rooms folders and level.lua and storygen)
https://steamcommunity.com/sharedfiles/filedetails/?id=2230181360

If I remember right, there is a tool somewhere, to generate this data array from your screenshot, but unfortunately I can not remember which one it was or if it is already shipped with mod tools... But you only need it for setpieces anyway. One single setpiece for a world is enough for static and very small worlds, but usually you will need tasks and rooms.

Edited by Serpens
  • Thanks 2

In the example below, what do 'entrace_room' and 'room_choices' do? 

And, a task that has a 'QUAGMIRE_TRIBE' key, will it call to run that task? And that task will call to run another task that has a 'QUAGMIRE_PARK_L1' lock, is that it?

AddTask("Contest", {
	locks = LOCKS.QUAGMIRE_TRIBE,
	keys_given = { KEYS.QUAGMIRE_PARK_L1 },
	entrance_room = "contestroom",
	room_choices = { 
		["blankbuffer2"] = 8,
	}, 
	room_bg = GROUND.IMPASSABLE,
	background_room = "BGImpassable",
	colour = {r = 2, g = 1, b = 0, a = 1}
})

 

can't help with locks/keys/entrance, but I think you already described how they work.
The best is to read all the code in the map folder, then you will know how it works :D But it is of course alot of work.

But if you succeed, feel free to make it optionally an adventure world for my adventure mod. Any mod can inject their world-code so their world might be chosen as adventure world. See https://steamcommunity.com/workshop/filedetails/discussion/756229217/1635291505019487419/
This custom desert world already uses that injection:
https://steamcommunity.com/sharedfiles/filedetails/?id=929742407

Edited by Serpens

I need to get some obstacles out of my mind that won't let me move forward on my project. The image inside the game, which I showed above, is an island that was created as a static_layouts. Can I place more pieces on that static_layout in a specific position? (other than within the static_layout that created the island). For example, after some action, add two ground at the top connecting the inside with the outside of the island.

9 minutes ago, Deicon said:

I need to get some obstacles out of my mind that won't let me move forward on my project. The image inside the game, which I showed above, is an island that was created as a static_layouts. Can I place more pieces on that static_layout in a specific position? (other than within the static_layout that created the island). For example, after some action, add two ground at the top connecting the inside with the outside of the island.

so you dont want to create world and leave it like that, but want a chainging world while playing? In this case you should look at the editor mods that already exist in the workshop. Or did I missunderstood your question and you simply want to add eg. some flowers to this static_layout at a specific position within worldgeneration? (I'm going to bed now, so response will be in~11 hours))

Edited by Serpens

I am using these small examples to understand the concept of how to implement something. The first image shows the assembled island using a static_layout, the second image shows the altered island (added a path at that specific position) after doing some action (as an example click on the torch). I'm wondering if I can make this change with another static_layout or something else?

image.png.2e2462b4857e0ab94fd246cf4f376f46.png

image.png.58dea1bee0103bb327fd2157405f922d.png  
 

sorry, I don't understand what your final goal is.

Altering the static layout to achieve this during the one-time worldgeneration is one thing.
But altering the world after an action while playing, eg. clikcing on the torch is a completely different problem, with a completely differnt solution.
Your starting post was about world generation, the one time thing when you first generate the world. Now you are asking about that completely different problem, that has nothing to do with a static_layout. So I'm confused.

I mean, for the first problem, you need to understand the whole worldgeneration thing, that I also know very little from,
For the second problem, you don't need anything of that, you only need to know a command to spawn land at positin xy. And for this you will surely find code within mapeditor mods, like https://steamcommunity.com/workshop/browse/?appid=322330&searchtext=editor&childpublishedfileid=0&browsesort=textsearch&section=home
 

  • Thanks 1

My goal is to understand how things work so that I can implement them later. These questions are confusing because I'm trying to learn, I apologize for that. But, according to your answer, if I want to change something in the world somewhere specific (add or remove a piece of land, spawn monsters, etc.), this is done with commands in the modmain file, right?

3 hours ago, Serpens said:

For the second problem, you don't need anything of that, you only need to know a command to spawn land at positin xy. And for this you will surely find code within mapeditor mods, like https://steamcommunity.com/workshop/browse/?appid=322330&searchtext=editor&childpublishedfileid=0&browsesort=textsearch&section=home

Thanks, I'll take a look.

1 hour ago, Deicon said:

My goal is to understand how things work so that I can implement them later. These questions are confusing because I'm trying to learn, I apologize for that. But, according to your answer, if I want to change something in the world somewhere specific (add or remove a piece of land, spawn monsters, etc.), this is done with commands in the modmain file, right?

Thanks, I'll take a look.

I never used such map editors and I don't know if they are still working or if they require a server restart everytime the land changes (Ithink I heard sth like that,but not sure).
Anyway, you should really think about what exactly you want to achieve, and if you can achieve this alot easier. For example to "open a new way to walk", instead of spawning a land bridge, you can block the path with sth. undestroyable and after interaction with the torch, you can remove the block via script. This is thousand times easier for sure.

Edited by Serpens
  • Like 1
3 minutes ago, Serpens said:

For example to "open a new way to walk", instead of spawning a land bridge, you can block the path with sth. undestroyable and after interaction with the torch, you can remove the block via script. This is thousand times easier for sure.

Interesting. How do I do this? Can you show me where it works, I mean, which script works with this block?

Just now, Deicon said:

Interesting. How do I do this? Can you show me where it works, I mean, which script works with this block?

for map coordinates and stuff like this, you will find alot of sample functions within scripts/components/map.lua from the game.
So there you see how to get coordinates of a point and how to measure distance and how to get the turf type and so on.
But not sure if you will need this, but since you want to learn ;)

So again, it does depend on what exactly you want. You could use the normal one-time world with locks/keys and such stuff, to create two landmasses that are seperated by a small landbridge, that i blocked by eg sanity-obelisks (like found in the DS adventure). These obelisk will let you pass if your anity is high/low (depending on the obelisk-type). Now you could create your own obelisks, that let one pass if a certain action was done before, or you could place undestroyable "basalt" stone instead and remove it via script, if the action was done.
Instead of using keys/locks, you can also use your static_layout you had above, and directly place obeliks/basalt at a specific position. But this only works for very small worlds, like this prison island.

To be able to remove eg. the basalt after a certain action was done, do need to save that basalt entity within modmain. If the basalt was placed within the worldgeneration, you could do AddPrefabPostInit("basalt"...) in which you could check the x,y coordinates and also alot more, to find out which of your multiple blocked ways this basalt is blocking. When you found out, you can save the entities sorted, so you will know which basalt belongs to which way, without checking it again.
Then you can listen for your specific action. Most of the devs code is already Pushing Events. Eg. an event on death and so on. So lets say you want to clear one of the ways as soon as a special pig died. Then you do AddPrefabPostInit for this pg (you need to identify the correct one, eg. via a Tag) and add inst:ListenForEvent(death,OnDeath). And in this OnDeath function you have to write, you can remove the basalt.

This is only one of many possible ways. I don't know what you know, so not sure how familar you are already with AddPrefabPostInit and ListenForEvent and such.
If you give me a real example, that we could live test, I can write it for you and you see how that example exactly works.

The most complicated part of this, is to place these blockers exactly at the right position with help of worldgeneration, to block a way. I mostly copy/pasted the DS adventure code, for my adventure mod, but there it still happens frequently, that you can walk beside the blockers, so the way is not really blocked =/


 

  • Thanks 1

I will write here some stuff I explained via PM:

sceanrio within static_layout, goal is to connect a blocker object for example with an enemy to remove the blocker after the enemy died. Both are placed within a static_layout file:

On 9/27/2020 at 7:02 PM, Deicon said:

Everything will be defined in static_layouts.

ok, this will make it alot easier.
Because within such a layout, you can use so called "scenarios", which are functions, bound to an entity you placed in the layout.

I already did this within this mod:
https://steamcommunity.com/sharedfiles/filedetails/?id=758921911

There we have in the scrpts/scenarios folder a scenario file called chest_totalrandom.lua, that add random loot to a chest, that was placed via a static_layout.
within the static_layout file you use sth like this:

objects = {
        {
          name = "",
          type = "chest",
          shape = "rectangle",
          x = 312,
          y = 232,
          width = 0,
          height = 0,
          visible = true,
          properties = {
            ["scenario"] = "chest_totalrandom"
          }
        },
        -- ...


The chest_totalrandom.lua need to return 3 functions:
return
{
    OnCreate = OnCreate,
    OnLoad = OnLoad,
    OnDestroy = OnDestroy
}
You can define these function within that file. So you can tell the game what should happen with that chest, when it is first created, what happens when the game is loaded and what happens when the chest is destroyed. We should be able to apply the same to eg. "basalt" blocker

right now I don't know a really good way how to connect the blocker with the enemy...

You could create a global list within modmain (make sure you name it unique) and in OnLoad of the enemy and the blockers you can add their inst to that global list.
And OnDestroy of enemy (not sure if this is also called on death, you have to find out. if not you need to do ListenForEvent), you then could look in this global list to find out which blockers are linked to that enemy and do blocket:Remove(), to remove them.

Or you could add tags to enemy and blokcer to identify them and use TheSim:FindEntities(x, y, z, radius, nil, nil, {"Tag"}) to find the entities of blockers after the enemy was destroyed.


Event Listeners and how to use them:

You dont need eventhandler.
You only need PushEvent, if you want to create your own event, most of the time this is not needed.

ListeForEvent listens for any PushEvent. Simply search the game code for "PushEvent" and you will find plenty results.
These commands are always executed on an instance, so eg. inst:ListenForEvent("death",OnDeath). This Listener will call the local OnDeath function that you define within your script, as soon anyone does inst:PushEvent("death") for this inst. When you search for inst:PushEvent("death" (without the closing paranthese) you will find it most likely within the health component I guess. And you also will see what information is passed along for example: inst:PushEvent("death", { cause = cause, afflicter = afflicter }).
Your OnDeath function, that is called from your ListenForEvent, will always get the inst, and any additional data that was given to Pushevent, usually all within one table.
So your OnDeath funciton could look like this:

local function OnDeath(inst,data)
    if data~=nil then
      local killer = data.afflicter
      print(tostring(killer).." killed "..tostring(inst))
   end
end


The same applies to all other events.
So first of all clarify on what kind of event you want to be notified. Then either search the relevant component or any other code for PushEvent, if there is already such a PushEvent, you could use. or use the script-wide notepad++ search for all PushEvent and see if you find one you can use. In 99% of the cases you will find one and then you only need to add a listener inst:ListenForEvent for this within your modmain (or scenario).

 

Edited by Serpens
  • Like 1

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
  • Create New...