Beispiel #1
0
        public void AddCactus(Level Lvl, ushort x, ushort y, ushort z, Random Rand, bool blockChange = false, bool overwrite = true)
        {
            byte height = (byte)Rand.Next(3, 6);
            ushort yy;

            for (yy = 0; yy <= height; yy++) {
                if (overwrite || Lvl.GetTile(z, (ushort)(y + yy), z) == Block.air)
                    if (blockChange) Lvl.Blockchange(x, (ushort)(y + yy), z, Block.green);
                    else Lvl.skipChange(x, (ushort)(y + yy), z, Block.green);
            }

            int inX = 0, inZ = 0;

            switch (Rand.Next(1, 3))
            {
                case 1: inX = -1; break;
                case 2:
                default: inZ = -1; break;
            }

            for (yy = height; yy <= Rand.Next(height + 2, height + 5); yy++)
            {
                if (overwrite || Lvl.GetTile((ushort)(x + inX), (ushort)(y + yy), (ushort)(z + inZ)) == Block.air)
                    if (blockChange) Lvl.Blockchange((ushort)(x + inX), (ushort)(y + yy), (ushort)(z + inZ), Block.green);
                    else Lvl.skipChange((ushort)(x + inX), (ushort)(y + yy), (ushort)(z + inZ), Block.green);
            }
            for (yy = height; yy <= Rand.Next(height + 2, height + 5); yy++)
            {
                if (overwrite || Lvl.GetTile((ushort)(x + inX), (ushort)(y + yy), (ushort)(z + inZ)) == Block.air)
                    if (blockChange) Lvl.Blockchange((ushort)(x - inX), (ushort)(y + yy), (ushort)(z - inZ), Block.green);
                    else Lvl.skipChange((ushort)(x - inX), (ushort)(y + yy), (ushort)(z - inZ), Block.green);
            }
        }
        public PlayerBot(string n, Level l, ushort x, ushort y, ushort z, byte rotx, byte roty)
        {
            name = n;
            color = "&1";
            id = FreeId();

            DisplayName = n;
            SkinName = n;

            level = l;
            pos = new ushort[3] { x, y, z }; rot = new byte[2] { rotx, roty };
            GlobalSpawn();

            foreach (Player p in Player.players)
            {
                if (p.level == level)
                {
                    Player.SendMessage(p, color + name + Server.DefaultColor + ", the bot, has been added.");
                }
            }

            botTimer.Elapsed += delegate
            {
                int currentNum, foundNum = (32 * 75);
            //    Random rand = new Random();

                x = (ushort)Math.Round((decimal)pos[0] / (decimal)32);
                y = (ushort)((pos[1] - 33) / 32);
                z = (ushort)Math.Round((decimal)pos[2] / (decimal)32);

                if (kill)
                {
                    foreach (Player p in Player.players)
                    {
                        if ((ushort)(p.pos[0] / 32) == x)
                        {
                            if (Math.Abs((ushort)(p.pos[1] / 32) - y) < 2)
                            {
                                if ((ushort)(p.pos[2] / 32) == z)
                                {
                                    p.HandleDeath(Block.Zero);
                                }
                            }
                        }
                    }
                }

                if (Waypoints.Count < 1)
                {
                    if (hunt)
                        Player.players.ForEach(delegate(Player p)
                        {
                            if (p.level == level && !p.invincible)
                            {
                                currentNum = Math.Abs(p.pos[0] - pos[0]) + Math.Abs(p.pos[1] - pos[1]) + Math.Abs(p.pos[2] - pos[2]);
                                if (currentNum < foundNum)
                                {
                                    foundNum = currentNum;
                                    foundPos = p.pos;
                                    foundRot = p.rot;
                                    movement = true;
                                    rot[1] = (byte)(Block.maxblocks - foundRot[1]);
                                    if (foundRot[0] < 128) rot[0] = (byte)(foundRot[0] + 128);
                                    else rot[0] = (byte)(foundRot[0] - 128);
                                }
                            }
                        });
                }
                else
                {
                    bool skip = false;
                    movement = false;

                retry: switch (Waypoints[currentPoint].type)
                    {
                        case "walk":
                            foundPos[0] = Waypoints[currentPoint].x;
                            foundPos[1] = Waypoints[currentPoint].y;
                            foundPos[2] = Waypoints[currentPoint].z;
                            movement = true;

                            if ((ushort)(pos[0] / 32) == (ushort)(Waypoints[currentPoint].x / 32))
                            {
                                if ((ushort)(pos[2] / 32) == (ushort)(Waypoints[currentPoint].z / 32))
                                {
                                    rot[0] = Waypoints[currentPoint].rotx;
                                    rot[1] = Waypoints[currentPoint].roty;
                                    currentPoint++;
                                    movement = false;

                                    if (currentPoint == Waypoints.Count) currentPoint = 0;
                                    if (!skip) { skip = true; goto retry; }
                                }
                            }
                            break;
                        case "teleport":
                            pos[0] = Waypoints[currentPoint].x;
                            pos[1] = Waypoints[currentPoint].y;
                            pos[2] = Waypoints[currentPoint].z;
                            rot[0] = Waypoints[currentPoint].rotx;
                            rot[1] = Waypoints[currentPoint].roty;
                            currentPoint++;
                            if (currentPoint == Waypoints.Count) currentPoint = 0;
                            return;
                        case "wait":
                            if (countdown != 0)
                            {
                                countdown--;
                                if (countdown == 0)
                                {
                                    currentPoint++;
                                    if (currentPoint == Waypoints.Count) currentPoint = 0;
                                    if (!skip) { skip = true; goto retry; }
                                }
                            }
                            else
                            {
                                countdown = Waypoints[currentPoint].seconds;
                            }
                            return;
                        case "nod":
                            if (countdown != 0)
                            {
                                countdown--;

                                if (nodUp)
                                {
                                    if (rot[1] > 32 && rot[1] < 128) nodUp = !nodUp;
                                    else
                                    {
                                        if (rot[1] + (byte)Waypoints[currentPoint].rotspeed > Block.maxblocks) rot[1] = 0;
                                        else rot[1] += (byte)Waypoints[currentPoint].rotspeed;
                                    }
                                }
                                else
                                {
                                    if (rot[1] > 128 && rot[1] < 224) nodUp = !nodUp;
                                    else
                                    {
                                        if (rot[1] - (byte)Waypoints[currentPoint].rotspeed < 0) rot[1] = 255;
                                        else rot[1] -= (byte)Waypoints[currentPoint].rotspeed;
                                    }
                                }

                                if (countdown == 0)
                                {
                                    currentPoint++;
                                    if (currentPoint == Waypoints.Count) currentPoint = 0;
                                    if (!skip) { skip = true; goto retry; }
                                }
                            }
                            else
                            {
                                countdown = Waypoints[currentPoint].seconds;
                            }
                            return;
                        case "spin":
                            if (countdown != 0)
                            {
                                countdown--;

                                if (rot[0] + (byte)Waypoints[currentPoint].rotspeed > Block.maxblocks) rot[0] = 0;
                                else if (rot[0] + (byte)Waypoints[currentPoint].rotspeed < 0) rot[0] = 255;
                                else rot[0] += (byte)Waypoints[currentPoint].rotspeed;

                                if (countdown == 0)
                                {
                                    currentPoint++;
                                    if (currentPoint == Waypoints.Count) currentPoint = 0;
                                    if (!skip) { skip = true; goto retry; }
                                }
                            }
                            else
                            {
                                countdown = Waypoints[currentPoint].seconds;
                            }
                            return;
                        case "speed":
                            movementSpeed = (int)Math.Round((decimal)((decimal)24 / (decimal)100 * (decimal)Waypoints[currentPoint].seconds));
                            if (movementSpeed == 0) movementSpeed = 1;

                            currentPoint++;
                            if (currentPoint == Waypoints.Count) currentPoint = 0;
                            if (!skip) { skip = true; goto retry; }
                            return;
                        case "reset":
                            currentPoint = 0;
                            return;
                        case "remove":
                            removeBot();
                            return;
                        case "linkscript":
                            if (File.Exists("bots/" + Waypoints[currentPoint].newscript))
                            {
                                Command.all.Find("botset").Use(null, this.name + " " + Waypoints[currentPoint].newscript);
                                return;
                            }

                            currentPoint++;
                            if (currentPoint == Waypoints.Count) currentPoint = 0;
                            if (!skip) { skip = true; goto retry; }
                            return;
                        case "jump":
                            jumpTimer.Elapsed += delegate
                            {
                                currentjump++;
                                switch (currentjump)
                                {
                                    case 1:
                                    case 2: pos[1] += 24; break;
                                    case 3: break;
                                    case 4: pos[1] -= 24; break;
                                    case 5: pos[1] -= 24; jumping = false; currentjump = 0; jumpTimer.Stop(); break;
                                }
                            };
                            jumpTimer.Start();

                            currentPoint++;
                            if (currentPoint == Waypoints.Count) currentPoint = 0;
                            if (!skip) { skip = true; goto retry; }
                            break;
                    }

                    if (currentPoint == Waypoints.Count) currentPoint = 0;
                }

                if (!movement)
                {
                    if (rot[0] < 245) rot[0] += 8;
                    else rot[0] = 0;

                    if (rot[1] > 32 && rot[1] < 64) rot[1] = 224;
                    else if (rot[1] > 250) rot[1] = 0;
                    else rot[1] += 4;
                }
            };

            botTimer.Start();

            moveTimer.Elapsed += delegate
            {
                moveTimer.Interval = Server.updateTimer.Interval / movementSpeed;
                if (!movement) return;
                int newNum;// Random rand = new Random();

                if ((pos[1] - 19) % 32 != 0 && !jumping)
                {
                    pos[1] = (ushort)((pos[1] + 19) - (pos[1] % 32));
                }

                x = (ushort)Math.Round((decimal)(pos[0] - 16) / (decimal)32);
                y = (ushort)((pos[1] - 64) / 32);
                z = (ushort)Math.Round((decimal)(pos[2] - 16) / (decimal)32);

                ushort b = Block.Convert(level.GetTile(x, y, z));
                ushort b1, b2, b3;//, b4;

                if (Block.Walkthrough(b) && !jumping)
                {
                    pos[1] = (ushort)(pos[1] - 32);
                }

                y = (ushort)((pos[1] - 64) / 32);   //Block below feet

                newNum = level.PosToInt((ushort)(x + Math.Sign(foundPos[0] - pos[0])), y, (ushort)(z + Math.Sign(foundPos[2] - pos[2])));
                b = Block.Convert(level.GetTile(newNum));
                b1 = Block.Convert(level.GetTile(level.IntOffset(newNum, 0, 1, 0)));
                b2 = Block.Convert(level.GetTile(level.IntOffset(newNum, 0, 2, 0)));
                b3 = Block.Convert(level.GetTile(level.IntOffset(newNum, 0, 3, 0)));

                if (Block.Walkthrough(b2) && Block.Walkthrough(b3) && !Block.Walkthrough(b1))
                {     //Get ready to go up step
                    pos[0] += (ushort)Math.Sign(foundPos[0] - pos[0]);
                    pos[1] += (ushort)32;
                    pos[2] += (ushort)Math.Sign(foundPos[2] - pos[2]);
                }
                else if (Block.Walkthrough(b1) && Block.Walkthrough(b2))
                {                        //Stay on current level
                    pos[0] += (ushort)Math.Sign(foundPos[0] - pos[0]);
                    pos[2] += (ushort)Math.Sign(foundPos[2] - pos[2]);
                }
                else if (Block.Walkthrough(b) && Block.Walkthrough(b1))
                {                         //Drop a level
                    pos[0] += (ushort)Math.Sign(foundPos[0] - pos[0]);
                    pos[1] -= (ushort)32;
                    pos[2] += (ushort)Math.Sign(foundPos[2] - pos[2]);
                }

                x = (ushort)Math.Round((decimal)(pos[0] - 16) / (decimal)32);
                y = (ushort)((pos[1] - 64) / 32);
                z = (ushort)Math.Round((decimal)(pos[2] - 16) / (decimal)32);

                b1 = Block.Convert(level.GetTile(x, (ushort)(y + 1), z));
                b2 = Block.Convert(level.GetTile(x, (ushort)(y + 2), z));
                b3 = Block.Convert(level.GetTile(x, y, z));

                /*
                if ((ushort)(foundPos[1] / 32) > y) {
                    if (b1 == Block.water || b1 == Block.waterstill || b1 == Block.lava || b1 == Block.lavastill) {
                        if (Block.Walkthrough(b2)) {
                            pos[1] = (ushort)(pos[1] + (Math.Sign(foundPos[1] - pos[1])));
                        }
                    } else if (b2 == Block.water || b2 == Block.waterstill || b2 == Block.lava || b2 == Block.lavastill) {
                        pos[1] = (ushort)(pos[1] + (Math.Sign(foundPos[1] - pos[1])));
                    }
                } else if ((ushort)(foundPos[1] / 32) < y) {
                    if (b3 == Block.water || b3 == Block.waterstill || b3 == Block.lava || b3 == Block.lavastill) {
                        pos[1] = (ushort)(pos[1] + (Math.Sign(foundPos[1] - pos[1])));
                    }
                }*/
            };
            moveTimer.Start();
        }
Beispiel #3
0
 public void SendToSpawn(Level mainlevel, Auto_CTF game, Player p1)
 {
     Random rand = new Random();
     if (spawnx == 0 && spawny == 0 && spawnz == 0)
     {
         ushort xx = (ushort)(rand.Next(0, mainlevel.width));
         ushort yy = (ushort)(rand.Next(0, mainlevel.depth));
         ushort zz = (ushort)(rand.Next(0, mainlevel.height));
         while (mainlevel.GetTile(xx, yy, zz) != Block.air && game.OnSide((ushort)(zz * 32), this))
         {
             xx = (ushort)(rand.Next(0, mainlevel.width));
             yy = (ushort)(rand.Next(0, mainlevel.depth));
             zz = (ushort)(rand.Next(0, mainlevel.height));
         }
         unchecked { p1.SendPos((byte)-1, (ushort)(xx * 32), (ushort)(yy * 32), (ushort)(zz * 32), p1.rot[0], p1.rot[1]); }
     }
     else
         unchecked { p1.SendPos((byte)-1, spawnx, spawny, spawnz, p1.rot[0], p1.rot[1]); }
 }
Beispiel #4
0
 //return true if tree is near
 private bool TreeCheck(Level Lvl, ushort x, ushort z, ushort y, short dist)
 {
     byte foundTile;
     for (short xx = (short)-dist; xx <= +dist; ++xx)
     {
         for (short yy = (short)-dist; yy <= +dist; ++yy)
         {
             for (short zz = (short)-dist; zz <= +dist; ++zz)
             {
                 foundTile = Lvl.GetTile((ushort)(x + xx), (ushort)(z + zz), (ushort)(y + yy));
                 if (foundTile == Block.trunk || foundTile == Block.green)
                 {
                     return true;
                 }
             }
         }
     }
     return false;
 }
Beispiel #5
0
        public bool GenerateMap(Level Lvl, string type, int seed = 0, bool useSeed = false)
        {
            DateTime startTime = DateTime.Now;

            Server.s.Log("Attempting map gen");
            if (Inuse) { Server.s.Log("Generator in use"); return false; }
            Random rand = useSeed ? new System.Random(seed) : new System.Random();
            try
            {
                Inuse = true;
                terrain = new float[Lvl.width * Lvl.height];
                overlay = new float[Lvl.width * Lvl.height];

                if (!type.Equals("ocean"))
                { overlay2 = new float[Lvl.width * Lvl.height]; }

                //float dispAux, pd;
                ushort WaterLevel = (ushort)(Lvl.depth / 2 + 2);

                if (type.Equals("ocean"))
                {
                    WaterLevel = (ushort)(Lvl.depth * 0.85f);
                }

                //Generate the level
                GenerateFault(terrain, Lvl, type, rand);

                //APPLY FILTER to terrain
                FilterAverage(Lvl);

                //CREATE OVERLAY
                //GenerateFault(overlay, Lvl, "overlay", rand);
                Server.s.Log("Creating overlay");
                GeneratePerlinNoise(overlay, Lvl, "", rand);

                if (!type.Equals("ocean") && type != "desert")
                {
                    Server.s.Log("Planning trees");
                    GeneratePerlinNoise(overlay2, Lvl, "", rand);
                }

                Server.s.Log("Converting height map");
                Server.s.Log("And applying overlays");
                float RangeLow = 0.2f;
                float RangeHigh = 0.8f;
                float TreeDens = 0.35f;
                short TreeDist = 3;
                //changes the terrain range based on type, also tree threshold
                switch (type)
                {
                    case "island":
                        RangeLow = 0.4f;
                        RangeHigh = 0.75f;
                        break;
                    case "forest":
                        RangeLow = 0.45f;
                        RangeHigh = 0.8f;
                        TreeDens = 0.7f;
                        TreeDist = 2;
                        break;
                    case "mountains":
                        RangeLow = 0.3f;
                        RangeHigh = 0.9f;
                        TreeDist = 4;
                        break;
                    case "ocean":
                        RangeLow = 0.1f;
                        RangeHigh = 0.6f;
                        break;
                    case "desert":
                        RangeLow = 0.5f;
                        RangeHigh = 0.85f;
                        WaterLevel = 0;
                        TreeDist = 24;
                        break;
                    default:
                        break;
                }

                //loops though evey X/Z coordinate
                for (int bb = 0; bb < terrain.Length; bb++)
                {
                    ushort x = (ushort)(bb % Lvl.width);
                    ushort y = (ushort)(bb / Lvl.width);
                    ushort z;
                    if (type.Equals("island"))
                    {
                        z = Evaluate(Lvl, Range(terrain[bb], RangeLow - NegateEdge(x, y, Lvl), RangeHigh - NegateEdge(x, y, Lvl)));
                    }
                    else
                    {
                        z = Evaluate(Lvl, Range(terrain[bb], RangeLow, RangeHigh));
                    }
                    if (z > WaterLevel)
                    {
                        for (ushort zz = 0; z - zz >= 0; zz++)
                        {
                            if (type == "desert")
                            {
                                Lvl.skipChange(x, (ushort)(z - zz), y, Block.sand);
                            }
                            else if (overlay[bb] < 0.72f)    //If not zoned for rocks or gravel
                            {
                                if (type.Equals("island"))      //increase sand height for island
                                {
                                    if (z > WaterLevel + 2)
                                    {
                                        if (zz == 0) { Lvl.skipChange(x, (ushort)(z - zz), y, Block.grass); }      //top layer
                                        else if (zz < 3) { Lvl.skipChange(x, (ushort)(z - zz), y, Block.dirt); }   //next few
                                        else { Lvl.skipChange(x, (ushort)(z - zz), y, Block.rock); }               //ten rock it
                                    }
                                    else
                                    {
                                        Lvl.skipChange(x, (ushort)(z - zz), y, Block.sand);                        //SAAAND extra for islands
                                    }
                                }
                                else if (type == "desert")
                                {
                                    Lvl.skipChange(x, (ushort)(z - zz), y, Block.sand);
                                }
                                else
                                {
                                    if (zz == 0) { Lvl.skipChange(x, (ushort)(z - zz), y, Block.grass); }
                                    else if (zz < 3) { Lvl.skipChange(x, (ushort)(z - zz), y, Block.dirt); }
                                    else { Lvl.skipChange(x, (ushort)(z - zz), y, Block.rock); }
                                }
                            }
                            else
                            {
                                Lvl.skipChange(x, (ushort)(z - zz), y, Block.rock);    //zoned for above sea level rock floor
                            }
                        }

                        if (overlay[bb] < 0.25f && type != "desert")    //Zoned for flowers
                        {
                            int temprand = rand.Next(12);

                            switch (temprand)
                            {
                                case 10:
                                    Lvl.skipChange(x, (ushort)(z + 1), y, Block.redflower);
                                    break;
                                case 11:
                                    Lvl.skipChange(x, (ushort)(z + 1), y, Block.yellowflower);
                                    break;
                                default:
                                    break;
                            }
                        }

                        if (!type.Equals("ocean"))
                        {
                            if (overlay[bb] < 0.65f && overlay2[bb] < TreeDens)
                            {
                                if (Lvl.GetTile(x, (ushort)(z + 1), y) == Block.air)
                                {
                                    if (Lvl.GetTile(x, z, y) == Block.grass || type == "desert")
                                    {
                                        if (rand.Next(13) == 0)
                                        {
                                            if (!TreeCheck(Lvl, x, z, y, TreeDist))
                                            {
                                                if (type == "desert")
                                                    AddCactus(Lvl, x, (ushort)(z + 1), y, rand);
                                                else
                                                    AddTree(Lvl, x, (ushort)(z + 1), y, rand);
                                            }
                                        }
                                    }
                                }
                            }
                        }

                    }
                    else    //Must be on/under the water line then
                    {
                        for (ushort zz = 0; WaterLevel - zz >= 0; zz++)
                        {
                            if (WaterLevel - zz > z)
                            { Lvl.skipChange(x, (ushort)(WaterLevel - zz), y, Block.water); }    //better fill the water aboce me
                            else if (WaterLevel - zz > z - 3)
                            {
                                if (overlay[bb] < 0.75f)
                                {
                                    Lvl.skipChange(x, (ushort)(WaterLevel - zz), y, Block.sand);   //sand top
                                }
                                else
                                {
                                    Lvl.skipChange(x, (ushort)(WaterLevel - zz), y, Block.gravel);  //zoned for gravel
                                }
                            }
                            else
                            {
                                Lvl.skipChange(x, (ushort)(WaterLevel - zz), y, Block.rock);
                            }
                        }
                    }
                }

                Server.s.Log("Total time was " + (DateTime.Now - startTime).TotalSeconds.ToString() + " seconds.");
            }
            catch (Exception e)
            {
                Server.ErrorLog(e);
                Server.s.Log("Gen Fail");
                Inuse = false;
                return false;
            }

            terrain = new float[0]; //Derp
            overlay = new float[0]; //Derp
            overlay2 = new float[0]; //Derp

            Inuse = false;

            return true;
        }
Beispiel #6
0
        //
        public void AddTree(Level Lvl, ushort x, ushort y, ushort z, Random Rand, bool blockChange = false, bool overwrite = true, Player p = null)
        {
            byte height = (byte)Rand.Next(5, 8);
            short top = (short)(height - Rand.Next(2, 4));
            ushort xxx, yyy, zzz;
            for (ushort yy = 0; yy < top + height - 1; yy++)
            {
                if (overwrite || Lvl.GetTile(x, (ushort)(y + yy), z) == Block.air || (y + yy == y && Lvl.GetTile(x, (ushort)(y + yy), z) == Block.shrub))
                    if (blockChange)
                        if (p == null) Lvl.Blockchange(x, (ushort)(y + yy), z, Block.trunk);
                        else Lvl.Blockchange(p, x, (ushort)(y + yy), z, Block.trunk);
                    else Lvl.skipChange(x, (ushort)(y + yy), z, Block.trunk);
            }

            for (short xx = (short)-top; xx <= top; ++xx)
            {
                for (short yy = (short)-top; yy <= top; ++yy)
                {
                    for (short zz = (short)-top; zz <= top; ++zz)
                    {
                        short Dist = (short)(Math.Sqrt(xx * xx + yy * yy + zz * zz));
                        if (Dist < top + 1)
                        {
                            if (Rand.Next((int)(Dist)) < 2)
                            {
                                try
                                {
                                    xxx = (ushort)(x + xx);
                                    yyy = (ushort)(y + yy + height);
                                    zzz = (ushort)(z + zz);

                                    if ((xxx != x || zzz != z || yy >= top - 1) && (overwrite || Lvl.GetTile(xxx, yyy, zzz) == Block.air))
                                        if (blockChange)
                                            if (p == null) Lvl.Blockchange(xxx, yyy, zzz, Block.leaf);
                                            else Lvl.Blockchange(p, xxx, yyy, zzz, Block.leaf);
                                        else Lvl.skipChange(xxx, yyy, zzz, Block.leaf);
                                }
                                catch { }
                            }
                        }
                    }
                }
            }
        }
Beispiel #7
0
        public void AddNotchTree(Level Lvl, ushort x, ushort y, ushort z, Random Rand, bool blockChange = false, bool overwrite = true, Player p = null)
        {
            byte dist, tile;
            byte height = (byte)Rand.Next(3, 7);
            byte top = (byte)(height - 2);
            short xx, yy, zz;
            ushort xxx, yyy, zzz;
            for (yy = 0; yy <= height; yy++)
            {
                yyy = (ushort)(y + yy);
                tile = Lvl.GetTile(x, yyy, z);
                if (overwrite || tile == Block.air || (yyy == y && tile == Block.shrub))
                    if (blockChange)
                        if (p == null) Lvl.Blockchange(x, yyy, z, Block.trunk);
                        else Lvl.Blockchange(p, x, yyy, z, Block.trunk);
                    else Lvl.skipChange(x, yyy, z, Block.trunk);
            }

            for (yy = top; yy <= height + 1; yy++)
            {
                dist = yy > height - 1 ? (byte)1 : (byte)2;
                for (xx = (short)-dist; xx <= dist; xx++)
                {
                    for (zz = (short)-dist; zz <= dist; zz++)
                    {
                        xxx = (ushort)(x + xx);
                        yyy = (ushort)(y + yy);
                        zzz = (ushort)(z + zz);
                        tile = Lvl.GetTile(xxx, yyy, zzz);
                        //Server.s.Log(String.Format("{0} {1} {2}", xxx, yyy, zzz));

                        if ((xxx == x && zzz == z && yy <= height) || (!overwrite && tile != Block.air))
                            continue;

                        if (Math.Abs(xx) == dist && Math.Abs(zz) == dist)
                        {
                            if (yy > height)
                                continue;

                            if (Rand.Next(2) == 0)
                            {
                                if (blockChange)
                                    if (p == null) Lvl.Blockchange(xxx, yyy, zzz, Block.leaf);
                                    else Lvl.Blockchange(p, xxx, yyy, zzz, Block.leaf);
                                else Lvl.skipChange(xxx, yyy, zzz, Block.leaf);
                            }
                        }
                        else
                        {
                            if (blockChange)
                                if (p == null) Lvl.Blockchange(xxx, yyy, zzz, Block.leaf);
                                else Lvl.Blockchange(p, xxx, yyy, zzz, Block.leaf);
                            else Lvl.skipChange(xxx, yyy, zzz, Block.leaf);
                        }
                    }
                }
            }
        }