Decompiled source of Sandevistan v1.0.0
plugins/Sandevistan.dll
Decompiled 17 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Audio; using UnityEngine.InputSystem; using UnityEngine.Rendering; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("Sandevistan")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Sandevistan")] [assembly: AssemblyTitle("Sandevistan")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SandevistanMod { [BepInPlugin("breenihilation.ultrakill.sandevistan", "Sandevistan", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "breenihilation.ultrakill.sandevistan"; public const string PluginName = "Sandevistan"; public const string PluginVersion = "1.0.0"; private const string ConfiggyPluginGuid = "Hydraxous.ULTRAKILL.Configgy"; private Harmony _harmony; private static GameObject _runtimeObject; private static SandevistanRuntime _runtime; private static object _configgyBuilder; public static Plugin Instance { get; private set; } public static ManualLogSource ModLog { get; private set; } public static ConfigEntry<KeyCode> ActivationKey { get; private set; } public static ConfigEntry<float> SlowScale { get; private set; } public static ConfigEntry<bool> SlowPlayerFalling { get; private set; } public static ConfigEntry<bool> SoundEffects { get; private set; } public static ConfigEntry<float> SoundVolume { get; private set; } public static ConfigEntry<float> WorldAudioPitch { get; private set; } public static ConfigEntry<bool> ScreenEffects { get; private set; } public static ConfigEntry<bool> PlayerAfterimages { get; private set; } public static ConfigEntry<float> AfterimageInterval { get; private set; } public static ConfigEntry<float> AfterimageForwardOffset { get; private set; } public static ConfigEntry<float> AfterimageRightOffset { get; private set; } public static ConfigEntry<float> AfterimageVerticalOffset { get; private set; } public static ConfigEntry<float> AfterimageScale { get; private set; } public static ConfigEntry<bool> HideCloseAfterimages { get; private set; } public void Awake() { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Expected O, but got Unknown //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Expected O, but got Unknown //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Expected O, but got Unknown //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Expected O, but got Unknown //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Expected O, but got Unknown //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Expected O, but got Unknown //IL_03e9: Unknown result type (might be due to invalid IL or missing references) //IL_03f3: Expected O, but got Unknown Instance = this; ModLog = ((BaseUnityPlugin)this).Logger; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); ActivationKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Input", "ActivationKey", (KeyCode)118, "Hotkey for sandevistan toggle."); SlowScale = ((BaseUnityPlugin)this).Config.Bind<float>("Sandevistan", "WorldTimeScale", 0.05f, new ConfigDescription("World speed while active. 0.05 is a 95% slowdown.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.02f, 0.8f), Array.Empty<object>())); SlowPlayerFalling = ((BaseUnityPlugin)this).Config.Bind<bool>("Sandevistan", "SlowPlayerFalling", false, "Slow down gravity, but only when falling. Ascending, jumping and shi still works at the same speed."); SoundEffects = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "SoundEffects", true, "Play a sound effect when activating/disabling Sandevistan."); SoundVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "SoundVolume", 1f, new ConfigDescription("Sandevistan sound volume.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); WorldAudioPitch = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "WorldAudioPitch", 0.5f, new ConfigDescription("Changes the pitch of most sounds/music while a sandy is active.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 1f), Array.Empty<object>())); ScreenEffects = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects", "ScreenEffects", true, "Creates a green tint."); PlayerAfterimages = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects", "PlayerModelAfterimages", true, "Spawn colored afterimages, similar to the effect of sandevistan from cyberpunk: edgerunners"); AfterimageInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Effects", "AfterimageInterval", 0.055f, new ConfigDescription("Real seconds between afterimages.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.025f, 0.2f), Array.Empty<object>())); AfterimageForwardOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Afterimage Calibration", "ForwardOffset", -0.65f, new ConfigDescription("Change positioning of afterimages.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-5f, 5f), Array.Empty<object>())); AfterimageRightOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Afterimage Calibration", "RightOffset", 0.2f, new ConfigDescription("Change positioning of afterimages.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-5f, 5f), Array.Empty<object>())); AfterimageVerticalOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Afterimage Calibration", "VerticalOffset", -0.8f, new ConfigDescription("Change positioning of afterimages.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-5f, 5f), Array.Empty<object>())); AfterimageScale = ((BaseUnityPlugin)this).Config.Bind<float>("Afterimage Calibration", "Scale", 0.45f, new ConfigDescription("Scale. Size. Dimensions. Proportion. Volume. Bigness. Largeness. Vastness. Whatever other words for size exist.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 3f), Array.Empty<object>())); HideCloseAfterimages = ((BaseUnityPlugin)this).Config.Bind<bool>("Afterimage Calibration", "HideCloseAfterimages", true, "Afterimages near you fade away. So you know, you can actually see sometimes."); bool flag = false; if (Mathf.Approximately(SlowScale.Value, 0.18f) || Mathf.Approximately(SlowScale.Value, 0.1f)) { SlowScale.Value = 0.05f; flag = true; } if (Mathf.Approximately(SoundVolume.Value, 0.85f)) { SoundVolume.Value = 1f; flag = true; } flag |= SnapFloatSetting(SlowScale, 0.01f); flag |= SnapFloatSetting(SoundVolume, 0.05f); flag |= SnapFloatSetting(WorldAudioPitch, 0.05f); flag |= SnapFloatSetting(AfterimageInterval, 0.005f); flag |= SnapFloatSetting(AfterimageForwardOffset, 0.05f); flag |= SnapFloatSetting(AfterimageRightOffset, 0.05f); flag |= SnapFloatSetting(AfterimageVerticalOffset, 0.05f); if (flag | SnapFloatSetting(AfterimageScale, 0.05f)) { ((BaseUnityPlugin)this).Config.Save(); } RegisterWithConfiggy(); try { SandevistanClock.Initialize(SlowScale.Value); SandevistanInput.Initialize(); _harmony = new Harmony("breenihilation.ultrakill.sandevistan"); _harmony.PatchAll(typeof(Plugin).Assembly); EnsureRuntime(); SceneManager.sceneLoaded += OnSceneLoaded; SlowScale.SettingChanged += OnSlowScaleChanged; ActivationKey.SettingChanged += OnActivationKeyChanged; ((MonoBehaviour)this).StartCoroutine(FindPlayerUntilAttached()); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)ex); throw; } } private void RegisterWithConfiggy() { try { Type type = Type.GetType("Configgy.ConfigBuilder, Configgy", throwOnError: false); if (type == null) { return; } MethodInfo method = type.GetMethod("RegisterBepInExConfigEntry", BindingFlags.Instance | BindingFlags.Public); MethodInfo method2 = type.GetMethod("RegisterElement", BindingFlags.Instance | BindingFlags.Public); MethodInfo method3 = type.GetMethod("Rebuild", BindingFlags.Instance | BindingFlags.Public); Assembly assembly = type.Assembly; Type type2 = assembly.GetType("Configgy.FloatSlider", throwOnError: false); Type type3 = assembly.GetType("Configgy.ConfigValueElement", throwOnError: false); Type type4 = assembly.GetType("Configgy.ConfiggableAttribute", throwOnError: false); MethodInfo methodInfo = assembly.GetType("Configgy.Configuration.AutoGeneration.BepinElement", throwOnError: false)?.GetMethod("WrapUntyped", BindingFlags.Static | BindingFlags.Public); MethodInfo methodInfo2 = null; if (type3 != null) { MethodInfo[] methods = type3.GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo methodInfo3 in methods) { if (methodInfo3.Name == "Create" && methodInfo3.IsGenericMethodDefinition && methodInfo3.GetParameters().Length == 1) { methodInfo2 = methodInfo3; break; } } } MethodInfo methodInfo4 = type4?.GetMethod("SetOwner", BindingFlags.Instance | BindingFlags.Public); if (method == null || method3 == null) { throw new MissingMethodException("Configgy 1.0.7 ConfigBuilder registration API was not found."); } _configgyBuilder = Activator.CreateInstance(type, "Configgy.Generated.Sandevistan", "Sandevistan"); int num = 0; foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in ((BaseUnityPlugin)this).Config) { ConfigEntryBase value = item.Value; float num2 = ConfiggyStepFor(value); AcceptableValueRange<float> val = value.Description.AcceptableValues as AcceptableValueRange<float>; if (method2 != null && type4 != null && methodInfo != null && methodInfo4 != null && methodInfo2 != null) { try { object obj = ((!(num2 > 0f) || val == null || !(type2 != null)) ? methodInfo2.MakeGenericMethod(value.SettingType).Invoke(null, new object[1] { value.DefaultValue }) : Activator.CreateInstance(type2, (float)value.DefaultValue, val.MinValue, val.MaxValue, num2)); object obj2 = Activator.CreateInstance(type4, ConfiggyCategoryFor(value), ConfiggyDisplayNameFor(value), ConfiggyOrderFor(value), value.Description.Description); methodInfo4.Invoke(obj2, new object[1] { _configgyBuilder }); object obj3 = methodInfo.Invoke(null, new object[2] { value, obj }); method2.Invoke(_configgyBuilder, new object[2] { obj2, obj3 }); } catch (Exception) { method.Invoke(_configgyBuilder, new object[1] { value }); } } else { method.Invoke(_configgyBuilder, new object[1] { value }); } num++; } method3.Invoke(_configgyBuilder, null); } catch (TargetInvocationException ex2) { Exception? obj4 = ex2.InnerException ?? ex2; ((BaseUnityPlugin)this).Logger.LogError((object)("Configgy registration failed: " + obj4)); } catch (Exception ex3) { ((BaseUnityPlugin)this).Logger.LogError((object)("Configgy registration failed: " + ex3)); } } private static string ConfiggyCategoryFor(ConfigEntryBase entry) { switch (entry.Definition.Key) { case "PlayerModelAfterimages": case "AfterimageInterval": case "ForwardOffset": case "RightOffset": case "VerticalOffset": case "Scale": case "HideCloseAfterimages": return "Afterimage Tuning"; default: return "General"; } } private static int ConfiggyOrderFor(ConfigEntryBase entry) { return entry.Definition.Key switch { "ActivationKey" => 0, "WorldTimeScale" => 1, "SlowPlayerFalling" => 2, "SoundEffects" => 3, "SoundVolume" => 4, "WorldAudioPitch" => 5, "ScreenEffects" => 6, "PlayerModelAfterimages" => 0, "AfterimageInterval" => 1, "ForwardOffset" => 2, "RightOffset" => 3, "VerticalOffset" => 4, "Scale" => 5, "HideCloseAfterimages" => 6, _ => 100, }; } private static string ConfiggyDisplayNameFor(ConfigEntryBase entry) { return entry.Definition.Key switch { "ActivationKey" => "Activation Key", "WorldTimeScale" => "World Time Scale", "SlowPlayerFalling" => "Slow falling", "SoundEffects" => "Sound Effects", "SoundVolume" => "Sound Volume", "WorldAudioPitch" => "Audio Speed/Pitch", "ScreenEffects" => "Screen Effects", "PlayerModelAfterimages" => "Afterimages", "AfterimageInterval" => "Afterimage Interval", "ForwardOffset" => "Forward Offset", "RightOffset" => "Right Offset", "VerticalOffset" => "Vertical Offset", "Scale" => "Scale", "HideCloseAfterimages" => "Hide close afterimages", _ => entry.Definition.Key, }; } private static float ConfiggyStepFor(ConfigEntryBase entry) { if (entry == null || entry.SettingType != typeof(float)) { return 0f; } switch (entry.Definition.Key) { case "WorldTimeScale": return 0.01f; case "SoundVolume": return 0.05f; case "WorldAudioPitch": return 0.05f; case "AfterimageInterval": return 0.005f; case "VerticalOffset": case "RightOffset": case "ForwardOffset": case "Scale": return 0.05f; default: return 0.01f; } } private static bool SnapFloatSetting(ConfigEntry<float> entry, float step) { if (entry == null || step <= 0f) { return false; } float num = Mathf.Round(entry.Value / step) * step; if (Mathf.Approximately(entry.Value, num)) { return false; } entry.Value = num; return true; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if (SandevistanClock.Active) { SandevistanClock.SetActive(active: false, "scene change"); } ((MonoBehaviour)this).StartCoroutine(FindPlayerUntilAttached()); } public void Update() { SandevistanInput.Poll("Plugin.Update"); SandevistanClock.MaintainWorldTime(); } public void LateUpdate() { SandevistanClock.MaintainWorldTime(); } private void OnSlowScaleChanged(object sender, EventArgs args) { SandevistanClock.SetSlowScale(SlowScale.Value); } private void OnActivationKeyChanged(object sender, EventArgs args) { SandevistanInput.Initialize(); ((BaseUnityPlugin)this).Config.Save(); } internal static void NotifyStateChanged(bool active) { if ((Object)(object)_runtime != (Object)null) { _runtime.OnSandevistanStateChanged(active); } } internal static void EnsureRuntime() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown if (!((Object)(object)_runtime != (Object)null)) { _runtimeObject = new GameObject("Sandevistan Runtime"); Object.DontDestroyOnLoad((Object)(object)_runtimeObject); _runtime = _runtimeObject.AddComponent<SandevistanRuntime>(); _runtime.Initialize(); } } private IEnumerator FindPlayerUntilAttached() { NewMovement val = default(NewMovement); for (int i = 0; i < 600; i++) { if (MonoSingleton<NewMovement>.TryGetInstance(ref val) && (Object)(object)val != (Object)null) { SandevistanPlayer.Attach(val); break; } yield return null; } } public void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; } } public static class SandevistanClock { private static float _playerTime; private static int _playerTimeFrame = -1; private static float _normalTimeScale = 1f; private static float _normalFixedDelta = 0.02f; private static float _gameScale = 1f; private static bool _initialized; public static bool Active { get; private set; } public static float SlowScale { get; private set; } = 0.05f; public static float EffectiveWorldScale { get; private set; } = 1f; public static bool PlayerUsesUnscaledTime { get { if (Active) { return !GamePaused; } return false; } } public static float PlayerDeltaTime { get { if (!PlayerUsesUnscaledTime) { return Time.deltaTime; } return Time.unscaledDeltaTime; } } public static float PlayerFixedDeltaTime { get { if (!PlayerUsesUnscaledTime) { return Time.fixedDeltaTime; } return _normalFixedDelta; } } public static float PlayerTimeScale { get { if (!PlayerUsesUnscaledTime) { return Time.timeScale; } return 1f; } } public static float NormalFixedDelta => _normalFixedDelta; public static float PlayerTime { get { if (_playerTimeFrame != Time.frameCount) { if (_playerTimeFrame < 0) { _playerTime = Time.time; } else { _playerTime += (PlayerUsesUnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime); } _playerTimeFrame = Time.frameCount; } return _playerTime; } } public static bool CanToggle { get { NewMovement movement = default(NewMovement); MonoSingleton<NewMovement>.TryGetInstance(ref movement); return CanToggleWith(movement); } } private static bool GamePaused { get { try { return (Object)(object)MonoSingleton<OptionsManager>.Instance != (Object)null && MonoSingleton<OptionsManager>.Instance.paused; } catch { return false; } } } public static float ReadPlayerTimeSince(TimeSince value) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return PlayerTime - value.time; } public static TimeSince CreatePlayerTimeSince(float elapsed) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) return new TimeSince { time = PlayerTime - elapsed }; } public static void InvokePlayer(MonoBehaviour behaviour, string methodName, float delay) { if (!((Object)(object)behaviour == (Object)null) && (!PlayerUsesUnscaledTime || !SandevistanPlayerInvokes.Schedule(behaviour, methodName, delay))) { behaviour.Invoke(methodName, delay); } } public static void AddPlayerForce(Rigidbody rigidbody, Vector3 force) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rigidbody == (Object)null)) { if (!PlayerUsesUnscaledTime) { rigidbody.AddForce(force); } else { rigidbody.velocity += force * (_normalFixedDelta / Mathf.Max(rigidbody.mass, 0.001f)); } } } public static void AddPlayerForce(Rigidbody rigidbody, Vector3 force, ForceMode mode) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected I4, but got Unknown //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rigidbody == (Object)null)) { if (!PlayerUsesUnscaledTime) { rigidbody.AddForce(force, mode); return; } Vector3 val = (Vector3)((int)mode switch { 0 => force * (_normalFixedDelta / Mathf.Max(rigidbody.mass, 0.001f)), 5 => force * _normalFixedDelta, 1 => force / Mathf.Max(rigidbody.mass, 0.001f), 2 => force, _ => Vector3.zero, }); rigidbody.velocity += val; } } public static bool CanToggleWith(NewMovement movement) { if (!_initialized || GamePaused) { return false; } if (!Active && Time.timeScale <= 0f) { return false; } if ((Object)(object)movement != (Object)null) { return !movement.dead; } return false; } public static void Initialize(float slowScale) { SlowScale = Mathf.Clamp(slowScale, 0.02f, 0.8f); _normalFixedDelta = ((Time.fixedDeltaTime > 0f) ? Time.fixedDeltaTime : 0.02f); _normalTimeScale = ((Time.timeScale > 0f) ? Time.timeScale : 1f); _gameScale = _normalTimeScale; _initialized = true; } public static void SetSlowScale(float slowScale) { float slowScale2 = SlowScale; SlowScale = Mathf.Clamp(slowScale, 0.02f, 0.8f); if (Active && !Mathf.Approximately(slowScale2, SlowScale)) { SandevistanVelocity.ChangeScale(slowScale2, SlowScale); Apply(_gameScale * SlowScale); } } public static void ToggleFromInput(string source) { SetActive(!Active, source); } public static void SetActive(bool active, string source) { if (_initialized && Active != active) { if (active) { _normalTimeScale = ((Time.timeScale > 0f) ? Time.timeScale : 1f); _normalFixedDelta = ((Time.fixedDeltaTime > 0f) ? Time.fixedDeltaTime : 0.02f); _gameScale = _normalTimeScale; Active = true; SandevistanVelocity.BeginActivation(); MaintainWorldTime(); Plugin.NotifyStateChanged(active: true); } else { SandevistanVelocity.Deactivate(); Active = false; EffectiveWorldScale = _gameScale; Time.timeScale = _gameScale; Time.fixedDeltaTime = _normalFixedDelta; Plugin.NotifyStateChanged(active: false); } } } public static void CaptureAndApplyGameTime() { if (Active && !GamePaused) { float num = Mathf.Max(0f, Time.timeScale); if (Mathf.Abs(num - EffectiveWorldScale) >= 0.0001f) { _gameScale = num; } Apply(_gameScale * SlowScale); } } public static void MaintainWorldTime() { if (Active && !GamePaused) { Apply(_gameScale * SlowScale); } } private static void Apply(float scale) { EffectiveWorldScale = Mathf.Clamp(scale, 0f, 1f); Time.timeScale = EffectiveWorldScale; Time.fixedDeltaTime = _normalFixedDelta * Mathf.Max(EffectiveWorldScale, 0.001f); } } public static class SandevistanVelocity { private static NewMovement _movement; private static bool _physicalVelocity; private static int _logicalDepth; private static bool _reportedGravityCompensation; private static bool _stabilizingActivation; private static bool _activationSnapshotCaptured; private static bool _activationFixedBatchSeen; private static Vector3 _activationPosition; private static Quaternion _activationRotation; private static Vector3 _activationLogicalVelocity; public static bool StabilizingActivation => _stabilizingActivation; public static void Bind(NewMovement movement) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_movement != (Object)(object)movement) { if (_physicalVelocity && (Object)(object)_movement != (Object)null && (Object)(object)_movement.rb != (Object)null) { Rigidbody rb = _movement.rb; rb.velocity *= SandevistanClock.SlowScale; } _physicalVelocity = false; _logicalDepth = 0; _reportedGravityCompensation = false; } _movement = movement; } public static void ChangeScale(float oldScale, float newScale) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (_physicalVelocity && !((Object)(object)_movement == (Object)null) && !((Object)(object)_movement.rb == (Object)null) && !(newScale <= 0f)) { Rigidbody rb = _movement.rb; rb.velocity *= oldScale / newScale; } } public static void Unbind(NewMovement movement) { if ((Object)(object)_movement == (Object)(object)movement) { Deactivate(); _movement = null; } } public static void Activate() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (!_physicalVelocity && !((Object)(object)_movement == (Object)null) && !((Object)(object)_movement.rb == (Object)null)) { Rigidbody rb = _movement.rb; rb.velocity /= SandevistanClock.SlowScale; _physicalVelocity = true; } } public static void BeginActivation() { _stabilizingActivation = true; _activationSnapshotCaptured = false; _activationFixedBatchSeen = false; } public static void Deactivate() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (_physicalVelocity && (Object)(object)_movement != (Object)null && (Object)(object)_movement.rb != (Object)null) { Rigidbody rb = _movement.rb; rb.velocity *= SandevistanClock.SlowScale; } _physicalVelocity = false; _logicalDepth = 0; _stabilizingActivation = false; _activationSnapshotCaptured = false; _activationFixedBatchSeen = false; } public static void FinishActivationStabilization(NewMovement movement) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) if (_stabilizingActivation && _activationSnapshotCaptured && _activationFixedBatchSeen && !((Object)(object)movement == (Object)null) && !((Object)(object)movement.rb == (Object)null)) { Bind(movement); movement.rb.position = _activationPosition; movement.rb.rotation = _activationRotation; ((Component)movement).transform.position = _activationPosition; ((Component)movement).transform.rotation = _activationRotation; movement.rb.velocity = _activationLogicalVelocity; _physicalVelocity = false; _stabilizingActivation = false; _activationSnapshotCaptured = false; _activationFixedBatchSeen = false; } } public static void EnterPlayerCode(NewMovement movement) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) if (SandevistanClock.Active) { Bind(movement); if (_logicalDepth++ == 0 && _physicalVelocity && (Object)(object)_movement != (Object)null && (Object)(object)_movement.rb != (Object)null) { Rigidbody rb = _movement.rb; rb.velocity *= SandevistanClock.SlowScale; _physicalVelocity = false; } } } public static void ExitPlayerCode() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) if (_logicalDepth <= 0) { return; } _logicalDepth--; if (_logicalDepth != 0) { return; } if (_stabilizingActivation) { if (!_activationSnapshotCaptured && (Object)(object)_movement != (Object)null && (Object)(object)_movement.rb != (Object)null) { _activationPosition = ((Component)_movement).transform.position; _activationRotation = ((Component)_movement).transform.rotation; _activationLogicalVelocity = _movement.rb.velocity; _activationSnapshotCaptured = true; } } else { Activate(); } } public static void ExitPlayerFixedCode() { if (_logicalDepth <= 0) { return; } _logicalDepth--; if (_logicalDepth == 0) { if (_stabilizingActivation) { _activationFixedBatchSeen = true; } else { Activate(); } } } public static Vector3 ReadLogicalPlayerVelocity(Rigidbody rigidbody) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rigidbody == (Object)null) { return Vector3.zero; } Vector3 val = rigidbody.velocity; if (SandevistanClock.Active && _physicalVelocity && (Object)(object)_movement != (Object)null && (Object)(object)_movement.rb == (Object)(object)rigidbody) { val *= SandevistanClock.SlowScale; } return val; } public static void ApplyGravityCompensation(NewMovement movement) { //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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: 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_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) if (SandevistanClock.Active && !_stabilizingActivation && !((Object)(object)movement == (Object)null) && !((Object)(object)movement.rb == (Object)null) && PhysicsExtensions.GetGravityMode(movement.rb) && _logicalDepth > 0) { float slowScale = SandevistanClock.SlowScale; Vector3 gravityVector = PhysicsExtensions.GetGravityVector(movement.rb); bool flag = ((Vector3)(ref gravityVector)).sqrMagnitude > 0.0001f && Vector3.Dot(movement.rb.velocity, gravityVector) > 0f; float num = ((Plugin.SlowPlayerFalling != null && Plugin.SlowPlayerFalling.Value && flag) ? slowScale : 1f); Vector3 val = gravityVector * SandevistanClock.NormalFixedDelta * (num - slowScale * slowScale); Rigidbody rb = movement.rb; rb.velocity += val; if (!_reportedGravityCompensation && ((Vector3)(ref val)).sqrMagnitude > 0f) { _reportedGravityCompensation = true; } } } } [DefaultExecutionOrder(10001)] public sealed class SandevistanExplosionFlash : MonoBehaviour { private static readonly FieldInfo WhiteExplosionField = AccessTools.Field(typeof(Explosion), "whiteExplosion"); private static readonly FieldInfo RendererField = AccessTools.Field(typeof(Explosion), "mr"); private static readonly FieldInfo OriginalMaterialField = AccessTools.Field(typeof(Explosion), "originalMaterial"); private Explosion _explosion; private float _born; public void Awake() { _explosion = ((Component)this).GetComponent<Explosion>(); _born = Time.unscaledTime; } public void Update() { //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Expected O, but got Unknown if (Time.unscaledTime - _born < 0.1f) { return; } if (SandevistanClock.Active && (Object)(object)_explosion != (Object)null && WhiteExplosionField != null && RendererField != null && OriginalMaterialField != null && (bool)WhiteExplosionField.GetValue(_explosion)) { object? value = RendererField.GetValue(_explosion); MeshRenderer val = (MeshRenderer)((value is MeshRenderer) ? value : null); object? value2 = OriginalMaterialField.GetValue(_explosion); Material val2 = (Material)((value2 is Material) ? value2 : null); WhiteExplosionField.SetValue(_explosion, false); if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null) { ((Renderer)val).material = new Material(val2); } } Object.Destroy((Object)(object)this); } } internal static class SandevistanInput { private static InputAction _vAction; private static Timer _nativeVTimer; private static int _nativeVWasDown; private static int _nativeVPressPending; private static int _physicalVPressConsumed; private static int _managedInputLive; private static bool _nativeInputFailureReported; private static KeyCode ConfiguredKey { get { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (Plugin.ActivationKey != null) { return Plugin.ActivationKey.Value; } return (KeyCode)118; } } public unsafe static void Initialize() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_0056: Expected O, but got Unknown Shutdown(); KeyCode configuredKey = ConfiguredKey; _nativeVTimer = new Timer(PollNativeV, null, 0, 8); try { string text = ToInputSystemPath(configuredKey); if (!string.IsNullOrEmpty(text)) { _vAction = new InputAction("Sandevistan", (InputActionType)1, text, (string)null, (string)null, (string)null); _vAction.performed += OnVPerformed; _vAction.canceled += OnVCanceled; _vAction.Enable(); } InputSystem.onAfterUpdate += OnAfterInputUpdate; } catch (Exception ex) { ManualLogSource modLog = Plugin.ModLog; if (modLog != null) { modLog.LogError((object)("Could not create the Sandevistan input action for " + ((object)(*(KeyCode*)(&configuredKey))/*cast due to .constrained prefix*/).ToString() + ": " + ex)); } } } public static void Shutdown() { if (_nativeVTimer != null) { _nativeVTimer.Dispose(); _nativeVTimer = null; } Interlocked.Exchange(ref _nativeVWasDown, 0); Interlocked.Exchange(ref _nativeVPressPending, 0); Interlocked.Exchange(ref _physicalVPressConsumed, 0); Interlocked.Exchange(ref _managedInputLive, 0); try { InputSystem.onAfterUpdate -= OnAfterInputUpdate; if (_vAction != null) { _vAction.performed -= OnVPerformed; _vAction.canceled -= OnVCanceled; _vAction.Disable(); _vAction.Dispose(); } } catch { } _vAction = null; } private static void OnVPerformed(CallbackContext context) { Interlocked.Exchange(ref _managedInputLive, 1); Interlocked.Exchange(ref _nativeVPressPending, 0); if (Interlocked.CompareExchange(ref _physicalVPressConsumed, 1, 0) == 0) { ToggleDetected("global Unity InputAction callback", ResolveMovement()); } } private static void OnVCanceled(CallbackContext context) { Interlocked.Exchange(ref _physicalVPressConsumed, 0); Interlocked.Exchange(ref _nativeVPressPending, 0); } private static void OnAfterInputUpdate() { Interlocked.Exchange(ref _managedInputLive, 1); Interlocked.Exchange(ref _nativeVPressPending, 0); } [DllImport("user32.dll")] private static extern short GetAsyncKeyState(int virtualKey); private static void PollNativeV(object state) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) try { if (Interlocked.CompareExchange(ref _managedInputLive, 0, 0) != 0) { return; } int num = ToVirtualKey(ConfiguredKey); if (num != 0) { bool flag = (GetAsyncKeyState(num) & 0x8000) != 0; bool flag2 = Interlocked.Exchange(ref _nativeVWasDown, flag ? 1 : 0) != 0; if (!flag) { Interlocked.Exchange(ref _physicalVPressConsumed, 0); } else if (!flag2 && Interlocked.CompareExchange(ref _physicalVPressConsumed, 0, 0) == 0) { Interlocked.Exchange(ref _nativeVPressPending, 1); } } } catch (Exception ex) { ReportBackendFailure(ref _nativeInputFailureReported, "Win32 GetAsyncKeyState", ex); } } private static bool ConsumeNativeV(string source, NewMovement movement) { if (Interlocked.Exchange(ref _nativeVPressPending, 0) == 0) { return false; } if (Interlocked.CompareExchange(ref _physicalVPressConsumed, 1, 0) != 0) { return false; } ToggleDetected("Win32 GetAsyncKeyState in " + source, movement ?? ResolveMovement()); return true; } public unsafe static void Poll(string source, NewMovement movement = null) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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) if ((Object)(object)movement != (Object)null) { ReportGameplayReady(movement); } KeyCode configuredKey = ConfiguredKey; if ((int)configuredKey != 0) { if (Input.GetKeyUp(configuredKey)) { Interlocked.Exchange(ref _physicalVPressConsumed, 0); } if (Input.GetKeyDown(configuredKey) && Interlocked.CompareExchange(ref _physicalVPressConsumed, 1, 0) == 0) { Interlocked.Exchange(ref _nativeVPressPending, 0); ToggleDetected("Unity legacy input for " + ((object)(*(KeyCode*)(&configuredKey))/*cast due to .constrained prefix*/).ToString(), movement ?? ResolveMovement()); } } ConsumeNativeV(source, movement); } private static NewMovement ResolveMovement() { NewMovement val = default(NewMovement); if (MonoSingleton<NewMovement>.TryGetInstance(ref val) && (Object)(object)val != (Object)null) { return val; } try { return Object.FindObjectOfType<NewMovement>(); } catch { return null; } } private static void ToggleDetected(string source, NewMovement movement) { if ((Object)(object)movement != (Object)null) { Plugin.EnsureRuntime(); } if (SandevistanClock.CanToggleWith(movement)) { SandevistanClock.ToggleFromInput(source); } } private static void ReportGameplayReady(NewMovement movement) { Plugin.EnsureRuntime(); SandevistanPlayer.Attach(movement); } private static void ReportBackendFailure(ref bool reported, string backend, Exception ex) { if (!reported) { reported = true; ManualLogSource modLog = Plugin.ModLog; if (modLog != null) { modLog.LogError((object)(backend + " input backend failed: " + ex.Message)); } } } private unsafe static string ToInputSystemPath(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Invalid comparison between Unknown and I4 //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Invalid comparison between Unknown and I4 //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Invalid comparison between Unknown and I4 //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Invalid comparison between Unknown and I4 //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected I4, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Invalid comparison between Unknown and I4 //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Invalid comparison between Unknown and I4 //IL_005d: 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_0065: Expected I4, but got Unknown //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Invalid comparison between Unknown and I4 //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Invalid comparison between Unknown and I4 //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected I4, but got Unknown //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Expected I4, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Invalid comparison between Unknown and I4 //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Invalid comparison between Unknown and I4 //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Expected I4, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Invalid comparison between Unknown and I4 //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Invalid comparison between Unknown and I4 //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Invalid comparison between Unknown and I4 //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Expected I4, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Invalid comparison between Unknown and I4 if ((int)key >= 97 && (int)key <= 122) { return "<Keyboard>/" + ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString().ToLowerInvariant(); } if ((int)key >= 48 && (int)key <= 57) { return "<Keyboard>/" + (key - 48); } if ((int)key >= 256 && (int)key <= 265) { return "<Keyboard>/numpad" + (key - 256); } if ((int)key >= 282 && (int)key <= 296) { return "<Keyboard>/f" + (key - 282 + 1); } if ((int)key <= 27) { if ((int)key <= 8) { if ((int)key == 0) { return null; } if ((int)key == 8) { return "<Keyboard>/backspace"; } } else { if ((int)key == 9) { return "<Keyboard>/tab"; } if ((int)key == 13) { return "<Keyboard>/enter"; } if ((int)key == 27) { return "<Keyboard>/escape"; } } } else if ((int)key <= 127) { if ((int)key == 32) { return "<Keyboard>/space"; } if ((int)key == 127) { return "<Keyboard>/delete"; } } else { switch (key - 271) { default: switch (key - 303) { case 1: return "<Keyboard>/leftShift"; case 0: return "<Keyboard>/rightShift"; case 3: return "<Keyboard>/leftCtrl"; case 2: return "<Keyboard>/rightCtrl"; case 5: return "<Keyboard>/leftAlt"; case 4: return "<Keyboard>/rightAlt"; } switch (key - 323) { case 0: return "<Mouse>/leftButton"; case 1: return "<Mouse>/rightButton"; case 2: return "<Mouse>/middleButton"; } break; case 0: return "<Keyboard>/numpadEnter"; case 6: return "<Keyboard>/insert"; case 7: return "<Keyboard>/home"; case 8: return "<Keyboard>/end"; case 9: return "<Keyboard>/pageUp"; case 10: return "<Keyboard>/pageDown"; case 2: return "<Keyboard>/upArrow"; case 3: return "<Keyboard>/downArrow"; case 5: return "<Keyboard>/leftArrow"; case 4: return "<Keyboard>/rightArrow"; case 1: break; } } return "<Keyboard>/" + char.ToLowerInvariant(((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString()[0]) + ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString().Substring(1); } private static int ToVirtualKey(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected I4, but got Unknown //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Invalid comparison between Unknown and I4 //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Invalid comparison between Unknown and I4 //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Invalid comparison between Unknown and I4 //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected I4, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected I4, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Invalid comparison between Unknown and I4 //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Invalid comparison between Unknown and I4 //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Invalid comparison between Unknown and I4 //IL_00a2: 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_00c6: Expected I4, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Invalid comparison between Unknown and I4 //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Invalid comparison between Unknown and I4 //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 if (((int)key >= 97 && (int)key <= 122) || ((int)key >= 48 && (int)key <= 57)) { return (int)key; } if ((int)key >= 282 && (int)key <= 296) { return 112 + key - 282; } if ((int)key <= 27) { if ((int)key <= 9) { if ((int)key == 8) { return 8; } if ((int)key == 9) { return 9; } } else { if ((int)key == 13) { return 13; } if ((int)key == 27) { return 27; } } } else if ((int)key <= 127) { if ((int)key == 32) { return 32; } if ((int)key == 127) { return 46; } } else { switch (key - 273) { case 4: return 45; case 5: return 36; case 6: return 35; case 7: return 33; case 8: return 34; case 0: return 38; case 1: return 40; case 3: return 37; case 2: return 39; } switch (key - 303) { case 0: case 1: return 16; case 2: case 3: return 17; case 4: case 5: return 18; } } return 0; } } [HarmonyPatch(typeof(NewMovement), "Awake")] public static class NewMovementAwakePatch { [HarmonyPostfix] public static void Postfix(NewMovement __instance) { SandevistanPlayer.Attach(__instance); } } [HarmonyPatch(typeof(NewMovement), "Start")] public static class NewMovementStartPatch { [HarmonyPostfix] public static void Postfix(NewMovement __instance) { SandevistanPlayer.Attach(__instance); } } [HarmonyPatch] public static class TimeControllerScalePatch { public static IEnumerable<MethodBase> TargetMethods() { HashSet<string> names = new HashSet<string> { "ContinueTime", "FixedUpdate", "HitStop", "InitializeValues", "RestoreTime", "TrueStop", "Update" }; foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(typeof(TimeController))) { if (names.Contains(declaredMethod.Name)) { yield return declaredMethod; } } } [HarmonyPostfix] public static void Postfix(TimeController __instance, MethodBase __originalMethod) { SandevistanInput.Poll("TimeController Harmony patch"); SandevistanClock.CaptureAndApplyGameTime(); if (SandevistanClock.Active && (__originalMethod.Name == "InitializeValues" || __originalMethod.Name == "FixedUpdate" || __originalMethod.Name == "TrueStop" || __originalMethod.Name == "ContinueTime")) { SandevistanAudioPitch.ApplyGamePitchMultiplier(__instance); } } } public static class SandevistanAudioPitch { private static readonly FieldInfo AudioMixersField = AccessTools.Field(typeof(TimeController), "audmix"); public static void ApplyGamePitchMultiplier(TimeController controller) { if ((Object)(object)controller == (Object)null || AudioMixersField == null || Plugin.WorldAudioPitch == null || !(AudioMixersField.GetValue(controller) is AudioMixer[] array)) { return; } float num = Mathf.Clamp(Plugin.WorldAudioPitch.Value, 0.25f, 1f); AudioMixer[] array2 = array; float num2 = default(float); foreach (AudioMixer val in array2) { if (!((Object)(object)val == (Object)null)) { if (!val.GetFloat("allPitch", ref num2)) { num2 = 1f; } val.SetFloat("allPitch", num2 * num); } } } public static void SetImmediate(bool active) { TimeController val = default(TimeController); if (MonoSingleton<TimeController>.TryGetInstance(ref val) && !((Object)(object)val == (Object)null)) { val.SetAllPitch((active && Plugin.WorldAudioPitch != null) ? Mathf.Clamp(Plugin.WorldAudioPitch.Value, 0.25f, 1f) : 1f); } } } [HarmonyPatch(typeof(NewMovement), "Update")] public static class PlayerVelocityUpdatePatch { [HarmonyPrefix] public static void Prefix(NewMovement __instance) { SandevistanVelocity.FinishActivationStabilization(__instance); SandevistanInput.Poll("NewMovement.Update Harmony patch", __instance); SandevistanVelocity.EnterPlayerCode(__instance); } [HarmonyFinalizer] public static Exception Finalizer(Exception __exception) { SandevistanVelocity.ExitPlayerCode(); return __exception; } } [HarmonyPatch(typeof(NewMovement), "FixedUpdate")] public static class PlayerVelocityFixedUpdatePatch { [HarmonyPrefix] public static void Prefix(NewMovement __instance) { SandevistanVelocity.EnterPlayerCode(__instance); } [HarmonyFinalizer] public static Exception Finalizer(NewMovement __instance, Exception __exception) { SandevistanVelocity.ApplyGravityCompensation(__instance); SandevistanVelocity.ExitPlayerFixedCode(); return __exception; } } [HarmonyPatch] public static class PlayerMovementForcePatch { public static IEnumerable<MethodBase> TargetMethods() { foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(typeof(NewMovement))) { if (declaredMethod.Name == "Jump" || declaredMethod.Name == "WallJump" || declaredMethod.Name == "Launch" || declaredMethod.Name == "LaunchUp" || declaredMethod.Name == "LaunchFromPoint" || declaredMethod.Name == "LaunchFromPointAtSpeed") { yield return declaredMethod; } } } [HarmonyPrefix] public static void Prefix(NewMovement __instance) { SandevistanVelocity.EnterPlayerCode(__instance); } [HarmonyFinalizer] public static Exception Finalizer(Exception __exception) { SandevistanVelocity.ExitPlayerCode(); return __exception; } } [HarmonyPatch(typeof(Explosion), "Collide")] public static class PlayerExplosionVelocityReadPatch { [HarmonyTranspiler] public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); FieldInfo objB = AccessTools.Field(typeof(NewMovement), "rb"); MethodInfo methodInfo = AccessTools.PropertyGetter(typeof(Rigidbody), "velocity"); MethodInfo operand = AccessTools.Method(typeof(SandevistanVelocity), "ReadLogicalPlayerVelocity", (Type[])null, (Type[])null); int num = 0; for (int i = 0; i < list.Count; i++) { if (i > 0 && CodeInstructionExtensions.Calls(list[i], methodInfo) && list[i - 1].opcode == OpCodes.Ldfld && object.Equals(list[i - 1].operand, objB)) { list[i] = ReplaceInstruction(list[i], OpCodes.Call, operand); num++; } } return list; } private static CodeInstruction ReplaceInstruction(CodeInstruction original, OpCode opcode, object operand) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown CodeInstruction val = new CodeInstruction(opcode, operand); val.labels.AddRange(original.labels); val.blocks.AddRange(original.blocks); return val; } } [HarmonyPatch] public static class EnemyPlayerVelocityReadPatch { public static IEnumerable<MethodBase> TargetMethods() { foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(typeof(PlayerTracker))) { if (declaredMethod.Name == "GetPlayerVelocity" || declaredMethod.Name == "PredictPlayerPosition") { yield return declaredMethod; } } foreach (MethodInfo declaredMethod2 in AccessTools.GetDeclaredMethods(typeof(EnemyTarget))) { if (declaredMethod2.Name == "GetVelocity") { yield return declaredMethod2; } } foreach (MethodInfo declaredMethod3 in AccessTools.GetDeclaredMethods(typeof(V2))) { if (declaredMethod3.Name == "LateUpdate") { yield return declaredMethod3; } } } [HarmonyTranspiler] public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod) { MethodInfo velocityGetter = AccessTools.PropertyGetter(typeof(Rigidbody), "velocity"); MethodInfo logicalGetter = AccessTools.Method(typeof(SandevistanVelocity), "ReadLogicalPlayerVelocity", (Type[])null, (Type[])null); int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (CodeInstructionExtensions.Calls(instruction, velocityGetter)) { CodeInstruction val = new CodeInstruction(OpCodes.Call, (object)logicalGetter); val.labels.AddRange(instruction.labels); val.blocks.AddRange(instruction.blocks); replacements++; yield return val; } else { yield return instruction; } } } } [HarmonyPatch(typeof(V2), "LateUpdate")] public static class V2AimRotationPatch { public sealed class AimSnapshot { public Transform[] Targets; public Quaternion[] Rotations; } private static readonly FieldInfo AimAtTarget = AccessTools.Field(typeof(V2), "aimAtTarget"); private static readonly Dictionary<int, AimSnapshot> Snapshots = new Dictionary<int, AimSnapshot>(); [HarmonyPrefix] public static void Prefix(V2 __instance, ref AimSnapshot __state) { //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) if (!SandevistanClock.Active || AimAtTarget == null || !(AimAtTarget.GetValue(__instance) is Transform[] array) || array.Length == 0) { return; } int instanceID = ((Object)__instance).GetInstanceID(); if (!Snapshots.TryGetValue(instanceID, out __state)) { __state = new AimSnapshot(); Snapshots[instanceID] = __state; } __state.Targets = array; if (__state.Rotations == null || __state.Rotations.Length != array.Length) { __state.Rotations = (Quaternion[])(object)new Quaternion[array.Length]; } for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null) { __state.Rotations[i] = array[i].rotation; } } } [HarmonyPostfix] public static void Postfix(AimSnapshot __state) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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) if (__state == null || !SandevistanClock.Active) { return; } float num = 1080f * Mathf.Max(0f, Time.deltaTime); for (int i = 0; i < __state.Targets.Length; i++) { Transform val = __state.Targets[i]; if ((Object)(object)val != (Object)null) { val.rotation = Quaternion.RotateTowards(__state.Rotations[i], val.rotation, num); } } } } [HarmonyPatch(typeof(V2), "Update")] public static class V2BodyRotationPatch { [HarmonyPrefix] public static void Prefix(V2 __instance, ref Quaternion __state) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (SandevistanClock.Active && (Object)(object)__instance != (Object)null) { __state = ((Component)__instance).transform.rotation; } } [HarmonyPostfix] public static void Postfix(V2 __instance, Quaternion __state) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_0046: Unknown result type (might be due to invalid IL or missing references) if (SandevistanClock.Active && !((Object)(object)__instance == (Object)null)) { Quaternion rotation = ((Component)__instance).transform.rotation; float num = 720f * Mathf.Max(0f, Time.deltaTime); if (Quaternion.Angle(__state, rotation) > num) { ((Component)__instance).transform.rotation = Quaternion.RotateTowards(__state, rotation, num); } } } } [HarmonyPatch] public static class PlayerVelocityViewPatch { public static IEnumerable<MethodBase> TargetMethods() { string[] array = new string[3] { "CameraController:LateUpdate", "WalkingBob:Update", "PlayerAnimations:LateUpdate" }; string[] array2 = array; foreach (string text in array2) { string[] split = text.Split(new char[1] { ':' }); Type type = AccessTools.TypeByName(split[0]); if (type == null) { continue; } foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type)) { if (declaredMethod.Name == split[1]) { yield return declaredMethod; } } } } [HarmonyTranspiler] public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod) { MethodInfo velocityGetter = AccessTools.PropertyGetter(typeof(Rigidbody), "velocity"); MethodInfo logicalGetter = AccessTools.Method(typeof(SandevistanVelocity), "ReadLogicalPlayerVelocity", (Type[])null, (Type[])null); int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (CodeInstructionExtensions.Calls(instruction, velocityGetter)) { replacements++; CodeInstruction val = new CodeInstruction(OpCodes.Call, (object)logicalGetter); val.labels.AddRange(instruction.labels); val.blocks.AddRange(instruction.blocks); yield return val; } else { yield return instruction; } } } } [HarmonyPatch] public static class PunchAnimatorClockPatch { public static IEnumerable<MethodBase> TargetMethods() { string[] array = new string[3] { "PunchStart", "ActiveStart", "OnEnable" }; foreach (string text in array) { MethodInfo methodInfo = AccessTools.Method(typeof(Punch), text, (Type[])null, (Type[])null); if (methodInfo != null) { yield return methodInfo; } } } [HarmonyPostfix] public static void Postfix(Punch __instance) { if (SandevistanClock.Active && !((Object)(object)__instance == (Object)null)) { Animator component = ((Component)__instance).GetComponent<Animator>(); if ((Object)(object)component != (Object)null) { SandevistanPlayerAnimator.Ensure(component); } } } } [HarmonyPatch] public static class WeaponSwitchAnimatorPatch { public static IEnumerable<MethodBase> TargetMethods() { foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(typeof(GunControl))) { if (declaredMethod.Name == "SwitchWeapon" || declaredMethod.Name == "ForceWeapon" || declaredMethod.Name == "YesWeapon") { yield return declaredMethod; } } } [HarmonyPostfix] public static void Postfix(GunControl __instance) { NewMovement val = default(NewMovement); if (SandevistanClock.Active && MonoSingleton<NewMovement>.TryGetInstance(ref val) && !((Object)(object)val == (Object)null)) { SandevistanVisuals component = ((Component)val).GetComponent<SandevistanVisuals>(); if ((Object)(object)component != (Object)null) { component.RefreshWeaponAnimators(__instance); } } } [HarmonyPrefix] public static void Prefix() { PreparePlayerAnimatorsBeforeEnable(); } internal static void PreparePlayerAnimatorsBeforeEnable() { NewMovement val = default(NewMovement); if (SandevistanClock.Active && MonoSingleton<NewMovement>.TryGetInstance(ref val) && !((Object)(object)val == (Object)null)) { SandevistanVisuals component = ((Component)val).GetComponent<SandevistanVisuals>(); if ((Object)(object)component != (Object)null) { component.PreparePlayerAnimatorsForEnable(); } } } } [HarmonyPatch] public static class FistPreEnableAnimatorPatch { public static IEnumerable<MethodBase> TargetMethods() { Type typeFromHandle = typeof(FistControl); HashSet<string> names = new HashSet<string> { "ArmChange", "YesFist", "ResetFists", "CheckFist" }; foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(typeFromHandle)) { if (names.Contains(declaredMethod.Name)) { yield return declaredMethod; } } MethodInfo methodInfo = AccessTools.Method(typeof(Punch), "OnEnable", (Type[])null, (Type[])null); if (methodInfo != null) { yield return methodInfo; } } [HarmonyPrefix] public static void Prefix() { WeaponSwitchAnimatorPatch.PreparePlayerAnimatorsBeforeEnable(); } } [HarmonyPatch] public static class ShotgunPreEnableAnimatorPatch { public static IEnumerable<MethodBase> TargetMethods() { MethodInfo methodInfo = AccessTools.Method(typeof(Shotgun), "OnEnable", (Type[])null, (Type[])null); if (methodInfo != null) { yield return methodInfo; } Type type = AccessTools.TypeByName("ShotgunHammer"); MethodInfo methodInfo2 = ((type == null) ? null : AccessTools.Method(type, "OnEnable", (Type[])null, (Type[])null)); if (methodInfo2 != null) { yield return methodInfo2; } } [HarmonyPrefix] public static void Prefix(Component __instance) { if (!SandevistanClock.Active || (Object)(object)__instance == (Object)null) { return; } WeaponSwitchAnimatorPatch.PreparePlayerAnimatorsBeforeEnable(); Animator[] componentsInChildren = __instance.GetComponentsInChildren<Animator>(true); foreach (Animator val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { SandevistanPlayerAnimator.Ensure(val); } } } } [HarmonyPatch(typeof(Explosion), "Start")] public static class ExplosionFlashRealTimePatch { [HarmonyPostfix] public static void Postfix(Explosion __instance) { if ((Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).GetComponent<SandevistanExplosionFlash>() == (Object)null) { ((Component)__instance).gameObject.AddComponent<SandevistanExplosionFlash>(); } } } [HarmonyPatch] public static class PlayerTimeTranspilers { public static IEnumerable<MethodBase> TargetMethods() { string[] array = new string[67] { "NewMovement:Update", "NewMovement:FixedUpdate", "NewMovement:Move", "NewMovement:Jump", "NewMovement:WallJump", "NewMovement:Dodge", "NewMovement:TrySSJ", "NewMovement:Cling", "NewMovement:HandleSlideState", "NewMovement:TryFloorSnap", "NewMovement:Launch", "NewMovement:LaunchUp", "NewMovement:LaunchFromPoint", "NewMovement:LaunchFromPointAtSpeed", "CameraController:LateUpdate", "PlayerAnimations:LateUpdate", "GunControl:Update", "FistControl:Update", "Punch:Update", "WalkingBob:Update", "WeaponCharges:Update", "WeaponCharges:Charge", "Revolver:Update", "Revolver:LateUpdate", "Shotgun:Start", "Shotgun:OnEnable", "Shotgun:OnDisable", "Shotgun:Update", "Shotgun:UpdateMeter", "ShotgunHammer:OnEnable", "ShotgunHammer:Update", "ShotgunHammer:FixedUpdate", "ShotgunHammer:ThrowNade", "ShotgunHammer:Pump", "ShotgunHammer:UpdateMeter", "ShotgunHammer:LateUpdate", "Nailgun:Update", "Nailgun:FixedUpdate", "Nailgun:UpdateZapHud", "Nailgun:RefreshHeatSinkFill", "RocketLauncher:Start", "RocketLauncher:OnEnable", "RocketLauncher:OnDisable", "RocketLauncher:Update", "RocketLauncher:FixedUpdate", "RocketLauncher:FreezeRockets", "Chainsaw:Start", "Chainsaw:Update", "Chainsaw:FixedUpdate", "Chainsaw:GetPunched", "NewMovement:HandleInputs", "HookArm:Update", "HookArm:FixedUpdate", "HookArm:SemiBlockCheck", "HookArm:UpdateLineRendererPositions", "ClimbStep:FixedUpdate", "GroundCheck:UpdateState", "StaminaMeter:Update", "HurtZone:FixedUpdate", "Noclip:UpdateTick", "Sandbox.Arm.SandboxArm:Update", "NewMovement:Parry", "TimeController:ParryFlash", "ParryFlash:Update", "FlashImage:Update", "HealthBar:Update", "ScreenBlood:Update" }; HashSet<MethodBase> yielded = new HashSet<MethodBase>(); string[] array2 = array; foreach (string text in array2) { string[] split = text.Split(new char[1] { ':' }); Type type = AccessTools.TypeByName(split[0]); if (type == null) { continue; } foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type)) { if (declaredMethod.Name == split[1] && yielded.Add(declaredMethod)) { yield return declaredMethod; } } } string[] array3 = new string[13] { "GunControl", "FistControl", "Punch", "WalkingBob", "WeaponCharges", "Revolver", "Shotgun", "ShotgunHammer", "Nailgun", "RocketLauncher", "Railcannon", "Chainsaw", "HookArm" }; array2 = array3; for (int i = 0; i < array2.Length; i++) { Type type2 = AccessTools.TypeByName(array2[i]); if (type2 == null) { continue; } foreach (MethodBase patchableMethod in GetPatchableMethods(type2)) { if (yielded.Add(patchableMethod)) { yield return patchableMethod; } } } } private static IEnumerable<MethodBase> GetPatchableMethods(Type type) { MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!methodInfo.IsAbstract && !methodInfo.ContainsGenericParameters && methodInfo.GetMethodBody() != null) { yield return methodInfo; } } Type[] nestedTypes = type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic); foreach (Type type2 in nestedTypes) { foreach (MethodBase patchableMethod in GetPatchableMethods(type2)) { yield return patchableMethod; } } } [HarmonyTranspiler] public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod) { MethodInfo deltaTime = AccessTools.PropertyGetter(typeof(Time), "deltaTime"); MethodInfo fixedDeltaTime = AccessTools.PropertyGetter(typeof(Time), "fixedDeltaTime"); MethodInfo timeScale = AccessTools.PropertyGetter(typeof(Time), "timeScale"); MethodInfo playerDeltaTime = AccessTools.PropertyGetter(typeof(SandevistanClock), "PlayerDeltaTime"); MethodInfo playerFixedDeltaTime = AccessTools.PropertyGetter(typeof(SandevistanClock), "PlayerFixedDeltaTime"); MethodInfo playerTimeScale = AccessTools.PropertyGetter(typeof(SandevistanClock), "PlayerTimeScale"); MethodInfo readTimeSince = AccessTools.Method(typeof(TimeSince), "op_Implicit", new Type[1] { typeof(TimeSince) }, (Type[])null); MethodInfo createTimeSince = AccessTools.Method(typeof(TimeSince), "op_Implicit", new Type[1] { typeof(float) }, (Type[])null); MethodInfo readPlayerTimeSince = AccessTools.Method(typeof(SandevistanClock), "ReadPlayerTimeSince", (Type[])null, (Type[])null); MethodInfo createPlayerTimeSince = AccessTools.Method(typeof(SandevistanClock), "CreatePlayerTimeSince", (Type[])null, (Type[])null); ConstructorInfo waitForSeconds = AccessTools.Constructor(typeof(WaitForSeconds), new Type[1] { typeof(float) }, false); ConstructorInfo waitForPlayerSeconds = AccessTools.Constructor(typeof(WaitForPlayerSeconds), new Type[1] { typeof(float) }, false); MethodInfo invoke = AccessTools.Method(typeof(MonoBehaviour), "Invoke", new Type[2] { typeof(string), typeof(float) }, (Type[])null); MethodInfo invokePlayer = AccessTools.Method(typeof(SandevistanClock), "InvokePlayer", (Type[])null, (Type[])null); MethodInfo addForce = AccessTools.Method(typeof(Rigidbody), "AddForce", new Type[1] { typeof(Vector3) }, (Type[])null); MethodInfo addPlayerForce = AccessTools.Method(typeof(SandevistanClock), "AddPlayerForce", new Type[2] { typeof(Rigidbody), typeof(Vector3) }, (Type[])null); MethodInfo addForceMode = AccessTools.Method(typeof(Rigidbody), "AddForce", new Type[2] { typeof(Vector3), typeof(ForceMode) }, (Type[])null); MethodInfo addPlayerForceMode = AccessTools.Method(typeof(SandevistanClock), "AddPlayerForce", new Type[3] { typeof(Rigidbody), typeof(Vector3), typeof(ForceMode) }, (Type[])null); bool jumpForceMethod = __originalMethod.DeclaringType == typeof(NewMovement) && (__originalMethod.Name == "Jump" || __originalMethod.Name == "WallJump"); bool launchForceMethod = __originalMethod.DeclaringType == typeof(NewMovement) && (__originalMethod.Name == "Launch" || __originalMethod.Name == "LaunchUp" || __originalMethod.Name == "LaunchFromPoint" || __originalMethod.Name == "LaunchFromPointAtSpeed"); Type type = typeof(float).MakeByRefType(); Type type2 = typeof(Vector3).MakeByRefType(); MethodInfo smoothAngle4 = AccessTools.Method(typeof(Mathf), "SmoothDampAngle", new Type[4] { typeof(float), typeof(float), type, typeof(float) }, (Type[])null); MethodInfo smoothAngle5 = AccessTools.Method(typeof(Mathf), "SmoothDampAngle", new Type[5] { typeof(float), typeof(float), type, typeof(float), typeof(float) }, (Type[])null); MethodInfo smoothAngle6 = AccessTools.Method(typeof(Mathf), "SmoothDampAngle", new Type[6] { typeof(float), typeof(float), type, typeof(float), typeof(float), typeof(float) }, (Type[])null); MethodInfo smooth4 = AccessTools.Method(typeof(Mathf), "SmoothDamp", new Type[4] { typeof(float), typeof(float), type, typeof(float) }, (Type[])null); MethodInfo smooth5 = AccessTools.Method(typeof(Mathf), "SmoothDamp", new Type[5] { typeof(float), typeof(float), type, typeof(float), typeof(float) }, (Type[])null); MethodInfo smooth6 = AccessTools.Method(typeof(Mathf), "SmoothDamp", new Type[6] { typeof(float), typeof(float), type, typeof(float), typeof(float), typeof(float) }, (Type[])null); MethodInfo vectorSmooth4 = AccessTools.Method(typeof(Vector3), "SmoothDamp", new Type[4] { typeof(Vector3), typeof(Vector3), type2, typeof(float) }, (Type[])null); MethodInfo vectorSmooth5 = AccessTools.Method(typeof(Vector3), "SmoothDamp", new Type[5] { typeof(Vector3), typeof(Vector3), type2, typeof(float), typeof(float) }, (Type[])null); MethodInfo vectorSmooth6 = AccessTools.Method(typeof(Vector3), "SmoothDamp", new Type[6] { typeof(Vector3), typeof(Vector3), type2, typeof(float), typeof(float), typeof(float) }, (Type[])null); int replacements = 0; foreach (CodeInstruction instruction in instructions) { MethodInfo methodInfo = null; if (CodeInstructionExtensions.Calls(instruction, deltaTime)) { methodInfo = playerDeltaTime; } else if (CodeInstructionExtensions.Calls(instruction, fixedDeltaTime)) { methodInfo = playerFixedDeltaTime; } else if (CodeInstructionExtensions.Calls(instruction, timeScale)) { methodInfo = playerTimeScale; } if (methodInfo != null) { replacements++; yield return ReplaceInstruction(instruction, OpCodes.Call, methodInfo); } else if (CodeInstructionExtensions.Calls(instruction, readTimeSince) || CodeInstructionExtensions.Calls(instruction, createTimeSince)) { replacements++; yield return ReplaceInstruction(instruction, OpCodes.Call, CodeInstructionExtensions.Calls(instruction, readTimeSince) ? readPlayerTimeSince : createPlayerTimeSince); } else if (instruction.opcode == OpCodes.Newobj && object.Equals(instruction.operand, waitForSeconds)) { replacements++; yield return ReplaceInstruction(instruction, OpCodes.Newobj, waitForPlayerSeconds); } else if (CodeInstructionExtensions.Calls(instruction, invoke)) { replacements++; yield return ReplaceInstruction(instruction, OpCodes.Call, invokePlayer); } else if (jumpForceMethod && CodeInstructionExtensions.Calls(instruction, addForce)) { replacements++; yield return ReplaceInstruction(instruction, OpCodes.Call, addPlayerForce); } else if (launchForceMethod && CodeInstructionExtensions.Calls(instruction, addForceMode)) { replacements++; yield return ReplaceInstruction(instruction, OpCodes.Call, addPlayerForceMode); } else if (CodeInstructionExtensions.Calls(instruction, smoothAngle4) || CodeInstructionExtensions.Calls(instruction, smooth4) || CodeInstructionExtensions.Calls(instruction, vectorSmooth4)) { replacements++; CodeInstruction val = new CodeInstruction(OpCodes.Ldc_R4, (object)float.PositiveInfinity); CopyMetadata(instruction, val); yield return val; yield return new CodeInstruction(OpCodes.Call, (object)playerDeltaTime); yield return new CodeInstruction(OpCodes.Call, (object)(CodeInstructionExtensions.Calls(instruction, smoothAngle4) ? smoothAngle6 : (CodeInstructionExtensions.Calls(instruction, smooth4) ? smooth6 : vectorSmooth6))); } else if (CodeInstructionExtensions.Calls(instruction, smoothAngle5) || CodeInstructionExtensions.Calls(instruction, smooth5) || CodeInstructionExtensions.Calls(instruction, vectorSmooth5)) { replacements++; CodeInstruction val2 = new CodeInstruction(OpCodes.Call, (object)playerDeltaTime); CopyMetadata(instruction, val2); yield return val2; yield return new CodeInstruction(OpCodes.Call, (object)(CodeInstructionExtensions.Calls(instruction, smoothAngle5) ? smoothAngle6 : (CodeInstructionExtensions.Calls(instruction, smooth5) ? smooth6 : vectorSmooth6))); } else { yield return instruction; } } } private static CodeInstruction ReplaceInstruction(CodeInstruction source, OpCode opcode, object operand) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown CodeInstruction val = new CodeInstruction(opcode, operand); CopyMetadata(source, val); return val; } private static void CopyMetadata(CodeInstruction source, CodeInstruction destination) { destination.labels.AddRange(source.labels); destination.blocks.AddRange(source.blocks); } } public sealed class WaitForPlayerSeconds : CustomYieldInstruction { private float _remaining; public override bool keepWaiting { get { _remaining -= SandevistanClock.PlayerDeltaTime; return _remaining > 0f; } } public WaitForPlayerSeconds(float seconds) { _remaining = seconds; } } [DefaultExecutionOrder(30000)] public sealed class SandevistanPlayerAnimator : MonoBehaviour { private Animator _animator; private AnimatorUpdateMode _normalUpdateMode; private AnimatorCullingMode _normalCullingMode; private float _normalSpeed; private bool _captured; private bool _applied; public static SandevistanPlayerAnimator Ensure(Animator animator) { if ((Object)(object)animator == (Object)null) { return null; } SandevistanPlayerAnimator sandevistanPlayerAnimator = ((Component)animator).GetComponent<SandevistanPlayerAnimator>(); if ((Object)(object)sandevistanPlayerAnimator == (Object)null) { sandevistanPlayerAnimator = ((Component)animator).gameObject.AddComponent<SandevistanPlayerAnimator>(); } sandevistanPlayerAnimator.Capture(animator); sandevistanPlayerAnimator.ApplyNow(); return sandevistanPlayerAnimator; } public void Awake() { Capture(((Component)this).GetComponent<Animator>()); } public void OnEnable() { ApplyNow(); } public void Update() { ApplyNow(); } public void LateUpdate() { ApplyNow(); } private void Capture(Animator animator) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)animator == (Object)null)) { _animator = animator; if (!_captured || !_applied) { _normalUpdateMode = animator.updateMode; _normalCullingMode = animator.cullingMode; _normalSpeed = animator.speed; _captured = true; } } } public void ApplyNow() { if (_captured && !((Object)(object)_animator == (Object)null)) { if (SandevistanClock.Active) { float speed = CompensatedSpeed(_normalSpeed); _animator.updateMode = (AnimatorUpdateMode)0; _animator.cullingMode = (AnimatorCullingMode)0; _animator.speed = speed; _applied = true; } else { Restore(); } } } public void Restore() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (_captured && !((Object)(object)_animator == (Object)null) && _applied) { _animator.updateMode = _normalUpdateMode; _animator.cullingMode = _normalCullingMode; _animator.speed = _normalSpeed; _applied = false; } } public static float CompensatedSpeed(float authoredSpeed) { float num = Mathf.Max(SandevistanClock.EffectiveWorldScale, 0.001f); return authoredSpeed / num; } } public static class SandevistanPlayerInvokes { private sealed class PendingInvoke { public MonoBehaviour Target; public MethodInfo Method; public string MethodName; public float Remaining; } private static readonly List<PendingInvoke> Pending = new List<PendingInvoke>(); private static int _lastTickFrame = -1; public static bool IsPlayerOwned(MonoBehaviour behaviour) { if ((Object)(object)behaviour == (Object)null) { return false; } NewMovement val = default(NewMovement); if (MonoSingleton<NewMovement>.TryGetInstance(ref val) && (Object)(object)val != (Object)null) { Transform transform = ((Component)val).transform; Transform transform2 = ((Component)behaviour).transform; if ((Object)(object)transform2 == (Object)(object)transform || transform2.IsChildOf(transform)) { return true; } } GunControl val2 = default(GunControl); if (MonoSingleton<GunControl>.TryGetInstance(ref val2) && (Object)(object)val2 != (Object)null && ((Object)(object)((Component)behaviour).transform == (Object)(object)((Component)val2).transform || ((Component)behaviour).transform.IsChildOf(((Component)val2).transform))) { return true; } FistControl val3 = default(FistControl); if (MonoSingleton<FistControl>.TryGetInstance(ref val3) && (Object)(object)val3 != (Object)null) { if (!((Object)(object)((Component)behaviour).transform == (Object)(object)((Component)val3).transform)) { return ((Component)behaviour).transform.IsChildOf(((Component)val3).transform); } return true; } return false; } public static bool Schedule(MonoBehaviour target, string methodName, float delay) { if ((Object)(object)target == (Object)null || string.IsNullOrEmpty(methodName)) { return false; } MethodInfo methodInfo = AccessTools.Method(((object)target).GetType(), methodName, Type.EmptyTypes, (Type[])null); if (methodInfo == null) { return false; } Pending.Add(new PendingInvoke { Target = target, Method = methodInfo, MethodName = methodName, Remaining = Mathf.Max(0f, delay) }); return true; } public static void Cancel(MonoBehaviour target, string methodName = null) { for (int num = Pending.Count - 1; num >= 0; num--) { PendingInvoke pendingInvoke = Pending[num]; if ((Object)(object)pendingInvoke.Target == (Object)(object)target && (methodName == null || pendingInvoke.MethodName == methodName)) { Pending.RemoveAt(num); } } } public static bool IsScheduled(MonoBehaviour target, string methodName) { for (int i = 0; i < Pending.Count; i++) { if ((Object)(object)Pending[i].Target == (Object)(object)target && Pending[i].MethodName == methodName) { return true; } } return false; } public static void Tick() { if (_lastTickFrame == Time.frameCount) { return; } _lastTickFrame = Time.frameCount; float playerDeltaTime = SandevistanClock.PlayerDeltaTime; for (int num = Pending.Count - 1; num >= 0; num--) { PendingInvoke pendingInvoke = Pending[num]; if ((Object)(object)pendingInvoke.Target == (Object)null) { Pending.RemoveAt(num); } else { pendingInvoke.Remaining -= playerDeltaTime; if (!(pendingInvoke.Remaining > 0f)) { Pending.RemoveAt(num); try { pendingInvoke.Method.Invoke(pendingInvoke.Target, null); } catch (TargetInvocationException ex) { ManualLogSource modLog = Plugin.ModLog; if (modLog != null) { modLog.LogError((object)("Player Invoke failed: " + ((object)pendingInvoke.Target).GetType().Name + "." + pendingInvoke.MethodName + ": " + (ex.InnerException ?? ex))); } } catch (Exception ex2) { ManualLogSource modLog2 = Plugin.ModLog; if (modLog2 != null) { modLog2.LogError((object)("Player Invoke failed: " + ex2)); } } } } } } } [HarmonyPatch(typeof(MonoBehaviour), "Invoke", new Type[] { typeof(string), typeof(float) })] public static class PlayerOwnedInvokePatch { [HarmonyPrefix] public static bool Prefix(MonoBehaviour __instance, string methodName, float time) { if (!SandevistanClock.Active || !SandevistanPlayerInvokes.IsPlayerOwned(__instance)) { return true; } return !SandevistanPlayerInvokes.Schedule(__instance, methodName, time); } } [HarmonyPatch(typeof(MonoBehaviour), "CancelInvoke", new Type[] { typeof(string) })] public static class PlayerOwnedCancelNamedInvokePatch { [HarmonyPrefix] public static void Prefix(MonoBehaviour __instance, string methodName) { SandevistanPlayerInvokes.Cancel(__instance, methodName); } } [HarmonyPatch(typeof(MonoBehaviour), "CancelInvoke", new Type[] { })] public static class PlayerOwnedCancelAllInvokesPatch { [HarmonyPrefix] public static void Prefix(MonoBehaviour __instance) { SandevistanPlayerInvokes.Cancel(__instance); } } [HarmonyPatch(typeof(MonoBehaviour), "IsInvoking", new Type[] { typeof(string) })] public static class PlayerOwnedIsInvokingPatch { [HarmonyPostfix] public static void Postfix(MonoBehaviour __instance, string methodName, ref bool __result) { if (!__result) { __result = SandevistanPlayerInvokes.IsScheduled(__instance, methodName); } } } public class SandevistanRuntime : MonoBehaviour { private const int SampleRate = 44100; private AudioSource _effectSource; private AudioClip _activateClip; private AudioClip _deactivateClip; private bool _initialized; private AudioMixerGroup _routedSfxGroup; public void Initialize() { if (!_initialized) { _effectSource = ((Component)this).gameObject.AddComponent<AudioSource>(); ConfigureSource(_effectSource); _activateClip = LoadEmbeddedPcmWav("SandevistanMod.Audio.EdgeEnter.wav", "EdgeEnter") ?? CreateActivationClip(); _deactivateClip = LoadEmbeddedPcmWav("SandevistanMod.Audio.EdgeExit.wav", "EdgeExit") ?? CreateDeactivationClip(); Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); SceneManager.sceneLoaded += OnSceneLoaded; _initialized = true; } } private void Update() { SandevistanInput.Poll("persistent runtime Update"); SandevistanClock.MaintainWorldTime(); SandevistanPlayerInvokes.Tick(); } private void LateUpdate() { SandevistanClock.MaintainWorldTime(); } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if (SandevistanClock.Active) { SandevistanClock.SetActive(active: false, "scene change"); } ((MonoBehaviour)this).StartCoroutine(FindPlayer()); } private IEnumerator FindPlayer() { NewMovement val = default(NewMovement); for (int i = 0; i < 1200; i++) { if (MonoSingleton<NewMovement>.TryGetInstance(ref val) && (Object)(object)val != (Object)null) { SandevistanPlayer.Attach(val); break; } yield return null; } } private static void ConfigureSource(AudioSource source) { source.playOnAwake = false; source.spatialBlend = 0f; source.dopplerLevel = 0f; source.bypassReverbZones = true; } public void OnSandevistanStateChanged(bool active) { if (!_initialized) { return; } SandevistanAudioPitch.SetImmediate(active); if (!Plugin.SoundEffects.Value) { _effectSource.Stop(); return; } float num = Mathf.Clamp01(Plugin.SoundVolume.Value); RouteToGameSfxMixer(); _effectSource.volume = num * 0.8f; _effectSource.Stop(); if (active) { _effectSource.clip = _activateClip; _effectSource.Play(); } else { _effectSource.clip = _deactivateClip; _effectSource.Play(); } } private void RouteToGameSfxMixer() { if ((Object)(object)_routedSfxGroup != (Object)null) { _effectSource.outputAudioMixerGroup = _routedSfxGroup; } else { NewMovement val = default(NewMovement); if (!MonoSingleton<NewMovement>.TryGetInstance(ref val) || (Object)(object)val == (Object)null) { return; } AudioMixerGroup val2 = null; AudioSource[] componentsInChildren = ((Component)val).GetComponentsInChildren<AudioSource>(true); foreach (AudioSource val3 in componentsInChildren) { if ((Object)(object)val3 != (Object)null && (Object)(object)val3.outputAudioMixerGroup != (Object)null) { val2 = val3.outputAudioMixerGroup; break; } } if ((Object)(object)val2 == (Object)null) { return; } AudioMixer audioMixer = val2.audioMixer; if ((Object)(object)audioMixer != (Object)null) { AudioMixerGroup[] array = audioMixer.FindMatchingGroups(string.Empty); AudioMixerGroup val4 = null; int num = 0; AudioMixerGroup[] array2 = array; foreach (AudioMixerGroup val5 in array2) { if (!((Object)(object)val5 == (Object)null)) { string text = ((Object)val5).name ?? string.Empty; int num2 = ((text.Equals("SFX", StringComparison.OrdinalIgnoreCase) || text.Equals("Sound Effects", StringComparison.OrdinalIgnoreCase)) ? 3 : ((text.IndexOf("sound effect", StringComparison.OrdinalIgnoreCase) >= 0) ? 2 : ((text.IndexOf("sfx", StringComparison.OrdinalIgnoreCase) >= 0) ? 1 : 0))); if (num2 > num) { val4 = val5; num = num2; } } } if ((Object)(object)val4 != (Object)null) { val2 = val4; } } _routedSfxGroup = val2; _effectSource.outputAudioMixerGroup = val2; } } private static AudioClip LoadEmbeddedPcmWav(string resourceName, string clipName) { try { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName); if (stream == null) { throw new InvalidDataException("Embedded resource was not found: " + resourceName); } using BinaryReader binaryReader = new BinaryReader(stream); if (ReadFourCc(binaryReader) != "RIFF") { throw new InvalidDataException("Missing RIFF header."); } binaryReader.ReadUInt32(); if (ReadFourCc(binaryReader) != "WAVE") { throw new InvalidDataException("Missing WAVE header."); } ushort num = 0; ushort num2 = 0; uint num3 = 0u; ushort num4 = 0; byte[] array = null; while (stream.Position + 8 <= stream.Length) { string text = ReadFourCc(binaryReader); uint num5 = binaryReader.ReadUInt32(); long num6 = stream.Position + num5; if (text == "fmt ") { num = binaryReader.ReadUInt16(); num2 = binaryReader.ReadUInt16(); num3 = binaryReader.ReadUInt32(); binaryReader.ReadUInt32(); binaryReader.ReadUInt16(); num4 = binaryReader.ReadUInt16(); } else if (text == "data") { array = binaryReader.ReadBytes((int)num5); } stream.Position = num6 + (num5 & 1); } if (num != 1 || (num4 != 16 && num4 != 32) || num2 == 0 || num3 == 0 || array == null) { throw new InvalidDataException("Only PCM16 and PCM32 WAV audio is supported."); } int num7 = num4 / 8; float[] array2 = new float[array.Length / num7]; float num8 = 0f; for (int i = 0; i < array2.Length; i++) { int num9 = i * num7; if (num4 == 16) { array2[i] = (float)(short)(array[num9] | (array[num9 + 1] << 8)) / 32768f; } else { int num10 = array[num9] | (array[num9 + 1] << 8) | (array[num9 + 2] << 16) | (array[num9 + 3] << 24); array2[i] = (float)num10 / 2.1474836E+09f; } num8 = Mathf.Max(num8, Mathf.Abs(array2[i])); } float num11 = ((num8 > 0.0001f) ? Mathf.Min(4f, 0.98f / num8) : 1f); for (int j = 0; j < array2.Length; j++) { array2[j] = Mathf.Clamp(array2[j] * num11, -1f, 1f); } int num12 = array2.Length / num2; AudioClip obj = AudioClip.Create(clipName, num12, (int)num2, (int)num3, false); obj.SetData(array2, 0); return obj; } catch (Exception) { return null; } } private static string ReadFourCc(BinaryReader reader) { return Encoding.ASCII.GetString(reader.ReadBytes(4)); } private static AudioClip CreateActivationClip() { Random random = new Random(2077); float phase = 0f; return CreateClip("Sandevistan Activate", 0.72f, delegate(float t) { float num = Mathf.Clamp01(t / 0.018f); float num2 = Mathf.Clamp01((0.72f - t) / 0.2f); float num3 = num * num2; float num4 = Mathf.Lerp(85f, 1850f, t * t / 0.5184f); phase += (float)Math.PI * 2f * num4 / 44100f; float num5 = Mathf.Sin(phase) * 0.42f + Mathf.Sin(phase * 0.503f) * 0.22f; float num6 = ((float)random.NextDouble() * 2f - 1f) * (0.19f * (1f - t / 0.72f)); float num7 = Mathf.Sin((float)Math.PI * 62f * t) * 0.12f; return Mathf.Clamp((num5 + num6 + num7) * num3, -1f, 1f); }); } private static AudioClip CreateDeactivationClip() { Random random = new Random(77); float phase = 0f; return CreateClip("Sandevistan Deactivate", 0.52f, delegate(float t) { float num = t / 0.52f; float num2 = Mathf.Lerp(1250f, 62f, Mathf.Sqrt(num)); phase += (float)Math.PI * 2f * num2 / 44100f; float num3 = Mathf.Clamp01(t / 0.012f) * (1f - num); float num4 = ((float)random.NextDouble() * 2f - 1f) * 0.13f; return Mathf.Clamp((Mathf.Sin(phase) * 0.48f + Mathf.Sin(phase * 1.99f) * 0.13f + num4) * num3, -1f, 1f); }); } private static AudioClip CreateClip(string name, float duration, Func<float, float> sample) { int num = Mathf.CeilToInt(duration * 44100f); float[] array = new float[num]; for (int i = 0; i < num; i++) { array[i] = sample((float)i / 44100f); } AudioClip obj = AudioClip.Create(name, num, 1, 44100, false); obj.SetData(array, 0); return obj; } public void Shutdown() { if (_initialized) { SceneManager.sceneLoaded -= OnSceneLoaded; if ((Object)(object)_activateClip != (Object)null) { Object.Destroy((Object)(object)_activateClip); } if ((Object)(object)_deactivateClip != (Object)null) { Object.Destroy((Object)(object)_deactivateClip); } _initialized = false; } } public void OnDestroy() { Shutdown(); } } public class SandevistanPlayer : MonoBehaviour { private SandevistanVisuals _visuals; public NewMovement Movement { get; private set; } public static SandevistanPlayer Attach(NewMovement movement) { if ((Object)(object)movement == (Object)null) { return null; } SandevistanPlayer sandevistanPlayer = ((Component)movement).GetComponent<SandevistanPlayer>(); if ((Object)(object)sandevistanPlayer == (Object)null) { sandevistanPlayer = ((Component)movement).gameObject.AddComponent<SandevistanPlayer>(); } sandevistanPlayer.Bind(movement); return sandevistanPlayer; } public void Bind(NewMovement movement) { Movement = movement; SandevistanVelocity.Bind(movement); if ((Object)(object)_visuals == (Object)null) { _visuals = ((Component)this).gameObject.GetComponent<SandevistanVisuals>() ?? ((Component)this).gameObject.AddComponent<SandevistanVisuals>(); } } public void Awake() { Movement = ((Component)this).GetComponent<NewMovement>(); } public void Start() { Bind(((Object)(object)Movement != (Object)null) ? Movement : ((Component)this).GetComponent<NewMovement>()); } public void Update() { if ((Object)(object)Movement != (Object)null && Movement.dead && SandevistanClock.Active) { SandevistanClock.SetActive(active: false, "player death"); } } public void OnDestroy() { SandevistanVelocity.Unbind(Movement); } } [DefaultExecutionOrder(10000)] public class SandevistanVisuals : MonoBehaviour { private sealed class Ghost { public GameObject Object; public Material Material; public Material[] Materials; public Renderer[] Renderers; public Mesh OwnedMesh; public Color Color; public bool IsBody; public Vector3 BasePosition; public Quaternion BaseRotation; } private const int GhostLayer = 31; private static readonly Color ActiveWorldMultiply = new Color(0.48f, 1f, 0.78f, 1f); private static readonly Color ActiveWorldAdd = new Color(0.01f, 0.06f, 0.025f, 0f); private static readonly FieldInfo PlayerWeaponsField = AccessTools.Field(typeof(PlayerAnimations), "weapons"); private static readonly FieldInfo PlayerAltWeaponsField = AccessTools.Field(typeof(PlayerAnimations), "altweapons"); private static readonly FieldInfo GunControlAllWeaponsField = AccessTools.Field(typeof(GunControl), "allWeapons"); private static readonly FieldInfo GunControlCurrentWeaponField = AccessTools.Field(typeof(GunControl), "currentWeapon"); private const float GhostHueStep = 1f / 72f; private readonly List<Ghost> _ghosts = new List<Ghost>(); private readonly HashSet<SandevistanPlayerAnimator> _animato