FANDOM


2012-09-30 00002

see the demonite and meteorite? i did that in blahblahbal's avalon mod, by helping him fixing something.

Difficulty: Difficulty-5
Clock: noframe



Hey everyone, Poro here!


This may take time to understand and to make it work, but don't give up!


Spawning the BiomeEdit

To spawn the biome, we have to use the ModifyWorld() Method (in the Tile.cs), the same method as in Spawning Ores. because, if we put it in the GenerateWorld, we wil get things messed up, and that's something we don't want!

public void ModifyWorld() {
    Main.statusText="Adding Custom Biome"; // you can always change the text.
    AddCustomBiome(); // the method it's calling

}

// now we need the AddCustomBiome().

public static void AddCustomBiome() {
int num9 = 0;;
double num6;
num6 = Main.worldSurface;
for (int num57 = 0; num57 < (int)((double)(Main.maxTilesX * Main.maxTilesY) * 0.0015); num57++)
{
  float num58 = (float)((double)num57 / ((double)(Main.maxTilesX * Main.maxTilesY) * 0.0015));
  Main.statusText = string.Concat(new object[]
  {
   "Adding Custom Biome:",
   " ",
   (int)(num58 * 100f + 1f),
   "%"
  }); // this gives a %-counter.
  WorldGen.TileRunner(WorldGen.genRand.Next(0, Main.maxTilesX), WorldGen.genRand.Next((int)num6, Main.maxTilesY), (double)WorldGen.genRand.Next(2, 5), WorldGen.genRand.Next(2, 20), (byte)Config.tileDefs.ID["Custom Biome Tile"], false, 0f, 0f, false, true);
  WorldGen.TileRunner(WorldGen.genRand.Next(0, Main.maxTilesX), WorldGen.genRand.Next((int)num6, Main.maxTilesY), (double)WorldGen.genRand.Next(8, 15), WorldGen.genRand.Next(7, 30), (byte)Config.tileDefs.ID["Custom Biome Tile 2"], false, 0f, 0f, false, true);

 }
}

// this code is ripped from the 'generating random holes'
// from the world generation.

You can always change it!

(Use ILSpy to decompile it, then take a look at the WorldGen class.)

(The link for ILSpy is in the Resources page)


But, as always, there are some exceptions.


If you base your ore on the Mushroom Patches (remember to delete the grass part),

use this to call your custom method:

	Main.statusText = "Generating Custom Biomes";
	for (int loopcounter = 0; loopcounter < Main.maxTilesX / 500; loopcounter++) {
		int i3 = WorldGen.genRand.Next((int)((double)Main.maxTilesX * 0.3), (int)((double)Main.maxTilesX * 0.7));
		int j3 = WorldGen.genRand.Next((int)Main.rockLayer, Main.maxTilesY - 450);
		ModWorld.CustomBiomeGeneration(i3, j3); // here, the code is called CustomBiomeGeneration, and it's located in World.cs.
	}

You can see that it is not CustomBiomeGeneration(), but CustomBiomeGeneration(int, int).

It's the same with the dungeon:

    Main.statusText = "Generating Custom Dungeon...";
    int x;
    if (num9 == -1) {
        x = WorldGen.genRand.Next((int)((double)Main.maxTilesX * 0.05), (int)((double)Main.maxTilesX * 0.2));
        num9 = -1;
    }
    else {
        x = WorldGen.genRand.Next((int)((double)Main.maxTilesX * 0.8), (int)((double)Main.maxTilesX * 0.95));
        num9 = 1;
    }
    int y = (int)((Main.rockLayer + (double)Main.maxTilesY) / 2.0) + WorldGen.genRand.Next(-200, 200);
    ModWorld.MakeCustomDungeon(x, y, 41, 7);

See, it's MakeCustomDungeon(int, int, int, int);

Now the Meteor, pretty hard:

public static void DropCustomMeteor() { // nothing here

 bool flag = true;
int num = 0;
if (Main.netMode == 1) {
  return;
}
for (int i = 0; i < 255; i++) {
  if (Main.player[i].active) {
   flag = false;
   break;
  }
}
int num2 = 0;
float num3 = (float)(Main.maxTilesX / 4200);
int num4 = (int)(400f * num3);
for (int j = 5; j < Main.maxTilesX - 5; j++) {
  int num5 = 5;
  while ((double)num5 < Main.worldSurface) {
   if (Main.tile[j, num5].active && (Main.tile[j, num5].type == (byte)Config.tileDefs.ID["Tile 1"] || Main.tile[j, num5].type == (byte)Config.tileDefs.ID["Tile 2"])) {
    num2++;
    if (num2 > num4) {
     return;
    }
   }
   num5++;
  }
}
while (!flag) {
  float num6 = (float)Main.maxTilesX * 0.08f;
  int num7 = Main.rand.Next(50, Main.maxTilesX - 50);
  while ((float)num7 > (float)Main.spawnTileX - num6 && (float)num7 < (float)Main.spawnTileX + num6) {
   num7 = Main.rand.Next(50, Main.maxTilesX - 50);
  }
  for (int k = Main.rand.Next(100); k < Main.maxTilesY; k++) {
   if (Main.tile[num7, k].active && Main.tileSolid[(int)Main.tile[num7, k].type]) {
    flag = ModWorld.CustomMeteor(num7, k); // call code 2 (in World.cs) (int X, int Y)
    break;
   }
  }
  num++;
  if (num >= 100) {
   return;
  }
}
}
// code 2, and a nice divider -------------------------------------------------
public static bool CustomMeteor(int i, int j) {
    if (i < 50 || i > Main.maxTilesX - 50) {
        return false;
    }
    if (j < 50 || j > Main.maxTilesY - 50) {
        return false;
    }
    int num = 25;
    Rectangle rectangle = new Rectangle((i - num) * 16, (j - num) * 16, num * 2 * 16, num * 2 * 16);
    for (int k = 0; k < 255; k++) {
        if (Main.player[k].active) {
            Rectangle value = new Rectangle((int)(Main.player[k].position.X + (float)(Main.player[k].width / 2) - (float)(NPC.sWidth / 2) - (float)NPC.safeRangeX), (int)(Main.player[k].position.Y + (float)(Main.player[k].height / 2) - (float)(NPC.sHeight / 2) - (float)NPC.safeRangeY), NPC.sWidth + NPC.safeRangeX * 2, NPC.sHeight + NPC.safeRangeY * 2);
            if (rectangle.Intersects(value)) {
                return false;
            }
        }
    }
    for (int l = 0; l < 200; l++) {
        if (Main.npc[l].active) {
            Rectangle value2 = new Rectangle((int)Main.npc[l].position.X, (int)Main.npc[l].position.Y, Main.npc[l].width, Main.npc[l].height);
            if (rectangle.Intersects(value2)) {
                return false;
            }
        }
    }
    for (int m = i - num; m < i + num; m++) {
        for (int n = j - num; n < j + num; n++) {
            if (Main.tile[m, n].active && Main.tile[m, n].type == 21) {
                return false;
            }
        }
    }
    WorldGen.stopDrops = true;
    num = 15;
    for (int num2 = i - num; num2 < i + num; num2++) {
        for (int num3 = j - num; num3 < j + num; num3++) {
            if (num3 > j + Main.rand.Next(-2, 3) - 5 && (double)(Math.Abs(i - num2) + Math.Abs(j - num3)) < (double)num * 1.5 + (double)Main.rand.Next(-5, 5)) {
                if (!Main.tileSolid[(int)Main.tile[num2, num3].type]) {
                    Main.tile[num2, num3].active = false;
                }
                if (Main.rand.Next(2) == 1) {
                    Main.tile[num8, num9].type = (byte)Config.tileDefs.ID["rile 1"];
                }
                else {
                    Main.tile[num8, num9].type = (byte)Config.tileDefs.ID["tile 2"];
                }
            }
        }
    }
    num = 10;
    for (int num4 = i - num; num4 < i + num; num4++) {
        for (int num5 = j - num; num5 < j + num; num5++) {
            if (num5 > j + Main.rand.Next(-2, 3) - 5 && Math.Abs(i - num4) + Math.Abs(j - num5) < num + Main.rand.Next(-3, 4)) {
                Main.tile[num4, num5].active = false;
            }
        }
    }
    num = 16;
    for (int num6 = i - num; num6 < i + num; num6++) {
        for (int num7 = j - num; num7 < j + num; num7++) {
            if (Main.tile[num6, num7].type == 5 || Main.tile[num6, num7].type == 32) {
                WorldGen.KillTile(num6, num7, false, false, false, null);
            }
            WorldGen.SquareTileFrame(num6, num7, true);
            WorldGen.SquareWallFrame(num6, num7, true);
        }
    }
    num = 23;
    for (int num8 = i - num; num8 < i + num; num8++) {
        for (int num9 = j - num; num9 < j + num; num9++) {
            if (Main.tile[num8, num9].active && Main.rand.Next(10) == 0 && (double)(Math.Abs(i - num8) + Math.Abs(j - num9)) < (double)num * 1.3) {
                if (Main.tile[num8, num9].type == 5 || Main.tile[num8, num9].type == 32) {
                    WorldGen.KillTile(num8, num9, false, false, false, null);
                }
                if (Main.rand.Next(2) == 1) {
                    Main.tile[num8, num9].type = (byte)Config.tileDefs.ID["Tile 1"];
                }
                else {
                    Main.tile[num8, num9].type = (byte)Config.tileDefs.ID["Tile 2"];
                }
                WorldGen.SquareTileFrame(num8, num9, true);
            }
        }
    }
    WorldGen.stopDrops = false;
    if (Main.netMode == 0) {
        Main.NewText("A Moon Meteor has Landed!", 50, 255, 130);
    }
    else {
        if (Main.netMode == 2) {
            NetMessage.SendData(25, -1, -1, "A Custom Meteor has Landed!", 255, 50f, 255f, 130f, 0);
        }
    }
    if (Main.netMode != 1) {
        NetMessage.SendTileSquare(-1, i, j, 30);
    }
    return true;
}
// don't touch all other things!


If you rip and edit a code from the GenerateWorld(), you don't have to put something in between the ()'s.


For adding a chest, you can add:

​ if (AddCustomChest(i, j, Config.itemDefs.byName["Item"].type, false, 1/* stack!*/)) { // that item will always be in the chest, and replace the i (X) and j (Y) to what 
you want.
}

Then the code itself (in the same .cs file)

public static bool AddCustomChest(int i, int j, int contain = 0, bool notNearOtherChests = false, int Style = -1) {
	if (WorldGen.genRand == null) {
		WorldGen.genRand = new Random((int)DateTime.Now.Ticks);
	}
	int k = j;
	while (k < Main.maxTilesY) {
		if (Main.tile[i, k].active && Main.tileSolid[(int)Main.tile[i, k].type]) {
			int num = k;
			int num2 = WorldGen.PlaceChest(i - 1, num - 1,(byte)Config.tileDefs.ID["Chest Name"], notNearOtherChests, 1);
			if (num2 >= 0) {
				int num3 = 0;
				while (num3 == 0) {
					if (contain > 0) {
						Main.chest[num2].item[num3].SetDefaults(contain, false);
						if (contain == Config.itemDefs.byName["Item 1"].type) {
							Main.chest[num2].item[num3].stack = WorldGen.genRand.Next(5, 11); // random stack
						}
						else if (contain == Config.itemDefs.byName["Item 2"].type) {
							Main.chest[num2].item[num3].stack = WorldGen.genRand.Next(2, 3); // random stack
						}
						else if (contain == 73 /* default item!*/) {
							Main.chest[num2].item[num3].stack = WorldGen.genRand.Next(1, 2); // random stack
						}
						else if (contain == Config.itemDefs.byName["Weapon 1"].type) {
							Main.chest[num2].item[num3].Prefix(-1); // random prefix
						}
						num3++;
					}
					int randomNum = WorldGen.genRand.Next(3); // random item type
					if (randomNum == 0) {
						Main.chest[num2].item[num3].SetDefaults(50, false);
						num3++;
					}
					else if (randomNum == 1) {
						Main.chest[num2].item[num3].SetDefaults(287, false);
						Main.chest[num2].item[num3].stack = WorldGen.genRand.Next(31, 53);
						num3++;
					}
					else if (randomNum == 2) {
						Main.chest[num2].item[num3].SetDefaults(126, false);
						Main.chest[num2].item[num3].stack = WorldGen.genRand.Next(7, 14);
						num3++;
					}
					Main.chest[num2].item[num3].SetDefaults(57, false);
					int numOfItems = WorldGen.genRand.Next(6, 19);
					Main.chest[num2].item[3].stack = numOfItems;
					int randomNum2 = WorldGen.genRand.Next(3);
					if (randomNum2 == 0) {
						Main.chest[num2].item[3].SetDefaults(118, false);
					}
					else if (randomNum2 == 1)
					{
						Main.chest[num2].item[3].SetDefaults(28, false);
						Main.chest[num2].item[3].stack = WorldGen.genRand.Next(1, 6);
					}
					else if (randomNum2 == 2) {
						Main.chest[num2].item[3].SetDefaults(166, false);
						Main.chest[num2].item[3].stack = WorldGen.genRand.Next(7, 14);
					}
					Main.chest[num2].item[4].SetDefaults(73, false);
					int numOfCoins = WorldGen.genRand.Next(1, 3);
					Main.chest[num2].item[4].stack = numOfItems;
// random items
				}
				return true;
			}
			return false;
		}
		else {
			k++;
		}
	}
	return false;
}


Spawning NPC's in the biome.Edit

With tiles only, it gets pretty boring. so, let's move on to the NPC's.


You have to put this in the <npc name>.cs.

public bool SpawnNPC(int x, int y, int PID) {
	int swidth = (int)(Main.screenWidth/16f);
	int sheight = (int)(Main.screenHeight/16f);
	int sy = (int)(Main.screenPosition.Y/16f);
	int sx = (int)(Main.screenPosition.X/16f);
	for (int a = sx; a <(sx+swidth); a++) {
		for (int b = sy; b <(sy + sheight); b++) {
// some tile-check variables
			if ((Main.tile[a,b].active /* if active */&& (Main.tile[a,b].type == Config.tileDefs.ID["Custom Biome Block" /* guess what this is... */])) && Main.dayTime /* change this to what you want* Main.rand.Next(20 /* you can edit this, too */) == 1) {
				return true; // only then, spawn
			}
            return false; // otherwise, not
		}
        return false; // same
	}
	return false; // same
}

Thank Phlebas for this code!


This is not everything!

Adding musicEdit

Yes, why not?

We need a music (put it in the sound folder), and have it to play when we're in the biome.

Put this in the ModWorld (aka. World.cs)

public static int musicCount=0;
public static float qcurVolume;

public static void UpdateWorld() {
    int swidth = (int)(Main.screenWidth/16f);
    int sheight= (int)(Main.screenHeight/16f);
    int sy= (int)(Main.screenPosition.Y/16f);
    int sx= (int)(Main.screenPosition.X/16f);
    for (int i = sx; i <(sx+swidth); i++) {
        for (int j = sy; j <(sy + sheight); j++) {
            if ((Main.tile[i,j].active && (Main.tile[i,j].type == Config.tileDefs.ID["Custom Biome tile"]) || (Main.tile[i,j].type == Config.tileDefs.ID["Custom biome Tile"]))) { // yup, again.
                if (musicCount==0) { // if count is 0
                    Main.PlaySound(2,-1,-1,soundHandler.soundID["Custom Biome Music"]); // change the name to the sound in your sound folder that you want to use)
                    Main.musicVolume = qcurVolume;
                    musicCount++;
                }
                if (musicCount == 7680 /* set this to the time of your music (in frames (60 frames per second))*/) {
                    musicCount = 0; // reset
                }
            }
        }
    }
}

public void Initialize() {
// reset everything
musicCount = 0;
qcurVolume = Main.musicVolume;
}

That's it! Don't forget to make your tiles themselves!


-Poro

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.