Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of DramaMask v2.1.4
DramaMask.dll
Decompiled a year ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using CSync.Extensions; using CSync.Lib; using DramaMask.Config; using DramaMask.Constants; using DramaMask.Extensions; using DramaMask.Models.Network; using DramaMask.NetcodePatcher; using DramaMask.Network; using DramaMask.Patches.LethalHandsPatch; using DramaMask.UI; using DunGen; using GameNetcodeStuff; using HarmonyLib; using LethalCompanyInputUtils.Api; using LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using LethalHands; using LethalLib.Modules; using Microsoft.CodeAnalysis; using TMPro; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("DramaMask")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Enables masks to be worn to hide from enemies by blending in with the Masked and adds a safe mask, Drama!")] [assembly: AssemblyFileVersion("2.1.4.0")] [assembly: AssemblyInformationalVersion("2.1.4+12e14aa0a0a289897b00b0088b805cc3beb1406c")] [assembly: AssemblyProduct("Stealthy Masks")] [assembly: AssemblyTitle("DramaMask")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.1.4.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] internal class <Module> { static <Module>() { } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsUnmanagedAttribute : Attribute { } [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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DramaMask { [BepInDependency("evaisa.lethallib", "0.15.1")] [BepInDependency("com.sigurd.csync", "5.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("DramaMask", "Stealthy Masks", "2.1.4")] public class Plugin : BaseUnityPlugin { public static ManualLogSource Logger; internal static ConfigValues Config; private static readonly Harmony Harmony = new Harmony("DramaMask"); private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)"Plugin DramaMask (2.1.4) is loading..."); Config = new ConfigValues(((BaseUnityPlugin)this).Config); try { InputUtilsCompat.Init(); } catch { Logger.LogInfo((object)"Soft dependency on InputUtils could not be loaded."); } NetcodePatcher(); Logger.LogInfo((object)"Loading assets..."); LoadAssets(); Logger.LogInfo((object)"Loading assets complete!"); Logger.LogInfo((object)"Patching..."); Type typeFromHandle = typeof(LethalHandsPatch); Harmony.PatchExcept(new Type[1] { typeFromHandle }); try { Harmony.PatchAll(typeFromHandle); } catch { } Logger.LogInfo((object)"Patching complete!"); Logger.LogInfo((object)"Plugin DramaMask (2.1.4) is loaded!"); } private static void NetcodePatcher() { Type[] array; try { array = Assembly.GetExecutingAssembly().GetTypes(); } catch (ReflectionTypeLoadException ex) { array = ex.Types.Where((Type t) => t != null).ToArray(); } Type[] array2 = array; foreach (Type type in array2) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); MethodInfo[] array3 = methods; foreach (MethodInfo methodInfo in array3) { object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false); if (customAttributes.Length != 0) { methodInfo.Invoke(null, null); } } } } private void LoadAssets() { AssetBundle val = LoadBundle("DramaMask", "dramamask"); if ((Object)(object)val == (Object)null) { return; } Item val2 = val.SafeLoadAsset<Item>("assets/drama/dramamask.asset"); if ((Object)(object)val2 == (Object)null) { return; } Utilities.FixMixerGroups(val2.spawnPrefab); NetworkPrefabs.RegisterNetworkPrefab(val2.spawnPrefab); Items.RegisterScrap(val2, Config.DramaSpawnMapVanilla, Config.DramaSpawnMapModded); Logger.LogDebug((object)"Loaded asset: dramaMask"); AssetBundle val3 = LoadBundle("DramaMask", "maskview"); if ((Object)(object)val3 == (Object)null) { return; } Mesh val4 = val3.SafeLoadAsset<Mesh>("assets/maskview/maskoutline.001.mesh"); if (!((Object)(object)val4 == (Object)null)) { HauntedMaskItemExtensions.OutlineMesh = val4; Logger.LogDebug((object)"Loaded asset: maskOutline"); Material val5 = val3.SafeLoadAsset<Material>("assets/maskview/transmaskmat.mat"); if (!((Object)(object)val5 == (Object)null)) { HauntedMaskItemExtensions.TransparentMat = val5; Logger.LogDebug((object)"Loaded asset: transMaskMat"); } } } private AssetBundle LoadBundle(string guid, string bundleName) { AssetBundle val = null; Assembly executingAssembly = Assembly.GetExecutingAssembly(); string[] manifestResourceNames = executingAssembly.GetManifestResourceNames(); string text = manifestResourceNames.FirstOrDefault((string n) => n.StartsWith(guid + ".Assets." + bundleName)); if (text == null) { Logger.LogError((object)("Embedded resource for [" + guid + "] not found!\nAvailable: [" + string.Join(", ", manifestResourceNames) + "]")); return val; } try { Logger.LogDebug((object)("Loading embedded resource data [" + text + "]...")); using Stream stream = executingAssembly.GetManifestResourceStream(text); using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); val = AssetBundle.LoadFromMemory(memoryStream.ToArray()); } catch (Exception arg) { Logger.LogError((object)("Bundle [" + text + "] failed to load!\nAvailable: [" + string.Join(", ", val.GetAllAssetNames()) + "]" + $"\n{arg}")); return val; } Logger.LogDebug((object)("Bundle [" + text + "] accessible!")); return val; } } public static class PluginInfo { public const string PLUGIN_GUID = "DramaMask"; public const string PLUGIN_NAME = "Stealthy Masks"; public const string PLUGIN_VERSION = "2.1.4"; } } namespace DramaMask.UI { public class StealthMeter : MonoBehaviour { private const float AccurateMinValue = 0.2978f; private const float AccurateMaxValue = 0.9101f; private const float AccurateValueRange = 0.6123f; private static Vector3 _initWeightPosition; private static Vector3 _initStatusPosition; public static bool Initialised; private GameObject _sprintMeter; private GameObject _stealthMeter; private Image uiElement; private TextMeshProUGUI uiEladsText; private static bool IsOxygenInstalled => Chainloader.PluginInfos.ContainsKey("consequential.Oxygen"); private static bool IsEladsHudInstalled => Chainloader.PluginInfos.ContainsKey("me.eladnlg.customhud"); private static bool IsShyHudInstalled => Chainloader.PluginInfos.ContainsKey("ShyHUD"); private static bool IsLcVrInstalled => false; private static GameObject WeightUi => GameObject.Find("Systems/UI/Canvas/IngamePlayerHUD/TopLeftCorner/WeightUI"); private static GameObject StatusEffectContainer => GameObject.Find("Systems/UI/Canvas/IngamePlayerHUD/TopLeftCorner/StatusEffects"); public static StealthMeter Instance { get; private set; } public bool Visible { get { if ((Object)(object)uiElement == (Object)null) { return false; } return ((Behaviour)uiElement).enabled; } set { if (!((Object)(object)uiElement == (Object)null)) { ((Behaviour)uiElement).enabled = value; if ((Object)(object)uiEladsText != (Object)null) { ((Behaviour)uiEladsText).enabled = value; } } } } public float Percent { get { if ((Object)(object)uiElement == (Object)null) { return 0f; } return IsEladsHudInstalled ? uiElement.fillAmount : InvAdjustFillAmount(uiElement.fillAmount); } set { if ((Object)(object)uiElement == (Object)null) { return; } float num = (IsEladsHudInstalled ? value : AdjustFillAmount(value)); if (uiElement.fillAmount != num) { uiElement.fillAmount = num; if ((Object)(object)uiEladsText != (Object)null) { float num2 = (float)Math.Round(Percent, 2); int num3 = (int)(num2 * 100f); ((TMP_Text)uiEladsText).text = $"{num3}<size=75%><voffset=1>%</voffset></size>"; } if (IsShyHudInstalled) { bool flag = value >= 0.75f; ((Graphic)uiElement).CrossFadeAlpha(flag ? 0f : 1f, flag ? 5f : 0.5f, false); } } } } public Color Colour { get { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)uiElement == (Object)null) { return Color.white; } return ((Graphic)uiElement).color; } set { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)uiElement == (Object)null)) { ((Graphic)uiElement).color = value; if ((Object)(object)uiEladsText != (Object)null) { ((Graphic)uiEladsText).color = value; } } } } private GameObject SprintMeter { get { if ((Object)(object)_sprintMeter == (Object)null) { _sprintMeter = (IsEladsHudInstalled ? GameObject.Find("Systems/UI/Canvas/IngamePlayerHUD/PlayerInfo(Clone)/Stamina") : ((Component)GameNetworkManager.Instance.localPlayerController.sprintMeterUI).gameObject); if ((Object)(object)_sprintMeter == (Object)null) { Plugin.Logger.LogError((object)"SprintMeter is null"); } } return _sprintMeter; } } private static float AdjustFillAmount(float value) { return Plugin.Config.AccurateMeter ? (value * 0.6123f + 0.2978f) : value; } private static float InvAdjustFillAmount(float value) { return Plugin.Config.AccurateMeter ? ((value - 0.2978f) / 0.6123f) : value; } public static void Init() { if (Initialised) { Plugin.Logger.LogDebug((object)"StealthMeter already initialized"); return; } Instance = new StealthMeter(); Initialised = true; } private static void SetInitPositions() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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) //IL_0044: 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) _initWeightPosition = (Vector3)(((Object)(object)WeightUi == (Object)null) ? default(Vector3) : WeightUi.transform.localPosition); _initStatusPosition = (Vector3)(((Object)(object)StatusEffectContainer == (Object)null) ? default(Vector3) : StatusEffectContainer.transform.localPosition); } private StealthMeter() { //IL_0083: Unknown result type (might be due to invalid IL or missing references) GameObject gameObject = ((Component)SprintMeter.transform.parent).gameObject; _stealthMeter = Object.Instantiate<GameObject>(SprintMeter, gameObject.transform); ((Object)_stealthMeter).name = "StealthMeter"; if (IsLcVrInstalled) { CoroutineHelper.Start(InitVr()); return; } SetInitPositions(); if (IsEladsHudInstalled) { InitEladsHud(); } else { InitVanilla(); } Colour = Plugin.Config.MeterColour; Percent = 1f; } private void InitVanilla() { uiElement = ((Component)_stealthMeter.transform).GetComponent<Image>(); ApplyMeterOffsets(); Plugin.Logger.LogInfo((object)"StealthMeter initialised (Vanilla)"); } public void ApplyMeterOffsets() { if (IsLcVrInstalled) { ApplyVrMeterOffsets(); } else { ApplyMeterOffsetsCommon(); } } private void ApplyMeterOffsetsCommon() { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: 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_00e6: 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_010c: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_stealthMeter == (Object)null) { Plugin.Logger.LogError((object)"StealthMeter was uninitialised while applying offsets"); return; } RectTransform component = SprintMeter.GetComponent<RectTransform>(); if ((Object)(object)component == (Object)null) { Plugin.Logger.LogError((object)"SprintRectTransform not found while applying offsets"); return; } int num = 1; Vector3 val = (Vector3)(IsLcVrInstalled ? (new Vector3(0f, -5f, 3f) / (float)num) : new Vector3(3f, -5f, 0f)); Vector3 val2 = (IsLcVrInstalled ? new Vector3(0f, 0.4f, 0.3f) : new Vector3(0.3f, 0.4f, 0f)); _stealthMeter.transform.localPosition = ((Transform)component).localPosition + Plugin.Config.MeterOffset * val; _stealthMeter.transform.localScale = ((Transform)component).localScale + Plugin.Config.MeterOffset * val2; _stealthMeter.transform.rotation = ((Transform)component).rotation; if ((Object)(object)StatusEffectContainer != (Object)null) { int num2 = ((IsOxygenInstalled && !IsLcVrInstalled) ? 1 : 0); StatusEffectContainer.transform.localPosition = _initStatusPosition + new Vector3(Math.Max(num2, Plugin.Config.MeterOffset) * 20f, 0f, 0f); Plugin.Logger.LogInfo((object)"StatusEffectHUD adjusted"); } if ((Object)(object)WeightUi != (Object)null) { WeightUi.transform.localPosition = _initWeightPosition + new Vector3(Math.Max(0f, Plugin.Config.MeterOffset * 20f), 0f, 0f); Plugin.Logger.LogInfo((object)"WeightUI adjusted"); } } private void InitEladsHud() { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) uiElement = ((Component)_stealthMeter.transform.Find("Bar/StaminaBar")).GetComponent<Image>(); uiEladsText = ((Component)_stealthMeter.transform.Find("StaminaInfo")).GetComponent<TextMeshProUGUI>(); ((TMP_Text)uiEladsText).horizontalAlignment = (HorizontalAlignmentOptions)4; Object.DestroyImmediate((Object)(object)((Component)_stealthMeter.transform.Find("CarryInfo")).gameObject); Object.DestroyImmediate((Object)(object)((Component)_stealthMeter.transform.Find("Bar/Stamina Change FG")).gameObject); _stealthMeter.transform.localPosition = SprintMeter.transform.localPosition + new Vector3(0f, 60f, 0f); Plugin.Logger.LogInfo((object)"StealthMeter initialised (EladsHUD)"); } private IEnumerator InitVr() { yield break; } private void ApplyVrMeterOffsets() { if ((Object)(object)_stealthMeter == (Object)null) { Plugin.Logger.LogError((object)"StealthMeter was uninitialised while applying offsets"); return; } Transform transform = SprintMeter.transform; _stealthMeter.transform.SetParent(transform.parent, false); ApplyMeterOffsets(); _stealthMeter.transform.SetParent(transform, true); } } } namespace DramaMask.Patches.StartOfRoundPatch { [HarmonyPatch(typeof(StartOfRound), "EndPlayersFiredSequenceClientRpc")] public class EndPlayersFiredSequencePatch { [HarmonyPostfix] public static void Postfix(StartOfRound __instance) { bool isMaskAttached = NetworkHandler.Instance.MyPretend.IsMaskAttached; NetworkHandler.Instance.MyPretend.IsMaskAttached = false; if (isMaskAttached) { int currentItemSlot = __instance.localPlayerController.currentItemSlot; ((Behaviour)HUDManager.Instance.itemSlotIcons[currentItemSlot]).enabled = false; } NetworkHandler.Instance.MyPretend.Reset(); NetworkHandler.Instance.MyStealth.Reset(); if (!NetworkHandler.IsHostOrServer()) { return; } foreach (KeyValuePair<ulong, StealthData> item in NetworkHandler.Instance.StealthMap) { item.Value.Reset(); } foreach (KeyValuePair<ulong, PretendData> item2 in NetworkHandler.Instance.PretendMap) { item2.Value.Reset(); } } } } namespace DramaMask.Patches.LethalHandsPatch { [HarmonyPatch(typeof(LethalHands))] public class LethalHandsPatch { [HarmonyPatch("SquareUp")] [HarmonyPrefix] public static void Prefix(LethalHands __instance) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Invalid comparison between Unknown and I4 //IL_005f: 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) PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; if (localPlayerController.IsLocal() && NetworkHandler.Instance.MyPretend.IsMaskAttached) { NetworkHandler.Instance.MyPretend.IsMaskAttached = false; if ((int)SyncedInstance<NetworkConfig>.Instance.itemDropMode == 0) { localPlayerController.DiscardHeldObject(false, (NetworkObject)null, default(Vector3), true); } } } } } namespace DramaMask.Patches.HudManagerPatch { [HarmonyPatch(typeof(HUDManager), "Start")] public class StartPatch { [HarmonyPostfix] public static void Postfix(HUDManager __instance) { CoroutineHelper.Start(CreateStealthMeter()); } private static IEnumerator CreateStealthMeter() { yield return (object)new WaitUntil((Func<bool>)(() => (Object)(object)GameNetworkManager.Instance.localPlayerController?.sprintMeterUI != (Object)null)); if (Plugin.Config.UseStealthMeter.Value && Plugin.Config.StealthMeterVisibility.LocalValue != 0) { StealthMeter.Init(); StealthMeter.Instance.Visible = Plugin.Config.StealthMeterVisibility.LocalValue == MeterVisibility.Always; } } } } namespace DramaMask.Patches.HauntedMaskItemPatch { [HarmonyPatch(typeof(HauntedMaskItem), "BeginAttachment")] public class BeginAttachmentPatch { [HarmonyPrefix] public static bool Prefix(HauntedMaskItem __instance) { return !NetworkHandler.Instance.MyPretend.IsMaskAttached || Plugin.Config.AttachedCanPossess.Value; } } [HarmonyPatch(typeof(HauntedMaskItem), "DiscardItem")] public class DiscardItemPatch { [HarmonyPrefix] public static void Prefix(HauntedMaskItem __instance) { if (!((Object)(object)((GrabbableObject)__instance).playerHeldBy == (Object)null)) { ((GrabbableObject)__instance).playerHeldBy.equippedUsableItemQE = false; } } } [HarmonyPatch(typeof(HauntedMaskItem), "EquipItem")] public class EquipItemPatch { [HarmonyPostfix] public static void Postfix(HauntedMaskItem __instance) { ((GrabbableObject)__instance).playerHeldBy.equippedUsableItemQE = true; } } [HarmonyPatch(typeof(HauntedMaskItem), "MaskClampToHeadAnimationEvent")] public class MaskClampPatch { [HarmonyPrefix] public static void Prefix(HauntedMaskItem __instance, bool ___attaching, PlayerControllerB ___previousPlayerHeldBy) { if (___attaching && !((Object)(object)___previousPlayerHeldBy == (Object)null) && !((Object)(object)__instance.currentHeadMask == (Object)null)) { Object.Destroy((Object)(object)((Component)__instance.currentHeadMask).gameObject); __instance.currentHeadMask = null; } } } [HarmonyPatch(typeof(HauntedMaskItem), "PocketItem")] public class PocketItemPatch { [HarmonyPrefix] public static void Prefix(HauntedMaskItem __instance) { if (!((Object)(object)((GrabbableObject)__instance).playerHeldBy == (Object)null)) { ((GrabbableObject)__instance).playerHeldBy.equippedUsableItemQE = false; } } } } namespace DramaMask.Patches.GrabbableObjectItemPatch { [HarmonyPatch(typeof(GrabbableObject), "SetControlTipsForItem")] public class ControlTipsPatch { private static List<string> _defaultTooltips; [HarmonyPostfix] public static void Postfix(GrabbableObject __instance) { HauntedMaskItem val = (HauntedMaskItem)(object)((__instance is HauntedMaskItem) ? __instance : null); if (val != null && !((Object)(object)((GrabbableObject)val).playerHeldBy == (Object)null) && ((NetworkBehaviour)val).IsOwner && !((Object)(object)((GrabbableObject)val).itemProperties == (Object)null) && ((GrabbableObject)val).itemProperties.toolTips != null && val.CanHide()) { if (_defaultTooltips == null) { _defaultTooltips = ((GrabbableObject)val).itemProperties.toolTips.ToList(); } List<string> list = _defaultTooltips.ToList(); if (NetworkHandler.Instance.MyPretend.IsMaskAttached) { list.AddRange(new <>z__ReadOnlyArray<string>(new string[2] { "Detach mask: [Q]", (!NetworkHandler.Instance.MyPretend.IsMaskEyesOn) ? "Activate eyes: [E]" : "Deactivate eyes: [E]" })); } else { list.AddRange(new <>z__ReadOnlyArray<string>(new string[2] { "Attach mask: [Q]", "" })); } ((GrabbableObject)val).itemProperties.toolTips = list.ToArray(); HUDManager.Instance.ChangeControlTipMultiple(((GrabbableObject)val).itemProperties.toolTips, true, ((GrabbableObject)val).itemProperties); } } } [HarmonyPatch(typeof(GrabbableObject), "InteractLeftRightServerRpc")] public class InteractLeftRightPatch { private static bool _useInputFlipFlop; [HarmonyPostfix] public static void Postfix(GrabbableObject __instance, bool right) { HauntedMaskItem val = (HauntedMaskItem)(object)((__instance is HauntedMaskItem) ? __instance : null); if (val == null || !val.CanHide() || (Object)(object)((GrabbableObject)val).playerHeldBy == (Object)null || (!NetworkHandler.IsHostOrServer() && !((GrabbableObject)val).playerHeldBy.IsLocal())) { return; } ulong id = ((GrabbableObject)val).playerHeldBy.GetId(); if (NetworkHandler.IsHostOrServer() && ((GrabbableObject)val).playerHeldBy.IsLocal()) { _useInputFlipFlop = !_useInputFlipFlop; if (_useInputFlipFlop) { return; } } StealthData stealth = NetworkHandler.Instance.GetStealth(((GrabbableObject)val).playerHeldBy.IsLocal(), id); if (stealth == null) { return; } PretendData pretend = NetworkHandler.Instance.GetPretend(((GrabbableObject)val).playerHeldBy.IsLocal(), id); if (pretend == null) { return; } if (pretend.IsMaskAttached) { if (!right) { pretend.IsMaskAttached = false; if (Plugin.Config.ChangeClientViewInstantly) { val.SetMaskAttached(isAttaching: false); } if (stealth.IsHoldingMask) { ((GrabbableObject)val).playerHeldBy.playerBodyAnimator.SetBool("HoldMask", true); ((GrabbableObject)val).playerHeldBy.playerBodyAnimator.Play("HoldingItemsRightHand.HoldMaskToFace", 2, 1f); } else { Traverse.Create((object)val).Field("maskOn").SetValue((object)false); } return; } bool flag = !StartOfRound.Instance.localPlayerUsingController; if (!Plugin.Config.IgnoreCustomKeybinds) { try { flag = InputUtilsCompat.IsMaskEyeInteractClash(); } catch (TypeLoadException) { } } if (((GrabbableObject)val).playerHeldBy.IsLocal() && (!flag || (Object)(object)((GrabbableObject)val).playerHeldBy.hoveringOverTrigger == (Object)null)) { pretend.IsMaskEyesOn = !pretend.IsMaskEyesOn; if (Plugin.Config.ChangeClientViewInstantly) { val.SetMaskEyes(pretend.IsMaskEyesOn); } NetworkHandler.Instance.SetPlayerMaskEyesValueServerRpc(id, pretend.IsMaskEyesOn); } } else if (!right) { pretend.IsMaskAttached = true; if (Plugin.Config.ChangeClientViewInstantly) { val.SetMaskAttached(isAttaching: true); } Traverse.Create((object)val).Field("maskOn").SetValue((object)true); } } } [HarmonyPatch(typeof(GrabbableObject), "ActivateItemServerRpc")] public class ItemActivatePatch { private static bool _useInputFlipFlop; [HarmonyPostfix] public static void Postfix(GrabbableObject __instance, bool onOff, bool buttonDown) { HauntedMaskItem val = (HauntedMaskItem)(object)((__instance is HauntedMaskItem) ? __instance : null); if (val == null || (Object)(object)((GrabbableObject)val).playerHeldBy == (Object)null || (!NetworkHandler.IsHostOrServer() && !((GrabbableObject)val).playerHeldBy.IsLocal())) { return; } ulong id = ((GrabbableObject)val).playerHeldBy.GetId(); if (NetworkHandler.IsHostOrServer() && ((GrabbableObject)val).playerHeldBy.IsLocal()) { _useInputFlipFlop = !_useInputFlipFlop; if (_useInputFlipFlop) { return; } } StealthData stealth = NetworkHandler.Instance.GetStealth(((GrabbableObject)val).playerHeldBy.IsLocal(), id); if (stealth == null) { return; } PretendData pretend = NetworkHandler.Instance.GetPretend(((GrabbableObject)val).playerHeldBy.IsLocal(), id); if (pretend != null) { stealth.IsHoldingMask = buttonDown && val.CanHide(); if (!pretend.IsMaskAttached) { Traverse.Create((object)val).Field("maskOn").SetValue((object)buttonDown); } if (((GrabbableObject)val).playerHeldBy.IsLocal()) { val.SetMaskView(buttonDown ? new int?((int)Plugin.Config.HeldMaskView.LocalValue) : null); } } } } [HarmonyPatch(typeof(GrabbableObject), "Start")] public class StartPatch { [HarmonyPostfix] public static void Postfix(GrabbableObject __instance) { if (__instance is HauntedMaskItem) { __instance.itemProperties.syncUseFunction = true; __instance.itemProperties.syncInteractLRFunction = true; } } } } namespace DramaMask.Patches.PlayerControllerBPatch { [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] public class DisconnectPatch { [HarmonyPostfix] public static void Postfix(GameNetworkManager __instance) { if (StealthMeter.Initialised) { StealthMeter.Initialised = false; } } } [HarmonyPatch(typeof(GameNetworkManager), "SaveItemsInShip")] public class SaveItemsInShipPatch { [HarmonyPrefix] public static void Prefix(GameNetworkManager __instance) { HauntedMaskItem[] array = Object.FindObjectsByType<HauntedMaskItem>((FindObjectsSortMode)0); HauntedMaskItem[] array2 = array; foreach (HauntedMaskItem val in array2) { if ((Object)(object)val == (Object)null || (Object)(object)val.currentHeadMask == (Object)null) { continue; } HauntedMaskItem component = ((Component)val.currentHeadMask).gameObject.GetComponent<HauntedMaskItem>(); if (!((Object)(object)component == (Object)null)) { if (!__instance.isDisconnecting) { break; } ((GrabbableObject)component).deactivated = true; Object.Destroy((Object)(object)((Component)val.currentHeadMask).gameObject); val.currentHeadMask = null; } } } } public class BaseEndSpecialAnimationPatch { public static void HideMaskVisibilityOnAnimationEnd(PlayerControllerB player) { if (!((Object)(object)player == (Object)null) && !((Object)(object)player.currentlyHeldObjectServer == (Object)null)) { GrabbableObject currentlyHeldObjectServer = player.currentlyHeldObjectServer; HauntedMaskItem val = (HauntedMaskItem)(object)((currentlyHeldObjectServer is HauntedMaskItem) ? currentlyHeldObjectServer : null); if (val != null && !((Object)(object)val.currentHeadMask == (Object)null)) { val.SetVisibility(isVisible: false); } } } } [HarmonyPatch(typeof(InteractTrigger), "Interact")] public class InteractPatch { private const string StorageClosetName = "StorageCloset"; private const string DepositCounterName = "DepositCounter"; [HarmonyPrefix] public static bool Prefix(InteractTrigger __instance, Transform playerTransform) { if (((Component)__instance).transform.parent == null || ((Component)__instance).transform.parent.parent == null) { return true; } if (((Object)((Component)__instance).transform.parent.parent).name != "StorageCloset" && ((Object)((Component)__instance).transform.parent.parent).name != "DepositCounter") { return true; } PlayerControllerB component = ((Component)playerTransform).GetComponent<PlayerControllerB>(); StealthData stealth = NetworkHandler.Instance.GetStealth(component.IsLocal(), component.GetId()); if (stealth == null || !stealth.IsAttemptingStealth()) { return true; } HUDManager.Instance.DisplayStatusEffect("Cannot interact with this object while using a mask"); return false; } } [HarmonyPatch(typeof(InteractTrigger), "StopSpecialAnimation")] public class StopSpecialAnimationPatch : BaseEndSpecialAnimationPatch { [HarmonyPrefix] public static void Prefix(InteractTrigger __instance, Transform ___lockedPlayer, out Transform __state) { __state = ___lockedPlayer; } [HarmonyPostfix] public static void Postfix(InteractTrigger __instance, Transform __state) { if (!((Object)(object)__state == (Object)null)) { BaseEndSpecialAnimationPatch.HideMaskVisibilityOnAnimationEnd(((Component)__state).GetComponent<PlayerControllerB>()); } } } [HarmonyPatch(typeof(InteractTrigger), "SetInteractTriggerNotInAnimation")] public class SetInteractTriggerNotInAnimationPatch : BaseEndSpecialAnimationPatch { [HarmonyPostfix] public static void Postfix(InteractTrigger __instance, int playerUsing) { if (StartOfRound.Instance.allPlayerScripts.Length > playerUsing) { BaseEndSpecialAnimationPatch.HideMaskVisibilityOnAnimationEnd(StartOfRound.Instance.allPlayerScripts[playerUsing]); } } } public abstract class BaseChangeItemPatch { protected static bool ShouldInvoke(PlayerControllerB __instance) { if (!__instance.isPlayerControlled) { return true; } if (!__instance.IsLocal()) { return true; } if (!NetworkHandler.Instance.MyPretend.IsMaskAttached) { return true; } return false; } } [HarmonyPatch(typeof(PlayerControllerB), "Discard_performed")] public class DiscardPatch : BaseChangeItemPatch { [HarmonyPrefix] public static bool Prefix(PlayerControllerB __instance) { return BaseChangeItemPatch.ShouldInvoke(__instance); } } [HarmonyPatch(typeof(PlayerControllerB), "DropAllHeldItems")] public class DropAllHeldItemsPatch { private static readonly List<CodeInstruction> _isMaskAttached = new List<CodeInstruction>(2) { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(DropAllHeldItemsPatch), "IsMaskAttached", (Type[])null, (Type[])null)) }; private static readonly List<CodeInstruction> _isPlayerValid = new List<CodeInstruction>(3) { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldarg_2, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(DropAllHeldItemsPatch), "IsPlayerValid", (Type[])null, (Type[])null)) }; private static readonly List<CodeInstruction> _currentItemIsHeld = new List<CodeInstruction>(4) { new CodeInstruction(OpCodes.Ldloc_0, (object)null), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(PlayerControllerB), "currentlyHeldObjectServer")), new CodeInstruction(OpCodes.Ceq, (object)null) }; private static bool IsMaskAttached(PlayerControllerB player) { GrabbableObject currentlyHeldObjectServer = player.currentlyHeldObjectServer; HauntedMaskItem val = (HauntedMaskItem)(object)((currentlyHeldObjectServer is HauntedMaskItem) ? currentlyHeldObjectServer : null); return (Object)(object)val != (Object)null && (Object)(object)val.currentHeadMask != (Object)null; } private static bool IsPlayerValid(PlayerControllerB player, bool disconnecting) { return !player.isPlayerDead && !disconnecting; } [HarmonyPrefix] public static void Prefix(PlayerControllerB __instance, bool itemsFall = true, bool disconnecting = false) { if (!IsPlayerValid(__instance, disconnecting)) { GrabbableObject currentlyHeldObjectServer = __instance.currentlyHeldObjectServer; HauntedMaskItem val = (HauntedMaskItem)(object)((currentlyHeldObjectServer is HauntedMaskItem) ? currentlyHeldObjectServer : null); if (__instance.IsLocal()) { NetworkHandler.Instance.MyPretend.IsMaskAttached = false; } else if (NetworkHandler.IsHostOrServer()) { NetworkHandler.Instance.PretendMap[__instance.GetId()].IsMaskAttached = false; } if (__instance.isPlayerDead && (Object)(object)val != (Object)null && (Object)(object)val.currentHeadMask != (Object)null) { Object.Destroy((Object)(object)((Component)val.currentHeadMask).gameObject); val.currentHeadMask = null; } } } [HarmonyPostfix] public static void Postfix(PlayerControllerB __instance, bool itemsFall = true, bool disconnecting = false) { if (IsPlayerValid(__instance, disconnecting) && IsMaskAttached(__instance)) { __instance.carryWeight = __instance.currentlyHeldObjectServer.itemProperties.weight; } } [HarmonyTranspiler] private static IEnumerable<CodeInstruction> IgnoreDroppingAttachedMask(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Expected O, but got Unknown //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Expected O, but got Unknown //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Expected O, but got Unknown //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Expected O, but got Unknown //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Expected O, but got Unknown //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Expected O, but got Unknown //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Expected O, but got Unknown //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Expected O, but got Unknown //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Expected O, but got Unknown //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Expected O, but got Unknown //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Expected O, but got Unknown //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Expected O, but got Unknown //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Expected O, but got Unknown //IL_02ed: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Expected O, but got Unknown //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[4] { new CodeMatch((OpCode?)OpCodes.Ldloc_1, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldc_I4_1, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Add, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Stloc_1, (object)null, (string)null) }); Label label = generator.DefineLabel(); val.AddLabelsAt(val.Pos, (IEnumerable<Label>)new <>z__ReadOnlySingleElementList<Label>(label)); val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ret, (object)null, (string)null) }); Label label2 = generator.DefineLabel(); val.AddLabelsAt(val.Pos, (IEnumerable<Label>)new <>z__ReadOnlySingleElementList<Label>(label2)); val.Start(); val.MatchForward(true, (CodeMatch[])(object)new CodeMatch[5] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(PlayerControllerB), "ItemSlots"), (string)null), new CodeMatch((OpCode?)OpCodes.Ldloc_1, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldelem_Ref, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Stloc_0, (object)null, (string)null) }); val.Advance(1); val.InsertAndAdvance(_isPlayerValid.Union(_isMaskAttached).Union(_currentItemIsHeld).Union(new <>z__ReadOnlyArray<CodeInstruction>((CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.And, (object)null), new CodeInstruction(OpCodes.And, (object)null), new CodeInstruction(OpCodes.Brtrue, (object)label) }))); val.MatchForward(true, (CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Property(typeof(NetworkBehaviour), "IsOwner").GetMethod, (string)null) }); val.Advance(1); val.InsertAndAdvance(_isPlayerValid.Union(_isMaskAttached).Union(new <>z__ReadOnlyArray<CodeInstruction>((CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.And, (object)null), new CodeInstruction(OpCodes.Not, (object)null), new CodeInstruction(OpCodes.And, (object)null) }))); val.MatchForward(true, (CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(PlayerControllerB), "isHoldingObject"), (string)null) }); val.Advance(1); Label? label3 = default(Label?); while (!CodeInstructionExtensions.Branches(val.Instruction, ref label3)) { val.Advance(1); } val.Advance(1); val.InsertAndAdvance(_isPlayerValid.Union(_isMaskAttached).Union(new <>z__ReadOnlyArray<CodeInstruction>((CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.And, (object)null), new CodeInstruction(OpCodes.Brtrue, (object)label2) }))); return val.InstructionEnumeration(); } } [HarmonyPatch(typeof(PlayerControllerB), "BeginGrabObject")] public class GrabObjectPatch : BaseChangeItemPatch { [HarmonyPrefix] public static bool Prefix(PlayerControllerB __instance) { return BaseChangeItemPatch.ShouldInvoke(__instance); } } [HarmonyPatch(typeof(PlayerControllerB))] public class KillPlayerPatch { [HarmonyPatch("KillPlayerClientRpc")] [HarmonyPrefix] public static void Prefix(int playerId, bool spawnBody, Vector3 bodyVelocity, int causeOfDeath, int deathAnimation) { PlayerControllerB component = StartOfRound.Instance.allPlayerObjects[playerId].GetComponent<PlayerControllerB>(); component.isPlayerDead = true; } [HarmonyPatch("KillPlayer")] [HarmonyPostfix] public static void Postfix(PlayerControllerB __instance, Vector3 bodyVelocity, bool spawnBody, CauseOfDeath causeOfDeath, int deathAnimation) { ulong id = __instance.GetId(); if (__instance.IsLocal()) { NetworkHandler.Instance.MyStealth.Reset(); NetworkHandler.Instance.MyPretend.Reset(); } if (NetworkHandler.IsHostOrServer()) { NetworkHandler.Instance.StealthMap[id].Reset(); NetworkHandler.Instance.PretendMap[id].Reset(); } } } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] public class LateUpdatePatch { [HarmonyPostfix] public static void Postfix(PlayerControllerB __instance) { HandleStealthMeter(__instance); HandleAttachedMask(__instance); } private static void HandleStealthMeter(PlayerControllerB __instance) { if (Plugin.Config.UseStealthMeter.Value && Plugin.Config.StealthMeterVisibility.LocalValue != 0 && StealthMeter.Initialised && __instance.isPlayerControlled && __instance.IsLocal() && !__instance.isPlayerDead) { bool flag = ShouldBarBeVisible(__instance.currentlyHeldObjectServer); StealthMeter.Instance.Visible = flag; if (flag) { float percent = Math.Max(0f, NetworkHandler.Instance.MyStealth.StealthValue) / Plugin.Config.MaxHiddenTime.Value; StealthMeter.Instance.Percent = percent; } } } private static bool ShouldBarBeVisible(GrabbableObject heldItem) { return Plugin.Config.StealthMeterVisibility.LocalValue == MeterVisibility.Always || (((HauntedMaskItem)(object)((heldItem is HauntedMaskItem) ? heldItem : null))?.CanHide() ?? false); } private static void HandleAttachedMask(PlayerControllerB __instance) { if (__instance.isPlayerControlled && !((Object)(object)__instance.currentlyHeldObjectServer == (Object)null)) { GrabbableObject currentlyHeldObjectServer = __instance.currentlyHeldObjectServer; HauntedMaskItem val = (HauntedMaskItem)(object)((currentlyHeldObjectServer is HauntedMaskItem) ? currentlyHeldObjectServer : null); if (val != null && !((Object)(object)val.currentHeadMask == (Object)null)) { AccessTools.Method(typeof(HauntedMaskItem), "PositionHeadMaskWithOffset", (Type[])null, (Type[])null).Invoke(val, null); } } } } public class QeInputPatchBase { public static bool ShouldProcessInput(PlayerControllerB __instance, ref bool isCustomInput, bool right) { if (!InputUtilsCompat.Enabled) { return true; } if ((!right && InputUtilsCompat.IsMaskAttachDefaultClash()) || (right && InputUtilsCompat.IsMaskEyeDefaultClash())) { return true; } bool flag = (Object)(object)__instance != (Object)null && __instance.currentlyHeldObjectServer is HauntedMaskItem; PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController; bool flag2 = (Object)(object)localPlayerController != (Object)null && localPlayerController.currentlyHeldObjectServer is HauntedMaskItem; bool flag3 = false; if (flag == flag2) { flag3 = isCustomInput; isCustomInput = false; } return flag3 ^ !flag; } } [HarmonyPatch(typeof(PlayerControllerB), "ScrollMouse_performed")] public class SwitchSlotsPatch : BaseChangeItemPatch { [HarmonyPrefix] public static bool Prefix(PlayerControllerB __instance) { if (__instance.inTerminalMenu) { return true; } return BaseChangeItemPatch.ShouldInvoke(__instance); } } [HarmonyPatch(typeof(PlayerControllerB), "ItemSecondaryUse_performed")] public class SecondaryUsePatch : QeInputPatchBase { [HarmonyPrefix] public static bool Prefix(PlayerControllerB __instance) { return QeInputPatchBase.ShouldProcessInput(__instance, ref InputUtilsCompat.HandleAttachMask, right: false); } } [HarmonyPatch(typeof(PlayerControllerB), "SwitchToItemSlot")] public class SwitchToItemSlotPatch : BaseChangeItemPatch { [HarmonyPrefix] public static bool Prefix(PlayerControllerB __instance) { return BaseChangeItemPatch.ShouldInvoke(__instance); } } [HarmonyPatch(typeof(PlayerControllerB), "ItemTertiaryUse_performed")] public class TertiaryUsePatch : QeInputPatchBase { [HarmonyPrefix] public static bool Prefix(PlayerControllerB __instance) { return QeInputPatchBase.ShouldProcessInput(__instance, ref InputUtilsCompat.HandleMaskEyes, right: true); } } [HarmonyPatch(typeof(PlayerControllerB), "Update")] public class UpdatePatch { [HarmonyPostfix] public static void Postfix(PlayerControllerB __instance) { if (!Plugin.Config.UseStealthMeter.Value || !__instance.isPlayerControlled || (!NetworkHandler.IsHostOrServer() && !__instance.IsLocal())) { return; } ulong id = __instance.GetId(); PretendData pretend = NetworkHandler.Instance.GetPretend(__instance.IsLocal(), id); if (pretend == null) { return; } StealthData stealth = NetworkHandler.Instance.GetStealth(__instance.IsLocal(), id); if (stealth == null) { return; } bool flag = stealth.IsAttemptingStealth(); if (flag) { if (stealth.StealthValue > 0f) { stealth.StealthValue = Math.Max(0f, stealth.StealthValue - Time.deltaTime * (pretend.IsMaskAttached ? Plugin.Config.AttachedStealthMultiplier.Value : 1f)); } else if (Plugin.Config.RemoveOnDepletion.Value) { pretend.IsMaskAttached = false; } } else if (!flag && stealth.StealthValue < Plugin.Config.MaxHiddenTime.Value && (!stealth.LastStoppedStealth.HasValue || DateTime.UtcNow.Subtract(stealth.LastStoppedStealth.Value).TotalSeconds > (double)Plugin.Config.RechargeDelay.Value)) { stealth.StealthValue = Math.Min(Plugin.Config.MaxHiddenTime.Value, stealth.StealthValue + Time.deltaTime); if (stealth.LastStoppedStealth.HasValue) { stealth.LastStoppedStealth = null; } if (stealth.AddExhaustionPenalty) { stealth.AddExhaustionPenalty = false; } } } } } namespace DramaMask.Patches.Enemies { public abstract class ModifyPlayerArrayPatchBase { private static PlayerControllerB[] allPlayerScriptsOriginal; protected static void AddOobCheckToLoopPredicate(CodeMatcher matcher, ILGenerator generator, CodeInstruction index) { //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown int pos = matcher.Pos; Label? label = default(Label?); if (!CodeInstructionExtensions.Branches(matcher.Instruction, ref label)) { Plugin.Logger.LogWarning((object)"Couldn't apply OOB check to loop predicate: Loop entry target not accessible"); return; } Label enterLoopTarget = label.Value; matcher.Advance(1); Label label2; if ((label2 = matcher.Instruction.labels.FirstOrDefault()) == default(Label)) { label2 = generator.DefineLabel(); matcher.AddLabelsAt(matcher.Pos, (IEnumerable<Label>)new <>z__ReadOnlySingleElementList<Label>(label2)); } matcher.Start(); matcher.SearchForward((Func<CodeInstruction, bool>)((CodeInstruction instruction) => instruction.labels.Contains(enterLoopTarget))); List<CodeInstruction> list = new List<CodeInstruction>(3); list.Add(index); list.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ModifyPlayerArrayPatchBase), "IsWithinPlayerBounds", (Type[])null, (Type[])null))); list.Add(new CodeInstruction(OpCodes.Brfalse, (object)label2)); List<CodeInstruction> list2 = list; CodeInstruction instruction2 = matcher.Instruction; matcher.Insert((IEnumerable<CodeInstruction>)list2); CodeInstructionExtensions.MoveLabelsFrom(matcher.Instruction, instruction2); matcher.Start(); matcher.Advance(pos + list2.Count); } protected static bool IsWithinPlayerBounds(int index) { return index < StartOfRound.Instance.allPlayerScripts.Length; } protected static ulong GetTrueIndex(int index) { return StartOfRound.Instance.allPlayerScripts[index].playerClientId; } protected static void SaveAndModifyPlayerArray(EnemyAI __instance) { if (EnemyTargetHandler.ShouldHideFromEnemy(__instance)) { allPlayerScriptsOriginal = StartOfRound.Instance.allPlayerScripts; StartOfRound.Instance.allPlayerScripts = StartOfRound.Instance.allPlayerScripts.Where((PlayerControllerB player) => (Object)(object)player == (Object)null || !player.isPlayerControlled || !player.IsHidden()).ToArray(); } } protected static void LoadOriginalPlayerArray(EnemyAI __instance) { if (EnemyTargetHandler.ShouldHideFromEnemy(__instance)) { StartOfRound.Instance.allPlayerScripts = allPlayerScriptsOriginal; } } } public abstract class OnCollideWithPlayerPatchBase { protected static void AddNoCollideCheck(CodeMatcher matcher, ILGenerator generator, CodeInstruction player, string enemyName) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown matcher.Advance(1); Label label = generator.DefineLabel(); matcher.AddLabelsAt(matcher.Pos, (IEnumerable<Label>)new <>z__ReadOnlySingleElementList<Label>(label)); matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[9] { player, new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(PlayerControllerBExtensions), "IsHidden", (Type[])null, (Type[])null)), player, new CodeInstruction(OpCodes.Ldstr, (object)enemyName), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(EnemyTargetHandler), "ShouldCollideWithEnemy", new Type[2] { typeof(PlayerControllerB), typeof(string) }, (Type[])null)), new CodeInstruction(OpCodes.Not, (object)null), new CodeInstruction(OpCodes.And, (object)null), new CodeInstruction(OpCodes.Brfalse, (object)label), new CodeInstruction(OpCodes.Ret, (object)null) }); } } } namespace DramaMask.Patches.Enemies.TurretPatch { [HarmonyPatch(typeof(Turret), "CheckForPlayersInLineOfSight")] public class CheckForPlayersInLineOfSightPatch { private static readonly List<CodeInstruction> _isPlayerHidden = new List<CodeInstruction>(2) { new CodeInstruction(OpCodes.Ldloc_3, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(PlayerControllerBExtensions), "IsHidden", (Type[])null, (Type[])null)) }; [HarmonyTranspiler] private static IEnumerable<CodeInstruction> HidePlayerFromRaycast(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldstr, (object)"Player", (string)null) }); val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null) }); val.Advance(-1); object operand = val.Instruction.operand; val.MatchForward(true, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Stloc_3, (object)null, (string)null) }); val.Advance(1); val.InsertAndAdvance(_isPlayerHidden.Union(new <>z__ReadOnlySingleElementList<CodeInstruction>(new CodeInstruction(OpCodes.Brtrue, operand)))); return val.InstructionEnumeration(); } } } namespace DramaMask.Patches.Enemies.SandWormAIPatch { [HarmonyPatch(typeof(SandWormAI), "OnCollideWithPlayer")] public class OnCollideWithPlayerPatch : OnCollideWithPlayerPatchBase { [HarmonyTranspiler] private static IEnumerable<CodeInstruction> CheckIfNoCollide(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Stloc_0, (object)null, (string)null) }); OnCollideWithPlayerPatchBase.AddNoCollideCheck(val, generator, new CodeInstruction(OpCodes.Ldloc_0, (object)null), "SandWormAI"); return val.InstructionEnumeration(); } } } namespace DramaMask.Patches.Enemies.SandSpiderAIPatch { [HarmonyPatch(typeof(SandSpiderAI), "DoAIInterval")] public class DoAIIntervalPatch : ModifyPlayerArrayPatchBase { [HarmonyPrefix] public static void Prefix(SandSpiderAI __instance) { ModifyPlayerArrayPatchBase.SaveAndModifyPlayerArray((EnemyAI)(object)__instance); } [HarmonyAfter(new string[] { "notnotnotswipez-MoreCompany-1.8.1", "bizzlemip-BiggerLobby-2.6.0", "PotatoePet-AdvancedCompany-1.0.150" })] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> StopOutOfBounds(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.End(); val.MatchBack(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Blt, (object)null, (string)null) }); ModifyPlayerArrayPatchBase.AddOobCheckToLoopPredicate(val, generator, new CodeInstruction(OpCodes.Ldloc_1, (object)null)); return val.InstructionEnumeration(); } [HarmonyPostfix] public static void Postfix(SandSpiderAI __instance) { ModifyPlayerArrayPatchBase.LoadOriginalPlayerArray((EnemyAI)(object)__instance); } } [HarmonyPatch(typeof(SandSpiderAI), "TriggerChaseWithPlayer")] public class TriggerChaseWithPlayerPatch { [HarmonyPrefix] public static bool Prefix(SandSpiderAI __instance, PlayerControllerB playerScript) { if (!EnemyTargetHandler.ShouldHideFromEnemy("SandSpiderAI")) { return true; } return !playerScript.IsHidden(); } } } namespace DramaMask.Patches.Enemies.RedLocustBeesPatch { [HarmonyPatch(typeof(RedLocustBees), "DoAIInterval")] public class DoAIIntervalPatch { private static bool IsPlayerHidden() { return EnemyTargetHandler.ShouldHideFromEnemy("RedLocustBees") && StartOfRound.Instance.localPlayerController.IsHidden(); } [HarmonyTranspiler] private static IEnumerable<CodeInstruction> HidePlayerFromCollider(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldelem_Ref, (object)null, (string)null) }); val.Advance(7); val.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(DoAIIntervalPatch), "IsPlayerHidden", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Not, (object)null), new CodeInstruction(OpCodes.And, (object)null) }); return val.InstructionEnumeration(); } } } namespace DramaMask.Patches.Enemies.RadMechAIPatch { [HarmonyPatch(typeof(RadMechAI), "CheckSightForThreat")] public class CheckSightForThreatPatch { private static bool IsThreatHiddenPlayer(Collider collider) { IVisibleThreat val = default(IVisibleThreat); int result; if (EnemyTargetHandler.ShouldHideFromEnemy("RadMechAI") && ((Component)((Component)collider).transform).TryGetComponent<IVisibleThreat>(ref val)) { PlayerControllerB val2 = (PlayerControllerB)(object)((val is PlayerControllerB) ? val : null); if (val2 != null) { result = (val2.IsHidden() ? 1 : 0); goto IL_002f; } } result = 0; goto IL_002f; IL_002f: return (byte)result != 0; } [HarmonyTranspiler] private static IEnumerable<CodeInstruction> HidePlayerFromCollider(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Expected O, but got Unknown //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Br, (object)null, (string)null) }); val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Brtrue, (object)null, (string)null) }); object operand = val.Instruction.operand; val.Advance(1); val.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[6] { new CodeInstruction(OpCodes.Call, (object)AccessTools.Property(typeof(RoundManager), "Instance").GetMethod), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(RoundManager), "tempColliderResults")), new CodeInstruction(OpCodes.Ldloc_S, (object)5), new CodeInstruction(OpCodes.Ldelem_Ref, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(CheckSightForThreatPatch), "IsThreatHiddenPlayer", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Brtrue, operand) }); return val.InstructionEnumeration(); } } [HarmonyPatch(typeof(RadMechAI), "LookForPlayersInFlight")] public class LookForPlayersInFlightPatch : ModifyPlayerArrayPatchBase { [HarmonyPrefix] public static void Prefix(RadMechAI __instance) { ModifyPlayerArrayPatchBase.SaveAndModifyPlayerArray((EnemyAI)(object)__instance); } [HarmonyAfter(new string[] { "notnotnotswipez-MoreCompany-1.8.1", "bizzlemip-BiggerLobby-2.6.0", "PotatoePet-AdvancedCompany-1.0.150" })] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> StopOutOfBounds(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.End(); val.MatchBack(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Blt, (object)null, (string)null) }); ModifyPlayerArrayPatchBase.AddOobCheckToLoopPredicate(val, generator, new CodeInstruction(OpCodes.Ldloc_0, (object)null)); return val.InstructionEnumeration(); } [HarmonyPostfix] public static void Postfix(RadMechAI __instance) { ModifyPlayerArrayPatchBase.LoadOriginalPlayerArray((EnemyAI)(object)__instance); } } } namespace DramaMask.Patches.Enemies.NutcrackerEnemyAIPatch { [HarmonyPatch(typeof(NutcrackerEnemyAI), "CheckLineOfSightForLocalPlayer")] public class CheckLineOfSightForLocalPlayerPatch { [HarmonyPrefix] public static bool Prefix(NutcrackerEnemyAI __instance, ref bool __result, float width = 45f, int range = 60, int proximityAwareness = -1) { if (!GameNetworkManager.Instance.localPlayerController.IsHidden()) { return true; } __result = false; return false; } } } namespace DramaMask.Patches.Enemies.JesterAIPatch { [HarmonyPatch(typeof(JesterAI), "Update")] public class UpdatePatch { private static readonly List<CodeInstruction> _isPlayerHidden = new List<CodeInstruction>(5) { new CodeInstruction(OpCodes.Call, (object)AccessTools.Property(typeof(StartOfRound), "Instance").GetMethod), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(StartOfRound), "allPlayerScripts")), new CodeInstruction(OpCodes.Ldloc_2, (object)null), new CodeInstruction(OpCodes.Ldelem_Ref, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(PlayerControllerBExtensions), "IsHidden", (Type[])null, (Type[])null)) }; [HarmonyTranspiler] private static IEnumerable<CodeInstruction> HidePlayerFromPopCheck(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(PlayerControllerB), "isInsideFactory"), (string)null) }); val.Advance(1); object operand = val.Instruction.operand; val.Advance(1); val.InsertAndAdvance(_isPlayerHidden.Union(new <>z__ReadOnlySingleElementList<CodeInstruction>(new CodeInstruction(OpCodes.Brtrue, operand)))); return val.InstructionEnumeration(); } } } namespace DramaMask.Patches.Enemies.ForestGiantAIPatch { [HarmonyPatch(typeof(ForestGiantAI), "OnCollideWithPlayer")] public class OnCollideWithPlayerPatch : OnCollideWithPlayerPatchBase { [HarmonyTranspiler] private static IEnumerable<CodeInstruction> CheckIfNoCollide(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Stloc_0, (object)null, (string)null) }); OnCollideWithPlayerPatchBase.AddNoCollideCheck(val, generator, new CodeInstruction(OpCodes.Ldloc_0, (object)null), "ForestGiantAI"); return val.InstructionEnumeration(); } } } namespace DramaMask.Patches.Enemies.EnemyAIPatch { [HarmonyPatch(typeof(EnemyAI), "CheckLineOfSightForClosestPlayer")] public class CheckLineOfSightForClosestPlayerPatch : ModifyPlayerArrayPatchBase { [HarmonyPrefix] public static void Prefix(EnemyAI __instance, float width = 45f, int range = 60, int proximityAwareness = -1, float bufferDistance = 0f) { ModifyPlayerArrayPatchBase.SaveAndModifyPlayerArray(__instance); } [HarmonyAfter(new string[] { "notnotnotswipez-MoreCompany-1.8.1", "bizzlemip-BiggerLobby-2.6.0", "PotatoePet-AdvancedCompany-1.0.150" })] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> StopOutOfBounds(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.End(); val.MatchBack(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Blt, (object)null, (string)null) }); ModifyPlayerArrayPatchBase.AddOobCheckToLoopPredicate(val, generator, new CodeInstruction(OpCodes.Ldloc_S, (object)4)); return val.InstructionEnumeration(); } [HarmonyPostfix] public static void Postfix(EnemyAI __instance, ref PlayerControllerB __result, float width = 45f, int range = 60, int proximityAwareness = -1, float bufferDistance = 0f) { ModifyPlayerArrayPatchBase.LoadOriginalPlayerArray(__instance); } } [HarmonyPatch(typeof(EnemyAI), "CheckLineOfSightForPlayer")] public class CheckLineOfSightForPlayerPatch : ModifyPlayerArrayPatchBase { [HarmonyPrefix] public static void Prefix(EnemyAI __instance, float width = 45f, int range = 60, int proximityAwareness = -1) { ModifyPlayerArrayPatchBase.SaveAndModifyPlayerArray(__instance); } [HarmonyAfter(new string[] { "notnotnotswipez-MoreCompany-1.8.1", "bizzlemip-BiggerLobby-2.6.0", "PotatoePet-AdvancedCompany-1.0.150" })] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> StopOutOfBounds(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.End(); val.MatchBack(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Blt, (object)null, (string)null) }); ModifyPlayerArrayPatchBase.AddOobCheckToLoopPredicate(val, generator, new CodeInstruction(OpCodes.Ldloc_1, (object)null)); return val.InstructionEnumeration(); } [HarmonyPostfix] public static void Postfix(EnemyAI __instance, ref PlayerControllerB __result, float width = 45f, int range = 60, int proximityAwareness = -1) { ModifyPlayerArrayPatchBase.LoadOriginalPlayerArray(__instance); } } [HarmonyPatch(typeof(EnemyAI), "GetAllPlayersInLineOfSight")] public class GetAllPlayersInLineOfSightPatch : ModifyPlayerArrayPatchBase { [HarmonyPrefix] public static void Prefix(EnemyAI __instance, float width = 45f, int range = 60, Transform eyeObject = null, float proximityCheck = -1f, int layerMask = -1) { ModifyPlayerArrayPatchBase.SaveAndModifyPlayerArray(__instance); } [HarmonyAfter(new string[] { "notnotnotswipez-MoreCompany-1.8.1", "bizzlemip-BiggerLobby-2.6.0", "PotatoePet-AdvancedCompany-1.0.150" })] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> StopOutOfBounds(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.End(); val.MatchBack(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Blt, (object)null, (string)null) }); ModifyPlayerArrayPatchBase.AddOobCheckToLoopPredicate(val, generator, new CodeInstruction(OpCodes.Ldloc_2, (object)null)); return val.InstructionEnumeration(); } [HarmonyPostfix] public static void Postfix(EnemyAI __instance, ref PlayerControllerB[] __result, float width = 45f, int range = 60, Transform eyeObject = null, float proximityCheck = -1f, int layerMask = -1) { ModifyPlayerArrayPatchBase.LoadOriginalPlayerArray(__instance); } } [HarmonyPatch(typeof(EnemyAI), "GetClosestPlayer")] public class GetClosestPlayerPatch : ModifyPlayerArrayPatchBase { [HarmonyPrefix] public static void Prefix(EnemyAI __instance, bool requireLineOfSight = false, bool cannotBeInShip = false, bool cannotBeNearShip = false) { ModifyPlayerArrayPatchBase.SaveAndModifyPlayerArray(__instance); } [HarmonyAfter(new string[] { "notnotnotswipez-MoreCompany-1.8.1", "bizzlemip-BiggerLobby-2.6.0", "PotatoePet-AdvancedCompany-1.0.150" })] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> StopOutOfBounds(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.End(); val.MatchBack(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Blt, (object)null, (string)null) }); ModifyPlayerArrayPatchBase.AddOobCheckToLoopPredicate(val, generator, new CodeInstruction(OpCodes.Ldloc_1, (object)null)); return val.InstructionEnumeration(); } [HarmonyPostfix] public static void Postfix(EnemyAI __instance, ref PlayerControllerB __result, bool requireLineOfSight = false, bool cannotBeInShip = false, bool cannotBeNearShip = false) { ModifyPlayerArrayPatchBase.LoadOriginalPlayerArray(__instance); } } [HarmonyPatch(typeof(EnemyAI), "PlayerIsTargetable")] public class PlayerIsTargetablePatch { [HarmonyPrefix] public static bool Prefix(EnemyAI __instance, ref bool __result, PlayerControllerB playerScript, bool cannotBeInShip = false, bool overrideInsideFactoryCheck = false) { if (playerScript.IsHidden() && !EnemyTargetHandler.ShouldCollideWithEnemy(playerScript, __instance)) { __result = false; return false; } if (!Plugin.Config.IncreaseCustomEnemyCompatibility.Value) { return true; } string name = new StackFrame(1).GetMethod().Name; if ("MeetsStandardPlayerCollisionConditions" == name) { return true; } if (!playerScript.IsHidden()) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(EnemyAI), "TargetClosestPlayer")] public class TargetClosestPlayerPatch : ModifyPlayerArrayPatchBase { [HarmonyPrefix] public static void Prefix(EnemyAI __instance, float bufferDistance = 1.5f, bool requireLineOfSight = false, float viewWidth = 70f) { ModifyPlayerArrayPatchBase.SaveAndModifyPlayerArray(__instance); } [HarmonyAfter(new string[] { "notnotnotswipez-MoreCompany-1.8.1", "bizzlemip-BiggerLobby-2.6.0", "PotatoePet-AdvancedCompany-1.0.150" })] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> StopOutOfBounds(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.End(); val.MatchBack(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Blt, (object)null, (string)null) }); ModifyPlayerArrayPatchBase.AddOobCheckToLoopPredicate(val, generator, new CodeInstruction(OpCodes.Ldloc_1, (object)null)); return val.InstructionEnumeration(); } [HarmonyPostfix] public static void Postfix(EnemyAI __instance, ref bool __result, float bufferDistance = 1.5f, bool requireLineOfSight = false, float viewWidth = 70f) { ModifyPlayerArrayPatchBase.LoadOriginalPlayerArray(__instance); } } } namespace DramaMask.Patches.Enemies.DressGirlAIPatch { [HarmonyPatch(typeof(DressGirlAI), "ChoosePlayerToHaunt")] public class ChoosePlayerToHauntPatch : ModifyPlayerArrayPatchBase { [HarmonyPrefix] public static void Prefix(DressGirlAI __instance) { ModifyPlayerArrayPatchBase.SaveAndModifyPlayerArray((EnemyAI)(object)__instance); } [HarmonyAfter(new string[] { "notnotnotswipez-MoreCompany-1.8.1", "bizzlemip-BiggerLobby-2.6.0", "PotatoePet-AdvancedCompany-1.0.150" })] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> StopOutOfBounds(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Blt, (object)null, (string)null) }); ModifyPlayerArrayPatchBase.AddOobCheckToLoopPredicate(val, generator, new CodeInstruction(OpCodes.Ldloc_S, (object)5)); val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Blt, (object)null, (string)null) }); ModifyPlayerArrayPatchBase.AddOobCheckToLoopPredicate(val, generator, new CodeInstruction(OpCodes.Ldloc_S, (object)6)); return val.InstructionEnumeration(); } [HarmonyPostfix] public static void Postfix(DressGirlAI __instance) { ModifyPlayerArrayPatchBase.LoadOriginalPlayerArray((EnemyAI)(object)__instance); } } } namespace DramaMask.Patches.Enemies.CrawlerAIPatch { [HarmonyPatch(typeof(CrawlerAI), "CheckForVeryClosePlayer")] public class CheckForVeryClosePlayerPatch { private static readonly List<CodeInstruction> _getVisiblePlayerCollider = new List<CodeInstruction>(2) { new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(CrawlerAI), "nearPlayerColliders")), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(CheckForVeryClosePlayerPatch), "GetVisiblePlayerCollider", (Type[])null, (Type[])null)) }; private static PlayerControllerB GetVisiblePlayerCollider(Collider[] nearPlayerColliders) { foreach (Collider val in nearPlayerColliders) { if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).transform == (Object)null)) { PlayerControllerB component = ((Component)((Component)val).transform).GetComponent<PlayerControllerB>(); if (!((Object)(object)component == (Object)null) && !component.IsHidden()) { return component; } } } return null; } [HarmonyTranspiler] private static IEnumerable<CodeInstruction> HidePlayerFromCollider(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ret, (object)null, (string)null) }); val.Advance(2); val.RemoveInstructions(5); val.InsertAndAdvance((IEnumerable<CodeInstruction>)_getVisiblePlayerCollider); return val.InstructionEnumeration(); } } } namespace DramaMask.Patches.Enemies.ClaySurgeonAIPatch { [HarmonyPatch(typeof(ClaySurgeonAI), "DoAIInterval")] public class DoAIIntervalPatch { [HarmonyTranspiler] private static IEnumerable<CodeInstruction> HandleNonTargetablePlayer(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.End(); val.MatchBack(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Brfalse, (object)null, (string)null) }); object operand = val.Instruction.operand; val.Advance(1); val.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[6] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldloc_0, (object)null), new CodeInstruction(OpCodes.Ldc_I4_0, (object)null), new CodeInstruction(OpCodes.Ldc_I4_0, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(EnemyAI), "PlayerIsTargetable", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Brfalse, operand) }); return val.InstructionEnumeration(); } } } namespace DramaMask.Patches.Enemies.CentipedeAIPatch { [HarmonyPatch(typeof(CentipedeAI), "TriggerCentipedeFallServerRpc")] public class TriggerCentipedeFallPatch { [HarmonyPrefix] public static bool Prefix(CentipedeAI __instance, ref bool ___triggeredFall, ulong clientId) { if (!GameNetworkManager.Instance.localPlayerController.IsHidden()) { return true; } ___triggeredFall = false; return false; } } } namespace DramaMask.Patches.Enemies.ButlerEnemyAIPatch { [HarmonyPatch(typeof(ButlerEnemyAI), "CheckLOS")] public class CheckLOSPatch : ModifyPlayerArrayPatchBase { [HarmonyPrefix] public static void Prefix(ButlerEnemyAI __instance) { ModifyPlayerArrayPatchBase.SaveAndModifyPlayerArray((EnemyAI)(object)__instance); } [HarmonyAfter(new string[] { "notnotnotswipez-MoreCompany-1.8.1", "bizzlemip-BiggerLobby-2.6.0", "PotatoePet-AdvancedCompany-1.0.150" })] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> StopOutOfBounds(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.End(); val.MatchBack(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Blt, (object)null, (string)null) }); ModifyPlayerArrayPatchBase.AddOobCheckToLoopPredicate(val, generator, new CodeInstruction(OpCodes.Ldloc_S, (object)4)); val.MatchBack(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Clt, (object)null, (string)null) }); val.MatchBack(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldloc_S, (object)null, (string)null) }); val.Advance(-1); val.MatchBack(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldloc_S, (object)null, (string)null) }); val.Advance(-1); while (true) { val.MatchBack(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldloc_S, (object)null, (string)null) }); if (val.Pos == -1) { break; } val.Advance(1); if (val.Instruction.opcode == OpCodes.Stloc_3 || val.Instruction.opcode == OpCodes.Stloc_S) { val.Advance(-2); continue; } val.Advance(-2); if (!CodeInstructionExtensions.Is(val.Instruction, OpCodes.Ldfld, (MemberInfo)AccessTools.Field(typeof(StartOfRound), "allPlayerScripts"))) { val.Advance(2); val.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ModifyPlayerArrayPatchBase), "GetTrueIndex", (Type[])null, (Type[])null)) }); val.Advance(-3); } } return val.InstructionEnumeration(); } [HarmonyPostfix] public static void Postfix(ButlerEnemyAI __instance) { ModifyPlayerArrayPatchBase.LoadOriginalPlayerArray((EnemyAI)(object)__instance); } } } namespace DramaMask.Patches.Enemies.BaboonBirdAIPatch { [HarmonyPatch(typeof(BaboonBirdAI), "DoLOSCheck")] public class DoLOSCheckPatch { private static bool IsThreatHiddenPlayer(IVisibleThreat threat) { int result; if (EnemyTargetHandler.ShouldHideFromEnemy("BaboonBirdAI")) { PlayerControllerB val = (PlayerControllerB)(object)((threat is PlayerControllerB) ? threat : null); if (val != null) { result = (val.IsHidden() ? 1 : 0); goto IL_0020; } } result = 0; goto IL_0020; IL_0020: return (byte)result != 0; } [HarmonyTranspiler] private static IEnumerable<CodeInstruction> HidePlayerFromCollider(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldloc_0, (object)null, (string)null) }); val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null) }); val.Advance(-1); object operand = val.Instruction.operand; val.MatchBack(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldloc_0, (object)null, (string)null) }); val.Advance(3); val.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldloc_0, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(DoLOSCheckPatch), "IsThreatHiddenPlayer", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Brtrue, operand) }); return val.InstructionEnumeration(); } } } namespace DramaMask.Network { public class NetworkHandler : NetworkBehaviour { public NetworkList<ulong> VisiblePlayers; public static NetworkHandler Instance { get; private set; } public Dictionary<ulong, StealthData> StealthMap { get; private set; } public StealthData MyStealth { get; private set; } public Dictionary<ulong, PretendData> PretendMap { get; private set; } public PretendData MyPretend { get; private set; } public StealthData GetStealth(bool isLocal, ulong id) { return StealthMap.GetNetworkData(MyStealth, isLocal, id); } public PretendData GetPretend(bool isLocal, ulong id) { return PretendMap.GetNetworkData(MyPretend, isLocal, id); } public static bool IsHostOrServer() { return NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer; } private void Awake() { VisiblePlayers = new NetworkList<ulong>(); ((NetworkVariableBase)VisiblePlayers).Initialize((NetworkBehaviour)(object)this); } public override void OnNetworkSpawn() { NetworkHandler instance = Instance; Instance = this; MyStealth = new StealthData(); MyPretend = new PretendData(); if (IsHostOrServer()) { StealthMap = new Dictionary<ulong, StealthData>(); PretendMap = new Dictionary<ulong, PretendData>(); VisiblePlayers.Clear(); RegisterPlayer(0uL); ((NetworkBehaviour)this).NetworkManager.OnClientConnectedCallback += NetworkManager_OnClientConnectedCallback; ((NetworkBehaviour)this).NetworkManager.OnClientDisconnectCallback += NetworkManager_OnClientDisconnectedCallback; } VisiblePlayers.OnListChanged += OnVisiblePlayersChanged; ((NetworkBehaviour)this).OnNetworkSpawn(); } public override void OnNetworkDespawn() { if (IsHostOrServer()) { ((NetworkBehaviour)this).NetworkManager.OnClientConnectedCallback -= NetworkManager_OnClientConnectedCallback; ((NetworkBehaviour)this).NetworkManager.OnClientDisconnectCallback -= NetworkManager_OnClientDisconnectedCallback; } VisiblePlayers.OnListChanged -= OnVisiblePlayersChanged; ((NetworkBehaviour)this).OnNetworkDespawn(); } private void NetworkManager_OnClientConnectedCallback(ulong obj) { if (obj != 0) { RegisterPlayer(obj); } } private void RegisterPlayer(ulong id) { if (!StealthMap.ContainsKey(id)) { StealthMap.Add(id, new StealthData(id)); } if (!PretendMap.ContainsKey(id)) { PretendMap.Add(id, new PretendData(id)); } if (!VisiblePlayers.Contains(id)) { VisiblePlayers.Add(id); } } private void NetworkManager_OnClientDisconnectedCallback(ulong obj) { if (obj != 0) { UnregisterPlayer(obj); } } private void UnregisterPlayer(ulong id) { if (StealthMap.ContainsKey(id)) { StealthMap.Remove(id); } if (!PretendMap.ContainsKey(id)) { PretendMap.Remove(id); } if (VisiblePlayers == null) { Plugin.Logger.LogWarning((object)"Visible player list could not unregister player: This is fine on host disconnection"); } else if (VisiblePlayers.Contains(id)) { VisiblePlayers.Remove(id); } } private void OnVisiblePlayersChanged(NetworkListEvent<ulong> changeEvent) { Plugin.Logger.LogInfo((object)("Visible players: [" + VisiblePlayers.AsString<ulong>() + "]")); if (!IsHostOrServer()) { } } public void SetPlayerHiddenServer(ulong playerId, bool isHidden) { if (isHidden && VisiblePlayers.Contains(playerId)) { VisiblePlayers.Remove(playerId); } else if (!isHidden && !VisiblePlayers.Contains(playerId)) { VisiblePlayers.Add(playerId); } } public void SetPlayerMaskAttachedServer(ulong playerId, bool isAttaching) { SetPlayerMaskAttachedClientRpc(playerId, isAttaching); } [ClientRpc] public void SetPlayerMaskAttachedClientRpc(ulong playerId, bool isAttaching) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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_008a: 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_00a4: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(4253758658u, val, (RpcDelivery)0); BytePacker.WriteValueBitPacked(val2, playerId); ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref isAttaching, default(ForPrimitives)); ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 4253758658u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost)) { PlayerControllerB player = StartOfRound.Instance.GetPlayer(playerId); Plugin.Logger.LogDebug((object)$"AttachMaskClientRPC {playerId} -> {player}: {isAttaching}"); if (!IsMaskActionValid(player, out var mask, out var reasonInvalid)) { Plugin.Logger.LogDebug((object)("AttachMaskClientRPC invalid call: " + reasonInvalid)); } else { mask.SetMaskAttached(isAttaching); } } } [ServerRpc(RequireOwnership = false)] public void SetPlayerMaskEyesValueServerRpc(ulong playerId, bool isActivating) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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_008a: 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_00a4: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager != null && networkManager.IsListening) { if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost)) { ServerRpcParams val = default(ServerRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(3585587505u, val, (RpcDelivery)0); BytePacker.WriteValueBitPacked(val2, playerId); ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref isActivating, default(ForPrimitives)); ((NetworkBehaviour)this).__endSendServerRpc(ref val2, 3585587505u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost)) { PretendMap[playerId].IsMaskEyesOn = isActivating; } } } public void SetPlayerMaskEyesServer(ulong playerId, bool isActivating) { SetPlayerMaskEyesClientRpc(playerId, isActivating); } [ClientRpc] public void SetPlayerMaskEyesClientRpc(ulong playerId, bool isActivating) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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_008a: 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_00a4: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3711124253u, val, (RpcDelivery)0); BytePacker.WriteValueBitPacked(val2, playerId); ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref isActivating, default(ForPrimitives)); ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3711124253u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost)) { PlayerControllerB player = StartOfRound.Instance.GetPlayer(playerId); Plugin.Logger.LogDebug((object)$"MaskEyesClientRPC {playerId} -> {player}: {isActivating}"); if (!IsMaskActionValid(player, out var mask, out var reasonInvalid)) { Plugin.Logger.LogDebug((object)("MaskEyesClientRPC invalid call: " + reasonInvalid)); } else { mask.SetMaskEyes(isActivating); } } } private bool IsMaskActionValid(PlayerControllerB player, out HauntedMaskItem mask, out string reasonInvalid) { reasonInvalid = null; mask = null; if ((Object)(object)player == (Object)null) { reasonInvalid = "Player is null"; retu