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";
}
}