private Dictionary <Vec2i, ChunkStructure> GenerateElementalDungeonEntranceStructures()
    {
        Dictionary <Vec2i, ChunkStructure> elDunShells = new Dictionary <Vec2i, ChunkStructure>();

        //iterate all counts
        for (int i = 0; i < 4; i++)
        {
            //We make5 attempts to find a valid place for each bandit camp
            for (int a = 0; a < 5; a++)
            {
                //Generate random position and size
                Vec2i position = GenerationRandom.RandomFromList(GameGenerator.TerrainGenerator.LandChunks);
                Vec2i size     = GenerationRandom.RandomVec2i(1, 3);
                //Check if position is valid,
                if (IsPositionValid(position))
                {
                    //if valid, we add the structure to ChunkBases and to the dictionary of shells
                    ChunkStructure banditCampShell = new BanditCamp(position, size);
                    for (int x = 0; x < size.x; x++)
                    {
                        for (int z = 0; z < size.z; z++)
                        {
                            GameGenerator.TerrainGenerator.ChunkBases[position.x + x, position.z + z].AddChunkStructure(banditCampShell);
                        }
                    }
                    elDunShells.Add(position, banditCampShell);
                }
            }
        }
        return(elDunShells);
    }
示例#2
0
    /// Get functions for settlement and chunk structures
    #region ordered_gets
    /// <summary>
    /// Searches all settlements to find a random one within 'allowedDistance' regions
    /// of the defined position.
    /// </summary>
    /// <param name="centrePoint"></param>
    /// <param name="allowedDistance"></param>
    /// <returns></returns>
    private Settlement GetRandomSettlement(Vec2i centrePoint, int allowedDistance)
    {
        //We first collect all regions close to the required region
        List <Vec2i> allowedRegions = new List <Vec2i>();

        for (int x = -allowedDistance; x <= allowedDistance; x++)
        {
            for (int z = -allowedDistance; z <= allowedDistance; z++)
            {
                allowedRegions.Add(centrePoint + new Vec2i(x, z));
            }
        }

        //Keep running loop until a valid settlement is found
        bool isValid = false;

        while (!isValid)
        {
            //Choose random region
            Vec2i reg = GenRan.RandomFromList(allowedRegions);
            //If the selected region contains at least one settlment, randomly select one
            if (OrderedSettlements.ContainsKey(reg) && OrderedSettlements[reg].Count > 0)
            {
                return(GenRan.RandomFromList(OrderedSettlements[reg]));
            }
            else
            {
                //If no settlements, remove it from the list of allowed regions
                //to prevent selecting it twice
                allowedRegions.Remove(reg);
            }
        }
        return(null);
    }
示例#3
0
    public Vec2i FindSpace(Kingdom kingdom, int size)
    {
        int attempts = 0;

        while (attempts < 20)
        {
            Vec2i v = null;
            if (kingdom == null)
            {
                v = GenerationRandom.RandomFromList(GameGenerator.TerrainGenerator.LandChunks);
            }
            else
            {
                v = GenerationRandom.RandomFromList(KingdomChunks[kingdom]);
            }
            bool canDo = true;
            //Check point allows settlement within bounds
            if (v.x - size < 0 || v.x + size > World.WorldSize - 1 || v.z - size < 0 || v.z + size > World.WorldSize - 1)
            {
                canDo = false;
            }
            else
            {
                for (int x = -size; x <= size; x++)
                {
                    for (int z = -size; z <= size; z++)
                    {
                        int       cx = x + v.x;
                        int       cz = z + v.z;
                        ChunkBase cb = TerrainGenerator.ChunkBases[cx, cz];
                        if (cb.Kingdom != kingdom || cb.HasSettlement || !cb.IsLand)
                        {
                            canDo = false;
                        }
                        else if (cb.RiverNode != null || cb.Lake != null)
                        {
                            canDo = false;
                        }

                        /*
                         * else if (TerrainGenerator.ChunkBases[Mathf.Clamp(x + v.x, 0, World.WorldSize - 1), Mathf.Clamp(z + v.z, 0, World.WorldSize - 1)].Kingdom != kingdom)
                         *  canDo = false;
                         * else if (TerrainGenerator.ChunkBases[Mathf.Clamp(x + v.x, 0, World.WorldSize - 1), Mathf.Clamp(z + v.z, 0, World.WorldSize - 1)].Settlement != null)
                         *  canDo = false;
                         * else if (!TerrainGenerator.ChunkBases[Mathf.Clamp(x + v.x, 0, World.WorldSize - 1), Mathf.Clamp(z + v.z, 0, World.WorldSize - 1)].IsLand)
                         *  canDo = false;
                         */
                    }
                }
            }
            if (canDo)
            {
                return(v);
            }
            attempts++;
        }

        return(null);
    }
    private Vec2i ChooseValidChunk()
    {
        Vec2i pos = GenRan.RandomFromList(GameGenerator.TerrainGenerator.LandChunks);

        while (!IsPositionValid(pos))
        {
            pos = GenRan.RandomFromList(GameGenerator.TerrainGenerator.LandChunks);
        }
        return(pos);
    }
    private River GenerateRiver(Vec2i start, Vec2i mainDirection, GenerationRandom genRan)
    {
        bool  shouldStop = false;
        River r          = new River();

        r.SetFirstChunk(start, 5);
        List <Vec2i> directions = new List <Vec2i>();

        directions.Add(mainDirection);
        directions.Add(mainDirection);
        directions.Add(mainDirection);
        directions.Add(mainDirection);
        directions.AddRange(PerpDir(mainDirection));
        Vec2i last = start;

        while (!shouldStop)
        {
            Vec2i next = last + genRan.RandomFromList <Vec2i>(directions);
            if (r.AddChunk(next, 5))
            {
                last = next;
                if (next.x < 0 || next.z < 0 || next.x >= World.WorldSize || next.z >= World.WorldSize)
                {
                    shouldStop = true;
                }
                else if (!GameGenerator.TerrainGenerator.ChunkBases[next.x, next.z].IsLand)
                {
                    shouldStop = true;
                }
            }
        }

        return(r);
    }
    public GridPoint GetFreeGridPoint(int clearance, int attempts = 5)
    {
        if (attempts == -1)
        {
            return(null);
        }
        attempts--;
        GridPoint testPoint = GenRan.RandomFromList(FreePoints);

        for (int x = -clearance; x <= clearance; x++)
        {
            for (int z = -clearance; z <= clearance; z++)
            {
                Vec2i p = testPoint.GridPos + new Vec2i(x, z);
                if (GridPlacement.InGridBounds(p))
                {
                    GridPoint gp = GameGen.GridPlacement.GridPoints[p.x, p.z];
                    if (gp == null)
                    {
                        continue;
                    }
                    if (gp.HasNonSettlementStructure)
                    {
                        return(GetFreeGridPoint(clearance, attempts));
                    }
                }
            }
        }
        FreePoints.Remove(testPoint);
        testPoint.HasNonSettlementStructure = true;
        return(testPoint);
    }
示例#7
0
 public Entity ChooseRandomEntity(GenerationRandom ran = null)
 {
     Debug.Log(AllEntities.Count);
     if (ran == null)
     {
         return(GameManager.RNG.RandomFromList(AllEntities));
     }
     return(ran.RandomFromList(AllEntities));
 }
示例#8
0
    public SettlementPathNode CreatePathFromNode(SettlementPathNode node, int width, bool extraLength = false, int chosenDirection = -1, int length = -1)
    {
        //If no direction is given, choose a null one
        if (chosenDirection == -1)
        {
            List <int> nullDirection = new List <int>();
            for (int i = 0; i < 4; i++)
            {
                if (node.Connected[i] == null)
                {
                    nullDirection.Add(i);
                }
            }
            Debug.Log(nullDirection.Count);
            //Choose a valid direction and find the vector step
            chosenDirection = GenerationRandom.RandomFromList(nullDirection);
        }

        Vec2i step = SettlementPathNode.GetDirection(chosenDirection);

        //If no length is given or given length is invalid, choose a path length
        if (length == -1 || !InBounds(node.Position + step * length))
        {
            int attemptLength = length == -1 ? GenerationRandom.RandomInt(40, TileSize) : length;
            while (!InBounds(node.Position + step * attemptLength))
            {
                attemptLength -= 1;
            }

            length = attemptLength;
        }
        int   halfWidth     = width / 2;
        Vec2i perpDirection = SettlementPathNode.GetPerpendicular(chosenDirection);

        if (extraLength)
        {
            length += halfWidth;
        }
        for (int l = 0; l < length; l++)
        {
            for (int w = -halfWidth; w <= halfWidth; w++)
            {
                Vec2i pos = node.Position + step * l + perpDirection * w;
                SetTile(pos.x, pos.z, Tile.TEST_BLUE);
            }
        }
        SettlementPathNode endNode = new SettlementPathNode(node.Position + step * length);

        node.AddConnection(chosenDirection, endNode);
        endNode.AddConnection(SettlementPathNode.OppositeDirection(chosenDirection), node);
        return(endNode);
    }
示例#9
0
    /// <summary>
    /// Decides the tile placement in settlement coordinates of all entrances, based on
    /// the entrance direction data <see cref="Shell.LocationData"/>
    /// </summary>
    /// <returns></returns>
    private Vec2i DecideSettlementEntrance()
    {
        List <Vec2i> entrances = new List <Vec2i>();

        for (int i = 0; i < 8; i += 2)
        {
            int ip1 = (i + 1) % 8;

            if (Shell.LocationData.EntranceDirections[i] || Shell.LocationData.EntranceDirections[ip1])
            {
                Vec2i side = Vec2i.QUAD_DIR[i / 2];

                float xAmount = GenerationRandom.Random(0.8f, 0.95f) * side.x;
                float zAmount = GenerationRandom.Random(0.8f, 0.95f) * side.z;
                Vec2i pos     = Middle + new Vec2i((int)(xAmount * TileSize / 2), (int)(zAmount * TileSize / 2));
                entrances.Add(pos);
            }
        }

        return(GenerationRandom.RandomFromList(entrances));
    }
示例#10
0
    /// <summary>
    /// Places the dungeon key in a random structure.
    ///
    /// </summary>
    /// <param name="dungeonPos"></param>
    /// <param name="chunkStructure"></param>
    /// <param name="endTasks"></param>
    /// <returns></returns>
    private Quest GenerateDungeonKeyQuest_RandomStructure(Vec2i dungeonPos, Dungeon dungeon, List <QuestTask> endTasks)
    {
        //Find a random chunk structure
        ChunkStructure ranStruct = GetRandomFreeStructure(dungeonPos, 3);

        if (ranStruct == null)
        {
            throw new System.Exception("We need to fix this");
        }
        //We add the dungeon key to the loot chest of this structure
        ranStruct.FinalLootChest.GetInventory().AddItem(dungeon.GetKey());
        //Add the item finding task


        endTasks.Add(new QuestTask("Go to " + ranStruct.Name + " and collect the key", QuestTask.QuestTaskType.PICK_UP_ITEM,
                                   new object[] { dungeon.GetKey(), ranStruct.WorldMapLocation, (ranStruct.FinalLootChest as WorldObjectData).WorldPosition }));

        //Quest initiator will be a random entity
        //Therefore, we choose a random settlement
        Settlement set = GetRandomSettlement(dungeonPos, 5);
        //Then take a random npc from it.
        NPC            npc       = GameManager.EntityManager.GetEntityFromID(GenRan.RandomFromList(set.SettlementNPCIDs)) as NPC;
        QuestInitiator questInit = new QuestInitiator(QuestInitiator.InitiationType.TALK_TO_NPC, new object[] { npc, false });



        //We now reverse the tasks to get in correct order
        endTasks.Reverse();
        Quest quest = new Quest("Clear dungeon " + questCount, questInit, endTasks.ToArray(), QuestType.clear_dungeon);



        if (npc.Dialog == null)
        {
            NPCDialog dialog = new NPCDialog(npc, "Hello adventurer! How can I help you today?");

            NPCDialogNode exitNode = new NPCDialogNode("Don't worry, I'll be on my way", "");
            exitNode.IsExitNode = true;

            dialog.AddNode(exitNode);
            npc.SetDialog(dialog);
        }
        NPCDialogNode startQuestNode = new NPCDialogNode("Have you heard of any quests for an adventurer such as myself?", "I've heard of a dungeon that may be full of sweet shit." +
                                                         " It's probably locked though, last I heard the key was at " + ranStruct.Name);

        NPCDialogNode exitNode2 = new NPCDialogNode("Thanks! I'll be on my way", "");

        exitNode2.IsExitNode = true;
        startQuestNode.AddNode(exitNode2);
        npc.Dialog.AddNode(startQuestNode);

        startQuestNode.SetOnSelectFunction(() => {
            GameManager.QuestManager.StartQuest(quest);
        });
        startQuestNode.SetShouldDisplayFunction(() =>
        {
            if (GameManager.QuestManager.Unstarted.Contains(quest))
            {
                return(true);
            }
            return(false);
        });


        NPCDialogNode questRewardNode = new NPCDialogNode("I killed " + dungeon.Boss.Name, "I didn't think it was possible. Here, take this as a reward");

        questRewardNode.AddNode(exitNode2);
        questRewardNode.SetShouldDisplayFunction(() => {
            return(GameManager.QuestManager.Completed.Contains(quest));
        });
        questRewardNode.SetOnSelectFunction(() =>
        {
            Inventory playerInv = GameManager.PlayerManager.Player.Inventory;
            playerInv.AddItem(new SteelLongSword());
        });
        npc.Dialog.AddNode(questRewardNode);

        return(quest);
    }
    private void ClaimChunks(Kingdom[] kings)
    {
        int[,] claimedChunkKingdomIDs = new int[World.WorldSize, World.WorldSize];
        bool[,] obstruction           = new bool[World.WorldSize, World.WorldSize];

        for (int x = 0; x < World.WorldSize; x++)
        {
            for (int z = 0; z < World.WorldSize; z++)
            {
                claimedChunkKingdomIDs[x, z] = -1;
                if (GameGen.TerGen.ChunkBases[x, z].Biome is ChunkBiome.ocean)
                {
                    obstruction[x, z] = true;
                }
                else if (GameGen.TerGen.ChunkBases[x, z].ChunkFeature is ChunkRiverNode)
                {
                    obstruction[x, z] = true;
                }
                //else if (GameGen.TerGen.EvilDragonMountainPeak.QuickDistance(new Vec2i(x, z)) < 128 * 128)
                //    obstruction[x, z] = true;
            }
        }

        Dictionary <Kingdom, List <Vec2i> > freeBorder = new Dictionary <Kingdom, List <Vec2i> >();

        foreach (Kingdom k in kings)
        {
            ClaimedChunks.Add(k, new List <Vec2i>(250000));
            ClaimedChunks[k].Add(k.CapitalChunk);
            freeBorder.Add(k, new List <Vec2i>(2000));
            freeBorder[k].Add(k.CapitalChunk);
        }

        bool shouldRun = true;

        while (shouldRun)
        {
            shouldRun = false;
            foreach (Kingdom k in kings)
            {
                if (freeBorder[k].Count == 0)
                {
                    continue;
                }
                shouldRun = true;
                //We randomly select a border point and remove it from the list
                Vec2i curBorder = GenRan.RandomFromList(freeBorder[k]);
                freeBorder[k].Remove(curBorder);

                foreach (Vec2i v in Vec2i.QUAD_DIR)
                {
                    //We iterate all 8 surrounding chunks
                    Vec2i p = curBorder + v;

                    //if there is an obstruction we cannot claim the chunk
                    if (obstruction[p.x, p.z])
                    {
                        continue;
                    }
                    if (claimedChunkKingdomIDs[p.x, p.z] == -1)
                    {
                        claimedChunkKingdomIDs[p.x, p.z] = k.KingdomID;
                        freeBorder[k].Add(p);
                        ClaimedChunks[k].Add(p);
                    }
                }
            }
        }

        foreach (Kingdom k in Kingdoms)
        {
            k.ClaimedChunks = ClaimedChunks[k];
        }
        for (int x = 0; x < World.WorldSize; x++)
        {
            for (int z = 0; z < World.WorldSize; z++)
            {
                GameGen.TerGen.ChunkBases[x, z].KingdomID = claimedChunkKingdomIDs[x, z];
            }
        }
        return;
    }
示例#12
0
    /*
     * private void FromRiverSource(Vec2i source, Vec2i mainDir)
     * {
     *
     *  int i = 0;
     *  Vec2i end = null;
     *  Vec2i current = source;
     *  //Ray cast from the source to find the ocean point at this rivers end
     *  while(end == null)
     *  {
     *      i++;
     *      current += mainDir;
     *      if(ChunkBases[current.x, current.z].Biome == ChunkBiome.ocean)
     *      {
     *          end = current;
     *      }
     *      if (i > World.WorldSize)
     *          return;
     *
     *  }
     *  i = 0;
     *
     *  Vec2i last = source;
     *
     *  current = source + mainDir;
     *  bool isDone = false;
     *
     *  Vector2 lastDir = (end - current).AsVector2().normalized;
     *  Vector2 exactCurrent = current.AsVector2();
     *
     *  List<Vec2i> river = new List<Vec2i>();
     *
     *  while (!isDone)
     *  {
     *
     *
     *
     *      i++;
     *      // Vector2 currentFlow = FlowField[current.x, current.z];
     *
     *      float fx = PerlinNoise(current.x, current.z, 36)*2 - 1;
     *      float fz = PerlinNoise(current.x, current.z, 37)*2 - 1;
     *      Vector2 noiseFlow = new Vector2(fx, fz);
     *      Vector2 flowField = FlowField[current.x, current.z];
     *      Vector2 targetFlow = (end - current).AsVector2().normalized;
     *
     *      Vector2 flow = (noiseFlow + 4 * targetFlow + 3 * flowField).normalized;
     *      exactCurrent += flow;
     *      current = Vec2i.FromVector2(exactCurrent);
     *      int check = Mathf.Min(river.Count, 5);
     *      bool isValid = true;
     *      for(int j=0; j< check; j++)
     *      {
     *          if (river[river.Count - j - 1] == current)
     *              isValid = false;
     *      }
     *      if (!isValid)
     *      {
     *          current += mainDir;
     *          exactCurrent = current.AsVector2();
     *      }
     *
     *
     *      if (ChunkBases[current.x, current.z].Biome == ChunkBiome.ocean)
     *          isDone = true;
     *      ChunkBases[current.x, current.z].SetChunkFeature(new ChunkRiverNode());
     *      river.Add(current);
     *      if (i > 2048)
     *          return;
     *
     *  }
     *
     *
     * }*/


    private void ReverseFlowRiver(Vec2i start, int length, int distSinceFork = 0)
    {
        //Give rivers a slight biase towards the middle of the map
        Vector2 bias = -(new Vector2(World.WorldSize / 2, World.WorldSize / 2) - start.AsVector2()).normalized;


        Vec2i            current         = start;
        Vector2          fullCurrent     = current.AsVector2();
        Vec2i            last            = Vec2i.FromVector2(fullCurrent + bias);
        List <FlowPoint> inputFlowPoints = new List <FlowPoint>(5);

        for (int i = 0; i < length; i++)
        {
            distSinceFork++;
            inputFlowPoints.Clear();
            //if this chunk is a river node already, we have reached the end of this river branch
            if (ChunkBases[current.x, current.z].ChunkFeature is ChunkRiverNode)
            {
                //return;
            }

            //Add a river node here
            ChunkBases[current.x, current.z].SetChunkFeature(new ChunkRiverNode(current));

            //We iterate each of the near chunks
            foreach (Vec2i v in Vec2i.OCT_DIRDIR)
            {
                //Coordinate of point of interest
                Vec2i p = v + current;
                //If this is the point we just came from, ignore it
                if (last == p)
                {
                    continue;
                }
                Vector2 vFlow = FlowField[p.x, p.z];
                //Find the coordinate that this point flows into
                Vec2i pointFlowPos = Vec2i.FromVector2(p.AsVector2() + vFlow);

                //Check if this point flows into our current point
                if (pointFlowPos == current)
                {
                    FlowPoint fp = new FlowPoint();
                    fp.Pos = p;
                    fp.Dir = vFlow;
                    inputFlowPoints.Add(fp);
                }
            }
            //If no points flow here, then the river has reached an end (add lakes?)
            if (inputFlowPoints.Count == 0)
            {
                Debug.Log("zero flow");
                Vector2 currentToLast = (current - last).AsVector2();
                fullCurrent = fullCurrent - currentToLast;
                //Debug.Log("zero error...");
                //return;
            }
            else if (inputFlowPoints.Count == 1)
            {
                Debug.Log("single flow");
                fullCurrent = fullCurrent - inputFlowPoints[0].Dir;
            }
            else
            {
                if (distSinceFork < 40)
                {
                    fullCurrent = fullCurrent - GenRan.RandomFromList(inputFlowPoints).Dir;
                    Debug.Log("No fork - dist");
                }
                else
                {
                    Debug.Log("fork");
                    //If we are over 40, then we can create a fork

                    //only 2 forks maximum
                    while (inputFlowPoints.Count > 2)
                    {
                        inputFlowPoints.RemoveAt(GenRan.RandomInt(0, inputFlowPoints.Count));
                    }
                    ReverseFlowRiver(inputFlowPoints[0].Pos, length - i, 0);
                    ReverseFlowRiver(inputFlowPoints[1].Pos, length - i, 0);
                    Debug.Log("forks");
                    return;
                }
            }
            last    = new Vec2i(current.x, current.z);
            current = Vec2i.FromVector2(fullCurrent);

            /*
             * //We iterate all directions
             * Vector2 grad = (FlowField[current.x, current.z] + 0.1f * bias).normalized;
             * fullCurrent = fullCurrent - grad;
             * current = Vec2i.FromVector2(fullCurrent);
             */
        }
    }