Added MainPathExtender
This commit is contained in:
parent
9ca2b662e3
commit
99d9d7ae1e
|
@ -15,6 +15,8 @@ namespace DunGenPlus.Collections {
|
|||
internal const string MainPathCountTooltip = "The number of main paths.\n\n1 means no additional main paths\n3 means two additional main paths\netc.";
|
||||
internal const string MainRoomTilePrefabTooltip = "The Tile prefab where the additional main paths will start from.\n\nCannot be null if MainPathCount is more than 1.";
|
||||
internal const string CopyNodeBehaviourTooltip = "Defines how the nodes list is copied onto the additional main paths.\n\nCopyFromMainPathPosition: nodes will copy based on the MainRoomTilePrefab's position in the main path.\nCopyFromNodeList: nodes will copy based on the MainRoomTilePrefab's position in the node list + 1.";
|
||||
internal const string MainPathDetailsTooltip = "Tooltip";
|
||||
|
||||
|
||||
[Tooltip(MainPathCountTooltip)]
|
||||
[Range(1, 9)]
|
||||
|
@ -23,11 +25,21 @@ namespace DunGenPlus.Collections {
|
|||
public GameObject MainRoomTilePrefab;
|
||||
[Tooltip(CopyNodeBehaviourTooltip)]
|
||||
public CopyNodeBehaviour CopyNodeBehaviour = CopyNodeBehaviour.CopyFromMainPathPosition;
|
||||
[Tooltip(MainPathDetailsTooltip)]
|
||||
public List<MainPathExtender> MainPathDetails = new List<MainPathExtender>();
|
||||
|
||||
public MainPathExtender GetMainPathDetails(int index) {
|
||||
var count = MainPathDetails.Count;
|
||||
if (count == 0) return null;
|
||||
if (index < count) return MainPathDetails[index];
|
||||
return MainPathDetails[count - 1];
|
||||
}
|
||||
|
||||
internal void CopyFrom(MainPathProperties props) {
|
||||
MainPathCount = props.MainPathCount;
|
||||
MainRoomTilePrefab = props.MainRoomTilePrefab;
|
||||
CopyNodeBehaviour = props.CopyNodeBehaviour;
|
||||
MainPathDetails = props.MainPathDetails;
|
||||
}
|
||||
|
||||
internal MainPathProperties Copy() {
|
||||
|
|
|
@ -10,7 +10,7 @@ using DunGenPlus.Collections;
|
|||
|
||||
namespace DunGenPlus {
|
||||
|
||||
[CreateAssetMenu(fileName = "DunGenExtender", menuName = "DunGenExtender", order = 1)]
|
||||
[CreateAssetMenu(fileName = "DunGen Extender", menuName = "DunGenExtender/DunGen Extender", order = 1)]
|
||||
public class DunGenExtender : ScriptableObject {
|
||||
|
||||
[Tooltip("DunGenExtender will only influence this DungeonFlow")]
|
||||
|
|
|
@ -146,6 +146,8 @@
|
|||
<Compile Include="Components\MainRoomDoorwayGroups.cs" />
|
||||
<Compile Include="Components\Props\SpawnSyncedObjectCycle.cs" />
|
||||
<Compile Include="Components\Scrap\RandomGuaranteedScrapSpawn.cs" />
|
||||
<Compile Include="Generation\DunGenPlusGenerationPaths.cs" />
|
||||
<Compile Include="MainPathExtender.cs" />
|
||||
<Compile Include="PluginConfig.cs" />
|
||||
<Compile Include="DevTools\DevDebugManager.cs" />
|
||||
<Compile Include="DevTools\DevDebugManagerUI.cs" />
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
using DunGen;
|
||||
using DunGen.Graph;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DunGenPlus.Generation {
|
||||
internal partial class DunGenPlusGenerator {
|
||||
|
||||
public static MainPathExtender currentMainPathExtender;
|
||||
|
||||
public static void SetCurrentMainPathExtender(int mainPathIndex){
|
||||
currentMainPathExtender = Properties.MainPathProperties.GetMainPathDetails(mainPathIndex);
|
||||
}
|
||||
|
||||
public static GraphLine GetLineAtDepth(DungeonFlow flow, float depth) {
|
||||
if (!DunGenPlusGenerator.Active) {
|
||||
//Plugin.logger.LogInfo("Default");
|
||||
return flow.GetLineAtDepth(depth);
|
||||
}
|
||||
|
||||
//Plugin.logger.LogInfo(currentMainPathExtender == null ? "NULL" : "ITEM");
|
||||
var lines = MainPathExtender.GetLines(currentMainPathExtender, flow);
|
||||
return GetLineAtDepthHelper(lines, depth);
|
||||
}
|
||||
|
||||
public static GraphLine GetLineAtDepthHelper(List<GraphLine> graphLines, float normalizedDepth) {
|
||||
normalizedDepth = Mathf.Clamp(normalizedDepth, 0f, 1f);
|
||||
if (normalizedDepth == 0f) return graphLines[0];
|
||||
if (normalizedDepth == 1f) return graphLines[graphLines.Count - 1];
|
||||
foreach (GraphLine graphLine in graphLines){
|
||||
if (normalizedDepth >= graphLine.Position && normalizedDepth < graphLine.Position + graphLine.Length) {
|
||||
return graphLine;
|
||||
}
|
||||
}
|
||||
Debug.LogError("GetLineAtDepth was unable to find a line at depth " + normalizedDepth.ToString() + ". This shouldn't happen.");
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<GraphNode> GetNodes(DungeonFlow flow){
|
||||
if (!DunGenPlusGenerator.Active) {
|
||||
//Plugin.logger.LogInfo("Default");
|
||||
return flow.Nodes;
|
||||
}
|
||||
|
||||
//Plugin.logger.LogInfo(currentMainPathExtender == null ? "NULL" : "ITEM");
|
||||
return MainPathExtender.GetNodes(currentMainPathExtender, flow);
|
||||
}
|
||||
|
||||
public static BranchMode GetBranchMode(DungeonFlow flow) {
|
||||
if (!DunGenPlusGenerator.Active) {
|
||||
//Plugin.logger.LogInfo("Default M");
|
||||
return flow.BranchMode;
|
||||
}
|
||||
|
||||
//Plugin.logger.LogInfo(currentMainPathExtender == null ? "NULL" : "ITEM M");
|
||||
return MainPathExtender.GetBranchMode(currentMainPathExtender, flow);
|
||||
}
|
||||
|
||||
public static IntRange GetBranchCount(DungeonFlow flow) {
|
||||
if (!DunGenPlusGenerator.Active) {
|
||||
//Plugin.logger.LogInfo("Default C");
|
||||
return flow.BranchCount;
|
||||
}
|
||||
|
||||
//Plugin.logger.LogInfo(currentMainPathExtender == null ? "NULL" : "ITEM C");
|
||||
return MainPathExtender.GetBranchCount(currentMainPathExtender, flow);
|
||||
}
|
||||
|
||||
public static IntRange GetLength(DungeonFlow flow) {
|
||||
if (!DunGenPlusGenerator.Active) {
|
||||
Plugin.logger.LogInfo("Default");
|
||||
return flow.Length;
|
||||
}
|
||||
|
||||
Plugin.logger.LogInfo(currentMainPathExtender == null ? "NULL" : "ITEM");
|
||||
return MainPathExtender.GetLength(currentMainPathExtender, flow);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -142,42 +142,39 @@ namespace DunGenPlus.Generation {
|
|||
// index of MaxValue is how we tell which doorway proxy is fake
|
||||
var fakeDoorwayProxy = new DoorwayProxy(mainRoom, int.MaxValue, mainRoom.doorways[0].DoorwayComponent, Vector3.zero, Quaternion.identity);
|
||||
|
||||
// nodes
|
||||
var nodesSorted = gen.DungeonFlow.Nodes.OrderBy(n => n.Position).ToList();
|
||||
var startingNodeIndexCache = -1;
|
||||
if (copyNodeBehaviour == DunGenExtenderProperties.CopyNodeBehaviour.CopyFromNodeList) {
|
||||
startingNodeIndexCache = nodesSorted.FindIndex(n => n.TileSets.SelectMany(t => t.TileWeights.Weights).Any(t => t.Value == mainRoomTilePrefab));
|
||||
|
||||
if (startingNodeIndexCache == -1) {
|
||||
yield return gen.Wait(GenerateBranchPaths(gen, $"CopyNodeBehaviour being CopyFromNodeList AND MainRoomTilePrefab not existing in the Nodes' tilesets", LogLevel.Warning));
|
||||
yield break;
|
||||
}
|
||||
|
||||
startingNodeIndexCache++;
|
||||
}
|
||||
|
||||
//FixDoorwaysToAllFloors(mainRoom, doorwayGroups);
|
||||
|
||||
gen.ChangeStatus(GenerationStatus.MainPath);
|
||||
|
||||
for (var b = 0; b < altCount; ++b) {
|
||||
SetCurrentMainPathExtender(b + 1);
|
||||
RandomizeLineArchetypes(gen, true);
|
||||
|
||||
var previousTile = mainRoom;
|
||||
var targetLength = Mathf.RoundToInt(gen.DungeonFlow.Length.GetRandom(gen.RandomStream) * gen.LengthMultiplier);
|
||||
var targetLength = Mathf.RoundToInt(GetLength(gen.DungeonFlow).GetRandom(gen.RandomStream) * gen.LengthMultiplier);
|
||||
var archetypes = new List<DungeonArchetype>(targetLength);
|
||||
|
||||
var newMainPathTiles = new List<TileProxy>();
|
||||
// this causes the main room to create three sets of branch paths
|
||||
// newMainPathTiles.Add(mainRoom);
|
||||
|
||||
// nodes
|
||||
var nodesSorted = GetNodes(gen.DungeonFlow).OrderBy(n => n.Position).ToList();
|
||||
int startingNodeIndex;
|
||||
if (copyNodeBehaviour == DunGenExtenderProperties.CopyNodeBehaviour.CopyFromMainPathPosition) {
|
||||
if (copyNodeBehaviour == DunGenExtenderProperties.CopyNodeBehaviour.CopyFromNodeList) {
|
||||
var index = nodesSorted.FindIndex(n => n.TileSets.SelectMany(t => t.TileWeights.Weights).Any(t => t.Value == mainRoomTilePrefab));
|
||||
|
||||
if (index == -1) {
|
||||
yield return gen.Wait(GenerateBranchPaths(gen, $"CopyNodeBehaviour being CopyFromNodeList AND MainRoomTilePrefab not existing in the Nodes' tilesets", LogLevel.Warning));
|
||||
yield break;
|
||||
}
|
||||
|
||||
startingNodeIndex = index + 1;
|
||||
} else if (copyNodeBehaviour == DunGenExtenderProperties.CopyNodeBehaviour.CopyFromMainPathPosition) {
|
||||
var lineDepthRatio = Mathf.Clamp01(1f / (targetLength - 1));
|
||||
startingNodeIndex = nodesSorted.FindIndex(n => n.Position >= lineDepthRatio);
|
||||
} else if (copyNodeBehaviour == DunGenExtenderProperties.CopyNodeBehaviour.CopyFromNodeList) {
|
||||
startingNodeIndex = startingNodeIndexCache;
|
||||
} else {
|
||||
Plugin.logger.LogError($"{copyNodeBehaviour} is not yet defined. How did this happen?");
|
||||
Plugin.logger.LogFatal($"{copyNodeBehaviour} is not yet defined. Really really bad");
|
||||
startingNodeIndex = -1;
|
||||
}
|
||||
|
||||
|
@ -188,7 +185,7 @@ namespace DunGenPlus.Generation {
|
|||
// and GenerateBranch() code
|
||||
for(var t = 1; t < targetLength; ++t){
|
||||
var lineDepthRatio = Mathf.Clamp01((float)t / (targetLength - 1));
|
||||
var lineAtDepth = gen.DungeonFlow.GetLineAtDepth(lineDepthRatio);
|
||||
var lineAtDepth = GetLineAtDepth(gen.DungeonFlow, lineDepthRatio);
|
||||
if (lineAtDepth == null){
|
||||
yield return gen.Wait(gen.InnerGenerate(true));
|
||||
yield break;
|
||||
|
@ -281,6 +278,7 @@ namespace DunGenPlus.Generation {
|
|||
// this is major trickery and it works still
|
||||
for(var b = 0; b < altCount + 1; ++b){
|
||||
Plugin.logger.LogDebug($"Branch {b}");
|
||||
SetCurrentMainPathExtender(b);
|
||||
RandomizeLineArchetypes(gen, false);
|
||||
gen.proxyDungeon.MainPathTiles = allMainPathTiles[b];
|
||||
|
||||
|
@ -305,6 +303,7 @@ namespace DunGenPlus.Generation {
|
|||
Plugin.logger.Log(logLevel, $"Switching to default dungeon branch generation: {message}");
|
||||
|
||||
ActiveAlternative = false;
|
||||
SetCurrentMainPathExtender(0);
|
||||
yield return gen.Wait(gen.GenerateBranchPaths());
|
||||
ActiveAlternative = true;
|
||||
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
using DunGen;
|
||||
using DunGen.Graph;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DunGenPlus {
|
||||
|
||||
[System.Serializable]
|
||||
public class PropertyOverride<T> {
|
||||
[Tooltip("If false, use the value found in DungeonFlow. If true, use this Value instead.")]
|
||||
public bool Override;
|
||||
public T Value;
|
||||
|
||||
public PropertyOverride(bool _override, T value) {
|
||||
Override = _override;
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
|
||||
[CreateAssetMenu(fileName = "Main Path Extender", menuName = "DunGenExtender/Main Path Extender", order = 2)]
|
||||
public class MainPathExtender : ScriptableObject {
|
||||
|
||||
public PropertyOverride<IntRange> Length = new PropertyOverride<IntRange>(false, new IntRange(5, 10));
|
||||
|
||||
public PropertyOverride<BranchMode> BranchMode = new PropertyOverride<BranchMode>(false, DunGen.BranchMode.Local);
|
||||
public PropertyOverride<IntRange> BranchCount = new PropertyOverride<IntRange>(false, new IntRange(1, 5));
|
||||
|
||||
public PropertyOverride<List<GraphNode>> Nodes = new PropertyOverride<List<GraphNode>>(false, new List<GraphNode>());
|
||||
public PropertyOverride<List<GraphLine>> Lines = new PropertyOverride<List<GraphLine>>(false, new List<GraphLine>());
|
||||
|
||||
[Header("DEV ONLY: DON'T TOUCH")]
|
||||
public string Version = "0";
|
||||
|
||||
public static IntRange GetLength(MainPathExtender extender, DungeonFlow flow) {
|
||||
if (extender && extender.Length.Override) return extender.Length.Value;
|
||||
return flow.Length;
|
||||
}
|
||||
|
||||
public static BranchMode GetBranchMode(MainPathExtender extender, DungeonFlow flow) {
|
||||
if (extender && extender.BranchMode.Override) return extender.BranchMode.Value;
|
||||
return flow.BranchMode;
|
||||
}
|
||||
|
||||
public static IntRange GetBranchCount(MainPathExtender extender, DungeonFlow flow) {
|
||||
if (extender && extender.BranchCount.Override) return extender.BranchCount.Value;
|
||||
return flow.BranchCount;
|
||||
}
|
||||
|
||||
public static List<GraphNode> GetNodes(MainPathExtender extender, DungeonFlow flow) {
|
||||
if (extender && extender.Nodes.Override) return extender.Nodes.Value;
|
||||
return flow.Nodes;
|
||||
}
|
||||
|
||||
public static List<GraphLine> GetLines(MainPathExtender extender, DungeonFlow flow) {
|
||||
if (extender && extender.Lines.Override) return extender.Lines.Value;
|
||||
return flow.Lines;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -13,6 +13,8 @@ using DunGenPlus.Generation;
|
|||
using DunGenPlus.Managers;
|
||||
using DunGenPlus.Collections;
|
||||
using DunGenPlus.DevTools;
|
||||
using DunGen.Graph;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DunGenPlus.Patches {
|
||||
internal class DungeonGeneratorPatch {
|
||||
|
@ -23,6 +25,10 @@ namespace DunGenPlus.Patches {
|
|||
if (DevDebugManager.Instance && !isRetry) {
|
||||
DevDebugManager.Instance.RecordNewSeed(__instance.ChosenSeed);
|
||||
}
|
||||
|
||||
if (DunGenPlusGenerator.Active && DunGenPlusGenerator.ActiveAlternative) {
|
||||
DunGenPlusGenerator.SetCurrentMainPathExtender(0);
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
|
@ -42,9 +48,6 @@ namespace DunGenPlus.Patches {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(DungeonGenerator), "GenerateMainPath", MethodType.Enumerator)]
|
||||
public static IEnumerable<CodeInstruction> GenerateMainPathPatch(IEnumerable<CodeInstruction> instructions){
|
||||
|
@ -78,6 +81,116 @@ namespace DunGenPlus.Patches {
|
|||
archSequence.ReportComplete();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(DungeonGenerator), "GenerateMainPath", MethodType.Enumerator)]
|
||||
public static IEnumerable<CodeInstruction> GenerateMainPathGetLineAtDepthPatch(IEnumerable<CodeInstruction> instructions){
|
||||
|
||||
var getLineFunction = typeof(DungeonFlow).GetMethod("GetLineAtDepth", BindingFlags.Instance | BindingFlags.Public);
|
||||
var nodesField = typeof(DungeonFlow).GetField("Nodes", BindingFlags.Instance | BindingFlags.Public);
|
||||
|
||||
var lineSequence = new InstructionSequenceStandard("GetLineAtDepth");
|
||||
lineSequence.AddBasic(OpCodes.Callvirt, getLineFunction);
|
||||
|
||||
var nodesSequence = new InstructionSequenceStandard("Nodes", false);
|
||||
nodesSequence.AddBasic(OpCodes.Ldfld, nodesField);
|
||||
|
||||
foreach(var instruction in instructions){
|
||||
if (lineSequence.VerifyStage(instruction)) {
|
||||
var specialFunction = typeof(DunGenPlusGenerator).GetMethod("GetLineAtDepth", BindingFlags.Static | BindingFlags.Public);
|
||||
|
||||
yield return new CodeInstruction(OpCodes.Call, specialFunction);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nodesSequence.VerifyStage(instruction)) {
|
||||
var specialFunction = typeof(DunGenPlusGenerator).GetMethod("GetNodes", BindingFlags.Static | BindingFlags.Public);
|
||||
|
||||
yield return new CodeInstruction(OpCodes.Call, specialFunction);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
yield return instruction;
|
||||
}
|
||||
|
||||
lineSequence.ReportComplete();
|
||||
nodesSequence.ReportComplete();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(BranchCountHelper), "ComputeBranchCounts")]
|
||||
public static IEnumerable<CodeInstruction> ComputeBranchCountsPatch(IEnumerable<CodeInstruction> instructions){
|
||||
|
||||
var branchModeField = typeof(DungeonFlow).GetField("BranchMode", BindingFlags.Instance | BindingFlags.Public);
|
||||
|
||||
var branchSequence = new InstructionSequenceStandard("BranchMode", false);
|
||||
branchSequence.AddBasic(OpCodes.Ldfld, branchModeField);
|
||||
|
||||
foreach(var instruction in instructions){
|
||||
if (branchSequence.VerifyStage(instruction)) {
|
||||
var specialFunction = typeof(DunGenPlusGenerator).GetMethod("GetBranchMode", BindingFlags.Static | BindingFlags.Public);
|
||||
|
||||
yield return new CodeInstruction(OpCodes.Call, specialFunction);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return instruction;
|
||||
}
|
||||
|
||||
branchSequence.ReportComplete();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(BranchCountHelper), "ComputeBranchCountsGlobal")]
|
||||
public static IEnumerable<CodeInstruction> ComputeBranchCountsGlobalPatch(IEnumerable<CodeInstruction> instructions){
|
||||
|
||||
var branchCountField = typeof(DungeonFlow).GetField("BranchCount", BindingFlags.Instance | BindingFlags.Public);
|
||||
|
||||
var branchSequence = new InstructionSequenceStandard("BranchCount");
|
||||
branchSequence.AddBasic(OpCodes.Ldfld, branchCountField);
|
||||
|
||||
foreach(var instruction in instructions){
|
||||
if (branchSequence.VerifyStage(instruction)) {
|
||||
var specialFunction = typeof(DunGenPlusGenerator).GetMethod("GetBranchCount", BindingFlags.Static | BindingFlags.Public);
|
||||
|
||||
yield return new CodeInstruction(OpCodes.Call, specialFunction);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return instruction;
|
||||
}
|
||||
|
||||
branchSequence.ReportComplete();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(DungeonGenerator), "InnerGenerate", MethodType.Enumerator)]
|
||||
public static IEnumerable<CodeInstruction> InnerGenerateLengthPatch(IEnumerable<CodeInstruction> instructions){
|
||||
|
||||
var lengthField = typeof(DungeonFlow).GetField("Length", BindingFlags.Instance | BindingFlags.Public);
|
||||
|
||||
var lengthSequence = new InstructionSequenceStandard("Length");
|
||||
lengthSequence.AddBasic(OpCodes.Ldfld, lengthField);
|
||||
|
||||
foreach(var instruction in instructions){
|
||||
if (lengthSequence.VerifyStage(instruction)) {
|
||||
var specialFunction = typeof(DunGenPlusGenerator).GetMethod("GetLength", BindingFlags.Static | BindingFlags.Public);
|
||||
|
||||
yield return new CodeInstruction(OpCodes.Call, specialFunction);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return instruction;
|
||||
}
|
||||
|
||||
lengthSequence.ReportComplete();
|
||||
}
|
||||
|
||||
/*
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(DungeonGenerator), "AddTile")]
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace DunGenPlus {
|
|||
|
||||
internal const string modGUID = "dev.ladyalice.dungenplus";
|
||||
private const string modName = "Dungeon Generation Plus";
|
||||
private const string modVersion = "1.1.2";
|
||||
private const string modVersion = "1.2.0";
|
||||
|
||||
internal readonly Harmony Harmony = new Harmony(modGUID);
|
||||
|
||||
|
|
Loading…
Reference in New Issue