diff --git a/DunGenPlus/DunGenPlus/API.cs b/DunGenPlus/DunGenPlus/API.cs index cb2967b..7e38ee4 100644 --- a/DunGenPlus/DunGenPlus/API.cs +++ b/DunGenPlus/DunGenPlus/API.cs @@ -9,7 +9,6 @@ using DunGen.Graph; using DunGenPlus.Generation; using LethalLevelLoader; using UnityEngine; -using static DunGenPlus.Components.DoorwayCleanupScripting.DCSConnectorBlockerSpawnedPrefab; namespace DunGenPlus { @@ -137,5 +136,9 @@ namespace DunGenPlus DunGenPlusGenerator.AddTileToMainPathDictionary(dictionary); } + public static bool IsDevDebugModeActive(){ + return DevTools.DevDebugManager.IsActive; + } + } } diff --git a/DunGenPlus/DunGenPlus/Components/Scrap/RandomGuaranteedScrapSpawn.cs b/DunGenPlus/DunGenPlus/Components/Scrap/RandomGuaranteedScrapSpawn.cs index 3d86202..89e239e 100644 --- a/DunGenPlus/DunGenPlus/Components/Scrap/RandomGuaranteedScrapSpawn.cs +++ b/DunGenPlus/DunGenPlus/Components/Scrap/RandomGuaranteedScrapSpawn.cs @@ -15,21 +15,42 @@ namespace DunGenPlus.Components.Scrap { public float spawnChance = 1f; [Tooltip("Minimum scrap value of the scrap item.")] public int minimumScrapValue = 0; + [Tooltip("Maximum scrap value of the scrap item.")] + public int maximumScrapValue = 100; + [Tooltip("Forces this item in particular to spawn. Overrides min/max scrap values")] + public string specificScrapTarget; - internal static Dictionary> scrapItemRarityCache; + internal static Dictionary<(int, int), IEnumerable> scrapItemRarityValueCache; + internal static Dictionary> scrapItemRarityNameCache; internal static void ResetCache(){ - scrapItemRarityCache = new Dictionary>(); + scrapItemRarityValueCache = new Dictionary<(int, int), IEnumerable>(); + scrapItemRarityNameCache = new Dictionary>(); } - internal static IEnumerable GetCachedItemList(List allMoonItems, int scrapValue) { - if (!scrapItemRarityCache.TryGetValue(scrapValue, out var list)){ - list = allMoonItems.Where(i => i.spawnableItem.minValue >= scrapValue).ToArray(); - scrapItemRarityCache.Add(scrapValue, list); + internal static IEnumerable GetCachedItemList(List allMoonItems, int minScrapValue, int maxScrapValue) { + var pair = (minScrapValue, maxScrapValue); + if (!scrapItemRarityValueCache.TryGetValue(pair, out var list)){ + list = allMoonItems.Where(i => i.spawnableItem.minValue >= minScrapValue && maxScrapValue <= i.spawnableItem.minValue).ToArray(); + scrapItemRarityValueCache.Add(pair, list); } return list; } + internal static IEnumerable GetCachedItemList(List allMoonItems, string scrapName) { + scrapName = scrapName.ToLowerInvariant(); + if (!scrapItemRarityNameCache.TryGetValue(scrapName, out var list)){ + list = allMoonItems.Where(i => i.spawnableItem.name.ToLowerInvariant().Contains(scrapName) || i.spawnableItem.itemName.ToLowerInvariant().Contains(scrapName)).ToArray(); + scrapItemRarityNameCache.Add(scrapName, list); + } + return list; + } + + internal IEnumerable GetCachedItemList(List allMoonItems) { + if (string.IsNullOrWhiteSpace(specificScrapTarget)) return GetCachedItemList(allMoonItems, minimumScrapValue, maximumScrapValue); + return GetCachedItemList(allMoonItems, specificScrapTarget); + } + internal static Item GetRandomItem(IEnumerable list) { var weightList = new int[list.Count()]; for(var i = 0; i < weightList.Length; ++i) { @@ -45,7 +66,7 @@ namespace DunGenPlus.Components.Scrap { var anomalyRandom = roundManager.AnomalyRandom; if (anomalyRandom.NextDouble() >= spawnChance) return (null, 0); - var itemList = GetCachedItemList(allMoonItems, minimumScrapValue); + var itemList = GetCachedItemList(allMoonItems); var itemListCount = itemList.Count(); if (itemListCount == 0) return (null, 0); diff --git a/DunGenPlus/DunGenPlus/DevTools/DevDebugManager.cs b/DunGenPlus/DunGenPlus/DevTools/DevDebugManager.cs index 8391995..8e5ddc3 100644 --- a/DunGenPlus/DunGenPlus/DevTools/DevDebugManager.cs +++ b/DunGenPlus/DunGenPlus/DevTools/DevDebugManager.cs @@ -85,6 +85,7 @@ namespace DunGenPlus.DevTools { MainPanel.Instance = null; DunFlowPanel.Instance = null; DunGenPlusPanel.Instance = null; + AssetsPanel.Instance = null; Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false; diff --git a/DunGenPlus/DunGenPlus/DunGenPlus/DunGenPlus.dll b/DunGenPlus/DunGenPlus/DunGenPlus/DunGenPlus.dll index 52c55cb..2de848f 100644 Binary files a/DunGenPlus/DunGenPlus/DunGenPlus/DunGenPlus.dll and b/DunGenPlus/DunGenPlus/DunGenPlus/DunGenPlus.dll differ diff --git a/DunGenPlus/DunGenPlus/Generation/DunGenPlusGenerator.cs b/DunGenPlus/DunGenPlus/Generation/DunGenPlusGenerator.cs index e62f5ba..7808781 100644 --- a/DunGenPlus/DunGenPlus/Generation/DunGenPlusGenerator.cs +++ b/DunGenPlus/DunGenPlus/Generation/DunGenPlusGenerator.cs @@ -261,22 +261,8 @@ namespace DunGenPlus.Generation { var tileProxy = gen.AddTile(previousTile, useableTileSets, lineDepthRatio, archetype, TilePlacementResult.None); - if (tileProxy == null) { - var prevName = previousTile != null ? previousTile.Prefab.name : "NULL"; - var archetypeName = archetype ? archetype.name : "NULL"; - var tileSetNames = string.Join(", ", useableTileSets); - Plugin.logger.LogDebug($"Alt. main branch gen failed at Branch {b} (Length: {t}, Ratio: {lineDepthRatio})"); - Plugin.logger.LogDebug($"Prev tile: {prevName}\nArchetype: {archetypeName}\nTilesets: {tileSetNames}"); - Plugin.logger.LogDebug($"Reason: {DungeonGeneratorPatch.lastTilePlacementResult}"); - - if (previousTile != null) { - var availableDoorways = string.Join(",", previousTile.UnusedDoorways); - var usedDoorways = string.Join(",", previousTile.UsedDoorways); - - Plugin.logger.LogDebug($"Available Doorways: {availableDoorways}"); - Plugin.logger.LogDebug($"Used Doorways: {usedDoorways}"); - } - + if (tileProxy == null) { + PrintAddTileError(gen, previousTile, archetype, useableTileSets, b + 1, t, lineDepthRatio); yield return gen.Wait(gen.InnerGenerate(true)); yield break; } @@ -341,6 +327,42 @@ namespace DunGenPlus.Generation { AddForcedTiles(gen); } + public static void PrintAddTileError(DungeonGenerator gen, TileProxy previousTile, DungeonArchetype archetype, IEnumerable useableTileSets, int branchId, int lineLength, float lineRatio){ + + var prevName = previousTile != null ? previousTile.Prefab.name : "NULL"; + var archetypeName = archetype ? archetype.name : "NULL"; + var tileSetNames = string.Join(", ", useableTileSets); + + var stringList = new List(); + stringList.Add($"Main branch gen failed at Branch {branchId} (Length: {lineLength}, Ratio: {lineRatio})"); + stringList.Add($"Prev tile: {prevName}"); + stringList.Add($"Archetype: {archetypeName}"); + stringList.Add($"Tilesets: {tileSetNames}"); + stringList.Add($"Reason: {DungeonGeneratorPatch.lastTilePlacementResult}"); + + if (previousTile != null) { + var availableDoorways = string.Join(", ", previousTile.UnusedDoorways.Select(d => d.DoorwayComponent.gameObject.name)); + var usedDoorways = string.Join(", ", previousTile.UsedDoorways.Select(d => d.DoorwayComponent.gameObject.name)); + + stringList.Add($"Available Doorways: {availableDoorways}"); + stringList.Add($"Used Doorways: {usedDoorways}"); + + if (API.IsDevDebugModeActive()){ + var allTiles = GetDoorwayPairs(gen, previousTile, useableTileSets, archetype, lineRatio); + var uniqueTiles = string.Join(", ", allTiles.Select(t => t.NextTemplate.Prefab).Distinct().Select(d => d.name)); + + stringList.Add($"Next Possible Tiles: {uniqueTiles}"); + } + } + + stringList.Add(string.Empty); + Plugin.logger.LogDebug(string.Join("\n", stringList)); + } + + public static void PrintAddTileErrorQuick(DungeonGenerator gen, int lineLength){ + PrintAddTileError(gen, DungeonGeneratorPatch.lastAttachTo, DungeonGeneratorPatch.lastArchetype, DungeonGeneratorPatch.lastUseableTileSets, 0, lineLength, DungeonGeneratorPatch.lastNormalizedDepth); + } + private static IEnumerator GenerateBranchPaths(DungeonGenerator gen, TileProxy mainRoom, string message, LogLevel logLevel){ Plugin.logger.Log(logLevel, $"Switching to default dungeon branch generation: {message}"); diff --git a/DunGenPlus/DunGenPlus/Generation/DunGenPlusGeneratorBranchLoop.cs b/DunGenPlus/DunGenPlus/Generation/DunGenPlusGeneratorBranchLoop.cs index 20bef46..3b7ba32 100644 --- a/DunGenPlus/DunGenPlus/Generation/DunGenPlusGeneratorBranchLoop.cs +++ b/DunGenPlus/DunGenPlus/Generation/DunGenPlusGeneratorBranchLoop.cs @@ -232,6 +232,34 @@ namespace DunGenPlus.Generation collection = useableTileSets.SelectMany(t => t.TileWeights.Weights); } + DoorwayPairStopwatch.Reset(); + DoorwayPairStopwatch.Start(); + var doorwayPairs = GetDoorwayPairs(gen, attachTo, collection, archetype, normalizedDepth); + DoorwayPairStopwatch.Stop(); + DoorwayPairTime += (float)DoorwayPairStopwatch.Elapsed.TotalMilliseconds; + + var tilePlacementResult = new TilePlacementResultProxy(TilePlacementResult.NoValidTile); + while(doorwayPairs.Count > 0) { + var pair = doorwayPairs.Dequeue(); + tilePlacementResult = TryPlaceTileResult(gen, pathProxy, pair, archetype); + if (tilePlacementResult.result == TilePlacementResult.None) break; + } + + if (tilePlacementResult.result == TilePlacementResult.None){ + if (injectedTile != null) { + var tileProxy = tilePlacementResult.tileProxy; + tileProxy.Placement.InjectionData = injectedTile; + pathProxy.injectedTiles[tileProxy] = injectedTile; + pathProxy.tilesPendingInjection.RemoveAt(index); + } + return tilePlacementResult; + } + + return new TilePlacementResultProxy(TilePlacementResult.NoValidTile); + + } + + private static Queue GetDoorwayPairs(DungeonGenerator gen, TileProxy attachTo, IEnumerable collection, DungeonArchetype archetype, float normalizedDepth){ // get rotation state var value = attachTo.PrefabTile.AllowRotation; if (gen.OverrideAllowTileRotation) { @@ -275,32 +303,13 @@ namespace DunGenPlus.Generation }; var maxCount = gen.UseMaximumPairingAttempts ? new int?(gen.MaxPairingAttempts) : null; + return doorwayPairFinder.GetDoorwayPairs(maxCount); + } - DoorwayPairStopwatch.Reset(); - DoorwayPairStopwatch.Start(); - var doorwayPairs = doorwayPairFinder.GetDoorwayPairs(maxCount); - DoorwayPairStopwatch.Stop(); - DoorwayPairTime += (float)DoorwayPairStopwatch.Elapsed.TotalMilliseconds; - - var tilePlacementResult = new TilePlacementResultProxy(TilePlacementResult.NoValidTile); - while(doorwayPairs.Count > 0) { - var pair = doorwayPairs.Dequeue(); - tilePlacementResult = TryPlaceTileResult(gen, pathProxy, pair, archetype); - if (tilePlacementResult.result == TilePlacementResult.None) break; - } - - if (tilePlacementResult.result == TilePlacementResult.None){ - if (injectedTile != null) { - var tileProxy = tilePlacementResult.tileProxy; - tileProxy.Placement.InjectionData = injectedTile; - pathProxy.injectedTiles[tileProxy] = injectedTile; - pathProxy.tilesPendingInjection.RemoveAt(index); - } - return tilePlacementResult; - } - - return new TilePlacementResultProxy(TilePlacementResult.NoValidTile); - + private static Queue GetDoorwayPairs(DungeonGenerator gen, TileProxy attachTo, IEnumerable useableTileSets, DungeonArchetype archetype, float normalizedDepth){ + IEnumerable collection; + collection = useableTileSets.SelectMany(t => t.TileWeights.Weights); + return GetDoorwayPairs(gen, attachTo, collection, archetype, normalizedDepth); } private static TilePlacementResultProxy TryPlaceTileResult(DungeonGenerator gen, BranchPathProxy pathProxy, DoorwayPair pair, DungeonArchetype archetype){ diff --git a/DunGenPlus/DunGenPlus/Generation/DunGenPlusGeneratorGlobalProps.cs b/DunGenPlus/DunGenPlus/Generation/DunGenPlusGeneratorGlobalProps.cs index ac7033f..04f7d1f 100644 --- a/DunGenPlus/DunGenPlus/Generation/DunGenPlusGeneratorGlobalProps.cs +++ b/DunGenPlus/DunGenPlus/Generation/DunGenPlusGeneratorGlobalProps.cs @@ -191,6 +191,7 @@ namespace DunGenPlus.Generation { /* Plugin.logger.LogError("Spawned"); + var colors = new Color[] { Color.red, Color.blue }; foreach(var tile in dungeonGenerator.CurrentDungeon.AllTiles){ @@ -198,27 +199,27 @@ namespace DunGenPlus.Generation { foreach(var globalProp in tile.GetComponentsInChildren()){ if (globalProp.PropGroupID == 1717){ - var newGameObject = GameObject.Instantiate(DunGenPlusPanel.Instance.dungeonBoundsHelperGameObject); - newGameObject.transform.position = globalProp.transform.position + Vector3.up * 10f; - newGameObject.transform.localScale = Vector3.one * 4f; - Plugin.logger.LogError($"{globalProp.PropGroupID}: {newGameObject.transform.position}"); + //var newGameObject = GameObject.Instantiate(DunGenPlusPanel.Instance.dungeonBoundsHelperGameObject); + //newGameObject.transform.position = globalProp.transform.position; + //newGameObject.transform.localScale = Vector3.one * 1f; + Plugin.logger.LogError($"{globalProp.PropGroupID}: {globalProp.transform.position}"); - var renderer = newGameObject.GetComponent(); - renderer.material.color = colors[0]; + //var renderer = newGameObject.GetComponent(); + //renderer.material.color = colors[0]; - newGameObject.SetActive(true); + // newGameObject.SetActive(true); } if (globalProp.PropGroupID == 1718){ - var newGameObject = GameObject.Instantiate(DunGenPlusPanel.Instance.dungeonBoundsHelperGameObject); - newGameObject.transform.position = globalProp.transform.position + Vector3.up * 10f; - newGameObject.transform.localScale = Vector3.one * 4f; - Plugin.logger.LogError($"{globalProp.PropGroupID}: {newGameObject.transform.position}"); + //var newGameObject = GameObject.Instantiate(DunGenPlusPanel.Instance.dungeonBoundsHelperGameObject); + //newGameObject.transform.position = globalProp.transform.position; + //newGameObject.transform.localScale = Vector3.one * 1f; + Plugin.logger.LogError($"{globalProp.PropGroupID}: {globalProp.transform.position}"); - var renderer = newGameObject.GetComponent(); - renderer.material.color = colors[1]; + //var renderer = newGameObject.GetComponent(); + //renderer.material.color = colors[1]; - newGameObject.SetActive(true); + //newGameObject.SetActive(true); } } diff --git a/DunGenPlus/DunGenPlus/Generation/DunGenPlusGeneratorMiscellaneous.cs b/DunGenPlus/DunGenPlus/Generation/DunGenPlusGeneratorMiscellaneous.cs index 06b6b9d..ece6bac 100644 --- a/DunGenPlus/DunGenPlus/Generation/DunGenPlusGeneratorMiscellaneous.cs +++ b/DunGenPlus/DunGenPlus/Generation/DunGenPlusGeneratorMiscellaneous.cs @@ -92,7 +92,7 @@ namespace DunGenPlus.Generation { } public static bool AllowRetryStop(bool defaultState){ - return defaultState || DevDebugManager.IsActive; + return defaultState || API.IsDevDebugModeActive(); } } diff --git a/DunGenPlus/DunGenPlus/Patches/DungeonGeneratorPatch.cs b/DunGenPlus/DunGenPlus/Patches/DungeonGeneratorPatch.cs index 9c6bcf1..e4828f3 100644 --- a/DunGenPlus/DunGenPlus/Patches/DungeonGeneratorPatch.cs +++ b/DunGenPlus/DunGenPlus/Patches/DungeonGeneratorPatch.cs @@ -42,7 +42,7 @@ namespace DunGenPlus.Patches { [HarmonyPatch(typeof(DungeonGenerator), "InnerGenerate")] public static void InnerGeneratePatch(ref DungeonGenerator __instance, bool isRetry, ref IEnumerator __result){ //Plugin.logger.LogWarning($"InnerGenerate: {DunGenPlusGenerator.Active}, {DunGenPlusGenerator.ActiveAlternative}, {__instance.Status}"); - if (DevDebugManager.IsActive && !isRetry) { + if (API.IsDevDebugModeActive() && !isRetry) { DevDebugManager.Instance.RecordNewSeed(__instance.ChosenSeed); } @@ -382,6 +382,52 @@ namespace DunGenPlus.Patches { } + [HarmonyTranspiler] + [HarmonyPatch(typeof(DungeonGenerator), "GenerateMainPath", MethodType.Enumerator)] + public static IEnumerable GenerateMainPathDebugPatch(IEnumerable instructions){ + + var tileProxyNullSequence = new InstructionSequenceStandard("TileProxyNull"); + tileProxyNullSequence.AddBasic(OpCodes.Br); + tileProxyNullSequence.AddBasicLocal(OpCodes.Ldloc_S, 14); + tileProxyNullSequence.AddBasic(OpCodes.Brtrue); + + foreach(var instruction in instructions){ + if (tileProxyNullSequence.VerifyStage(instruction)) { + var specialFunction = typeof(DunGenPlusGenerator).GetMethod("PrintAddTileErrorQuick", BindingFlags.Static | BindingFlags.Public); + var field = typeof(DungeonGenerator).Assembly.GetType("DunGen.DungeonGenerator+d__100").GetField("5__8", BindingFlags.NonPublic | BindingFlags.Instance); + + yield return instruction; + + yield return new CodeInstruction(OpCodes.Ldloc_1); + yield return new CodeInstruction(OpCodes.Ldarg_0); + yield return new CodeInstruction(OpCodes.Ldfld, field); + + yield return new CodeInstruction(OpCodes.Call, specialFunction); + + continue; + } + + yield return instruction; + } + + tileProxyNullSequence.ReportComplete(); + } + + + public static TileProxy lastAttachTo; + public static IEnumerable lastUseableTileSets; + public static float lastNormalizedDepth; + public static DungeonArchetype lastArchetype; + + [HarmonyPrefix] + [HarmonyPatch(typeof(DungeonGenerator), "AddTile")] + public static void AddTileDebugPatch(TileProxy attachTo, IEnumerable useableTileSets, float normalizedDepth, DungeonArchetype archetype){ + lastAttachTo = attachTo; + lastUseableTileSets = useableTileSets; + lastNormalizedDepth = normalizedDepth; + lastArchetype = archetype; + } + /* [HarmonyTranspiler] [HarmonyPatch(typeof(DungeonGenerator), "GenerateMainPath", MethodType.Enumerator)] diff --git a/DunGenPlus/DunGenPlus/dungen b/DunGenPlus/DunGenPlus/dungen index a0a7388..d5e1c2b 100644 Binary files a/DunGenPlus/DunGenPlus/dungen and b/DunGenPlus/DunGenPlus/dungen differ