예제 #1
0
        public override bool TryPlaceBlockForWorldGen(IBlockAccessor blAcc, BlockPos pos, BlockFacing onBlockFace, Random worldgenRand)
        {
            int   cnt          = 2 + worldgenRand.Next(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.Next(3) == 0 ? (worldgenRand.Next(3) - 1) : 0;
                tmpPos.Y += worldgenRand.Next(8) == 0 ? (worldgenRand.Next(3) - 1) : 0;
                tmpPos.Z += worldgenRand.Next(3) == 0 ? (worldgenRand.Next(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")).BlockId;
            int looseSueviteBlockId = api.World.GetBlock(new AssetLocation("loosestones-suevite")).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;
                        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.Next(10) == 0)
            {
                quantityFragments = worldgenRand.Next(10);
            }
            else if (worldgenRand.Next(5) == 0)
            {
                quantityFragments = worldgenRand.Next(5);
            }

            while (quantityFragments-- > 0)
            {
                tmpPos.Set(
                    pos.X + (worldgenRand.Next(11) + worldgenRand.Next(11)) / 2 - 5,
                    0,
                    pos.Z + (worldgenRand.Next(11) + worldgenRand.Next(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);
        }