diff --git a/ScarletMansion/ScarletMansion/DunGenAnalyis.cs b/ScarletMansion/ScarletMansion/DunGenAnalyis.cs index d19ddac..33155a1 100644 --- a/ScarletMansion/ScarletMansion/DunGenAnalyis.cs +++ b/ScarletMansion/ScarletMansion/DunGenAnalyis.cs @@ -47,7 +47,7 @@ namespace ScarletMansion { var strList = new List(); values.Sort(); - var sectionCount = Mathf.Min(10, values.Count); + var sectionCount = Mathf.Clamp(values.Count, 1, 10); var sectionDistance = values.Count / sectionCount; for(var i = 0; i * sectionDistance < values.Count; ++i){ var avg = GetAverage(values.Skip(i * sectionDistance).Take(sectionDistance)); diff --git a/ScarletMansion/ScarletMansion/DunGenPatch/Components/MainRoomDoorwayGroups.cs b/ScarletMansion/ScarletMansion/DunGenPatch/Components/MainRoomDoorwayGroups.cs index d01a440..ef12515 100644 --- a/ScarletMansion/ScarletMansion/DunGenPatch/Components/MainRoomDoorwayGroups.cs +++ b/ScarletMansion/ScarletMansion/DunGenPatch/Components/MainRoomDoorwayGroups.cs @@ -11,12 +11,13 @@ namespace ScarletMansion { public List groupA; public List groupB; - public List groupC; + + public List groupBasement; public List GrabDoorwayGroup(Doorway target){ if (groupA.Contains(target)) return groupA; else if (groupB.Contains(target)) return groupB; - else if (groupC.Contains(target)) return groupC; + else if (groupBasement.Contains(target)) return groupBasement; return null; } diff --git a/ScarletMansion/ScarletMansion/DunGenPatch/GeneratePath.cs b/ScarletMansion/ScarletMansion/DunGenPatch/GeneratePath.cs index 163f8f2..e034f10 100644 --- a/ScarletMansion/ScarletMansion/DunGenPatch/GeneratePath.cs +++ b/ScarletMansion/ScarletMansion/DunGenPatch/GeneratePath.cs @@ -92,7 +92,11 @@ namespace ScarletMansion.DunGenPatch { public static IEnumerator GenerateAlternativeMainPaths(DungeonGenerator gen) { // the amount of extra alt. paths - var altCount = PluginConfig.Instance.mainPathCountValue - 1; + var altV = PluginConfig.Instance.mainPathCountValue; + if (PluginConfig.Instance.disableBasementValue) { + altV = Mathf.Min(altV, 2); + } + var altCount = altV - 1; if (!active || altCount == 0){ Patch.callAlternative = false; @@ -101,10 +105,10 @@ namespace ScarletMansion.DunGenPatch { yield break; } - gen.ChangeStatus(GenerationStatus.Branching); + gen.ChangeStatus(GenerationStatus.MainPath); var allMainPathTiles = new List>(); - allMainPathTiles.Add(gen.proxyDungeon.MainPathTiles); + allMainPathTiles.Add(gen.proxyDungeon.MainPathTiles.ToList()); // main tile is the true main room and not the fake room // this MUST have multiple doorways as you can imainge @@ -152,6 +156,7 @@ namespace ScarletMansion.DunGenPatch { // and yet it worked // this is how my last node cannot be a target of pruning GraphNode graphNode = null; + DungeonArchetype archetype = null; foreach(var g in nodes) { if (lineDepthRatio >= g.Position && !nodesVisited.Contains(g)) { graphNode = g; @@ -162,9 +167,11 @@ namespace ScarletMansion.DunGenPatch { List useableTileSets; if (graphNode != null) { + archetype = graphNode.NodeType == NodeType.Normal ? Assets.networkObjectList.hallwayEntranceArchetype : null; useableTileSets = graphNode.TileSets; } else { - useableTileSets = gen.currentArchetype.TileSets; + archetype = gen.currentArchetype; + useableTileSets = archetype.TileSets; } if (t == 1){ @@ -193,7 +200,7 @@ namespace ScarletMansion.DunGenPatch { } - var tileProxy = gen.AddTile(previousTile, useableTileSets, lineDepthRatio, gen.currentArchetype, TilePlacementResult.None); + var tileProxy = gen.AddTile(previousTile, useableTileSets, lineDepthRatio, archetype, TilePlacementResult.None); if (tileProxy == null) { if (!Patch.startAnalysis) Plugin.logger.LogInfo($"Alt. main branch gen failed at {b}:{lineDepthRatio}"); @@ -210,8 +217,15 @@ namespace ScarletMansion.DunGenPatch { tileProxy.Placement.BranchDepth = t; tileProxy.Placement.NormalizedBranchDepth = lineDepthRatio; - tileProxy.Placement.GraphNode = previousTile.Placement.GraphNode; - tileProxy.Placement.GraphLine = previousTile.Placement.GraphLine; + + if (graphNode != null) { + tileProxy.Placement.GraphNode = graphNode; + tileProxy.Placement.GraphLine = null; + } else { + tileProxy.Placement.GraphNode = null; + tileProxy.Placement.GraphLine = lineAtDepth; + } + previousTile = tileProxy; newMainPathTiles.Add(tileProxy); @@ -234,11 +248,20 @@ namespace ScarletMansion.DunGenPatch { Patch.callAlternative = false; if (!Patch.startAnalysis) Plugin.logger.LogInfo($"Created {altCount} alt. paths, creating branches now"); + gen.ChangeStatus(GenerationStatus.Branching); + // this is major trickery and it works still for(var b = 0; b < altCount + 1; ++b){ if (!Patch.startAnalysis) Plugin.logger.LogInfo($"Branch {b}"); RandomizeLineArchetypes(gen, false); gen.proxyDungeon.MainPathTiles = allMainPathTiles[b]; + + /* + foreach (var t in gen.proxyDungeon.MainPathTiles){ + Plugin.logger.LogInfo(t.Prefab.name); + Plugin.logger.LogInfo(t.Placement.Archetype); + } + */ yield return gen.Wait(gen.GenerateBranchPaths()); } @@ -249,6 +272,12 @@ namespace ScarletMansion.DunGenPatch { if (AnalysisUpdate(gen)) yield return gen.Wait(gen.InnerGenerate(true)); } + public static DungeonArchetype ModifyMainBranchNodeArchetype(DungeonArchetype archetype, GraphNode node){ + if (!Patch.active) return archetype; + if (node.NodeType == NodeType.Normal) return Assets.networkObjectList.hallwayEntranceArchetype; + return archetype; + } + public static bool AnalysisUpdate(DungeonGenerator gen){ if (Patch.startAnalysis && analTestCount <= analTestCountMax) { var t = Patch.stopwatch.ElapsedMilliseconds; @@ -271,7 +300,7 @@ namespace ScarletMansion.DunGenPatch { } } - Plugin.logger.LogInfo($"C{analTestCount}, S{analAltFailCount}, R{gen.retryCount - analAltFailCount - analTestCount}\nLoot {Patch.scrapDistance.ToString()}\nFloor {Patch.scrapFloors.ToString()}"); + Plugin.logger.LogInfo($"C{analTestCount}, S{analAltFailCount}, R{gen.retryCount - analAltFailCount - analTestCount}\nLoot {Patch.scrapDistance.ToString()}"); analTestCount++; Patch.stopwatch.Restart(); diff --git a/ScarletMansion/ScarletMansion/DunGenPatch/GeneratePathPatch.cs b/ScarletMansion/ScarletMansion/DunGenPatch/GeneratePathPatch.cs index 4a56a25..697eab0 100644 --- a/ScarletMansion/ScarletMansion/DunGenPatch/GeneratePathPatch.cs +++ b/ScarletMansion/ScarletMansion/DunGenPatch/GeneratePathPatch.cs @@ -54,5 +54,70 @@ namespace ScarletMansion.DunGenPatch { Plugin.logger.LogInfo("Alt. InnerGenerate() function complete"); } } + + [HarmonyTranspiler] + [HarmonyPatch(typeof(DungeonGenerator), "GenerateMainPath", MethodType.Enumerator)] + public static IEnumerable GenerateMainPathPatch(IEnumerable instructions){ + + var addFunction = typeof(List).GetMethod("Add", BindingFlags.Instance | BindingFlags.Public); + + var sequence = new InstructionSequence("archetype node"); + sequence.AddOperandTypeCheck(OpCodes.Ldfld, typeof(List)); + sequence.AddBasic(OpCodes.Ldnull); + sequence.AddBasic(OpCodes.Callvirt, addFunction); + + foreach(var instruction in instructions){ + + if (sequence.VerifyStage(instruction)){ + + var method = typeof(GeneratePath).GetMethod("ModifyMainBranchNodeArchetype", BindingFlags.Public | BindingFlags.Static); + + yield return new CodeInstruction(OpCodes.Ldloc_S, 8); + yield return new CodeInstruction(OpCodes.Call, method); + + yield return instruction; + + continue; + } + + yield return instruction; + } + + sequence.ReportComplete(); + } + + /* + + [HarmonyPatch(typeof(DungeonGenerator), "AddTile")] + [HarmonyPostfix] + public static void AddTilePatch(TileProxy attachTo, IEnumerable useableTileSets, DungeonArchetype archetype, ref TileProxy __result){ + var atString = attachTo != null ? attachTo.Prefab.ToString() : "NULL"; + var aString = archetype ? archetype.ToString() : "NULL"; + var rString = __result != null ? __result.Prefab.ToString() : "NULL"; + + Plugin.logger.LogInfo($""); + Plugin.logger.LogInfo($"Attach: {atString}"); + Plugin.logger.LogInfo($"ValidCount: {useableTileSets.Sum(u => u.TileWeights.Weights.Count).ToString()}"); + Plugin.logger.LogInfo($"Entry: {aString}"); + Plugin.logger.LogInfo($"Result: {rString}"); + + } + + [HarmonyPatch(typeof(DungeonGenerator), "TryPlaceTile")] + [HarmonyPostfix] + public static void TryPlaceTilePatch(ref TilePlacementResult __result){ + Plugin.logger.LogInfo(__result.ToString()); + } + + [HarmonyPatch(typeof(DoorwayPairFinder), "GetDoorwayPairs")] + [HarmonyPostfix] + public static void GetDoorwayPairsPatch(ref Queue __result){ + Plugin.logger.LogInfo(__result.Count().ToString()); + } + */ + } + + + } diff --git a/ScarletMansion/ScarletMansion/DunGenPatch/Patch.cs b/ScarletMansion/ScarletMansion/DunGenPatch/Patch.cs index 32684dd..db1f491 100644 --- a/ScarletMansion/ScarletMansion/DunGenPatch/Patch.cs +++ b/ScarletMansion/ScarletMansion/DunGenPatch/Patch.cs @@ -67,7 +67,6 @@ namespace ScarletMansion.DunGenPatch { Plugin.logger.LogError(e.ToString()); } - if (startAnalysis) ActivateAnalysis(); } diff --git a/ScarletMansion/ScarletMansion/GamePatch/InitPatch.cs b/ScarletMansion/ScarletMansion/GamePatch/InitPatch.cs index f430aaf..9ee2fe2 100644 --- a/ScarletMansion/ScarletMansion/GamePatch/InitPatch.cs +++ b/ScarletMansion/ScarletMansion/GamePatch/InitPatch.cs @@ -13,6 +13,7 @@ using Unity.Netcode; using LethalLevelLoader; using static UnityEngine.GraphicsBuffer; using ScarletMansion.GamePatch.Components; +using System.Security.Cryptography; namespace ScarletMansion.GamePatch { @@ -370,6 +371,9 @@ namespace ScarletMansion.GamePatch { //Assets.dungeonExtended.DynamicDungeonSizeMinMax = new Vector2(PluginConfig.Instance.dunGenMultiplierValue.min, PluginConfig.Instance.dunGenMultiplierValue.max); Assets.dungeon.Length = PluginConfig.Instance.mainPathLengthValue.GetDungenIntRange(); + var mayorTileSet = PluginConfig.Instance.disableBasementValue ? Assets.networkObjectList.mayorVanillaTileset : Assets.networkObjectList.mayorRegularTileset; + Assets.dungeon.Nodes[1].TileSets = new List() { mayorTileSet }; + DungeonFlow.GlobalPropSettings GetGlobalPropSetting(int id) { foreach(var p in Assets.dungeon.GlobalProps){ if (p.ID == id ) return p; diff --git a/ScarletMansion/ScarletMansion/LoadingPatch/NetworkObjectListScriptableObject.cs b/ScarletMansion/ScarletMansion/LoadingPatch/NetworkObjectListScriptableObject.cs index 4b80bdf..b85f2bd 100644 --- a/ScarletMansion/ScarletMansion/LoadingPatch/NetworkObjectListScriptableObject.cs +++ b/ScarletMansion/ScarletMansion/LoadingPatch/NetworkObjectListScriptableObject.cs @@ -23,10 +23,13 @@ namespace ScarletMansion { public List items; [Header("DunGen")] + public TileSet mayorRegularTileset; + public TileSet mayorVanillaTileset; + public DungeonArchetype hallwayEntranceArchetype; + public List archetypes; public List tilesets; - //public GameObject mainMenuPrefab; [Header("Main Prefabs")] public GameObject scarletNetworkManager; public AudioClip sinkingAudioClip; diff --git a/ScarletMansion/ScarletMansion/Plugin.cs b/ScarletMansion/ScarletMansion/Plugin.cs index be48688..012ddc9 100644 --- a/ScarletMansion/ScarletMansion/Plugin.cs +++ b/ScarletMansion/ScarletMansion/Plugin.cs @@ -33,7 +33,7 @@ namespace ScarletMansion { public class Plugin : BaseUnityPlugin { public const string modGUID = "ImoutoSama.ScarletMansion"; private const string modName = "Scarlet Mansion"; - private const string modVersion = "1.3.12"; + private const string modVersion = "1.3.13"; public readonly Harmony harmony = new Harmony(modGUID); diff --git a/ScarletMansion/ScarletMansion/PluginConfig.cs b/ScarletMansion/ScarletMansion/PluginConfig.cs index a35f119..b34eb09 100644 --- a/ScarletMansion/ScarletMansion/PluginConfig.cs +++ b/ScarletMansion/ScarletMansion/PluginConfig.cs @@ -168,11 +168,20 @@ namespace ScarletMansion { $"The minimum allowed length of the main path. This value is multiplied by the dungeon's size.\n\n{_mainPathLengthPostMessage}", $"The maximum allowed length of the main path. This value is multiplied by the dungeon's size.\n\n{_mainPathLengthPostMessage}", null, - new AcceptableValueRange(2, 20) + new AcceptableValueRange(3, 20) + ); + + public static ConfigEntryBundle disableBasement = new ConfigEntryBundle( + dungeonGenerationMPathsPrefix, + "Disable Mayor Basement", + false, + "Removes the basement section of the mayor tile. Forces the Main Path Count to a maximum of 2." ); public int mainPathCountValue; public IntRange mainPathLengthValue = new IntRange("main path length"); + public bool disableBasementValue; + // branching path private static string _branchPathBranchCountMessage(int section, string minmax, string middleSection) => $"The {minmax} amount of branching paths in Section {section} of the dungeon generation process.\n{middleSection}\n\n{_branchPathPostCountMessage}"; @@ -187,11 +196,11 @@ namespace ScarletMansion { private static readonly string _branchPathPostDepthMessage = $"Each branching path will try to generate a number of connecting tiles equal to this number. {_branchPathPostGenericMessage}"; public static ConfigEntryBundleBranchingPath branchPathSectionOne = new ConfigEntryBundleBranchingPath( - dungeonGenerationBPathOnePrefix, 1, _branchPathSectionOneMessage, 6, 8, 0, 2 + dungeonGenerationBPathOnePrefix, 1, _branchPathSectionOneMessage, 4, 6, 1, 2 ); public static ConfigEntryBundleBranchingPath branchPathSectionTwo = new ConfigEntryBundleBranchingPath( - dungeonGenerationBPathTwoPrefix, 2, _branchPathSectionTwoMessage, 2, 3, 0, 1 + dungeonGenerationBPathTwoPrefix, 2, _branchPathSectionTwoMessage, 2, 3, 1, 2 ); public static ConfigEntryBundleBranchingPath branchPathSectionThree = new ConfigEntryBundleBranchingPath( diff --git a/ScarletMansion/ScarletMansion/PresetConfig.cs b/ScarletMansion/ScarletMansion/PresetConfig.cs index b51279a..8c99676 100644 --- a/ScarletMansion/ScarletMansion/PresetConfig.cs +++ b/ScarletMansion/ScarletMansion/PresetConfig.cs @@ -32,6 +32,7 @@ namespace ScarletMansion { new ChangeInt ( PluginConfig.mainPathCount ), new ChangeMinMaxInt ( PluginConfig.mainPathLength ), + new ChangeBool( PluginConfig.disableBasement ), new ChangeBranchingPath( PluginConfig.branchPathSectionOne ), new ChangeBranchingPath( PluginConfig.branchPathSectionTwo ), @@ -76,6 +77,7 @@ namespace ScarletMansion { ); + public static ChangeList bitMoreLootGeneration = new ChangeList( "Bit More Loot, Bit More Danger", "Increases the amount of loot, map hazards, and starting enemies in the mansion a bit. Intended for lobbies with 1-3 players.", @@ -103,6 +105,11 @@ namespace ScarletMansion { new ChangeInt ( PluginConfig.mainPathCount, 1 ), new ChangeMinMaxInt ( PluginConfig.mainPathLength, 6, 9 ), + new ChangeBool( PluginConfig.disableBasement, true ), + + new ChangeBranchingPath( PluginConfig.branchPathSectionOne, 4, 6, 3, 4 ), + new ChangeBranchingPath( PluginConfig.branchPathSectionTwo, 2, 3, 2, 3 ), + new ChangeBranchingPath( PluginConfig.branchPathSectionThree, 1, 2, 1, 2 ), new ChangeFloat ( PluginConfig.lootMultiplier, 1f ), @@ -270,6 +277,11 @@ namespace ScarletMansion { } } + public class ChangeBool : ChangeType { + public ChangeBool(PluginConfig.ConfigEntryBundle configEntry) : base (configEntry){ } + public ChangeBool(PluginConfig.ConfigEntryBundle configEntry, bool value) : base (configEntry, value){ } + } + public class ChangeFloat : ChangeType { public ChangeFloat(PluginConfig.ConfigEntryBundle configEntry) : base (configEntry){ } public ChangeFloat(PluginConfig.ConfigEntryBundle configEntry, float value) : base (configEntry, value){ } diff --git a/ScarletMansion/ScarletMansion/TranspilerUtilities.cs b/ScarletMansion/ScarletMansion/TranspilerUtilities.cs index 8e50e01..756bb24 100644 --- a/ScarletMansion/ScarletMansion/TranspilerUtilities.cs +++ b/ScarletMansion/ScarletMansion/TranspilerUtilities.cs @@ -83,6 +83,17 @@ namespace ScarletMansion { seq.Add((i) => i.opcode == opcode && i.operand == operand); } + public void AddOperandTypeCheck(OpCode opcode, Type operandType){ + seq.Add((i) => { + var fieldInfo = i.operand as FieldInfo; + if (i.opcode == opcode && fieldInfo != null) { + return fieldInfo.FieldType == operandType; + } + return false; + }); + } + + public void AddBasicWithAlternateMethodName(OpCode opcode, object operand, string methodName){ seq.Add((i) => { if (i.opcode == opcode && i.operand == operand) return true; @@ -162,5 +173,13 @@ namespace ScarletMansion { return Mathf.Abs((float)instruction.operand - value) < 0.1f; } + public static void PrintInstructions(IEnumerable instructions) { + foreach(var i in instructions){ + var opString = i.opcode.ToString(); + var objString = i.operand != null ? i.operand.ToString() : "NULL"; + Plugin.logger.LogInfo($"{opString}: {objString}"); + } + } + } }