Decompiled source of Fatal Experiment 2 v4.1.1

plugins/Fatal Experiment 2/CustomLevelDifficulty.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.Json;
using BepInEx;
using BepInEx.IL2CPP;
using Flaff.CustomLevelDifficulty.Data;
using GameData;
using Gear;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using MTFO.Managers;
using Microsoft.CodeAnalysis;
using Player;
using SNetwork;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("CustomLevelDifficulty")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CustomLevelDifficulty")]
[assembly: AssemblyTitle("CustomLevelDifficulty")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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;
		}
	}
}
namespace Flaff.CustomLevelDifficulty
{
	[BepInPlugin("dev.flaff.gtfo.CustomLevelDifficulty", "CustomLevelDifficulty", "1.0.1")]
	public class CustomLevelDifficultyPlugin : BasePlugin
	{
		public const string GUID = "dev.flaff.gtfo.CustomLevelDifficulty";

		public const string NAME = "CustomLevelDifficulty";

		public const string VERSION = "1.0.1";

		public const string AUTHOR = "Flaff";

		public override void Load()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			ClassInjector.RegisterTypeInIl2Cpp<ExpeditionChangeListener>();
			new Harmony("dev.flaff.gtfo.CustomLevelDifficulty").PatchAll();
		}
	}
	public class ExpeditionChangeListener : MonoBehaviour
	{
		private static ExpeditionChangeListener instance;

		private eRundownTier tier = (eRundownTier)99;

		private int expIndex;

		public ExpeditionChangeListener(IntPtr value)
			: base(value)
		{
		}//IL_0003: Unknown result type (might be due to invalid IL or missing references)


		private void Update()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected I4, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if ((int)GameStateManager.CurrentStateName == 5)
			{
				bool num = (int)tier == 99;
				pActiveExpedition activeExpeditionData = RundownManager.GetActiveExpeditionData();
				if (num || tier != activeExpeditionData.tier || expIndex != activeExpeditionData.expeditionIndex)
				{
					GameInfo.ExpeditionIndex = activeExpeditionData.expeditionIndex;
					GameInfo.Tier = activeExpeditionData.tier;
					tier = activeExpeditionData.tier;
					expIndex = activeExpeditionData.expeditionIndex;
					Debug.Log(Object.op_Implicit($"> Current Expedition Changed (Tier: {(int)tier}, ExpIndex: {expIndex})"));
					GameInfo.RemoveBannedGear();
				}
			}
			else
			{
				tier = (eRundownTier)99;
				expIndex = -1;
			}
		}

		public static void Create()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			if ((Object)(object)instance == (Object)null)
			{
				Debug.Log(Object.op_Implicit("> Creating shitass"));
				GameObject val = new GameObject();
				instance = val.AddComponent<ExpeditionChangeListener>();
				Object.DontDestroyOnLoad((Object)val);
			}
		}
	}
	public static class GameInfo
	{
		public static eRundownTier Tier { get; set; }

		public static int ExpeditionIndex { get; set; }

		public static DifficultyData DifficultyData { get; set; }

		public static bool IsGearBannedForLevel(string gearPlayfabInstanceID)
		{
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			if (DifficultyData == null)
			{
				return false;
			}
			List<WeaponRestrictionData> weaponRestrictions = DifficultyData.WeaponRestrictions;
			GearIDRange val = default(GearIDRange);
			PlayerBackpack val3 = default(PlayerBackpack);
			GearIDRange val4 = default(GearIDRange);
			PlayerBackpack val6 = default(PlayerBackpack);
			for (int i = 0; i < weaponRestrictions.Count; i++)
			{
				WeaponRestrictionData weaponRestrictionData = weaponRestrictions[i];
				if (!weaponRestrictionData.internalEnabled || !(weaponRestrictionData.PlayfabInstanceID == gearPlayfabInstanceID))
				{
					continue;
				}
				if (weaponRestrictionData.UseBlacklist)
				{
					for (int j = 0; j < weaponRestrictionData.BlacklistedLevels.Count; j++)
					{
						SpecificLevelData specificLevelData = weaponRestrictionData.BlacklistedLevels[j];
						if (specificLevelData.Tier == Tier && specificLevelData.ExpeditionIndex == ExpeditionIndex)
						{
							Debug.Log(Object.op_Implicit("> " + weaponRestrictionData.name + " is blacklisted"));
							return true;
						}
					}
					SNet_Lobby lobby = SNet.Lobby;
					if (!((Object)(object)lobby != (Object)null) || !GearManager.TryGetGear(gearPlayfabInstanceID, ref val))
					{
						continue;
					}
					Debug.Log(Object.op_Implicit("> Found SNET lobby and gear"));
					ItemDataBlock block = GameDataBlockBase<ItemDataBlock>.GetBlock(val.GetCompID((eGearComponent)3));
					if (block == null)
					{
						continue;
					}
					List<SpecificWeaponLevelData> list = ((weaponRestrictionData.WhitelistedLevels == null) ? new List<SpecificWeaponLevelData>() : weaponRestrictionData.WhitelistedLevels);
					for (int k = 0; k < list.Count; k++)
					{
						SpecificWeaponLevelData specificWeaponLevelData = list[k];
						if (specificWeaponLevelData.Tier != Tier || specificWeaponLevelData.ExpeditionIndex != ExpeditionIndex)
						{
							continue;
						}
						if (specificWeaponLevelData.MaxInstances > 0)
						{
							int num = 0;
							for (int l = 0; l < lobby.Players.Count; l++)
							{
								SNet_Player val2 = lobby.Players[l];
								if ((Object)(object)val2 != (Object)null && !val2.IsLocal && PlayerBackpackManager.TryGetBackpack(val2, ref val3) && val3.HasGear(val, block.inventorySlot))
								{
									num++;
								}
							}
							if (num >= specificWeaponLevelData.MaxInstances)
							{
								Debug.Log(Object.op_Implicit("> Blacklisting " + weaponRestrictionData.name + " because greater than max instances"));
								return true;
							}
						}
						if (specificWeaponLevelData.CharacterRestrictions == null || specificWeaponLevelData.CharacterRestrictions.Count <= 0)
						{
							continue;
						}
						SNet_Player localPlayer = SNet.LocalPlayer;
						if (!((Object)(object)localPlayer != (Object)null))
						{
							continue;
						}
						Debug.Log(Object.op_Implicit($"> Using Slot Restrictions (Player slot index: {localPlayer.CharacterIndex})"));
						for (int m = 0; m < specificWeaponLevelData.CharacterRestrictions.Count; m++)
						{
							WeaponCharacterRestrictionsData weaponCharacterRestrictionsData = specificWeaponLevelData.CharacterRestrictions[m];
							if (weaponCharacterRestrictionsData.CharacterIndex == localPlayer.CharacterIndex && !weaponCharacterRestrictionsData.Enabled)
							{
								Debug.Log(Object.op_Implicit("> Blacklisting " + weaponRestrictionData.name + " because not allowed for slot"));
								return true;
							}
						}
					}
					continue;
				}
				for (int n = 0; n < weaponRestrictionData.WhitelistedLevels.Count; n++)
				{
					SpecificWeaponLevelData specificWeaponLevelData2 = weaponRestrictionData.WhitelistedLevels[n];
					if (specificWeaponLevelData2.Tier != Tier || specificWeaponLevelData2.ExpeditionIndex != ExpeditionIndex)
					{
						continue;
					}
					SNet_Lobby lobby2 = SNet.Lobby;
					if ((Object)(object)lobby2 != (Object)null && GearManager.TryGetGear(gearPlayfabInstanceID, ref val4))
					{
						ItemDataBlock block2 = GameDataBlockBase<ItemDataBlock>.GetBlock(val4.GetCompID((eGearComponent)3));
						if (block2 != null)
						{
							if (specificWeaponLevelData2.MaxInstances > 0)
							{
								int num2 = 0;
								for (int num3 = 0; num3 < lobby2.Players.Count; num3++)
								{
									SNet_Player val5 = lobby2.Players[num3];
									if ((Object)(object)val5 != (Object)null && !val5.IsLocal && PlayerBackpackManager.TryGetBackpack(val5, ref val6) && val6.HasGear(val4, block2.inventorySlot))
									{
										num2++;
									}
								}
								if (num2 >= specificWeaponLevelData2.MaxInstances)
								{
									Debug.Log(Object.op_Implicit("> Blacklisting " + weaponRestrictionData.name + " because greater than max instances"));
									return true;
								}
							}
							if (specificWeaponLevelData2.CharacterRestrictions != null && specificWeaponLevelData2.CharacterRestrictions.Count > 0)
							{
								SNet_Player localPlayer2 = SNet.LocalPlayer;
								if ((Object)(object)localPlayer2 != (Object)null)
								{
									for (int num4 = 0; num4 < specificWeaponLevelData2.CharacterRestrictions.Count; num4++)
									{
										WeaponCharacterRestrictionsData weaponCharacterRestrictionsData2 = specificWeaponLevelData2.CharacterRestrictions[num4];
										if (weaponCharacterRestrictionsData2.CharacterIndex == localPlayer2.CharacterIndex && !weaponCharacterRestrictionsData2.Enabled)
										{
											Debug.Log(Object.op_Implicit("> Blacklisting " + weaponRestrictionData.name + " because not allowed for slot"));
											return true;
										}
									}
								}
							}
						}
					}
					Debug.Log(Object.op_Implicit("> " + weaponRestrictionData.name + " is whitelisted"));
					return false;
				}
				Debug.Log(Object.op_Implicit("> " + weaponRestrictionData.name + " not in whitelist (blacklisted)"));
				return true;
			}
			return false;
		}

		private static void RemoveBannedGearFromSlot(PlayerBackpack pack, InventorySlot slot)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			BackpackItem val = default(BackpackItem);
			if (!pack.TryGetBackpackItem(slot, ref val) || !IsGearBannedForLevel(val.GearIDRange.PlayfabItemInstanceId))
			{
				return;
			}
			Il2CppReferenceArray<GearIDRange> allGearForSlot = GearManager.GetAllGearForSlot(slot);
			for (int i = 0; i < ((Il2CppArrayBase<GearIDRange>)(object)allGearForSlot).Length; i++)
			{
				GearIDRange val2 = ((Il2CppArrayBase<GearIDRange>)(object)allGearForSlot)[i];
				if (!IsGearBannedForLevel(val2.PlayfabItemInstanceId))
				{
					PlayerBackpackManager.ResetLocalAmmoStorage(false);
					PlayerBackpackManager.EquipLocalGear(val2);
					GearManager.RegisterGearInSlotAsEquipped(val2.PlayfabItemInstanceId, slot);
					break;
				}
			}
		}

		public static void RemoveBannedGear()
		{
			PlayerBackpack localBackpack = PlayerBackpackManager.LocalBackpack;
			RemoveBannedGearFromSlot(localBackpack, (InventorySlot)1);
			RemoveBannedGearFromSlot(localBackpack, (InventorySlot)2);
			RemoveBannedGearFromSlot(localBackpack, (InventorySlot)10);
			RemoveBannedGearFromSlot(localBackpack, (InventorySlot)3);
		}
	}
	internal static class Patches
	{
		[HarmonyPatch(typeof(GearManager), "RegisterGearInSlotAsEquipped")]
		private static class NoEquipPatch
		{
			public static bool Prefix(string itemInstanceKey)
			{
				return !GameInfo.IsGearBannedForLevel(itemInstanceKey);
			}
		}

		[HarmonyPatch(typeof(GearManager), "GetAllGearForSlot")]
		private static class GetNonBannedGearPatch
		{
			public static void Postfix(ref Il2CppReferenceArray<GearIDRange> __result)
			{
				List<GearIDRange> list = new List<GearIDRange>();
				for (int i = 0; i < ((Il2CppArrayBase<GearIDRange>)(object)__result).Length; i++)
				{
					if (!GameInfo.IsGearBannedForLevel(((Il2CppArrayBase<GearIDRange>)(object)__result)[i].PlayfabItemInstanceId))
					{
						list.Add(((Il2CppArrayBase<GearIDRange>)(object)__result)[i]);
					}
				}
				__result = Il2CppReferenceArray<GearIDRange>.op_Implicit(list.ToArray());
			}
		}

		[HarmonyPatch(typeof(PlayerBackpackManager), "EquipLocalGear")]
		private static class NoEquipPatch2
		{
			public static void Prefix(ref GearIDRange gearSetup)
			{
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_0081: Unknown result type (might be due to invalid IL or missing references)
				//IL_0083: Unknown result type (might be due to invalid IL or missing references)
				//IL_0095: Expected I4, but got Unknown
				//IL_0095: Unknown result type (might be due to invalid IL or missing references)
				//IL_0098: Invalid comparison between Unknown and I4
				//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
				if (!GameInfo.IsGearBannedForLevel(gearSetup.PlayfabItemInstanceId))
				{
					return;
				}
				Debug.Log(Object.op_Implicit("> SWITCHING TO BANNED GEAR IS NOT ALLOWED!"));
				InventorySlot inventorySlot = GameDataBlockBase<ItemDataBlock>.GetBlock(gearSetup.GetCompID((eGearComponent)3)).inventorySlot;
				Il2CppReferenceArray<GearIDRange> allGearForSlot = GearManager.GetAllGearForSlot(inventorySlot);
				if (allGearForSlot == null)
				{
					return;
				}
				for (int i = 0; i < ((Il2CppArrayBase<GearIDRange>)(object)allGearForSlot).Length; i++)
				{
					GearIDRange val = ((Il2CppArrayBase<GearIDRange>)(object)allGearForSlot)[i];
					if (GameInfo.IsGearBannedForLevel(val.PlayfabItemInstanceId))
					{
						continue;
					}
					Debug.Log(Object.op_Implicit("> Found replacement (" + val.PublicGearName + ")"));
					gearSetup = val;
					switch (inventorySlot - 1)
					{
					default:
						if ((int)inventorySlot == 10)
						{
							GearManager.FavoritesData.LastEquipped_Melee = val.PlayfabItemId;
						}
						break;
					case 0:
						GearManager.FavoritesData.LastEquipped_Standard = val.PlayfabItemId;
						break;
					case 1:
						GearManager.FavoritesData.LastEquipped_Special = val.PlayfabItemId;
						break;
					case 2:
						GearManager.FavoritesData.LastEquipped_Class = val.PlayfabItemId;
						break;
					}
					GearManager.SaveFavoritesData();
					GearManager.RegisterGearInSlotAsEquipped(val.PlayfabItemInstanceId, inventorySlot);
					break;
				}
			}
		}

		[HarmonyPatch(typeof(SNet_GlobalManager), "OnPlayerEvent")]
		private static class PlayerEventHook
		{
			public static void Postfix(SNet_Player player, SNet_PlayerEvent playerEvent, SNet_PlayerEventReason reason)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Invalid comparison between Unknown and I4
				if ((int)playerEvent == 5 && player.IsLocal)
				{
					GameInfo.RemoveBannedGear();
				}
			}
		}

		[HarmonyPatch(typeof(GS_InLevel), "Enter")]
		private static class InLevelPatch
		{
			public static void Postfix()
			{
				OnLevelEnter();
			}
		}

		[HarmonyPatch(typeof(GS_Startup), "Enter")]
		private static class StartupPatch
		{
			public static void Postfix()
			{
				GameInfo.DifficultyData = new DifficultyData();
				if (ConfigManager.HasCustomContent)
				{
					string path = Path.Combine(ConfigManager.CustomPath, "GameData_CustomDifficultyData_bin.json");
					if (File.Exists(path))
					{
						GameInfo.DifficultyData = JsonSerializer.Deserialize<DifficultyData>(File.ReadAllText(path));
					}
				}
				ExpeditionChangeListener.Create();
			}
		}

		[HarmonyPatch(typeof(GS_Generating), "Exit")]
		private static class GeneratingLevelPatch
		{
			public static void Prefix()
			{
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Invalid comparison between Unknown and I4
				if ((int)GameStateManager.Current.m_nextState == 11)
				{
					OnLevelEnter();
				}
			}
		}

		private static void OnLevelEnter()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			List<PlayerBalancingData> playerOverrides = GameInfo.DifficultyData.PlayerOverrides;
			PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent();
			for (int i = 0; i < playerOverrides.Count; i++)
			{
				PlayerBalancingData playerBalancingData = playerOverrides[i];
				if (playerBalancingData.Tier != GameInfo.Tier)
				{
					continue;
				}
				bool flag = true;
				for (int j = 0; j < playerBalancingData.BlacklistedExpeditions.Count; j++)
				{
					if (playerBalancingData.BlacklistedExpeditions[j] == GameInfo.ExpeditionIndex)
					{
						flag = false;
						break;
					}
				}
				if (flag)
				{
					Debug.Log(Object.op_Implicit("Found valid player data"));
					PlayerDataBlock playerData = localPlayerAgent.PlayerData;
					playerData.health = playerBalancingData.Data.health;
					playerData.healthRegenStartDelayAfterDamage = playerBalancingData.Data.healthRegenStartDelayAfterDamage;
					playerData.healthRegenRelMax = playerBalancingData.Data.healthRegenRelMax;
					playerData.healthRegenDelay = playerBalancingData.Data.healthRegenDelay;
					playerData.healthRegenPerSecond = playerBalancingData.Data.healthRegenPerSecond;
					localPlayerAgent.PlayerData = playerData;
				}
			}
		}
	}
}
namespace Flaff.CustomLevelDifficulty.Data
{
	public class DifficultyData
	{
		public List<WeaponRestrictionData> WeaponRestrictions { get; set; }

		public List<PlayerBalancingData> PlayerOverrides { get; set; }

		public DifficultyData()
		{
			WeaponRestrictions = new List<WeaponRestrictionData>();
			PlayerOverrides = new List<PlayerBalancingData>();
		}
	}
	public class PlayerBalancingData
	{
		public eRundownTier Tier { get; set; }

		public List<int> BlacklistedExpeditions { get; set; }

		public PlayerOverrideData Data { get; set; }
	}
	public class PlayerOverrideData
	{
		public float health;

		public float healthRegenStartDelayAfterDamage;

		public float healthRegenRelMax;

		public float healthRegenDelay;

		public float healthRegenPerSecond;
	}
	public class SpecificLevelData
	{
		public eRundownTier Tier { get; set; }

		public int ExpeditionIndex { get; set; }
	}
	public class SpecificWeaponLevelData : SpecificLevelData
	{
		public int MaxInstances { get; set; }

		public List<WeaponCharacterRestrictionsData> CharacterRestrictions { get; set; }
	}
	public class WeaponCharacterRestrictionsData
	{
		public int CharacterIndex { get; set; }

		public bool Enabled { get; set; }
	}
	public class WeaponRestrictionData
	{
		public uint OfflineDataPersistentID { get; set; }

		public bool UseBlacklist { get; set; }

		public List<SpecificLevelData> BlacklistedLevels { get; set; }

		public List<SpecificWeaponLevelData> WhitelistedLevels { get; set; }

		public bool internalEnabled { get; set; }

		public string name { get; set; }

		public string PlayfabInstanceID => "OfflineGear_ID_" + OfflineDataPersistentID;
	}
}