Example #1
0
        public GenerationStats Clone()
        {
            GenerationStats newStats = new GenerationStats();

            newStats.MainPathRoomCount   = MainPathRoomCount;
            newStats.BranchPathRoomCount = BranchPathRoomCount;
            newStats.TotalRoomCount      = TotalRoomCount;
            newStats.MaxBranchDepth      = MaxBranchDepth;
            newStats.TotalRetries        = TotalRetries;

            newStats.PreProcessTime           = PreProcessTime;
            newStats.MainPathGenerationTime   = MainPathGenerationTime;
            newStats.BranchPathGenerationTime = BranchPathGenerationTime;
            newStats.PostProcessTime          = PostProcessTime;
            newStats.TotalTime = TotalTime;

            return(newStats);
        }
Example #2
0
 public DungeonGenerator()
 {
     GenerationStats = new GenerationStats();
 }
Example #3
0
        protected virtual IEnumerator InnerGenerate(bool isRetry)
        {
            if (isRetry)
            {
                ChosenSeed   = RandomStream.Next();
                RandomStream = new Random(ChosenSeed);


                if (retryCount >= MaxAttemptCount && Application.isEditor)
                {
                    string errorText = "Failed to generate the dungeon " + MaxAttemptCount + " times.\n" +
                                       "This could indicate a problem with the way the tiles are set up. Try to make sure most rooms have more than one doorway and that all doorways are easily accessible.\n" +
                                       "Here are a list of all reasons a tile placement had to be retried:";

                    foreach (var pair in tilePlacementResultCounters)
                    {
                        if (pair.Value > 0)
                        {
                            errorText += "\n" + pair.Key + " (x" + pair.Value + ")";
                        }
                    }

                    Debug.LogError(errorText);
                    ChangeStatus(GenerationStatus.Failed);
                    yield break;
                }

                retryCount++;
                GenerationStats.IncrementRetryCount();

                if (Retrying != null)
                {
                    Retrying();
                }
            }
            else
            {
                retryCount = 0;
                GenerationStats.Clear();
            }

            currentDungeon = Root.GetComponent <Dungeon>();
            if (currentDungeon == null)
            {
                currentDungeon = Root.AddComponent <Dungeon>();
            }

            currentDungeon.DebugRender = DebugRender;
            currentDungeon.PreGenerateDungeon(this);

            Clear(false);
            targetLength = Mathf.RoundToInt(DungeonFlow.Length.GetRandom(RandomStream) * LengthMultiplier);
            targetLength = Mathf.Max(targetLength, 2);

            // Tile Injection
            GenerationStats.BeginTime(GenerationStatus.TileInjection);

            if (tilesPendingInjection == null)
            {
                tilesPendingInjection = new List <InjectedTile>();
            }
            else
            {
                tilesPendingInjection.Clear();
            }

            injectedTiles.Clear();
            GatherTilesToInject();

            // Pre-Processing
            GenerationStats.BeginTime(GenerationStatus.PreProcessing);
            PreProcess();

            // Main Path Generation
            GenerationStats.BeginTime(GenerationStatus.MainPath);
            yield return(Wait(GenerateMainPath()));

            // We may have had to retry when generating the main path, if so, the status will be either Complete or Failed and we should exit here
            if (Status == GenerationStatus.Complete || Status == GenerationStatus.Failed)
            {
                yield break;
            }

            // Branch Paths Generation
            GenerationStats.BeginTime(GenerationStatus.Branching);
            yield return(Wait(GenerateBranchPaths()));

            // If there are any required tiles missing from the tile injection stage, the generation process should fail
            foreach (var tileInjection in tilesPendingInjection)
            {
                if (tileInjection.IsRequired)
                {
                    yield return(Wait(InnerGenerate(true)));

                    yield break;
                }
            }

            // We may have missed some required injected tiles and have had to retry, if so, the status will be either Complete or Failed and we should exit here
            if (Status == GenerationStatus.Complete || Status == GenerationStatus.Failed)
            {
                yield break;
            }

            // Post-Processing
            yield return(Wait(PostProcess()));


            // Waiting one frame so objects are in their expected state
            yield return(null);


            ChangeStatus(GenerationStatus.Complete);

            // Let DungenCharacters know that they should re-check the Tile they're in
            foreach (var character in Component.FindObjectsOfType <DungenCharacter>())
            {
                character.ForceRecheckTile();
            }
        }
Example #4
0
        protected virtual IEnumerator PostProcess()
        {
            // Waiting one frame so objects are in their expected state
            yield return(null);


            GenerationStats.BeginTime(GenerationStatus.PostProcessing);
            ChangeStatus(GenerationStatus.PostProcessing);

            // Order post-process steps by priority
            postProcessSteps.Sort((a, b) =>
            {
                return(b.Priority.CompareTo(a.Priority));
            });

            // Apply any post-process to be run BEFORE built-in post-processing is run
            foreach (var step in postProcessSteps)
            {
                if (ShouldSkipFrame(false))
                {
                    yield return(null);
                }

                if (step.Phase == PostProcessPhase.BeforeBuiltIn)
                {
                    step.PostProcessCallback(this);
                }
            }


            // Waiting one frame so objects are in their expected state
            yield return(null);

            foreach (var tile in currentDungeon.AllTiles)
            {
                tile.gameObject.SetActive(true);
            }

            int length = currentDungeon.MainPathTiles.Count;

            //
            // Need to sort list manually to avoid compilation problems on iOS
            int maxBranchDepth = 0;

            if (currentDungeon.BranchPathTiles.Count > 0)
            {
                List <Tile> branchTiles = currentDungeon.BranchPathTiles.ToList();
                branchTiles.Sort((a, b) =>
                {
                    return(b.Placement.BranchDepth.CompareTo(a.Placement.BranchDepth));
                }
                                 );

                maxBranchDepth = branchTiles[0].Placement.BranchDepth;
            }
            // End calculate max branch depth
            //

            if (!IsAnalysis)
            {
                ConnectOverlappingDoorways(DungeonFlow.DoorwayConnectionChance);

                foreach (var tile in currentDungeon.AllTiles)
                {
                    if (ShouldSkipFrame(false))
                    {
                        yield return(null);
                    }

                    tile.Placement.NormalizedPathDepth = tile.Placement.PathDepth / (float)(length - 1);
                    tile.Placement.ProcessDoorways(RandomStream);
                }

                currentDungeon.PostGenerateDungeon(this);

                if (DungeonFlow.KeyManager != null)
                {
                    PlaceLocksAndKeys();
                }

                // Process random props
                foreach (var tile in currentDungeon.AllTiles)
                {
                    foreach (var prop in tile.GetComponentsInChildren <RandomProp>())
                    {
                        if (ShouldSkipFrame(false))
                        {
                            yield return(null);
                        }

                        prop.Process(RandomStream, tile);
                    }
                }

                ProcessGlobalProps();
            }

            GenerationStats.SetRoomStatistics(currentDungeon.MainPathTiles.Count, currentDungeon.BranchPathTiles.Count, maxBranchDepth);
            ClearPreProcessData();


            // Waiting one frame so objects are in their expected state
            yield return(null);


            // Apply any post-process to be run AFTER built-in post-processing is run
            foreach (var step in postProcessSteps)
            {
                if (ShouldSkipFrame(false))
                {
                    yield return(null);
                }

                if (step.Phase == PostProcessPhase.AfterBuiltIn)
                {
                    step.PostProcessCallback(this);
                }
            }


            // Finalise
            GenerationStats.EndTime();

            // Activate all door gameobjects that were added to doorways
            foreach (var door in currentDungeon.Doors)
            {
                if (door != null)
                {
                    door.SetActive(true);
                }
            }
        }