예제 #1
0
        /// <summary>
        /// Generates a broken temple pillar. Only places between vitric sand. Automatically scans for crystals, and returns false if a crystal is in the way.
        /// </summary>
        /// <param name="x">Center X position.</param>
        /// <param name="y">Y position. Can be anywhere between a ceiling and floor; will generate appropriately.</param>
        /// <returns>True if a pillar was successfully placed within an area</returns>
        public static bool GenPillar(int x, int y)
        {
            int ceil  = FindTypeUp(x, y, VitricBiome.Y - 20, TileType <VitricSand>(), TileType <VitricSoftSand>());
            int floor = FindType(x, y, VitricBiome.Bottom + 20, TileType <VitricSand>(), TileType <VitricSoftSand>());

            if (ceil == -1 || floor == -1 || ceil >= floor)
            {
                return(false);         //If there's an invalid ceiling or floor, or if the floor is above or on the ceiling, kill
            }
            int height = floor - ceil; //Height of pillar

            if (height < 7 || height > 50)
            {
                return(false);            //If it's too short or too tall
            }
            int wid = genRand.Next(3, 6); //Width of pillar

            int GetHeight(int xPos) => Math.Abs(ceil - FindTypeUp(xPos, y, VitricBiome.Y - 20, TileType <VitricSand>(), TileType <VitricSoftSand>()));
            int GetDepth(int xPos) => Math.Abs(floor - FindType(xPos, y, VitricBiome.Y - 20, TileType <VitricSand>(), TileType <VitricSoftSand>()));

            for (int i = -wid; i < wid + 1; ++i) //Checks for crystals. If there's a crystal, kill this pillar before it gens
            {
                if (Helper.ScanForTypeDown(x + i, y, TileType <VitricLargeCrystal>(), 100) || Helper.ScanForTypeDown(x + i, y, TileType <VitricSmallCrystal>(), 100))
                {
                    return(false); //Crystal found, can't place here
                }
                if (GetHeight(x + i) - 30 > GetHeight(x - wid) || GetHeight(x + i) - 30 > GetHeight(x + wid))
                {
                    return(false);                                                                                          //Large height differencial found, can't place
                }
                if (GetDepth(x + i) + 30 < GetDepth(x - wid) || GetDepth(x + i) + 30 < GetDepth(x + wid))
                {
                    return(false);                                                                                      //Large height differencial found, can't place
                }
            }

            for (int i = -wid; i < wid + 1; ++i)
            {
                //Tile placement
                int depth = genRand.Next(2) + 1;
                if (Math.Abs(i) == wid || Math.Abs(i) == wid - 2)
                {
                    depth = (int)Math.Ceiling(height / 4f) + genRand.Next((int)Math.Ceiling(-height / 6f), (int)Math.Ceiling(height / 6f));
                }
                if (Math.Abs(i) == wid - 1)
                {
                    depth = (int)Math.Ceiling(height / 3f) + genRand.Next((int)Math.Ceiling(-height / 6f), (int)Math.Ceiling(height / 6f));
                }
                int ceilingY = FindTypeUp(x + i, y, VitricBiome.Y - 20, TileType <VitricSand>(), TileType <VitricSoftSand>());
                int floorY   = FindType(x + i, y, VitricBiome.Bottom + 20, TileType <VitricSand>(), TileType <VitricSoftSand>());

                for (int j = 0; j < depth; ++j)
                {
                    KillTile(x + i, ceilingY + j, false, false, true);
                    PlaceTile(x + i, ceilingY + j, TileType <AncientSandstone>(), true, false);
                    KillTile(x + i, floorY - j, false, false, true);
                    PlaceTile(x + i, floorY - j, TileType <AncientSandstone>(), true, false);
                }

                //Wall placement
                depth = (int)Math.Ceiling(height / 2f) + 2;
                if (Math.Abs(i) >= wid)
                {
                    depth = genRand.Next(2) + 1;
                }
                if (Math.Abs(i) == wid - 2)
                {
                    depth = (int)Math.Ceiling(height / 3f) + genRand.Next((int)Math.Ceiling(-height / 6f), (int)Math.Ceiling(height / 4f));
                }
                if (Math.Abs(i) == wid - 1)
                {
                    depth = (int)Math.Ceiling(height / 4f) + genRand.Next((int)Math.Ceiling(-height / 6f), (int)Math.Ceiling(height / 6f));
                }

                for (int j = 0; j < depth; ++j)
                {
                    KillWall(x + i, ceilingY + j, false);
                    PlaceWall(x + i, ceilingY + j, WallType <AncientSandstoneWall>(), true);
                    KillWall(x + i, floorY - j, false);
                    PlaceWall(x + i, floorY - j, WallType <AncientSandstoneWall>(), true);
                }
            }
            RuinedPillarPositions.Add(new Point(x, y));
            return(true);
        }
예제 #2
0
        /// <summary>Generates ruins using premade structures, or using the GenPillar method.</summary>
        /// <param name="validGround"></param>
        private static void GenRuins()
        {
            Point16[] ruinedHouseSizes = new Point16[6] {
                new Point16(8, 7), new Point16(14, 7), new Point16(12, 7), new Point16(10, 6), new Point16(12, 5), new Point16(14, 7)
            };
            int failCount = 0;

            for (int i = 0; i < 6; ++i)
            {
                if (failCount > 120)
                {
                    break;                  //To many fails, stop
                }
                int x = VitricBiome.X + VitricSlopeOffset + genRand.Next(VitricBiome.Width - (VitricSlopeOffset * 2));
                while (x > VitricBiome.X + VitricBiome.Width / 2 - 71 && x < VitricBiome.X + VitricBiome.Width / 2 + 70)
                {
                    x = VitricBiome.X + genRand.Next(VitricBiome.Width);
                }
                int     ty   = genRand.Next(ruinedHouseSizes.Length);
                Point16 size = ruinedHouseSizes[ty];
                int     y    = FindType(x, (VitricBiome.Y + 38) + (genRand.Next((int)(VitricBiome.Height / 3.2f))), -1, ValidGround) + genRand.Next(2);
                if ((x < VitricBiome.X + VitricBiome.Width / 2 - 71 || x > VitricBiome.X + VitricBiome.Width / 2 + 70) && Helper.CheckAirRectangle(new Point16(x, y - size.Y), new Point16(size.X, size.Y - 3)) && //ScanRectangle(x, y, size.X, size.Y) < 10
                    ValidGround.Any(v => v == Main.tile[x + 1, y].type) && ValidGround.Any(v => v == Main.tile[x + size.X - 1, y].type))
                {
                    StructureHelper.StructureHelper.GenerateStructure("Structures/Vitric/VitricTempleRuins_" + ty, new Point16(x, y - size.Y), StarlightRiver.Instance);
                }
                else
                {
                    i--; failCount++; continue;
                }
            }

            failCount = 0;
            for (int i = 0; i < 4; ++i)
            {
                if (failCount > 60)
                {
                    break;                 //Too many fails, stop
                }
                int x = VitricBiome.X + VitricSlopeOffset + genRand.Next(VitricBiome.Width - (VitricSlopeOffset * 2));
                while (x > VitricBiome.Center.X - 71 && x < VitricBiome.Center.X + 70)
                {
                    x = VitricBiome.X + VitricSlopeOffset + genRand.Next(VitricBiome.Width - (VitricSlopeOffset * 2));
                }
                int y = VitricBiome.Y + genRand.Next(VitricBiome.Height);
                while (Main.tile[x, y].active())
                {
                    y = VitricBiome.Y + genRand.Next(VitricBiome.Height);
                }
                if (RuinedPillarPositions.Any(v => Vector2.Distance(v.ToVector2(), new Vector2(x, y)) < 40) || !GenPillar(x, y))
                {
                    i--;
                    failCount++;
                }
            }
        }
예제 #3
0
        /// <summary>Generates a large island at X/Y.</summary>
        /// <param name="x">X position.</param>
        /// <param name="y">Y position.</param>
        private static void CreateIsland(int x, int y, bool small = false)
        {
            int wid = genRand.Next(32, 42);

            if (small)
            {
                wid = genRand.Next(10, 18);
            }
            int top   = 5;
            int depth = 2;

            bool peak      = false;
            int  peakEnd   = 0;
            int  peakStart = 0;
            int  offset    = 0;

            for (int i = x - (int)(wid / 2f); i < x + (wid / 2f); ++i)
            {
                if (i == x - (int)(wid / 2f) + 1)
                {
                    top++;
                }
                else if (i == (x + (int)(wid / 2f)) - 1)
                {
                    top--;
                }

                if (!peak)
                {
                    if (depth <= 2)
                    {
                        depth += genRand.Next(2);
                    }
                    else
                    {
                        depth += genRand.Next(-1, 2);
                    }

                    if (genRand.Next(3) == 0)
                    {
                        peak      = true;
                        peakStart = i;
                        peakEnd   = i + genRand.Next(3, 8);
                        if (peakEnd > (x + (wid / 2f)) - 1)
                        {
                            peakEnd = (int)(x + (wid / 2f)) - 1;
                        }
                    }
                }
                else
                {
                    int dist = peakEnd - i;
                    int dif  = peakEnd - peakStart;
                    int deep = (7 - dif);

                    if (dist > (int)(dif / 2f))
                    {
                        depth += genRand.Next(deep, deep + 2);
                    }
                    else
                    {
                        depth -= genRand.Next(deep, deep + 2);
                    }

                    if (x >= peakEnd)
                    {
                        peak = false;
                    }
                }

                if (i % 4 == 0)
                {
                    if (i < x)
                    {
                        top += genRand.Next(2);
                    }
                    else
                    {
                        top -= genRand.Next(2);
                    }
                }

                if (i % 8 == 2)
                {
                    offset += genRand.Next(-1, 2);
                }

                if (top < 3)
                {
                    top = 3;
                }

                if (i > x + (wid / 2f) - 4 && depth > 4)
                {
                    depth--;
                }
                if (i > x + (wid / 2f) - 4 && depth > 8)
                {
                    depth--;
                }

                for (int j = y - top + offset; j < y + depth + offset; j++)
                {
                    int t = j > (y + depth + offset) - 4 ? TileType <VitricSand>() : TileType <VitricSoftSand>();
                    PlaceTile(i, j, t, false, true);
                }
            }

            //Place crystal if needed
            if (crystalsPlaced <= (VitricBiome.Width / 240) + 2 && !small)
            {
                int tries = 0;
                while (true)
                {
                    int cX = x + genRand.Next((int)(wid * -0.60f), (int)(wid * 0.60f)) - 3;
                    int cY = y - 5;
                    while (Main.tile[cX, cY].active())
                    {
                        cY--;
                    }
                    cY = Math.Max(
                        FindType(cX, cY, -1, ValidGround),
                        FindType(cX + 1, cY, -1, ValidGround)
                        );
                    if (ValidGround.Any(v => v == Main.tile[cX + 1, cY].type) && ValidGround.Any(v => v == Main.tile[cX + 2, cY].type) && ScanRectangle(cX, cY - 6, 4, 6) < 3)
                    {
                        StructureHelper.StructureHelper.GenerateStructure(
                            "Structures/Vitric/VitricSmallCrystal_" + genRand.Next(2),
                            new Point16(cX, cY - 6),
                            StarlightRiver.Instance
                            );
                        crystalsPlaced++;
                        break;
                    }
                    else
                    if (tries++ >= 20)
                    {
                        break;
                    }
                }
            }
            else if (small)
            {
                // Input variables
                int spawnAttempts = 30;
                int cX, cY;

                // Perform several checks
                while (spawnAttempts-- > 0)
                {
                    cX = x + genRand.Next((int)(wid * -0.60f), (int)(wid * 0.60f)) - 3;
                    cY = y - 5;
                    cY = FindType(cX, cY, -1, ValidGround);
                    // If the left side of the crystal isn't valid,
                    // or if the right side is occupied,
                    // skip.
                    if (cY == -1)
                    {
                        continue;
                    }

                    // If there are solid tiles in the way, skip.
                    if (ScanRectangle(cX, cY - 3, 2, 3) > 2)
                    {
                        continue;
                    }

                    // Success! Halve the spawnAttempts count so we don't spam crystals.
                    PlaceTile(cX + 1, cY, Framing.GetTileSafely(cX, cY).type, true, true);
                    Helper.PlaceMultitile(new Point16(cX, cY - 3), TileType <VitricOre>());
                    spawnAttempts /= 4;
                }
            }
        }
예제 #4
0
        /// <summary>Generates the Vitric Desert under the Underground Desert.</summary>
        /// <param name="progress"></param>
        public static void VitricGen(GenerationProgress progress)
        {
            progress.Message = "Digging Vitric Desert";

            int vitricHeight = 140;

            ValidGround = new int[] { TileType <VitricSand>(), TileType <VitricSoftSand>() };
            //Basic biome information
            VitricBiome = new Rectangle(UndergroundDesertLocation.X - 80, UndergroundDesertLocation.Y + UndergroundDesertLocation.Height, UndergroundDesertLocation.Width + 150, vitricHeight);

            int minCeilingDepth = (int)((VitricBiome.Y + (VitricBiome.Height / 2)) - (17f * Math.Log(VitricSlopeOffset - 8))); //Various informational variables - not to be changed
            int maxCeilingDepth = minCeilingDepth + 7;
            int minFloorDepth   = (int)(VitricBiome.Y + (13f * Math.Log(VitricSlopeOffset - 8))) + (VitricBiome.Height / 2);

            GenerateBase(minCeilingDepth, maxCeilingDepth, minFloorDepth);

            for (int x = VitricBiome.Center.X - 35; x <= VitricBiome.Center.X + 36; x++) //Entrance from Desert
            {
                for (int y = VitricBiome.Y - 6; y < VitricBiome.Y + 20; y++)
                {
                    KillTile(x, y);
                    if (y > VitricBiome.Y + 5 && y < VitricBiome.Y + 9)
                    {
                        PlaceTile(x, y, TileType <VitricBossBarrier>(), true, true);
                    }
                }
            }

            for (int y = VitricBiome.Y + 9; y < VitricBiome.Y + VitricBiome.Height - 77; y++) //collision for pillars
            {
                PlaceTile(VitricBiome.X + VitricBiome.Width / 2 - 40, y, TileType <VitricBossBarrier>(), false, false);
                PlaceTile(VitricBiome.X + VitricBiome.Width / 2 + 41, y, TileType <VitricBossBarrier>(), false, false);
            }

            VitricIslandLocations = new List <Point>(); //List for island positions
            int fail = 0;

            for (int i = 0; i < (VitricBiome.Width / 40) - 1; ++i)
            {
                int  x;
                int  y;
                bool repeat = false;

                do
                {
                    x = genRand.Next(2) == 0 ? genRand.Next(VitricBiome.X + VitricSlopeOffset + 20, VitricBiome.Center.X - 61) : genRand.Next(VitricBiome.Center.X + 62, VitricBiome.Right - VitricSlopeOffset - 20);
                    y = (maxCeilingDepth + 18) + (genRand.Next((int)(VitricBiome.Height / 2.8f)));

                    if (VitricIslandLocations.Any(v => Vector2.Distance(new Vector2(x, y), v.ToVector2()) < 32) || (x > VitricBiome.X + VitricBiome.Width / 2 - 71 && x < VitricBiome.X + VitricBiome.Width / 2 + 70))
                    {
                        repeat = true;
                        if (fail++ >= 50)
                        {
                            break;
                        }
                    }
                    else
                    {
                        repeat = false;
                    }
                }while (repeat); //Gets a valid island position

                if (fail >= 50)
                {
                    break;             //Could not get a valid position, stop trying
                }
                VitricIslandLocations.Add(new Point(x, y));
                CreateIsland(x, y); //Adds island pos to list and places island
            }

            for (int i = 0; i < 8; ++i) //Mini islands v2, outer only
            {
                int x = i <= 2 ? VitricBiome.X + 6 + genRand.Next((int)(VitricSlopeOffset * 1.3f)) : VitricBiome.Right - 6 - genRand.Next((int)(VitricSlopeOffset * 1.3f));
                if (i <= 2 && forgeSide == 0)
                {
                    x += 10;
                }
                if (i > 2 && forgeSide == 1)
                {
                    x -= 10;
                }
                int y = genRand.Next(VitricBiome.Y + 22, VitricBiome.Bottom - 50);
                if (ScanRectangle(x - 13, y - 4, 26, 14) < 8)
                {
                    CreateIsland(x, y, true);
                }
                else
                {
                    i--;
                }
            }

            //Mini islands throughout main area
            List <Point> MiniIslandLocations = new List <Point>();

            for (int i = 0; i < 20;)  //I may or may not be doing this because I find this form of a for loop neat.
            {
                int x = genRand.Next(2) == 0 ? genRand.Next(VitricBiome.X + VitricSlopeOffset + 20, VitricBiome.Center.X - 61) : genRand.Next(VitricBiome.Center.X + 62, VitricBiome.Right - VitricSlopeOffset - 20);
                int y = (maxCeilingDepth + 18) + (genRand.Next((int)(VitricBiome.Height / 2.8f)));

                if (MiniIslandLocations.Any(v => Vector2.Distance(v.ToVector2(), new Vector2(x, y)) < 1) || ScanRectangle(x - 13, y - 4, 26, 14) > 8)
                {
                    i++;
                    continue;
                }
                else
                {
                    MiniIslandLocations.Add(new Point(x, y));
                }
            }
            for (int i = 0; i < MiniIslandLocations.Count; ++i)
            {
                if (genRand.NextFloat() > 0.7f)
                {
                    CreateIsland(MiniIslandLocations[i].X, MiniIslandLocations[i].Y, true);
                }
            }

            fail = 0;
            for (int i = 0; i < VitricBiome.Width / 160; ++i)
            {
                if (fail > 40)
                {
                    break;
                }

                int x = genRand.Next(2) == 0 ? genRand.Next(VitricBiome.X + VitricSlopeOffset + 20, VitricBiome.Center.X - 61) : genRand.Next(VitricBiome.Center.X + 62, VitricBiome.Right - VitricSlopeOffset - 20);
                int y = (maxCeilingDepth + 20) + (genRand.Next((int)(VitricBiome.Height / 3.2f)));

                if (Helper.ScanForTypeDown(x, y, TileType <VitricSpike>(), 120))
                {
                    y = FindType(x, y, VitricBiome.Bottom + 20, TileType <VitricSpike>());
                }
                else
                {
                    i--;
                    fail++;
                    continue;
                }

                if (!FloorCrystal(x, y))
                {
                    i--;
                    fail++;
                    continue;
                }
            } //Mini islands

            progress.Message = "Populating the Vitric";

            GenConsistentMiniIslands();
            GenSandstonePillars();
            RuinedPillarPositions = new List <Point>();
            GenRuins();
            GenForge();
            GenDecoration();
            //GenMoss();
            GenTemple();

            VitricBiome.Y -= 8; //Adjust a bit
        }