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