Added some better debugging for failed dungeon generations
RandomGuaranteedScrapSpawn has more fields
This commit is contained in:
parent
15a550af53
commit
a166b3d4a7
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<int, IEnumerable<SpawnableItemWithRarity>> scrapItemRarityCache;
|
||||
internal static Dictionary<(int, int), IEnumerable<SpawnableItemWithRarity>> scrapItemRarityValueCache;
|
||||
internal static Dictionary<string, IEnumerable<SpawnableItemWithRarity>> scrapItemRarityNameCache;
|
||||
|
||||
internal static void ResetCache(){
|
||||
scrapItemRarityCache = new Dictionary<int, IEnumerable<SpawnableItemWithRarity>>();
|
||||
scrapItemRarityValueCache = new Dictionary<(int, int), IEnumerable<SpawnableItemWithRarity>>();
|
||||
scrapItemRarityNameCache = new Dictionary<string, IEnumerable<SpawnableItemWithRarity>>();
|
||||
}
|
||||
|
||||
internal static IEnumerable<SpawnableItemWithRarity> GetCachedItemList(List<SpawnableItemWithRarity> 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<SpawnableItemWithRarity> GetCachedItemList(List<SpawnableItemWithRarity> 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<SpawnableItemWithRarity> GetCachedItemList(List<SpawnableItemWithRarity> 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<SpawnableItemWithRarity> GetCachedItemList(List<SpawnableItemWithRarity> allMoonItems) {
|
||||
if (string.IsNullOrWhiteSpace(specificScrapTarget)) return GetCachedItemList(allMoonItems, minimumScrapValue, maximumScrapValue);
|
||||
return GetCachedItemList(allMoonItems, specificScrapTarget);
|
||||
}
|
||||
|
||||
internal static Item GetRandomItem(IEnumerable<SpawnableItemWithRarity> 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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Binary file not shown.
|
@ -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<TileSet> 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<string>();
|
||||
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}");
|
||||
|
||||
|
|
|
@ -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<DoorwayPair> GetDoorwayPairs(DungeonGenerator gen, TileProxy attachTo, IEnumerable<GameObjectChance> 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<DoorwayPair> GetDoorwayPairs(DungeonGenerator gen, TileProxy attachTo, IEnumerable<TileSet> useableTileSets, DungeonArchetype archetype, float normalizedDepth){
|
||||
IEnumerable<GameObjectChance> 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){
|
||||
|
|
|
@ -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<GlobalProp>()){
|
||||
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>();
|
||||
renderer.material.color = colors[0];
|
||||
//var renderer = newGameObject.GetComponent<Renderer>();
|
||||
//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>();
|
||||
renderer.material.color = colors[1];
|
||||
//var renderer = newGameObject.GetComponent<Renderer>();
|
||||
//renderer.material.color = colors[1];
|
||||
|
||||
newGameObject.SetActive(true);
|
||||
//newGameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ namespace DunGenPlus.Generation {
|
|||
}
|
||||
|
||||
public static bool AllowRetryStop(bool defaultState){
|
||||
return defaultState || DevDebugManager.IsActive;
|
||||
return defaultState || API.IsDevDebugModeActive();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<CodeInstruction> GenerateMainPathDebugPatch(IEnumerable<CodeInstruction> 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+<GenerateMainPath>d__100").GetField("<j>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<TileSet> lastUseableTileSets;
|
||||
public static float lastNormalizedDepth;
|
||||
public static DungeonArchetype lastArchetype;
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(DungeonGenerator), "AddTile")]
|
||||
public static void AddTileDebugPatch(TileProxy attachTo, IEnumerable<TileSet> useableTileSets, float normalizedDepth, DungeonArchetype archetype){
|
||||
lastAttachTo = attachTo;
|
||||
lastUseableTileSets = useableTileSets;
|
||||
lastNormalizedDepth = normalizedDepth;
|
||||
lastArchetype = archetype;
|
||||
}
|
||||
|
||||
/*
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(DungeonGenerator), "GenerateMainPath", MethodType.Enumerator)]
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue