void PlaceTallGrass(int x, int posY, int z, IServerChunk[] chunks, float rainRel, float tempRel, float temp, float forestRel) { double rndVal = blockLayerConfig.Tallgrass.RndWeight * rnd.NextDouble() + blockLayerConfig.Tallgrass.PerlinWeight * grassDensity.Noise(x, z, -0.5f); double extraGrass = Math.Max(0, rainRel * tempRel - 0.25); if (rndVal <= GameMath.Clamp(forestRel - extraGrass, 0.05, 0.99) || posY >= mapheight - 1 || posY < 1) { return; } int blockId = chunks[posY / chunksize].Blocks[(chunksize * (posY % chunksize) + z) * chunksize + x]; if (api.World.Blocks[blockId].Fertility <= rnd.NextInt(100)) { return; } double gheight = Math.Max(0, grassHeight.Noise(x, z) * blockLayerConfig.Tallgrass.BlockCodeByMin.Length - 1); int start = (int)gheight + (rnd.NextDouble() < gheight ? 1 : 0); for (int i = start; i < blockLayerConfig.Tallgrass.BlockCodeByMin.Length; i++) { TallGrassBlockCodeByMin bcbymin = blockLayerConfig.Tallgrass.BlockCodeByMin[i]; if (forestRel <= bcbymin.MaxForest && rainRel >= bcbymin.MinRain && temp >= bcbymin.MinTemp) { chunks[(posY + 1) / chunksize].Blocks[(chunksize * ((posY + 1) % chunksize) + z) * chunksize + x] = bcbymin.BlockId; return; } } }
public override bool TryPlaceBlockForWorldGen(IBlockAccessor blockAccessor, BlockPos pos, BlockFacing onBlockFace, LCGRandom worldgenRandom) { int fruit = (int)Math.Round(worldgenRandom.NextDouble() * 2.0); GenPalmTree(blockAccessor, pos, fruit); return(true); }
public void Generate(IBlockAccessor blockAccessor, LCGRandom rnd, int posX, int posY, int posZ, int firstBlockId) { float quantity = Quantity.nextFloat() + 1; int chunkSize = blockAccessor.ChunkSize; Block[] blocks = getBlocks(firstBlockId); if (blocks.Length == 0) { return; } while (quantity-- > 0) { if (quantity < 1 && rnd.NextDouble() > quantity) { break; } pos.X = posX + (int)OffsetX.nextFloat(); pos.Z = posZ + (int)OffsetZ.nextFloat(); int index = GameMath.Mod((int)BlockCodeIndex.nextFloat(), blocks.Length); IServerChunk chunk = (IServerChunk)blockAccessor.GetChunk(pos.X / chunkSize, 0, pos.Z / chunkSize); if (chunk == null) { break; } int lx = GameMath.Mod(pos.X, chunkSize); int lz = GameMath.Mod(pos.Z, chunkSize); if (Placement == EnumBlockPatchPlacement.Underground) { pos.Y = rnd.NextInt(Math.Max(1, chunk.MapChunk.WorldGenTerrainHeightMap[lz * blockAccessor.ChunkSize + lx] - 1)); } else { pos.Y = chunk.MapChunk.RainHeightMap[lz * blockAccessor.ChunkSize + lx] + 1; if (Math.Abs(pos.Y - posY) > 8 || pos.Y >= blockAccessor.MapSizeY - 1) { continue; } if (Placement == EnumBlockPatchPlacement.UnderWater) { tempPos.Set(pos.X, pos.Y - GameMath.Max(1, MinWaterDepth), pos.Z); Block downBlock = blockAccessor.GetBlock(tempPos); if (downBlock == null || downBlock.LiquidCode != "water") { continue; } } } blocks[index].TryPlaceBlockForWorldGen(blockAccessor, pos, BlockFacing.UP, rnd); } }
public override bool TryPlaceBlockForWorldGen(IBlockAccessor blockAccessor, BlockPos pos, BlockFacing onBlockFace, LCGRandom worldGenRand) { if (blockAccessor.GetBlockId(pos) != 0) { return(false); } int surfaceY = blockAccessor.GetTerrainMapheightAt(pos); if (surfaceY - pos.Y < 30 || pos.Y < 25) { return(false); } BlockPos cavepos = getSemiLargeCavePos(blockAccessor, pos); if (cavepos == null) { return(false); } int dy = 0; while (dy < 15 && !blockAccessor.GetBlock(cavepos.X, cavepos.Y + dy, cavepos.Z).SideSolid[BlockFacing.UP.Index]) { dy++; } if (dy >= 15) { return(false); } blockAccessor.SetBlock(this.BlockId, cavepos.AddCopy(0, dy, 0)); if (EntityClass != null) { blockAccessor.SpawnBlockEntity(EntityClass, cavepos.AddCopy(0, dy, 0)); } BlockPos tmppos = new BlockPos(); int tries = 55 + worldGenRand.NextInt(55); while (tries-- > 0) { int offX = worldGenRand.NextInt(15) - 7; int offY = worldGenRand.NextInt(15) - 7; int offZ = worldGenRand.NextInt(15) - 7; if (worldGenRand.NextDouble() < 0.4) { tryPlaceDecoUp(tmppos.Set(cavepos.X + offX, cavepos.Y + offY, cavepos.Z + offZ), blockAccessor, worldGenRand); } else { tryPlaceDecoDown(tmppos.Set(cavepos.X + offX, cavepos.Y + offY, cavepos.Z + offZ), blockAccessor, worldGenRand); } } return(true); }
private void OnChunkColumnGen(IServerChunk[] chunks, int chunkX, int chunkZ, ITreeAttribute chunkGenParams = null) { Dictionary <Vec3i, int> ores = new Dictionary <Vec3i, int>(); for (int cY = 0; cY < chunks.Length; cY++) { IServerChunk chunk = chunks[cY]; if (chunk.Blocks == null) { continue; } for (int x = 0; x < chunksize; x++) { for (int y = 0; y < chunksize; y++) { for (int z = 0; z < chunksize; z++) { int block = chunk.Blocks[(y * chunksize + z) * chunksize + x]; if (surfaceBlocks.ContainsKey(block) && !ores.ContainsKey(new Vec3i(x, y, z))) { ores.Add(new Vec3i(x, y, z), block); } } } } foreach (var val in ores) { Vec3i vec = val.Key; int ore = val.Value; if (surfaceBlocks.TryGetValue(ore, out int surface)) { for (int y = vec.Y; y < chunksize; y++) { rnd.InitPositionSeed(chunkX * vec.X, chunkZ * vec.Z); if (y < 1 || rnd.NextDouble() > 0.1) { continue; } int dX = rnd.NextInt(chunksize), dZ = rnd.NextInt(chunksize); int block = chunk.Blocks[(y * chunksize + dZ) * chunksize + dX]; int dBlock = chunk.Blocks[((y - 1) * chunksize + dZ) * chunksize + dX]; if (bA.GetBlock(dBlock).Fertility > 4 && bA.GetBlock(block).IsReplacableBy(bA.GetBlock(ore)) && !bA.GetBlock(block).IsLiquid()) { chunk.Blocks[(y * chunksize + dZ) * chunksize + dX] = surface; bA.ScheduleBlockUpdate(new BlockPos(dX, y, dZ)); } } } } } }
public override bool TryPlaceBlockForWorldGen(IBlockAccessor blockAccessor, BlockPos pos, BlockFacing onBlockFace, LCGRandom worldGenRand) { bool placed = base.TryPlaceBlockForWorldGen(blockAccessor, pos, onBlockFace, worldGenRand); if (!placed) { return(false); } double rnd = worldGenRand.NextDouble(); if (rnd < 1 / 300.0) { GenRareColorPatch(blockAccessor, pos, rareVariants[worldGenRand.NextInt(rareVariants.Length)], worldGenRand); } else if (rnd < 1 / 120.0) { GenRareColorPatch(blockAccessor, pos, uncommonVariants[worldGenRand.NextInt(uncommonVariants.Length)], worldGenRand); } return(true); }
public void GenPalmTree(IBlockAccessor blockAccessor, BlockPos pos, int fruit) { Block block = blockAccessor.GetBlock(pos.DownCopy()); if (block.FirstCodePart() == "sand") { for (int i = 0; i < bottomOffsets.Length; i++) { Block d = blockAccessor.GetBlock(pos.X + bottomOffsets[i].X, pos.Y + bottomOffsets[i].Y, pos.Z + bottomOffsets[i].Z); if (d.LiquidCode == "water") { for (int k = 0; k < offsets.Length; k++) { Block c = blockAccessor.GetBlock(pos.X + offsets[i].X, pos.Y + offsets[i].Y, pos.Z + offsets[i].Z); if (c.Class == Class) { return; } } rand.InitPositionSeed(pos.X, pos.Y); Block[] stretchedTrunk = trunk.Stretch((int)(rand.NextDouble() * (maxTreeSize))); BlockPos top = new BlockPos(pos.X, pos.Y + stretchedTrunk.Length, pos.Z); for (int j = 0; j < stretchedTrunk.Length; j++) { blockAccessor.SetBlock(stretchedTrunk[j].BlockId, new BlockPos(pos.X, pos.Y + j, pos.Z)); } blockAccessor.SetBlock(tip.BlockId, top); blockAccessor.SpawnBlockEntity("PalmTree", top); GenFrondAndFruits(top, blockAccessor, stretchedTrunk.Length, fruit); break; } } } return; }
public override bool TryPlaceBlockForWorldGen(IBlockAccessor blockAccessor, BlockPos pos, BlockFacing onBlockFace, LCGRandom worldGenRand) { if (!HasSolidGround(blockAccessor, pos)) { return(false); } int blockId = BlockId; if (worldGenRand.NextDouble() <= 0.20) { blockId = blockAccessor.GetBlock(CodeWithPath("looseflints-" + Variant["rock"] + "-free")).BlockId; } Block block = blockAccessor.GetBlock(pos); if (block.IsReplacableBy(this) && !block.IsLiquid()) { blockAccessor.SetBlock(blockId, pos); return(true); } return(false); }
public void TriggerTransition() { TriggerTransition(30 + (float)Rand.NextDouble() * 60 * 60 / ws.api.World.Calendar.SpeedOfTime); }
public override bool TryPlaceBlockForWorldGen(IBlockAccessor blAcc, BlockPos pos, BlockFacing onBlockFace, LCGRandom worldgenRand) { int cnt = 2 + worldgenRand.NextInt(25); float depth = GameMath.Sqrt(GameMath.Sqrt(cnt)); float craterRadius = GameMath.Sqrt(cnt) * 1.25f; // Look for even or downwards curved ground if (pos.Y > 250 || !IsSolid(blAcc, pos.X, pos.Y - 3, pos.Z) || !IsSolid(blAcc, pos.X, pos.Y - (int)depth, pos.Z) || !IsSolid(blAcc, pos.X + (int)craterRadius, pos.Y - 1, pos.Z) || !IsSolid(blAcc, pos.X - (int)craterRadius, pos.Y - 1, pos.Z) || !IsSolid(blAcc, pos.X, pos.Y - 1, pos.Z - (int)craterRadius) || !IsSolid(blAcc, pos.X, pos.Y - 1, pos.Z + (int)craterRadius) ) { return(false); } int y1 = blAcc.GetTerrainMapheightAt(tmpPos.Set(pos.X - 5, pos.Y, pos.Z)); int y2 = blAcc.GetTerrainMapheightAt(tmpPos.Set(pos.X + 5, pos.Y, pos.Z)); int y3 = blAcc.GetTerrainMapheightAt(tmpPos.Set(pos.X - 0, pos.Y, pos.Z + 5)); int y4 = blAcc.GetTerrainMapheightAt(tmpPos.Set(pos.X - 0, pos.Y, pos.Z - 5)); if ((GameMath.Max(y1, y2, y3, y4) - GameMath.Min(y1, y2, y3, y4)) > 4) { return(false); } tmpPos = tmpPos.Set(pos.X, pos.Y - (int)depth - 2, pos.Z); while (cnt-- > 0) { tmpPos.X += worldgenRand.NextInt(3) == 0 ? (worldgenRand.NextInt(3) - 1) : 0; tmpPos.Y += worldgenRand.NextInt(8) == 0 ? (worldgenRand.NextInt(3) - 1) : 0; tmpPos.Z += worldgenRand.NextInt(3) == 0 ? (worldgenRand.NextInt(3) - 1) : 0; blAcc.SetBlock(this.BlockId, tmpPos); } int sueviteBlockId = api.World.GetBlock(new AssetLocation("rock-suevite")).BlockId; int fragmentBlockId = api.World.GetBlock(new AssetLocation("loosestones-meteorite-iron-free")).BlockId; int looseSueviteBlockId = api.World.GetBlock(new AssetLocation("loosestones-suevite-free")).BlockId; float impactRockRadius = craterRadius * 1.2f; int range = (int)Math.Ceiling(impactRockRadius); int chunksize = api.World.BlockAccessor.ChunkSize; Vec2i vecTmp = new Vec2i(); // 1. Generate a basin of suevite and lower terrain for (int dx = -range; dx <= range; dx++) { for (int dz = -range; dz <= range; dz++) { float distImpactRockEdge = (dx * dx + dz * dz) / (impactRockRadius * impactRockRadius); if (distImpactRockEdge > 1) { continue; } tmpPos.X = pos.X + dx; tmpPos.Z = pos.Z + dz; int surfaceY = blAcc.GetTerrainMapheightAt(tmpPos); tmpPos.Y = surfaceY - (int)depth; vecTmp.X = tmpPos.X / chunksize; vecTmp.Y = tmpPos.Z / chunksize; IMapChunk mapchunk = blAcc.GetMapChunk(vecTmp); float q = 3 * Math.Max(0, 2 * (1 - distImpactRockEdge) - 0.2f); tmpPos.Y -= (int)q + 1; while (q > 0) { if (q < 1 && worldgenRand.NextDouble() > q) { break; } Block block = blAcc.GetBlock(tmpPos); if (block != this && block.BlockMaterial == EnumBlockMaterial.Stone) { blAcc.SetBlock(sueviteBlockId, tmpPos); } q--; tmpPos.Y++; } float distToCraterEdge = (dx * dx + dz * dz) / (craterRadius * craterRadius) + (float)worldgenRand.NextDouble() * 0.1f; if (distToCraterEdge > 1) { continue; } q = depth * (1 - distToCraterEdge); tmpPos.Y = surfaceY; Block surfaceblock = blAcc.GetBlock(tmpPos); Block abovesurfaceblock = blAcc.GetBlock(tmpPos.X, tmpPos.Y + 1, tmpPos.Z); for (int i = -1; i <= (int)q; i++) { tmpPos.Y = surfaceY - i; int id = i == (int)q ? surfaceblock.BlockId : 0; Block bblock = blAcc.GetBlock(tmpPos); if (!bblock.IsLiquid()) { blAcc.SetBlock(id, tmpPos); } } mapchunk.WorldGenTerrainHeightMap[(tmpPos.Z % chunksize) * chunksize + (tmpPos.X % chunksize)] -= (ushort)q; tmpPos.Y = blAcc.GetTerrainMapheightAt(tmpPos) + 1; blAcc.SetBlock(abovesurfaceblock.BlockId, tmpPos); } } int quantityFragments = 0; if (worldgenRand.NextInt(10) == 0) { quantityFragments = worldgenRand.NextInt(10); } else if (worldgenRand.NextInt(5) == 0) { quantityFragments = worldgenRand.NextInt(5); } while (quantityFragments-- > 0) { tmpPos.Set( pos.X + (worldgenRand.NextInt(11) + worldgenRand.NextInt(11)) / 2 - 5, 0, pos.Z + (worldgenRand.NextInt(11) + worldgenRand.NextInt(11)) / 2 - 5 ); tmpPos.Y = blAcc.GetTerrainMapheightAt(tmpPos) + 1; if (!blAcc.GetBlock(tmpPos.X, tmpPos.Y - 1, tmpPos.Z).SideSolid[BlockFacing.UP.Index]) { continue; } if (worldgenRand.NextDouble() < 0.3) { blAcc.SetBlock(fragmentBlockId, tmpPos); } else { blAcc.SetBlock(looseSueviteBlockId, tmpPos); } } //blAcc.SetBlock(61, pos.AddCopy(0, 20, 0)); return(true); }
void genPatches(int chunkX, int chunkZ, bool postPass) { int dx, dz, x, z; Block block; for (int i = 0; i < bpc.Patches.Length; i++) { BlockPatch blockPatch = bpc.Patches[i]; if (blockPatch.PostPass != postPass) { continue; } float chance = blockPatch.Chance * bpc.ChanceMultiplier.nextFloat(); while (chance-- > rnd.NextDouble()) { dx = rnd.NextInt(chunksize); dz = rnd.NextInt(chunksize); x = dx + chunkX * chunksize; z = dz + chunkZ * chunksize; int y = heightmap[dz * chunksize + dx]; if (y <= 0 || y >= worldheight - 15) { continue; } tmpPos.Set(x, y, z); block = blockAccessor.GetBlock(tmpPos); // Place according to forest value float forestRel = GameMath.BiLerp(forestUpLeft, forestUpRight, forestBotLeft, forestBotRight, (float)dx / chunksize, (float)dz / chunksize) / 255f; forestRel = GameMath.Clamp(forestRel + forestMod, 0, 1); int climate = GameMath.BiLerpRgbColor((float)dx / chunksize, (float)dz / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight); if (bpc.IsPatchSuitableAt(blockPatch, block, api.WorldManager, climate, y, forestRel)) { int firstBlockId = 0; bool found = true; if (blockPatch.BlocksByRockType != null) { found = false; int dy = 1; while (dy < 5 && y - dy > 0) { string lastCodePart = blockAccessor.GetBlock(x, y - dy, z).LastCodePart(); if (RockBlockIdsByType.TryGetValue(lastCodePart, out firstBlockId)) { found = true; break; } dy++; } } if (found) { blockPatch.Generate(blockAccessor, rnd, x, y, z, firstBlockId); } } } } }
private void OnChunkColumnGen(IServerChunk[] chunks, int chunkX, int chunkZ, ITreeAttribute chunkGenParams = null) { rand.InitPositionSeed(chunkX, chunkZ); ushort[] heightmap = chunks[0].MapChunk.RainHeightMap; IntDataMap2D climateMap = chunks[0].MapChunk.MapRegion.ClimateMap; int regionChunkSize = api.WorldManager.RegionSize / chunksize; float fac = (float)climateMap.InnerSize / regionChunkSize; int rlX = chunkX % regionChunkSize; int rlZ = chunkZ % regionChunkSize; climateUpLeft = climateMap.GetUnpaddedInt((int)(rlX * fac), (int)(rlZ * fac)); climateUpRight = climateMap.GetUnpaddedInt((int)(rlX * fac + fac), (int)(rlZ * fac)); climateBotLeft = climateMap.GetUnpaddedInt((int)(rlX * fac), (int)(rlZ * fac + fac)); climateBotRight = climateMap.GetUnpaddedInt((int)(rlX * fac + fac), (int)(rlZ * fac + fac)); int climateMid = GameMath.BiLerpRgbColor(0.5f, 0.5f, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight); // 16-23 bits = Red = temperature // 8-15 bits = Green = rain // 0-7 bits = Blue = humidity int rain = (climateMid >> 8) & 0xff; int humidity = climateMid & 0xff; int temp = (climateMid >> 16) & 0xff; // Lake density at chunk center float pondDensity = 4 * (rain + humidity) / 255f; float sealeveltemp = TerraGenConfig.GetScaledAdjustedTemperatureFloat(temp, 0); // Less lakes where its below -5 degrees pondDensity -= Math.Max(0, 5 - sealeveltemp); float maxTries = pondDensity * 10; int dx, dz; int baseX = chunkX * chunksize; int baseZ = chunkZ * chunksize; while (maxTries-- > 0) { if (maxTries < 1 && rand.NextDouble() > maxTries) { break; } dx = rand.NextInt(chunksize); dz = rand.NextInt(chunksize); pondYPos = heightmap[dz * chunksize + dx] + 1; if (pondYPos <= 0 || pondYPos >= mapheight - 1) { return; } TryPlacePondAt(dx, pondYPos, dz, chunkX, chunkZ); } maxTries = 600; while (maxTries-- > 0) { if (maxTries < 1 && rand.NextDouble() > maxTries) { break; } dx = rand.NextInt(chunksize); dz = rand.NextInt(chunksize); pondYPos = (int)(rand.NextDouble() * heightmap[dz * chunksize + dx]); if (pondYPos <= 0 || pondYPos >= mapheight - 1) { return; } int chunkY = pondYPos / chunksize; int dy = pondYPos % chunksize; int blockID = chunks[chunkY].Blocks[(dy * chunksize + dz) * chunksize + dx]; while (blockID == 0 && pondYPos > 20) { pondYPos--; chunkY = pondYPos / chunksize; dy = pondYPos % chunksize; blockID = chunks[chunkY].Blocks[(dy * chunksize + dz) * chunksize + dx]; if (blockID != 0) { //blockAccessor.SetBlock(63, new BlockPos(dx + baseX, pondYPos, dz + baseZ)); TryPlacePondAt(dx, pondYPos, dz, chunkX, chunkZ); } } } }
public bool TryGenerate(IBlockAccessor blockAccessor, IWorldAccessor worldForCollectibleResolve, BlockPos pos, int climateUpLeft, int climateUpRight, int climateBotLeft, int climateBotRight, DidGenerate didGenerateStructure) { this.climateUpLeft = climateUpLeft; this.climateUpRight = climateUpRight; this.climateBotLeft = climateBotLeft; this.climateBotRight = climateBotRight; float cnt = QuantityStructures.nextFloat(); int minQuantity = (int)cnt; BlockPos schemPos = pos.Copy(); Cuboidi location = new Cuboidi(); rand.InitPositionSeed(pos.X, pos.Z); List <GeneratableStructure> generatables = new List <GeneratableStructure>(); while (cnt-- > 0) { if (cnt < 1 && rand.NextDouble() > cnt) { break; } int tries = 30; while (tries-- > 0) { schemPos.Set(pos); schemPos.Add(rand.NextInt(50) - 25, 0, rand.NextInt(50) - 25); schemPos.Y = blockAccessor.GetTerrainMapheightAt(schemPos); double rndVal = rand.NextDouble() * totalWeight; int i = 0; VillageSchematic schem = null; while (rndVal > 0) { schem = Schematics[i++]; rndVal -= schem.Weight; } BlockSchematicStructure struc = GetGeneratableStructure(schem, blockAccessor, worldForCollectibleResolve, schemPos); if (struc != null) { location.Set(schemPos.X, schemPos.Y, schemPos.Z, schemPos.X + struc.SizeX, schemPos.Y + struc.SizeY, schemPos.Z + struc.SizeZ); bool intersect = false; for (int k = 0; k < generatables.Count; k++) { if (location.IntersectsOrTouches(generatables[k].location)) { intersect = true; break; } } if (!intersect) { generatables.Add(new GeneratableStructure() { struc = struc, pos = schemPos.Copy(), location = location.Clone() }); } break; } } } if (generatables.Count >= minQuantity) { foreach (var val in generatables) { val.struc.PlaceRespectingBlockLayers(blockAccessor, worldForCollectibleResolve, val.pos, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight, replaceblockids); didGenerateStructure(val.location, val.struc); } } return(true); }
private void DoGenStructures(IMapRegion region, int chunkX, int chunkZ, bool postPass, ITreeAttribute chunkGenParams = null) { BlockPos pos = new BlockPos(); ITreeAttribute chanceModTree = null; ITreeAttribute maxQuantityModTree = null; if (chunkGenParams?["structureChanceModifier"] != null) { chanceModTree = chunkGenParams["structureChanceModifier"] as TreeAttribute; } if (chunkGenParams?["structureMaxCount"] != null) { maxQuantityModTree = chunkGenParams["structureMaxCount"] as TreeAttribute; } strucRand.InitPositionSeed(chunkX, chunkZ); scfg.Structures.Shuffle(strucRand); for (int i = 0; i < scfg.Structures.Length; i++) { WorldGenStructure struc = scfg.Structures[i]; if (struc.PostPass != postPass) { continue; } float chance = struc.Chance * scfg.ChanceMultiplier; int toGenerate = 9999; if (chanceModTree != null) { chance *= chanceModTree.GetFloat(struc.Code, 0); } if (maxQuantityModTree != null) { toGenerate = maxQuantityModTree.GetInt(struc.Code, 9999); } while (chance-- > strucRand.NextDouble() && toGenerate > 0) { int dx = strucRand.NextInt(chunksize); int dz = strucRand.NextInt(chunksize); int ySurface = heightmap[dz * chunksize + dx]; if (ySurface <= 0 || ySurface >= worldheight - 15) { continue; } if (struc.Placement == EnumStructurePlacement.Underground) { if (struc.Depth != null) { pos.Set(chunkX * chunksize + dx, ySurface - (int)struc.Depth.nextFloat(1, strucRand), chunkZ * chunksize + dz); } else { pos.Set(chunkX * chunksize + dx, 8 + strucRand.NextInt(ySurface - 8 - 5), chunkZ * chunksize + dz); } } else { pos.Set(chunkX * chunksize + dx, ySurface, chunkZ * chunksize + dz); } if (struc.TryGenerate(worldgenBlockAccessor, api.World, pos, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight)) { Cuboidi loc = struc.LastPlacedSchematicLocation; string code = struc.Code + (struc.LastPlacedSchematic == null ? "" : "/" + struc.LastPlacedSchematic.FromFileName); region.GeneratedStructures.Add(new GeneratedStructure() { Code = code, Group = struc.Group, Location = loc.Clone() }); region.DirtyForSaving = true; if (struc.BuildProtected) { api.World.Claims.Add(new LandClaim() { Areas = new List <Cuboidi>() { loc.Clone() }, Description = struc.BuildProtectionDesc, ProtectionLevel = 10, LastKnownOwnerName = struc.BuildProtectionName, AllowUse = true }); } toGenerate--; } } } }
public bool Suitable(float temp, float rain, float yRel, LCGRandom rnd) { float transDistance = MinTemp - temp + transSize; return(rain >= MinRain && rain <= MaxRain && MinY <= yRel && MaxY >= yRel && transDistance <= rnd.NextDouble() * transSize); }
private void GenPatches(IBlockAccessor blockAccessor, BlockPos pos, float forestNess, EnumTreeType treetype, LCGRandom rnd) { var bpc = genPatchesSystem.bpc; int radius = 5; int worldheight = blockAccessor.MapSizeY; int cnt = underTreePatches?.Count ?? 0; for (int i = 0; i < cnt; i++) { BlockPatch bPatch = underTreePatches[i]; if (bPatch.TreeType != EnumTreeType.Any && bPatch.TreeType != treetype) { continue; } float chance = 0.003f * forestNess * bPatch.Chance * bpc.ChanceMultiplier.nextFloat(); //if (bPatch.blockCodes[0].Path.Contains("mushroom")) chance *= 20; - for debugging while (chance-- > rnd.NextDouble()) { int dx = rnd.NextInt(2 * radius) - radius; int dz = rnd.NextInt(2 * radius) - radius; tmpPos.Set(pos.X + dx, 0, pos.Z + dz); int y = blockAccessor.GetTerrainMapheightAt(tmpPos); if (y <= 0 || y >= worldheight - 8) { continue; } tmpPos.Y = y; var climate = blockAccessor.GetClimateAt(tmpPos, EnumGetClimateMode.WorldGenValues); if (climate == null) { continue; } if (bpc.IsPatchSuitableUnderTree(bPatch, worldheight, climate, y)) { int regionX = pos.X / blockAccessor.RegionSize; int regionZ = pos.Z / blockAccessor.RegionSize; if (bPatch.MapCode != null && rnd.NextInt(255) > genPatchesSystem.GetPatchDensity(bPatch.MapCode, tmpPos.X, tmpPos.Z, blockAccessor.GetMapRegion(regionX, regionZ))) { continue; } int firstBlockId = 0; bool found = true; if (bPatch.BlocksByRockType != null) { found = false; int dy = 1; while (dy < 5 && y - dy > 0) { string lastCodePart = blockAccessor.GetBlock(tmpPos.X, y - dy, tmpPos.Z).LastCodePart(); if (genPatchesSystem.RockBlockIdsByType.TryGetValue(lastCodePart, out firstBlockId)) { found = true; break; } dy++; } } if (found) { bPatch.Generate(blockAccessor, rnd, tmpPos.X, tmpPos.Y, tmpPos.Z, firstBlockId); } } } } cnt = onTreePatches?.Count ?? 0; for (int i = 0; i < cnt; i++) { BlockPatch blockPatch = onTreePatches[i]; float chance = 3 * forestNess * blockPatch.Chance * bpc.ChanceMultiplier.nextFloat(); while (chance-- > rnd.NextDouble()) { int dx = 1 - rnd.NextInt(2) * 2; int dy = rnd.NextInt(5); int dz = 1 - rnd.NextInt(2) * 2; tmpPos.Set(pos.X + dx, pos.Y + dy, pos.Z + dz); var block = api.GetBlock(tmpPos); if (block.Id != 0) { continue; } BlockFacing facing = null; for (int j = 0; j < 4; j++) { var f = BlockFacing.HORIZONTALS[j]; var nblock = api.GetBlock(tmpPos.X + f.Normali.X, tmpPos.Y, tmpPos.Z + f.Normali.Z); if (nblock is BlockLog && nblock.Variant["type"] != "resin") { facing = f; break; } } if (facing == null) { break; } var climate = blockAccessor.GetClimateAt(tmpPos, EnumGetClimateMode.WorldGenValues); if (climate == null) { continue; } if (bpc.IsPatchSuitableUnderTree(blockPatch, worldheight, climate, tmpPos.Y)) { int regionX = pos.X / blockAccessor.RegionSize; int regionZ = pos.Z / blockAccessor.RegionSize; if (blockPatch.MapCode != null && rnd.NextInt(255) > genPatchesSystem.GetPatchDensity(blockPatch.MapCode, tmpPos.X, tmpPos.Z, blockAccessor.GetMapRegion(regionX, regionZ))) { continue; } int index = rnd.NextInt(blockPatch.Blocks.Length); blockPatch.Blocks[index].TryPlaceBlockForWorldGen(blockAccessor, tmpPos, facing, rnd); } } } }