tModLoader Modding Tutorial: World Generation

Did this thread help you?

  • Yes it did!

    Votes: 54 93.1%
  • No, it didn't.

    Votes: 4 6.9%

  • Total voters
    58
  • Poll closed .
Could you help me withore generation after bosses have been killed, I have tried everything I could think of and nothing is working.
 
Thanks for the guide, it's really useful! I have a question, now that I managed to spawn a room (by manipulating the well in ExampleMod), how would I go about putting a door on the side? Its location is relative to wherever the room ends up, so I can't use the player location for a reference point.

capture_2017_03_17_17_22_52_by_irin_mae-db2l0zc.png
 
If you're making the door in a standalone step, just place the door there. Otherwise, assuming you have either a constant size or a variable size (literally, e.g. int size) you could get the middle (if needed), and then the left/right edge of the building, then place it there. Example:
Code:
int size = 10;
//Assuming building is placed from left to right, starting on the way left.
int doorX = position.X;
WorldGen.PlaceObject(/* Forgot what goes here. But you know. :P */); 
//Assuming building is placed right to left, starting on the way right.
doorX = position.X + size;
WorldGen.PlaceObject(/* etc. */); 
//Assuming building is placed from middle.
doorX = position.X - (size / 2); //On left.
doorX = position.X + (size / 2); //On right.
 
HI! Thanks For guide, it helps so much! but how I can transform my biome to something like beehive? (with clear space inside) cuz right now it's looking like this:

And if i can ask, can you add to your guide how to make custom structure that spawns inside biome? Like Abeemination in hive. or jungle shrines.

Thanks a lot!
 

Attachments

  • 20170319161624_1.jpg
    20170319161624_1.jpg
    460.1 KB · Views: 340
Ok finally an update - I could not get the door to work by the code given above :( It spawns doors but they are not attached to the walls around them so they drop when interacted with.

WorldGen.PlaceTile(k + -1, l + 2, 10, true, false, 0, 4);

This did work, for placing specific type of door(in this case a cactus door). But it's not consistent(sometimes there is a door, most times not) and I can't figure out why.
 
HI! Thanks For guide, it helps so much! but how I can transform my biome to something like beehive? (with clear space inside) cuz right now it's looking like this:

And if i can ask, can you add to your guide how to make custom structure that spawns inside biome? Like Abeemination in hive. or jungle shrines.

Thanks a lot!

Looks nice :D
Just place whatever inside of your area. You know, clear it out and place whatever in there. Not much more I can say (without code).

Ok finally an update - I could not get the door to work by the code given above :( It spawns doors but they are not attached to the walls around them so they drop when interacted with.



This did work, for placing specific type of door(in this case a cactus door). But it's not consistent(sometimes there is a door, most times not) and I can't figure out why.

PlaceObject might have a random placement chance, and so mayn't place sometimes. Not sure. Code please (post on http://hastebin.com or http://pastebin.com)
 
Here you go: https://pastebin.com/E9binRyQ
It's very small, but the output is good, only clear space inside it needed (with some islands of blocks to hang on it, mob spawn, structures blah blah blah...)
sry for English :p

PS: how to make it spawn a little bit higher? i tried to manipulate with the numbers but it does not work
 
Last edited:
Hey. I really need help. I read all this but i still dont get it :( Im pretty new to C# so i guess that explains it. I tried to make a Biome in many ways but i always ended up with an only dirt biome or a biome of nothingnes. Pls help i just need the code for ModWorld and the tile code cuase i think im always doing something wrong with that :/. Pls help and thx
 
Hello people!
It seems that there has been an explosion of World Generation in mods, and, well, I want to make it bigger/I'm bored. :p

Note: This tutorial is a bit complicated. You should know how to at least make a basic NPC before you read this. Or be crazy and read it anyways.

So, here will be a basic tutorial on how to make simple lines/passageways, blobs of block, or pools/mini biomes, which will come later.
Ok, let's start off now :D
First off, it'd be useful to have something to base off, so ExampleMod has a decent example (duh) with it's Well. Use that and tinker for a bit, change the water to dirt, as to get a feel for it.
Basic Blob Making
Then, once you're done turning a well into a blob, we can begin.
Go into your ModWorld.cs file add a method called ModifyWorldGenTasks()
The full method is here:
Code:
public override void ModifyWorldGenTasks(List<GenPass> tasks, ref float totalWeight)

Obviously, put {} around it. Now, let's start with a blob because I'm lazy.
Code:
public override void ModifyWorldGenTasks(List<GenPass> tasks, ref float totalWeight)
{
    int genIndex = tasks.FindIndex(genpass => genpass.Name.Equals("Micro Biomes"));
    tasks.Insert(genIndex + 1, new PassLegacy("Dirt Blob", delegate (GenerationProgress progress)
    {
         WorldGen.TileRunner(Main.spawnTileX, Main.spawnTileY + -46, 6, Main.rand.Next(1, 3), TileID.Dirt, true, 0f, 0f, true, true);
    }));
}

Here's an explanation of what's in the TileRunner method.
Code:
TileRunner(int i, int j, double strength, int steps, int type, bool addTile = false, float speedX = 0f, float speedY = 0f, bool noYChange = false, bool overRide = true)
So, I and J is X and Y, respectively. Strength decides how big it is (I can't understand the code enough to give a presise measurement.) Type is the type of tile, in TileID, int, or mod.tiletype. Add Tile checks if you're adding tiles or replacing them. SpeedX and Y sets the direction it goes is (also don't understand the code). noYChange is just that. It doesn't change Y. overRide means it can override other tiles.

That should place a blob of dirt above the player. You can replace the TileID with any other ID or mod.TileType("") if you wish.
That is the simplest of the things you can possibly do.

I'll keep the above code for future inserts, so I don't have to re-write it over. And over. And over again :D
So when I say something of this sort: Add code into your existing method, it means add the code into the Dirt Blob thing :D
Making a Line
Now for something a bit less...blobby.

I personally did this in a method as to make it easier to randomize, but you may do whatever you want.
So, there is a method in WorldGen called PlaceTile. It's a more precise way of using TileRunner.
Here is the method.
Code:
WorldGen.PlaceTile(int X, int Y, int TileType);
Please note that it places in tile positions, so if you want to place it in game at, say, npc.position.X, do npc.position.X / 16.

So, we use a for loop to make a straight line, like this:
Code:
for (int i = 0; i < 10; i++)
{
    WorldGen.PlaceTile(Main.spawnTileX + i, Main.spawnTileY - 30, TileID.Iron);
}

If you add that, it should make a 10 block long iron ore thing. I might've gotten the TileID wrong, but you get the point.
View attachment 131880
Now let's get to the really fun stuff :D
Overriding a Biome
Are you tired of having Jungles in your world? Don't Jungle Bats bother you when you're setting up your mud hut? Well, I got the fix for you! Code. yay?
Anyways, yes, you can remove biomes and put a bunch of whatever there.
Code:
int jungleGen = tasks.FindIndex(genpass => genpass.Name.Equals("Jungle"));
tasks[jungleGen] = new PassLegacy("More Dirt Blobs", delegate (GenerationProgress progress)
{
    WorldGen.TileRunner(Main.spawnTileX, Main.spawnTileY + 12, 6, Main.rand.Next(1, 3), TileID.Dirt, true, 0f, 0f, true, true);
});
So now you should have no jungle (if I remembered the name correctly) and an extra blob of dirt, but below you. Do not put this is the same code block (These: { }) as the previous dirt blob, that will give an error. Still needs verifacation.

How to Place Multi blocks


As shown above, people want to know how to place something such as a Table or Chair.
So, you have to use the WorldGen.PlaceTile method.
Code:
//PlaceObject(int x, int y, int type, bool mute = false, int style = 0, int alternate = 0, int random = -1, int direction = -1)[code] That's an explanation of the args.[/SPOILER]
So, this will place a modded chair in the X and Y:
[code] WorldGen.PlaceObject(Main.spawnTileX + 10, Main.spawnTileY, mod.TileType("ExampleChair"), false, 0, 0, -1, 1);
This, without testing, should place an Example Chair 10 blocks away from the player.
Placing a Chest
I've barely explored this concept; you could make a "starter chest" near spawn with some good lewt. Or, just a Meowmere. Either work.
So, you can't place chests with PlaceObject (for some reason) so you need PlaceChest. Code shown below.
Code:
WorldGen.PlaceChest(int X, int Y, int type, bool noNearOtherChests = false, int style = 0);
So, basic explanation of what those do: X and Y is duh. Type is what chest type. notNearOtherChests makes it so you can't place a chest there if it's near another. Style is what frame.X is should be at, used for placing locked chests.
So, just do
Code:
WorldGen.PlaceChest(Main.spawnTileX - 10, Main.spawnTileY, 21, false, 2);
for a chest to appear next to the player. Not sure what chest though, the chest tilesheet is the longest thing ever. (Needs testing)

Making a Meteor-like biome

Easy enough ;)
Code:
        public void OreComet()
        {
            int x = Main.rand.Next(0, Main.maxTilesX);
            int y = Main.worldSurface - 200;
            int[] tileIDs = { 6, 7, 8, 9 , 166, 167, 168, 169};
            if (Main.tile[x, y].type <= -1)
            {
                y--;
            }
            else
            {
                WorldGen.TileRunner(x, y, 2, 4, tileIDs[Main.rand.Next(tileIDs.Length)], false, 0f, 0f, true, true);
                return;
            }
        }
So, here is a method that makes a 'comet' out of any pre-hardmode ore, except Demonite, Hellstone and Crimtane. It places this anywhere above ground, with it initially spawning above the world, and doesn't place until it hits a block. This method won't do anything alone, though, you'll place it in the Kill method of a projectile, which is easiest. The projectile should call Kill OnTileCollide(). Code:
Code:
        public override void Kill()
        {
            OreComet();
        }
That should have a 0.1% chance to spawn every frame.
Have fun! :D

Floating Islands
Let's spam us some candy cane w/ red team block floating islands.

As suggested by @Jenosis ;)
Anyways, I'll be using a method named (by me, since I'm creative) BlockLining.

Code:
        public int BlockLining(double x, double y, int repeats, int tileType, bool random, int max, int min = 3)
        {
            for (double i = x; i < x + repeats; i++)
            {
                if (random)
                {
                    for (double k = y; k < y + Main.rand.Next(min, max); k++)
                    {
                        WorldGen.PlaceTile((int)i, (int)k, tileType);
                    }
                }
                else
                {
                    for (double k = y; k < y + max; k++)
                    {
                        WorldGen.PlaceTile((int)i, (int)k, tileType);
                    }
                }
            }
            return repeats;
        }
This will make a "lining" of blocks either as tall as Max or a random of Min, Max.
Now for the actual island. I used it in an inefficient way, but it makes it easier to read.
Code:
        public void MiniIsland()
        {
            double X = WorldGen.genRand.Next(0, Main.maxTilesX);
            double Y = (double)Main.worldSurface - Main.rand.Next(255, 270);
            for (int i = 0; i < 13; i++)
            {
                if (i == 0)
                {
                    BlockLining(X, Y - 4, 4, TileID.Cloud, true, 6);
                }
                else if (i == 1)
                {
                    BlockLining(X + 4, Y - 3, 4, TileID.Cloud, true, 6);
                }
                else if (i == 2)
                {
                    BlockLining(X + 8, Y - 2, 4, TileID.Cloud, true, 6);
                }
                else if (i == 3)
                {
                    BlockLining(X + 12, Y - 1, 5, TileID.Cloud, true, 6);
                }
                else if (i == 4)
                {
                    BlockLining(X + 17, Y, 5, TileID.Cloud, true, 6);
                }
                else if (i == 5)
                {
                    BlockLining(X + 21, Y + 1, 6, TileID.Cloud, true, 6);
                }
                else if (i == 6)
                {
                    BlockLining(X + 27, Y + 2, 6, TileID.Cloud, true, 6);
                }
                else if (i == 7)
                {
                    BlockLining(X + 33, Y + 1, 7, TileID.Cloud, true, 6);
                }
                else if (i == 8)
                {
                    BlockLining(X + 40, Y, 5, TileID.Cloud, true, 6);
                }
                else if (i == 9)
                {
                    BlockLining(X + 45, Y - 1, 5, TileID.Cloud, true, 6);
                }
                else if (i == 10)
                {
                    BlockLining(X + 49, Y - 2, 4, TileID.Cloud, true, 6);
                }
                else if (i == 11)
                {
                    BlockLining(X + 53, Y - 3, 4, TileID.Cloud, true, 6);
                }
                else if (i == 12)
                {
                    BlockLining(X + 57, Y - 4, 4, TileID.Cloud, true, 6);
                }//z
                else if (i == 13)
                {
                    BlockLining(X + 61, Y - 5, 4, TileID.Cloud, true, 6);
                }
            }
            for (double i = X + 4; i < X + 57; i++)
                WorldGen.PlaceTile((int)i, (int)Y - 4, TileID.MushroomGrass);
            for (double i = X + 8; i < X + 53; i++)
                WorldGen.PlaceTile((int)i, (int)Y - 3, TileID.Mud);
            for (double i = X + 12; i < X + 49; i++)
                WorldGen.PlaceTile((int)i, (int)Y - 2, TileID.Mud);
            for (double i = X + 16; i < X + 45; i++)
                WorldGen.PlaceTile((int)i, (int)Y - 1, TileID.Mud);
            for (double i = X + 21; i < X + 40; i++)
                WorldGen.PlaceTile((int)i, (int)Y, TileID.Mud);
            for (double i = X + 26; i < X + 33; i++)
                WorldGen.PlaceTile((int)i, (int)Y + 1, TileID.Mud);
        }
Basically, it makes an "outline" of clouds out of BlockLinings and then places Mushroom Grass and Mud in the center.
View attachment 144435
Change any of the TileIDs to your liking. Have fun! :D

Placing a Tree, and growing the Tree
This one is pretty simple, really. I'll just slap in some code and done :p
Code:
WorldGen.PlaceTile(X, Y, TileID.Dirt);
do that as a base. Make it 3 wide, so the tree will go properly.
Then:
Code:
WorldGen.PlaceObject(X, Y - 1, mod.TileType("MagicSapling));
WorldGen.GrowTree(X, Y - 1);
This will grow the MagicSapling if it can. Otherwise, it'll simply place a sapling.
Notify me on this thread/my profile page if this doesn't work. Thanks!

Placing Walls
It's basically the same as placing a tile. But with walls. Woah.
Here's two:
Code:
WorldGen.PlaceTile(int i, int j, int type)
or
Code:
Main.tile[i, j].wall = WallID.MudUnsafe;
Simple enough :p

Changing Tile Slopes
Also simple.
Code:
Main.tile[i, j].slope(0);
From what I know, it goes from 0 to 12. Tell me if I'm wrong.

TileIDs can be found here: https://github.com/bluemagic123/tModLoader/wiki/Vanilla-Tile-IDs

Some useful (ints) things for WorldGen are Main.maxTilesY, same thing but with X, Main.spawnTileY, and X.
Main.spawnTileX +/- 300-400 is the Snow/Desert biome. Main.maxTilesY - 200 is the top of the Underworld.

The amount of derps done here: 9 so far.

I will expand this upon user request, though I won't do your WorldGen for you.
Anyways, that'll be it for now. Leave any comments/questions/suggestions below :D

Credits
Thanks to @Graydee for being helpful with worldgen on occasion;)
Thanks to @EchoNex for the first WorldGen code he gave me.
Thanks to @jopojelly for random helps :D


I request that anyone who uses this tutorial and publishes it in any way, Mod Browser or not, gives me any sort of credit. Either it be a link to this thread, a link to me, a simple "thanks to gabe for some worldgen stuff", please do it :D

So, how do I make a custom grass that will spread on a custom block?
 
The grass seed item will only be needed if you want to place it. The block alone will spread naturally.

I'm assuming you mean the TileRunner of the first part of the tutorial, which means of course it can't override it...it places dirt. lol
 
Back
Top Bottom