#define DEBUG
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.Json;
using AIGraph;
using AK;
using Agents;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Utils.Collections;
using BoosterImplants;
using CellMenu;
using ChainedPuzzles;
using Enemies;
using GTFO.LobbyExpansion.Compatibility;
using GTFO.LobbyExpansion.Patches.Manual;
using GTFO.LobbyExpansion.Util;
using GameData;
using Gear;
using HarmonyLib;
using Il2CppInterop.Common;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Player;
using PlayerCoverage;
using SNetwork;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("GTFO.LobbyExpansion")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.3.0.0")]
[assembly: AssemblyInformationalVersion("1.3.0+390cccab78c13ff133cdd3f5968e81f36d5be05c")]
[assembly: AssemblyProduct("GTFO.LobbyExpansion")]
[assembly: AssemblyTitle("GTFO.LobbyExpansion")]
[assembly: TargetPlatform("Windows7.0")]
[assembly: SupportedOSPlatform("Windows7.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.3.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
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;
}
}
[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 NativeIntegerAttribute : Attribute
{
public readonly bool[] TransformFlags;
public NativeIntegerAttribute()
{
TransformFlags = new bool[1] { true };
}
public NativeIntegerAttribute(bool[] P_0)
{
TransformFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 GTFO.LobbyExpansion
{
public static class CoolButton
{
private const float ALPHA_OVER = 1f;
private const float ALPHA_OVER_DISABLED = 0.25f;
private const float ALPHA_OUT = 0.66f;
private const float ALPHA_OUT_DISABLED = 0.25f;
private static readonly Color COLOR_OUT = new Color(1f, 1f, 1f, 0.66f);
private static readonly Color COLOR_HOVER = new Color(1f, 1f, 1f, 1f);
private static readonly Color COLOR_DISABLED = new Color(1f, 1f, 1f, 0.25f);
private static GameObject _squareButtonPrefab = null;
public static void SetCoolButtonEnabled(this CM_Item button, bool enabled)
{
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: 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)
if (!((Object)(object)button == (Object)null))
{
button.m_spriteAlphaOut = (enabled ? 0.66f : 0.25f);
button.m_spriteAlphaOver = (enabled ? 1f : 0.25f);
button.m_spriteColorOut = (enabled ? COLOR_OUT : COLOR_DISABLED);
button.m_spriteColorOver = (enabled ? COLOR_HOVER : COLOR_DISABLED);
button.OnHoverOut();
((Behaviour)button.m_collider).enabled = enabled;
}
}
internal static void Setup(CM_PageLoadout pageLoadout)
{
if (!((Object)(object)_squareButtonPrefab != (Object)null))
{
_squareButtonPrefab = CreateButtonPrefab(pageLoadout);
}
}
public static CM_Item InstantiateSquareButton(Transform parent, Vector3 position, bool hideText = false, bool displayArrow = false, bool flipArrow = false)
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_0130: Expected O, but got Unknown
GameObject val = Object.Instantiate<GameObject>(_squareButtonPrefab, parent);
val.gameObject.SetActive(true);
val.transform.localPosition = position;
CM_Item component = val.GetComponent<CM_Item>();
if (hideText)
{
((Component)val.transform.Find("MainText")).gameObject.SetActive(false);
}
Transform val2 = val.transform.Find("Arrow");
((Component)val2).gameObject.SetActive(displayArrow);
if (flipArrow)
{
val2.localRotation = Quaternion.Euler(0f, 0f, -90f);
}
component.m_hoverSpriteArray = Il2CppReferenceArray<SpriteRenderer>.op_Implicit(((IEnumerable<SpriteRenderer>)val.gameObject.GetComponentsInChildren<SpriteRenderer>(true)).ToArray());
foreach (SpriteRenderer item in (Il2CppArrayBase<SpriteRenderer>)(object)component.m_hoverSpriteArray)
{
item.color = new Color(1f, 1f, 1f, 0.66f);
}
component.m_spriteAlphaOver = 1f;
component.m_spriteAlphaOut = 0.66f;
component.m_alphaSpriteOnHover = true;
component.m_onBtnPress = new UnityEvent();
((RectTransformComp)component).Setup();
return component;
}
private static GameObject CreateButtonPrefab(CM_PageLoadout pageLoadout)
{
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
//IL_011c: Unknown result type (might be due to invalid IL or missing references)
//IL_0289: Unknown result type (might be due to invalid IL or missing references)
//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
//IL_019c: Unknown result type (might be due to invalid IL or missing references)
//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
//IL_0213: Unknown result type (might be due to invalid IL or missing references)
//IL_0231: Unknown result type (might be due to invalid IL or missing references)
//IL_024d: Unknown result type (might be due to invalid IL or missing references)
CM_Item component = Object.Instantiate<GameObject>(pageLoadout.m_readyButtonPrefab).GetComponent<CM_Item>();
GameObject gameObject = ((Component)component).gameObject;
Transform transform = gameObject.transform;
Object.Destroy((Object)(object)component);
component = gameObject.AddComponent<CM_Item>();
Object.Destroy((Object)(object)((Component)transform.Find("PressAndHold")).gameObject);
Object.Destroy((Object)(object)((Component)transform.Find("ProgressFillBase")).gameObject);
Object.Destroy((Object)(object)((Component)transform.Find("ProgressFill")).gameObject);
Object.Destroy((Object)(object)((Component)transform.Find("Progress")).gameObject);
Transform val = transform.Find("MainText");
val.localPosition = new Vector3(-20f, -18f, 0f);
component.SetText("<color=white>P1</color>");
Transform val2 = transform.Find("Arrow");
val2.localPosition = new Vector3(0f, -40f, 0f);
val2.localScale = new Vector3(0.3f, 0.3f, 1f);
Transform val3 = transform.Find("Box");
val3.localPosition = new Vector3(0f, -40f, 0f);
for (int i = 0; i < val3.childCount; i++)
{
Transform child = val3.GetChild(i);
switch (((Object)child).name)
{
case "StretchLineT":
child.localScale = new Vector3(0.22f, 4f, 1f);
child.localPosition = new Vector3(-45f, 45f, 0f);
break;
case "StretchLineB":
child.localScale = new Vector3(0.22f, 4f, 1f);
child.localPosition = new Vector3(-45f, -45f, 0f);
break;
case "StretchLineR":
child.localPosition = new Vector3(45f, 45f, 0f);
break;
case "StretchLineL":
child.localScale = new Vector3(0.5f, 1f, 1f);
child.localPosition = new Vector3(-45f, 45f, 0f);
break;
}
}
BoxCollider2D component2 = ((Component)component).GetComponent<BoxCollider2D>();
component2.size = new Vector2(80f, 80f);
((Collider2D)component2).offset = new Vector2(0f, -40f);
((Object)component).name = "LobbyExpander_SwitchLobbyButton";
Object.DontDestroyOnLoad((Object)(object)gameObject);
((Object)gameObject).hideFlags = (HideFlags)61;
gameObject.SetActive(false);
return gameObject;
}
}
public static class HarmonyControlFlow
{
public const bool DontExecute = false;
public const bool Execute = true;
}
internal static class L
{
private static readonly ManualLogSource Logger;
static L()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Expected O, but got Unknown
Logger = new ManualLogSource("GTFO.LobbyExpansion");
Logger.Sources.Add((ILogSource)(object)Logger);
}
internal static void Assert([DoesNotReturnIf(false)] bool condition, object data)
{
if (!condition)
{
string text = "ASSERTION FAILED: " + Format(data);
Fatal(text);
throw new ApplicationException(text);
}
}
[Conditional("DEBUG")]
internal static void DebugWarning(object data)
{
Warning("-------------------------------------------");
Warning("-------------- DEBUG WARNING --------------");
Warning(Format(data));
Warning("-------------------------------------------");
}
[Conditional("DEBUG")]
internal static void Debug(object data)
{
Logger.LogDebug((object)Format(data));
}
internal static void Info(object data)
{
Logger.LogMessage((object)Format(data));
}
[Conditional("DEBUG")]
internal static void Verbose(object data)
{
Logger.LogDebug((object)Format(data));
}
internal static void Error(object data)
{
Logger.LogError((object)Format(data));
}
internal static void Fatal(object data)
{
Logger.LogFatal((object)Format(data));
}
internal static void Warning(object data)
{
Logger.LogWarning((object)Format(data));
}
[Conditional("DEBUG")]
internal static void LogExecutingMethod(string? parameterInfo = "")
{
MethodBase method = new StackFrame(1, needFileInfo: false).GetMethod();
if (method == null)
{
Error("COULD NOT LOG EXECUTING METHOD. THIS SHOULD NOT HAPPEN.");
return;
}
string text = method.DeclaringType?.FullName ?? "???";
string name = method.Name;
string text2 = (string.IsNullOrWhiteSpace(parameterInfo) ? "" : (" (" + parameterInfo + ")"));
Verbose(text + "." + name + text2);
}
private static string Format(object msg)
{
return msg.ToString() ?? "";
}
}
public class LobbyExpansionPlayerCount
{
public byte MaxPlayers { get; set; } = 8;
}
public class LobbyExpansionConfig
{
public Dictionary<int, SlotPermission>? SlotPermissions { get; set; } = new Dictionary<int, SlotPermission>();
public List<string>? CustomExtraBotNames { get; set; } = new List<string>();
public List<string>? BioscanLetters { get; set; } = PluginConfig.DEFAULT_BIOSCAN_LETTERS;
}
public class Pagination
{
public int PageIndex { get; set; }
public event Action? OnPageChanged;
public bool CanPageUp()
{
int num = (int)Math.Ceiling((double)(int)PluginConfig.MaxPlayers / 4.0) - 1;
return PageIndex < num;
}
public bool PageUp()
{
if (CanPageUp())
{
PageIndex++;
this.OnPageChanged?.Invoke();
return true;
}
return false;
}
public bool CanPageDown()
{
return PageIndex > 0;
}
public bool PageDown()
{
if (CanPageDown())
{
PageIndex--;
this.OnPageChanged?.Invoke();
return true;
}
return false;
}
public static int GetLocalPlayerPageIndexFromPillar()
{
foreach (CM_PlayerLobbyBar item in (Il2CppArrayBase<CM_PlayerLobbyBar>)(object)CM_PageLoadout.Current.m_playerLobbyBars)
{
if (!item.m_player.IsLocal)
{
continue;
}
return GetPageFromSlotIndex(item.PlayerSlotIndex);
}
return 0;
}
public static int GetLocalPlayerPageFromSlotIndex()
{
return GetPageFromSlotIndex(SNet.LocalPlayer.PlayerSlot.index);
}
public static int GetPageFromSlotIndex(int slotIndex)
{
return (int)Math.Floor((float)slotIndex / 4f);
}
}
public class PatchingException : Exception
{
public readonly ManualPatch PatchOrigin;
public PatchingException(string? message, ManualPatch origin)
: base(message)
{
PatchOrigin = origin;
}
public PatchingException(string? message, ManualPatch origin, Exception? innerException)
: base(message, innerException)
{
PatchOrigin = origin;
}
}
[BepInPlugin("GTFO.LobbyExpansion", "GTFO.LobbyExpansion", "1.3.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BasePlugin
{
private Harmony _harmony = null;
public override void Load()
{
//IL_0371: Unknown result type (might be due to invalid IL or missing references)
//IL_037b: Expected O, but got Unknown
try
{
PluginConfig.Load();
}
catch (Exception ex)
{
L.Error("Failed to load plugin config?!");
L.Error(ex.GetType().Name + ": " + ex.Message);
L.Warning("StackTrace:\n" + ex.StackTrace);
}
try
{
L.Warning("------------------------------------------------------");
L.Warning("------------------------------------------------------");
L.Warning("------------------------------------------------------");
L.Warning("------------------------------------------------------");
L.Warning("-------------- Applying manual patches. --------------");
L.Warning("------------------------------------------------------");
L.Warning("------------------------------------------------------");
L.Warning("------------------------------------------------------");
L.Warning("------------------------------------------------------");
HashSet<Type> hashSet = new HashSet<Type>();
List<ManualPatch> list = new List<ManualPatch>
{
new CM_PageExpeditionSuccessManualPatch(),
new CM_PageLoadoutManualPatch(),
new CM_PageMapManualPatch(),
new CM_PlayerLobbyBarManualPatch(),
new DiscordManagerManualPatch(),
new GuiManagerManualPatch(),
new PLOC_InElevatorManualPatch(),
new PlayerAgentManualPatch(),
new PlayerBotAIDataManualPatch(),
new PlayerCoverageDataSet_NodeManualPatch(),
new PlayerCoverageDataSet_PortalManualPatch(),
new PlayerManagerManualPatch(),
new PlayerSessionStatusManagerManualPatch(),
new PlayerVoiceManagerManualPatch(),
new SNet_PlayerSlotManagerManualPatch(),
new SNet_SyncManagerManualPatch(),
new CM_PageLoadoutDisplayClassManualPatch()
};
List<PatchingException> list2 = new List<PatchingException>();
foreach (ManualPatch item in list)
{
Type type = item.GetType();
if (hashSet.Contains(type))
{
string text = $"The same patch {type} is being applied twice. Fix this.";
L.Fatal(text);
list2.Add(new PatchingException(text, item));
}
else
{
L.Verbose("Applying manual patch " + item.GetType().Name + ".");
list2.AddRange(item.Apply());
hashSet.Add(type);
}
}
if (list2.Count > 0)
{
L.Fatal("Errors occurred while applying manual patches:");
{
foreach (PatchingException item2 in list2)
{
L.Fatal(item2.PatchOrigin.GetType().Name + ": " + item2.Message);
}
return;
}
}
}
catch (Exception data)
{
L.Fatal("An error occurred while applying manual patches:");
L.Fatal(data);
return;
}
L.Warning("------------------------------------------------------");
L.Warning("------------------------------------------------------");
L.Warning("------------------------------------------------------");
L.Warning("------------------------------------------------------");
L.Warning("-------------- Applying Harmony patches. -------------");
L.Warning("------------------------------------------------------");
L.Warning("------------------------------------------------------");
L.Warning("------------------------------------------------------");
L.Warning("------------------------------------------------------");
try
{
_harmony = new Harmony("GTFO.LobbyExpansion");
_harmony.PatchAll();
}
catch (Exception data2)
{
L.Fatal("An error occurred while applying patches:");
L.Fatal(data2);
return;
}
L.Warning("------------------------------------------------------");
L.Warning("------------------------------------------------------");
L.Warning("------------------------------------------------------");
L.Warning("------------------------------------------------------");
L.Warning("--------- Applying mod compatibility patches. --------");
L.Warning("------------------------------------------------------");
L.Warning("------------------------------------------------------");
L.Warning("------------------------------------------------------");
L.Warning("------------------------------------------------------");
List<ModCompatibilityPatch> list3 = new List<ModCompatibilityPatch>
{
new PacksHelperPatch(),
ChatterRebornPatch.Instance
};
foreach (ModCompatibilityPatch item3 in list3)
{
string name = item3.GetType().Name;
try
{
if (!item3.ShouldApply())
{
L.Verbose("Skipping initialization of " + name + " since the patch deemed it shouldn't be applied.");
return;
}
L.Info("Applying mod compatibility patch " + name + ".");
item3.Apply(_harmony);
}
catch (Exception data3)
{
L.Fatal("An error occurred while applying mod compatibility patch " + name + ":");
L.Fatal(data3);
return;
}
}
L.Info("Loaded plugin GTFO.LobbyExpansion.");
}
}
public static class PluginConfig
{
public const byte DEFAULT_MAX_PLAYERS = 8;
private const string CONFIG_FILE_NAME = "LobbyExpansionConfig.json";
private const string USER_CONFIG_FILE_NAME = "LobbyExpansionConfig_UserData.json";
public static readonly List<string> DEFAULT_BIOSCAN_LETTERS = new List<string>(8) { "A", "B", "C", "D", "E", "F", "G", "H" };
private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions
{
WriteIndented = true
};
private static readonly string _configPath = Path.Combine(Paths.ConfigPath, "LobbyExpansionConfig.json");
private static readonly string _configPathUserData = Path.Combine(Paths.ConfigPath, "LobbyExpansionConfig_UserData.json");
internal static byte MaxPlayers = 8;
private static LobbyExpansionPlayerCount _configPlayerCount = new LobbyExpansionPlayerCount();
private static LobbyExpansionConfig _configUserData = new LobbyExpansionConfig();
private static string[]? _bioscanLettersCache;
internal static void Load()
{
LoadCustomPlayerCount();
if (!File.Exists(_configPathUserData))
{
SaveUserData();
}
string json = File.ReadAllText(_configPathUserData);
_configUserData = JsonSerializer.Deserialize<LobbyExpansionConfig>(json, _serializerOptions) ?? new LobbyExpansionConfig();
LobbyExpansionConfig configUserData = _configUserData;
if (configUserData.SlotPermissions == null)
{
Dictionary<int, SlotPermission> dictionary2 = (configUserData.SlotPermissions = new Dictionary<int, SlotPermission>());
}
configUserData = _configUserData;
if (configUserData.CustomExtraBotNames == null)
{
List<string> list2 = (configUserData.CustomExtraBotNames = new List<string>());
}
configUserData = _configUserData;
if (configUserData.BioscanLetters == null)
{
List<string> list2 = (configUserData.BioscanLetters = DEFAULT_BIOSCAN_LETTERS);
}
}
private static void LoadCustomPlayerCount()
{
if (File.Exists(_configPath))
{
string json = File.ReadAllText(_configPath);
_configPlayerCount = JsonSerializer.Deserialize<LobbyExpansionPlayerCount>(json, _serializerOptions) ?? new LobbyExpansionPlayerCount();
if (_configPlayerCount.MaxPlayers < 4)
{
L.Error("ConfigFile: MaxPlayers must be greater or equal to '4'!");
MaxPlayers = 8;
return;
}
L.Info($"Loaded custom player count from config file: {MaxPlayers} (default) -> {_configPlayerCount.MaxPlayers} (config)");
MaxPlayers = _configPlayerCount.MaxPlayers;
}
}
private static void SaveUserData()
{
string contents = JsonSerializer.Serialize(_configUserData, _serializerOptions);
File.WriteAllText(_configPathUserData, contents);
}
public static SlotPermission GetExtraSlotPermission(int slotIndex)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
return _configUserData.SlotPermissions.GetValueOrDefault(slotIndex, (SlotPermission)4);
}
public static void SetExtraLobbySlotPermissions(int slotIndexMinusOne, SlotPermission permission)
{
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
int num = slotIndexMinusOne + 1;
L.Info($"SetExtraLobbySlotPermissions called: slotIndex:{num}, SlotPermission:{permission}");
_configUserData.SlotPermissions[num] = permission;
SaveUserData();
}
public static string GetExtraSlotNickname(int characterIndex)
{
int num = characterIndex - 4;
if (_configUserData.CustomExtraBotNames.Count > 0 && num < _configUserData.CustomExtraBotNames.Count)
{
string text = _configUserData.CustomExtraBotNames[num];
if (!string.IsNullOrWhiteSpace(text))
{
return text;
}
}
if (1 == 0)
{
}
string result = characterIndex switch
{
4 => "Schaeffer",
5 => "North",
6 => "Henriksson",
7 => "Maddox",
_ => $"Prisoner{characterIndex}",
};
if (1 == 0)
{
}
return result;
}
public static string GetBioscanLetter(int index)
{
List<string> bioscanLetters = _configUserData.BioscanLetters;
if (bioscanLetters != null && bioscanLetters.Count > 0 && index >= 0 && index < bioscanLetters.Count)
{
return bioscanLetters[index];
}
if (index < DEFAULT_BIOSCAN_LETTERS.Count)
{
return DEFAULT_BIOSCAN_LETTERS[index];
}
return ((char)(65 + index)).ToString();
}
public static string[] GetBioscanLetters()
{
if (_bioscanLettersCache != null)
{
return _bioscanLettersCache;
}
_bioscanLettersCache = new string[MaxPlayers];
for (int i = 0; i < MaxPlayers; i++)
{
_bioscanLettersCache[i] = GetBioscanLetter(i);
}
return _bioscanLettersCache;
}
}
internal static class PluginInfo
{
internal const string Guid = "GTFO.LobbyExpansion";
internal const string Name = "GTFO.LobbyExpansion";
internal const string Version = "1.3.0";
}
}
namespace GTFO.LobbyExpansion.Util
{
public static class BepInExUtil
{
public static bool IsPluginLoaded(string pluginGuid)
{
return ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey(pluginGuid);
}
public static object GetPluginInstance(string pluginGuid)
{
if (!((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.TryGetValue(pluginGuid, out var value))
{
throw new InvalidOperationException("Could not retrieve plugin info for plugin with GUID " + pluginGuid + ".");
}
object instance = value.Instance;
if (instance == null)
{
throw new InvalidOperationException("Plugin with GUID " + pluginGuid + " had a null instance.");
}
return instance;
}
}
public static class CoroutineHelpers
{
[CompilerGenerated]
private sealed class <NextFrame>d__0 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public Action action;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <NextFrame>d__0(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = null;
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
action?.Invoke();
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[IteratorStateMachine(typeof(<NextFrame>d__0))]
public static IEnumerator NextFrame(Action action)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <NextFrame>d__0(0)
{
action = action
};
}
}
public abstract class ManualPatch
{
protected record Patch
{
public string Method { get; init; } = "";
public string Description { get; init; } = "";
public string Pattern { get; init; } = "";
public int Offset { get; init; }
public byte[] Bytes { get; init; } = Array.Empty<byte>();
public long? ScanSize { get; init; }
public Type[]? ParameterTypes { get; init; } = Array.Empty<Type>();
}
[CompilerGenerated]
private sealed class <Apply>d__6 : IEnumerable<PatchingException>, IEnumerable, IEnumerator<PatchingException>, IEnumerator, IDisposable
{
private int <>1__state;
private PatchingException <>2__current;
private int <>l__initialThreadId;
public ManualPatch <>4__this;
private List<Patch>.Enumerator <>s__1;
private Patch <patch>5__2;
private Type[] <parameterTypes>5__3;
private nint <methodPointer>5__4;
private nint <signatureAddress>5__5;
private nint <patchAddress>5__6;
private string <message>5__7;
PatchingException IEnumerator<PatchingException>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <Apply>d__6(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
int num = <>1__state;
if (num == -3 || (uint)(num - 1) <= 1u)
{
try
{
}
finally
{
<>m__Finally1();
}
}
<>s__1 = default(List<Patch>.Enumerator);
<patch>5__2 = null;
<parameterTypes>5__3 = null;
<message>5__7 = null;
<>1__state = -2;
}
private bool MoveNext()
{
try
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>4__this.SetupPatches();
<>s__1 = <>4__this.Patches.GetEnumerator();
<>1__state = -3;
break;
case 1:
<>1__state = -3;
break;
case 2:
<>1__state = -3;
break;
}
while (<>s__1.MoveNext())
{
<patch>5__2 = <>s__1.Current;
<parameterTypes>5__3 = <patch>5__2.ParameterTypes ?? Array.Empty<Type>();
string method = <patch>5__2.Method;
bool flag = ((method == ".ctor" || method == "ctor") ? true : false);
<methodPointer>5__4 = (flag ? Memory.GetIl2CppConstructorAddress(<>4__this.TargetType, <parameterTypes>5__3) : Memory.GetIl2CppMethodAddress(<>4__this.TargetType, <patch>5__2.Method, <parameterTypes>5__3));
<signatureAddress>5__5 = Memory.FindSignatureInIl2CppMethod(<methodPointer>5__4, <patch>5__2.Pattern, <patch>5__2.ScanSize);
if (<signatureAddress>5__5 == 0)
{
<>2__current = new PatchingException("Could not find pattern for patch \"" + <patch>5__2.Description + "\".", <>4__this);
<>1__state = 1;
return true;
}
<patchAddress>5__6 = <signatureAddress>5__5 + <patch>5__2.Offset;
if (PatchedAddresses.Contains(<patchAddress>5__6))
{
<message>5__7 = "Patching the same address " + ((IntPtr)<patchAddress>5__6).ToString("X") + "! Something is wrong!";
L.Fatal(<message>5__7);
<>2__current = new PatchingException(<message>5__7, <>4__this);
<>1__state = 2;
return true;
}
L.Verbose("Applying \"" + <patch>5__2.Description + "\" patch at " + ((IntPtr)<patchAddress>5__6).ToString("X"));
Memory.PatchMemory(<patchAddress>5__6, <patch>5__2.Bytes);
PatchedAddresses.Add(<patchAddress>5__6);
<parameterTypes>5__3 = null;
<patch>5__2 = null;
}
<>m__Finally1();
<>s__1 = default(List<Patch>.Enumerator);
return false;
}
catch
{
//try-fault
((IDisposable)this).Dispose();
throw;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
private void <>m__Finally1()
{
<>1__state = -1;
((IDisposable)<>s__1).Dispose();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<PatchingException> IEnumerable<PatchingException>.GetEnumerator()
{
<Apply>d__6 result;
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
result = this;
}
else
{
result = new <Apply>d__6(0)
{
<>4__this = <>4__this
};
}
return result;
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<PatchingException>)this).GetEnumerator();
}
}
private static readonly HashSet<IntPtr> PatchedAddresses = new HashSet<IntPtr>();
protected const byte NOP = 144;
protected List<Patch> Patches { get; } = new List<Patch>();
protected abstract Type TargetType { get; }
[IteratorStateMachine(typeof(<Apply>d__6))]
public IEnumerable<PatchingException> Apply()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <Apply>d__6(-2)
{
<>4__this = this
};
}
protected abstract void SetupPatches();
protected static byte[] GenerateNop(int count)
{
if (count <= 0)
{
throw new ArgumentException("Count must be greater than 0.", "count");
}
return Enumerable.Repeat((byte)144, count).ToArray();
}
}
public static class Memory
{
private record Signature(byte[] Bytes, char[] Mask);
private const long DefaultBlockScanSize = 3000L;
public static nint GetIl2CppConstructorAddress(Type type, params Type[] parameterTypes)
{
ConstructorInfo constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public, parameterTypes);
if (constructor == null)
{
IEnumerable<string> value = parameterTypes.Select((Type x) => x.FullName?.ToString() ?? "null");
throw new MissingMethodException($"Could not find constructor for {type.FullName} with {parameterTypes.Length} parameters ({value}).");
}
return GetIl2CppMethodAddress(type, constructor);
}
public static nint GetIl2CppConstructorAddress<T>(params Type[] parameterTypes) where T : Il2CppObjectBase
{
return GetIl2CppConstructorAddress(typeof(T), parameterTypes);
}
public static nint GetIl2CppMethodAddress(Type type, string methodName)
{
return GetIl2CppMethodAddress(type, methodName, Array.Empty<Type>());
}
public static nint GetIl2CppMethodAddress(Type type, string methodName, Type[] parameterTypes)
{
MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
if (method == null)
{
string value = "";
if (parameterTypes.Length != 0)
{
value = $" with {parameterTypes.Length} parameters (${string.Join(", ", parameterTypes.Select((Type x) => x.FullName?.ToString() ?? x.Name))})";
}
throw new MissingMethodException($"Could not find method {methodName} in type {type.FullName}{value}.");
}
return GetIl2CppMethodAddress(type, method);
}
public static nint GetIl2CppMethodAddress<T>(string methodName) where T : Il2CppObjectBase
{
return GetIl2CppMethodAddress<T>(methodName, Array.Empty<Type>());
}
public static nint GetIl2CppMethodAddress<T>(string methodName, Type[] parameterTypes) where T : Il2CppObjectBase
{
return GetIl2CppMethodAddress(typeof(T), methodName, parameterTypes);
}
public unsafe static nint GetIl2CppMethodAddress(Type type, MethodBase methodBase)
{
FieldInfo il2CppMethodInfoPointerFieldForGeneratedMethod = Il2CppInteropUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(methodBase);
if (il2CppMethodInfoPointerFieldForGeneratedMethod == null)
{
throw new MissingFieldException($"Could not find IL2CPP method info pointer field for method {methodBase} of {type.FullName ?? type.Name}.");
}
object value = il2CppMethodInfoPointerFieldForGeneratedMethod.GetValue(null);
if (value == null)
{
throw new NullReferenceException($"Method info pointer field for method {methodBase} of {type.FullName ?? type.Name} was null.");
}
return *(nint*)(void*)(IntPtr)value;
}
public static nint GetIl2CppMethodAddress<T>(MethodBase methodBase) where T : Il2CppObjectBase
{
return GetIl2CppMethodAddress(typeof(T), methodBase);
}
public static nint FindSignatureInIl2CppMethod(nint methodPointer, string signature, long? blockSize)
{
Signature signature2 = ConvertAobToSignature(signature);
if (signature2 == null)
{
throw new ArgumentException("signature was an invalid signature.");
}
return FindSignatureInBlock(methodPointer, blockSize.GetValueOrDefault(3000L), signature2.Bytes, signature2.Mask);
}
public static nint FindSignatureInIl2CppMethod<T>(string methodName, string signature, long blockSize = 3000L) where T : Il2CppObjectBase
{
nint il2CppMethodAddress = GetIl2CppMethodAddress<T>(methodName);
return FindSignatureInIl2CppMethod(il2CppMethodAddress, signature, blockSize);
}
public static void PatchMemory(IntPtr address, byte[] bytes)
{
if (address == IntPtr.Zero)
{
throw new ArgumentException("address cannot be zero.");
}
if (!Win32.VirtualProtect(address, new IntPtr(bytes.Length), Win32.MemoryProtection.ExecuteReadWrite, out var lpflOldProtect))
{
throw new Exception($"VirtualProtect failed for address {address}.");
}
bool flag = false;
try
{
L.Verbose("Patching " + address.ToString("X") + " with " + string.Join(", ", bytes.Select((byte x) => x.ToString("X"))));
for (int i = 0; i < bytes.Length; i++)
{
Marshal.WriteByte(address, i, bytes[i]);
}
}
catch (Exception value)
{
Console.WriteLine(value);
throw;
}
finally
{
try
{
flag = Win32.VirtualProtect(address, new IntPtr(bytes.Length), lpflOldProtect, out var _);
}
catch
{
L.Error($"VirtualProtect failed to restore protection for address {address}.");
}
}
if (!flag)
{
throw new Exception($"VirtualProtect failed to restore protection for address {address}.");
}
}
private unsafe static nint FindSignatureInBlock(nint block, long blockSize, byte[] pattern, char[] mask)
{
for (long num = 0L; num < blockSize; num++)
{
bool flag = true;
for (uint num2 = 0u; num2 < mask.Length; num2++)
{
if (*(byte*)(num + block + num2) != pattern[num2] && mask[num2] != '?')
{
flag = false;
break;
}
}
if (flag)
{
return (nint)(num + block);
}
}
return 0;
}
private static Signature? ConvertAobToSignature(string signature)
{
if (string.IsNullOrWhiteSpace(signature))
{
return null;
}
string[] array = signature.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (array.Length == 0)
{
return null;
}
byte[] array2 = new byte[array.Length];
char[] array3 = new char[array.Length];
for (int i = 0; i < array.Length; i++)
{
string text = array[i];
if ((text == "?" || text == "??") ? true : false)
{
array2[i] = 0;
array3[i] = '?';
}
else
{
array2[i] = byte.Parse(text, NumberStyles.HexNumber);
array3[i] = 'x';
}
}
return new Signature(array2, array3);
}
}
public static class ReflectionUtil
{
public static void SetStaticField(Type type, string fieldName, object value)
{
FieldInfo field = type.GetField(fieldName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (field == null)
{
throw new ArgumentException($"Could not find static field '{fieldName}' in type '{type.FullName}'.", "fieldName");
}
field.SetValue(null, value);
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
public static Type GetRequiredTypeByName(string name, Assembly assembly)
{
Type[] types = assembly.GetTypes();
Type[] array = types;
foreach (Type type in array)
{
if (type.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
{
return type;
}
}
throw new ArgumentException($"Could not find type '{name}' in assembly '{assembly.FullName ?? "unnamed"}'.");
}
}
public static class Win32
{
[Flags]
public enum MemoryProtection : uint
{
NoAccess = 1u,
ReadOnly = 2u,
ReadWrite = 4u,
WriteCopy = 8u,
Execute = 0x10u,
ExecuteRead = 0x20u,
ExecuteReadWrite = 0x40u,
ExecuteWriteCopy = 0x80u,
GuardModifierflag = 0x100u,
NoCacheModifierflag = 0x200u,
WriteCombineModifierflag = 0x400u
}
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool VirtualProtect(IntPtr lpAddress, IntPtr dwSize, MemoryProtection flNewProtect, out MemoryProtection lpflOldProtect);
}
}
namespace GTFO.LobbyExpansion.Patches.Manual
{
public class CM_PageExpeditionSuccessManualPatch : ManualPatch
{
protected override Type TargetType { get; } = typeof(CM_PageExpeditionSuccess);
protected override void SetupPatches()
{
base.Patches.AddRange(new <>z__ReadOnlySingleElementList<Patch>(new Patch
{
Method = "Setup",
Description = "Adjust hardcoded m_playerReports size in Setup.",
Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8D B7 F0 01 00 00",
Offset = 1,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
}));
}
}
public class CM_PageLoadoutDisplayClassManualPatch : ManualPatch
{
protected override Type TargetType { get; } = typeof(__c__DisplayClass38_1);
protected override void SetupPatches()
{
base.Patches.AddRange(new <>z__ReadOnlySingleElementList<Patch>(new Patch
{
Method = "_ShowPermissionWindow_b__1",
Description = "NOP out Il2Cpp check and assignment of CellSettingsManager.SettingsData.Player.LobbySlotPermissions[num] = this.permission;",
Pattern = "48 85 C9 74 5C 3B 71 18 73 7D 48 63 C6 89 54 81 20",
Offset = 0,
Bytes = ManualPatch.GenerateNop(17)
}));
}
}
public class CM_PageLoadoutManualPatch : ManualPatch
{
protected override Type TargetType { get; } = typeof(CM_PageLoadout);
protected override void SetupPatches()
{
base.Patches.AddRange(new <>z__ReadOnlySingleElementList<Patch>(new Patch
{
Method = "Setup",
Description = $"Adjust CM_PageLoadout Setup m_playerLobbyBars size from 4 -> {PluginConfig.MaxPlayers}.",
Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8B D0 48 89 87 08 02 00 00",
Offset = 1,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
}));
}
}
public class CM_PageMapManualPatch : ManualPatch
{
protected override Type TargetType { get; } = typeof(CM_PageMap);
protected override void SetupPatches()
{
base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[13]
{
new Patch
{
Method = "TryGetInventoryWithSlotIndex",
Description = "Remove CM_PageMap::TryGetInventoryWithSlotIndex slotIndex > 3",
Pattern = "83 FF 03 77 60",
Offset = 2,
Bytes = new byte[1] { (byte)(PluginConfig.MaxPlayers - 1) }
},
new Patch
{
Method = "Setup",
Description = "Adjust CM_PageMap::Setup() m_inventory = new PUI_Inventory[4] to new max players.",
Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 4C 8D A7 38 02 00 00",
Offset = 1,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = "CreatePlayerIcons",
Description = "Adjust CM_PageMap::CreatePlayerIcons() m_syncedPlayers = new CM_MapPlayerGUIItem[4] to new max players.",
Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 49 8D AF 50 02 00 00",
Offset = 1,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = "CreatePlayerIcons",
Description = "Adjust CM_PageMap::CreatePlayerIcons() m_syncedCursors = new CM_Cursor[4] to new max players.",
Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 4D 8D B7 58 02 00 00",
Offset = 1,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = "CreatePlayerIcons",
Description = "Adjust CM_PageMap::CreatePlayerIcons() m_drawPixelBufferIndex = new int[4] to new max players.",
Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 49 8D 8F 80 02 00 00",
Offset = 1,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = "CreatePlayerIcons",
Description = "Adjust CM_PageMap::CreatePlayerIcons() m_drawPixelBuffer = new CM_MapDrawPixel[4][] to new max players.",
Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8B D0 49 89 87 78 02 00 00",
Offset = 1,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = "CreatePlayerIcons",
Description = "Adjust CM_PageMap::CreatePlayerIcons() m_lastDrawingPos = new Vector2[4] to new max players.",
Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 49 8D 8F 68 02 00 00",
Offset = 1,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = "CreatePlayerIcons",
Description = "Adjust CM_PageMap::CreatePlayerIcons() for (int i = 0; i < 4; i++) to new max players.",
Pattern = "83 FE 04 0F 8C A6 FC FF FF",
Offset = 2,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = "UpdatePlayerData",
Description = "Adjust CM_PageMap::UpdatePlayerData() for (int i = 0; i < 4; i++) to new max players.",
Pattern = "83 FB 04 0F 8C 1B FF FF FF",
Offset = 2,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = "UpdateSyncedCursorVisibility",
Description = "Adjust CM_PageMap::UpdateSyncedCursorVisibility() for (int i = 0; i < 4; i++) to new max players.",
Pattern = "83 FB 04 0F 8C 61 FF FF FF",
Offset = 2,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = "Update",
Description = "Adjust CM_PageMap::UpdateSyncedCursorVisibility() (Inlined into Update()!) for (int i = 0; i < 4; i++) to new max players.",
Pattern = "83 FB 04 0F 8C 55 FF FF FF",
Offset = 2,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = "SetPageActive",
Description = "Adjust CM_PageMap::SetPageActive() m_playerIsDrawing = new bool[4] to new max players.",
Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8D 8B 60 02 00 00",
Offset = 1,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = "OnEnable",
Description = "Adjust CM_PageMap::OnEnable() for (int i = 0; i < 4; i++) to new max players.",
Pattern = "83 FE 04 7C 94",
Offset = 2,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
}
}));
}
}
public class CM_PlayerLobbyBarManualPatch : ManualPatch
{
protected override Type TargetType { get; } = typeof(CM_PlayerLobbyBar);
protected override void SetupPatches()
{
base.Patches.AddRange(new <>z__ReadOnlySingleElementList<Patch>(new Patch
{
Method = "UpdatePlayer",
Description = "Adjust hardcoded limit of 4 in CM_PlayerLobbyBar::UpdatePlayer to new max players.",
Pattern = "83 F8 04 0F 8D F0 00 00 00",
Offset = 2,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
}));
}
}
public class DiscordManagerManualPatch : ManualPatch
{
protected override Type TargetType { get; } = typeof(DiscordManager);
protected override void SetupPatches()
{
base.Patches.AddRange(new <>z__ReadOnlySingleElementList<Patch>(new Patch
{
Method = "GetMaxLobbySize",
Description = "Adjust DiscordManager::GetMaxLobbySize hardcoded iteration to new max players.",
Pattern = "BF 04 00 00 00 33 DB",
Offset = 1,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
}));
}
}
public class GuiManagerManualPatch : ManualPatch
{
protected override Type TargetType { get; } = typeof(GuiManager);
protected override void SetupPatches()
{
base.Patches.AddRange(new <>z__ReadOnlySingleElementList<Patch>(new Patch
{
Method = "Setup",
Description = "Adjust GuiManager::Setup() m_playerPings = new SyncedNavMarkerWrapper[4] to new max players.",
Pattern = "BA 04 00 00 00 4C 8B E8",
Offset = 1,
Bytes = new byte[1] { PluginConfig.MaxPlayers },
ScanSize = 7500L
}));
}
}
public class PlayerAgentManualPatch : ManualPatch
{
protected override Type TargetType { get; } = typeof(PlayerAgent);
protected override void SetupPatches()
{
base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[2]
{
new Patch
{
Method = "Setup",
Description = "Remove characterID limit in PlayerAgent::Setup",
Pattern = "0F 87 2C 10 00 00",
Offset = 0,
Bytes = ManualPatch.GenerateNop(6)
},
new Patch
{
Method = "Setup",
Description = "Remove characterID >= m_modelsForSync length in PlayerAgent::Setup since m_modelsForSync isn't used anyway",
Pattern = "44 3B 70 18 0F 8D 12 10 00 00",
Offset = 4,
Bytes = ManualPatch.GenerateNop(6)
}
}));
}
}
public class PlayerCoverageDataSet_NodeManualPatch : ManualPatch
{
protected override Type TargetType { get; } = typeof(PlayerCoverageDataSet_Node);
protected override void SetupPatches()
{
base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[4]
{
new Patch
{
Method = ".ctor",
Description = "Patch PlayerCoverageDataSet_Node constructor and PlayerCoverageDataSet_Portal$$ constructor (#1)",
Pattern = "FF C6 83 FE 04 7C 8D 48 8B 5C 24 30",
Offset = 4,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = ".ctor",
Description = $"Patch PlayerCoverageDataSet_Node constructor m_coverageDatas array size from 4 -> {PluginConfig.MaxPlayers}.",
Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 4C 8D 73 10 48 8B D0 49 8B CE 49 89 06 E8 ?? ?? ?? ?? 33 D2",
Offset = 1,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = "GetNodeDistanceToClosestPlayer",
Description = "Adjust GetNodeDistanceToClosestPlayer hardcoded iteration of 4.",
Pattern = "83 F9 04 7C CC",
Offset = 2,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = "GetNodeDistanceToClosestPlayer_Unblocked",
Description = "Adjust GetNodeDistanceToClosestPlayer_Unblocked hardcoded iteration of 4.",
Pattern = "83 FB 04 0F 8C 5B FF FF FF",
Offset = 2,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
}
}));
}
}
public class PlayerCoverageDataSet_PortalManualPatch : ManualPatch
{
protected override Type TargetType { get; } = typeof(PlayerCoverageDataSet_Portal);
protected override void SetupPatches()
{
base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[2]
{
new Patch
{
Method = ".ctor",
ParameterTypes = new Type[1] { typeof(AIG_CoursePortal) },
Description = "Patch PlayerCoverageDataSet_Portal constructor (#1) for loop",
Pattern = "FF C6 83 FE 04 7C 8D 48 8B 5C 24 30",
Offset = 4,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = ".ctor",
ParameterTypes = new Type[1] { typeof(AIG_CoursePortal) },
Description = $"Patch PlayerCoverageDataSet_Portal constructor m_coverageDatas array size from 4 -> {PluginConfig.MaxPlayers}.",
Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 4C 8D 73 10 48 8B D0 49 8B CE 49 89 06 E8 ?? ?? ?? ?? 33 F6",
Offset = 1,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
}
}));
}
}
public class PlayerManagerManualPatch : ManualPatch
{
protected override Type TargetType { get; } = typeof(PlayerManager);
protected override void SetupPatches()
{
base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[4]
{
new Patch
{
Method = "SpawnBot",
Description = "Remove SpawnBot hardcoded limit of 4.",
Pattern = "83 78 18 04 0F 84 9D 03 00 00",
Offset = 4,
Bytes = ManualPatch.GenerateNop(6)
},
new Patch
{
Method = ".ctor",
Description = "Set constructor m_botSlot size to new max player limit.",
Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8D 4E 70",
Offset = 1,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = ".ctor",
Description = "Patch inlined version of the creation of PositionReservations in PlayerManager constructor.",
Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8D 4F 20 48 8B D0 48 89 01 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8D 4F 28 48 8B D0 48 89 01 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 48 8B C8 48 8B D8 E8 ?? ?? ?? ?? 48 8D 4F 30 48 8B D3 48 89 19 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 48 8B C8 48 8B D8 E8 ?? ?? ?? ?? 48 8D 4F 38 48 8B D3 48 89 19 E8 ?? ?? ?? ?? 33 D2 48 8B CF E8",
Offset = 1,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = ".ctor",
Description = "Patch inlined version of the creation of ObjectReservations in PlayerManager constructor.",
Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8D 4F 28 48 8B D0 48 89 01 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 48 8B C8 48 8B D8 E8 ?? ?? ?? ?? 48 8D 4F 30 48 8B D3 48 89 19 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 48 8B C8 48 8B D8 E8 ?? ?? ?? ?? 48 8D 4F 38 48 8B D3 48 89 19 E8 ?? ?? ?? ?? 33 D2 48 8B CF E8",
Offset = 1,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
}
}));
}
}
public class PlayerBotAIDataManualPatch : ManualPatch
{
protected override Type TargetType { get; } = typeof(PlayerBotAIData);
protected override void SetupPatches()
{
base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[2]
{
new Patch
{
Method = ".ctor",
Description = "Set PlayerBotAIData constructor PositionReservations size to new max player limit.",
Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8D 4F 20 48 8B D0 48 89 01 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8D 4F 28 48 8B D0 48 89 01 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 48 8B C8 48 8B D8 E8 ?? ?? ?? ?? 48 8D 4F 30 48 8B D3 48 89 19 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 48 8B C8 48 8B D8 E8 ?? ?? ?? ?? 48 8D 4F 38 48 8B D3 48 89 19 E8 ?? ?? ?? ?? 33 D2 48 8B CF 48 8B 5C 24 30",
Offset = 1,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = ".ctor",
Description = "Set PlayerBotAIData constructor ObjectReservations size to new max player limit.",
Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8D 4F 28 48 8B D0 48 89 01 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 48 8B C8 48 8B D8 E8 ?? ?? ?? ?? 48 8D 4F 30 48 8B D3 48 89 19 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 48 8B C8 48 8B D8 E8 ?? ?? ?? ?? 48 8D 4F 38 48 8B D3 48 89 19 E8 ?? ?? ?? ?? 33 D2 48 8B CF 48 8B 5C 24 30",
Offset = 1,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
}
}));
}
}
public class PlayerSessionStatusManagerManualPatch : ManualPatch
{
protected override Type TargetType { get; } = typeof(PlayerSessionStatusManager);
protected override void SetupPatches()
{
base.Patches.AddRange(new <>z__ReadOnlySingleElementList<Patch>(new Patch
{
Method = "OnPlayerStateCapture",
Description = "Adjust PlayerSessionStatusManager::OnPlayerStateCapture() bool flag2 = characterIndex > -1 && characterIndex < 4; to new max players.",
Pattern = "83 F8 04 0F 9C C3",
Offset = 2,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
}));
}
}
public class PlayerVoiceManagerManualPatch : ManualPatch
{
protected override Type TargetType { get; } = typeof(PlayerVoiceManager);
protected override void SetupPatches()
{
base.Patches.AddRange(new <>z__ReadOnlySingleElementList<Patch>(new Patch
{
Method = "RegisterPlayerVoice",
Description = "Patch PlayerVoiceManager < 3",
Pattern = "83 FE 03 76 67",
Offset = 2,
Bytes = new byte[1] { (byte)(PluginConfig.MaxPlayers - 1) }
}));
}
}
public class PLOC_InElevatorManualPatch : ManualPatch
{
protected override Type TargetType { get; } = typeof(PLOC_InElevator);
protected override void SetupPatches()
{
base.Patches.AddRange(new <>z__ReadOnlySingleElementList<Patch>(new Patch
{
Method = "CommonEnter",
Description = "PLOC_InElevator::CommonEnter PLOCStateReferenceID > 3",
Pattern = "83 B8 A0 00 00 00 03",
Offset = 6,
Bytes = new byte[1] { (byte)(PluginConfig.MaxPlayers - 1) }
}));
}
}
public class SNet_PlayerSlotManagerManualPatch : ManualPatch
{
protected override Type TargetType { get; } = typeof(SNet_PlayerSlotManager);
protected override void SetupPatches()
{
base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[7]
{
new Patch
{
Method = "Internal_ManageSlot",
Description = "Adjust Internal_ManageSlot hardcoded iteration of 4.",
Pattern = "83 FF 04 0F 8C 95 FE FF FF",
Offset = 2,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = "OnResetSession",
Description = "Adjust OnResetSession hardcoded iteration of 4.",
Pattern = "83 FB 04 7C 9E",
Offset = 2,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = "OnValidateMasterData",
Description = "Adjust OnValidateMasterData hardcoded iteration of 4.",
Pattern = "83 FF 04 0F 8C 68 FE FF FF",
Offset = 2,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = "HasFreeBotSlot",
Description = "Adjust HasFreeBotSlot hardcoded iteration of 4.",
Pattern = "83 FB 04 7C 87",
Offset = 2,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = "HasFreeHumanSlot",
Description = "Adjust HasFreeHumanSlot hardcoded iteration of 4.",
Pattern = "83 FB 04 0F 8C 38 FF FF FF",
Offset = 2,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = "SetAllPlayerSlotPermissions",
Description = "Adjust SetAllPlayerSlotPermissions hardcoded iteration of 4.",
Pattern = "83 FB 04 7C C7",
Offset = 2,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
},
new Patch
{
Method = "AreSlotPermissionsSet",
Description = "Adjust AreSlotPermissionsSet hardcoded iteration of 4.",
Pattern = "83 F8 04 7C EA",
Offset = 2,
Bytes = new byte[1] { PluginConfig.MaxPlayers }
}
}));
}
}
public class SNet_SyncManagerManualPatch : ManualPatch
{
protected override Type TargetType { get; } = typeof(SNet_SyncManager);
protected override void SetupPatches()
{
base.Patches.AddRange(new <>z__ReadOnlySingleElementList<Patch>(new Patch
{
Method = "ValidateIndex",
Description = "Remove SNet_SyncManager::ValidateIndex character index > 3 check, since we're using higher characterIDs.",
Pattern = "0F 87 C8 06 00 00",
Offset = 0,
Bytes = ManualPatch.GenerateNop(6)
}));
}
}
}
namespace GTFO.LobbyExpansion.Patches.Harmony
{
[HarmonyPatch(typeof(BoosterImplantManager))]
public static class BoosterImplantManagerPatch
{
[HarmonyPatch("Awake")]
[HarmonyPostfix]
public static void Awake__Postfix(BoosterImplantManager __instance)
{
L.LogExecutingMethod();
if (((Il2CppArrayBase<PlayerBoosterImplantState>)(object)__instance.m_boosterPlayers).Length < PluginConfig.MaxPlayers)
{
L.Verbose("Expanding m_boosterPlayers size.");
__instance.m_boosterPlayers = new Il2CppReferenceArray<PlayerBoosterImplantState>((long)PluginConfig.MaxPlayers);
}
}
}
[HarmonyPatch(typeof(CM_PageExpeditionSuccess))]
public static class CM_PageExpeditionSuccessPatch
{
private static bool _needPositionUpdate;
private static DateTime _lastVisibilityUpdate = DateTime.Now;
private static readonly Pagination _pagination = new Pagination();
private static CM_Item _buttonPageUp = null;
private static CM_Item _buttonPageDown = null;
[HarmonyPatch("OnEnable")]
[HarmonyPostfix]
public static void OnEnable__Postfix(CM_PageExpeditionSuccess __instance)
{
L.LogExecutingMethod();
_pagination.PageIndex = 0;
UpdateCustomButtons();
_needPositionUpdate = true;
UpdateVisiblePlayerReports(__instance);
}
[HarmonyPatch("Update")]
[HarmonyPostfix]
public static void Update__Postfix(CM_PageExpeditionSuccess __instance)
{
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
if (_needPositionUpdate)
{
L.Verbose("Updating position of extra player reports.");
for (int i = 4; i < ((Il2CppArrayBase<CM_PageSuccess_PrisonerEvaluation>)(object)__instance.m_playerReports).Length; i++)
{
Transform transform = ((Component)((Il2CppArrayBase<CM_PageSuccess_PrisonerEvaluation>)(object)__instance.m_playerReports)[i % 4]).transform;
((Component)((Il2CppArrayBase<CM_PageSuccess_PrisonerEvaluation>)(object)__instance.m_playerReports)[i]).transform.position = transform.position;
((Component)((Il2CppArrayBase<CM_PageSuccess_PrisonerEvaluation>)(object)__instance.m_playerReports)[i]).transform.parent = transform.parent;
}
_needPositionUpdate = false;
}
if (DateTime.Now > _lastVisibilityUpdate)
{
_lastVisibilityUpdate = DateTime.Now + TimeSpan.FromMilliseconds(50.0);
UpdateVisiblePlayerReports(__instance);
}
if (Input.GetKeyDown((KeyCode)281))
{
_pagination.PageDown();
}
if (Input.GetKeyDown((KeyCode)280))
{
_pagination.PageUp();
}
}
private static void UpdateVisiblePlayerReports(CM_PageExpeditionSuccess page)
{
if (page.m_playerReports == null)
{
return;
}
Il2CppReferenceArray<SNet_Slot> playerSlots = SNet.Slots.PlayerSlots;
int num = _pagination.PageIndex * 4;
int num2 = Math.Min(num + 4, PluginConfig.MaxPlayers);
for (int i = 0; i < ((Il2CppArrayBase<CM_PageSuccess_PrisonerEvaluation>)(object)page.m_playerReports).Count; i++)
{
if (!((Object)(object)((Il2CppArrayBase<CM_PageSuccess_PrisonerEvaluation>)(object)page.m_playerReports)[i] == (Object)null))
{
bool active = true;
if (i < num)
{
active = false;
}
else if (i >= num2)
{
active = false;
}
else if (i >= ((Il2CppArrayBase<SNet_Slot>)(object)playerSlots).Count || (Object)(object)((Il2CppArrayBase<SNet_Slot>)(object)playerSlots)[i].player == (Object)null)
{
active = false;
}
((Component)((Il2CppArrayBase<CM_PageSuccess_PrisonerEvaluation>)(object)page.m_playerReports)[i]).gameObject.SetActive(active);
}
}
}
private static void OnPageChanged()
{
L.Verbose("Updating visible player reports.");
UpdateVisiblePlayerReports(MainMenuGuiLayer.Current.PageExpeditionSuccess);
UpdateCustomButtons();
}
private static void UpdateCustomButtons()
{
bool enabled = _pagination.CanPageDown();
bool enabled2 = _pagination.CanPageUp();
_buttonPageDown.SetCoolButtonEnabled(enabled);
_buttonPageUp.SetCoolButtonEnabled(enabled2);
}
[HarmonyPatch("Setup")]
[HarmonyPostfix]
public static void Setup__Postfix(CM_PageExpeditionSuccess __instance, MainMenuGuiLayer guiLayer)
{
CM_PageExpeditionSuccess __instance2 = __instance;
_pagination.OnPageChanged += OnPageChanged;
CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(CoroutineHelpers.NextFrame(delegate
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
_buttonPageUp = CoolButton.InstantiateSquareButton(((Component)__instance2.m_btnLeaveExpedition).transform, new Vector3(320f, 42f, 0f), hideText: true, displayArrow: true);
_buttonPageDown = CoolButton.InstantiateSquareButton(((Component)__instance2.m_btnLeaveExpedition).transform, new Vector3(-320f, 42f, 0f), hideText: true, displayArrow: true, flipArrow: true);
UpdateCustomButtons();
_buttonPageUp.OnBtnPressCallback = Action<int>.op_Implicit((Action<int>)delegate
{
_pagination.PageUp();
});
_buttonPageDown.OnBtnPressCallback = Action<int>.op_Implicit((Action<int>)delegate
{
_pagination.PageDown();
});
})), (Action)null);
}
}
[HarmonyPatch(typeof(__c__DisplayClass38_1))]
public class CM_PageLoadoutDisplayClassPatch
{
[HarmonyPatch("_ShowPermissionWindow_b__1")]
public static void Prefix(__c__DisplayClass38_1 __instance)
{
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
int num = 0;
for (int i = 0; i < __instance.field_Public___c__DisplayClass38_0_0.playerIndex; i++)
{
SNet_Player player = ((Il2CppArrayBase<SNet_Slot>)(object)SNet.Slots.PlayerSlots)[i].player;
if ((Object)(object)player == (Object)null || !player.IsLocal)
{
num++;
}
}
if (num < 3)
{
((Il2CppArrayBase<SlotPermission>)(object)CellSettingsManager.SettingsData.Player.LobbySlotPermissions)[num] = __instance.permission;
}
else
{
PluginConfig.SetExtraLobbySlotPermissions(num, __instance.permission);
}
}
}
[HarmonyPatch(typeof(CM_PageLoadout))]
public static class CM_PageLoadoutPatch
{
private static CM_Item _centerButton = null;
private static CM_Item _buttonPageDown = null;
private static CM_Item _buttonPageUp = null;
private const string DECOR_TEXT = "//: Lobby Page Switcher";
private static readonly Pagination _pagination = new Pagination();
[HarmonyPatch("Setup")]
[HarmonyPrefix]
public static bool Setup__Prefix(CM_PageLoadout __instance, MainMenuGuiLayer guiLayer)
{
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
//IL_00c8: Expected O, but got Unknown
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
//IL_010a: Unknown result type (might be due to invalid IL or missing references)
L.LogExecutingMethod();
Il2CppReferenceArray<Transform> playerInfoHolders = __instance.m_playerInfoHolders;
__instance.m_playerInfoHolders = new Il2CppReferenceArray<Transform>((long)PluginConfig.MaxPlayers);
for (int i = 0; i < 4; i++)
{
((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[i] = ((Il2CppArrayBase<Transform>)(object)playerInfoHolders)[i];
}
GameObject val = GameObject.Find("GUI/CellUI_Camera(Clone)/MainMenuLayer/CM_PageLoadout_CellUI(Clone)/PlayerMovement/PlayerPillars");
L.Assert((Object)(object)val != (Object)null, "playerPillarsGameObj was null!");
for (int j = 4; j < PluginConfig.MaxPlayers; j++)
{
string text = $"Player{j + 1}Root";
L.Verbose("Creating extra player root (" + text + ").");
GameObject val2 = new GameObject(text);
Transform val3 = ((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[j % 4];
val2.transform.position = val3.position;
val2.transform.localPosition = val3.localPosition;
val2.transform.localScale = val3.localScale;
val2.transform.SetParent(val.transform);
val2.layer = LayerMask.NameToLayer("UI");
val2.SetActive(true);
((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[j] = val2.transform;
}
return true;
}
[HarmonyPatch("ArrangePlayerPillarSpacing")]
[HarmonyPostfix]
public static void ArrangePlayerPillarSpacing__Postfix(CM_PageLoadout __instance)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: 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_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0192: Unknown result type (might be due to invalid IL or missing references)
//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
Vector3[] array = (Vector3[])(object)new Vector3[4]
{
((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[0]).transform.position,
((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[1]).transform.position,
((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[2]).transform.position,
((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[3]).transform.position
};
for (int i = 4; i < PluginConfig.MaxPlayers; i++)
{
string text = $"Player{i + 1}Root";
Transform val = ((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[i % 4];
((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[i]).transform.position = val.position;
((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[i]).transform.localPosition = val.localPosition;
((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[i]).transform.localScale = val.localScale;
}
int num = _pagination.PageIndex * 4;
int num2 = Math.Min(num + 4, PluginConfig.MaxPlayers);
for (int j = 0; j < ((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders).Count; j++)
{
if (j < num)
{
((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[j]).gameObject.transform.position = new Vector3(5000f, 5000f, 5000f);
}
else if (j >= num2)
{
((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[j]).gameObject.transform.position = new Vector3(5000f, 5000f, 5000f);
}
else
{
((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[j]).transform.position = array[j % array.Length];
}
}
}
public static void UpdatePlayerPillars()
{
CM_PageLoadout.Current.ArrangePlayerPillarSpacing();
}
[HarmonyPatch("Update")]
[HarmonyPostfix]
public static void Update__Postfix(CM_PageLoadout __instance)
{
if (Input.GetKeyDown((KeyCode)281) && _pagination.PageDown())
{
UpdateCustomButtons();
}
if (Input.GetKeyDown((KeyCode)280) && _pagination.PageUp())
{
UpdateCustomButtons();
}
}
[HarmonyPatch("ApplyPlayerSlotPermissionsFromSettings")]
[HarmonyPostfix]
public static void ApplyPlayerSlotPermissionsFromSettings__Postfix(CM_PageLoadout __instance)
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
L.LogExecutingMethod();
bool flag = false;
for (int i = 4; i < PluginConfig.MaxPlayers; i++)
{
SlotPermission extraSlotPermission = PluginConfig.GetExtraSlotPermission(i);
if ((Object)(object)((Il2CppArrayBase<SNet_Slot>)(object)SNet.Slots.PlayerSlots)[i].player == (Object)null || !((Il2CppArrayBase<SNet_Slot>)(object)SNet.Slots.PlayerSlots)[i].player.IsLocal)
{
flag = SNet.Slots.SetSlotPermission(i, extraSlotPermission) || flag;
}
else if (((Il2CppArrayBase<SNet_Slot>)(object)SNet.Slots.PlayerSlots)[i].player.IsLocal)
{
flag = SNet.Slots.SetSlotPermission(i, (SlotPermission)4) || flag;
}
}
if (!flag)
{
L.Verbose("Calling OnSlotsStatusChange.");
SNet.Core.OnSlotsStatusChanged();
}
if (SNet_Events.OnLobbyPermissionsSet != null)
{
L.Verbose("Calling OnLobbyPermissionsSet.");
SNet_Events.OnLobbyPermissionsSet.Invoke();
}
}
[HarmonyPatch("OnDisable")]
[HarmonyPostfix]
public static void OnDisable__Postfix()
{
L.LogExecutingMethod();
}
private static void UpdateCustomButtons()
{
bool enabled = _pagination.CanPageDown();
bool enabled2 = _pagination.CanPageUp();
_buttonPageDown.SetCoolButtonEnabled(enabled);
_buttonPageUp.SetCoolButtonEnabled(enabled2);
_centerButton.SetText($"<color=white>P{_pagination.PageIndex + 1}</color>");
}
private static void OnPageChanged()
{
UpdatePlayerPillars();
}
[HarmonyPatch("Setup")]
[HarmonyPostfix]
public static void Setup__Postfix(CM_PageLoadout __instance, MainMenuGuiLayer guiLayer)
{
CM_PageLoadout __instance2 = __instance;
if ((Object)(object)CM_PageLoadout.Current == (Object)null)
{
return;
}
_pagination.OnPageChanged += OnPageChanged;
CoolButton.Setup(__instance2);
CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(CoroutineHelpers.NextFrame(delegate
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: 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)
//IL_005b: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject("LobbySwitcherHolder");
Transform transform = val.transform;
transform.SetParent(__instance2.m_readyButtonAlign.parent);
transform.localPosition = __instance2.m_readyButtonAlign.localPosition + new Vector3(0f, 1150f, 0f);
transform.localScale = Vector3.one * 0.9f;
Transform val2 = __instance2.m_readyButtonAlign.Find("DecorText");
val2 = Object.Instantiate<Transform>(val2, transform);
((Component)val2).transform.localPosition = new Vector3(100f, 0f, 0f);
((Component)val2).transform.localScale = Vector3.one;
((Component)val2).gameObject.SetActive(true);
((TMP_Text)((Component)val2).GetComponent<TextMeshPro>()).SetText("//: Lobby Page Switcher", true);
_centerButton = CoolButton.InstantiateSquareButton(transform, Vector3.zero);
_buttonPageDown = CoolButton.InstantiateSquareButton(transform, new Vector3(-110f, 0f, 0f), hideText: true, displayArrow: true, flipArrow: true);
_buttonPageUp = CoolButton.InstantiateSquareButton(transform, new Vector3(110f, 0f, 0f), hideText: true, displayArrow: true);
UpdateCustomButtons();
_centerButton.OnBtnPressCallback = Action<int>.op_Implicit((Action<int>)delegate
{
int localPlayerPageIndexFromPillar = Pagination.GetLocalPlayerPageIndexFromPillar();
if (_pagination.PageIndex != localPlayerPageIndexFromPillar)
{
_pagination.PageIndex = localPlayerPageIndexFromPillar;
UpdatePlayerPillars();
}
UpdateCustomButtons();
});
_buttonPageDown.OnBtnPressCallback = Action<int>.op_Implicit((Action<int>)delegate
{
_pagination.PageDown();
UpdateCustomButtons();
});
_buttonPageUp.OnBtnPressCallback = Action<int>.op_Implicit((Action<int>)delegate
{
_pagination.PageUp();
UpdateCustomButtons();
});
})), (Action)null);
}
}
[HarmonyPatch(typeof(CM_PageMap))]
public static class CM_PageMapPatch
{
private static readonly Pagination _pagination = new Pagination();
private static CM_Item _buttonCenter = null;
private static CM_Item _buttonPageUp = null;
private static CM_Item _buttonPageDown = null;
private static void OnPageChanged()
{
UpdateCustomButtons();
UpdateAllPlayerInventories();
}
private static void UpdateCustomButtons()
{
_buttonPageUp.SetCoolButtonEnabled(_pagination.CanPageUp());
_buttonPageDown.SetCoolButtonEnabled(_pagination.CanPageDown());
_buttonCenter.SetText($"<color=white>P{_pagination.PageIndex + 1}</color>");
}
[HarmonyPatch("Setup")]
[HarmonyPostfix]
public static void Setup__Postfix(CM_PageMap __instance)
{
CM_PageMap __instance2 = __instance;
_pagination.OnPageChanged += OnPageChanged;
CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(CoroutineHelpers.NextFrame(delegate
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject("LobbyExpansion_PageButtonRoot");
val.transform.SetParent(((Component)__instance2.m_btnGotoObjectives).transform);
val.transform.localPosition = new Vector3(40f, -200f, 0f);
val.transform.localScale = Vector3.one * 0.6f;
_buttonCenter = CoolButton.InstantiateSquareButton(val.transform, Vector3.zero);
_buttonPageDown = CoolButton.InstantiateSquareButton(val.transform, new Vector3(-40f, 80f, 0f), hideText: true, displayArrow: true);
((Component)_buttonPageDown).transform.localRotation = Quaternion.Euler(0f, 0f, 90f);
_buttonPageUp = CoolButton.InstantiateSquareButton(val.transform, new Vector3(-40f, -160f, 0f), hideText: true, displayArrow: true, flipArrow: true);
((Component)_buttonPageUp).transform.localRotation = Quaternion.Euler(0f, 0f, 90f);
UpdateCustomButtons();
_buttonCenter.OnBtnPressCallback = Action<int>.op_Implicit((Action<int>)delegate
{
int localPlayerPageFromSlotIndex = Pagination.GetLocalPlayerPageFromSlotIndex();
if (_pagination.PageIndex != localPlayerPageFromSlotIndex)
{
_pagination.PageIndex = localPlayerPageFromSlotIndex;
UpdateAllPlayerInventories();
}
UpdateCustomButtons();
});
_buttonPageDown.OnBtnPressCallback = Action<int>.op_Implicit((Action<int>)delegate
{
_pagination.PageDown();
});
_buttonPageUp.OnBtnPressCallback = Action<int>.op_Implicit((Action<int>)delegate
{
_pagination.PageUp();
});
})), (Action)null);
}
private static void UpdateAllPlayerInventories()
{
CM_PageMap current = CM_PageMap.Current;
int num = 0;
Enumerator<SNet_Player> enumerator = SNet.Slots.SlottedPlayers.GetEnumerator();
while (enumerator.MoveNext())
{
SNet_Player current2 = enumerator.Current;
if (current2.IsInSlot)
{
current.UpdatePlayerInventory(current2, num);
num++;
}
}
}
[HarmonyPatch("Update")]
[HarmonyPostfix]
public static void Update__Postfix()
{
if (Input.GetKeyDown((KeyCode)281))
{
_pagination.PageDown();
}
if (Input.GetKeyDown((KeyCode)280))
{
_pagination.PageUp();
}
}
[HarmonyPatch("UpdatePlayerInventory")]
[HarmonyPostfix]
public static void UpdatePlayerInventory__Postfix(CM_PageMap __instance, SNet_Player player, int count)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
PUI_Inventory val = ((Il2CppArrayBase<PUI_Inventory>)(object)__instance.m_inventory)[player.PlayerSlotIndex()];
Vector2 position = ((RectTransformComp)val).GetPosition();
Vector2 position2 = default(Vector2);
((Vector2)(ref position2))..ctor(position.x, position.y);
int num = 0;
for (int num2 = count; num2 > 3; num2 -= 4)
{
num++;
}
if (_pagination.PageIndex != num)
{
position2.x = 5000f;
}
position2.y = -150f + (float)(count % 4) * (0f - __instance.m_inventoryOffsetPerPlayer);
((RectTransformComp)val).SetPosition(position2);
}
}
[HarmonyPatch(typeof(CM_PlayerLobbyBar))]
public static class CM_PlayerLobbyBarPatch
{
[HarmonyPatch("SpawnPlayerModel")]
[HarmonyPrefix]
public static bool SpawnPlayerModel__Prefix(CM_PlayerLobbyBar __instance, ref int index)
{
L.LogExecutingMethod($"{"index"}: {index}");
if (index > 3)
{
int num = index % 4;
L.Verbose($"Clamping {"index"} to {num}.");
index = num;
}
return true;
}
}
[HarmonyPatch(typeof(CP_Bioscan_Core))]
public static class CP_Bioscan_CorePatch
{
[HarmonyPatch("Setup")]
[HarmonyPostfix]
public static void Setup__Postfix(CP_Bioscan_Core __instance)
{
Component hUDComp = __instance.m_HUDComp;
CP_Bioscan_Hud val = ((hUDComp != null) ? ((Il2CppObjectBase)hUDComp).TryCast<CP_Bioscan_Hud>() : null);
if ((Object)(object)val != (Object)null)
{
CP_Bioscan_HudPatch.HudToCoreMap[((Object)val).GetInstanceID()] = __instance;
}
}
[HarmonyPatch("OnSyncStateChange")]
[HarmonyPostfix]
public static void OnSyncStateChange__Postfix(CP_Bioscan_Core __instance, eBioscanStatus status, List<PlayerAgent> playersInScan, int playersMax)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Invalid comparison between Unknown and I4
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Invalid comparison between Unknown and I4
//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
//IL_018d: Unknown result type (might be due to invalid IL or missing references)
//IL_0198: Unknown result type (might be due to invalid IL or missing references)
//IL_019d: Unknown result type (might be due to invalid IL or missing references)
//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
int playersInScan2 = __instance.m_sync.GetCurrentState().playersInScan;
int num = playersInScan?.Count ?? 0;
if ((int)status != 3)
{
return;
}
if (__instance.IsMovable)
{
CP_BasicMovable movingComp = __instance.m_movingComp;
if ((Object)(object)movingComp != (Object)null && movingComp.OnlyMoveWhenScannig)
{
int num2 = CountPlayersInScan(__instance);
bool flag = Extensions.RequireAllPlayers(__instance.m_playerScanner.ScanPlayersRequired);
bool flag2 = Extensions.RequireSoloPlayer(__instance.m_playerScanner.ScanPlayersRequired);
if ((int)__instance.m_playerScanner.ScanPlayersRequired == 0 || (flag && num2 == playersMax) || (flag2 && num2 == 1))
{
movingComp.ResumeMovement();
}
else
{
movingComp.PauseMovement();
}
}
}
if (playersInScan2 <= num)
{
return;
}
bool flag3 = false;
if (((Behaviour)__instance).enabled && playersInScan != null)
{
for (int i = 0; i < num; i++)
{
if ((Object)(object)playersInScan[i] != (Object)null && ((Agent)playersInScan[i]).IsLocallyOwned)
{
flag3 = true;
break;
}
}
}
PlayerAgent val = default(PlayerAgent);
if (!flag3 && PlayerManager.TryGetLocalPlayerAgent(ref val) && ((Agent)val).Alive)
{
Component playerScannerComp = __instance.m_PlayerScannerComp;
CP_PlayerScanner val2 = ((playerScannerComp != null) ? ((Il2CppObjectBase)playerScannerComp).TryCast<CP_PlayerScanner>() : null);
if ((Object)(object)val2 != (Object)null)
{
float radius = val2.Radius;
Vector3 val3 = ((Agent)val).Position - ((Component)__instance).transform.position;
float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
flag3 = sqrMagnitude < radius * radius;
}
}
__instance.m_hud.SetPlayerData(__instance.m_puzzleIndex, playersInScan2, playersMax, flag3, __instance.m_playerScanner.ScanPlayersRequired, __instance.m_playerScanner.ReduceWhenNoPlayer);
}
private static int CountPlayersInScan(CP_Bioscan_Core core)
{
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
Component playerScannerComp = core.m_PlayerScannerComp;
CP_PlayerScanner val = ((playerScannerComp != null) ? ((Il2CppObjectBase)playerScannerComp).TryCast<CP_PlayerScanner>() : null);
if ((Object)(object)val == (Object)null)
{
return 0;
}
float num = val.Radius * val.Radius;
Vector3 position = ((Component)core).transform.position;
int num2 = 0;
List<PlayerAgent> playerAgentsInLevel = PlayerManager.PlayerAgentsInLevel;
for (int i = 0; i < playerAgentsInLevel.Count; i++)
{
PlayerAgent val2 = playerAgentsInLevel[i];
if ((Object)(object)val2 != (Object)null && ((Agent)val2).Alive)
{
Vector3 val3 = ((Agent)val2).Position - position;
float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
if (sqrMagnitude < num)
{
num2++;
}
}
}
return num2;
}
}
[HarmonyPatch(typeof(CP_Bioscan_Hud))]
public static class CP_Bioscan_HudPatch
{
internal static readonly Dictionary<int, CP_Bioscan_Core> HudToCoreMap = new Dictionary<int, CP_Bioscan_Core>();
internal static void OnLevelCleanup()
{
HudToCoreMap.Clear();
}
[HarmonyPatch("SetPlayerData")]
[HarmonyPostfix]
public static void SetPlayerData__Postfix(CP_Bioscan_Hud __instance)
{
if (((Il2CppArrayBase<string>)(object)__instance.m_progressBarPlayerChar).Length < PluginConfig.MaxPlayers)
{
__instance.m_progressBarPlayerChar = Il2CppStringArray.op_Implicit(PluginConfig.GetBioscanLetters());
}
}
[HarmonyPatch("OnDestroy")]
[HarmonyPostfix]
public static void OnDestroy__Postfix(CP_Bioscan_Hud __instance)
{
HudToCoreMap.Remove(((Object)__instance).GetInstanceID());
}
[HarmonyPatch("Update")]
[HarmonyPrefix]
public static void Update__Prefix(CP_Bioscan_Hud __instance)
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Invalid comparison between Unknown and I4
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
if (HudToCoreMap.TryGetValue(((Object)__instance).GetInstanceID(), out CP_Bioscan_Core value) && !((Object)(object)value == (Object)null) && !((Il2CppObjectBase)value).WasCollected)
{
pBioscanState currentState = value.m_sync.GetCurrentState();
eBioscanStatus status = currentState.status;
if (((int)status != 0 && status - 4 > 1) || 1 == 0)
{
__instance.m_playersInScan = currentState.playersInScan;
__instance.m_playersMax = currentState.playersMax;
}
}
}
}
[HarmonyPatch(typeof(CP_Bioscan_Sync))]
public static class CP_Bioscan_SyncPatch
{
[HarmonyPatch("SetStateData")]
[HarmonyPostfix]
public static void SetStateData__Postfix(CP_Bioscan_Sync __instance, List<PlayerAgent> playersInScan)
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
if (playersInScan != null && playersInScan.Count > 4)
{
PlayerAgent obj = playersInScan[0];
pBioscanState latestState;
if ((Object)(object)((obj != null) ? obj.Owner : null) != (Object)null)
{
latestState = __instance.m_latestState;
((pPlayer)(ref latestState.playerInScan1)).SetPlayer(playersInScan[0].Owner);
}
PlayerAgent obj2 = playersInScan[1];
if ((Object)(object)((obj2 != null) ? obj2.Owner : null) != (Object)null)
{
latestState = __instance.m_latestState;
((pPlayer)(ref latestState.playerInScan2)).SetPlayer(playersInScan[1].Owner);
}
PlayerAgent obj3 = playersInScan[2];
if ((Object)(object)((obj3 != null) ? obj3.Owner : null) != (Object)null)
{
latestState = __instance.m_latestState;
((pPlayer)(ref latestState.playerInScan3)).SetPlayer(playersInScan[2].Owner);
}
PlayerAgent obj4 = playersInScan[3];
if ((Object)(object)((obj4 != null) ? obj4.Owner : null) != (Object)null)
{
latestState = __instance.m_latestState;
((pPlayer)(ref latestState.playerInScan4)).SetPlayer(playersInScan[3].Owner);
}
}
}
}
[HarmonyPatch(typeof(CP_Cluster_Hud))]
public static class CP_Cluster_HudPatch
{
[HarmonyPatch("SetPlayerData")]
[HarmonyPostfix]
public static void SetPlayerData__Postfix(CP_Cluster_Hud __instance)
{
Component bioscanHUDComp = __instance.m_bioscanHUDComp;
CP_Bioscan_Hud val = ((bioscanHUDComp != null) ? ((Il2CppObjectBase)bioscanHUDComp).TryCast<CP_Bioscan_Hud>() : null);
if ((Object)(object)val != (Object)null && ((Il2CppArrayBase<string>)(object)val.m_progressBarPlayerChar).Length < PluginConfig.MaxPlayers)
{
val.m_progressBarPlayerChar = Il2CppStringArray.op_Implicit(PluginConfig.GetBioscanLetters());
}
}
}
[HarmonyPatch(typeof(CP_PlayerScanner))]
public static class CP_PlayerScannerPatch
{
[HarmonyPatch("StartScan")]
[HarmonyPrefix]
public static bool StartScan__Prefix(CP_PlayerScanner __instance)
{
L.LogExecutingMethod();
if (((Il2CppArrayBase<float>)(object)__instance.m_scanSpeeds).Length < PluginConfig.MaxPlayers)
{
L.Verbose($"Expanding {"m_scanSpeeds"} size from {((Il2CppArrayBase<float>)(object)__instance.m_scanSpeeds).Length} to {PluginConfig.MaxPlayers} to account for more players being in the scan.");
Il2CppStructArray<float> scanSpeeds = __instance.m_scanSpeeds;
__instance.m_scanSpeeds = new Il2CppStructArray<float>((long)PluginConfig.MaxPlayers);
for (int i = 0; i < PluginConfig.MaxPlayers; i++)
{
((Il2CppArrayBase<float>)(object)__instance.m_scanSpeeds)[i] = ((Il2CppArrayBase<float>)(object)scanSpeeds)[Math.Min(i, ((Il2CppArrayBase<float>)(object)scanSpeeds).Length - 1)];
}
}
return true;
}
[HarmonyPatch("CanGoFaster")]
[HarmonyPrefix]
public static bool CanGoFaster__Prefix(CP_PlayerScanner __instance, int nrOccupiers, ref bool __result)
{
int num = ((Il2CppArrayBase<float>)(object)__instance.m_scanSpeeds).Length - 1;
if (__instance.m_reqItemsEnabled || nrOccupiers >= num || nrOccupiers >= PluginConfig.MaxPlayers)
{
__result = false;
return false;
}
__result = nrOccupiers == 0 || ((Il2CppArrayBase<float>)(object)__instance.m_scanSpeeds)[nrOccupiers - 1] < ((Il2CppArrayBase<float>)(object)__instance.m_scanSpeeds)[nrOccupiers];
return false;
}
}
[HarmonyPatch(typeof(DefaultCharacterLayouts))]
public class DefaultCharacterLayoutsPatch
{
[HarmonyPatch("GetDefaultVanityItems")]
[HarmonyPriority(600)]
[HarmonyPrefix]
public static bool GetDefaultVanityItems__Prefix(ref int characterIndex)
{
if (characterIndex > 3)
{
characterIndex %= 4;
L.Verbose($"Clamping {"characterIndex"} to {characterIndex}.");
}
return true;
}
}
[HarmonyPatch(typeof(DiscordManager))]
public class DiscordManagerPatch
{
[HarmonyPatch("GetCharacterNickname")]
[HarmonyPostfix]
public static void GetCharacterNickname__Postfix(ref string __result, int characterIndex)
{
L.LogExecutingMethod($"{"characterIndex"}: {characterIndex}, {"__result"}: {__result}");
if (characterIndex > 3)
{
__result = PluginConfig.GetExtraSlotNickname(characterIndex);
L.Verbose($"Corrected character nickname for index #{characterIndex} to {__result}.");
}
}
}
[HarmonyPatch(typeof(DramaManager))]
public static class DramaManagerPatch
{
[HarmonyPatch("Setup")]
[HarmonyPostfix]
public static void Setup__Postfix()
{
L.LogExecutingMethod();
ResetDramaFieldsProperly();
}
[HarmonyPatch("OnLevelCleanup")]
[HarmonyPostfix]
public static void OnLevelCleanup__Postfix()
{
L.LogExecutingMethod();
ResetDramaFieldsProperly();
CP_Bioscan_HudPatch.OnLevelCleanup();
}
private static void ResetDramaFieldsProperly()
{
DramaManager.SyncedPlayerStates = new Il2CppStructArray<DRAMA_State>((long)PluginConfig.MaxPlayers);
DramaManager.SyncedPlayerTensions = new Il2CppStructArray<float>((long)PluginConfig.MaxPlayers);
for (int i = 0; i < ((Il2CppArrayBase<DRAMA_State>)(object)DramaManager.SyncedPlayerStates).Length; i++)
{
((Il2CppArrayBase<DRAMA_State>)(object)DramaManager.SyncedPlayerStates)[i] = (DRAMA_State)0;
}
}
}
[HarmonyPatch(typeof(ElevatorCage))]
public static class ElevatorCagePatch
{
[HarmonyPatch("SkipPreReleaseSequence")]
[HarmonyPrefix]
[HarmonyWrapSafe]
public static bool SkipPreReleaseSequence__Prefix(ElevatorCage __instance, CellSoundPlayer sound, ref int playerId)
{
L.LogExecutingMethod($"{"playerId"}: {playerId}");
if ((Object)(object)((Il2CppArrayBase<ElevatorSeat>)(object)__instance.m_seatsFromShaft)[playerId] == (Object)null)
{
L.Warning($"playerId {playerId} has a null seat. Skipping call.");
return false;
}
return true;
}
[HarmonyPatch("RegisterSpawnPoints")]
[HarmonyPrefix]
[HarmonyWrapSafe]
public static bool RegisterSpawnPoints__Prefix(ElevatorCage __instance)
{
L.LogExecutingMethod();
__instance.m_spawnPoints = new Il2CppReferenceArray<PlayerSpawnpoint>((long)PluginConfig.MaxPlayers);
for (int i = 0; i < PluginConfig.MaxPlayers; i++)
{
int num = i % 4;
((Il2CppArrayBase<PlayerSpawnpoint>)(object)__instance.m_spawnPoints)[i] = PlayerManager.RegisterSpawnpoint((PlayerspawnpointType)0, i, ((Il2CppArrayBase<ElevatorSeat>)(object)__instance.m_seatsFromShaft)[num]);
}
return false;
}
[HarmonyPatch("PlaySeatOpenStraps")]
[HarmonyPrefix]
[HarmonyWrapSafe]
public static bool PlaySeatOpenStraps__Prefix(CellSoundPlayer sound, int playerId, bool isLocal)
{
if (playerId > 3)
{
L.Verbose("Skipping PlaySeatOpenStraps for playerId > 3.");
return false;
}
return true;
}
}
[HarmonyPatch(typeof(ElevatorRide))]
public static class ElevatorRidePatch
{
[HarmonyPatch("StartPreReleaseSequence")]
[HarmonyPrefix]
[HarmonyWrapSafe]
public static bool StartPreReleaseSequence__Prefix(Action onDone)
{
L.LogExecutingMethod();
return true;
}
[HarmonyPatch("Cleanup")]
[HarmonyPrefix]
[HarmonyWrapSafe]
public static bool Cleanup__Prefix()
{
L.LogExecutingMethod();
return true;
}
[HarmonyPatch("SpawnShaftSegments")]
[HarmonyPostfix]
[HarmonyWrapSafe]
public static void SpawnShaftSegments__Postfix(ElevatorRide __instance)
{
ElevatorRide __instance2 = __instance;
L.LogExecutingMethod();
ElevatorShaftTop shaftTop = __instance2.m_shaftTop;
Il2CppReferenceArray<ElevatorSeat> elevatorSeats = shaftTop.m_elevatorSeats;
L.Verbose($"Expanding {"m_shaftTop"}.{"m_elevatorSeats"} size from {((Il2CppArrayBase<ElevatorSeat>)(object)elevatorSeats).Length} to {PluginConfig.MaxPlayers}.");
shaftTop.m_elevatorSeats = new Il2CppReferenceArray<ElevatorSeat>((long)PluginConfig.MaxPlayers);
for (int i = 0; i < PluginConfig.MaxPlayers; i++)
{
int num = i % 4;
((Il2CppArrayBase<ElevatorSeat>)(object)shaftTop.m_elevatorSeats)[i] = ((Il2CppArrayBase<ElevatorSeat>)(object)elevatorSeats)[num];
}
Il2CppReferenceArray<Animator> hSULoadingArmAnims = shaftTop.m_HSULoadingArmAnims;
L.Verbose($"Expanding {"m_shaftTop"}.{"m_HSULoadingArmAnims"} size from {((Il2CppArrayBase<Animator>)(object)hSULoadingArmAnims).Length} to {PluginConfig.MaxPlayers}.");
shaftTop.m_HSULoadingArmAnims = new Il2CppReferenceArray<Animator>((long)PluginConfig.MaxPlayers);
for (int j = 0; j < PluginConfig.MaxPlayers; j++)
{
int num2 = j % 4;
((Il2CppArrayBase<Animator>)(object)shaftTop.m_HSULoadingArmAnims)[j] = ((Il2CppArrayBase<Animator>)(object)hSULoadingArmAnims)[num2];
}
((MonoBehaviour)__instance2).StartCoroutine(CollectionExtensions.WrapToIl2Cpp(CoroutineHelpers.NextFrame(delegate
{
ElevatorCage elevatorCage = __instance2.m_elevatorCage;
Il2CppReferenceArray<Transform> hSUAligns = elevatorCage.m_HSUAligns;
L.Verbose($"Expanding {"m_elevatorCage"}.{"m_HSUAligns"} size from {((Il2CppArrayBase<Transform>)(object)hSUAligns).Length} to {PluginConfig.MaxPlayers}.");
elevatorCage.m_HSUAligns = new Il2CppReferenceArray<Transform>((long)PluginConfig.MaxPlayers);
for (int k = 0; k < PluginConfig.MaxPlayers; k++)
{
int num3 = k % 4;
((Il2CppArrayBase<Transform>)(object)elevatorCage.m_HSUAligns)[k] = ((Il2CppArrayBase<Transform>)(object)hSUAligns)[num3];
}
})));
}
[HarmonyPatch("Cleanup")]
[HarmonyPostfix]
[HarmonyWrapSafe]
public static void Cleanup__Postfix()
{
L.LogExecutingMethod();
if (ElevatorRide.ElevatorRideInProgress)
{
ElevatorRide.ElevatorRideInProgress = false;
ElevatorRide.Current.m_shaftTop.Cleanup();
}
}
}
[HarmonyPatch(typeof(ElevatorSeat))]
public class ElevatorSeatPatch
{
private static int _frame;
[HarmonyPatch("SkipPreReleaseSequence")]
[HarmonyPostfix]
[HarmonyWrapSafe]
public static void SkipPreReleaseSequence__Postfix(CellSoundPlayer sound)
{
CellSoundPlayer sound2 = sound;
sound2.Stop();
int frameCount = Time.frameCount;
if (_frame != frameCount)
{
CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(CoroutineHelpers.NextFrame(delegate
{
sound2.Post(EVENTS.PLAY_15_ELEVATOR_RELEASE, true);
})), (Action)null);
}
_frame = frameCount;
}
}
[HarmonyPatch(typeof(_PreReleaseSequence_d__33))]
public class ElevatorSeatPatchTwo
{
private static ElevatorSeat _localSeat;
[HarmonyPatch("MoveNext")]
[HarmonyPostfix]
[HarmonyWrapSafe]
public static void ElevatorSeat___PreReleaseSequence_d__33__MoveNext__Postfix(_PreReleaseSequence_d__33 __instance)
{
if (__instance.isLocal)
{
_localSeat = __instance.__4__this;
}
if (((Il2CppObjectBase)__instance.__4__this).Pointer == ((Il2CppObjectBase)_localSeat).Pointer)
{
__instance.isLocal = true;
}
}
}
[HarmonyPatch(typeof(EnemyAgent))]
public class EnemyAgentArenaDimensionPatch
{
[HarmonyPatch("GetArenaDimension")]
[HarmonyPrefix]
public static void GetArenaDimension__Prefix(ref uint slotIndex)
{
slotIndex %= 4u;
}
}
[HarmonyPatch(typeof(GearManager))]
public static class GearManagerPatch
{
[HarmonyPatch("Setup")]
[HarmonyPostfix]
public static void Setup__Postfix()
{
L.Verbose("GearManager::Setup postfix");
BotFavoritesData botFavoritesData = GearManager.BotFavoritesData;
Il2CppStringArray original = botFavoritesData.LastEquipped_Melee;
if (Expand(ref original))
{
botFavoritesData.LastEquipped_Melee = original;
}
Il2CppStringArray original2 = botFavoritesData.LastEquipped_Standard;
if (Expand(ref original2))
{
botFavoritesData.LastEquipped_Standard = original2;
}
Il2CppStringArray original3 = botFavoritesData.LastEquipped_Special;
if (Expand(ref original3))
{
botFavoritesData.LastEquipped_Special = original3;
}
Il2CppStringArray original4 = botFavoritesData.LastEquipped_Class;
if (Expand(ref original4))
{
botFavoritesData.LastEquipped_Class = original4;
}
Il2CppStringArray original5 = botFavoritesData.LastEquipped_HackingTool;
if (Expand(ref original5))
{
botFavoritesData.LastEq