using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using HarmonyLib; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Microsoft.CodeAnalysis; using OutOfThePast.Patches.BugFixPatches; using OutOfThePast.Patches.DecorPatches; using OutOfThePast.Patches.DialoguePatches; using OutOfThePast.Patches.EchelonPatches; using OutOfThePast.Patches.InteractionPatches; using OutOfThePast.Patches.SideJobPatches; using OutOfThePast.Patches.UIPatches; using SOD.Common.BepInEx; using SOD.Common.BepInEx.Configuration; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("OutOfThePast")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+4b5f1cb49ccf6ac6359aa3ac203c3b7adb2c1714")] [assembly: AssemblyProduct("My first plugin")] [assembly: AssemblyTitle("OutOfThePast")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace OutOfThePast { public interface IPluginBindings : IPatchToggleBindings, IPatchExtraBindings, IAdjustPayphoneCallDelayBindings, IDecorBindings, IDebugBindings { } public interface IPatchToggleBindings { [Binding(true, "Enable Improved Payphone Call Delay", "_PatchEnable.PayphoneCallDelay")] bool PatchEnablePayphoneCallDelay { get; set; } [Binding(true, "Enable Talking While Sitting", "_PatchEnable.SitAndTalk")] bool PatchEnableSitAndTalk { get; set; } [Binding(true, "Enable Pass Time BugFixes", "_PatchEnable.PassTimeBugFixes")] bool PatchEnablePassTimeBugFixes { get; set; } [Binding(true, "Suppress [Target] brackets on all action prompts", "_PatchEnable.SuppressAllTargetBrackets")] bool PatchEnableSuppressAllTargetBrackets { get; set; } [Binding(true, "Enable Echelon Zone Restrictions", "_PatchEnable.EchelonZoneRestrictions")] bool PatchEnableEchelonZoneRestrictions { get; set; } [Binding(true, "Enable Extended Decor Placement", "_PatchEnable.ExtendDecorPlacement")] bool PatchEnableExtendDecorPlacement { get; set; } [Binding(true, "Enable Place Cigarette Butt in Ashtray", "_PatchEnable.PlaceCigaretteButtInAshtray")] bool PatchEnablePlaceCigaretteButtInAshtray { get; set; } [Binding(true, "Fix Wok being held upside-down", "_PatchEnable.FixWokRotation")] bool PatchEnableFixWokRotation { get; set; } [Binding(true, "Don't pause game when opening the case board or notebook", "_PatchEnable.NoPauseCaseBoard")] bool PatchEnableNoPauseCaseBoard { get; set; } } public interface IPatchExtraBindings { [Binding(false, "Require watch to be held for Pass Time while sitting", "_PatchExtra.PassTimeRequiresWatch")] bool PatchExtraEnablePassTimeRequiresWatch { get; set; } } public interface IAdjustPayphoneCallDelayBindings { [Binding(20, "Minimum delay (minutes) before Side Job phone rings", "PayphoneCallDelay.MinimumDelay")] int PayphoneCallDelayMinimumDelay { get; set; } [Binding(30, "Maximum delay (minutes) before Side Job phone rings", "PayphoneCallDelay.MaximumDelay")] int PayphoneCallDelayMaximumDelay { get; set; } } public interface IDecorBindings { [Binding(0.9f, "How far decor items are held from the camera during placement", "Decor.DecorPlaceDistance")] float DecorPlaceDistance { get; set; } } public interface IDebugBindings { [Binding(false, "Enable SitAndTalk Debug Console", "zzz.Debug.SitAndTalk")] bool DebugSitAndTalk { get; set; } } [BepInPlugin("Sclamy.OutOfThePast", "OutOfThePast", "0.6.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : PluginController { public const string PLUGIN_GUID = "Sclamy.OutOfThePast"; public const string PLUGIN_NAME = "OutOfThePast"; public const string PLUGIN_VERSION = "0.6.2"; public override void Load() { //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Expected O, but got Unknown PatchIfEnabled(typeof(AdjustPayphoneCallDelay), base.Config.PatchEnablePayphoneCallDelay); PatchIfEnabled(typeof(SitAndTalk), base.Config.PatchEnableSitAndTalk); PatchIfEnabled(typeof(PassTimeImprovements), base.Config.PatchEnablePassTimeBugFixes); PatchIfEnabled(typeof(SuppressAllTargetBrackets), base.Config.PatchEnableSuppressAllTargetBrackets); PatchIfEnabled(typeof(EchelonZoneRestrictions), base.Config.PatchEnableEchelonZoneRestrictions); PatchIfEnabled(typeof(ExtendedDecorCarryDistance), base.Config.PatchEnableExtendDecorPlacement); PatchIfEnabled(typeof(PlaceInAshtray), base.Config.PatchEnablePlaceCigaretteButtInAshtray); PatchIfEnabled(typeof(FixWokRotation), base.Config.PatchEnableFixWokRotation); PatchIfEnabled(typeof(PassTimeRequiresWatch), base.Config.PatchExtraEnablePassTimeRequiresWatch); PatchIfEnabled(typeof(NoPauseCaseBoard), base.Config.PatchEnableNoPauseCaseBoard); ManualLogSource log = PluginController.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(20, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Plugin "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted("Sclamy.OutOfThePast"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" v"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted("0.6.2"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is loaded!"); } log.LogInfo(val); } private void PatchIfEnabled(Type patchType, bool enabled) { if (enabled) { base.Harmony.CreateClassProcessor(patchType).Patch(); Type[] nestedTypes = patchType.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic); foreach (Type type in nestedTypes) { base.Harmony.CreateClassProcessor(type).Patch(); } } } } public static class MyPluginInfo { public const string PLUGIN_GUID = "OutOfThePast"; public const string PLUGIN_NAME = "My first plugin"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace OutOfThePast.Patches.UIPatches { [HarmonyPatch(typeof(InputController), "Update")] internal static class NoPauseCaseBoard { [HarmonyPatch(typeof(InterfaceController), "SetDesktopMode")] internal static class DisableMovementInDesktopMode { private static bool shouldRestoreMovement; [HarmonyPostfix] private static void Postfix(bool val) { if (((PluginController)PluginController.Instance).Config.PatchEnableNoPauseCaseBoard) { if (val && SessionData.Instance.play) { shouldRestoreMovement = InteractionController.Instance.lockedInInteraction == null; Player.Instance.EnablePlayerMovement(false, true); } else if (shouldRestoreMovement) { Player.Instance.EnablePlayerMovement(true, true); shouldRestoreMovement = false; } } } } [HarmonyPatch(typeof(SessionData), "PauseGame")] internal static class SuppressPauseWithBoardOpen { [HarmonyPrefix] private static bool Prefix() { if (!((PluginController)PluginController.Instance).Config.PatchEnableNoPauseCaseBoard) { return true; } if (InterfaceController.Instance.desktopMode && SessionData.Instance.play && !SessionData.Instance.isDecorEdit) { return false; } return true; } } [HarmonyPatch(typeof(BioScreenController), "SetInventoryOpen")] internal static class CloseBoardForInventory { [HarmonyPrefix] private static void Prefix(BioScreenController __instance, bool val) { if (((PluginController)PluginController.Instance).Config.PatchEnableNoPauseCaseBoard && val && !__instance.isOpen && InterfaceController.Instance.desktopMode) { InterfaceController.Instance.SetDesktopMode(false, true); } } } [HarmonyPatch(typeof(MainMenuController), "EnableMainMenu")] internal static class ResumeOnMenuClose { [HarmonyPostfix] private static void Postfix(bool val) { if (((PluginController)PluginController.Instance).Config.PatchEnableNoPauseCaseBoard && !val) { SessionData instance = SessionData.Instance; if (instance.startedGame && !instance.play && instance.enableUserPause && !instance.isFloorEdit && !instance.isCityEdit) { instance.ResumeGame(); } } } } [HarmonyPatch(typeof(InterfaceController), "ToggleNotebook")] internal static class OpenBoardWithNotebook { [HarmonyPostfix] private static void Postfix(InterfaceController __instance) { if (((PluginController)PluginController.Instance).Config.PatchEnableNoPauseCaseBoard && !__instance.desktopMode && SessionData.Instance.play && IsNotebookOpen(__instance)) { __instance.SetDesktopMode(true, true); } } private static bool IsNotebookOpen(InterfaceController ic) { List activeWindows = ic.activeWindows; if (activeWindows == null) { return false; } for (int i = 0; i < activeWindows.Count; i++) { InfoWindow val = activeWindows[i]; if ((Object)(object)val != (Object)null && (SoCustomComparison)(object)val.preset != (SoCustomComparison)null && ((Object)val.preset).name == "DetectivesNotebook") { return true; } } return false; } } [HarmonyPatch] internal static class ReleasePopupPauseOwnership { [HarmonyPostfix] [HarmonyPatch(typeof(PopupMessageController), "PopupMessage")] private static void PopupMessagePostfix(PopupMessageController __instance) { Release(__instance); } [HarmonyPostfix] [HarmonyPatch(typeof(PopupMessageController), "TutorialMessage")] private static void TutorialMessagePostfix(PopupMessageController __instance) { Release(__instance); } private static void Release(PopupMessageController popup) { if (((PluginController)PluginController.Instance).Config.PatchEnableNoPauseCaseBoard && InterfaceController.Instance.desktopMode && SessionData.Instance.play) { popup.affectPauseState = false; } } } private static bool wasAutoTraveling; private static bool didOverride; [HarmonyPrefix] private static bool Prefix(InputController __instance) { didOverride = false; if (!((PluginController)PluginController.Instance).Config.PatchEnableNoPauseCaseBoard) { return true; } if (__instance.player == null) { return true; } if ((Object)(object)InterfaceController.Instance == (Object)null || (Object)(object)SessionData.Instance == (Object)null) { return true; } if (__instance.player.GetButtonDown("Menu") && InterfaceController.Instance.desktopMode && SessionData.Instance.play && (Object)(object)PopupMessageController.Instance != (Object)null && !PopupMessageController.Instance.active && (Object)(object)MainMenuController.Instance != (Object)null && !MainMenuController.Instance.mainMenuActive && (Object)(object)CutSceneController.Instance != (Object)null && !CutSceneController.Instance.cutSceneActive) { InterfaceController.Instance.SetDesktopMode(false, true); return false; } if (__instance.player.GetButtonDown("CaseBoard") && BioScreenController.Instance.isOpen) { BioScreenController.Instance.SetInventoryOpen(false, true, true); InterfaceController.Instance.SetDesktopMode(true, true); return false; } if (__instance.player.GetButtonDown("CaseBoard") || __instance.player.GetButtonDown("Notebook")) { wasAutoTraveling = Player.Instance.autoTravelActive; Player.Instance.autoTravelActive = true; didOverride = true; } return true; } [HarmonyPostfix] private static void Postfix() { if (didOverride) { Player.Instance.autoTravelActive = wasAutoTraveling; didOverride = false; } if (((PluginController)PluginController.Instance).Config.PatchEnableNoPauseCaseBoard && !((Object)(object)InterfaceController.Instance == (Object)null) && !((Object)(object)SessionData.Instance == (Object)null) && InterfaceController.Instance.desktopMode && SessionData.Instance.play) { SessionData.Instance.autoPauseTimer = 0f; } } } internal static class SuppressAllTargetBrackets { [HarmonyPatch(typeof(ControlDisplayController), "SetControlText")] internal static class SuppressAllBrackets { [HarmonyPrefix] private static void Prefix(ref bool useContext) { useContext = false; } } } } namespace OutOfThePast.Patches.SideJobPatches { [HarmonyPatch(typeof(SideJob), "ObjectiveStateLoop")] internal static class AdjustPayphoneCallDelay { [HarmonyPrefix] private static void Prefix(SideJob __instance, ref float __state) { __state = __instance.gooseChaseCallTime; } [HarmonyPostfix] private static void Postfix(SideJob __instance, float __state) { if (__instance.gooseChaseCallTime != __state) { float num = ((PluginController)PluginController.Instance).Config.PayphoneCallDelayMinimumDelay; float num2 = ((PluginController)PluginController.Instance).Config.PayphoneCallDelayMaximumDelay; float num3 = Random.Range(num, num2); __instance.gooseChaseCallTime = SessionData.Instance.gameTime + num3 / 60f; } } } } namespace OutOfThePast.Patches.InteractionPatches { internal static class PassTimeRequiresWatch { [HarmonyPatch(typeof(Interactable), "UpdateCurrentActions")] internal static class SuppressPassTimeActions { [HarmonyPostfix] private static void Postfix(Interactable __instance) { if (((PluginController)PluginController.Instance).Config.PatchExtraEnablePassTimeRequiresWatch) { InteractionController instance = InteractionController.Instance; if (!((Object)(object)instance == (Object)null) && ((instance.lockedInInteraction != null && __instance == instance.lockedInInteraction) || (instance.hideInteractable != null && __instance == instance.hideInteractable)) && !IsWatchDrawn()) { DisablePassTimeActions(__instance); } } } } [HarmonyPatch(typeof(BioScreenController), "SelectSlot")] internal static class RefreshActionsOnSlotChange { [HarmonyPostfix] private static void Postfix() { if (((PluginController)PluginController.Instance).Config.PatchExtraEnablePassTimeRequiresWatch) { InteractionController instance = InteractionController.Instance; if (!((Object)(object)instance == (Object)null) && instance.lockedInInteraction != null) { instance.lockedInInteraction.UpdateCurrentActions(); instance.UpdateInteractionText(); } } } } private static bool IsWatchDrawn() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 BioScreenController instance = BioScreenController.Instance; if ((Object)(object)instance == (Object)null) { return false; } InventorySlot selectedSlot = instance.selectedSlot; if (selectedSlot == null) { return false; } return (int)selectedSlot.isStatic == 2; } private static void DisablePassTimeActions(Interactable target) { Enumerator enumerator = target.currentActions.GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair current = enumerator.Current; InteractionAction currentAction = current.Value.currentAction; if (currentAction == null) { continue; } AIActionPreset action = currentAction.action; if (!((SoCustomComparison)(object)action == (SoCustomComparison)null)) { string presetName = ((SoCustomComparison)action).presetName; if (presetName == "PassTime" || presetName == "ActivateTimePass") { current.Value.enabled = false; } } } } } } namespace OutOfThePast.Patches.EchelonPatches { internal static class EchelonZoneRestrictions { [HarmonyPatch(typeof(ApartmentSalesController), "OnPurchaseButton")] internal static class BlockEchelonApartmentPurchase { [HarmonyPrefix] private static bool Prefix(ApartmentSalesController __instance) { if (GameplayController.Instance.money < ((NewGameLocation)__instance.parentWindow.passedInteractable.forSale).GetPrice(false)) { return true; } int num = Mathf.RoundToInt(UpgradeEffectController.Instance.GetUpgradeEffect((Effect)59)); if (!Game.Instance.allowSocialCreditPerks) { num = 1; } if ((Object)(object)ChapterController.Instance != (Object)null && (Object)(object)ChapterController.Instance.chapterScript != (Object)null && !Game.Instance.sandboxMode) { Chapter chapterScript = ChapterController.Instance.chapterScript; ChapterIntro val = (ChapterIntro)(object)((chapterScript is ChapterIntro) ? chapterScript : null); if ((Object)(object)val != (Object)null && !val.completed) { num = -1; } } if (num <= 0) { return true; } InfoWindow parentWindow = __instance.parentWindow; object obj; if (parentWindow == null) { obj = null; } else { Interactable passedInteractable = parentWindow.passedInteractable; obj = ((passedInteractable != null) ? passedInteractable.forSale : null); } NewAddress val2 = (NewAddress)obj; if ((Object)(object)val2 == (Object)null) { return true; } if (!IsEchelonRestricted(((NewGameLocation)val2).thisAsAddress)) { return true; } PopupMessageController.Instance.PopupMessage("LevelUpBeforeApartment", true, false, "Confirm", "", true, (AffectPauseState)0, false, "", false, false, false, false, "", "", false, "", false, "", "You must level up your social credit before you are allowed to purchase an apartment in an Echelon Zone...", false); return false; } } [HarmonyPatch(typeof(SideJob), "PostJob")] internal static class PreventEchelonJobPosting { [HarmonyPrefix] private static bool Prefix(SideJob __instance) { if ((Object)(object)__instance.poster == (Object)null) { return true; } if (!IsEchelonRestricted(__instance.poster.home)) { return true; } pendingCancelJobId = __instance.jobID; return false; } } [HarmonyPatch(typeof(SideJobController), "JobCreationCheck")] internal static class CleanupBlockedEchelonJob { [HarmonyPostfix] private static void Postfix() { if (pendingCancelJobId >= 0) { if (SideJobController.Instance.allJobsDictionary.ContainsKey(pendingCancelJobId)) { SideJob val = SideJobController.Instance.allJobsDictionary[pendingCancelJobId]; val.SetJobState((JobState)2, false); } pendingCancelJobId = -1; } } } private static int pendingCancelJobId = -1; private static bool IsEchelonRestricted(NewAddress address) { return Game.Instance.allowEchelons && (Object)(object)address != (Object)null && (Object)(object)((NewGameLocation)address).floor != (Object)null && ((NewGameLocation)address).floor.isEchelons && (double)UpgradeEffectController.Instance.GetUpgradeEffect((Effect)68) <= 0.0; } } } namespace OutOfThePast.Patches.DialoguePatches { internal static class SitAndTalk { [HarmonyPatch(typeof(Interactable), "UpdateCurrentActions")] internal static class PrioritizeTalkWhileSitting { [HarmonyPostfix] private static void Postfix(Interactable __instance) { //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Invalid comparison between Unknown and I4 //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Invalid comparison between Unknown and I4 //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Invalid comparison between Unknown and I4 //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) if (__instance == null) { return; } InteractionController instance = InteractionController.Instance; Player instance2 = Player.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null || instance.lockedInInteraction == null || instance.lockedInInteraction.usagePoint == null || __instance == instance.lockedInInteraction || (Object)(object)__instance.isActor == (Object)null || __instance.isActor.isDead || __instance.isActor.isAsleep || __instance.isActor.isStunned || (Object)(object)__instance.isActor.ai == (Object)null || __instance.isActor.ai.ko) { return; } InteractionKey val = (InteractionKey)0; Enumerator enumerator = __instance.currentActions.GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair current = enumerator.Current; InteractionAction currentAction = current.Value.currentAction; object obj; if (currentAction == null) { obj = null; } else { AIActionPreset action = currentAction.action; obj = ((action != null) ? ((SoCustomComparison)action).presetName : null); } if ((string?)obj == "TalkTo") { val = current.Key; break; } } if ((int)val == 0) { return; } InteractableCurrentAction val2 = __instance.currentActions[val]; if (val2 == null) { return; } val2.enabled = true; val2.display = true; InteractionKey val3 = (InteractionKey)0; Enumerator enumerator2 = __instance.currentActions.GetEnumerator(); while (enumerator2.MoveNext()) { KeyValuePair current2 = enumerator2.Current; InteractionAction currentAction2 = current2.Value.currentAction; object obj2; if (currentAction2 == null) { obj2 = null; } else { AIActionPreset action2 = currentAction2.action; obj2 = ((action2 != null) ? ((SoCustomComparison)action2).presetName : null); } if ((string?)obj2 == "Inspect") { val3 = current2.Key; break; } } if ((int)val3 > 0) { InteractableCurrentAction val4 = __instance.currentActions[val3]; if (val4 != null) { val4.enabled = true; val4.display = true; } } InteractionKey val5 = (InteractionKey)1; InteractionKey val6 = (InteractionKey)2; __instance.currentActions[val5] = val2; if ((int)val3 > 0) { __instance.currentActions[val6] = __instance.currentActions[val3]; } } } [HarmonyPatch(typeof(NewAIController), "TalkTo", new Type[] { typeof(ConversationType) })] internal static class PreserveSittingDuringTalk { [HarmonyPrefix] private static void Prefix(NewAIController __instance, ConversationType convoType) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (AnyProtectionActive) { LogDebug("[SitAndTalk] TalkTo.Prefix clearing previous state (" + StateString + ")"); ClearState(); } InteractionController instance = InteractionController.Instance; if (instance.lockedInInteraction != null && instance.lockedInInteraction.usagePoint != null) { LogDebug($"[SitAndTalk] Entering sit-and-talk mode (convoType={convoType}, chair={instance.lockedInInteraction.name}, NPC={((Object)__instance).name})"); LogStateSnapshot("BEFORE sit-and-talk"); storedSittingInteractable = instance.lockedInInteraction; isSitAndTalkActive = true; } } [HarmonyPostfix] private static void Postfix(NewAIController __instance, ConversationType convoType) { if (!IsStoredChairValid()) { if (storedSittingInteractable != null) { ClearState(); } } else if (isSitAndTalkActive && storedSittingInteractable != null) { LogDebug("[SitAndTalk] TalkTo.Postfix - restoring sitting state (" + StateString + ")"); ((Actor)Player.Instance).SetInteracting(storedSittingInteractable); if (storedSittingInteractable.usagePoint != null) { storedSittingInteractable.usagePoint.TrySetUser((UsePointSlot)0, (Human)(object)Player.Instance, ""); } } } } [HarmonyPatch(typeof(UsagePoint), "TrySetUser")] internal static class PreventUsagePointClear { [HarmonyPrefix] private static bool Prefix(UsagePoint __instance, Human newUser) { if (!IsStoredChairValid()) { if (storedSittingInteractable != null) { ClearState(); } return true; } if ((AnyProtectionActive || ((Object)(object)InteractionController.Instance != (Object)null && InteractionController.Instance.lockedInInteraction == storedSittingInteractable)) && (Object)(object)newUser == (Object)null && storedSittingInteractable.usagePoint == __instance) { return false; } return true; } } [HarmonyPatch(typeof(ActionController), "Return")] internal static class AllowUserInitiatedReturn { [HarmonyPrefix] private static void Prefix() { if (sittingRestored) { LogDebug("[SitAndTalk] ActionController.Return - setting userInitiatedReturn"); userInitiatedReturn = true; } } } [HarmonyPatch(typeof(ActionController), "PullPlayerFromHidingPlace")] internal static class AllowPullFromHiding { [HarmonyPrefix] private static void Prefix() { if (sittingRestored) { LogDebug("[SitAndTalk] PullPlayerFromHidingPlace - setting userInitiatedReturn"); userInitiatedReturn = true; } } } [HarmonyPatch(typeof(InteractionController), "SetLockedInInteractionMode")] internal static class PreventClearingSitting { [HarmonyPrefix] private static bool Prefix(Interactable val, InteractionController __instance) { if (val == null && restorationFrame == Time.frameCount) { LogDebug("[SitAndTalk] Blocking post-restoration input bleed (same frame as restoration)"); return false; } if (!IsStoredChairValid()) { if (storedSittingInteractable != null) { ClearState(); } return true; } if (val != null && (Object)(object)val.isActor != (Object)null && isSitAndTalkActive && __instance.lockedInInteraction == storedSittingInteractable) { LogDebug("[SitAndTalk] Redirecting interacting to chair to prevent NPC clear"); ((Actor)Player.Instance).SetInteracting(storedSittingInteractable); } if (val == null && userInitiatedReturn && sittingRestored) { LogDebug("[SitAndTalk] User-initiated return, clearing state and allowing"); ClearState(); return true; } if (val == null && (pendingRestoration || isRestoringSitting || sittingRestored)) { LogDebug("[SitAndTalk] Blocking SetLockedIn(null) (" + StateString + ")"); return false; } return true; } [HarmonyPostfix] private static void Postfix(InteractionController __instance) { if (!IsStoredChairValid()) { if (storedSittingInteractable != null) { ClearState(); } } else if (isRestoringSitting && storedSittingInteractable != null) { if (__instance.lockedInInteraction == storedSittingInteractable) { LogDebug("[SitAndTalk] Deferred restoration succeeded, entering permanent protection (" + StateString + ")"); isRestoringSitting = false; sittingRestored = true; LogStateSnapshot("AFTER restoration (protected)"); } else { LogDebug("[SitAndTalk] WARNING: Deferred restoration write failed (" + StateString + ")"); LogStateSnapshot("FAILED deferred restoration"); ClearState(); } } } } [HarmonyPatch(typeof(InteractionController), "Update")] internal static class DeferredRestorationUpdate { [HarmonyPostfix] private static void Postfix(InteractionController __instance) { if (!pendingRestoration) { return; } if (!IsStoredChairValid()) { ClearState(); return; } LogDebug("[SitAndTalk] Performing deferred restoration (" + StateString + ")"); LogStateSnapshot("BEFORE deferred restoration"); pendingRestoration = false; isRestoringSitting = true; __instance.SetLockedInInteractionMode(storedSittingInteractable, 0, false); if (isRestoringSitting) { LogDebug("[SitAndTalk] DeferredRestoration - Postfix didn't finalize, cleaning up"); ClearState(); } } } [HarmonyPatch(typeof(Player), "TransformPlayerController")] internal static class SkipTransformWhileSitting { [HarmonyPrefix] private static bool Prefix(PlayerTransitionPreset newEnterTransition, Interactable newInteractable) { if (!AnyProtectionActive) { return true; } if (!IsStoredChairValid()) { ClearState(); return true; } if (isSitAndTalkActive) { InteractionController instance = InteractionController.Instance; if ((Object)(object)instance != (Object)null && instance.lockedInInteraction == null) { LogDebug("[SitAndTalk] Stale transform block detected, clearing (" + StateString + ")"); ClearState(); return true; } } LogDebug($"[SitAndTalk] Skipping TransformPlayerController (transition={((newEnterTransition != null) ? ((Object)newEnterTransition).name : null) ?? "null"}, interactable={((newInteractable != null) ? newInteractable.name : null) ?? "null"})"); return false; } } [HarmonyPatch(typeof(Player), "OnReturnFromHide")] internal static class BlockOnReturnFromHide { [HarmonyPrefix] private static bool Prefix() { if (!AnyProtectionActive) { return true; } if (!IsStoredChairValid()) { if (storedSittingInteractable != null) { ClearState(); } return true; } if (isSitAndTalkActive && !pendingRestoration && !isRestoringSitting && !sittingRestored) { InteractionController instance = InteractionController.Instance; if ((Object)(object)instance != (Object)null && instance.lockedInInteraction == null) { LogDebug("[SitAndTalk] Stale OnReturnFromHide block detected, clearing (" + StateString + ")"); ClearState(); return true; } } LogDebug("[SitAndTalk] Blocking OnReturnFromHide (" + StateString + ")"); return false; } } [HarmonyPatch(typeof(Player), "ReturnFromTransform")] internal static class PreventReturnFromTransform { [HarmonyPrefix] private static bool Prefix() { if (!AnyProtectionActive) { return true; } if (!IsStoredChairValid()) { if (storedSittingInteractable != null) { ClearState(); } return true; } LogDebug("[SitAndTalk] Blocking ReturnFromTransform (" + StateString + ")"); return false; } } [HarmonyPatch(typeof(InteractionController), "SetDialog")] internal static class RestoreSittingAfterDialogue { [HarmonyPostfix] private static void Postfix(bool val) { if (!IsStoredChairValid()) { if (storedSittingInteractable != null) { ClearState(); } } else if (!val && isSitAndTalkActive && storedSittingInteractable != null) { LogDebug("[SitAndTalk] Dialogue ended, deferring restoration to next frame (" + StateString + ")"); isSitAndTalkActive = false; pendingRestoration = true; } else if (val && isSitAndTalkActive) { LogDebug("[SitAndTalk] Dialogue opened (" + StateString + ")"); } } } private static bool isSitAndTalkActive = false; private static bool pendingRestoration = false; private static bool isRestoringSitting = false; private static bool sittingRestored = false; private static bool userInitiatedReturn = false; private static int restorationFrame = -1; private static Interactable storedSittingInteractable = null; private static bool Debug => ((PluginController)PluginController.Instance).Config.DebugSitAndTalk; private static string StateString => $"active={isSitAndTalkActive}, pending={pendingRestoration}, restoring={isRestoringSitting}, restored={sittingRestored}, chair={((storedSittingInteractable != null) ? storedSittingInteractable.name : "null")}"; private static bool AnyProtectionActive => isSitAndTalkActive || pendingRestoration || isRestoringSitting || sittingRestored; private static void LogDebug(string msg) { if (Debug) { PluginController.Log.LogInfo((object)msg); } } private static void LogStateSnapshot(string label) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Expected O, but got Unknown //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Expected O, but got Unknown //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Expected O, but got Unknown //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Expected O, but got Unknown //IL_0380: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Expected O, but got Unknown //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Expected O, but got Unknown if (!Debug) { return; } InteractionController instance = InteractionController.Instance; Player instance2 = Player.Instance; Interactable val = ((instance != null) ? instance.lockedInInteraction : null); ManualLogSource log = PluginController.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(21, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[SitAndTalk] === "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(label); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ==="); } log.LogInfo(val2); ManualLogSource log2 = PluginController.Log; val2 = new BepInExInfoLogInterpolatedStringHandler(28, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" lockedInInteraction="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(((val != null) ? val.name : null) ?? "null"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", ref="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted((instance != null) ? new int?(instance.lockedInInteractionRef) : ((int?)null)); } log2.LogInfo(val2); ManualLogSource log3 = PluginController.Log; val2 = new BepInExInfoLogInterpolatedStringHandler(23, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" hideInteractable(IC)="); BepInExInfoLogInterpolatedStringHandler obj = val2; object obj2; if (instance == null) { obj2 = null; } else { Interactable hideInteractable = instance.hideInteractable; obj2 = ((hideInteractable != null) ? hideInteractable.name : null); } if (obj2 == null) { obj2 = "null"; } ((BepInExLogInterpolatedStringHandler)obj).AppendFormatted((string)obj2); } log3.LogInfo(val2); ManualLogSource log4 = PluginController.Log; val2 = new BepInExInfoLogInterpolatedStringHandler(37, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" hideInteractable(Player)="); BepInExInfoLogInterpolatedStringHandler obj3 = val2; object obj4; if (instance2 == null) { obj4 = null; } else { Interactable hideInteractable2 = instance2.hideInteractable; obj4 = ((hideInteractable2 != null) ? hideInteractable2.name : null); } if (obj4 == null) { obj4 = "null"; } ((BepInExLogInterpolatedStringHandler)obj3).AppendFormatted((string)obj4); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", hideRef="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted((instance2 != null) ? new int?(instance2.hideReference) : ((int?)null)); } log4.LogInfo(val2); ManualLogSource log5 = PluginController.Log; val2 = new BepInExInfoLogInterpolatedStringHandler(18, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" interactingWith="); BepInExInfoLogInterpolatedStringHandler obj5 = val2; object obj6; if (instance2 == null) { obj6 = null; } else { Interactable interactingWith = ((Actor)instance2).interactingWith; obj6 = ((interactingWith != null) ? interactingWith.name : null); } if (obj6 == null) { obj6 = "null"; } ((BepInExLogInterpolatedStringHandler)obj5).AppendFormatted((string)obj6); } log5.LogInfo(val2); ManualLogSource log6 = PluginController.Log; val2 = new BepInExInfoLogInterpolatedStringHandler(30, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" isHiding="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted((instance2 != null) ? new bool?(((Actor)instance2).isHiding) : ((bool?)null)); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", transitionActive="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted((instance2 != null) ? new bool?(instance2.transitionActive) : ((bool?)null)); } log6.LogInfo(val2); ManualLogSource log7 = PluginController.Log; val2 = new BepInExInfoLogInterpolatedStringHandler(17, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" exitTransition="); BepInExInfoLogInterpolatedStringHandler obj7 = val2; object obj8; if (instance2 == null) { obj8 = null; } else { PlayerTransitionPreset exitTransition = instance2.exitTransition; obj8 = ((exitTransition != null) ? ((Object)exitTransition).name : null); } if (obj8 == null) { obj8 = "null"; } ((BepInExLogInterpolatedStringHandler)obj7).AppendFormatted((string)obj8); } log7.LogInfo(val2); if (val != null && val.usagePoint != null) { Human val3 = null; val.usagePoint.users?.TryGetValue((UsePointSlot)0, ref val3); ManualLogSource log8 = PluginController.Log; val2 = new BepInExInfoLogInterpolatedStringHandler(25, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" usagePoint.defaultUser="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(((val3 != null) ? ((Object)val3).name : null) ?? "null"); } log8.LogInfo(val2); } ManualLogSource log9 = PluginController.Log; val2 = new BepInExInfoLogInterpolatedStringHandler(29, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" OnReturnFromLockedIn null?="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted((Delegate)(object)((instance != null) ? instance.OnReturnFromLockedIn : null) == (Delegate)null); } log9.LogInfo(val2); } private static bool IsStoredChairValid() { if (storedSittingInteractable == null) { return false; } if (storedSittingInteractable.usagePoint == null) { return false; } return true; } private static void ClearState() { LogDebug("[SitAndTalk] ClearState called (" + StateString + ")"); storedSittingInteractable = null; isSitAndTalkActive = false; pendingRestoration = false; isRestoringSitting = false; sittingRestored = false; userInitiatedReturn = false; restorationFrame = Time.frameCount; } } } namespace OutOfThePast.Patches.DecorPatches { internal static class ExtendedDecorCarryDistance { [HarmonyPatch(typeof(InteractableController), "Update")] internal static class PatchUpdate { [HarmonyPrefix] private static void Prefix(InteractableController __instance) { if (__instance.isCarriedByPlayer && !__instance.interactable.preset.isInventoryItem) { originalCarryDistance = GameplayControls.Instance.carryDistance; GameplayControls.Instance.carryDistance = ((PluginController)PluginController.Instance).Config.DecorPlaceDistance; isActive = true; isDecorCarry = true; } } [HarmonyPostfix] private static void Postfix(InteractableController __instance) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 if (isActive) { isActive = false; GameplayControls.Instance.carryDistance = originalCarryDistance; if ((int)__instance.interactable.preset.apartmentPlacementMode <= 0) { CorrectSurfaceClipping(__instance); } } } } [HarmonyPatch(typeof(InteractableController), "DropThis")] internal static class PatchDropThis { [HarmonyPrefix] private static void Prefix(InteractableController __instance) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 if (isDecorCarry) { isDecorCarry = false; if ((int)__instance.interactable.preset.apartmentPlacementMode <= 0) { CorrectSurfaceClipping(__instance); FixNonConvexMeshColliders(__instance); } } } } private static float originalCarryDistance; private static bool isActive; private static bool isDecorCarry; private static void FixNonConvexMeshColliders(InteractableController ic) { GameObject val = (((Object)(object)ic.alternativePhysicsParent != (Object)null) ? ((Component)ic.alternativePhysicsParent).gameObject : ((Component)ic).gameObject); foreach (MeshCollider componentsInChild in val.GetComponentsInChildren()) { if (!componentsInChild.convex) { componentsInChild.convex = true; } } } private static void CorrectSurfaceClipping(InteractableController ic) { //IL_0039: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: 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_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)Player.Instance.cam).transform; bool flag = (Object)(object)ic.alternativePhysicsParent != (Object)null; Vector3 val = (flag ? ((Component)ic.alternativePhysicsParent).transform.position : ((Component)ic).transform.position); Vector3 val2 = val - transform.position; float magnitude = ((Vector3)(ref val2)).magnitude; if (magnitude < 0.01f) { return; } Vector3 val3 = val2 / magnitude; Transform val4 = (flag ? ic.alternativePhysicsParent : ((Component)ic).transform); int heldObjectsObjectsLayerMask = Toolbox.Instance.heldObjectsObjectsLayerMask; RaycastHit val5 = default(RaycastHit); if (!Physics.Raycast(transform.position, val3, ref val5, magnitude, heldObjectsObjectsLayerMask)) { return; } float num = ((RaycastHit)(ref val5)).distance; if (((RaycastHit)(ref val5)).transform.IsChildOf(val4)) { float num2 = ((RaycastHit)(ref val5)).distance + 0.01f; if (num2 >= magnitude || !Physics.Raycast(transform.position + val3 * num2, val3, ref val5, magnitude - num2, heldObjectsObjectsLayerMask) || ((RaycastHit)(ref val5)).transform.IsChildOf(val4)) { return; } num = num2 + ((RaycastHit)(ref val5)).distance; } float num3 = 0.25f; if (ic.meshes.Count > 0) { Bounds bounds = ((Renderer)ic.meshes[0]).bounds; Vector3 center = ((Bounds)(ref bounds)).center; bounds = ((Renderer)ic.meshes[0]).bounds; num3 = Vector3.Distance(center, ((Bounds)(ref bounds)).ClosestPoint(transform.position)); } float num4 = magnitude - num + num3; float num5 = num3 + 0.1f; float num6 = Mathf.Max(0f, magnitude - num5); num4 = Mathf.Min(num4, num6); if (!(num4 <= 0f)) { Vector3 position = val - val3 * num4; if (flag) { ((Component)ic.alternativePhysicsParent).transform.position = position; } else { ((Component)ic).transform.position = position; } } } } internal static class FixWokRotation { [HarmonyPatch(typeof(InteractableController), "Update")] internal static class PatchUpdate { [HarmonyPrefix] private static void Prefix(InteractableController __instance) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) if (__instance.isCarriedByPlayer && __instance.setHeldEuler && ((Object)__instance.interactable.preset).name.Equals("Wok")) { PhysicsProfile physicsProfile = __instance.interactable.preset.GetPhysicsProfile(); if (!((SoCustomComparison)(object)physicsProfile == (SoCustomComparison)null)) { __instance.heldEuler = new Vector3(physicsProfile.heldEuler.x + 180f, __instance.heldEuler.y, __instance.heldEuler.z); } } } } } internal static class PlaceInAshtray { [HarmonyPatch(typeof(FirstPersonItemController), "UpdateCurrentActions")] internal static class PatchUpdateCurrentActions { [HarmonyPostfix] private static void Postfix(FirstPersonItemController __instance) { //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Invalid comparison between Unknown and I4 //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) if ((SoCustomComparison)(object)__instance.drawnItem == (SoCustomComparison)null || !__instance.finishedDrawingItem || __instance.isConsuming) { return; } InventorySlot selectedSlot = BioScreenController.Instance.selectedSlot; if (selectedSlot == null || selectedSlot.interactableID <= -1) { return; } Interactable interactable = selectedSlot.GetInteractable(); if (interactable == null || !((Object)interactable.preset).name.ToLower().Contains("cigaretteend") || !InteractionController.Instance.lookingAtInteractable) { return; } InteractableController currentLookingAtInteractable = InteractionController.Instance.currentLookingAtInteractable; if ((Object)(object)currentLookingAtInteractable == (Object)null || currentLookingAtInteractable.interactable == null || !((Object)currentLookingAtInteractable.interactable.preset).name.ToLower().Contains("ashtray")) { return; } FPSInteractionAction val = null; Enumerator enumerator = __instance.drawnItem.actions.GetEnumerator(); while (enumerator.MoveNext()) { FPSInteractionAction current = enumerator.Current; if ((int)current.availability == 7) { val = current; break; } } if (val == null) { return; } InteractionKey interactionKey = ((InteractionAction)val).GetInteractionKey(); if (__instance.currentActions.ContainsKey(interactionKey)) { InteractableCurrentAction val2 = __instance.currentActions[interactionKey]; if (val2.enabled) { val2.currentAction = (InteractionAction)(object)val; } } } } } } namespace OutOfThePast.Patches.BugFixPatches { internal static class PassTimeImprovements { [HarmonyPatch(typeof(Player), "OnHide")] internal static class SuppressOnHide { [HarmonyPrefix] private static bool Prefix() { if (suppressOnHide) { return false; } return true; } } [HarmonyPatch(typeof(ActionController), "PassTime")] internal static class PassTimeNoJolt { [HarmonyPrefix] private static void Prefix() { InteractionController instance = InteractionController.Instance; Interactable val = ((instance != null) ? instance.lockedInInteraction : null); if (val != null) { suppressOnHide = true; pendingRef = 1; } } [HarmonyPostfix] private static void Postfix() { if (suppressOnHide) { ApplyPendingRef(); } } } [HarmonyPatch(typeof(ActionController), "ActivateTimePass")] internal static class ActivateTimePassNoJolt { [HarmonyPrefix] private static void Prefix() { InteractionController instance = InteractionController.Instance; Interactable val = ((instance != null) ? instance.lockedInInteraction : null); if (val != null) { suppressOnHide = true; pendingRef = 0; } } [HarmonyPostfix] private static void Postfix() { if (suppressOnHide) { ApplyPendingRef(); } } } [HarmonyPatch(typeof(ActionController), "CancelPassTime")] internal static class CancelPassTimeNoJolt { [HarmonyPrefix] private static void Prefix() { InteractionController instance = InteractionController.Instance; Interactable val = ((instance != null) ? instance.lockedInInteraction : null); if (val != null) { suppressOnHide = true; pendingRef = 0; } } [HarmonyPostfix] private static void Postfix() { if (suppressOnHide) { Player.Instance.SetSettingAlarmMode(false); Player.Instance.setAlarmModeAfterDelay = 0f; ApplyPendingRef(); } } } [HarmonyPatch(typeof(BioScreenController), "SelectSlot")] internal static class CancelAlarmOnItemSwitch { [HarmonyPostfix] private static void Postfix() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 InventorySlot selectedSlot = BioScreenController.Instance.selectedSlot; if (selectedSlot == null || (int)selectedSlot.isStatic == 2) { return; } Player instance = Player.Instance; if (instance.setAlarmMode || instance.setAlarmModeAfterDelay > 0f) { instance.SetSettingAlarmMode(false); instance.setAlarmModeAfterDelay = 0f; InteractionController instance2 = InteractionController.Instance; if (((instance2 != null) ? instance2.lockedInInteraction : null) != null) { instance2.lockedInInteractionRef = 0; instance.hideReference = 0; instance2.lockedInInteraction.UpdateCurrentActions(); instance2.UpdateInteractionText(); } } } } private static bool suppressOnHide = false; private static int pendingRef = -1; private static void ApplyPendingRef() { InteractionController instance = InteractionController.Instance; instance.lockedInInteractionRef = pendingRef; Player.Instance.hideReference = pendingRef; if (instance.lockedInInteraction != null) { instance.lockedInInteraction.UpdateCurrentActions(); instance.UpdateInteractionText(); } suppressOnHide = false; pendingRef = -1; } } }