How To - make your own dungeon sets

Discussion in 'Starbound Modding' started by Trook, Jan 8, 2014.

Thread Status:
Not open for further replies.
  1. Trook

    Trook Space Penguin Leader

    Hi and welcome!

    After making my first dungeon mod, i have been asked to make a tut - so here it is:

    I will do my best to explain all basics you need to create your very own dungeon mod.
    Such mods allow new unknown planets, to have a chance to generate this custom dungeon, instead of the predefined ones, as soon as you visit them.

    Very basic modding or programming knowledge should be enough to understand this here (hopefully =S):


    So we start with a powerfull tool called Starstructor, created by Kel^ (thx dude!), which allows you to visualize and edit .dungeon and .structure files.

    Lets take a look at the .dungeon files. For example open the file
    "C:\Program Files (x86)\Steam\SteamApps\common\Starbound\assets\dungeons\glitch\glitchcastle\glitchcastle.dungeon"
    (the path may differ, depended on where you installed the game)
    ...with starstructor.

    You may also need an enhanched text editor like "notepad++" or equal.
    Open the same file with the text editor too.

    A dungeon begins with an "anchor" which simply is an entrance or a base.
    Inside the code (opened with the texteditor) they are declared with one of the first the lines
    Code:
    "anchor" : [ "castlebase1", "castlebase2", "castlebase3", "castlebase4", "castlebase5" ]
    As you can see, there are multiple anchors declined. This means the game will pick a random one of this list when creating the dungeon.
    With starstructor, take a look at the first entrance, called "castlebase1", by selecting it in the top right list.

    When you expand the note "castlebase1", you will see that it has 2 images or "layers".
    [​IMG]
    The first layer is a bitmap which contains information about where to place which "geometrical" tile (like dirt, stone or kinda)
    The second layer "...objects" tells the game where to place which object (like torches, doors and so on)

    There can be a 3rd layer called "wires" - i guess you already have an idea what it would do -, but there is a problem with showing wires right now, which means they aren't visible (it is still able to edit them with starstructor, but is is a pain .. ... ... =S)

    So how does this "place which tile/object where" work?

    Each bit of the bitmap represents a specific tile of the games database.
    Therfor we need to clarify which bit represents which tile.
    This is done inside the code-section "tiles" which mostly is the first section.
    Code:
     "tiles" : [
        {
          "value" : [55, 140, 140, 255],
          "comment" : "background castlewalls1",
          "brush" : [ [ "clear" ], [ "back", "castlewalls1" ] ]
        },
    ...
    ...
    specifies that the color [ 55, 140, 140, 255] (red green blue alpha) represents a tile with the style of a castlewall.
    "back" tells us that it is a background tile only. (while front would be a foregroundtile - combinations of both are possible too)

    Sadly starstructor doesn't allow to add new brushes/tiles right now (the option is there but inactive), so if we want to add a new one, we have to do this inside the code directly.

    To add tiles have a look at the folder
    "...\Starbound\assets\tiles"
    (I am sure the "castlewalls1" can be found somewhere inside there too)

    Instead of goin into much more details of how to add new tiles, i recommend to clone the "randomencounter.dungeon" file locatet at
    "...\Starbound\assets\dungeons\microdungeons\randomencounter\generic"
    and change it for your needs. (this file already contains a broad span of common tile-declarations)

    Beside such tiles, there are some "special tiles" too.
    Code:
    {
          "value" : [255, 0, 220, 255],
          "comment" : "magic pinkppp, a no-op value"
    },
    Is a tile which means "nothing" or empty space.

    Code:
        {
          "value" : [0, 0, 0, 255],
          "rules" : [ [ "worldGenMustContainAirBackground" ], [ "allowOverdrawing" ] ],
          "brush" : [ [ "clear" ] ]
    },
    This tile with the color black is used to tell the generator that there HAS TO BE air. I am not sure how it is done exactly, but i bet the game first generates the dungeon and then merges it into the planet. However, this tile has a rule defined which has to be used when merging it.

    Code:
        {
          "value" : [255, 255, 255, 255],
          "rules" : [ [ "worldGenMustContainSolidBackground" ], [ "allowOverdrawing" ] ],
          "brush" : [ [ "surface" ] ]
    },
    Color black means, there has to be a background tile.

    So with Black and White we can show the game where the planet surface should be.

    Starstructor has an option at the bottom left of the window, to show the color codes instead of the graphical brushes.
    Switch "Mode:" to "Color Display" and take a look at the areas where you might expect the surface of the world.

    At the left and right borders you can see a black pixel above a white one
    [​IMG]
    Lets call these b&w pixelpairs "surfacepairs". It seems to be important that these two surfacepairs have to be on the same height-level. This isn't confirmed, i just can tell that i ran into weird behaviours as i placed them on different levels on my dungeons entrance map.

    There are some other sepecial tiles too and much more options to specify other details, like here
    Code:
        {
          "value": [ 47,  213,  255,  255  ],
          "comment": "fridge facing left",
          "brush": [
            [
              "clear"
            ],
            [
              "object",
              "fridge",
              {
                "direction": "left",
                "parameters": {
                  "treasurePools": [
                    "apexfridge"
                  ]
                }
              }
            ]
          ]
        },
    Defines the color ... to represent a fridge. Also defines the items which can be found when opening it ingame:
    "treasurePools": [ "apexfridge" ]

    I recommend to take a look at existing files and experiment with them! I could tell you tons of stuff, but it may be easier to figure it out by your own. (Feel free to ask question here pls)

    If you didn't already figure it out, you can pick tiles/brushes in starstructor by switching to the "brushes" tab on the top right and selecting them from the list, or pick one from the preview by rightclicking it. To delete one pick the "pink" one or simply overwrite it with an other tile.

    The last tile i want to talk about are couplers or "connectors".
    They act like joints between rooms. For now it should be enough to understand that rooms can only be connected if they have a matching connector and the space arround the connector fullfills the rules to place the room there. (remember "HasToContain...", "IsOverwriteable" .... all these rules are used here too).

    Rooms:
    "Anchors" and "rooms" are the "parts" or modules of each dungeon.
    Scroll down the code until you reach the line
    Code:
    "parts" : [
    {
    ...
    ...
    (or better search for it as the tiles list is huge^^)

    This is the place where these parts are defined.
    Code:
        {
          "name" : "castlebase1",
          "rules" : [
            [ "maxSpawnCount", [1] ],
            [ "doNotCombineWith", [ "castlebase2", "castlebase3", "castlebase4", "castlebase5" ] ]
          ],
          "def" : [ "image", [ "castlebase1.png", "castlebase1-objects.png" ] ]
        },
    Is the entrance we have used before.

    "rules" will be considered when connecting rooms. Here're some details about them:

    "maxSpawnCount" means that the generator will place this part maximal x times (just to mention it : it can still be placed less than x times)

    Don't mix up "doNotCombineWith" and "doNotConnectToPart" !!

    "doNotCombineWith": for example if you got "room1a" and "room1b" and room1b is the same as room1a but mirrored. It may be a bit boring to have both rooms in the generated dungeon, so with "....Combine..." you can tell the game to only use one of them. Or with other words: Dear generator, if you place this part, do not place the parts "castlebase2", "castlebase3", "castlebase4", "castlebase5" .... too! THX =)

    "doNotConnectToPart": For example we want "room2" to be able to appear multiple times in our dungeon, but we don't want that its copies appear right next to each other. So "...Connect..." can prevent this, if we tell the generator not to connect "room2" to "room2".
    Or there may be parts which simply don't fit very well to each other, while they got the same connectors. With "...Connect..." we can add a special rule to them... guess you got it? Fine^^

    Inside the "scifidungeon" file i found some other very usefull things!
    Code:
        {
          "name" : "7",
          "rules" : [
            [ "maxSpawnCount", [1] ],
            [ "ignorePartMaximumRule" ]
          ],
          "def" : [ "image", [ "7.png", "7pod.png" ] ]
        },
    
        {
          "name" : "endleft",
          "rules" : [
            [ "ignorePartMaximumRule" ]
          ],
          "def" : [ "image", [ "endleft.png", "endlefta.png" ] ],
          "chance" : 0
        },
    "ignorePartMaximumRule":
    At the very top section of the .dungeon code we can define how many parts the generated dungeon can hold: "maxParts" : 100
    So the generator will stop to add parts as soon as there are 100.

    This rule "ignore...." is used for endpieces. In combination with the "chance 0.0" (bottom of the snippet)
    The combination says, that whenever there could be placed an endpiece, it wont happen, because they got a chance of 0.0 to be placed.
    But in sooner or later the partMaximum will be reached, while there may be still some ugly "open ends".
    So now the combination becomes active, because we told the generator to ignore the maxParts limit for this special part.
    Don't ask me why it suddenly ignores the "chance 0", but it is doin so and a i am very thankfull for this :)

    Let's go back to the castlebase declaration:
    Code:
        {
          "name" : "castlebase1",
          "rules" : [
            [ "maxSpawnCount", [1] ],
            [ "doNotCombineWith", [ "castlebase2", "castlebase3", "castlebase4", "castlebase5" ] ]
          ],
          "def" : [ "image", [ "castlebase1.png", "castlebase1-objects.png" ] ]
        },
    Have a look at "def" : ...
    Here we tell the game the names of our bitmaps/layers.

    This is a good point to talk about how to ship your mod.

    Modding starbound is somewhat handy! All you need to make a mod is:

    Create a "[modname].modinfo" file.
    Here is mine for example: "bandithideouts.modinfo" (no idea if there are rules for .modinfo names, but better use lowercase letters and prevent whitespaces)
    Code:
    {
        "name" : "Bandit Hideouts",
        "version" : "Beta v. Angry Koala",
        "path" : ".",
        "dependencies" : []
    }
    This file will be placed inside the "...\Starbound\mods\ [Modname] \" folder.

    Next we need to do, is to create the main folder of our mod:
    "...\Starbound\mods\ [Modname] \assets\dungeons\ [optionalSubFolders] \ [dungeonname]"
    In there go all the files of our dungeon set: The .dungeon file itself and the bitmaps of each part/module.
    (The folder and the .dungeon file both have to have the same [dungeonname])

    I guess you can see how this works? Starbound handles all the folders and files inside your mod's folder like they are merged together with the games original files and folders.

    With an exception which follows below...

    Now, we still didn't tell the game to consider our dungeon when a player visits a new planet.
    All the possible dungeons, used when creating a new planet are listed inside the "planetgen.config" file locatet at
    "...\Starbound\assets"

    If you open the file with the texteditor, you can find the line (at the end)
    Code:
      "dungeonWhitelist" : [ "scifidungeon", "apexresearchlab", "apextestchamber", "apextowerblock" ]
    
    So this is the list of dungeons which may be created on new planets.

    We now need to expand this list with our dungeon, but we wont touch the games original "planetgen.config"
    Instead we create our own planetgen.config and place it inside our mod's folder
    "...\Starbound\mods\ [Modname] \"
    Notice that, even if the original file is locatet in "assets" we must not place it inside "...mods\...\assets", it directly has to go into the main folder of our mod. (right next to our .modinfo file)

    Inside this file we write
    Code:
        "__merge" : [
           // [ "overwrite", "dungeonWhitelist" ]
        ],
        "dungeonWhitelist" : [ "dungeonname" ]
    }
    
    So now the game will merge the content of our planetgen into the original planetgen. (For more info about merging pls have a look at the sticky "merging" thread inside the modding section)

    // [ "overwrite", "dungeonWhitelist" ] The "//" means this is a comment and ignored. To test your dungeon you may remove the slashes. This will overwrite the original whitelist instead of combining them, which means each new planet can only contain your dungeon.

    And that's quite all the magic =)

    Hopefully i already told enough and you should be able to create your first little test dungeon now.

    If you want to, you can also have a look at my Bandit Hideouts files, but i don't recomment to do so, as i used some tricks which may confuse you.

    Always feel free to ask your questions about making dungeons here, i will do my best (and for sure the community too) to answer them.

    Some tips:
    - Procedural generation is a mighty thing! Understand and use its powers to get great results =)
    - Dublicating and mirroring rooms already adds varity (but don't forget that you have to change the objects too as they got a "direction")
    - Choose the size of your modules/parts and the location of the connectors wisely - a good system may help to get better results (for example if each module fits into a sizepattern like room1 is 1 units wide, while room2 is 3 units wide and so on, there may be much less gaps and ugly sections in your generated dungeon.)
    I regret that i didn't think about this before making my underground modules :(
    - Use different connectors to "declare" connection rules too. Some rules are a insanly complex if defined by code. Try to understand the way how connectors work exactly and you may be able to cast awesome magic :D
    - There is an order in which connectors are "read" or used by the generator. In my Underground dungeon i used 7 different connectors. Why? That's the confusing part: The generator seems to read the bitmap from topleft to bottomright. So the first connector read, will be the topmost and leftmost one (correct terms?). In my dungeon, the parts follow a hirachy like (first only the entrance can be placed, then a sub-entrance, then stairs and small hallways, then bigger halls, then "spreading"-hallways, then rooms, then smaller rooms..... and so on). I did this by using these 7 connectors (in combination with the code's "rules") and it works fine! ...even if it looks weird =S, i guess there would be no real chance to get this done with the coded rules only.
    - Have fun! A project can only be a good project if you have fun while realizing it =)

    Questions? I'm not there for a while *joking :p SHoOT!
     
    Last edited: Jan 8, 2014
  2. Trook

    Trook Space Penguin Leader

    sry, postet this before spellchecking it and also forgot some important pieces =S
    But now it should be fine. I am too lazy to pimp the layout right now, maybe laters.
    Hope it still helps! hf
     
  3. ArtoriasX

    ArtoriasX Void-Bound Voyager

    Thanks for the help, I will still need a bit of time until i can make my own dungeon but this will help a lot.
     
  4. Trook

    Trook Space Penguin Leader

    bluecollarart likes this.
  5. seancruz

    seancruz Big Damn Hero

    Hi Trook, awesome tutorial!

    A few questions:
    1. Can we decide how frequently a dungeon spawns?
    2. Can we decide if the dungeon only spawns in certain biomes?
    3. How can we make sure certain dungeons spawn only on the surface?
     
  6. jLnMart

    jLnMart Void-Bound Voyager

    any one try to use __merge on existing dungeon with success ? i try to add a pnj in 'apextowerblock' or just alter a part for testing but nothing seams to work. it' always load the original one.

    Edit : ok my bad, it's work... just do not make mistake in file path : /
     
    Last edited: Jan 12, 2014
  7. Trook

    Trook Space Penguin Leader

    It seems you can not merge evry type of file right now. Tried to merge a .npctype or a .treasurpool, but no chance (or i did it wrong). Hopefully this will work in future days. (the merge stuff is quite new)

    3.: That's in the main post arround this image:
    [​IMG]
    (Black = mustContainAirBack... White = must ContainSolidBack / so this may only occur at the surface)

    2. Not sure about that now, but as i payed the game i noticed that for example the scifi dungeon mostly spawns on moons.
    I have many ides how this may happen, but nothing confirmed (I belive it has to do with the layout of the entrance?)

    1. Also not 100% sure, but it seems that "easy to merge" entrances have a better chance to appear. (or is it just the maxRadius of the dungeon?)

    I will tell you more about it as soon as i figured it out.
     
  8. jLnMart

    jLnMart Void-Bound Voyager

    i can't say for .treasurpool but merge work like a charm on .npctype files
     
  9. Trook

    Trook Space Penguin Leader

    damned, so i did it wrong :/ I tried to merge the "items" section, but no idea how to merge these arrays ( "[0, .... [1, ...")
     
  10. jLnMart

    jLnMart Void-Bound Voyager

  11. seancruz

    seancruz Big Damn Hero

    Thanks for the answers.

    Weird though. I've only seen sci-fi dungeons on forest worlds. And on several instances, newly created players have actually spawned atop sci-fi dungeons on forest homeworlds.
     
  12. seancruz

    seancruz Big Damn Hero

    Also, do you know of any way to test your dungeons? For example, how will you know your dungeons are spawning correctly? Do you have to travel to different worlds until you find it?
     
  13. Trook

    Trook Space Penguin Leader

    hehe, from the README.txt:

    Note:
    As there are many predefined dungeons, it may take a while until you will find a planet with an hideout.
    If you want the game to ignore all other dungeons, you can edit the file
    "mods\Bandit Hideouts\planetgen.config"
    change the line
    //[ "overwrite", "dungeonWhitelist" ]
    to
    [ "overwrite", "dungeonWhitelist" ]

    This will cause the game to only create BanditHideouts on new visited planets.
     
  14. seancruz

    seancruz Big Damn Hero

    Okay sweet. Everything's going awesome. Been working on a village with new tiles based off the avianvillage, except smaller. Started off only making the villagecenter1 anchor part. All the other parts I deleted, so they do not generate with my new tiles as you can see below:
    [​IMG]
    Only problem is, as soon as I add new parts, they do not generate. And if I try opening the dungeon file in Startructor, an error occurs. I've repeated the process about 3 times, with the same results. Here's what I added to my dungeon file:


    Code:
    "parts" : [
        {
          "name" : "villagecenter1",
          "rules" : [
            [ "maxSpawnCount", [1] ]
          ],
          "def" : [ "image", [ "villagecenter1.png", "villagecenter1-objects.png" ] ]
        },
        {
          "name" : "1",
          "rules" : [
            [ "maxSpawnCount", [ 1 ] ]
          ],
          "def" : [ "image", [ "1.png", "1-objects.png" ] ]
        }
    Any clue? I've also made part 1 have different "rules", but they didn't change anything. no matter what, it never generates, or works on Starstructor. If I take the code part 1 out, and load it into Starstructor everything works fine. So it has to be the code, I'm sure.
     
  15. Trook

    Trook Space Penguin Leader

    oh these errors :D
    the error short text would help.

    I bet it is the missing comma behind the very last "}" when you paste the parts code

    be sure that "body entries" are seperated "{ [ entrya1] , [entry2] , ..... }".
    Only after the last element inside a body MUST NOT be a comma.

    Oh and btw, this looks awesome!!!
    Keep it up, i will help ad far as i can!
     
  16. seancruz

    seancruz Big Damn Hero

    hmm I checked for that too. The last } has no comma. I've no idea what could be the problem.
     
  17. Trook

    Trook Space Penguin Leader

    could you paste the whole part section pls? And the error short text maybe

    You can also try to use http://jsonlint.com/, a JSON validatior
     
  18. seancruz

    seancruz Big Damn Hero

    Trook likes this.
  19. Shadow Wolf TJC

    Shadow Wolf TJC Spaceman Spiff

    For the record, starbound.log shows you what kinds of errors have occurred while running the game. Dungeon not showing up on a planet? There may be an error log about it. Starbound seems to hang while booting up? There may be a syntax error (such as a missing comma, bracket, or curly brace, or one too many). For dealing with syntax errors, the error log will usually include the line number that it's located on. (I usually use Notepad to quickly locate the line number of the file and correct it.)
     
  20. seancruz

    seancruz Big Damn Hero

    I use the Starbound log, but in my case when new parts weren't working, it would say that my dungeon file had a color that couldn't be processed. It gave a #xxxxxx value for the color, but whenever I look it up on photoshop to see what color it is, it doesn't exist. The other strange thing is, none of the colors were edited. It's only once I added the new part code that something happened. If I would take that piece of code out, it worked perfectly. Eventually, I just started from scratch and it worked. No idea why, but I'm glad it works now.
     
Thread Status:
Not open for further replies.

Share This Page