Decompiled source of CycleRandomizer v1.0.2

CycleRandomizer.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CycleRandomizer.Patches;
using DunGen;
using HarmonyLib;
using LethalLevelLoader;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Video;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("CycleRandomizer")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CycleRandomizer")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("3f8d7100-f4c7-4c78-86cc-49272a0208d5")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace CycleRandomizer
{
	internal class ConfigManager
	{
		public static ConfigEntry<bool> isCycleDungeon;

		public static ConfigEntry<bool> isMoonScreenHided;

		internal static void Load()
		{
			isCycleDungeon = CycleRandomizer.configFile.Bind<bool>("_Global_", "Cycle Dungeon", true, "Activate dungeon cycling.");
			isMoonScreenHided = CycleRandomizer.configFile.Bind<bool>("_Global_", "Hide Infos", true, "Hide information on moon screen.");
		}
	}
	[BepInPlugin("Lega.CycleRandomizer", "Cycle Randomizer", "1.0.2")]
	internal class CycleRandomizer : BaseUnityPlugin
	{
		private const string modGUID = "Lega.CycleRandomizer";

		private const string modName = "Cycle Randomizer";

		private const string modVersion = "1.0.2";

		private readonly Harmony harmony = new Harmony("Lega.CycleRandomizer");

		internal static ManualLogSource mls;

		public static ConfigFile configFile;

		public static List<string> cycleMoons = new List<string>();

		public static List<string> cycleDungeons = new List<string>();

		public static List<Dictionary<string, int>> planetWeights = new List<Dictionary<string, int>>();

		private void Awake()
		{
			mls = Logger.CreateLogSource("CycleRandomizer");
			configFile = ((BaseUnityPlugin)this).Config;
			ConfigManager.Load();
			harmony.PatchAll(typeof(CycleRandomizer));
			harmony.PatchAll(typeof(StartOfRoundPatch));
			harmony.PatchAll(typeof(TerminalPatch));
			harmony.PatchAll(typeof(MoonPatch));
			harmony.PatchAll(typeof(DungeonPatch));
		}
	}
}
namespace CycleRandomizer.Patches
{
	internal class DungeonPatch
	{
		[HarmonyPatch(typeof(DungeonGenerator), "Generate")]
		[HarmonyPostfix]
		private static void GenerateDungeon()
		{
			AddCycleDungeon(DungeonManager.CurrentExtendedDungeonFlow.DungeonName, autoClear: true);
		}

		[HarmonyPatch(typeof(DungeonManager), "GetValidExtendedDungeonFlows")]
		[HarmonyPostfix]
		private static void PreventDungeon(ref List<ExtendedDungeonFlowWithRarity> __result)
		{
			if (!ConfigManager.isCycleDungeon.Value)
			{
				return;
			}
			List<ExtendedDungeonFlowWithRarity> list = new List<ExtendedDungeonFlowWithRarity>();
			foreach (ExtendedDungeonFlowWithRarity item in __result)
			{
				if (!CycleRandomizer.cycleDungeons.Contains(item.extendedDungeonFlow.DungeonName))
				{
					list.Add(item);
				}
			}
			if (list.Count > 0)
			{
				__result = list;
			}
		}

		internal static bool AddCycleDungeon(string dungeonName, bool autoClear = false)
		{
			if (!CycleRandomizer.cycleDungeons.Contains(dungeonName))
			{
				CycleRandomizer.cycleDungeons.Add(dungeonName);
				if (autoClear && CycleRandomizer.cycleDungeons.Count == PatchedContent.ExtendedDungeonFlows.Select((ExtendedDungeonFlow d) => d.DungeonName).Distinct().Count())
				{
					CycleRandomizer.cycleDungeons.Clear();
				}
				RefreshTerminalCycleDungeons();
				return true;
			}
			return false;
		}

		internal static bool RemoveCycleDungeon(string dungeonName)
		{
			if (!CycleRandomizer.cycleDungeons.Contains(dungeonName))
			{
				return false;
			}
			CycleRandomizer.cycleDungeons.Remove(dungeonName);
			RefreshTerminalCycleDungeons();
			return true;
		}

		internal static void RefreshTerminalCycleDungeons()
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			string text = "List of dungeons that cannot be randomly selected:\n\n";
			foreach (string cycleDungeon in CycleRandomizer.cycleDungeons)
			{
				text = text + "* " + cycleDungeon + "\n";
			}
			text += "\n\n";
			Terminal val = (Terminal)AccessTools.Field(typeof(HUDManager), "terminalScript").GetValue(HUDManager.Instance);
			val.terminalNodes.allKeywords.First((TerminalKeyword k) => ((Object)k).name.Equals("CycleDisplayDungeons")).specialKeywordResult.displayText = text;
		}
	}
	internal class MoonPatch
	{
		[HarmonyPatch(typeof(StartOfRound), "StartGame")]
		[HarmonyPostfix]
		private static void StartGame(ref SelectableLevel ___currentLevel)
		{
			AddCycleMoon(___currentLevel.PlanetName, autoClear: true);
		}

		internal static bool AddCycleMoon(string planetName, bool autoClear = false)
		{
			if (!CycleRandomizer.cycleMoons.Contains(planetName))
			{
				CycleRandomizer.cycleMoons.Add(planetName);
				if (autoClear && CycleRandomizer.cycleMoons.Count == StartOfRound.Instance.levels.Where((SelectableLevel l) => l.planetHasTime).Count())
				{
					CycleRandomizer.cycleMoons.Clear();
				}
				RefreshTerminalCycleMoons();
				return true;
			}
			return false;
		}

		internal static bool RemoveCycleMoon(string planetName)
		{
			if (!CycleRandomizer.cycleMoons.Contains(planetName))
			{
				return false;
			}
			CycleRandomizer.cycleMoons.Remove(planetName);
			RefreshTerminalCycleMoons();
			return true;
		}

		internal static void RefreshTerminalCycleMoons()
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			string text = "List of moons that cannot be randomly selected:\n\n";
			foreach (string cycleMoon in CycleRandomizer.cycleMoons)
			{
				text = text + "* " + cycleMoon + "\n";
			}
			text += "\n\n";
			Terminal val = (Terminal)AccessTools.Field(typeof(HUDManager), "terminalScript").GetValue(HUDManager.Instance);
			val.terminalNodes.allKeywords.First((TerminalKeyword k) => ((Object)k).name.Equals("CycleDisplayMoons")).specialKeywordResult.displayText = text;
		}
	}
	internal class StartOfRoundPatch
	{
		[HarmonyPatch(typeof(StartOfRound), "Start")]
		[HarmonyPostfix]
		private static void BindMoonsConfig(ref StartOfRound __instance)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			foreach (string item in from l in __instance.levels
				where l.planetHasTime
				select l.PlanetName)
			{
				if (!CycleRandomizer.configFile.ContainsKey(new ConfigDefinition("Moons", item + " Weight")))
				{
					ConfigEntry<int> val = CycleRandomizer.configFile.Bind<int>("Moons", item + " Weight", 1, "Weighting value for " + item + " to be randomly selected");
					CycleRandomizer.planetWeights.Add(new Dictionary<string, int> { { item, val.Value } });
				}
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "SetMapScreenInfoToCurrentLevel")]
		[HarmonyAfter(new string[] { "mrov.WeatherRegistry" })]
		[HarmonyPostfix]
		private static void HideMapScreenInfo(ref StartOfRound __instance, ref VideoPlayer ___screenLevelVideoReel, ref TextMeshProUGUI ___screenLevelDescription)
		{
			if (ConfigManager.isMoonScreenHided.Value && !((Object)__instance.currentLevel).name.Equals("CompanyBuildingLevel"))
			{
				((TMP_Text)___screenLevelDescription).text = "Orbiting: Unknown\nPOPULATION: Unknown\nCONDITIONS: Unknown\nFAUNA: Unknown\nWeather: Unknown";
				((Behaviour)___screenLevelVideoReel).enabled = false;
				___screenLevelVideoReel.clip = null;
				((Component)___screenLevelVideoReel).gameObject.SetActive(false);
				___screenLevelVideoReel.Stop();
			}
		}
	}
	internal class TerminalPatch
	{
		[HarmonyPatch(typeof(Terminal), "Awake")]
		[HarmonyPostfix]
		private static void AddCommands(ref Terminal __instance)
		{
			AddCycleRandomCommand(ref __instance);
			AddCycleDisplayCommands(ref __instance);
			AddCycleAddRemoveCommands(ref __instance, "Moon", "cam", "crm", from l in StartOfRound.Instance.levels
				where l.planetHasTime
				select l.PlanetName);
			AddCycleAddRemoveCommands(ref __instance, "Dungeon", "cad", "crd", PatchedContent.ExtendedDungeonFlows.Select((ExtendedDungeonFlow d) => d.DungeonName).Distinct());
		}

		[HarmonyPatch(typeof(Terminal), "ParsePlayerSentence")]
		[HarmonyPostfix]
		private static void RunCommands(ref TerminalNode __result, ref Terminal __instance)
		{
			if ((Object)(object)__result == (Object)null)
			{
				return;
			}
			if (!((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsServer && !((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsHost && (((Object)__result).name.Contains("cycle") || ((Object)__result).name.Contains("Cycle")))
			{
				__result = CreateTerminalNode("Unauthorized", "Command not found or usable only by host.\n\n\n");
			}
			else if (((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsServer || ((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsHost)
			{
				if (((Object)__result).name.Equals("cyclerandomNode"))
				{
					HandleCycleRandomNode(ref __result, ref __instance);
				}
				else if (((Object)__result).name.Contains("cycleaddmoon") || ((Object)__result).name.Contains("cycleremovemoon"))
				{
					HandleCycleAddRemoveNode(ref __result, "moon", ((Object)__result).name.Contains("add"));
				}
				else if (((Object)__result).name.Contains("cycleadddungeon") || ((Object)__result).name.Contains("cycleremovedungeon"))
				{
					HandleCycleAddRemoveNode(ref __result, "dungeon", ((Object)__result).name.Contains("add"));
				}
			}
		}

		private static void AddCycleRandomCommand(ref Terminal __instance)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			TerminalKeyword val = ((IEnumerable<TerminalKeyword>)__instance.terminalNodes.allKeywords).FirstOrDefault((Func<TerminalKeyword, bool>)((TerminalKeyword k) => ((Object)k).name == "Route"));
			TerminalKeyword val2 = CreateTerminalKeyword("CycleRandom", "cyclerandom", isVerb: false, val);
			__instance.terminalNodes.allKeywords = CollectionExtensions.AddToArray<TerminalKeyword>(__instance.terminalNodes.allKeywords, val2);
			val.compatibleNouns = CollectionExtensions.AddToArray<CompatibleNoun>(val.compatibleNouns, new CompatibleNoun
			{
				noun = val2,
				result = CreateTerminalNode("cyclerandomNode", null)
			});
		}

		private static void AddCycleDisplayCommands(ref Terminal __instance)
		{
			AddCycleDisplayCommand(ref __instance, "CycleDisplayMoons", "cdm", "CycleMCatalogue", "List of moons that cannot be randomly selected:\n\n\n");
			AddCycleDisplayCommand(ref __instance, "CycleDisplayDungeons", "cdd", "CycleDCatalogue", "List of dungeons that cannot be randomly selected:\n\n\n");
		}

		private static void AddCycleDisplayCommand(ref Terminal __instance, string name, string word, string nodeName, string displayText)
		{
			TerminalKeyword val = CreateTerminalKeyword(name, word, isVerb: false, null, CreateTerminalNode(nodeName, displayText));
			__instance.terminalNodes.allKeywords = CollectionExtensions.AddToArray<TerminalKeyword>(__instance.terminalNodes.allKeywords, val);
		}

		private static void AddCycleAddRemoveCommands(ref Terminal __instance, string type, string addWord, string removeWord, IEnumerable<string> names)
		{
			TerminalKeyword parentKeyword = CreateTerminalKeyword("CycleAdd" + type, addWord, isVerb: true);
			__instance.terminalNodes.allKeywords = CollectionExtensions.AddToArray<TerminalKeyword>(__instance.terminalNodes.allKeywords, parentKeyword);
			TerminalKeyword parentKeyword2 = CreateTerminalKeyword("CycleRemove" + type, removeWord, isVerb: true);
			__instance.terminalNodes.allKeywords = CollectionExtensions.AddToArray<TerminalKeyword>(__instance.terminalNodes.allKeywords, parentKeyword2);
			foreach (string name3 in names)
			{
				string name = GetNameOnlyWithLetters(name3);
				string name2 = GetFirstPart(name3);
				if (!string.IsNullOrEmpty(name2))
				{
					AddCycleAddRemoveCommand(ref __instance, ref parentKeyword, "cycleadd" + type.ToLower() + name.ToLower() + "Node", ref name2);
					AddCycleAddRemoveCommand(ref __instance, ref parentKeyword2, "cycleremove" + type.ToLower() + name.ToLower() + "Node", ref name2);
				}
				AddCycleAddRemoveCommand(ref __instance, ref parentKeyword, "cycleadd" + type.ToLower() + name.ToLower() + "NodeFull", ref name);
				AddCycleAddRemoveCommand(ref __instance, ref parentKeyword2, "cycleremove" + type.ToLower() + name.ToLower() + "NodeFull", ref name);
			}
		}

		private static void AddCycleAddRemoveCommand(ref Terminal __instance, ref TerminalKeyword parentKeyword, string nodeWord, ref string name)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			TerminalKeyword val = CreateTerminalKeyword(((Object)parentKeyword).name + name, name.ToLower(), isVerb: false, parentKeyword);
			__instance.terminalNodes.allKeywords = CollectionExtensions.AddToArray<TerminalKeyword>(__instance.terminalNodes.allKeywords, val);
			parentKeyword.compatibleNouns = CollectionExtensions.AddToArray<CompatibleNoun>(parentKeyword.compatibleNouns, new CompatibleNoun
			{
				noun = val,
				result = CreateTerminalNode(nodeWord, null)
			});
		}

		private static void HandleCycleRandomNode(ref TerminalNode __result, ref Terminal __instance)
		{
			List<CompatibleNoun> compatibleNouns = __instance.terminalNodes.allKeywords.First((TerminalKeyword k) => ((Object)k).name.Equals("Route")).compatibleNouns.Where((CompatibleNoun n) => n.result.buyRerouteToMoon == -2 && !CycleRandomizer.cycleMoons.Contains(StartOfRound.Instance.levels[n.result.displayPlanetInfo].PlanetName)).ToList();
			if (compatibleNouns.Count <= 0)
			{
				__result = CreateTerminalNode("NoMoonFound", "No moon found.\n\n\n");
				return;
			}
			CompatibleNoun val = GetRandomMoon(ref compatibleNouns);
			if (val == null)
			{
				CycleRandomizer.mls.LogInfo((object)"No moons could be recovered from the weight configurations.");
				val = compatibleNouns[new Random().Next(compatibleNouns.Count)];
			}
			TerminalNode result = val.result.terminalOptions.First((CompatibleNoun c) => ((Object)c.noun).name == "Confirm").result;
			__result = CreateTerminalNode("NoMoonInfo", "Routing on a random moon.\n\n\n", result.buyRerouteToMoon);
		}

		private static CompatibleNoun GetRandomMoon(ref List<CompatibleNoun> compatibleNouns)
		{
			List<CompatibleNoun> list = new List<CompatibleNoun>();
			foreach (CompatibleNoun compatibleNoun in compatibleNouns)
			{
				for (int i = 0; i < FindWeightByMoon(StartOfRound.Instance.levels[compatibleNoun.result.displayPlanetInfo].PlanetName); i++)
				{
					list.Add(compatibleNoun);
				}
			}
			if (list.Count > 0)
			{
				return list[new Random().Next(list.Count)];
			}
			return null;
		}

		public static int? FindWeightByMoon(string planetName)
		{
			foreach (Dictionary<string, int> planetWeight in CycleRandomizer.planetWeights)
			{
				if (planetWeight.TryGetValue(planetName, out var value))
				{
					return value;
				}
			}
			return null;
		}

		private static void HandleCycleAddRemoveNode(ref TerminalNode __result, string type, bool isAdd)
		{
			int length = ((isAdd ? "cycleadd" : "cycleremove") + type).Length;
			string typeNode = ((Object)__result).name.Substring(length, ((Object)__result).name.IndexOf("Node") - length);
			string text = ((!(type == "moon")) ? (from d in PatchedContent.ExtendedDungeonFlows.Select((ExtendedDungeonFlow d) => d.DungeonName).Distinct()
				where GetNameOnlyWithLetters(d).ToLower().Contains(typeNode)
				select d).FirstOrDefault() : StartOfRound.Instance.levels.Where((SelectableLevel l) => GetNameOnlyWithLetters(l.PlanetName).ToLower().Contains(typeNode)).FirstOrDefault()?.PlanetName);
			if (string.IsNullOrEmpty(text))
			{
				__result = CreateTerminalNode("Cycle" + (isAdd ? "Add" : "Remove") + type + "NotFound", ((type == "moon") ? "Moon" : "Dungeon") + " not found.\n\n\n");
				return;
			}
			bool flag = ((!(type == "moon")) ? (isAdd ? DungeonPatch.AddCycleDungeon(text) : DungeonPatch.RemoveCycleDungeon(text)) : (isAdd ? MoonPatch.AddCycleMoon(text) : MoonPatch.RemoveCycleMoon(text)));
			__result = CreateTerminalNode("Cycle" + (isAdd ? "Add" : "Remove") + type + "Info" + (flag ? "Success" : "Fail"), text + (flag ? (" has been " + (isAdd ? "added to" : "removed from") + " the list.\n\n\n") : (isAdd ? " is already in the list.\n\n\n" : " is not in the list.\n\n\n")));
		}

		private static TerminalKeyword CreateTerminalKeyword(string name, string word, bool isVerb = false, TerminalKeyword defaultVerb = null, TerminalNode specialKeywordResult = null)
		{
			TerminalKeyword val = ScriptableObject.CreateInstance<TerminalKeyword>();
			((Object)val).name = name;
			val.word = word;
			val.isVerb = isVerb;
			val.defaultVerb = defaultVerb;
			val.specialKeywordResult = specialKeywordResult;
			return val;
		}

		private static TerminalNode CreateTerminalNode(string name, string displayText, int buyRerouteToMoon = -1, int itemCost = 0, bool clearPreviousText = true)
		{
			TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
			((Object)val).name = name;
			val.displayText = displayText;
			val.buyRerouteToMoon = buyRerouteToMoon;
			val.itemCost = itemCost;
			val.clearPreviousText = clearPreviousText;
			return val;
		}

		private static string GetFirstPart(string name)
		{
			Match match = Regex.Match(name, "^[^a-zA-Z]*([a-zA-Z]+)[^a-zA-Z]+[a-zA-Z]");
			return match.Success ? match.Groups[1].Value : string.Empty;
		}

		private static string GetNameOnlyWithLetters(string name)
		{
			return new string(name.Where((char c) => char.IsLetter(c)).ToArray());
		}
	}
}