Decompiled source of SkipTimeAnywhere v1.0.0

plugins/SkipTimeAnywhere/SkipTimeAnywhere.dll

Decompiled 6 hours ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("SoDQuickRest")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.11.1.0")]
[assembly: AssemblyInformationalVersion("0.11.1")]
[assembly: AssemblyProduct("SoDQuickRest")]
[assembly: AssemblyTitle("SoDQuickRest")]
[assembly: AssemblyVersion("0.11.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[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 SoDQuickRest
{
	[BepInPlugin("sm3gm.sod.skiptimeanywhere", "Skip Time Anywhere", "1.0.0")]
	public sealed class Plugin : BasePlugin
	{
		public const string VER = "1.0.0";

		internal static ManualLogSource L;

		internal static ConfigEntry<float> Speed;

		internal static ConfigEntry<float> SkipSpeed;

		internal static ConfigEntry<bool> BoostGameRest;

		internal static ConfigEntry<string> WatchKey;

		internal static ConfigEntry<string> FullSkipKey;

		internal static ConfigEntry<string> EarlierKey;

		internal static ConfigEntry<string> LaterKey;

		internal static ConfigEntry<bool> WakeOnPhone;

		internal static ConfigEntry<bool> WakeOnKnock;

		internal static ConfigEntry<bool> WakeOnMurder;

		internal static ConfigEntry<bool> WakeOnBodyFound;

		internal static ConfigEntry<float> WakeWhenColder;

		internal static ConfigEntry<float> WakeWhenHurt;

		internal static ConfigEntry<bool> ShowWatchHint;

		internal static ConfigEntry<bool> StandingMenu;

		internal static ConfigEntry<float> StandingMenuDelay;

		internal static ConfigEntry<bool> ReplaceHoursToggle;

		internal static ConfigEntry<string> PadAlarm;

		internal static ConfigEntry<string> PadHour;

		internal static ConfigEntry<string> PromptAlarmSlot;

		internal static ConfigEntry<string> PromptHourSlot;

		public override void Load()
		{
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Expected O, but got Unknown
			L = ((BasePlugin)this).Log;
			Speed = ((BasePlugin)this).Config.Bind<float>("Speed", "RestSpeed", 80f, "How many times faster than normal the clock runs while you wait or sleep. The game's own speed is 40.");
			SkipSpeed = ((BasePlugin)this).Config.Bind<float>("Speed", "SkipSpeed", 2000f, "Speed for Ctrl+Shift+Alt+R, the near-instant skip. The world still runs, just very fast, so wake-ups still work.");
			BoostGameRest = ((BasePlugin)this).Config.Bind<bool>("Speed", "BoostGameRest", true, "Also speed up the game's own sleeping and waiting in beds and chairs. Turn off if another mod already changes that.");
			WatchKey = ((BasePlugin)this).Config.Bind<string>("Keys", "SkipHourKey", "T", "With the watch held up, or while sitting or lying down to pass time: skip one hour. Unity key name, empty = off.");
			FullSkipKey = ((BasePlugin)this).Config.Bind<string>("Keys", "SkipToWatchTimeKey", "Y", "Skip straight to the time set on the watch. Unity key name, empty = off.");
			EarlierKey = ((BasePlugin)this).Config.Bind<string>("Keys", "WatchEarlierKey", "Comma", "With the watch held up: set the watch time 15 minutes earlier. Unity key name.");
			LaterKey = ((BasePlugin)this).Config.Bind<string>("Keys", "WatchLaterKey", "Period", "With the watch held up: set the watch time 15 minutes later. Unity key name.");
			WakeOnPhone = ((BasePlugin)this).Config.Bind<bool>("Wake", "PhoneRings", true, "Wake when a phone rings where you are.");
			WakeOnKnock = ((BasePlugin)this).Config.Bind<bool>("Wake", "DoorKnock", true, "Wake when someone knocks on a door near you.");
			WakeOnMurder = ((BasePlugin)this).Config.Bind<bool>("Wake", "Murder", true, "Wake when a murder happens.");
			WakeOnBodyFound = ((BasePlugin)this).Config.Bind<bool>("Wake", "BodyFound", true, "Wake when a body is found.");
			PromptAlarmSlot = ((BasePlugin)this).Config.Bind<string>("Prompts", "AlarmPromptButton", "crouch", "Game button slot for the Skip To Alarm prompt while time passes (game names such as flashlight, crouch, alternative). The prompt shows the real key or controller button. Empty = the alarm menu's own button.");
			PromptHourSlot = ((BasePlugin)this).Config.Bind<string>("Prompts", "HourPromptButton", "", "Game button slot for the Skip One Hour prompt while time passes. Empty = the alarm menu's own button.");
			PadAlarm = ((BasePlugin)this).Config.Bind<string>("Controller", "SkipToAlarmPadButton", "JoystickButton1", "Controller button that skips to the alarm while time passes (JoystickButton1 = B on an Xbox pad, the button the prompt shows). Empty = off.");
			PadHour = ((BasePlugin)this).Config.Bind<string>("Controller", "SkipHourButton", "", "Controller button that skips one hour while time passes (JoystickButton2 = X on an Xbox pad). Empty = off.");
			ReplaceHoursToggle = ((BasePlugin)this).Config.Bind<bool>("Watch", "SkipToAlarmPrompt", true, "In the pass-time menu (standing, chairs, beds), the Switch Hours/Minutes prompt becomes Skip To Alarm. Alarm Forward/Back still step the alarm.");
			StandingMenu = ((BasePlugin)this).Config.Bind<bool>("Watch", "StandingMenu", true, "Look at your watch and hold still to get the game's own pass-time menu while standing.");
			StandingMenuDelay = ((BasePlugin)this).Config.Bind<float>("Watch", "StandingMenuDelay", 1.5f, "Seconds of holding still with the watch raised before the menu opens.");
			ShowWatchHint = ((BasePlugin)this).Config.Bind<bool>("Keys", "ShowWatchHint", true, "Show the pass time keys each time you raise the watch.");
			WakeWhenColder = ((BasePlugin)this).Config.Bind<float>("Wake", "ColdBelow", 0.15f, "Wake when your warmth drops to this or lower (0 = freezing, 1 = warm) and is still dropping, so you do not freeze to death outside. Warming up somewhere warm never wakes you. 0 = off.");
			WakeWhenHurt = ((BasePlugin)this).Config.Bind<float>("Wake", "HealthBelow", 0.5f, "Wake when your health drops to this share of the maximum or lower. 0 = off.");
			Harmony val = new Harmony("sm3gm.sod.skiptimeanywhere");
			val.PatchAll(typeof(PromptText));
			val.PatchAll(typeof(Patches));
			val.PatchAll(typeof(StandMenuPatches));
			val.PatchAll(typeof(SkipPromptPatches));
			val.PatchAll(typeof(SkipButtonPatches));
			((BasePlugin)this).AddComponent<Keeper>();
			ManualLogSource l = L;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(26, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Skip Time Anywhere ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("1.0.0");
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" loaded");
			}
			l.LogInfo(val2);
		}
	}
	internal static class Rest
	{
		internal static Interactable? Spot;

		internal static bool Own;

		internal static float HoursLeft;

		internal static float OwnSpeed;

		internal static float LastClock = -1f;

		private static float lastSkipPress = -1f;

		internal static bool GameResting
		{
			get
			{
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Invalid comparison between Unknown and I4
				try
				{
					return (Object)(object)Player.Instance != (Object)null && Player.Instance.spendingTimeMode && (int)SessionData.Instance.currentTimeSpeed == 3;
				}
				catch
				{
					return false;
				}
			}
		}

		internal static bool Resting
		{
			get
			{
				if (!Own)
				{
					return GameResting;
				}
				return true;
			}
		}

		internal static float Clock => SessionData.Instance.decimalClock;

		internal static void StartOrExtend(bool skip)
		{
			if (!Own)
			{
				Own = true;
				HoursLeft = 0f;
				LastClock = Clock;
				try
				{
					SessionData.Instance.SetTimeSpeed((TimeSpeed)3);
				}
				catch
				{
				}
			}
			HoursLeft = Math.Min(HoursLeft + 1f, 24f);
			OwnSpeed = (skip ? Plugin.SkipSpeed.Value : Plugin.Speed.Value);
			Note((skip ? "Skipping" : "Waiting") + " until " + Fmt(Clock + HoursLeft) + ". Press again for another hour, Esc or move to stop.");
		}

		internal static float AlarmHoursAhead()
		{
			try
			{
				float alarm = Player.Instance.alarm;
				float clock = Clock;
				if (alarm <= 0f)
				{
					return -1f;
				}
				float num = alarm % 24f - clock;
				if (num < 0f)
				{
					num += 24f;
				}
				return num;
			}
			catch
			{
				return -1f;
			}
		}

		internal static void Skip(float hours, string what)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			if (!Own)
			{
				Own = true;
				LastClock = Clock;
				try
				{
					SessionData.Instance.SetTimeSpeed((TimeSpeed)3);
				}
				catch
				{
				}
				HoursLeft = 0f;
			}
			HoursLeft = Math.Min(HoursLeft + hours, 24f);
			OwnSpeed = Plugin.SkipSpeed.Value;
			ManualLogSource l = Plugin.L;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(25, 3, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[REST] skip ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(hours, "0.00");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" h (");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(what);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("), until ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Fmt(Clock + HoursLeft));
			}
			l.LogInfo(val);
			Note("Skipping to " + Fmt(Clock + HoursLeft) + ".");
		}

		internal static void StopOwn(string why)
		{
			if (Own)
			{
				Own = false;
				try
				{
					SessionData.Instance.SetTimeSpeed((TimeSpeed)1);
				}
				catch
				{
				}
				if (why.Length > 0)
				{
					Note(why);
				}
			}
		}

		internal static void Wake(string why)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Invalid comparison between Unknown and I4
			if (!Resting)
			{
				return;
			}
			ManualLogSource l = Plugin.L;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(15, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[REST] waking: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(why);
			}
			l.LogInfo(val);
			bool own = Own;
			if (own)
			{
				StopOwn("");
			}
			try
			{
				if (Spot != null && Player.Instance.spendingTimeMode)
				{
					ActionController.Instance.CancelPassTime(Spot, Spot.node, (Actor)(object)Player.Instance);
				}
				if ((int)SessionData.Instance.currentTimeSpeed != 1)
				{
					SessionData.Instance.SetTimeSpeed((TimeSpeed)1);
				}
			}
			catch (Exception ex)
			{
				Plugin.L.LogWarning((object)("[REST] wake failed: " + ex.Message));
			}
			if (StandMenu.Active)
			{
				StandMenu.Close();
			}
			Note((own ? "You stopped waiting: " : "You woke up: ") + why);
		}

		internal static string Fmt(float h)
		{
			h %= 24f;
			int num = (int)h;
			int value = (int)((h - (float)num) * 60f);
			return $"{num:00}:{value:00}";
		}

		internal static bool Debounce()
		{
			if (Time.unscaledTime - lastSkipPress < 0.3f)
			{
				return false;
			}
			lastSkipPress = Time.unscaledTime;
			return true;
		}

		internal static void Note(string msg)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				InterfaceController.Instance.NewGameMessage((GameMessageType)0, 0, msg, (Icon)3, (AudioEvent)null, false, default(Color), -1, 0f, (RectTransform)null, (PingOnComplete)0, (Evidence)null, (List<DataKey>)null, (Sprite)null);
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch]
	internal static class Patches
	{
		[HarmonyPatch(typeof(ActionController), "PassTime")]
		[HarmonyPrefix]
		private static void PassTime(Interactable what)
		{
			Rest.Spot = what;
		}

		[HarmonyPatch(typeof(SessionData), "SetTimeSpeed")]
		[HarmonyPostfix]
		private static void SpeedSet()
		{
			Keeper.Apply();
		}

		[HarmonyPatch(typeof(TelephoneController), "AddActiveCall")]
		[HarmonyPostfix]
		private static void Call(PhoneCall newCall)
		{
			if (!Plugin.WakeOnPhone.Value || !Rest.Resting)
			{
				return;
			}
			try
			{
				NewGameLocation currentGameLocation = ((Actor)Player.Instance).currentGameLocation;
				if (((newCall != null) ? newCall.toNS : null) != null && (Object)(object)currentGameLocation != (Object)null && (Object)(object)newCall.toNS.location == (Object)(object)currentGameLocation)
				{
					Rest.Wake("the phone is ringing");
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(NewDoor), "OnKnock")]
		[HarmonyPostfix]
		private static void Knock(NewDoor __instance)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.WakeOnKnock.Value || !Rest.Resting)
			{
				return;
			}
			try
			{
				if (Vector3.Distance(((Component)__instance).transform.position, ((Component)Player.Instance).transform.position) < 15f)
				{
					Rest.Wake("someone is knocking");
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(MurderController), "OnVictimKilled")]
		[HarmonyPostfix]
		private static void Killed()
		{
			if (Plugin.WakeOnMurder.Value)
			{
				Rest.Wake("there has been a murder");
			}
		}

		[HarmonyPatch(typeof(MurderController), "OnVictimDiscovery")]
		[HarmonyPostfix]
		private static void Found()
		{
			if (Plugin.WakeOnBodyFound.Value)
			{
				Rest.Wake("a body has been found");
			}
		}
	}
	public class Keeper : MonoBehaviour
	{
		private static KeyCode? hourKey;

		private static KeyCode? fullKey;

		private static KeyCode? earlier;

		private static KeyCode? later;

		private static KeyCode? padAlarm;

		private static KeyCode? padHour;

		private static bool wasRunning;

		private static bool watchShown;

		private float nextBody;

		private float lastHeat = -1f;

		private float lowestHeat = 2f;

		public Keeper(IntPtr ptr)
			: base(ptr)
		{
		}

		internal static void Apply()
		{
			try
			{
				float num = (Rest.Own ? Rest.OwnSpeed : ((Plugin.BoostGameRest.Value && Rest.GameResting) ? Plugin.Speed.Value : 0f));
				if (num > 0f && SessionData.Instance.currentTimeMultiplier < num)
				{
					SessionData.Instance.currentTimeMultiplier = num;
				}
			}
			catch
			{
			}
		}

		private static string Or(string text, string pad)
		{
			if (!string.IsNullOrWhiteSpace(pad))
			{
				return text + " or " + PadName(pad);
			}
			return text;
		}

		private static string PadName(string key)
		{
			return key switch
			{
				"JoystickButton0" => "A", 
				"JoystickButton1" => "B", 
				"JoystickButton2" => "X", 
				"JoystickButton3" => "Y", 
				"JoystickButton4" => "LB", 
				"JoystickButton5" => "RB", 
				"JoystickButton6" => "Back", 
				"JoystickButton7" => "Start", 
				"JoystickButton8" => "left stick", 
				"JoystickButton9" => "right stick", 
				_ => key, 
			};
		}

		private static bool KeyDown(ref KeyCode? cache, ConfigEntry<string> entry)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			if (!cache.HasValue)
			{
				string text = entry.Value?.Trim() ?? "";
				cache = (KeyCode)((text.Length > 0 && Enum.TryParse<KeyCode>(text, ignoreCase: true, out KeyCode result)) ? ((int)result) : 0);
			}
			if (cache != (KeyCode?)0)
			{
				return Input.GetKeyDown(cache.Value);
			}
			return false;
		}

		private static string Pretty(string key)
		{
			if (!(key == "Comma"))
			{
				if (key == "Period")
				{
					return ".";
				}
				return key;
			}
			return ",";
		}

		private static bool HoldingWatch()
		{
			try
			{
				FirstPersonItemController instance = FirstPersonItemController.Instance;
				object obj;
				if (instance == null)
				{
					obj = null;
				}
				else
				{
					FirstPersonItem currentItem = instance.currentItem;
					obj = ((currentItem != null) ? ((Object)currentItem).name : null);
				}
				if (obj == null)
				{
					obj = "";
				}
				return ((string)obj).IndexOf("watch", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			catch
			{
				return false;
			}
		}

		private void Update()
		{
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Expected O, but got Unknown
			//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c1: Expected O, but got Unknown
			//IL_04f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fc: Invalid comparison between Unknown and I4
			bool flag = Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305);
			bool flag2 = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
			bool skip = Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307);
			try
			{
				bool flag3 = HoldingWatch();
				StandMenu.Tick(flag3);
				if (flag3 && !watchShown && Plugin.ShowWatchHint.Value)
				{
					Rest.Note("Hold still to pass time.");
				}
				watchShown = flag3;
				bool flag4 = false;
				try
				{
					flag4 = (Object)(object)Player.Instance != (Object)null && (Player.Instance.spendingTimeMode || Player.Instance.setAlarmMode);
				}
				catch
				{
				}
				bool flag5 = default(bool);
				if (flag3 && !flag && (KeyDown(ref earlier, Plugin.EarlierKey) || KeyDown(ref later, Plugin.LaterKey)))
				{
					Player instance = Player.Instance;
					bool keyDown = Input.GetKeyDown(later.GetValueOrDefault());
					if (!instance.setAlarmMode)
					{
						instance.SetSettingAlarmMode(true);
						if (Rest.AlarmHoursAhead() < 0.25f)
						{
							instance.alarm = Rest.Clock;
						}
					}
					instance.AddToAlarmTime(keyDown ? 0.25f : (-0.25f));
					ManualLogSource l = Plugin.L;
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(36, 2, ref flag5);
					if (flag5)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[REST] watch set to ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(instance.alarm, "0.00");
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" (setAlarmMode=");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(instance.setAlarmMode);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")");
					}
					l.LogInfo(val);
					Rest.Note($"Watch set to {Rest.Fmt(instance.alarm)}. {Plugin.FullSkipKey.Value} to skip there, {Plugin.WatchKey.Value} for one hour.");
				}
				if ((flag3 || flag4) && !flag && KeyDown(ref hourKey, Plugin.WatchKey))
				{
					Rest.LastClock = Rest.Clock;
					Rest.Skip(1f, "one hour");
				}
				if ((flag3 || flag4) && !flag && KeyDown(ref fullKey, Plugin.FullSkipKey))
				{
					float num = Rest.AlarmHoursAhead();
					if (num <= 0.01f)
					{
						Rest.Note("Set a time on the watch first.");
					}
					else
					{
						Rest.LastClock = Rest.Clock;
						Rest.Skip(num, "the watch time");
					}
				}
				bool flag6 = false;
				try
				{
					flag6 = (Object)(object)Player.Instance != (Object)null && Player.Instance.spendingTimeMode && !Player.Instance.setAlarmMode;
				}
				catch
				{
				}
				if (flag6 && !wasRunning && Plugin.ShowWatchHint.Value)
				{
					Rest.Note(Or("Skip to alarm: R", Plugin.PadAlarm.Value) + ". " + Or("One hour: " + Plugin.WatchKey.Value, Plugin.PadHour.Value) + ".");
				}
				wasRunning = flag6;
				if (flag6 && KeyDown(ref padHour, Plugin.PadHour) && Rest.Debounce())
				{
					Rest.LastClock = Rest.Clock;
					Rest.Skip(1f, "one hour");
				}
				if (!flag && Plugin.ReplaceHoursToggle.Value && (Input.GetKeyDown((KeyCode)114) || (flag6 && KeyDown(ref padAlarm, Plugin.PadAlarm))) && Rest.Debounce() && flag6)
				{
					float num2 = Rest.AlarmHoursAhead();
					ManualLogSource l2 = Plugin.L;
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(52, 1, ref flag5);
					if (flag5)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[REST] Skip To Alarm pressed while resting, ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(num2, "0.00");
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" h ahead");
					}
					l2.LogInfo(val);
					if (num2 <= 0.01f)
					{
						Rest.Note("Set the alarm on your watch first.");
					}
					else
					{
						Rest.LastClock = Rest.Clock;
						Rest.Skip(num2, "the alarm");
					}
				}
				if (flag && flag2 && Input.GetKeyDown((KeyCode)114) && (Object)(object)SessionData.Instance != (Object)null && (Object)(object)Player.Instance != (Object)null)
				{
					if (!Rest.Own)
					{
						Rest.LastClock = Rest.Clock;
					}
					Rest.StartOrExtend(skip);
				}
				if (Rest.Own)
				{
					if (Input.GetKeyDown((KeyCode)27) || Input.GetKeyDown((KeyCode)119) || Input.GetKeyDown((KeyCode)97) || Input.GetKeyDown((KeyCode)115) || Input.GetKeyDown((KeyCode)100))
					{
						Rest.StopOwn("You stopped waiting.");
					}
					else
					{
						float clock = Rest.Clock;
						Rest.HoursLeft -= ((clock >= Rest.LastClock) ? (clock - Rest.LastClock) : (clock + 24f - Rest.LastClock));
						Rest.LastClock = clock;
						if (Rest.HoursLeft <= 0f)
						{
							Rest.StopOwn("Done waiting.");
						}
						else if ((int)SessionData.Instance.currentTimeSpeed != 3)
						{
							SessionData.Instance.SetTimeSpeed((TimeSpeed)3);
						}
					}
				}
			}
			catch
			{
			}
			BodyCheck();
			Apply();
		}

		private void BodyCheck()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			if (!Rest.Resting)
			{
				if (lowestHeat < 2f)
				{
					ManualLogSource l = Plugin.L;
					bool flag = default(bool);
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(59, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[REST] rest over: lowest warmth ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(lowestHeat, "0.00");
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" (wakes at ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(Plugin.WakeWhenColder.Value, "0.00");
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" while dropping)");
					}
					l.LogInfo(val);
				}
				lowestHeat = 2f;
				lastHeat = -1f;
			}
			else
			{
				if (Time.unscaledTime < nextBody)
				{
					return;
				}
				nextBody = Time.unscaledTime + 0.25f;
				try
				{
					Player instance = Player.Instance;
					float heat = ((Human)instance).heat;
					bool flag2 = lastHeat >= 0f && heat < lastHeat - 0.0001f;
					lastHeat = heat;
					if (heat < lowestHeat)
					{
						lowestHeat = heat;
					}
					if (Plugin.WakeWhenColder.Value > 0f && heat <= Plugin.WakeWhenColder.Value && flag2)
					{
						Rest.Wake("you are getting cold");
					}
					else if (Plugin.WakeWhenHurt.Value > 0f && ((Actor)instance).maximumHealth > 0f && ((Actor)instance).currentHealth / ((Actor)instance).maximumHealth <= Plugin.WakeWhenHurt.Value)
					{
						Rest.Wake("you are hurt");
					}
				}
				catch
				{
				}
			}
		}
	}
	internal static class StandMenu
	{
		internal static bool Active;

		private static float stillSince = -1f;

		private static Vector3 lastPos;

		internal static Interactable? Spot;

		private static GameObject? spotObject;

		private static Vector3 standPos;

		private static Quaternion standRot;

		internal static float HoldUntil;

		internal static float GuardUntil;

		private static Vector3 guardPos;

		private static bool loggedMove;

		private static InteractablePreset? chairPreset;

		internal static bool InGuard => Time.unscaledTime < GuardUntil;

		internal static void Tick(bool watch)
		{
			//IL_0039: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Expected O, but got Unknown
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Expected O, but got Unknown
			if (!Plugin.StandingMenu.Value)
			{
				return;
			}
			Player instance = Player.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			bool flag = default(bool);
			if (!Active && Time.unscaledTime < GuardUntil)
			{
				Vector3 position = ((Component)instance).transform.position;
				float num = Vector3.Distance(position, guardPos);
				if (num > 3f)
				{
					ManualLogSource l = Plugin.L;
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(47, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[REST] moved ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(num, "0.0");
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" m in one step after resting (to ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Vector3>(position);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")");
					}
					l.LogInfo(val);
				}
				guardPos = position;
			}
			if (Time.unscaledTime < HoldUntil)
			{
				return;
			}
			if (Active)
			{
				Interactable lockedInInteraction = InteractionController.Instance.lockedInInteraction;
				bool num2 = lockedInInteraction != null && Spot != null && ((Il2CppObjectBase)lockedInInteraction).Pointer == ((Il2CppObjectBase)Spot).Pointer;
				bool flag2 = instance.spendingTimeMode && Spot != null && Rest.Spot != null && ((Il2CppObjectBase)Rest.Spot).Pointer == ((Il2CppObjectBase)Spot).Pointer;
				if (!num2 && !flag2)
				{
					ManualLogSource l2 = Plugin.L;
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(60, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[REST] stand menu closed (now locked into '");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>((lockedInInteraction == null) ? "nothing" : lockedInInteraction.GetName());
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("', passing time ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(instance.spendingTimeMode);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")");
					}
					l2.LogInfo(val);
					Active = false;
					Cleanup();
					HoldUntil = Time.unscaledTime + 1f;
					StartGuard();
					return;
				}
				float num3 = Vector3.Distance(((Component)instance).transform.position, standPos);
				if (num3 > 3f && !loggedMove)
				{
					loggedMove = true;
					ManualLogSource l3 = Plugin.L;
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(44, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[REST] moved ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(num3, "0.0");
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" m while the watch menu is open");
					}
					l3.LogInfo(val);
				}
				return;
			}
			if (instance.spendingTimeMode && InteractionController.Instance.lockedInInteraction == null && !Rest.Own)
			{
				Plugin.L.LogInfo((object)"[REST] cleared a leftover pass-time state");
				try
				{
					instance.SetSettingAlarmMode(false);
				}
				catch
				{
				}
				try
				{
					instance.spendingTimeMode = false;
				}
				catch
				{
				}
			}
			if (!watch || instance.spendingTimeMode || InteractionController.Instance.lockedInInteraction != null)
			{
				stillSince = -1f;
				return;
			}
			Vector3 position2 = ((Component)instance).transform.position;
			if (stillSince < 0f || Vector3.Distance(position2, lastPos) > 0.05f)
			{
				stillSince = Time.unscaledTime;
				lastPos = position2;
			}
			else if (!(Time.unscaledTime - stillSince < Plugin.StandingMenuDelay.Value))
			{
				stillSince = -1f;
				Open(instance);
			}
		}

		private static void StartGuard()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			loggedMove = false;
			GuardUntil = Time.unscaledTime + 10f;
			guardPos = (((Object)(object)Player.Instance != (Object)null) ? ((Component)Player.Instance).transform.position : standPos);
		}

		private static void Open(Player p)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Expected O, but got Unknown
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: 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_0193: Expected O, but got Unknown
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val;
				if (p.spendingTimeMode || p.setAlarmMode)
				{
					ManualLogSource l = Plugin.L;
					val = new BepInExInfoLogInterpolatedStringHandler(66, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[REST] stand menu: clearing leftover state (passing time ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(p.spendingTimeMode);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", alarm ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(p.setAlarmMode);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")");
					}
					l.LogInfo(val);
					try
					{
						p.SetSettingAlarmMode(false);
					}
					catch
					{
					}
					try
					{
						p.spendingTimeMode = false;
					}
					catch
					{
					}
				}
				standPos = ((Component)p).transform.position;
				standRot = ((Component)p).transform.rotation;
				InteractablePreset val2 = ChairPreset();
				if ((SoCustomComparison)(object)val2 == (SoCustomComparison)null)
				{
					Plugin.L.LogInfo((object)"[REST] stand menu: no chair preset");
					return;
				}
				spotObject = new GameObject("SkipTimeSpot");
				spotObject.transform.position = ((Component)p).transform.position;
				spotObject.transform.rotation = ((Component)p).transform.rotation;
				Spot = InteractableCreator.Instance.CreateTransformInteractable(val2, spotObject.transform, (Human)null, (Evidence)null, Vector3.zero, Vector3.zero, (List<Passed>)null);
				if (Spot == null)
				{
					Plugin.L.LogInfo((object)"[REST] stand menu: could not create the spot");
					Cleanup();
					return;
				}
				Active = true;
				InteractionController.Instance.SetLockedInInteractionMode(Spot, 0, false);
				ActionController.Instance.PassTime(Spot, Spot.node ?? ((Actor)p).currentNode, (Actor)(object)p);
				ManualLogSource l2 = Plugin.L;
				val = new BepInExInfoLogInterpolatedStringHandler(40, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[REST] stand menu open at your feet (");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(Vector3.Distance(Spot.wPos, ((Component)p).transform.position), "0.0");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" m)");
				}
				l2.LogInfo(val);
			}
			catch (Exception ex)
			{
				Active = false;
				Cleanup();
				Plugin.L.LogWarning((object)("[REST] stand menu failed: " + ex));
			}
		}

		private static InteractablePreset? ChairPreset()
		{
			if ((SoCustomComparison)(object)chairPreset != (SoCustomComparison)null)
			{
				return chairPreset;
			}
			foreach (Object item in (Il2CppArrayBase<Object>)(object)Resources.FindObjectsOfTypeAll(Il2CppType.Of<InteractablePreset>()))
			{
				InteractablePreset val = ((Il2CppObjectBase)item).TryCast<InteractablePreset>();
				if ((SoCustomComparison)(object)val != (SoCustomComparison)null && ((Object)val).name == "Chair")
				{
					chairPreset = val;
					break;
				}
			}
			return chairPreset;
		}

		private static void Cleanup()
		{
			try
			{
				Interactable? spot = Spot;
				if (spot != null)
				{
					spot.SafeDelete(false);
				}
			}
			catch
			{
			}
			Spot = null;
			try
			{
				if ((Object)(object)spotObject != (Object)null)
				{
					Object.Destroy((Object)(object)spotObject);
				}
			}
			catch
			{
			}
			spotObject = null;
		}

		internal static void Close()
		{
			Active = false;
			try
			{
				Player.Instance.SetSettingAlarmMode(false);
			}
			catch
			{
			}
			try
			{
				InteractionController.Instance.SetLockedInInteractionMode((Interactable)null, 0, false);
			}
			catch
			{
			}
			Cleanup();
			HoldUntil = Time.unscaledTime + 1f;
			StartGuard();
			Plugin.L.LogInfo((object)"[REST] stand menu: got up");
		}
	}
	[HarmonyPatch]
	internal static class StandMenuPatches
	{
		[HarmonyPatch(typeof(Interactable), "GetName")]
		[HarmonyPostfix]
		private static void Name(Interactable __instance, ref string __result)
		{
			Interactable spot = StandMenu.Spot;
			if (spot != null && ((Il2CppObjectBase)__instance).Pointer == ((Il2CppObjectBase)spot).Pointer)
			{
				__result = "Watch";
			}
		}

		[HarmonyPatch(typeof(Player), "TransformPlayerController")]
		[HarmonyPrefix]
		private static bool NoReturnWrite(Interactable newInteractable)
		{
			Interactable spot = StandMenu.Spot;
			if (spot != null && newInteractable != null && ((Il2CppObjectBase)newInteractable).Pointer == ((Il2CppObjectBase)spot).Pointer)
			{
				Plugin.L.LogInfo((object)"[REST] standing rest: seat transition skipped, you stay where you are");
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(Player), "ReturnFromTransform")]
		[HarmonyPrefix]
		private static bool NoReturnMove()
		{
			if (StandMenu.Active || Time.unscaledTime < StandMenu.HoldUntil)
			{
				Plugin.L.LogInfo((object)"[REST] standing rest: return from seat skipped");
				return false;
			}
			return true;
		}

		private static bool Holding()
		{
			if (!StandMenu.Active && !StandMenu.InGuard)
			{
				return Time.unscaledTime < StandMenu.HoldUntil;
			}
			return true;
		}

		[HarmonyPatch(typeof(PlayerUnstuck), "Update")]
		[HarmonyPrefix]
		private static void NotStuck(PlayerUnstuck __instance)
		{
			if (Holding())
			{
				try
				{
					__instance.currentAttemptedSecondsOfMovement = 0f;
				}
				catch
				{
				}
			}
		}

		[HarmonyPatch(typeof(PlayerUnstuck), "UnstuckTeleportPlayer")]
		[HarmonyPrefix]
		private static bool NoUnstuck()
		{
			if (!Holding())
			{
				return true;
			}
			Plugin.L.LogInfo((object)"[REST] blocked the game's unstuck teleport");
			return false;
		}

		[HarmonyPatch(typeof(ActionController), "Return")]
		[HarmonyPrefix]
		private static bool Return()
		{
			if (!StandMenu.Active)
			{
				return true;
			}
			StandMenu.Close();
			return false;
		}
	}
	internal static class SkipPrompts
	{
		internal const string Hour = "Skip One Hour";

		internal const string All = "Skip To Alarm";

		private static InteractionAction? all;

		private static bool swapLogged;

		private static bool logged;

		private static InteractionAction? runAll;

		private static InteractionAction? runHour;

		internal static InteractionAction? toggleSrc;

		internal static InteractionAction? forwardSrc;

		private static bool runLogged;

		internal static void Swap(Dictionary<InteractionKey, InteractableCurrentAction>? table)
		{
			//IL_0062: 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_009e: Expected O, but got Unknown
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			if (table == null || !Plugin.ReplaceHoursToggle.Value)
			{
				return;
			}
			Enumerator<InteractionKey, InteractableCurrentAction> enumerator = table.GetEnumerator();
			bool flag = default(bool);
			while (enumerator.MoveNext())
			{
				KeyValuePair<InteractionKey, InteractableCurrentAction> current = enumerator.Current;
				InteractableCurrentAction value = current.Value;
				InteractionAction val = ((value != null) ? value.currentAction : null);
				if (((val != null) ? val.interactionName : null) != "Switch Hours/Minutes")
				{
					continue;
				}
				if (all == null)
				{
					all = Copy(val, "Skip To Alarm", val.useDefaultKeySetting, val.keyOverride);
				}
				current.Value.currentAction = all;
				if (!swapLogged)
				{
					swapLogged = true;
					ManualLogSource l = Plugin.L;
					BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(38, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[REST] prompt on ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<InteractionKey>(current.Key);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" is now Skip To Alarm");
					}
					l.LogInfo(val2);
				}
			}
		}

		internal static void AddTo(List<InteractionAction>? acts)
		{
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			if (acts == null || !Plugin.ReplaceHoursToggle.Value)
			{
				return;
			}
			AddRunning(acts);
			bool flag = false;
			int num = -1;
			for (int i = 0; i < acts.Count; i++)
			{
				InteractionAction obj = acts[i];
				string text = ((obj != null) ? obj.interactionName : null);
				if (text == "Skip To Alarm")
				{
					return;
				}
				if (text == "Alarm Forward")
				{
					flag = true;
					if (forwardSrc == null)
					{
						forwardSrc = acts[i];
					}
				}
				if (text == "Switch Hours/Minutes")
				{
					num = i;
					if (toggleSrc == null)
					{
						toggleSrc = acts[i];
					}
				}
			}
			if (flag && num >= 0)
			{
				InteractionAction val = acts[num];
				if (all == null)
				{
					all = Copy(val, "Skip To Alarm", val.useDefaultKeySetting, val.keyOverride);
				}
				acts[num] = all;
				if (!logged)
				{
					logged = true;
					Plugin.L.LogInfo((object)"[REST] Skip To Alarm replaces Switch Hours/Minutes in the pass-time menu");
				}
			}
		}

		private static void AddRunning(List<InteractionAction> acts)
		{
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Expected O, but got Unknown
			bool flag = false;
			try
			{
				flag = (Object)(object)Player.Instance != (Object)null && Player.Instance.spendingTimeMode && !Player.Instance.setAlarmMode;
			}
			catch
			{
			}
			if (!flag)
			{
				for (int num = acts.Count - 1; num >= 0; num--)
				{
					if (acts[num] != null && ((runAll != null && ((Il2CppObjectBase)acts[num]).Pointer == ((Il2CppObjectBase)runAll).Pointer) || (runHour != null && ((Il2CppObjectBase)acts[num]).Pointer == ((Il2CppObjectBase)runHour).Pointer)))
					{
						acts.RemoveAt(num);
					}
				}
				return;
			}
			InteractionAction val = null;
			for (int i = 0; i < acts.Count; i++)
			{
				InteractionAction obj2 = acts[i];
				switch ((obj2 != null) ? obj2.interactionName : null)
				{
				case "Skip One Hour":
					return;
				case "Cancel":
					val = acts[i];
					break;
				}
			}
			if (val == null)
			{
				return;
			}
			if (toggleSrc != null)
			{
				if (runAll == null)
				{
					runAll = Slot(Mixed(val, toggleSrc, "Skip To Alarm"), Plugin.PromptAlarmSlot.Value);
				}
				acts.Add(runAll);
			}
			if (forwardSrc != null)
			{
				if (runHour == null)
				{
					runHour = Slot(Mixed(val, forwardSrc, "Skip One Hour"), Plugin.PromptHourSlot.Value);
				}
				acts.Add(runHour);
			}
			if (!runLogged)
			{
				runLogged = true;
				ManualLogSource l = Plugin.L;
				bool flag2 = default(bool);
				BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(64, 2, ref flag2);
				if (flag2)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[REST] prompts added while resting (alarm source ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(toggleSrc != null);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", hour source ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(forwardSrc != null);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(")");
				}
				l.LogInfo(val2);
			}
		}

		private static InteractionAction Slot(InteractionAction a, string slot)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_0018: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			if (!string.IsNullOrWhiteSpace(slot) && Enum.TryParse<InteractionKey>(slot.Trim(), ignoreCase: true, out InteractionKey result) && (int)result != 0)
			{
				a.useDefaultKeySetting = false;
				a.keyOverride = result;
			}
			ManualLogSource l = Plugin.L;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(20, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[REST] prompt '");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(a.interactionName);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' on ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(a.useDefaultKeySetting ? "its default button" : ((object)a.keyOverride/*cast due to .constrained prefix*/).ToString());
			}
			l.LogInfo(val);
			return a;
		}

		private static InteractionAction Mixed(InteractionAction shown, InteractionAction does, string name)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			InteractionAction obj = Copy(shown, name, does.useDefaultKeySetting, does.keyOverride);
			obj.action = does.action;
			return obj;
		}

		private static InteractionAction Copy(InteractionAction src, string name, bool useDefault, InteractionKey key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			return new InteractionAction
			{
				interactionName = name,
				action = src.action,
				useDefaultKeySetting = useDefault,
				keyOverride = key,
				onlyActiveIf = src.onlyActiveIf,
				effectSwitchStates = new List<SwitchState>(),
				availableWhileLockedIn = src.availableWhileLockedIn,
				availableWhileIllegal = true,
				availableWhileWitnessesToIllegal = true,
				specialCase = src.specialCase
			};
		}
	}
	[HarmonyPatch]
	internal static class SkipPromptPatches
	{
		[HarmonyPatch(typeof(Interactable), "UpdateCurrentActions")]
		[HarmonyPostfix]
		private static void Current(Interactable __instance)
		{
			try
			{
				SkipPrompts.Swap(__instance.currentActions);
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(InteractablePreset), "GetActions")]
		[HarmonyPostfix]
		private static void Actions(List<InteractionAction> __result)
		{
			try
			{
				SkipPrompts.AddTo(__result);
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(Interactable), "OnInteraction", new Type[]
		{
			typeof(InteractionAction),
			typeof(Actor),
			typeof(bool),
			typeof(float)
		})]
		[HarmonyPrefix]
		private static bool Pressed(InteractionAction action)
		{
			string text = ((action != null) ? action.interactionName : null);
			if ((text == "Skip One Hour" || text == "Skip To Alarm") && !Rest.Debounce())
			{
				return false;
			}
			if (text == "Skip One Hour")
			{
				Rest.Skip(1f, "one hour");
				return false;
			}
			if (text == "Skip To Alarm")
			{
				float num = Rest.AlarmHoursAhead();
				if (num <= 0.01f)
				{
					Rest.Note("Set the alarm on your watch first.");
				}
				else
				{
					Rest.Skip(num, "the alarm");
				}
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal static class SkipButtonPatches
	{
		private const string From = "Switch Hours/Minutes";

		private static bool busy;

		private static bool InAlarmMenu()
		{
			try
			{
				Player instance = Player.Instance;
				return (Object)(object)instance != (Object)null && (instance.setAlarmMode || StandMenu.Active || InteractionController.Instance.lockedInInteraction != null);
			}
			catch
			{
				return false;
			}
		}

		[HarmonyPatch(typeof(ActionController), "HoursMinutesToggle")]
		[HarmonyPrefix]
		private static bool Toggle()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			if (!Plugin.ReplaceHoursToggle.Value || !InAlarmMenu())
			{
				return true;
			}
			if (!Rest.Debounce())
			{
				return false;
			}
			float num = Rest.AlarmHoursAhead();
			ManualLogSource l = Plugin.L;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(38, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[REST] Skip To Alarm pressed, ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(num, "0.00");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" h ahead");
			}
			l.LogInfo(val);
			if (num <= 0.01f)
			{
				Rest.Note("Set the alarm on your watch first.");
			}
			else
			{
				Rest.Skip(num, "the alarm");
			}
			return false;
		}

		[HarmonyPatch(typeof(ActionController), "WatchForward")]
		[HarmonyPrefix]
		private static bool Forward()
		{
			bool flag = false;
			try
			{
				flag = Player.Instance.spendingTimeMode && !Player.Instance.setAlarmMode;
			}
			catch
			{
			}
			if (!flag)
			{
				return true;
			}
			if (Rest.Debounce())
			{
				Rest.Skip(1f, "one hour");
			}
			return false;
		}

		private static void Relabel(ControlDisplayController c)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (busy || !Plugin.ReplaceHoursToggle.Value || (Object)(object)c == (Object)null)
			{
				return;
			}
			try
			{
				string actionName = c.actionName;
				if (actionName != null && actionName.Contains("Switch Hours/Minutes"))
				{
					busy = true;
					c.SetControlText(c.key, actionName.Replace("Switch Hours/Minutes", "Skip To Alarm"), false);
				}
			}
			catch
			{
			}
			finally
			{
				busy = false;
			}
		}

		[HarmonyPatch(typeof(ControlDisplayController), "UpdateDisplay")]
		[HarmonyPostfix]
		private static void Display(ControlDisplayController __instance)
		{
			Relabel(__instance);
		}

		[HarmonyPatch(typeof(ControlDisplayController), "SetControlText")]
		[HarmonyPostfix]
		private static void Text(ControlDisplayController __instance)
		{
			Relabel(__instance);
		}
	}
	[HarmonyPatch(typeof(Strings), "Get")]
	internal static class PromptText
	{
		private static void Postfix(string key, ref string __result)
		{
			if (key == "Skip To Alarm")
			{
				__result = key + " (R)";
			}
			else if (key == "Skip One Hour")
			{
				__result = key + " (" + Plugin.WatchKey.Value + ")";
			}
		}
	}
}