ACR_Quest.RandomDungeon.RandomDungeon C# (CSharp) Метод

RandomDungeon() публичный Метод

public RandomDungeon ( string areaPrefix, int areasToGenerate, int cr, string name, CLRScriptBase script ) : ALFA.Shared
areaPrefix string
areasToGenerate int
cr int
name string
script CLRScriptFramework.CLRScriptBase
Результат ALFA.Shared
        public RandomDungeon(string areaPrefix, int areasToGenerate, int cr, string name, CLRScriptBase script)
        {
            CR = cr;
            DungeonStore.FindAvailableAreas(areaPrefix);

            List<RandomDungeonArea> sourceAreas = new List<RandomDungeonArea>();
            if (areasToGenerate > 1)
            {
                foreach (RandomDungeonArea area in DungeonStore.AvailableAreas[areaPrefix])
                {
                    if (area.AreaExits.Count <= areasToGenerate && area.AreaExits.Count > 1)
                    {
                        sourceAreas.Add(area);
                    }
                }
            }
            else
            {
                foreach (RandomDungeonArea area in DungeonStore.AvailableAreas[areaPrefix])
                {
                    if (area.AreaExits.Count == 1)
                    {
                        sourceAreas.Add(area);
                    }
                }
            }

            RandomDungeonArea template = sourceAreas[rnd.Next(sourceAreas.Count)];
            RandomDungeonArea toAdd = new RandomDungeonArea();
            toAdd.TemplateAreaId = template.AreaId;
            toAdd.DungeonName = name;
            toAdd.AreaExits = new List<ExitDirection>();
            toAdd.AreaExits.AddRange(template.AreaExits);
            toAdd.DungeonExit = toAdd.AreaExits[rnd.Next(toAdd.AreaExits.Count)];
            toAdd.AreaExits.Remove(toAdd.DungeonExit);
            toAdd.X = areasToGenerate + 1;
            toAdd.Y = areasToGenerate + 1;
            toAdd.Z = areasToGenerate + 1;
            toAdd.CR = cr;
            areasToGenerate -= toAdd.AreaExits.Count;
            areasToGenerate -= 1;
            AreasOfDungeon.Add(toAdd);

            List<RandomDungeonArea> areasNeedingAdjacentAreas = new List<RandomDungeonArea>();
            areasNeedingAdjacentAreas.Add(toAdd);

            while (areasNeedingAdjacentAreas.Count > 0)
            {
                // Randomly select one of our bare ends to build out from.
                RandomDungeonArea toExpand = areasNeedingAdjacentAreas[rnd.Next(areasNeedingAdjacentAreas.Count)];

                // Build a temporary collection of exit directions from this area, but
                // don't count the directions that already have adjacent areas.
                List<ExitDirection> NextAreaDirections = new List<ExitDirection>();
                NextAreaDirections.AddRange(toExpand.AreaExits);
                foreach(ExitDirection used in toExpand.AdjacentAreas.Keys)
                {
                    NextAreaDirections.Remove(used);
                }
                if(NextAreaDirections.Count == 0)
                {
                    // If that's all of the exits, then this area shouldn't actually be on the list
                    // of candidates to expand.
                    areasNeedingAdjacentAreas.Remove(toExpand);
                    continue;
                }

                // Pick a random direction out of those available and set the new area's coordinates
                // appropriately.
                ExitDirection nextAreaDirection = NextAreaDirections[rnd.Next(NextAreaDirections.Count)];
                toAdd = new RandomDungeonArea();
                _setAreaCoordinates(toExpand, toAdd, nextAreaDirection);

                // Scan for adjacent areas, and determine the necessary parts of the target area.
                Dictionary<ExitDirection, bool> necessaryBorders = new Dictionary<ExitDirection, bool>();
                Dictionary<ExitDirection, RandomDungeonArea> adjacentToBe = new Dictionary<ExitDirection, RandomDungeonArea>();
                _buildBorders(necessaryBorders, adjacentToBe, toAdd);


                // If we can't generate more areas, order the new areas to not open up any more exits that we'd have to
                // attach areas to. Future additions will just be attaching things to dangling ATs.
                if(areasToGenerate <= 0) _sealBorders(necessaryBorders);

                // Now that we know where the area is and what borders it has to maintain, we
                // loop through the areas that are available and build a list of all of the ones
                // that fit the restrictions of the area's location.
                sourceAreas.Clear();
                foreach(RandomDungeonArea area in DungeonStore.AvailableAreas[areaPrefix])
                {
                    bool areaUseful = true;
                    foreach(KeyValuePair<ExitDirection, bool> dir in necessaryBorders)
                    {
                        if(dir.Value)
                        {
                            if(!area.AreaExits.Contains(dir.Key)) areaUseful = false;
                        }
                        if(!dir.Value)
                        {
                            if(area.AreaExits.Contains(dir.Key)) areaUseful = false;
                        }
                        if(!areaUseful) break;
                    }
                    if(areaUseful) sourceAreas.Add(area);
                }

                if(sourceAreas.Count >= 1)
                {
                    // If we have more at least one area that fits the bill, we'll try to use that, so that
                    // the dungeon feels as connected and continuous as possible.
                    template = sourceAreas[rnd.Next(sourceAreas.Count)];
                    toAdd.TemplateAreaId = template.AreaId;
                    toAdd.DungeonName = name;
                    toAdd.AreaExits.AddRange(template.AreaExits);
                    toAdd.CR = cr;
                    foreach(KeyValuePair<ExitDirection, RandomDungeonArea> adj in adjacentToBe)
                    {
                        toAdd.AdjacentAreas.Add(adj.Key, adj.Value);
                        switch(adj.Key)
                        {
                            case ExitDirection.North:
                                adj.Value.AdjacentAreas.Add(ExitDirection.South, toAdd);
                                break;
                            case ExitDirection.South:
                                adj.Value.AdjacentAreas.Add(ExitDirection.North, toAdd);
                                break;
                            case ExitDirection.East:
                                adj.Value.AdjacentAreas.Add(ExitDirection.West, toAdd);
                                break;
                            case ExitDirection.West:
                                adj.Value.AdjacentAreas.Add(ExitDirection.East, toAdd);
                                break;
                            case ExitDirection.Up:
                                adj.Value.AdjacentAreas.Add(ExitDirection.Down, toAdd);
                                break;
                            case ExitDirection.Down:
                                adj.Value.AdjacentAreas.Add(ExitDirection.Up, toAdd);
                                break;
                        }
                    }
                    areasToGenerate -= (toAdd.AreaExits.Count - toAdd.AdjacentAreas.Count);
                    AreasOfDungeon.Add(toAdd);
                    areasNeedingAdjacentAreas.Add(toAdd);
                }
                else
                {
                    // But if no area fits the bill, we loop over each of the exits we're expecting and
                    // attach the dead end area with the appropriate exit to them.
                    foreach(KeyValuePair<ExitDirection, RandomDungeonArea> adj in adjacentToBe)
                    {
                        int X = toAdd.X;
                        int Y = toAdd.Y;
                        int Z = toAdd.Z;
                        switch(adj.Key)
                        {
                            case ExitDirection.North:
                                template = getSingleExitArea(ExitDirection.South, areaPrefix);
                                break;
                            case ExitDirection.South:
                                template = getSingleExitArea(ExitDirection.North, areaPrefix);
                                break;
                            case ExitDirection.East:
                                template = getSingleExitArea(ExitDirection.West, areaPrefix);
                                break;
                            case ExitDirection.West:
                                template = getSingleExitArea(ExitDirection.East, areaPrefix);
                                break;
                            case ExitDirection.Up:
                                template = getSingleExitArea(ExitDirection.Down, areaPrefix);
                                break;
                            case ExitDirection.Down:
                                template = getSingleExitArea(ExitDirection.Up, areaPrefix);
                                break;
                        }
                        toAdd = new RandomDungeonArea();
                        toAdd.X = X;
                        toAdd.Y = Y;
                        toAdd.Z = Z;
                        toAdd.TemplateAreaId = template.AreaId;
                        toAdd.DungeonName = name;
                        toAdd.AreaExits.AddRange(template.AreaExits);
                        toAdd.AdjacentAreas.Add(adj.Key, adj.Value);
                        switch(adj.Key)
                        {
                            case ExitDirection.North:
                                adj.Value.AdjacentAreas.Add(ExitDirection.South, toAdd);
                                break;
                            case ExitDirection.South:
                                adj.Value.AdjacentAreas.Add(ExitDirection.North, toAdd);
                                break;
                            case ExitDirection.East:
                                adj.Value.AdjacentAreas.Add(ExitDirection.West, toAdd);
                                break;
                            case ExitDirection.West:
                                adj.Value.AdjacentAreas.Add(ExitDirection.East, toAdd);
                                break;
                            case ExitDirection.Up:
                                adj.Value.AdjacentAreas.Add(ExitDirection.Down, toAdd);
                                break;
                            case ExitDirection.Down:
                                adj.Value.AdjacentAreas.Add(ExitDirection.Up, toAdd);
                                break;
                        }
                        areasToGenerate -= (toAdd.AreaExits.Count - toAdd.AdjacentAreas.Count);
                        AreasOfDungeon.Add(toAdd);
                        areasNeedingAdjacentAreas.Add(toAdd);
                    }
                }
            }
        }