Decompiled source of Exp Normalizer v1.1.1

BepInEx/plugins/com.binbin.ExpNormalization.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExpNormalization;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Obeliskial_Essentials;
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("com.binbin.ExpNormalization")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1+4e9f01795840ad144bb6a229851c65282f31c848")]
[assembly: AssemblyProduct("ExpNormalization")]
[assembly: AssemblyTitle("com.binbin.ExpNormalization")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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;
		}
	}
}
public static class EssentialsCompatibility
{
	private static bool? _enabled;

	public static bool Enabled
	{
		get
		{
			bool valueOrDefault = _enabled == true;
			if (!_enabled.HasValue)
			{
				valueOrDefault = Chainloader.PluginInfos.ContainsKey("com.stiffmeds.obeliskialessentials");
				_enabled = valueOrDefault;
			}
			return _enabled.Value;
		}
	}

	[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
	public static void EssentialsRegister()
	{
		Essentials.RegisterMod(Plugin.PluginName, "binbin", "Exp Normalization", Plugin.PluginVersion, Plugin.ModDate, "https://github.com/binbinmods/ExpNormalization", (string[])null, "", 100, (string[])null, "", true);
		Plugin.LogInfo(Plugin.PluginVersion + " has loaded with Essentials!");
	}
}
namespace ExpNormalization
{
	public class ExpNormalizationFunctions
	{
		public static Dictionary<int, List<int>> DifficultyExpDictionary = new Dictionary<int, List<int>>();

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

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

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

		public static Dictionary<CombatTier, int[]> champTierDict = new Dictionary<CombatTier, int[]>
		{
			{
				(CombatTier)0,
				new int[1] { 2 }
			},
			{
				(CombatTier)1,
				new int[1] { 2 }
			},
			{
				(CombatTier)2,
				new int[1] { 4 }
			},
			{
				(CombatTier)3,
				new int[1] { 6 }
			},
			{
				(CombatTier)4,
				new int[1] { 8 }
			},
			{
				(CombatTier)5,
				new int[1] { 10 }
			},
			{
				(CombatTier)6,
				new int[2] { 6, 8 }
			},
			{
				(CombatTier)7,
				new int[2] { 8, 10 }
			},
			{
				(CombatTier)8,
				new int[1] { 15 }
			},
			{
				(CombatTier)9,
				new int[1] { 16 }
			},
			{
				(CombatTier)10,
				new int[2] { 10, 12 }
			},
			{
				(CombatTier)11,
				new int[1] { 12 }
			},
			{
				(CombatTier)12,
				new int[1] { 12 }
			}
		};

		public static Dictionary<CombatTier, int[]> npcTierDict = new Dictionary<CombatTier, int[]>
		{
			{
				(CombatTier)0,
				new int[1] { 1 }
			},
			{
				(CombatTier)1,
				new int[1] { 1 }
			},
			{
				(CombatTier)2,
				new int[1] { 3 }
			},
			{
				(CombatTier)3,
				new int[2] { 5, 7 }
			},
			{
				(CombatTier)4,
				new int[3] { 5, 7, 9 }
			},
			{
				(CombatTier)5,
				new int[2] { 7, 9 }
			},
			{
				(CombatTier)6,
				new int[2] { 5, 7 }
			},
			{
				(CombatTier)7,
				new int[2] { 7, 9 }
			},
			{
				(CombatTier)8,
				new int[2] { 3, 5 }
			},
			{
				(CombatTier)9,
				new int[2] { 7, 9 }
			},
			{
				(CombatTier)10,
				new int[2] { 9, 11 }
			},
			{
				(CombatTier)11,
				new int[2] { 11, 13 }
			},
			{
				(CombatTier)12,
				new int[2] { 11, 13 }
			}
		};

		public static bool IsRandomCombat()
		{
			bool flag = false;
			try
			{
				NodeData nodeData = Globals.Instance.GetNodeData(AtOManager.Instance.currentMapNode);
				flag = (nodeData.CombatPercent > 0 || nodeData.NodeCombat.Length != 0) && !nodeData.DisableRandom;
				if (nodeData.NodeId == "dream_2")
				{
					Plugin.LogDebug("Exp Normalization: NodeCombat for node " + AtOManager.Instance.currentMapNode + " is dream_2. Not a random combat.", "IsRandomCombat");
					return false;
				}
				if (!flag)
				{
					Plugin.LogDebug($"Exp Normalization: NodeCombat for node {AtOManager.Instance.currentMapNode} is {nodeData.NodeCombat.Length}. Not a random combat.", "IsRandomCombat");
				}
			}
			catch (Exception ex)
			{
				Plugin.LogError(" Error getting random combat: " + ex.ToString(), "IsRandomCombat");
			}
			return flag;
		}

		public static int[] GetEnemyDifficulties(CombatTier combatTier)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return npcTierDict[combatTier];
		}

		public static int[] GetChampionDifficulty(CombatTier combatTier)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return champTierDict[combatTier];
		}

		public static int[] GetHighestExp(int[] difficulty, bool isAct3 = false)
		{
			List<int> list = new List<int>();
			Dictionary<int, List<int>> dictionary = (isAct3 ? Act3DifficultyExpDictionary : DifficultyExpDictionary);
			List<int> list2 = new List<int>();
			for (int i = 0; i < difficulty.Length; i++)
			{
				try
				{
					int num = difficulty[i];
					if (dictionary.TryGetValue(num, out var value))
					{
						if (value.Count < 1)
						{
							Plugin.LogDebug($"Not enough EXP data for npc difficulty {num} to determine highest EXP value.", "GetHighestExp");
						}
						else
						{
							list2.AddRange(value);
						}
					}
					else
					{
						Plugin.LogError($"No EXP data found for npc difficulty {num}.", "GetHighestExp");
					}
				}
				catch (Exception ex)
				{
					Plugin.LogError(" Error getting highest EXP: " + ex.ToString(), "GetHighestExp");
				}
			}
			list2.Sort();
			if (list2.Count < 3)
			{
				Plugin.LogError("Insufficient EXP data found for npc difficulties " + string.Join(", ", difficulty) + ".", "GetHighestExp");
				return list.ToArray();
			}
			list.Add(list2[list2.Count - 1]);
			list.Add(list2[list2.Count - 2]);
			list.Add(list2[list2.Count - 3]);
			Plugin.LogDebug(string.Format("Acquired Highest Experience for Difficulty {0}: {1}", difficulty, string.Join(", ", list)), "GetHighestExp");
			return list.ToArray();
		}

		public static int GetChampionExp(int[] difficulty, bool isAct3 = false)
		{
			int result = 0;
			Dictionary<int, List<int>> dictionary = (isAct3 ? Act3ChampionDifficultyExpDictionary : ChampionDifficultyExpDictionary);
			List<int> list = new List<int>();
			for (int i = 0; i < difficulty.Length; i++)
			{
				try
				{
					int num = difficulty[i];
					if (dictionary.TryGetValue(num, out var value))
					{
						if (value.Count < 1)
						{
							Plugin.LogDebug($"Not enough EXP data for npc difficulty {num} to determine highest EXP value.", "GetChampionExp");
						}
						else
						{
							list.AddRange(value);
						}
					}
					else
					{
						Plugin.LogError($"No EXP data found for npc difficulty {num}.", "GetChampionExp");
					}
				}
				catch (Exception ex)
				{
					Plugin.LogError("Error getting champion EXP: " + ex.ToString(), "GetChampionExp");
				}
			}
			list.Sort();
			if (list.Count < 3)
			{
				Plugin.LogDebug("No EXP data found for npc difficulties " + string.Join(", ", difficulty) + ".", "GetChampionExp");
				return result;
			}
			return list.Last();
		}

		public static void SetDifficultyExpDictionary(Dictionary<string, NPCData> npcDictionary, bool isChampion = false)
		{
			Plugin.LogDebug("Exp Normalization: Populating DifficultyExpDictionary...", "SetDifficultyExpDictionary");
			if (npcDictionary == null || DifficultyExpDictionary == null)
			{
				Plugin.LogError("NPC dictionary or DifficultyExpDictionary is null. Not populating DifficultyExpDictionary.", "SetDifficultyExpDictionary");
				return;
			}
			if (isChampion)
			{
				ChampionDifficultyExpDictionary.Clear();
			}
			else
			{
				DifficultyExpDictionary.Clear();
			}
			foreach (KeyValuePair<string, NPCData> item in npcDictionary)
			{
				NPCData val = item.Value;
				if (!((Object)(object)val == (Object)null) && val.Difficulty != -1)
				{
					int difficulty = val.Difficulty;
					if ((Object)(object)val.NgPlusMob != (Object)null)
					{
						val = val.NgPlusMob;
					}
					if ((Object)(object)val.HellModeMob != (Object)null)
					{
						val = val.HellModeMob;
					}
					int experienceReward = val.ExperienceReward;
					if ((isChampion ? ChampionDifficultyExpDictionary : DifficultyExpDictionary).TryGetValue(difficulty, out var value))
					{
						value.Add(experienceReward);
						value.Sort();
					}
					else
					{
						List<int> value2 = new List<int>(1) { experienceReward };
						(isChampion ? ChampionDifficultyExpDictionary : DifficultyExpDictionary)[difficulty] = value2;
					}
				}
			}
			Plugin.LogDebug($"Exp Normalization: DifficultyExpDictionary populated with {(isChampion ? ChampionDifficultyExpDictionary : DifficultyExpDictionary).Count} difficulty levels.", "SetDifficultyExpDictionary");
		}

		public static void SetAct3DifficultyExpDictionary(Dictionary<string, NPCData> npcDictionary, bool isChampion = false)
		{
			Plugin.LogDebug("Exp Normalization: Populating Act3DifficultyExpDictionary...", "SetAct3DifficultyExpDictionary");
			if (npcDictionary == null || Act3DifficultyExpDictionary == null)
			{
				Plugin.LogError("NPC dictionary or Act3DifficultyExpDictionary is null. Not populating Act3DifficultyExpDictionary.", "SetAct3DifficultyExpDictionary");
				return;
			}
			if (isChampion)
			{
				Act3ChampionDifficultyExpDictionary.Clear();
			}
			else
			{
				Act3DifficultyExpDictionary.Clear();
			}
			foreach (KeyValuePair<string, NPCData> item in npcDictionary)
			{
				NPCData val = item.Value;
				if (!((Object)(object)val == (Object)null) && val.Difficulty != -1)
				{
					int difficulty = val.Difficulty;
					if ((Object)(object)val.UpgradedMob != (Object)null)
					{
						val = val.UpgradedMob;
					}
					if ((Object)(object)val.NgPlusMob != (Object)null)
					{
						val = val.NgPlusMob;
					}
					if ((Object)(object)val.HellModeMob != (Object)null)
					{
						val = val.HellModeMob;
					}
					int experienceReward = val.ExperienceReward;
					if ((isChampion ? Act3ChampionDifficultyExpDictionary : Act3DifficultyExpDictionary).TryGetValue(difficulty, out var value))
					{
						value.Add(experienceReward);
						value.Sort();
					}
					else
					{
						List<int> value2 = new List<int>(1) { experienceReward };
						(isChampion ? Act3ChampionDifficultyExpDictionary : Act3DifficultyExpDictionary)[difficulty] = value2;
					}
				}
			}
			Plugin.LogDebug($"Exp Normalization: Act3DifficultyExpDictionary populated with {(isChampion ? Act3ChampionDifficultyExpDictionary : Act3DifficultyExpDictionary).Count} difficulty levels.", "SetAct3DifficultyExpDictionary");
		}
	}
	[HarmonyPatch]
	public class ExpNormalizationPatches
	{
		public static bool devMode;

		public static bool bSelectingPerk;

		public static bool IsHost()
		{
			return GameManager.Instance.IsMultiplayer() && NetworkManager.Instance.IsMaster();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(AtOManager), "GetExperienceFromCombat")]
		public static void GetExperienceFromCombat(ref int __result)
		{
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.EnableMod.Value)
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)AtOManager.Instance))
			{
				Plugin.LogDebug("Exp Normalization: Null AtOManager. Skipping EXP normalization.", "GetExperienceFromCombat");
				return;
			}
			if (!ExpNormalizationFunctions.IsRandomCombat())
			{
				Plugin.LogDebug("Exp Normalization: Not a random combat encounter. Skipping EXP normalization.", "GetExperienceFromCombat");
				return;
			}
			CombatData currentCombatData = AtOManager.Instance.GetCurrentCombatData();
			if ((Object)(object)currentCombatData == (Object)null)
			{
				Plugin.LogDebug("Exp Normalization: No combat data found for " + AtOManager.Instance.currentMapNode + ".", "GetExperienceFromCombat");
				return;
			}
			NodeData nodeData = Globals.Instance.GetNodeData(AtOManager.Instance.currentMapNode);
			if ((Object)(object)nodeData == (Object)null)
			{
				Plugin.LogDebug("Exp Normalization: No node data found for " + AtOManager.Instance.currentMapNode + ".", "GetExperienceFromCombat");
				return;
			}
			int[] enemyDifficulties = ExpNormalizationFunctions.GetEnemyDifficulties(nodeData.NodeCombatTier);
			int[] championDifficulty = ExpNormalizationFunctions.GetChampionDifficulty(nodeData.NodeCombatTier);
			bool isAct = AtOManager.Instance.GetActNumberForText("") == 3;
			int[] highestExp = ExpNormalizationFunctions.GetHighestExp(enemyDifficulties, isAct);
			int championExp = ExpNormalizationFunctions.GetChampionExp(championDifficulty, isAct);
			__result = highestExp.Sum() + championExp;
			Plugin.LogDebug(string.Format("Exp Normalization Applied: Combat {0}, Highest Difficulty {1}, Champion Difficulty {2}, Total Exp {3} + {4} = {5}", nodeData.NodeId, enemyDifficulties, championDifficulty, string.Join(", ", highestExp), championExp, __result), "GetExperienceFromCombat");
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Globals), "CreateGameContentRoutine")]
		public static void CreateGameContentPostfix(ref IEnumerator __result)
		{
			if (Plugin.EnableMod.Value)
			{
				__result = Plugin.RunAfter(__result, CreateGameContentPostfix);
			}
		}

		public static void CreateGameContentPostfix()
		{
			Plugin.LogDebug("CreateGameContentPostfix - Setting up EXP dictionaries.", "CreateGameContentPostfix");
			try
			{
				Dictionary<string, NPCData> value = Traverse.Create((object)Globals.Instance).Field("_NPCsSource").GetValue<Dictionary<string, NPCData>>();
				if (value == null)
				{
					Plugin.LogError("Special test - NPC dictionary is null. Not setting difficulty EXP dictionary.", "CreateGameContentPostfix");
					return;
				}
				ExpNormalizationFunctions.SetDifficultyExpDictionary(value);
			}
			catch (Exception ex)
			{
				Plugin.LogError("Exp Normalization: Error setting difficulty EXP dictionary: " + ex.ToString(), "CreateGameContentPostfix");
			}
			try
			{
				Dictionary<string, NPCData> value2 = Traverse.Create((object)Globals.Instance).Field("_NPCsSource").GetValue<Dictionary<string, NPCData>>();
				ExpNormalizationFunctions.SetAct3DifficultyExpDictionary(value2);
			}
			catch (Exception ex2)
			{
				Plugin.LogError("Exp Normalization: Error setting Act3 difficulty EXP dictionary: " + ex2.ToString(), "CreateGameContentPostfix");
			}
			try
			{
				Dictionary<string, NPCData> value3 = Traverse.Create((object)Globals.Instance).Field("_NPCsNamed").GetValue<Dictionary<string, NPCData>>();
				if (value3 == null)
				{
					Plugin.LogError("Special test - NPC dictionary is null. Not setting difficulty EXP dictionary.", "CreateGameContentPostfix");
					return;
				}
				ExpNormalizationFunctions.SetDifficultyExpDictionary(value3, isChampion: true);
			}
			catch (Exception ex3)
			{
				Plugin.LogError("Exp Normalization: Error setting difficulty EXP dictionary: " + ex3.ToString(), "CreateGameContentPostfix");
			}
			try
			{
				Dictionary<string, NPCData> value4 = Traverse.Create((object)Globals.Instance).Field("_NPCsNamed").GetValue<Dictionary<string, NPCData>>();
				ExpNormalizationFunctions.SetAct3DifficultyExpDictionary(value4, isChampion: true);
			}
			catch (Exception ex4)
			{
				Plugin.LogError("Exp Normalization: Error setting Act3 difficulty EXP dictionary: " + ex4.ToString(), "CreateGameContentPostfix");
			}
			Plugin.LogDebug("CreateGameContentPostfix - Done setting up EXP dictionaries.", "CreateGameContentPostfix");
		}
	}
	[BepInPlugin("com.binbin.ExpNormalization", "ExpNormalization", "1.1.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInProcess("AcrossTheObelisk.exe")]
	public class Plugin : BaseUnityPlugin
	{
		public static string PluginName;

		public static string PluginVersion;

		public static string PluginGUID;

		internal static int ModDate = int.Parse(DateTime.Today.ToString("yyyyMMdd"));

		private readonly Harmony harmony = new Harmony("com.binbin.ExpNormalization");

		internal static ManualLogSource Log;

		public static string debugBase = "com.binbin.ExpNormalization ";

		public static ConfigEntry<bool> EnableMod { get; set; }

		public static ConfigEntry<bool> EnableDebugging { get; set; }

		private void Awake()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_0039: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_0066: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			string text = "ExpNormalization";
			EnableMod = ((BaseUnityPlugin)this).Config.Bind<bool>(new ConfigDefinition(text, "EnableMod"), true, new ConfigDescription("Enables the mod. If false, the mod will not work then next time you load the game.", (AcceptableValueBase)null, Array.Empty<object>()));
			EnableDebugging = ((BaseUnityPlugin)this).Config.Bind<bool>(new ConfigDefinition(text, "EnableDebugging"), false, new ConfigDescription("Enables the debugging", (AcceptableValueBase)null, Array.Empty<object>()));
			EnableMod.SettingChanged += delegate
			{
				LogDebug($"EnableMod setting changed to {EnableMod.Value}", "Awake");
			};
			EnableDebugging.SettingChanged += delegate
			{
				LogDebug($"EnableDebugging setting changed to {EnableDebugging.Value}", "Awake");
			};
			PluginName = "ExpNormalization";
			PluginVersion = "1.1.1";
			PluginGUID = "com.binbin.ExpNormalization";
			if (EnableMod.Value)
			{
				if (EssentialsCompatibility.Enabled)
				{
					EssentialsCompatibility.EssentialsRegister();
				}
				else
				{
					LogInfo(PluginGUID + " " + PluginVersion + " has loaded!");
				}
				harmony.PatchAll();
			}
		}

		internal static void LogDebug(string msg, [CallerMemberName] string caller = "")
		{
			if (EnableDebugging.Value)
			{
				Log.LogDebug((object)(debugBase + "- " + caller + " - " + msg));
			}
		}

		internal static void LogInfo(string msg)
		{
			Log.LogInfo((object)(debugBase + msg));
		}

		internal static void LogError(string msg, [CallerMemberName] string caller = "")
		{
			Log.LogError((object)(debugBase + "- " + caller + " - " + msg));
		}

		public static IEnumerator RunAfter(IEnumerator original, Action action)
		{
			while (original.MoveNext())
			{
				yield return original.Current;
			}
			action();
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "com.binbin.ExpNormalization";

		public const string PLUGIN_NAME = "ExpNormalization";

		public const string PLUGIN_VERSION = "1.1.1";
	}
}