Ejemplo n.º 1
0
    /// <summary>
    /// Modifies the height of the supplied chunk to the paramater <paramref name="height"/>, and then
    /// further modifies the heights of near chunks that are heigher than this one
    /// </summary>
    /// <param name="position"></param>
    /// <param name="height"></param>
    private void ModifyRiverValleyHeight(Vec2i position, float height, int smoothRad = 32, float smoothAmount = 16)
    {
        ChunkBases[position.x, position.z].SetHeight(height);
        //iterate all points in a circle
        for (int x = -smoothRad; x <= smoothRad; x++)
        {
            for (int z = -smoothRad; z <= smoothRad; z++)
            {
                if (x * x + z * z < smoothRad * smoothRad)
                {
                    //Get chunk at this position
                    Vec2i      pos = position + new Vec2i(x, z);
                    ChunkBase2 cb  = ChunkBases[pos.x, pos.z];
                    //if this chunk is of valid height, we ignore it
                    if (cb.Height <= height)
                    {
                        continue;
                    }

                    float deltaHeight = cb.Height - height;
                    //Calculate new height
                    float nHeight = cb.Height - Mathf.Exp(-(x * x + z * z) / (smoothAmount * smoothAmount)) * deltaHeight;
                    cb.SetHeight(nHeight);
                }
            }
        }
    }
Ejemplo n.º 2
0
    /// <summary>
    /// Turns the array of chunk bases into a cost map
    /// </summary>
    private void GeneratePathfindingMap(ChunkBase2[,] map)
    {
        CostMap = new float[map.GetLength(0), map.GetLength(1)];

        for (int x = 0; x < map.GetLength(0); x++)
        {
            for (int z = 0; z < map.GetLength(1); z++)
            {
                ChunkBase2 cBase = map[x, z];

                if (cBase.HasSettlement)
                {
                    CostMap[x, z] = 10; //Low cost for inside settlement
                }
                else if (cBase.ChunkFeature != null)
                {
                    CostMap[x, z] = cBase.ChunkFeature.MovementCost(); //If a chunk feature is present, we set the value accordingly
                }
                else
                {
                    CostMap[x, z] = cBase.Biome.GetMovementCost();
                }
            }
        }
    }
Ejemplo n.º 3
0
    public Texture2D ToTexture()
    {
        Texture2D tex = new Texture2D(World.WorldSize, World.WorldSize);

        Dictionary <int, Color> kingCol = new Dictionary <int, Color>();

        for (int x = 0; x < World.WorldSize; x++)
        {
            for (int z = 0; z < World.WorldSize; z++)
            {
                ChunkBase2 cb = GameGen.TerGen.ChunkBases[x, z];
                if (cb.KingdomID != -1)
                {
                    if (!kingCol.ContainsKey(cb.KingdomID))
                    {
                        kingCol.Add(cb.KingdomID, GenRan.RandomColor(0.7f));
                    }
                    tex.SetPixel(x, z, kingCol[cb.KingdomID]);
                }
            }
        }


        tex.Apply();
        return(tex);
    }
Ejemplo n.º 4
0
    private string ChunkBaseDetail(ChunkBase2 b)
    {
        if (b == null)
        {
            return("");
        }
        string output = "Chunk: " + b.Pos + "\n";

        output += "Biome: " + b.Biome + "\n";
        output += "Height: " + b.Height + "\n";
        foreach (ChunkResource res in MiscUtils.GetValues <ChunkResource>())
        {
            output += res + ": " + b.GetResourceAmount(res) + "\n";
        }
        output += "riv_height: " + GameGen.TerGen.RiverGen.GetValAtChunk(b.Pos) + "\n";

        GridPoint nearestPoint = GameGen.GridPlacement.GetNearestPoint(b.Pos);

        if (nearestPoint != null)
        {
            output += "Nearest Grid Point: " + nearestPoint.GridPos + " at chunk " + nearestPoint.ChunkPos + "\n";
            output += "Has Road? " + nearestPoint.HasRoad + "\n";
            output += "Settlement? " + nearestPoint.HasSettlement + "\n";
        }
        else
        {
            output += "No grid point found near " + b.Pos;
        }

        return(output);
    }
Ejemplo n.º 5
0
    private void ModifyRiverHeight(ChunkRiverNode crn)
    {
        float height = ChunkBases[crn.Pos.x, crn.Pos.z].Height;

        foreach (ChunkRiverNode crn1 in crn.FlowOut)
        {
            ChunkBase2 cb = ChunkBases[crn1.Pos.x, crn1.Pos.z];
            if (cb.Height < height)
            {
                height = cb.Height;
                ModifyRiverValleyHeight(crn1.Pos, height);
            }
        }
    }
Ejemplo n.º 6
0
    /// <summary>
    /// Finds the type of resources near the supplied settlement, and then generates an economy based
    /// onthis
    /// </summary>
    private void CalculateSettlementEconomy(SettlementShell shell)
    {
        int size = shell.Type == SettlementType.CAPITAL ? 16 : shell.Type == SettlementType.CITY ? 14 : shell.Type == SettlementType.TOWN ? 10 : 8;

        //The total amount of resources within the settlement bounds
        Dictionary <ChunkResource, float> settlementResources = new Dictionary <ChunkResource, float>();

        Vec2i baseChunk = shell.ChunkPosition;

        //We iterate every chunk within this settlement
        for (int x = 0; x < size; x++)
        {
            for (int z = 0; z < size; z++)
            {
                ChunkBase2 cb = GameGen.TerGen.ChunkBases[baseChunk.x + x, baseChunk.z + z];
                //We iterate each possible resource the chunk could have,
                foreach (ChunkResource cr in MiscUtils.GetValues <ChunkResource>())
                {
                    //We find the amount of this resource in the chunk, and add this to the settlement total
                    float am = cb.GetResourceAmount(cr);
                    if (!settlementResources.ContainsKey(cr))
                    {
                        settlementResources.Add(cr, 0);
                    }

                    settlementResources[cr] += am;
                }
            }
        }

        //We now know the raw resources in the area,
        if (shell.Type == SettlementType.VILLAGE)
        {
            GenerateVillageEconomy(settlementResources, shell);
        }
        else if (shell.Type == SettlementType.TOWN)
        {
            GenerateTownEconomy(settlementResources, shell);
        }
        else
        {
            GenerateTownEconomy(settlementResources, shell);
        }
    }
Ejemplo n.º 7
0
    /// <summary>
    /// Generates a chunk that has no special land features
    /// </summary>
    /// <param name="x"></param>
    /// <param name="z"></param>
    /// <param name="cb"></param>
    /// <returns></returns>
    private ChunkData GenerateSimpleChunk(int x, int z, ChunkBase2 cb)
    {
        if (cb.Biome == ChunkBiome.ocean)
        {
            return(new ChunkData(x, z, (int[, ])OCEAN.Clone(), false));
        }/*
          * if(cb.Biome == ChunkBiome.dessert)
          * {
          * return new ChunkData(x, z, (int[,])EMPTY_DESERT.Clone(), cb.IsLand, 1, (float[,])OCEAN_HEIGHT.Clone());
          * }if(cb.Biome == ChunkBiome.mountain)
          * {
          * return new ChunkData(x, z, (int[,])MOUNTAIN.Clone(), cb.IsLand, 1, (float[,])OCEAN_HEIGHT.Clone());
          *
          * }*/
        int[,] tiles = (int[, ])(cb.Biome == ChunkBiome.dessert ? EMPTY_DESERT.Clone() : cb.Biome == ChunkBiome.mountain ? MOUNTAIN.Clone() : EMPTY_PLAINS.Clone());

        GenerationRandom genRan = new GenerationRandom(Seed + x << 16 + z);

        //if(genRan.Random() > 0.1f)
        //    return new ChunkData(x, z, tiles, cb.IsLand);

        Dictionary <int, WorldObjectData> obs = new Dictionary <int, WorldObjectData>(256);

        float[,] heights = new float[World.ChunkSize, World.ChunkSize];
        for (int i = 0; i < World.ChunkSize; i++)
        {
            for (int j = 0; j < World.ChunkSize; j++)
            {
                if (genRan.Random() < 0.01f)
                {
                    //obs.Add(WorldObject.ObjectPositionHash(i,j), new Tree(new Vec2i(x * World.ChunkSize + i, z * World.ChunkSize + j)));
                }
                else if (genRan.Random() < 0.3f)
                {
                    //obs.Add(WorldObject.ObjectPositionHash(i, j), new Tree(new Vec2i(x * World.ChunkSize + i, z * World.ChunkSize + j)));
                }
                heights[i, j] = GameGen.TerGen.GetWorldHeightAt(x * World.ChunkSize + i, z * World.ChunkSize + j);
            }
        }
        ChunkData cd = new ChunkData(x, z, tiles, true, cb.Height, heightMap: heights);

        return(cd);
    }
Ejemplo n.º 8
0
    /// <summary>
    /// Generates the chunk based on its biome, as well as things added to it such as forrests and wooded areas
    /// </summary>
    /// <param name="x"></param>
    /// <param name="z"></param>
    /// <returns></returns>
    public ChunkData GenerateChunk(int x, int z)
    {
        ChunkBase2 cb = ChunkBases[x, z];
        ChunkData  cd = null;

        if (cb.ChunkFeature is ChunkLake)
        {
            cd = GenerateLakeChunk(x, z, cb);
        }
        else if (cb.ChunkFeature is ChunkRiverNode)
        {
            cd = GenerateRiverChunk(x, z, cb);
        }
        else
        {
            cd = GenerateSimpleChunk(x, z, cb);
        }
        return(cd);
    }
Ejemplo n.º 9
0
    private void Update()
    {
        Vector3 p = Input.mousePosition;
        int     x = (int)p.x;
        int     z = (int)p.y;

        Vector3[] corn = new Vector3[4];
        Image.rectTransform.GetWorldCorners(corn);
        x = x - (int)corn[0].x;
        z = (z - (int)corn[0].y);

        if (x > 0 && z > 0 && x < World.WorldSize && z < World.WorldSize)
        {
            ChunkBase2 current = GameGen.TerGen.ChunkBases[x, z];
            InfoText.text = ChunkBaseDetail(current);
        }

        foreach (KeyValuePair <EntityGroup, GameObject> kvp in Caravans)
        {
            Vec2i pos = kvp.Key.CurrentChunk;
            kvp.Value.transform.localPosition = new Vector3(pos.x - World.WorldSize / 2, pos.z - World.WorldSize / 2, 0);
        }
    }
Ejemplo n.º 10
0
    /// <summary>
    ///  Calculates the location data for the supplied shell
    /// </summary>
    /// <param name="shell">The shell to generate and store data to</param>
    private void GenerateLocationData(Shell shell)
    {
        GridPoint gp = shell.GridPoint;

        bool onBorder = false;
        bool onRiver  = false;
        bool onCoast  = false;
        bool onLake   = false;
        //Get the chunk this grid point is on
        ChunkBase2 cb = GameGen.TerGen.ChunkBases[gp.ChunkPos.x, gp.ChunkPos.z];

        int kingdomID = cb.KingdomID;

        if (kingdomID == -1)
        {
            Debug.Error("Shell " + shell + " lays on unclaimed territory - not valid");
        }
        //iterate away from search point
        for (int i = 1; i < GridPlacement.GridPointSize; i++)
        {
            //Search in 4 directions
            foreach (Vec2i v in Vec2i.OCT_DIRDIR)
            {
                //Find the point in this direction
                Vec2i p = cb.Pos + v * i;
                //Ensure in world bounds
                if (GameGenerator2.InBounds(p))
                {
                    //Get chunk here
                    ChunkBase2 cb_p = GameGen.TerGen.ChunkBases[p.x, p.z];
                    if (cb_p.Biome == ChunkBiome.ocean)
                    {
                        onCoast = true;
                    }
                    if (cb_p.KingdomID != -1 && cb_p.KingdomID != kingdomID)
                    {
                        onBorder = true;
                    }
                    if (cb_p.ChunkFeature is ChunkRiverNode)
                    {
                        onRiver = true;
                    }
                }
            }
        }
        //Define entraces
        bool[] entrances = new bool[8];
        for (int i = 0; i < 8; i++)
        {
            foreach (Vec2i v in Vec2i.OCT_DIRDIR)
            {
                Vec2i p = gp.GridPos + v;
                if (GridPlacement.InGridBounds(p))
                {
                    GridPoint gp2 = GameGen.GridPlacement.GridPoints[p.x, p.z];
                    if (gp2.HasRoad)
                    {
                        entrances[i] = true;
                    }
                    else
                    {
                        entrances[i] = false;
                    }
                }
            }
        }
        LocationData ld = new LocationData()
        {
            OnCoast = onCoast, OnLake = onLake, OnRiver = onRiver, OnBorder = onBorder, EntranceDirections = entrances
        };

        shell.SetLocationData(ld);
        Vec2i size = shell.GetSize();

        ChunkBase2[,] bases = new ChunkBase2[size.x, size.z];
        //Iterate chunk bases that belong to this shell, add them to the array
        for (int x = 0; x < size.x; x++)
        {
            for (int z = 0; z < size.z; z++)
            {
                bases[x, z] = GameGen.TerGen.ChunkBases[x, z];
            }
        }
        //Set bases
        shell.SetChunkBases(bases);
    }
Ejemplo n.º 11
0
    public Vec2i[] ChooseStartChunks(int count, int minSep)
    {
        //The angle between map middle that each capital should approximately
        //be seperated by
        float thetaSep = 360f / count;

        float   thetaOffset = GenRan.Random(0, 90);
        Vector2 middle      = new Vector2(World.WorldSize / 2, World.WorldSize / 2);

        Vec2i[] caps = new Vec2i[count];
        //We iterate each of the kingdom capital positions we wish to calculate
        for (int i = 0; i < count; i++)
        {
            //Theta compared to (1,0) anticlockwise
            float   theta = thetaOffset + thetaSep * i;
            float   dx    = Mathf.Cos(theta * Mathf.Deg2Rad);
            float   dz    = Mathf.Sin(theta * Mathf.Deg2Rad);
            Vector2 delta = new Vector2(dx, dz);
            //We start at middle
            Vector2 current = middle;

            int minLength = 32;
            int maxLength = -1;

            //iterate out
            for (int l = minLength; l < World.WorldSize / 2; l++)
            {
                current = middle + delta * l;
                Vec2i      curChunk = Vec2i.FromVector2(current);
                ChunkBase2 cb       = GameGen.TerGen.ChunkBases[curChunk.x, curChunk.z];
                if (cb.Biome == ChunkBiome.ocean)
                {
                    //When we reach the ocean, we define this as the max distance away
                    maxLength = l - 1;
                    break;
                }
            }
            //Capital is random point between min length, and max length
            Vec2i capPoint = Vec2i.FromVector2(middle + GenRan.RandomInt(minLength, maxLength) * delta);
            caps[i] = capPoint;
        }

        return(caps);



        Vec2i[] dirs = new Vec2i[] { new Vec2i(1, 1), new Vec2i(-1, 1), new Vec2i(-1, -1), new Vec2i(1, -1) };
        Vec2i   mid  = new Vec2i(World.WorldSize / 2, World.WorldSize / 2);

        for (int i = 100; i < 400; i++)
        {
            for (int j = 0; j < dirs.Length; j++)
            {
                if (caps[j] == null)
                {
                    Vec2i      p = mid + dirs[j] * i;
                    ChunkBase2 b = GameGen.TerGen.ChunkBases[p.x, p.z];
                    if (b.Biome == ChunkBiome.ocean)
                    {
                        Vec2i p_ = mid + dirs[j] * (int)(0.75f * i);
                        caps[j] = p_;

                        GridPoint gp = GameGen.GridPlacement.GetNearestPoint(p_);
                    }
                }
            }
        }
        return(caps);

        for (int i = 0; i < count; i++)
        {
            bool validPoint = false;
            while (!validPoint)
            {
                Vec2i     pos = GenRan.RandomVec2i(0, World.WorldSize - 1);
                GridPoint p   = GameGen.GridPlacement.GetNearestPoint(pos);
                if (p != null && p.IsValid)
                {
                    if (i == 0)
                    {
                        caps[0]    = p.ChunkPos;
                        validPoint = true;
                    }
                    else
                    {
                        int minDist = -1;
                        for (int j = 0; j < i; j++)
                        {
                            int sqrDist = p.ChunkPos.QuickDistance(caps[j]);
                            if (minDist == -1 || sqrDist < minDist)
                            {
                                minDist = sqrDist;
                            }
                        }
                        if (minDist < minSep * minSep)
                        {
                            caps[i]    = p.ChunkPos;
                            validPoint = true;
                        }
                    }
                }
            }
            Debug.Log(caps[i]);
        }
        return(caps);
    }
Ejemplo n.º 12
0
    /// <summary>
    /// Generates the height map & biomes, + chunk resource details
    /// </summary>
    private void GenerateBaseTerrain()
    {
        //imulateWater();
        for (int x = 0; x < World.WorldSize; x++)
        {
            for (int z = 0; z < World.WorldSize; z++)
            {
                float height = GetChunkHeightAt(x, z);
                int   eqDist = Mathf.Abs(z - (World.WorldSize / 2));
                float temp   = Mathf.Exp(-eqDist / 100f) * 2f - height / 256f;
                float hum    = PerlinNoise(x, z, 2);

                ChunkBiome b = ChunkBiome.ocean;


                if (height > 100)
                {
                    b = ChunkBiome.mountain;
                }
                else if (height < WaterHeight)
                {
                    b = ChunkBiome.ocean;
                }
                else if ((temp > 0.4f && hum < 0.3f) || temp > 0.9f)
                {
                    b = ChunkBiome.dessert;
                }
                else if (temp > 0.4f & hum > 0.5f)
                {
                    b = ChunkBiome.forrest;
                }
                else
                {
                    b = ChunkBiome.grassland;
                }
                ChunkBases[x, z] = new ChunkBase2(new Vec2i(x, z), height, b);

                switch (b)
                {
                //Deserts and mountains are for mining
                case ChunkBiome.mountain:
                case ChunkBiome.dessert:
                    ChunkBases[x, z].SetResourceAmount(ChunkResource.ironOre, PerlinNoise(x, z, 3));
                    ChunkBases[x, z].SetResourceAmount(ChunkResource.silverOre, 0.4f * PerlinNoise(x, z, 4));
                    ChunkBases[x, z].SetResourceAmount(ChunkResource.goldOre, 0.2f * PerlinNoise(x, z, 5));
                    break;

                case ChunkBiome.forrest:
                    ChunkBases[x, z].SetResourceAmount(ChunkResource.wood, 1);
                    ChunkBases[x, z].SetResourceAmount(ChunkResource.sheepFarm, PerlinNoise(x, z, 6));
                    break;

                case ChunkBiome.grassland:
                    ChunkBases[x, z].SetResourceAmount(ChunkResource.sheepFarm, PerlinNoise(x, z, 7));
                    ChunkBases[x, z].SetResourceAmount(ChunkResource.cattleFarm, PerlinNoise(x, z, 8));
                    ChunkBases[x, z].SetResourceAmount(ChunkResource.wheatFarm, PerlinNoise(x, z, 9));
                    ChunkBases[x, z].SetResourceAmount(ChunkResource.vegetableFarm, PerlinNoise(x, z, 10));
                    ChunkBases[x, z].SetResourceAmount(ChunkResource.silkFarm, PerlinNoise(x, z, 11));


                    break;
                }
            }
        }
    }
Ejemplo n.º 13
0
    /// <summary>
    /// Finds the settlement placement desirability
    /// </summary>
    /// <param name="gp"></param>
    /// <returns></returns>
    private float CalculateGridPointSettlementDesirability(GridPoint gp)
    {
        bool onBorder = false;
        bool onRiver  = false;
        bool onCoast  = false;
        bool onLake   = false;
        //Get the chunk this grid point is on
        ChunkBase2 cb = GameGen.TerGen.ChunkBases[gp.ChunkPos.x, gp.ChunkPos.z];

        //desirability less than 0 means not valid
        if (cb.Biome == ChunkBiome.ocean)
        {
            return(-1);
        }
        int kingdomID = cb.KingdomID;

        //If this chunk is not claimed, then we don't use it
        if (kingdomID == -1)
        {
            return(-1);
        }

        if (cb.Pos.QuickDistance(GameGen.TerGen.EvilDragonMountainPeak) < 128 * 128)
        {
            return(-1);
        }
        if (cb.Pos.QuickDistance(GameGen.TerGen.GoodDragonMountainPeak) < 64 * 64)
        {
            return(-1);
        }


        if (gp.Shell != null)
        {
            return(-1);
        }
        //iterate away from search point
        for (int i = 1; i < GridPlacement.GridPointSize; i++)
        {
            //Search in 4 directions
            foreach (Vec2i v in Vec2i.OCT_DIRDIR)
            {
                //Find the point in this direction
                Vec2i p = cb.Pos + v * i;
                //Ensure in world bounds
                if (GameGenerator2.InBounds(p))
                {
                    //Get chunk here
                    ChunkBase2 cb_p = GameGen.TerGen.ChunkBases[p.x, p.z];
                    if (cb_p.Biome == ChunkBiome.ocean)
                    {
                        onCoast = true;
                    }
                    if (cb_p.KingdomID != -1 && cb_p.KingdomID != kingdomID)
                    {
                        onBorder = true;
                    }
                    if (cb_p.ChunkFeature is ChunkRiverNode)
                    {
                        onRiver = true;
                    }
                }
            }
        }

        float xGradient = Mathf.Abs(GameGen.TerGen.ChunkBases[gp.ChunkPos.x + 1, gp.ChunkPos.z].Height - GameGen.TerGen.ChunkBases[gp.ChunkPos.x - 1, gp.ChunkPos.z].Height);
        float zGradient = Mathf.Abs(GameGen.TerGen.ChunkBases[gp.ChunkPos.x, gp.ChunkPos.z + 1].Height - GameGen.TerGen.ChunkBases[gp.ChunkPos.x, gp.ChunkPos.z - 1].Height);

        if (xGradient > 3 || zGradient > 3 || xGradient + zGradient > 5)
        {
            return(-1);
        }


        float des = 5 + (onRiver ? 5f : 0) + (onCoast ? 8f : 0) + (onLake ? 3f : 0) - (onBorder ? 4 : 0) + GenRan.Random();

        return(des);
    }
Ejemplo n.º 14
0
    /// <summary>
    /// Decides the placement for all non capital settlements.
    ///
    /// <list type="bullet">
    ///     <item>
    ///         We choose a valid grid point by accessing <see cref="DesireWeightedGridpoints"/>,
    ///         and taking a weight random element from it.
    ///         </item>
    ///          <item>We then check which kingdom owns the territory of the point.</item>
    ///     <item>We check the number of capitals, towns, and villages allowed by the kingdom, based on <paramref name="kts"/></item>
    ///     <item>If they have not reached their maximum number of a settlement type, we place one here</item>
    ///     <item>We continuously do this until all settlements for all kingdoms are found,</item>
    /// </list>
    /// </summary>
    /// <param name="kts"></param>
    private Dictionary <int, Dictionary <SettlementType, List <SettlementShell> > > DecideSettlementPlacements(Dictionary <int, KingdomTotalSettlements> kts)
    {
        //Key = kingdom ID
        //Value[0] = Dictionary ordered by settlement type, containing values representing the desired settlement placement
        Dictionary <int, Dictionary <SettlementType, List <SettlementShell> > > setPlace = new Dictionary <int, Dictionary <SettlementType, List <SettlementShell> > >();

        //We create a data structure to hold each settlement
        foreach (Kingdom k in GameGen.KingdomGen.Kingdoms)
        {
            setPlace.Add(k.KingdomID, new Dictionary <SettlementType, List <SettlementShell> >());
            setPlace[k.KingdomID].Add(SettlementType.CITY, new List <SettlementShell>());
            setPlace[k.KingdomID].Add(SettlementType.TOWN, new List <SettlementShell>());
            setPlace[k.KingdomID].Add(SettlementType.VILLAGE, new List <SettlementShell>());
        }
        bool shouldContinue = true;

        while (shouldContinue)
        {
            //if no points remain, we break
            if (DesireWeightedGridpoints.Count == 0)
            {
                shouldContinue = false;
                break;
            }
            //We a random point
            GridPoint gp = DesireWeightedGridpoints.GetRandom(true);

            ChunkBase2 cb        = GameGen.TerGen.ChunkBases[gp.ChunkPos.x, gp.ChunkPos.z];
            int        kingdomID = cb.KingdomID;
            if (kingdomID == -1)
            {
                continue;
            }

            //We have now got to a valid settlement point so we check what type of settlement we need;

            SettlementType setType = SettlementType.CITY;
            if (setPlace[kingdomID][SettlementType.CITY].Count < kts[kingdomID].CityCount)
            {
                setType = SettlementType.CITY;
            }
            else if (setPlace[kingdomID][SettlementType.TOWN].Count < kts[kingdomID].TownCount)
            {
                setType = SettlementType.TOWN;
            }
            else if (setPlace[kingdomID][SettlementType.VILLAGE].Count < kts[kingdomID].VillageCount)
            {
                setType = SettlementType.VILLAGE;
            }
            else
            {
                Debug.Log("Already completed set placement for " + kingdomID);
                continue;
            }

            //Find the shorest distance
            int distSqr = FindShortestSquareDistance(setPlace[kingdomID], gp);
            //the maximum distance
            int minDistSqr = GridPlacement.GridPointSize * GridPlacement.GridPointSize * 5;
            if (distSqr >= minDistSqr || distSqr < 0)
            {
                gp.HasSet = true;
                gp.SETYPE = setType;
                SettlementShell sp = new SettlementShell(gp, kingdomID, setType);
                gp.Shell = sp;
                setPlace[kingdomID][setType].Add(sp);
            }
        }
        return(setPlace);
    }
Ejemplo n.º 15
0
    private ChunkData GenerateRiverChunk(int x, int z, ChunkBase2 cb)
    {
        GenerationRandom genRan = new GenerationRandom(new Vec2i(x, z).GetHashCode() + Seed);

        int[,] tiles            = new int[World.ChunkSize, World.ChunkSize];
        WorldObjectData[,] data = new WorldObjectData[World.ChunkSize, World.ChunkSize];
        float[,] heights        = new float[World.ChunkSize, World.ChunkSize];
        Vec2i exitDelta = new Vec2i(1, 0);
        Vec2i entrDelta = new Vec2i(-1, 0);

        if (exitDelta == null)
        {
            exitDelta = new Vec2i(0, 0);
        }
        if (entrDelta == null)
        {
            entrDelta = new Vec2i(0, 0);
        }

        //Calculatee the tile position of the entrance and exit point of the river
        int entrX = (entrDelta.x == 1) ? 16 : ((entrDelta.x == 0) ? 8 : 0);
        int entrZ = (entrDelta.z == 1) ? 16 : ((entrDelta.z == 0) ? 8 : 0);

        int exitX = (exitDelta.x == 1) ? 16 : ((exitDelta.x == 0) ? 8 : 0);
        int exitZ = (exitDelta.z == 1) ? 16 : ((exitDelta.z == 0) ? 8 : 0);



        float dx = entrX - exitX;
        float dz = entrZ - exitZ;
        //If dx or dz is 0, then
        float a, b, c;
        bool  angle = (dx != 0 && dz != 0);
        float divBy = angle ? 2 : 1;

        if (dx == 0)
        {
            a = 0;
            b = 1;
            c = -entrX;
        }
        else if (dz == 0)
        {
            a = 1;
            b = 0;
            c = -entrZ;
        }
        else
        {
            float m = dz / dx;
            c = -(entrZ - m * entrX);

            a = 1;
            b = -m;
        }

        int inWidth  = 8;
        int outWidth = 8;


        float          dem_sqr = (a * a + b * b);
        ChunkVoxelData vox     = new ChunkVoxelData();

        for (int tx = 0; tx < World.ChunkSize; tx++)
        {
            for (int tz = 0; tz < World.ChunkSize; tz++)
            {
                float baseheight = GameGen.TerGen.GetWorldHeightAt(x * World.ChunkSize + tx, z * World.ChunkSize + tz);

                float dist_sqr = ((a * tz + b * tx + c) * (a * tz + b * tx + c)) / dem_sqr;
                if (dist_sqr < (inWidth * inWidth) / divBy)
                {
                    Vector2 off = new Vector2(x * World.ChunkSize + tx, z * World.ChunkSize + tz);
                    //Debug.Log("here");
                    tiles[tx, tz] = Tile.WATER.ID;
                    //float baseheight = GameGen.TerrainGenerator.WorldHeight(x * World.ChunkSize + tx, z * World.ChunkSize + tz);
                    float lerp = dist_sqr / ((inWidth * inWidth) / divBy);


                    heights[tx, tz] = Mathf.Lerp(baseheight, baseheight - 5, 1 / lerp);
                    heights[tx, tz] = Mathf.Clamp(cb.Height - 5, 1, 16);
                    for (int y = Mathf.FloorToInt(heights[tx, tz]); y < baseheight; y++)
                    {
                        vox.SetVoxelNode(tx, y, tz, new VoxelNode(Voxel.glass));
                    }

                    /*
                     * if (!(data[tx, tz] is Water))
                     * {
                     *  data[tx, tz] = new Water(new Vec2i(x * World.ChunkSize + tx, z * World.ChunkSize + tz));
                     *  (data[tx, tz] as Water).SetUVOffset(off);
                     * }
                     *
                     * if (tx < World.ChunkSize - 1 && !(data[tx + 1, tz] is Water))
                     * {
                     *  data[tx + 1, tz] = new Water(new Vec2i(x * World.ChunkSize + tx + 1, z * World.ChunkSize + tz));
                     *  (data[tx + 1, tz] as Water).SetUVOffset(off + new Vector2(1, 0));
                     * }
                     * if (tz < World.ChunkSize - 1 && !(data[tx, tz + 1] is Water))
                     * {
                     *  data[tx, tz + 1] = new Water(new Vec2i(x * World.ChunkSize + tx, z * World.ChunkSize + tz + 1));
                     *  (data[tx, tz + 1] as Water).SetUVOffset(off + new Vector2(0, 1));
                     * }
                     * if (tx < World.ChunkSize - 1 && tz < World.ChunkSize - 1 && !(data[tx + 1, tz + 1] is Water))
                     * {
                     *  data[tx + 1, tz + 1] = new Water(new Vec2i(x * World.ChunkSize + tx + 1, z * World.ChunkSize + tz + 1));
                     *  (data[tx + 1, tz + 1] as Water).SetUVOffset(off + new Vector2(1, 1));
                     * }
                     *
                     * if (tx > 0 && !(data[tx - 1, tz] is Water))
                     * {
                     *  data[tx - 1, tz] = new Water(new Vec2i(x * World.ChunkSize + tx - 1, z * World.ChunkSize + tz));
                     *  (data[tx - 1, tz] as Water).SetUVOffset(off + new Vector2(-1, 0));
                     * }
                     * if (tz > 0 && !(data[tx, tz - 1] is Water))
                     * {
                     *  data[tx, tz - 1] = new Water(new Vec2i(x * World.ChunkSize + tx, z * World.ChunkSize + tz - 1));
                     *  (data[tx, tz - 1] as Water).SetUVOffset(off + new Vector2(0, -1));
                     * }
                     * if (tx > 0 && tz > 0 && !(data[tx - 1, tz - 1] is Water))
                     * {
                     *  data[tx - 1, tz - 1] = new Water(new Vec2i(x * World.ChunkSize + tx - 1, z * World.ChunkSize + tz - 1));
                     *  (data[tx - 1, tz - 1] as Water).SetUVOffset(off + new Vector2(-1, -1));
                     * }
                     *
                     * if (tx > 0 && tz < World.ChunkSize - 1 && !(data[tx - 1, tz + 1] is Water))
                     * {
                     *  data[tx - 1, tz + 1] = new Water(new Vec2i(x * World.ChunkSize + tx - 1, z * World.ChunkSize + tz + 1));
                     *  (data[tx - 1, tz + 1] as Water).SetUVOffset(off + new Vector2(-1, +1));
                     * }
                     * if (tz > 0 && tx < World.ChunkSize - 1 && !(data[tx + 1, tz - 1] is Water))
                     * {
                     *  data[tx + 1, tz - 1] = new Water(new Vec2i(x * World.ChunkSize + tx + 1, z * World.ChunkSize + tz - 1));
                     *  (data[tx + 1, tz - 1] as Water).SetUVOffset(off + new Vector2(1, -1));
                     * }*/
                }
                else if (dist_sqr < (inWidth * inWidth) * 2 / divBy)
                {
                    tiles[tx, tz]   = Tile.SAND.ID;
                    heights[tx, tz] = baseheight;
                    for (int y = Mathf.FloorToInt(heights[tx, tz]); y < baseheight; y++)
                    {
                        vox.SetVoxelNode(tx, y, tz, new VoxelNode(Voxel.glass));
                    }
                }
                else
                {
                    tiles[tx, tz]   = Tile.GRASS.ID;
                    heights[tx, tz] = baseheight;

                    // heights[tx, tz] = cb.BaseHeight;

                    //if (genRan.Random() < 0.25f)
                    //    data[tx, tz] = new Grass(new Vec2i(x * World.ChunkSize + tx + 1, z * World.ChunkSize + tz - 1));
                }
            }
        }

        //data[0, 0] = new Tree(new Vec2i(x * World.ChunkSize, z * World.ChunkSize));

        //data[2, 2] = new RockFormation(new Vec2i(x * World.ChunkSize + 2, z * World.ChunkSize + 2));


        Dictionary <int, WorldObjectData> data_ = new Dictionary <int, WorldObjectData>();

        for (int i = 0; i < World.ChunkSize; i++)
        {
            for (int j = 0; j < World.ChunkSize; j++)
            {
                if (data[i, j] != null)
                {
                    data_.Add(WorldObject.ObjectPositionHash(i, j), data[i, j]);
                }
            }
        }
        ChunkData cd = new ChunkData(x, z, tiles, true, baseHeight: cb.Height, heightMap: heights);

        cd.SetVoxelData(vox);
        return(cd);
    }
Ejemplo n.º 16
0
    /// <summary>
    /// Decides the placement of all tactical locations
    /// </summary>
    /// <param name="ktl"></param>
    private Dictionary <int, Dictionary <TacLocType, List <TacticalLocationShell> > > DecideAllTacticalLocationPlacements(Dictionary <int, KingdomTotalTactialLocations> ktl)
    {
        Dictionary <int, Dictionary <TacLocType, List <TacticalLocationShell> > > tactPlace = new Dictionary <int, Dictionary <TacLocType, List <TacticalLocationShell> > >();

        //Create data structure to hold tactical locations
        foreach (Kingdom k in GameGen.KingdomGen.Kingdoms)
        {
            tactPlace.Add(k.KingdomID, new Dictionary <TacLocType, List <TacticalLocationShell> >());
            tactPlace[k.KingdomID].Add(TacLocType.fort, new List <TacticalLocationShell>());
            tactPlace[k.KingdomID].Add(TacLocType.tower, new List <TacticalLocationShell>());
        }

        bool shouldContinue = true;

        while (shouldContinue)
        {
            //if no points remain, we break
            if (DesireWeightedGridpoints.Count == 0)
            {
                shouldContinue = false;
                break;
            }
            //We a random point
            GridPoint  gp        = DesireWeightedGridpoints.GetRandom(true);
            ChunkBase2 cb        = GameGen.TerGen.ChunkBases[gp.ChunkPos.x, gp.ChunkPos.z];
            int        kingdomID = cb.KingdomID;
            if (kingdomID == -1)
            {
                continue;
            }

            //We have now got to a valid settlement point so we check what type of settlement we need;

            TacLocType tactType = TacLocType.fort;
            if (tactPlace[kingdomID][TacLocType.fort].Count < ktl[kingdomID].FortCount)
            {
                tactType = TacLocType.fort;
            }
            else if (tactPlace[kingdomID][TacLocType.tower].Count < ktl[kingdomID].TowerCount)
            {
                tactType = TacLocType.tower;
            }
            else
            {
                Debug.Log("Already completed set placement for " + kingdomID);
                continue;
            }

            //Find the shorest distance
            int distSqr = FindShortestSquareDistance(tactPlace[kingdomID], gp);
            //the maximum distance
            int minDistSqr = GridPlacement.GridPointSize * GridPlacement.GridPointSize * 4;
            if (distSqr >= minDistSqr || distSqr < 0)
            {
                gp.HasTacLoc = true;
                gp.TACTYPE   = tactType;
                TacticalLocationShell tls = new TacticalLocationShell(gp, kingdomID, tactType);
                gp.Shell = tls;

                tactPlace[kingdomID][tactType].Add(tls);
            }
        }

        return(tactPlace);
    }
Ejemplo n.º 17
0
    /// <summary>
    /// Finds the tactical placement desirability
    /// </summary>
    /// <param name="gp"></param>
    /// <returns></returns>
    private float CalculateGridPointTacticalDesirability(GridPoint gp)
    {
        bool onBorder = false;
        bool onRiver  = false;
        bool onCoast  = false;
        bool onLake   = false;
        bool onHill   = false;


        //Get the chunk this grid point is on
        ChunkBase2 cb        = GameGen.TerGen.ChunkBases[gp.ChunkPos.x, gp.ChunkPos.z];
        int        kingdomID = cb.KingdomID;

        //If ocean, contains settlement, or belongs to no kingdom, then we do not use it
        if (cb.Biome == ChunkBiome.ocean || gp.HasSet || kingdomID == -1)
        {
            return(-1);
        }

        if (cb.Pos.QuickDistance(GameGen.TerGen.EvilDragonMountainPeak) < 128 * 128)
        {
            return(-1);
        }
        if (cb.Pos.QuickDistance(GameGen.TerGen.GoodDragonMountainPeak) < 64 * 64)
        {
            return(-1);
        }
        if (gp.Shell != null)
        {
            return(-1);
        }
        //we create an array, which holds the sum of all points, for each line in the 8 octangonal directions
        float[] sumSurroundingHeight = new float[8];
        //iterate away from search point
        for (int i = 1; i < GridPlacement.GridPointSize; i++)
        {
            int j = 0;
            //Search in 4 directions
            foreach (Vec2i v in Vec2i.OCT_DIRDIR)
            {
                //Find the point in this direction
                Vec2i p = cb.Pos + v * i;
                //Ensure in world bounds
                if (GameGenerator2.InBounds(p))
                {
                    //Get chunk here
                    ChunkBase2 cb_p = GameGen.TerGen.ChunkBases[p.x, p.z];
                    if (cb_p.Biome == ChunkBiome.ocean)
                    {
                        onCoast = true;
                    }
                    if (cb_p.KingdomID != -1 && cb_p.KingdomID != kingdomID)
                    {
                        onBorder = true;
                    }
                    if (cb_p.ChunkFeature is ChunkRiverNode)
                    {
                        onRiver = true;
                    }
                    //Sum total height
                    sumSurroundingHeight[j] += cb_p.Height;
                }
                j++;
            }
        }
        // Find chunk height, and create sum for surrounding heights

        float pointHeight        = cb.Height;
        float averageSurrounding = 0;

        //iterte each surrounding height sum, and divide by 31 to find average height in each direction
        for (int j = 0; j < 8; j++)
        {
            sumSurroundingHeight[j] /= 31f;

            //If the height is lower, we increase 'averageSurrounding' by the height difference
            if (sumSurroundingHeight[j] + 1 < pointHeight)
            {
                averageSurrounding += pointHeight - sumSurroundingHeight[j];
            }
            else if (sumSurroundingHeight[j] - 1 > pointHeight)
            {
                averageSurrounding += pointHeight - sumSurroundingHeight[j];
            }
        }
        float des = 5 + (onRiver ? 4f : 0) + (onCoast ? 3f : 0) - (onLake ? 2f : 0) + (onBorder ? 10 : 0) + (onHill ? 6 : 0);

        return(des);
    }
Ejemplo n.º 18
0
    // Start is called before the first frame update
    void Start()
    {
        TestMain.SetupTest();
        Player = TestMain.CreatePlayer(new Vector3(0, 0, 0));

        Kingdom king = new Kingdom("kingdom", new Vec2i(0, 0));

        World.Instance.AddKingdom(king);


        SettlementShell shell = new SettlementShell(new GridPoint(new Vec2i(0, 0), new Vec2i(0, 0)), 0, SettlementType.CAPITAL);

        bool[] entraceDir = new bool[8];
        entraceDir[0] = true;
        entraceDir[3] = true;
        // entraceDir[4] = true;
        // entraceDir[6] = true;
        SettlementGenerator2.LocationData ld = new SettlementGenerator2.LocationData()
        {
            OnRiver = false, OnBorder = false, OnLake = false, EntranceDirections = entraceDir
        };
        shell.SetLocationData(ld);

        int size = shell.Type.GetSize();

        ChunkBase2[,] bases = new ChunkBase2[size, size];
        for (int x = 0; x < size; x++)
        {
            for (int z = 0; z < size; z++)
            {
                bases[x, z] = new ChunkBase2(new Vec2i(x, z), WorldHeightChunk(x, z), ChunkBiome.grassland);
                if (z == 8)
                {
                    bases[x, z].SetChunkFeature(new ChunkRiverNode(new Vec2i(x, z)));
                }
            }
        }
        List <BuildingPlan> reqBuild = new List <BuildingPlan>()
        {
            Building.VEGFARM, Building.WHEATFARM, Building.VEGFARM, Building.WHEATFARM
        };

        shell.RequiredBuildings = reqBuild;
        shell.SetChunkBases(bases);
        Debug.BeginDeepProfile("Setgen");
        SettlementBuilder2 setB = new SettlementBuilder2(WorldHeight, shell);

        setB.Generate(new GenerationRandom(0));

        foreach (Building b in setB.Buildings)
        {
            if (b.BuildingSubworld != null)
            {
                World.Instance.AddSubworld(b.BuildingSubworld);
            }
        }

        Settlement set = new Settlement(king, "set", setB);

        World.Instance.AddLocation(set);
        EntityGenerator eg = new EntityGenerator(null, EntityManager.Instance);

        eg.GenerateAllKingdomEntities();
        SettlementWall = setB.GenerateWall();
        //wall = SettlementWall.WallPath.CalculateEvenlySpacedPoints(5, 1);
        Debug.EndDeepProfile("Setgen");

        /*
         * int seed = 0;
         * SettlementBuilder setB = new SettlementBuilder(WorldHeight, new SettlementBase(new Vec2i(9, 9), 8, SettlementType.CAPITAL));
         * setB.Generate(GameManager.RNG);
         *
         * Kingdom k = new Kingdom("king", new Vec2i(9, 9));
         * Settlement set = new Settlement(k, "set", setB);
         * k.AddSettlement(set);
         * KingdomNPCGenerator npcGen = new KingdomNPCGenerator(null, k, EntityManager.Instance);
         * npcGen.GenerateSettlementNPC(set);
         */


        List <ChunkData> chunks = setB.ToChunkData();

        Chunks = new ChunkData[20, 20];


        foreach (ChunkData cd in chunks)
        {
            if (cd == null)
            {
                continue;
            }

            Chunks[cd.X, cd.Z] = cd;

            EntityManager.Instance.LoadChunk(new Vec2i(cd.X, cd.Z));
        }

        SetChunks(Chunks);

        return;
    }
Ejemplo n.º 19
0
    private ChunkData GenerateLakeChunk(int x, int z, ChunkBase2 cb)
    {
        ChunkData cd = new ChunkData(x, z, (int[, ])OCEAN.Clone(), false);

        return(cd);
    }