Decompiled source of Nivalis Better Time v2.0.10
BepInEx/plugins/NivalisSlowDays/NivalisSlowDays.dll
Decompiled 13 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Text.Json; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using Cysharp.Threading.Tasks; using Cysharp.Threading.Tasks.CompilerServices; using HarmonyLib; using Hvizeu.NivalisMods; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.Attributes; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Il2CppSystem.Reflection; using Il2CppSystem.Threading; using Microsoft.CodeAnalysis; using Nivalis; using Nivalis.Dialogue; using Nivalis.GhostSystem; using Nivalis.GhostSystem.Ai; using Nivalis.GhostSystem.CustomerLoop; using Nivalis.Localization; using Nivalis.Player; using Nivalis.UI.Concrete; using Nivalis.UI.InGameMenu; using Nivalis.Utility; using TMPro; using UnityEngine; using UnityEngine.AI; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.InputSystem.Utilities; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("Hvizeu")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Configurable time and curfew-aware waiting for Nivalis Nights.")] [assembly: AssemblyFileVersion("2.0.10.0")] [assembly: AssemblyInformationalVersion("2.0.10")] [assembly: AssemblyProduct("NivalisSlowDays")] [assembly: AssemblyTitle("NivalisSlowDays")] [assembly: AssemblyVersion("2.0.10.0")] 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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NativeIntegerAttribute : Attribute { public readonly bool[] TransformFlags; public NativeIntegerAttribute() { TransformFlags = new bool[1] { true }; } public NativeIntegerAttribute(bool[] P_0) { TransformFlags = P_0; } } } namespace Hvizeu.NivalisMods { internal static class CharacterClearance { internal static void Volume(Character character, out Vector3 lower, out Vector3 upper, out float radius) { //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_015f: 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_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0177: 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_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0189: 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_009b: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00be: 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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) Collider collide = character.Collide; CapsuleCollider val = ((collide != null) ? ((Il2CppObjectBase)collide).TryCast<CapsuleCollider>() : null); Vector3 val2; float num; if ((Object)(object)val != (Object)null && val.direction == 1) { Vector3 lossyScale = ((Component)val).transform.lossyScale; val2 = ((Component)val).transform.TransformPoint(val.center); radius = val.radius * Mathf.Max(Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.z)); num = val.height * Mathf.Abs(lossyScale.y); } else { if ((Object)(object)collide != (Object)null && collide.enabled) { Bounds bounds = collide.bounds; Vector3 size = ((Bounds)(ref bounds)).size; if (((Vector3)(ref size)).sqrMagnitude > 0.01f) { Bounds bounds2 = collide.bounds; val2 = ((Bounds)(ref bounds2)).center; radius = Mathf.Max(((Bounds)(ref bounds2)).extents.x, ((Bounds)(ref bounds2)).extents.z); num = ((Bounds)(ref bounds2)).size.y; goto IL_013a; } } NavMeshAgent agent = character.Movement.Agent; radius = agent.radius; num = agent.height; val2 = ((BaseCharacter)character).ThisTransform.position + Vector3.up * (num * 0.5f + agent.baseOffset); } goto IL_013a; IL_013a: radius = Mathf.Max(0.1f, radius); float num2 = Mathf.Max(0f, num * 0.5f - radius); lower = val2 - Vector3.up * num2; upper = val2 + Vector3.up * num2; } internal static bool Blocks(Character character, Collider collider) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) Character componentInParent = ((Component)collider).GetComponentInParent<Character>(); if ((Object)(object)componentInParent != (Object)null) { return ((Il2CppObjectBase)componentInParent).Pointer != ((Il2CppObjectBase)character).Pointer; } Collider collide = character.Collide; if ((Object)(object)collide == (Object)null) { return true; } int layer = ((Component)collider).gameObject.layer; if (Singleton<CharacterManager>.InstanceExist() && (LayerMask.op_Implicit(Singleton<CharacterManager>.Instance.EnvironmentLayer) & (1 << layer)) != 0) { return true; } return !Physics.GetIgnoreLayerCollision(((Component)collide).gameObject.layer, layer); } } } namespace NivalisSlowDays { internal static class BindingJson { internal const string WaitId = "495c85ec-ebbd-47ae-8b9c-91a662d095eb"; internal const string WaitGamepadId = "73a613ea-91c5-4aac-af1c-ff77e2968d34"; internal static string WithoutWait(string json) { if (string.IsNullOrEmpty(json)) { return json; } using (JsonDocument jsonDocument = JsonDocument.Parse(json)) { JsonElement rootElement = jsonDocument.RootElement; if (!rootElement.TryGetProperty("bindings", out var value) || value.ValueKind != JsonValueKind.Array) { return json; } if (!value.EnumerateArray().Any(IsWait)) { return json; } using MemoryStream memoryStream = new MemoryStream(); using (Utf8JsonWriter utf8JsonWriter = new Utf8JsonWriter((Stream)memoryStream, default(JsonWriterOptions))) { utf8JsonWriter.WriteStartObject(); foreach (JsonProperty item in rootElement.EnumerateObject()) { if (item.Name != "bindings") { item.WriteTo(utf8JsonWriter); continue; } utf8JsonWriter.WriteStartArray("bindings"); foreach (JsonElement item2 in value.EnumerateArray()) { if (!IsWait(item2)) { item2.WriteTo(utf8JsonWriter); } } utf8JsonWriter.WriteEndArray(); } utf8JsonWriter.WriteEndObject(); } return Encoding.UTF8.GetString(memoryStream.ToArray()); } static bool IsWait(JsonElement entry) { if (entry.ValueKind == JsonValueKind.Object && entry.TryGetProperty("id", out var value2) && value2.ValueKind == JsonValueKind.String) { if (!string.Equals(value2.GetString(), "495c85ec-ebbd-47ae-8b9c-91a662d095eb", StringComparison.OrdinalIgnoreCase)) { return string.Equals(value2.GetString(), "73a613ea-91c5-4aac-af1c-ff77e2968d34", StringComparison.OrdinalIgnoreCase); } return true; } return false; } } } [HarmonyPatch(typeof(VisitVenueAgentActionType), "MeetsRequirements")] internal static class CustomerArrivalPatch { private static void Postfix(ref bool __result) { if (__result && Plugin.BalanceArrivals.Value) { __result = CustomerArrivalPolicy.Admit(Plugin.Rate.Value, WaitFaults.Active); } } } internal static class CustomerArrivalPolicy { internal static bool Admit(float rate, bool explicitWait) { if (!float.IsFinite(rate)) { rate = 1f; } rate = Math.Clamp(rate, 0f, 2f); return rate > 0f || explicitWait; } } internal static class HourlyWork { private static UniTask task = null; private static VenueManager? owner; private static int queued; private static Stopwatch? acceleratedTime; internal static bool Pending { get; private set; } internal static bool NeedsUnpausedDrain { get; private set; } internal static int FaultSequence { get; private set; } internal static string ProgressText { get; private set; } = "Updating venues for the new hour..."; internal static bool Start(VenueManager venue) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown //IL_00ba: Expected O, but got Unknown if ((Object)(object)TimeController.Current == (Object)null) { return false; } if (Pending) { if ((Object)(object)owner != (Object)null && ((Il2CppObjectBase)owner).Pointer == ((Il2CppObjectBase)venue).Pointer) { queued++; return true; } return false; } if (TimeController.Current.Busy) { try { WaitVenueHour.Run(venue); } catch (Exception ex) { FaultSequence++; ManualLogSource modLog = Plugin.ModLog; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(35, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Native venue catch-up hour failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } modLog.LogError(val); } return true; } owner = venue; if (venue.onDestroyCancelToken == null) { CancellationTokenSource val2 = new CancellationTokenSource(); CancellationTokenSource val3 = val2; venue.onDestroyCancelToken = val2; } task = venue.HourlyUpdateTask(venue.onDestroyCancelToken.Token); Pending = true; ProgressText = "Updating venues for the new hour..."; acceleratedTime = null; return true; } internal static void Poll() { //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown if (!Pending) { return; } bool flag = default(bool); try { if ((int)task.Status == 0) { if (!NeedsUnpausedDrain) { TimeController? current = TimeController.Current; if (current != null && current.Busy) { ExpediteOwnedDelay(); } } return; } } catch (Exception ex) { if (!NeedsUnpausedDrain) { NeedsUnpausedDrain = true; FaultSequence++; ManualLogSource modLog = Plugin.ModLog; BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(91, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Cannot accelerate the active venue hour. Returning to gameplay to drain its original task: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } modLog.LogError(val); } return; } Pending = false; NeedsUnpausedDrain = false; try { task.GetAwaiter().GetResult(); if (acceleratedTime != null) { ManualLogSource modLog2 = Plugin.ModLog; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(55, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Venue hour completed after "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<double>(acceleratedTime.Elapsed.TotalSeconds, "0.00"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("s of wait catch-up; venues="); VenueManager? obj = owner; ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int?>((obj != null) ? new int?(obj._venueGhosts.Count) : ((int?)null)); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); } modLog2.LogInfo(val2); } task = null; while (queued > 0 && (Object)(object)owner != (Object)null && !Pending) { queued--; Start(owner); } } catch (Exception ex2) { queued = 0; FaultSequence++; ManualLogSource modLog3 = Plugin.ModLog; BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(35, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Native venue hourly update failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex2); } modLog3.LogError(val); } finally { if (!Pending) { owner = null; task = null; acceleratedTime = null; } } } private static void ExpediteOwnedDelay() { //IL_00e1: Unknown result type (might be due to invalid IL or missing references) IUniTaskSource source = task.source; _HourlyUpdateTask_d__48 val = NativeHourState.Read(((source != null) ? ((Il2CppObjectBase)source).TryCast<AsyncUniTask<_HourlyUpdateTask_d__48>>() : null) ?? throw new InvalidOperationException("Unknown native venue-hour task runner; cannot safely remove its paused delay.")); if ((Object)(object)owner == (Object)null || ((Il2CppObjectBase)val.__4__this).Pointer != ((Il2CppObjectBase)owner).Pointer || val.__1__state != 0) { throw new InvalidOperationException($"Native venue-hour await state or owner does not match: state={val.__1__state}, ownerMatches={(Object)(object)owner != (Object)null && ((Il2CppObjectBase)val.__4__this).Pointer == ((Il2CppObjectBase)owner).Pointer}."); } UniTask val2 = val.__u__1.task; if ((int)val2.Status == 0) { IUniTaskSource source2 = val2.source; DelayPromise obj = ((source2 != null) ? ((Il2CppObjectBase)source2).TryCast<DelayPromise>() : null) ?? throw new InvalidOperationException("Venue hour is awaiting an unexpected task instead of its pacing delay."); if (acceleratedTime == null) { acceleratedTime = Stopwatch.StartNew(); } obj.delayTimeSpan = 0f; ProgressText = $"Updating venues {val._i_5__2 + 1}/{owner._venueGhosts.Count}..."; } } } internal static class NativeHourState { private static readonly IntPtr field = IL2CPP.il2cpp_class_get_field_from_name(Il2CppClassPointerStore<AsyncUniTask<_HourlyUpdateTask_d__48>>.NativeClassPtr, "stateMachine"); internal static _HourlyUpdateTask_d__48 Read(AsyncUniTask<_HourlyUpdateTask_d__48> runner) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown if (field == IntPtr.Zero) { throw new MissingFieldException("Native venue-hour stateMachine field was not found."); } IntPtr intPtr = IL2CPP.il2cpp_field_get_value_object(field, ((Il2CppObjectBase)runner).Pointer); if (intPtr == IntPtr.Zero) { throw new InvalidOperationException("Native venue-hour state could not be read."); } return new _HourlyUpdateTask_d__48(intPtr); } } internal static class NativeSettings { private sealed class RowCheck { internal GameObject Source; internal GameObject Row; internal int RowId; internal int VisibleFrame = -1; internal bool Reported; } private const string RateName = "HvizeuClockRate"; private const string WaitName = "Hvizeu.Wait"; private static InputAction? action; private static InputActionReference? reference; private static InputActionAsset? owner; private static LocObjRef<LocStringSingle>? waitText; private static readonly WaitShortcut controls = new WaitShortcut(); private static Action<InputDevice, InputDeviceChange>? deviceChanged; private static readonly List<GameObject> rows = new List<GameObject>(); private static readonly Dictionary<int, CanvasBehaviourManager> canvasOwners = new Dictionary<int, CanvasBehaviourManager>(); private static readonly List<RowCheck> layoutChecks = new List<RowCheck>(); internal static bool Pressed { get { if (action == null) { return false; } ReadOnlyArray<InputBinding> bindings = action.bindings; int i = 0; for (int count = bindings.Count; i < count; i++) { string effectivePath = bindings[i].effectivePath; if (controls.Pressed(effectivePath)) { return true; } } return false; } } private static void WatchDevices() { if (deviceChanged == null) { deviceChanged = Action<InputDevice, InputDeviceChange>.op_Implicit((Action<InputDevice, InputDeviceChange>)delegate { controls.Clear(); }); InputSystem.onDeviceChange += deviceChanged; } } internal static void InitializeInput(PlayerInputManager manager) { InputActionAsset asset = manager.Input.asset; if ((Object)(object)owner == (Object)(object)asset && action != null) { return; } Enumerator<InputActionMap> enumerator = asset.actionMaps.GetEnumerator(); while (enumerator.MoveNext()) { if (enumerator.Current.enabled) { throw new InvalidOperationException("Wait must be registered before native input actions are enabled."); } } string text = ""; enumerator = asset.actionMaps.GetEnumerator(); while (enumerator.MoveNext()) { Enumerator<InputBinding> enumerator2 = enumerator.Current.bindings.GetEnumerator(); while (enumerator2.MoveNext()) { InputBinding current = enumerator2.Current; string path = current.path; if (path != null && path.StartsWith("<Keyboard>/", StringComparison.OrdinalIgnoreCase)) { text = current.groups; break; } } } if (string.IsNullOrEmpty(text)) { throw new InvalidOperationException("Native keyboard binding group was not found."); } string text2 = ""; enumerator = asset.actionMaps.GetEnumerator(); while (enumerator.MoveNext()) { Enumerator<InputBinding> enumerator2 = enumerator.Current.bindings.GetEnumerator(); while (enumerator2.MoveNext()) { InputBinding current2 = enumerator2.Current; string path2 = current2.path; if (path2 != null && path2.StartsWith("<Gamepad>/", StringComparison.OrdinalIgnoreCase)) { text2 = current2.groups.Split(';')[0]; break; } } } if (string.IsNullOrEmpty(text2)) { throw new InvalidOperationException("Native controller binding group was not found."); } InputActionMap gameplayControls = manager.GameplayControls; action = InputActionSetupExtensions.AddAction(gameplayControls, "Wait", (InputActionType)1, "<Keyboard>/t", (string)null, (string)null, text, "Button"); action.m_Id = "6697fae0-b29e-493c-9cc9-d76d317452c7"; Il2CppReferenceArray<InputBinding> bindings = gameplayControls.m_Bindings; InputBinding val = ((Il2CppArrayBase<InputBinding>)(object)bindings)[((Il2CppArrayBase<InputBinding>)(object)bindings).Length - 1]; val.m_Id = "495c85ec-ebbd-47ae-8b9c-91a662d095eb"; ((Il2CppArrayBase<InputBinding>)(object)bindings)[((Il2CppArrayBase<InputBinding>)(object)bindings).Length - 1] = val; InputActionSetupExtensions.AddBinding(action, "<Gamepad>/leftTrigger", (string)null, (string)null, text2); Il2CppReferenceArray<InputBinding> bindings2 = gameplayControls.m_Bindings; val = ((Il2CppArrayBase<InputBinding>)(object)bindings2)[((Il2CppArrayBase<InputBinding>)(object)bindings2).Length - 1]; val.m_Id = "73a613ea-91c5-4aac-af1c-ff77e2968d34"; ((Il2CppArrayBase<InputBinding>)(object)bindings2)[((Il2CppArrayBase<InputBinding>)(object)bindings2).Length - 1] = val; gameplayControls.ClearActionLookupTable(); gameplayControls.OnSetupChanged(); InputActionReference val2 = reference; reference = InputActionReference.Create(action); foreach (GameObject row in rows) { if (!((Object)(object)row == (Object)null)) { InputRebindUI component = row.GetComponent<InputRebindUI>(); if ((Object)(object)component != (Object)null) { ((InputDisplayUI)component).action.actionReference = reference; } } } if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)val2); } owner = asset; RestoreBinding(); WatchDevices(); Plugin.ModLog.LogInfo((object)"Registered native Wait action before input activation; vanilla input was not disabled or re-enabled."); } internal static void RestoreBinding() { controls.Clear(); if (action != null) { InputActionRebindingExtensions.ApplyBindingOverride(action, 0, Plugin.BindingPath.Value); InputActionRebindingExtensions.ApplyBindingOverride(action, 1, Plugin.GamepadBindingPath.Value); } } internal static void SaveBinding() { if (action != null) { string text = action.bindings[0].effectivePath ?? ""; string text2 = action.bindings[1].effectivePath ?? ""; if (!(text == Plugin.BindingPath.Value) || !(text2 == Plugin.GamepadBindingPath.Value)) { Plugin.BindingPath.Value = text; Plugin.GamepadBindingPath.Value = text2; ((ConfigEntryBase)Plugin.BindingPath).ConfigFile.Save(); } } } internal static void Attach(GameplaySettingsUI settings) { //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Expected O, but got Unknown //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Expected O, but got Unknown if ((Object)(object)((Component)settings).transform.parent.Find("Hvizeu.ModsOptions") != (Object)null) { Transform previous = ((Transform)settings.scroll.content).Find("HvizeuClockRate"); if ((Object)(object)previous != (Object)null) { int id = ((Object)((Component)previous).gameObject).GetInstanceID(); ((SettingsTabPanel)settings)._elements = Il2CppReferenceArray<SettingUIElementBase>.op_Implicit(((IEnumerable<SettingUIElementBase>)((SettingsTabPanel)settings)._elements).Where((SettingUIElementBase e) => (Object)(object)e != (Object)null && (Object)(object)((Component)e).gameObject != (Object)(object)((Component)previous).gameObject).ToArray()); if (canvasOwners.Remove(id, out CanvasBehaviourManager value) && (Object)(object)value != (Object)null) { CanvasBehaviourManager.UnregisterRuntimeChildren(previous, value); } rows.RemoveAll((GameObject r) => (Object)(object)r == (Object)null || (Object)(object)r == (Object)(object)((Component)previous).gameObject); layoutChecks.RemoveAll((RowCheck r) => r.RowId == id); ((Component)previous).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)previous).gameObject); settings.UpdateManualUINavigation(); } } else { if ((Object)(object)((Transform)settings.scroll.content).Find("HvizeuClockRate") != (Object)null) { return; } SettingsCategory category = ((SettingsTabPanel)settings)._category; category.DefaultSettings["HvizeuClockRate"] = "0.3"; category._settings["HvizeuClockRate"] = Plugin.Rate.Value.ToString("R", CultureInfo.InvariantCulture); GameObject val = new GameObject("SlowDays.SettingsConstruction"); val.SetActive(false); try { GameObject val2 = CloneRow(((Component)settings.mouseSensitivity).gameObject, val.transform); ((Object)val2).name = "HvizeuClockRate"; SliderSettingUI slider = val2.GetComponent<SliderSettingUI>(); ((SettingUIElementBase)slider).settingName = "HvizeuClockRate"; ((SettingUIElementBase)slider).OnValueChanged = null; ((SettingUIElement<float>)(object)slider).defaultValue = 0.3f; slider.valueTextFormat = "F1"; slider.slider.onValueChanged = new SliderEvent(); slider.slider.minValue = 0f; slider.slider.maxValue = 2f; slider.slider.wholeNumbers = false; slider.slider.SetValueWithoutNotify(Plugin.Rate.Value); TextMeshProUGUI component = ((Component)val2.transform.Find("Label")).GetComponent<TextMeshProUGUI>(); foreach (MonoBehaviour component2 in ((Component)component).GetComponents<MonoBehaviour>()) { if (((MemberInfo)((Object)component2).GetIl2CppType()).Name != "TextMeshProUGUI") { ((Behaviour)component2).enabled = false; } } ((TMP_Text)component).text = "CLOCK SPEED"; TMP_InputField precise = AddPreciseValue(slider); ((SettingUIElementBase)slider).OnValueChanged += Action<SettingUIElementBase>.op_Implicit((Action<SettingUIElementBase>)delegate(SettingUIElementBase element) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown try { slider.slider.SetValueWithoutNotify(TimePolicy.SnapRate(((SettingUIElement<float>)(object)slider).CurrentChoice)); slider.RefreshValueText(); ((SettingsTabPanel)settings).ApplySetting(element); Plugin.Rate.Value = ((SettingUIElement<float>)(object)slider).CurrentChoice; ((ConfigEntryBase)Plugin.Rate).ConfigFile.Save(); precise.SetTextWithoutNotify(((SettingUIElement<float>)(object)slider).CurrentChoice.ToString("F1", CultureInfo.InvariantCulture) + "x"); ((SettingsTabPanel)settings).CheckButtonsInteractability(); } catch (Exception ex) { ManualLogSource modLog = Plugin.ModLog; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(27, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Unable to save clock rate: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Exception>(ex); } modLog.LogError(val3); } }); List<SettingUIElementBase> list = ((IEnumerable<SettingUIElementBase>)((SettingsTabPanel)settings)._elements).ToList(); list.Add((SettingUIElementBase)(object)slider); ((SettingsTabPanel)settings)._elements = Il2CppReferenceArray<SettingUIElementBase>.op_Implicit(list.ToArray()); PlaceRow(val2, ((Component)settings.mouseSensitivity).gameObject); val2.SetActive(true); RegisterRow(val2); ((TMP_Text)component).text = "CLOCK SPEED"; slider.RefreshValueText(); rows.Add(val2); settings.UpdateManualUINavigation(); LayoutRebuilder.ForceRebuildLayoutImmediate(settings.scroll.content); Plugin.ModLog.LogInfo((object)"Added native Clock Speed slider to Settings > Gameplay."); } finally { Object.Destroy((Object)(object)val); } } } internal static void Attach(ControlsSettingsUI settings) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Expected O, but got Unknown if ((Object)(object)((Transform)settings.scroll.content).Find("Hvizeu.Wait") != (Object)null) { return; } if ((Object)(object)reference == (Object)null) { throw new InvalidOperationException("Native input asset is not ready for the Wait binding."); } if (waitText == null) { ScriptableObjectSingleton<LocObjectsDB>.Instance.AddNewObjWithGuid("hvizeu.slowdays.wait-label", (LocObjPlain)new LocStringSingle { Text = "WAIT" }); LocObjRef<LocStringSingle> obj = new LocObjRef<LocStringSingle>(false); ((LocObjRef)obj).locObjGuid = "hvizeu.slowdays.wait-label"; waitText = obj; } GameObject val = new GameObject("SlowDays.BindingConstruction"); val.SetActive(false); try { InputRebindUI val2 = null; Enumerator<InputRebindUI> enumerator = settings.controls.GetEnumerator(); while (enumerator.MoveNext()) { InputRebindUI current = enumerator.Current; Enumerator<InputBinding> enumerator2 = ((InputDisplayUI)current).action.actionReference.action.bindings.GetEnumerator(); while (enumerator2.MoveNext()) { string path = enumerator2.Current.path; if (path != null && path.StartsWith("<Keyboard>/")) { val2 = current; break; } } if ((Object)(object)val2 != (Object)null) { break; } } if ((Object)(object)val2 == (Object)null) { throw new InvalidOperationException("A native keyboard rebind row was not found."); } GameObject val3 = CloneRow(((Component)val2).gameObject, val.transform); ((Object)val3).name = "Hvizeu.Wait"; InputRebindUI component = val3.GetComponent<InputRebindUI>(); ActionDisplay val4 = new ActionDisplay(); val4.actionReference = reference; val4.description = ((InputDisplayUI)val2).action.description; val4.displayInputText = ((InputDisplayUI)val2).action.displayInputText; val4.compositeIndex = Il2CppStructArray<int>.op_Implicit(new int[1]); ((InputDisplayUI)component).action = val4; component.actionDescription = "WAIT"; component.locObjRef = waitText; component.OnSelected = null; component.OnSelected += Action<GameObject>.op_Implicit((Action<GameObject>)settings.Selected); PlaceRow(val3, ((Component)val2).gameObject); val3.SetActive(true); RegisterRow(val3); ((TMP_Text)component.actionText).text = "WAIT"; settings.controls.Add(component); settings.UpdateManualUINavigation(); rows.Add(val3); LayoutRebuilder.ForceRebuildLayoutImmediate(settings.scroll.content); Plugin.ModLog.LogInfo((object)"Added native Wait rebinding row to Settings > Controls."); } finally { Object.Destroy((Object)(object)val); } } private static GameObject CloneRow(GameObject original, Transform staging) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown GameObject val = Object.Instantiate<GameObject>(original, staging, false); val.SetActive(false); int num = RestoreCanvasBehaviours(original.transform, val.transform, original.GetComponentInParent<CanvasBehaviourManager>()); CopyGeometry(original.transform, val.transform); ManualLogSource modLog = Plugin.ModLog; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(89, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Native Settings clone "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)original).name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": restored "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" canvas-managed disabled components before registration."); } modLog.LogInfo(val2); return val; } private static int RestoreCanvasBehaviours(Transform source, Transform target, CanvasBehaviourManager manager) { if ((Object)(object)manager == (Object)null) { throw new InvalidOperationException("Native Settings canvas owner is missing."); } int num = 0; Il2CppArrayBase<Behaviour> components = ((Component)source).GetComponents<Behaviour>(); Il2CppArrayBase<Behaviour> components2 = ((Component)target).GetComponents<Behaviour>(); for (int i = 0; i < components.Length; i++) { if (!components[i].enabled && manager.canvasBehaviours.Contains(components[i])) { components2[i].enabled = true; num++; } } for (int j = 0; j < source.childCount; j++) { num += RestoreCanvasBehaviours(source.GetChild(j), target.GetChild(j), manager); } return num; } private static void RegisterRow(GameObject row) { CanvasBehaviourManager val = default(CanvasBehaviourManager); CanvasBehaviourManager.RegisterRuntimeChildren(row, ref val); if ((Object)(object)val == (Object)null) { throw new InvalidOperationException("Native Settings row was not registered with its canvas."); } canvasOwners[((Object)row).GetInstanceID()] = val; } private static void CopyGeometry(Transform source, Transform target) { CopyRect(((Component)source).GetComponent<RectTransform>(), ((Component)target).GetComponent<RectTransform>()); for (int i = 0; i < source.childCount; i++) { CopyGeometry(source.GetChild(i), target.GetChild(i)); } } private static void CopyRect(RectTransform source, RectTransform target) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) ((Transform)target).localScale = ((Transform)source).localScale; ((Transform)target).localRotation = ((Transform)source).localRotation; target.anchorMin = source.anchorMin; target.anchorMax = source.anchorMax; target.pivot = source.pivot; target.sizeDelta = source.sizeDelta; target.anchoredPosition3D = source.anchoredPosition3D; } private static void PlaceRow(GameObject row, GameObject original) { row.transform.SetParent(original.transform.parent, false); CopyRect(original.GetComponent<RectTransform>(), row.GetComponent<RectTransform>()); layoutChecks.Add(new RowCheck { Source = original, Row = row, RowId = ((Object)row).GetInstanceID() }); } internal static void CheckVisibleLayouts() { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_020a: 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) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_0344: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) int num = 0; for (int num2 = layoutChecks.Count - 1; num2 >= 0; num2--) { RowCheck rowCheck = layoutChecks[num2]; if (!((Object)(object)rowCheck.Row != (Object)null)) { canvasOwners.Remove(rowCheck.RowId); layoutChecks.RemoveAt(num2); num++; } } for (int num3 = rows.Count - 1; num3 >= 0; num3--) { if ((Object)(object)rows[num3] == (Object)null) { rows.RemoveAt(num3); } } if (num > 0) { ManualLogSource modLog = Plugin.ModLog; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(82, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Released bookkeeping for "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" destroyed native settings row(s); "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(rows.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" live row(s) retained."); } modLog.LogInfo(val); } foreach (RowCheck layoutCheck in layoutChecks) { if ((Object)(object)layoutCheck.Row == (Object)null || (Object)(object)layoutCheck.Source == (Object)null || !canvasOwners.TryGetValue(((Object)layoutCheck.Row).GetInstanceID(), out CanvasBehaviourManager value) || (Object)(object)value == (Object)null) { continue; } if (!layoutCheck.Row.activeInHierarchy || !value.GetCanvasIsEnabled()) { layoutCheck.VisibleFrame = -1; layoutCheck.Reported = false; continue; } if (layoutCheck.Reported) { continue; } if (layoutCheck.VisibleFrame < 0) { layoutCheck.VisibleFrame = Time.frameCount; } if (Time.frameCount - layoutCheck.VisibleFrame < 5) { continue; } layoutCheck.Reported = true; RectTransform component = layoutCheck.Source.GetComponent<RectTransform>(); RectTransform component2 = layoutCheck.Row.GetComponent<RectTransform>(); RectTransform component3 = ((Component)((Transform)component).GetChild(0)).GetComponent<RectTransform>(); RectTransform component4 = ((Component)((Transform)component2).GetChild(0)).GetComponent<RectTransform>(); Rect rect = component4.rect; float x = ((Transform)component4).TransformPoint(new Vector3(((Rect)(ref rect)).xMin, 0f, 0f)).x; rect = component3.rect; float x2 = ((Transform)component3).TransformPoint(new Vector3(((Rect)(ref rect)).xMin, 0f, 0f)).x; rect = component2.rect; int num4; if (((Rect)(ref rect)).width > 0f) { rect = component2.rect; float width = ((Rect)(ref rect)).width; rect = component.rect; if (Math.Abs(width - ((Rect)(ref rect)).width) < 2f) { rect = component4.rect; if (((Rect)(ref rect)).width > 50f) { num4 = ((Math.Abs(x - x2) < 2f) ? 1 : 0); goto IL_02b4; } } } num4 = 0; goto IL_02b4; IL_02b4: bool flag2 = (byte)num4 != 0; DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(75, 6); defaultInterpolatedStringHandler.AppendLiteral("Native Settings layout "); defaultInterpolatedStringHandler.AppendFormatted(((Object)layoutCheck.Row).name); defaultInterpolatedStringHandler.AppendLiteral(": width="); rect = component2.rect; defaultInterpolatedStringHandler.AppendFormatted(((Rect)(ref rect)).width, "0.0"); defaultInterpolatedStringHandler.AppendLiteral(" native="); rect = component.rect; defaultInterpolatedStringHandler.AppendFormatted(((Rect)(ref rect)).width, "0.0"); defaultInterpolatedStringHandler.AppendLiteral(", labelWidth="); rect = component4.rect; defaultInterpolatedStringHandler.AppendFormatted(((Rect)(ref rect)).width, "0.0"); defaultInterpolatedStringHandler.AppendLiteral(", leftDelta="); defaultInterpolatedStringHandler.AppendFormatted(x - x2, "0.0"); defaultInterpolatedStringHandler.AppendLiteral(", aligned="); defaultInterpolatedStringHandler.AppendFormatted(flag2); defaultInterpolatedStringHandler.AppendLiteral("."); string text = defaultInterpolatedStringHandler.ToStringAndClear(); if (flag2) { Plugin.ModLog.LogInfo((object)text); } else { Plugin.ModLog.LogError((object)text); } } } private static TMP_InputField AddPreciseValue(SliderSettingUI setting) { //IL_0025: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: 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_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0186: 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_0198: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI valueText = setting.valueText; RectTransform rectTransform = ((TMP_Text)valueText).rectTransform; RectTransform val = new GameObject("Exact clock rate").AddComponent<RectTransform>(); ((Transform)val).SetParent(((Transform)rectTransform).parent, false); ((Transform)val).SetSiblingIndex(((Transform)rectTransform).GetSiblingIndex()); val.anchorMin = rectTransform.anchorMin; val.anchorMax = rectTransform.anchorMax; val.pivot = rectTransform.pivot; val.sizeDelta = rectTransform.sizeDelta; val.anchoredPosition = rectTransform.anchoredPosition; LayoutElement component = ((Component)rectTransform).GetComponent<LayoutElement>(); LayoutElement val2 = ((Component)val).gameObject.AddComponent<LayoutElement>(); Rect rect; float minWidth; if (!((Object)(object)component != (Object)null)) { rect = rectTransform.rect; minWidth = ((Rect)(ref rect)).width; } else { minWidth = component.minWidth; } val2.minWidth = minWidth; float preferredWidth; if (!((Object)(object)component != (Object)null)) { rect = rectTransform.rect; preferredWidth = ((Rect)(ref rect)).width; } else { preferredWidth = component.preferredWidth; } val2.preferredWidth = preferredWidth; float minHeight; if (!((Object)(object)component != (Object)null)) { rect = rectTransform.rect; minHeight = ((Rect)(ref rect)).height; } else { minHeight = component.minHeight; } val2.minHeight = minHeight; float preferredHeight; if (!((Object)(object)component != (Object)null)) { rect = rectTransform.rect; preferredHeight = ((Rect)(ref rect)).height; } else { preferredHeight = component.preferredHeight; } val2.preferredHeight = preferredHeight; if ((Object)(object)component != (Object)null) { val2.flexibleWidth = component.flexibleWidth; val2.flexibleHeight = component.flexibleHeight; val2.layoutPriority = component.layoutPriority; } ((Transform)rectTransform).SetParent((Transform)(object)val, false); rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; Vector2 offsetMin = (rectTransform.offsetMax = Vector2.zero); rectTransform.offsetMin = offsetMin; TMP_InputField input = ((Component)val).gameObject.AddComponent<TMP_InputField>(); input.textViewport = val; input.textComponent = (TMP_Text)(object)valueText; ((Selectable)input).targetGraphic = (Graphic)(object)valueText; ((Graphic)valueText).raycastTarget = true; input.contentType = (ContentType)0; input.lineType = (LineType)0; input.characterLimit = 16; input.richText = false; Navigation navigation = ((Selectable)input).navigation; navigation.mode = (Mode)0; ((Selectable)input).navigation = navigation; input.SetTextWithoutNotify(Plugin.Rate.Value.ToString("F1", CultureInfo.InvariantCulture) + "x"); ((UnityEvent<string>)(object)input.onEndEdit).AddListener(UnityAction<string>.op_Implicit((Action<string>)delegate(string value) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown try { if (TimePolicy.TryRate(value.Trim().TrimEnd('x', 'X'), out var value2)) { setting.slider.value = TimePolicy.SnapRate(value2); } input.SetTextWithoutNotify(((SettingUIElement<float>)(object)setting).CurrentChoice.ToString("F1", CultureInfo.InvariantCulture) + "x"); } catch (Exception ex) { ManualLogSource modLog = Plugin.ModLog; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(27, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Unable to edit clock rate: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Exception>(ex); } modLog.LogError(val3); } })); return input; } internal static void Shutdown() { if (deviceChanged != null) { InputSystem.onDeviceChange -= deviceChanged; } deviceChanged = null; controls.Clear(); foreach (GameObject row in rows) { if ((Object)(object)row == (Object)null) { continue; } GameplaySettingsUI componentInParent = row.GetComponentInParent<GameplaySettingsUI>(); if ((Object)(object)componentInParent != (Object)null) { ((SettingsTabPanel)componentInParent)._elements = Il2CppReferenceArray<SettingUIElementBase>.op_Implicit(((IEnumerable<SettingUIElementBase>)((SettingsTabPanel)componentInParent)._elements).Where((SettingUIElementBase e) => (Object)(object)e != (Object)null && (Object)(object)((Component)e).gameObject != (Object)(object)row).ToArray()); } ControlsSettingsUI componentInParent2 = row.GetComponentInParent<ControlsSettingsUI>(); if ((Object)(object)componentInParent2 != (Object)null) { componentInParent2.controls.Remove(row.GetComponent<InputRebindUI>()); } if (canvasOwners.TryGetValue(((Object)row).GetInstanceID(), out CanvasBehaviourManager value) && (Object)(object)value != (Object)null) { CanvasBehaviourManager.UnregisterRuntimeChildren(row.transform, value); } Object.Destroy((Object)(object)row); } rows.Clear(); canvasOwners.Clear(); layoutChecks.Clear(); if (action != null && (Object)(object)owner != (Object)null) { List<InputAction> list = new List<InputAction>(); Enumerator<InputActionMap> enumerator2 = owner.actionMaps.GetEnumerator(); while (enumerator2.MoveNext()) { Enumerator<InputAction> enumerator3 = enumerator2.Current.actions.GetEnumerator(); while (enumerator3.MoveNext()) { InputAction current = enumerator3.Current; if (current.enabled && current != action) { list.Add(current); } } } owner.Disable(); try { InputActionSetupExtensions.RemoveAction(action); } finally { foreach (InputAction item in list) { item.Enable(); } } } if ((Object)(object)reference != (Object)null) { Object.Destroy((Object)(object)reference); } action = null; reference = null; owner = null; } } internal sealed class PhoneDelayClock { private bool initialized; private int lastEnd; private int lastNow; private double elapsed; internal bool Ready(int now, int ended, float rate, float deltaSeconds, bool paused, int nativeDelay, bool dialogueActive = false) { if (dialogueActive) { elapsed = 0.0; initialized = true; lastEnd = ended; lastNow = now; return false; } rate = (float.IsFinite(rate) ? Math.Clamp(rate, 0f, 2f) : 1f); double num = ((rate > 0f) ? rate : 1f); if (!initialized || ended != lastEnd || now < lastNow) { elapsed = Math.Max(0.0, (double)now - (double)ended) / num; initialized = true; } else { double num2 = Math.Max(0.0, (double)now - (double)lastNow); double num3 = ((!paused && float.IsFinite(deltaSeconds)) ? (Math.Max(0f, deltaSeconds) * 60f) : 0f); elapsed += num3; if ((paused && num2 > 0.0) || num2 > Math.Max(2.0, num3 * num + 1.0)) { elapsed += Math.Max(0.0, num2 / num - num3); } } lastEnd = ended; lastNow = now; return elapsed > (double)nativeDelay; } } [HarmonyPatch(typeof(DialogueTreeProgressManager), "Update")] internal static class PhoneDelayPatch { private static nint owner; private static PhoneDelayClock clock = new PhoneDelayClock(); internal static void Clear() { owner = 0; clock = new PhoneDelayClock(); } private static void Prefix(DialogueTreeProgressManager __instance, out int __state) { __state = __instance.phoneCallDelay; if (owner != ((Il2CppObjectBase)__instance).Pointer) { Clear(); owner = ((Il2CppObjectBase)__instance).Pointer; } bool flag = clock.Ready(TimeOfDayManager.TotalGameSeconds, __instance._lastDialogueEndTime, Plugin.Rate.Value, Time.deltaTime, (Object)(object)Singleton<TimeOfDayManager>.Instance == (Object)null || Singleton<TimeOfDayManager>.Instance.IsPaused, __state, __instance.IsInDialogue); if (Plugin.Rate.Value != 1f) { __instance.phoneCallDelay = (flag ? (-1) : int.MaxValue); } } private static void Finalizer(DialogueTreeProgressManager __instance, int __state) { __instance.phoneCallDelay = __state; } } [HarmonyPatch(typeof(DialogueTreeProgressManager), "InitializeInternal")] internal static class ResetPhoneDelayPatch { private static void Postfix() { PhoneDelayPatch.Clear(); } } internal static class PlacementCosts { internal static float Read(int area, bool bound, Func<int, float> agentCost, Func<int, float> worldCost) { if (!bound) { return worldCost(area); } return agentCost(area); } } internal readonly record struct PlacementCapsule(Vector3 Lower, Vector3 Upper, float Radius) { internal PlacementCapsule Offset(Vector3 delta) { return new PlacementCapsule(Lower + delta, Upper + delta, Radius); } internal bool Overlaps(PlacementCapsule other) { float num = Math.Max(0f, Math.Max(other.Lower.Y - Upper.Y, Lower.Y - other.Upper.Y)); float num2 = Lower.X - other.Lower.X; float num3 = Lower.Z - other.Lower.Z; float num4 = Radius + other.Radius + 0.04f; return num2 * num2 + num * num + num3 * num3 < num4 * num4; } } internal sealed class PlacementReservations { private readonly Dictionary<nint, PlacementCapsule> positions = new Dictionary<IntPtr, PlacementCapsule>(); internal void Reserve(nint character, PlacementCapsule volume) { positions[character] = volume; } internal void Release(nint character) { positions.Remove(character); } internal bool Overlaps(PlacementCapsule candidate) { foreach (PlacementCapsule value in positions.Values) { if (candidate.Overlaps(value)) { return true; } } return false; } } internal static class PlacementSearch { internal const float Range = 3.2f; internal static bool CanRetainOrigin(Vector3 origin, Vector3? projected, Func<Vector3, bool> clear) { if (projected.HasValue && (projected.Value - origin).LengthSquared() < 0.0001f) { return clear(origin); } return false; } internal static Vector3? Find(Vector3 origin, Func<Vector3, Vector3?> project, Func<Vector3, bool> clear) { Vector3? result = null; foreach (byte item in FindSteps(origin, project, clear, delegate(Vector3? value) { result = value; })) { _ = item; } return result; } internal static IEnumerable<byte> FindSteps(Vector3 origin, Func<Vector3, Vector3?> project, Func<Vector3, bool> clear, Action<Vector3?> completed) { Vector3? best = null; float score = float.PositiveInfinity; for (int pass = 0; pass < 2; pass++) { if (best.HasValue) { break; } for (int ring = pass; ring <= 8; ring++) { for (int spoke = 0; spoke < ((ring == 0) ? 1 : 16); spoke++) { yield return 0; float x = ((float)spoke + (float)pass * 0.5f) * ((float)Math.PI / 8f); float num = (float)ring * 0.4f - (float)pass * 0.2f; Vector3? vector = project(origin + new Vector3(MathF.Cos(x) * num, 0f, MathF.Sin(x) * num)); if (vector.HasValue) { Vector3 vector2 = vector.Value - origin; float num2 = vector2.LengthSquared(); if (!(MathF.Abs(vector2.Y) > 0.5f) && !(num2 > 10.240001f) && !(num2 >= score) && clear(vector.Value)) { best = vector; score = num2; } } } } } completed(best); } } [BepInPlugin("hvizeu.nivalis.slowdays", "Nivalis Slow Days", "2.0.10")] [BepInProcess("Nivalis Nights.exe")] public sealed class Plugin : BasePlugin { internal static ManualLogSource ModLog; internal static ConfigEntry<float> Rate; internal static ConfigEntry<bool> BalanceArrivals; internal static ConfigEntry<Key> MenuKey; internal static ConfigEntry<string> BindingPath; internal static ConfigEntry<string> GamepadBindingPath; private readonly Harmony harmony = new Harmony("hvizeu.nivalis.slowdays"); public override void Load() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_00a3: 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_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Expected O, but got Unknown ModLog = ((BasePlugin)this).Log; Rate = ((BasePlugin)this).Config.Bind<float>("Time", "ClockRate", 0.3f, new ConfigDescription("Natural clock speed, rounded to tenths: 1 = original, 0.5 = half, 0.1 = tenth, 0 = frozen. Sleep and waiting keep their targets.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); BalanceArrivals = ((BasePlugin)this).Config.Bind<bool>("Balance", "ScaleCustomerArrivals", true, "Stop new restaurant visits while the clock is frozen, except during an explicit wait. At positive rates, native needs, schedules and visit/search cooldowns follow game time once. No sales-history forecast, first-day exemption or daily income cap. Prices, stock consumption, hourly pay and animation speed retain native rules."); MenuKey = ((BasePlugin)this).Config.Bind<Key>("Controls", "TimeMenuKey", (Key)34, "Legacy shortcut, migrated to WaitBinding. Use Settings > Controls to rebind Wait."); BindingPath = ((BasePlugin)this).Config.Bind<string>("Controls", "WaitBinding", "<Keyboard>/" + ((object)MenuKey.Value/*cast due to .constrained prefix*/).ToString().ToLowerInvariant(), "Wait shortcut, managed by the native Settings > Controls rebinding row."); GamepadBindingPath = ((BasePlugin)this).Config.Bind<string>("Controls", "WaitGamepadBinding", "<Gamepad>/leftTrigger", "Controller Wait shortcut (default LT/L2). Rebind WAIT in Settings > Controls while using a controller."); float num = TimePolicy.SnapRate(Rate.Value); if (Rate.Value != num) { Rate.Value = num; ((BasePlugin)this).Config.Save(); } try { harmony.PatchAll(typeof(Plugin).Assembly); ((BasePlugin)this).AddComponent<TimeController>(); } catch { harmony.UnpatchSelf(); throw; } ManualLogSource log = ((BasePlugin)this).Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(266, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Better Time 2.0.10 loaded (Steam build 25680465 bindings). Clock rate "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(Rate.Value, "F1"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; balanced customer arrivals="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(BalanceArrivals.Value); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; Wait binding "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(BindingPath.Value); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; controller Wait binding "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(GamepadBindingPath.Value); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". Native needs and visit/search cooldowns follow game time once. No additional admission multiplier or sales-history forecast."); } log.LogInfo(val); } public override bool Unload() { TimeController? current = TimeController.Current; if ((current != null && current.Busy) || HourlyWork.Pending) { return false; } TimeController.Current?.Shutdown(); NativeSettings.Shutdown(); PhoneDelayPatch.Clear(); harmony.UnpatchSelf(); return true; } } [HarmonyPatch(typeof(TimeOfDayManager), "Update")] internal static class ClockUpdatePatch { internal struct TickState { public float Original; public bool Applied; } [HarmonyPrefix] private static void Prefix(TimeOfDayManager __instance, out TickState __state) { __state = new TickState { Original = __instance.timeTickMultiplier }; float value = Plugin.Rate.Value; __instance.timeTickMultiplier = __state.Original * (float.IsFinite(value) ? Math.Clamp(value, 0f, 2f) : 1f); __state.Applied = true; } [HarmonyFinalizer] private static void Finalizer(TimeOfDayManager __instance, TickState __state) { if (__state.Applied) { __instance.timeTickMultiplier = __state.Original; } } } [HarmonyPatch(typeof(VenueManager), "OnHourTick")] internal static class HourlyPatch { [HarmonyPrefix] private static bool Prefix(VenueManager __instance) { return !HourlyWork.Start(__instance); } } [HarmonyPatch(typeof(GameplaySettingsUI), "BeforeDisplay")] internal static class SettingsEntryPatch { [HarmonyPostfix] private static void Postfix(GameplaySettingsUI __instance) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown try { NativeSettings.Attach(__instance); } catch (Exception ex) { ManualLogSource modLog = Plugin.ModLog; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(43, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Unable to add Slow Days gameplay settings: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } modLog.LogError(val); } } } [HarmonyPatch(typeof(ControlsSettingsUI), "Start")] internal static class ControlsEntryPatch { [HarmonyPostfix] private static void Postfix(ControlsSettingsUI __instance) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown try { NativeSettings.Attach(__instance); } catch (Exception ex) { ManualLogSource modLog = Plugin.ModLog; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(35, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Unable to add native Wait binding: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } modLog.LogError(val); } } } [HarmonyPatch(typeof(PlayerInputManager), "LoadBindings")] internal static class RestoreWaitBindingPatch { [HarmonyPrefix] private static void Prefix(PlayerInputManagerSave save) { WaitBindingPersistencePatch.RemoveOwnOverride(save); } [HarmonyPostfix] private static void Postfix() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown try { NativeSettings.RestoreBinding(); } catch (Exception ex) { ManualLogSource modLog = Plugin.ModLog; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(49, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Unable to restore Wait shortcut after save load: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } modLog.LogError(val); } } } [HarmonyPatch(typeof(InputRebindUI), "UpdateText")] internal static class WaitBindingLabelPatch { [HarmonyPrefix] private static bool Prefix(InputRebindUI __instance) { if (((Object)((Component)__instance).gameObject).name != "Hvizeu.Wait") { return true; } ((TMP_Text)__instance.actionText).text = "WAIT"; return false; } } [HarmonyPatch(typeof(PlayerInputManager), "InitializeInternal")] internal static class RegisterWaitInputPatch { [HarmonyPrefix] private static void Prefix(ISavePacket packet) { if (packet != null) { WaitBindingPersistencePatch.RemoveOwnOverride(((Il2CppObjectBase)packet).TryCast<PlayerInputManagerSave>()); } } [HarmonyPostfix] private static void Postfix(PlayerInputManager __instance) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown try { NativeSettings.InitializeInput(__instance); } catch (Exception ex) { ManualLogSource modLog = Plugin.ModLog; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(94, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Wait input registration failed; vanilla input was left enabled/disabled as owned by the game: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } modLog.LogError(val); } } } [HarmonyPatch(typeof(PlayerInputManager), "SaveBindings")] internal static class WaitBindingPersistencePatch { [HarmonyPostfix] private static void Postfix(PlayerInputManagerSave save) { NativeSettings.SaveBinding(); RemoveOwnOverride(save); } internal static void RemoveOwnOverride(PlayerInputManagerSave? save) { if (save != null) { string bindingJsonString = save.BindingJsonString; string text = BindingJson.WithoutWait(bindingJsonString); if (!(text == bindingJsonString)) { save.BindingJsonString = text; Plugin.ModLog.LogInfo((object)"Kept Wait override in mod config; removed its entry from native binding packet. Other bindings retained."); } } } } [HarmonyPatch(typeof(Debug), "LogException", new Type[] { typeof(Exception) })] internal static class ObserveWaitNativeException { [HarmonyPrefix] private static void Prefix(Exception exception) { if (WaitFaults.Active) { WaitFaults.ObserveException(((exception != null) ? ((Object)exception).ToString() : null) ?? "Native exception", "Unity Debug.LogException"); } } } public sealed class TimeController : MonoBehaviour { internal static TimeController? Current; private TimeMenu? menu; private AgentGhostSimulator? simulator; private WaitPacer? pacer; private WaitCrowdRefresh? crowdRefresh; private string? completionMessage; private float handoffStarted; private IEnumerator<byte>? presentationSteps; private bool closeAfterHandoff; private float nextSettingsCheck; private float nextHudCheck; private int simulationTicks; private float waitStarted; private bool quitting; private readonly List<OverrideLock> locks = new List<OverrideLock>(); private OverrideLock? saveLock; private bool busy; private bool cancel; private bool enabledMod = true; private bool reopenPlayerMenu; private bool uiFailed; private int openedFrame; private int start; private int target; private int expectedTime; private int faultSequence; private float lastRefresh; private float taskStarted; private WaitLedger before; private string status = "Choose your pace. Stay until the city closes."; [HideFromIl2Cpp] internal bool Busy => busy; public TimeController(IntPtr pointer) : base(pointer) { } public void Awake() { Current = this; } [HideFromIl2Cpp] internal static bool GameplayReady() { if (Singleton<GameSceneManager>.InstanceExist() && Singleton<GameSceneManager>.Instance.IsGame && Singleton<GameSceneManager>.Instance.IsGameplayInitialized && !Singleton<GameSceneManager>.Instance.IsLoading && !GameSceneManager.IsUnloadingGameplay && Singleton<TimeOfDayManager>.InstanceExist() && Singleton<PlayerManager>.InstanceExist()) { Player localPlayer = Singleton<PlayerManager>.Instance.LocalPlayer; if ((Object)(object)((localPlayer != null) ? localPlayer.Character : null) != (Object)null) { if (Singleton<ManagersBootstrap>.InstanceExist()) { return !Singleton<ManagersBootstrap>.Instance.IsLoadingSaveFile; } return true; } } return false; } [HideFromIl2Cpp] private static string? BlockReason() { if (HourlyWork.NeedsUnpausedDrain) { return "The previous venue update is recovering. Return to gameplay briefly."; } if (!GameplayReady()) { return "Load a save and return to normal gameplay."; } if (Singleton<DialogueTreeProgressManager>.InstanceExist() && Singleton<DialogueTreeProgressManager>.Instance.IsInDialogue) { return "Finish the conversation first."; } Player localPlayer = Singleton<PlayerManager>.Instance.LocalPlayer; if (localPlayer.IsHoldingObject) { return "Put down the object you are carrying first."; } if ((Object)(object)localPlayer.Character.DrivenBoat != (Object)null) { return "Leave your vehicle before waiting."; } if (!Singleton<VenueManager>.InstanceExist() || !Singleton<VenueManager>.Instance.RuntimeVenueDataIsInitialized) { return "The city's businesses are still loading."; } return null; } public void Update() { if (!enabledMod) { return; } HourlyWork.Poll(); try { if (GameSceneManager.IsUnloadingGameplay || (Singleton<GameSceneManager>.InstanceExist() && Singleton<GameSceneManager>.Instance.IsLoading) || (Singleton<ManagersBootstrap>.InstanceExist() && Singleton<ManagersBootstrap>.Instance.IsLoadingSaveFile)) { if (menu != null) { CloseForSceneChange(); } return; } if (Time.unscaledTime >= nextSettingsCheck) { nextSettingsCheck = Time.unscaledTime + 0.25f; NativeSettings.SaveBinding(); NativeSettings.CheckVisibleLayouts(); } if (menu == null && !uiFailed && Time.unscaledTime >= nextHudCheck) { nextHudCheck = Time.unscaledTime + 0.5f; if (GameplayReady()) { WorldStateDisplayUI val = Object.FindObjectOfType<WorldStateDisplayUI>(); if ((Object)(object)val != (Object)null) { AttachMenu(val); } } } if (menu == null) { return; } if (busy) { TickWait(); } if (Application.isFocused && Time.frameCount > openedFrame + 1) { if (menu.Visible) { Keyboard current = Keyboard.current; if ((current != null && ((ButtonControl)current.escapeKey).wasPressedThisFrame) || Singleton<PlayerInputManager>.Instance.Input.MenuControls.Cancel.WasPressedThisFrame()) { if (busy) { cancel = true; } else { Close(); } } else if (!menu.Editing && NativeSettings.Pressed) { if (busy) { cancel = true; } else { Close(); } } } else if (NativeSettings.Pressed && GameplayReady() && !Singleton<PlayerInputManager>.Instance.PreventGameplayMenuShortcuts.Value && !Singleton<PlayerInputManager>.Instance.PreventAllMenuShortcuts.Value && Singleton<PlayerManager>.Instance.LocalPlayer.Character.Controller.CanMove && !Singleton<TimeOfDayManager>.Instance.IsPaused) { Open(fromPlayerMenu: false); } } if (menu.Visible) { menu.EnsureControllerSelection(); if (Time.unscaledTime - lastRefresh > 0.15f) { Refresh(); } } } catch (Exception ex) { Fail(ex); } } [HideFromIl2Cpp] internal void Fail(Exception ex) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown ManualLogSource modLog = Plugin.ModLog; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(19, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Time & Wait error: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } modLog.LogError(val); cancel = true; if (HourlyWork.NeedsUnpausedDrain) { closeAfterHandoff = true; reopenPlayerMenu = false; } if (!busy) { status = "Waiting stopped after an error. Progress is retained; see the BepInEx log."; if (closeAfterHandoff) { closeAfterHandoff = false; Close(); } Refresh(); } else if (HourlyWork.Pending && !HourlyWork.NeedsUnpausedDrain) { status = "An error occurred. Finishing the active venue update before stopping."; } else if (completionMessage == null) { Finish("Waiting stopped after an error. Progress is retained; see the BepInEx log."); } else if (presentationSteps == null) { BeginHandoff(); } else { presentationSteps.Dispose(); presentationSteps = null; WaitPresentation.Abandon(); FinishImmediate("Waiting stopped after an error. Progress is retained; see the BepInEx log."); } } [HideFromIl2Cpp] internal void AttachMenu(WorldStateDisplayUI hud) { if (uiFailed) { return; } try { if (menu == null) { menu = new TimeMenu(this, hud); } } catch { uiFailed = true; throw; } } [HideFromIl2Cpp] internal void Open(bool fromPlayerMenu) { if (menu == null || menu.Visible) { return; } string text = BlockReason(); if (text != null) { Plugin.ModLog.LogInfo((object)text); return; } reopenPlayerMenu = fromPlayerMenu; if (fromPlayerMenu) { ((UIPanel)InGameMenuUi.Instance).Hide(); } try { locks.Add(Singleton<PlayerInputManager>.Instance.PreventAllMenuShortcuts.Override((Object)(object)this)); PlayerCharacter character = Singleton<PlayerManager>.Instance.LocalPlayer.Character; locks.Add(TimeOfDayManager.Pause((Object)(object)this)); locks.Add(character.Controller.DisableMovement((Object)(object)this)); locks.Add(character.Controller.LockCamera((Object)(object)this)); locks.Add(character.Interaction.DisableInteractions((Object)(object)this)); openedFrame = Time.frameCount; menu.Show(); status = (TimePolicy.InCurfew(TimeOfDayManager.TotalGameSeconds) ? "Curfew is in effect. Go to bed and sleep; waiting resumes at 08:00." : ((Plugin.Rate.Value == 0f) ? "Clock frozen: waiting simulates at normal speed." : "Businesses continue serving customers while you wait.")); Refresh(); } catch { Close(); throw; } } [HideFromIl2Cpp] internal void Close() { if (busy) { cancel = true; return; } openedFrame = Time.frameCount; menu?.Hide(); ReleaseLocks(); if (reopenPlayerMenu && GameplayReady() && (Object)(object)InGameMenuUi.Instance != (Object)null) { ((UIWindow)InGameMenuUi.Instance).Reopen(); } reopenPlayerMenu = false; } [HideFromIl2Cpp] private void ReleaseLocks() { OverrideLock? obj = saveLock; if (obj != null) { obj.Release(); } saveLock = null; foreach (OverrideLock @lock in locks) { if (!@lock.IsReleased) { @lock.Release(); } } locks.Clear(); } [HideFromIl2Cpp] internal void BeginWait() { //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Expected O, but got Unknown if (busy || menu == null) { return; } string text = BlockReason(); if (text != null) { status = text; Refresh(); return; } if (!double.TryParse(menu.HoursText.Replace(',', '.'), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var result) || !double.IsFinite(result) || result <= 0.0 || result > 24.0) { status = "Enter a duration greater than 0 and no more than 24 hours."; Refresh(); return; } start = TimeOfDayManager.TotalGameSeconds; target = TimePolicy.Target(start, result); if (target <= start) { status = (TimePolicy.InCurfew(start) ? "Waiting is unavailable during curfew (02:00-08:00). Go to bed and sleep." : "Choose a duration of at least one game second."); Refresh(); return; } simulator = Object.FindObjectOfType<AgentGhostSimulator>(); if ((Object)(object)simulator == (Object)null || !simulator._isInitialized) { status = "The customer simulation is not ready. Return to gameplay and try again."; Refresh(); return; } if (!((IEnumerable<GhostSimulator>)simulator.simulators).Any((GhostSimulator x) => (Object)(object)((Il2CppObjectBase)x).TryCast<AgentViewSimulator>() != (Object)null) || !((IEnumerable<GhostSimulator>)simulator.simulators).Any((GhostSimulator x) => (Object)(object)((Il2CppObjectBase)x).TryCast<AgentStateUpdateSimulator>() != (Object)null)) { status = "Required native movement/needs simulators are unavailable. Waiting was not started."; Refresh(); return; } TimeStamp lastRecordedTime = simulator._lastRecordedTime; if (((TimeStamp)(ref lastRecordedTime)).TotalGameSeconds != start) { status = "The city clock is synchronising. Return to gameplay briefly and try again."; Refresh(); return; } pacer = new WaitPacer(Singleton<TimeOfDayManager>.Instance.timeTickMultiplier, Plugin.Rate.Value); saveLock = Singleton<PlayerInputManager>.Instance.PreventSaving.Override((Object)(object)this); before = WaitLedger.Read(); completionMessage = null; closeAfterHandoff = false; simulationTicks = 0; waitStarted = Time.unscaledTime; expectedTime = start; faultSequence = HourlyWork.FaultSequence; cancel = false; busy = true; WaitSimulation.DrainLifecycle(); WaitPresentation.Begin(); taskStarted = Time.unscaledTime; ManualLogSource modLog = Plugin.ModLog; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(270, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Wait started: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(start); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" -> "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(target); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; natural clock rate="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(Plugin.Rate.Value); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; native baseline="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(Singleton<TimeOfDayManager>.Instance.timeTickMultiplier); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; <=5 game-second and <=0.25 action-second steps; actions and loaded commands honor positive clock rate (0 uses 1x); needs/offscreen movement use game seconds / 60. Native menu selection and transactions retained."); } modLog.LogInfo(val); Refresh(); } [HideFromIl2Cpp] private void TickWait() { if (completionMessage != null) { if (presentationSteps != null) { long timestamp = Stopwatch.GetTimestamp(); for (int i = 0; i < 128; i++) { if (!presentationSteps.MoveNext()) { presentationSteps.Dispose(); presentationSteps = null; FinishImmediate(completionMessage); break; } if ((double)(Stopwatch.GetTimestamp() - timestamp) / (double)Stopwatch.Frequency >= 0.004) { break; } } } else if (crowdRefresh.Poll()) { BeginHandoff(); } else if (Time.unscaledTime - handoffStarted > 30f) { throw new TimeoutException("Arrival crowd refresh did not finish within 30 seconds. See native logs; no further time was advanced."); } return; } if (HourlyWork.NeedsUnpausedDrain) { closeAfterHandoff = true; reopenPlayerMenu = false; Finish("Waiting stopped so the active venue update can recover in normal gameplay. See the BepInEx log."); return; } if (HourlyWork.Pending) { status = ((Time.unscaledTime - taskStarted > 30f) ? "A venue update is taking longer than expected. Waiting is paused; Cancel stops after it finishes." : HourlyWork.ProgressText); return; } if (HourlyWork.FaultSequence != faultSequence) { Finish("A venue update failed. Waiting stopped; see the BepInEx log."); return; } if (cancel) { Finish("Waiting cancelled. Time already passed is retained."); return; } string text = BlockReason(); if (text != null) { Finish(text); return; } int totalGameSeconds = TimeOfDayManager.TotalGameSeconds; if (totalGameSeconds != expectedTime) { Finish("Another game event changed the clock. Waiting stopped."); return; } if (totalGameSeconds >= target) { Finish(TimePolicy.InCurfew(totalGameSeconds) ? "Curfew has begun. Go to bed and sleep." : "Wait complete."); return; } if ((Object)(object)simulator == (Object)null || !simulator._isInitialized) { Finish("Customer simulation became unavailable. Waiting stopped."); return; } long timestamp2 = Stopwatch.GetTimestamp(); for (int j = 0; j < 512; j++) { (float, int, float) tuple = pacer.Next(totalGameSeconds, target); expectedTime = checked(totalGameSeconds + tuple.Item2); WaitSimulation.Advance(simulator, Singleton<TimeOfDayManager>.Instance, tuple.Item1, tuple.Item2, tuple.Item3); simulationTicks++; totalGameSeconds = TimeOfDayManager.TotalGameSeconds; if (totalGameSeconds != expectedTime) { Finish("Another game event changed the clock. Waiting stopped."); return; } if (totalGameSeconds >= target || HourlyWork.Pending || HourlyWork.FaultSequence != faultSequence || (double)(Stopwatch.GetTimestamp() - timestamp2) / (double)Stopwatch.Frequency >= 0.024) { break; } } taskStarted = Time.unscaledTime; status = "Waiting " + TimePolicy.Clock(totalGameSeconds) + " > " + TimePolicy.Clock(target); } [HideFromIl2Cpp] private void Finish(string message) { if (!busy || !GameplayReady()) { FinishImmediate(message); } else if (completionMessage == null) { completionMessage = message; crowdRefresh = new WaitCrowdRefresh(); handoffStarted = Time.unscaledTime; status = "Updating the city for your arrival..."; Refresh(); } } [HideFromIl2Cpp] private void BeginHandoff() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown crowdRefresh?.Abandon(); crowdRefresh = null; try { if ((Object)(object)simulator != (Object)null && simulator._isInitialized) { WaitSimulation.SyncViews(simulator); } } catch (Exception ex) { ManualLogSource modLog = Plugin.ModLog; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(63, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Wait view synchronization failed; recovering NPC presentation: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } modLog.LogError(val); completionMessage = "Waiting stopped after a view synchronization error. See the BepInEx log."; } presentationSteps = WaitPresentation.ResumeSteps().GetEnumerator(); status = "Restoring character positions and animations..."; } [HideFromIl2Cpp] private void FinishImmediate(string message) { //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Expected O, but got Unknown crowdRefresh?.Abandon(); crowdRefresh = null; completionMessage = null; bool flag = busy; busy = false; cancel = false; OverrideLock? obj = saveLock; if (obj != null) { obj.Release(); } saveLock = null; status = message; try { if (flag && GameplayReady()) { WaitLedger waitLedger = WaitLedger.Read().Since(before); status += $"\nCash in: {StringHelper.PriceToString(waitLedger.Gain, false)} Out: {StringHelper.PriceToString(checked(-waitLedger.Loss), false)} Net: {StringHelper.PriceToString(waitLedger.NetCash, true)}\nMeals: {waitLedger.Meals} Visits: {waitLedger.Visits}. Stock costs excluded; not profit."; ManualLogSource modLog = Plugin.ModLog; bool flag2 = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(256, 14, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(message); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" Clock="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(TimeOfDayManager.TotalGameSeconds); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; meals="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(waitLedger.Meals); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; visits="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(waitLedger.Visits); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; income="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(waitLedger.Gain); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; expenses="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(waitLedger.Loss); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; mealSales="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(waitLedger.MealSales); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; shopping="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(waitLedger.Shopping); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; staffPay="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(waitLedger.StaffPay); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; otherIncome="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(waitLedger.OtherIncome); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; otherExpenses="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(waitLedger.OtherExpenses); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; netCash="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(waitLedger.NetCash); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; actionTicks="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(simulationTicks); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; wallSeconds="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(Time.unscaledTime - waitStarted, "F2"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". Amounts are cents; shopping includes all shop purchases; net cash is not profit or ingredient cost of sales."); } modLog.LogInfo(val); } else if (flag) { WaitPresentation.Abandon(); } } finally { if (closeAfterHandoff) { closeAfterHandoff = false; Close(); } } Refresh(); } [HideFromIl2Cpp] private void Refresh() { lastRefresh = Time.unscaledTime; menu?.Refresh(status, busy, start, target); } [HideFromIl2Cpp] private void CloseForSceneChange() { presentationSteps?.Dispose(); presentationSteps = null; closeAfterHandoff = false; crowdRefresh?.Abandon(); crowdRefresh = null; completionMessage = null; WaitPresentation.Abandon(); if (busy) { Plugin.ModLog.LogWarning((object)"Scene transition interrupted waiting; no additional time will be advanced."); } busy = false; cancel = false; reopenPlayerMenu = false; uiFailed = false; menu?.Dispose(); menu = null; simulator = null; ReleaseLocks(); } [HideFromIl2Cpp] internal void Shutdown() { CloseForSceneChange(); enabledMod = false; Current = null; } public void OnApplicationQuit() { quitting = true; } public void OnDestroy() { if (!((Object)(object)Current != (Object)(object)this)) { if (quitting) { Current = null; } else { Shutdown(); } } } } internal sealed class TimeMenu : IDisposable { private readonly TimeController controller; private readonly WorldStateDisplayUI source; private readonly GameObject root; private readonly UIPanel panel; private readonly TextMeshProUGUI textStyle; private readonly TMP_InputField hours; private readonly TextMeshProUGUI destination; private readonly TextMeshProUGUI available; private readonly TextMeshProUGUI status; private readonly TextMeshProUGUI progress; private readonly TextMeshProUGUI waitLabel; private readonly TextMeshProUGUI hudTime; private readonly TextMeshProUGUI hudDay; private readonly TextMeshProUGUI hudMoney; private readonly RectTransform hourHand; private readonly RectTransform minuteHand; private readonly Button wait; private readonly Button minus; private readonly Button plus; private readonly Button close; private GameObject? previousSelection; private int shownFrame; private readonly Texture2D clockTexture; private readonly Sprite clockSprite; private readonly Sprite? panelSprite; private readonly Sprite? buttonSprite; private readonly Sprite? outlineSprite; private readonly Image nativeFrame; private readonly Image dimmer; private readonly Image progressFill; private readonly List<(TextMeshProUGUI Source, TextMeshProUGUI Copy)> hudLabels = new List<(TextMeshProUGUI, TextMeshProUGUI)>(); private bool disposed; private static readonly Color Amber = new Color(0.82f, 0.67f, 0.43f, 1f); private static readonly Color Blue = new Color(0.32f, 0.61f, 0.87f, 1f); private static readonly Color Muted = new Color(0.63f, 0.61f, 0.57f, 1f); internal bool Visible { get { if (!disposed) { return panel.IsVisible; } return false; } } internal bool Editing => hours.isFocused; internal string HoursText => hours.text; internal TimeMenu(TimeController controller, WorldStateDisplayUI source) { //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Expected O, but got Unknown //IL_01cc: 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_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_0345: Unknown result type (might be due to invalid IL or missing references) //IL_03ad: Unknown result type (might be due to invalid IL or missing references) //IL_0411: Unknown result type (might be due to invalid IL or missing references) //IL_0548: Unknown result type (might be due to invalid IL or missing references) //IL_0601: Unknown result type (might be due to invalid IL or missing references) //IL_0646: Unknown result type (might be due to invalid IL or missing references) //IL_0673: Unknown result type (might be due to invalid IL or missing references) //IL_06a3: Unknown result type (might be due to invalid IL or missing references) //IL_06c9: Unknown result type (might be due to invalid IL or missing references) //IL_070a: Unknown result type (might be due to invalid IL or missing references) //IL_0714: Expected O, but got Unknown //IL_078a: Unknown result type (might be due to invalid IL or missing references) //IL_0799: Unknown result type (might be due to invalid IL or missing references) //IL_07e1: Unknown result type (might be due to invalid IL or missing references) //IL_0816: Unknown result type (might be due to invalid IL or missing references) //IL_0845: Unknown result type (might be due to invalid IL or missing references) //IL_0864: Unknown result type (might be due to invalid IL or missing references) //IL_0896: Unknown result type (might be due to invalid IL or missing references) //IL_08c7: Unknown result type (might be due to invalid IL or missing references) //IL_0900: Unknown result type (might be due to invalid IL or missing references) //IL_0935: Unknown result type (might be due to invalid IL or missing references) //IL_0964: Unknown result type (might be due to invalid IL or missing references) //IL_0969: Unknown result type (might be due to invalid IL or missing references) //IL_096a: Unknown result type (might be due to invalid IL or missing references) //IL_0971: Unknown result type (might be due to invalid IL or missing references) //IL_098d: Unknown result type (might be due to invalid IL or missing references) //IL_09ac: Unknown result type (might be due to invalid IL or missing references) //IL_0b0e: Unknown result type (might be due to invalid IL or missing references) TimeMenu timeMenu = this; this.controller = controller; this.source = source; textStyle = source.dayTMP; nativeFrame = ((Component)((Component)source).transform.Find("NavigationGraphic")).GetComponent<Image>(); Il2CppArrayBase<Sprite> obj = Resources.FindObjectsOfTypeAll<Sprite>(); Dictionary<string, Sprite> art = new Dictionary<string, Sprite>(StringComparer.Ordinal); foreach (Sprite item in obj) { if (!((Object)(object)item == (Object)null)) { string name = ((Object)item).name; bool flag; switch (name) { case "9S_HUD_Panel": case "9S_ButtonResponse": case "9S_Square-2-Outline": case "9s_PopupFrame": case "9S_TitleFrame_Filled": flag = true; break; default: flag = false; break; } if (flag) { art.TryAdd(name, item); } if (art.Count == 5) { break; } } } panelSprite = Art("9S_HUD_Panel"); buttonSprite = Art("9S_ButtonResponse"); outlineSprite = Art("9S_Square-2-Outline"); root = new GameObject("Hvizeu.Wait"); root.SetActive(false); Object.DontDestroyOnLoad((Object)(object)root); try { Canvas obj2 = root.AddComponent<Canvas>(); obj2.renderMode = (RenderMode)0; obj2.sortingOrder = 30000; CanvasScaler obj3 = root.AddComponent<CanvasScaler>(); obj3.uiScaleMode = (ScaleMode)1; obj3.referenceResolution = new Vector2(1920f, 1080f); obj3.screenMatchMode = (ScreenMatchMode)1; root.AddComponent<GraphicRaycaster>(); CanvasGroup canvasGroup = root.AddComponent<CanvasGroup>(); panel = root.AddComponent<UIPanel>(); panel._canvasGroup = canvasGroup; panel._startVisible = false; panel.requiresMouse = true; UIPanel obj4 = panel; bool flag = (panel.pauseTimeCompletely = true); obj4.pauseTimeWhenOpen = flag; UIPanel obj5 = panel; flag = (panel.closeWithPause = false); obj5.closeWithCancel = flag; dimmer = Box(root.transform, "Dimmer", 0f, 0f, 1920f, 1080f, new Color(0f, 0f, 0f, 0.55f)); ((Graphic)dimmer).rectTransform.anchorMin = Vector2.zero; ((Graphic)dimmer).rectTransform.anchorMax = Vector2.one; RectTransform rectTransform = ((Graphic)dimmer).rectTransform; Vector2 offsetMin = (((Graphic)dimmer).rectTransform.offsetMax = Vector2.zero); rectTransform.offsetMin = offsetMin; RectTransform parent = Rect(root.transform, "Wait composition", 0f, 0f, 1080f, 720f); Image obj6 = Box((Transform)(object)parent, "Native popup frame", 0f, 0f, 1080f, 720f, Color.white); obj6.sprite = Art("9s_PopupFrame") ?? panelSprite ?? nativeFrame.sprite; obj6.type = (Type)1; obj6.pixelsPerUnitMultiplier = 2f; ((Graphic)obj6).raycastTarget = false; Image val = Box((Transform)(object)parent, "Native title frame", 0f, 305f, 670f, 102f, Color.white); val.sprite = Art("9S_TitleFrame_Filled") ?? nativeFrame.sprite; val.preserveAspect = true; ((Graphic)val).raycastTarget = false; Label(((Component)val).transform, "WAIT", 0f, 4f, 520f, 48f, 30f, Amber); RectTransform parent2 = Rect((Transform)(object)parent, "Native world state strip", 0f, -20f, 800f, 160f); string[] array = new string[5] { "NavigationGraphic", "TimeDisplay", "MoneyWrapper", "Date", "TimerIcon" }; foreach (string text in array) { CopyVisualTree(((Il2CppObjectBase)((Component)source).transform.Find(text)).Cast<RectTransform>(), (Transform)(object)parent2); } hudTime = hudLabels.Single<(TextMeshProUGUI, TextMeshProUGUI)>(((TextMeshProUGUI Source, TextMeshProUGUI Copy) x) => (Object)(object)x.Source == (Object)(object)source.timeTMP).Item2; hudDay = hudLabels.Single<(TextMeshProUGUI, TextMeshProUGUI)>(((TextMeshProUGUI Source, TextMeshProUGUI Copy) x) => (Object)(object)x.Source == (Object)(object)source.dayTMP).Item2; hudMoney = hudLabels.Single<(TextMeshProUGUI, TextMeshProUGUI)>(((TextMeshProUGUI Source, TextMeshProUGUI Copy) x) => (Object)(object)x.Source == (Object)(object)source.moneyDisplay.valueText).Item2; RectTransform parent3 = Wing((Transform)(object)parent, "Duration", -300f, 115f); Label((Transform)(object)parent3, "WAIT FOR", 0f, 49f, 210f, 30f, 21f, Amber); hours = Field((Transform)(object)parent3, 0f, -5f, 110f, 58f, "1"); minus = Button((Transform)(object)parent3, "-", -94f, -5f, 52f, 52f, delegate { timeMenu.Adjust(-0.25); }); plus = Button((Transform)(object)parent3, "+", 94f, -5f, 52f, 52f, delegate { timeMenu.Adjust(0.25); }); Label((Transform)(object)parent3, "HOURS", 0f, -51f, 210f, 25f, 19f, Muted); RectTransform parent4 = Wing((Transform)(object)parent, "Arrival", 300f, 115f); Label((Transform)(object)parent4, "ARRIVE AT", 0f, 49f, 210f, 30f, 21f, Amber); destination = Label((Transform)(object)parent4, "--:--", 0f, -5f, 220f, 64f, 48f, Blue); Label((Transform)(object)parent4, "CURFEW 02:00 - 08:00", 0f, -51f, 232f, 28f, 17f, Muted); Image val2 = Box((Transform)(object)parent, "Clock face", 0f, 132f, 240f, 240f, Color.white); using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("NivalisSlowDays.Assets.clock-face.png") ?? throw new InvalidOperationException("Embedded clock art is missing.")) { using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); clockTexture = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(clockTexture, Il2CppStructArray<byte>.op_Implicit(memoryStream.ToArray()), false)) { throw new InvalidOperationException("Clock art could not be decoded."); } } ((Texture)clockTexture).filterMode = (FilterMode)1; clockSprite = Sprite.Create(clockTexture, new Rect(0f, 0f, (float)((Texture)clockTexture).width, (float)((Texture)clockTexture).height), new Vector2(0.5f, 0.5f), 100f); val2.sprite = clockSprite; val2.preserveAspect = true; ((Graphic)val2).raycastTarget = false; hourHand = Hand(((Component)val2).transform, "Hour hand", 6f, 58f, Amber); minuteHand = Hand(((Component)val2).transform, "Minute hand", 3f, 82f, new Color(0.85f, 0.84f, 0.79f)); Image obj7 = Box(((Component)val2).transform, "Hub", 0f, 0f, 10f, 10f, Amber); ((Transform)((Graphic)obj7).rectTransform).lo