Decompiled source of MoonsEqualised v1.0.2

BepInEx\plugins\MoonsEqualised\MoonsEqualised.dll

Decompiled 4 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MoonsEqualised")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MoonsEqualised")]
[assembly: AssemblyTitle("MoonsEqualised")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MoonsEqualised
{
	[BepInPlugin("jakov.moonsequalised", "Moons Equalised", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		private sealed class MoonConfig
		{
			public float FactorySizeMultiplier { get; }

			public int MinScrap { get; }

			public int MaxScrap { get; }

			public int MaxIndoorPower { get; }

			public int MaxOutdoorPower { get; }

			public int FacilityChance { get; }

			public int MineshaftChance { get; }

			public int MansionChance { get; }

			public MoonConfig(float factorySizeMultiplier, int minScrap, int maxScrap, int maxIndoorPower, int maxOutdoorPower, int facilityChance, int mineshaftChance, int mansionChance)
			{
				FactorySizeMultiplier = factorySizeMultiplier;
				MinScrap = minScrap;
				MaxScrap = maxScrap;
				MaxIndoorPower = maxIndoorPower;
				MaxOutdoorPower = maxOutdoorPower;
				FacilityChance = facilityChance;
				MineshaftChance = mineshaftChance;
				MansionChance = mansionChance;
			}
		}

		private static Harmony _harmony;

		private static ManualLogSource _log;

		private void Awake()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			if (_log == null)
			{
				_log = Logger.CreateLogSource("Moons Equalised");
			}
			_log.LogInfo((object)"Moons Equalised awake.");
			if (_harmony == null)
			{
				_harmony = new Harmony("jakov.moonsequalised");
			}
			try
			{
				PatchMethod(typeof(RoundManager), "LoadNewLevel", "RoundManager_LoadNewLevel_Prefix");
				PatchMethod(typeof(Terminal), "LoadNewNode", "Terminal_LoadNewNode_Prefix", "Terminal_LoadNewNode_Postfix");
				PatchMethod(typeof(Terminal), "LoadNewNodeIfAffordable", "Terminal_LoadNewNodeIfAffordable_Prefix", "Terminal_LoadNewNodeIfAffordable_Postfix");
				_log.LogInfo((object)"Harmony patches applied successfully.");
			}
			catch (Exception arg)
			{
				_log.LogError((object)$"Failed to apply Harmony patches: {arg}");
			}
		}

		private static void PatchMethod(Type targetType, string methodName, string patchName, string? postfixName = null)
		{
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			MethodInfo method = targetType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (method == null)
			{
				_log.LogError((object)("Patch target not found: " + targetType.Name + "." + methodName));
				return;
			}
			MethodInfo method2 = typeof(Plugin).GetMethod(patchName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (method2 == null)
			{
				_log.LogError((object)("Patch method not found: " + patchName));
				return;
			}
			HarmonyMethod val = null;
			if (!string.IsNullOrEmpty(postfixName))
			{
				MethodInfo method3 = typeof(Plugin).GetMethod(postfixName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (method3 == null)
				{
					_log.LogError((object)("Patch postfix method not found: " + postfixName));
					return;
				}
				val = new HarmonyMethod(method3);
			}
			_harmony.Patch((MethodBase)method, new HarmonyMethod(method2), val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_log.LogInfo((object)("Patched " + targetType.Name + "." + methodName + " with " + patchName + ((val != null) ? " + postfix" : string.Empty) + "."));
		}

		private static void RoundManager_LoadNewLevel_Prefix(RoundManager __instance, int randomSeed, SelectableLevel newLevel)
		{
			try
			{
				if ((Object)(object)newLevel == (Object)null)
				{
					ManualLogSource log = _log;
					if (log != null)
					{
						log.LogWarning((object)"LoadNewLevel called with a null SelectableLevel.");
					}
					return;
				}
				ManualLogSource log2 = _log;
				if (log2 != null)
				{
					log2.LogInfo((object)("LoadNewLevel called for " + newLevel.PlanetName));
				}
				ApplyLevelPatch(newLevel);
				ApplyDoorPricePatch();
			}
			catch (Exception arg)
			{
				ManualLogSource log3 = _log;
				if (log3 != null)
				{
					log3.LogError((object)$"RoundManager_LoadNewLevel_Prefix error: {arg}");
				}
			}
		}

		[HarmonyPatch(typeof(Terminal), "LoadNewNode")]
		[HarmonyPrefix]
		private static void Terminal_LoadNewNode_Prefix(Terminal __instance, TerminalNode node)
		{
			try
			{
				ApplyTerminalRoutePrice(node);
			}
			catch (Exception arg)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogError((object)$"Terminal_LoadNewNode_Prefix error: {arg}");
				}
			}
		}

		private static void Terminal_LoadNewNode_Postfix(Terminal __instance)
		{
			try
			{
				if ((Object)(object)__instance != (Object)null && (Object)(object)__instance.currentNode != (Object)null)
				{
					ApplyTerminalRoutePrice(__instance.currentNode);
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogError((object)$"Terminal_LoadNewNode_Postfix error: {arg}");
				}
			}
		}

		[HarmonyPatch(typeof(Terminal), "LoadNewNodeIfAffordable")]
		[HarmonyPrefix]
		private static void Terminal_LoadNewNodeIfAffordable_Prefix(Terminal __instance, TerminalNode node)
		{
			try
			{
				ApplyTerminalRoutePrice(node);
			}
			catch (Exception arg)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogError((object)$"Terminal_LoadNewNodeIfAffordable_Prefix error: {arg}");
				}
			}
		}

		private static void Terminal_LoadNewNodeIfAffordable_Postfix(Terminal __instance)
		{
			try
			{
				if ((Object)(object)__instance != (Object)null && (Object)(object)__instance.currentNode != (Object)null)
				{
					ApplyTerminalRoutePrice(__instance.currentNode);
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogError((object)$"Terminal_LoadNewNodeIfAffordable_Postfix error: {arg}");
				}
			}
		}

		private static void ApplyLevelPatch(SelectableLevel level)
		{
			if ((Object)(object)level == (Object)null)
			{
				return;
			}
			Dictionary<string, MoonConfig> dictionary = new Dictionary<string, MoonConfig>
			{
				["Experimentation"] = new MoonConfig(1.1f, 12, 15, 6, 9, 75, 25, 0),
				["Assurance"] = new MoonConfig(1.2f, 13, 15, 6, 8, 65, 35, 0),
				["Vow"] = new MoonConfig(1.1f, 12, 14, 7, 6, 50, 50, 0),
				["Offense"] = new MoonConfig(1.5f, 17, 19, 10, 8, 0, 100, 0),
				["March"] = new MoonConfig(1.3f, 16, 16, 14, 12, 85, 0, 15),
				["Adamance"] = new MoonConfig(1.2f, 16, 18, 13, 11, 50, 50, 0),
				["Rend"] = new MoonConfig(1.8f, 25, 29, 12, 6, 0, 0, 100),
				["Dine"] = new MoonConfig(1.8f, 30, 30, 10, 9, 0, 20, 80),
				["Titan"] = new MoonConfig(2.2f, 31, 33, 16, 7, 34, 33, 33),
				["Artifice"] = new MoonConfig(1.8f, 27, 30, 12, 13, 60, 40, 0)
			};
			string text = NormalizeMoonName(level.PlanetName);
			if (string.IsNullOrEmpty(text))
			{
				return;
			}
			if (dictionary.TryGetValue(text, out var value))
			{
				ApplyMoonConfig(level, value);
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogInfo((object)("Patched " + text + " level values."));
				}
			}
			if (text == "Dine")
			{
				ApplyDineLootPool(level);
			}
		}

		private static void ApplyDoorPricePatch()
		{
			Terminal val = Object.FindObjectOfType<Terminal>();
			if ((Object)(object)val == (Object)null || (Object)(object)val.terminalNodes == (Object)null)
			{
				return;
			}
			List<TerminalNode> terminalNodes = val.terminalNodes.terminalNodes;
			if (terminalNodes == null)
			{
				return;
			}
			foreach (TerminalNode item in terminalNodes)
			{
				ApplyTerminalRoutePrice(item);
			}
		}

		private static void ApplyTerminalRoutePrice(TerminalNode node)
		{
			if ((Object)(object)node == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.levels == null)
			{
				return;
			}
			SelectableLevel[] levels = StartOfRound.Instance.levels;
			foreach (SelectableLevel val in levels)
			{
				if ((Object)(object)val == (Object)null || node.buyRerouteToMoon != val.levelID)
				{
					continue;
				}
				string text = NormalizeMoonName(val.PlanetName);
				switch (text)
				{
				default:
					if (!(text == "Artifice"))
					{
						continue;
					}
					break;
				case "Rend":
				case "Dine":
				case "Titan":
					break;
				}
				node.itemCost = 1000;
				UpdateTerminalRouteUi(node, 1000);
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogInfo((object)("Reroute cost set to 1000 for " + text + "."));
				}
			}
		}

		private static void UpdateTerminalRouteUi(TerminalNode node, int newCost)
		{
			if ((Object)(object)node == (Object)null)
			{
				return;
			}
			if (!string.IsNullOrEmpty(node.displayText))
			{
				node.displayText = ReplaceRouteCost(node.displayText, newCost);
			}
			Terminal val = Object.FindObjectOfType<Terminal>();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if (!string.IsNullOrEmpty(val.currentText))
			{
				val.currentText = ReplaceRouteCost(val.currentText, newCost);
			}
			List<Object> list = new List<Object>();
			if ((Object)(object)val.screenText != (Object)null)
			{
				list.Add((Object)(object)val.screenText);
			}
			if ((Object)(object)val.inputFieldText != (Object)null)
			{
				list.Add((Object)(object)val.inputFieldText);
			}
			if ((Object)(object)val.topRightText != (Object)null)
			{
				list.Add((Object)(object)val.topRightText);
			}
			TextMeshProUGUI[] array = Object.FindObjectsOfType<TextMeshProUGUI>();
			foreach (TextMeshProUGUI val2 in array)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					list.Add((Object)(object)val2);
				}
			}
			foreach (Object item in list)
			{
				if (item == (Object)null)
				{
					continue;
				}
				PropertyInfo property = ((object)item).GetType().GetProperty("text");
				if (property == null || property.PropertyType != typeof(string))
				{
					continue;
				}
				string text = property.GetValue(item) as string;
				if (!string.IsNullOrEmpty(text))
				{
					string text2 = ReplaceRouteCost(text, newCost);
					if (!string.Equals(text, text2, StringComparison.Ordinal))
					{
						property.SetValue(item, text2);
					}
				}
			}
		}

		private static string ReplaceRouteCost(string input, int newCost)
		{
			if (string.IsNullOrEmpty(input))
			{
				return input;
			}
			return Regex.Replace(input, "(?i)(costs?\\s+)(\\d+)(\\s+credits?)", (Match match) => $"{match.Groups[1].Value}{newCost}{match.Groups[3].Value}");
		}

		private static string NormalizeMoonName(string? moonName)
		{
			if (string.IsNullOrWhiteSpace(moonName))
			{
				return string.Empty;
			}
			string text = moonName.Trim();
			string[] array = text.Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
			if (array.Length > 1 && int.TryParse(array[0], out var _))
			{
				return string.Join(" ", array, 1, array.Length - 1);
			}
			return text;
		}

		private static void ApplyMoonConfig(SelectableLevel level, MoonConfig config)
		{
			if (!((Object)(object)level == (Object)null))
			{
				int minScrap = level.minScrap;
				int maxScrap = level.maxScrap;
				int minTotalScrapValue = level.minTotalScrapValue;
				int maxTotalScrapValue = level.maxTotalScrapValue;
				level.factorySizeMultiplier = config.FactorySizeMultiplier;
				level.minScrap = config.MinScrap;
				level.maxScrap = config.MaxScrap;
				if (minScrap > 0)
				{
					level.minTotalScrapValue = Mathf.RoundToInt((float)config.MinScrap * ((float)minTotalScrapValue / (float)minScrap));
				}
				else
				{
					level.minTotalScrapValue = config.MinScrap * 45;
				}
				if (maxScrap > 0)
				{
					level.maxTotalScrapValue = Mathf.RoundToInt((float)config.MaxScrap * ((float)maxTotalScrapValue / (float)maxScrap));
				}
				else
				{
					level.maxTotalScrapValue = config.MaxScrap * 75;
				}
				level.maxEnemyPowerCount = config.MaxIndoorPower;
				level.maxInsideDiversityPowerCount = config.MaxIndoorPower;
				level.maxDaytimeEnemyPowerCount = config.MaxIndoorPower;
				level.maxOutsideEnemyPowerCount = config.MaxOutdoorPower;
				level.maxOutsideDiversityPowerCount = config.MaxOutdoorPower;
				ApplyDungeonWeights(level, config.FacilityChance, config.MineshaftChance, config.MansionChance);
			}
		}

		private static void ApplyDungeonWeights(SelectableLevel level, int facilityChance, int mineshaftChance, int mansionChance)
		{
			if (!((Object)(object)level == (Object)null) && level.dungeonFlowTypes != null)
			{
				SetRarityAtIndex(level.dungeonFlowTypes, 0, facilityChance);
				SetRarityAtIndex(level.dungeonFlowTypes, 1, mineshaftChance);
				SetRarityAtIndex(level.dungeonFlowTypes, 2, mansionChance);
			}
		}

		private static void SetRarityAtIndex(Array dungeonFlowTypes, int index, int value)
		{
			if (dungeonFlowTypes == null || index < 0 || index >= dungeonFlowTypes.Length)
			{
				return;
			}
			object value2 = dungeonFlowTypes.GetValue(index);
			if (value2 != null)
			{
				FieldInfo field = value2.GetType().GetField("rarity", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					field.SetValue(value2, value);
				}
			}
		}

		private static void ApplyDineLootPool(SelectableLevel dineLevel)
		{
			if ((Object)(object)dineLevel == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.levels == null)
			{
				return;
			}
			SelectableLevel[] levels = StartOfRound.Instance.levels;
			foreach (SelectableLevel val in levels)
			{
				if (!((Object)(object)val != (Object)null) || !(NormalizeMoonName(val.PlanetName) == "Rend"))
				{
					continue;
				}
				FieldInfo field = typeof(SelectableLevel).GetField("spawnableScrap", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field2 = typeof(SelectableLevel).GetField("spawnableScrap", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null && field2 != null)
				{
					object value = field.GetValue(val);
					field2.SetValue(dineLevel, value);
					ManualLogSource log = _log;
					if (log != null)
					{
						log.LogInfo((object)"Dine loot pool reset to a Rend-like scrap pool.");
					}
				}
				break;
			}
		}
	}
}