Decompiled source of OpenSling v1.0.0
Mods/OpenSling.dll
Decompiled 13 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.Json; using BoneLib; using BoneLib.BoneMenu; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSLZ.Marrow; using Il2CppSLZ.Marrow.Input; using Il2CppSLZ.Marrow.Pool; using Il2CppSLZ.Marrow.SceneStreaming; using Il2CppSLZ.Marrow.Warehouse; using Il2CppSystem.Collections.Generic; using LabFusion.Entities; using LabFusion.Marrow.Extenders; using LabFusion.Network; using LabFusion.Network.Serialization; using LabFusion.Player; using LabFusion.SDK.Modules; using LabFusion.Utilities; using MelonLoader; using MelonLoader.Preferences; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using OpenSling; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(Main), "OpenSling", "1.0.0", "broaj", null)] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: MelonAdditionalDependencies(new string[] { "BoneLib" })] [assembly: MelonOptionalDependencies(new string[] { "LabFusion" })] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("OpenSling")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("OpenSling")] [assembly: AssemblyTitle("OpenSling")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace OpenSling { internal static class FusionSync { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static PlayerUpdate <>9__2_0; internal void <Init>b__2_0(PlayerID _) { Post(Net.PlayerJoined); } } private static readonly object Gate = new object(); private static readonly Queue<Action> Inbox = new Queue<Action>(); internal static bool InServer { get { try { return NetworkInfo.HasServer; } catch { return false; } } } internal static void Init() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown ModuleMessageManager.RegisterHandler<SlingConfigMessage>(); ModuleMessageManager.RegisterHandler<SlingRopeMessage>(); object obj = <>c.<>9__2_0; if (obj == null) { PlayerUpdate val = delegate { Post(Net.PlayerJoined); }; <>c.<>9__2_0 = val; obj = (object)val; } MultiplayerHooking.OnPlayerJoined += (PlayerUpdate)obj; } internal static bool TryEntity(Gun gun, out ushort id, out bool owner) { id = 0; owner = true; if (!InServer || (Object)(object)gun == (Object)null) { return false; } NetworkEntity val = default(NetworkEntity); if (!GunExtender.Cache.TryGet(gun, ref val) || val == null) { return false; } id = val.ID; owner = !val.HasOwner || val.IsOwner; return true; } internal static void SendConfig(ushort id, GunConfig c) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) if (PlayerIDManager.HasOtherPlayers) { MessageRelay.RelayModule<SlingConfigMessage, SlingConfigData>(new SlingConfigData { Entity = id, Mode = (byte)c.Mode, Style = (byte)(c.Style + 1), FrontForward = c.FrontForward, FrontUp = c.FrontUp, BackForward = c.BackForward, BackUp = c.BackUp, Length = c.Length, Width = c.Width, RollFront = c.RollFront, RollBack = c.RollBack, Swivels = c.Swivels }, new MessageRoute((RelayType)3, (NetworkChannel)0)); } } internal static void SendRope(ushort id, Vector3[] local) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (PlayerIDManager.HasOtherPlayers) { MessageRelay.RelayModule<SlingRopeMessage, SlingRopeData>(new SlingRopeData { Entity = id, Points = local }, new MessageRoute((RelayType)3, (NetworkChannel)1)); } } internal static void Post(Action a) { lock (Gate) { if (Inbox.Count < 512) { Inbox.Enqueue(a); } } } internal static void Drain() { while (true) { Action action; lock (Gate) { action = ((Inbox.Count > 0) ? Inbox.Dequeue() : null); } if (action == null) { break; } try { action(); } catch (Exception e) { Main.LogOnce("net-inbox", e); } } } } internal sealed class SlingConfigData : INetSerializable { public ushort Entity; public byte Mode; public byte Style; public float FrontForward; public float FrontUp; public float BackForward; public float BackUp; public float Length; public float Width; public float RollFront; public float RollBack; public bool Swivels = true; public int? GetSize() { return 37; } public void Serialize(INetSerializer s) { s.SerializeValue(ref Entity); s.SerializeValue(ref Mode); s.SerializeValue(ref Style); s.SerializeValue(ref FrontForward); s.SerializeValue(ref FrontUp); s.SerializeValue(ref BackForward); s.SerializeValue(ref BackUp); s.SerializeValue(ref Length); s.SerializeValue(ref Width); s.SerializeValue(ref RollFront); s.SerializeValue(ref RollBack); s.SerializeValue(ref Swivels); } } internal sealed class SlingRopeData : INetSerializable { public ushort Entity; public Vector3[] Points = (Vector3[])(object)new Vector3[16]; public int? GetSize() { return 194; } public void Serialize(INetSerializer s) { s.SerializeValue(ref Entity); if (Points == null || Points.Length != 16) { Points = (Vector3[])(object)new Vector3[16]; } for (int i = 0; i < 16; i++) { NetSerializerUnityExtensions.SerializeValue(s, ref Points[i]); } } } [SkipHandleWhileLoading] internal sealed class SlingConfigMessage : ModuleMessageHandler { protected override void OnHandleMessage(ReceivedMessage received) { SlingConfigData slingConfigData = ((ReceivedMessage)(ref received)).ReadData<SlingConfigData>(); GunConfig c = new GunConfig { Mode = (SlingMode)slingConfigData.Mode, Style = (SlingStyle)(slingConfigData.Style - 1), FrontForward = slingConfigData.FrontForward, FrontUp = slingConfigData.FrontUp, BackForward = slingConfigData.BackForward, BackUp = slingConfigData.BackUp, Length = slingConfigData.Length, Width = slingConfigData.Width, RollFront = slingConfigData.RollFront, RollBack = slingConfigData.RollBack, Swivels = slingConfigData.Swivels }; ushort id = slingConfigData.Entity; FusionSync.Post(delegate { Net.OnConfig(id, c); }); } } [SkipHandleWhileLoading] internal sealed class SlingRopeMessage : ModuleMessageHandler { protected override void OnHandleMessage(ReceivedMessage received) { SlingRopeData slingRopeData = ((ReceivedMessage)(ref received)).ReadData<SlingRopeData>(); ushort id = slingRopeData.Entity; Vector3[] pts = slingRopeData.Points; FusionSync.Post(delegate { Net.OnRope(id, pts); }); } } internal enum SlingStyle { Default = -1, Black, Leather, BlackTightener, Green, Brown } internal enum SlingMode { Auto, Always, Never } internal sealed class GunConfig { public const float DefaultWidth = 0.032f; public SlingMode Mode { get; set; } public SlingStyle Style { get; set; } = SlingStyle.Default; public float FrontForward { get; set; } public float FrontUp { get; set; } public float BackForward { get; set; } public float BackUp { get; set; } public float Length { get; set; } = 1f; public float Width { get; set; } = 0.032f; public float RollFront { get; set; } public float RollBack { get; set; } public bool Swivels { get; set; } = true; public bool IsDefault { get { if (Mode == SlingMode.Auto && Style == SlingStyle.Default && FrontForward == 0f && FrontUp == 0f && BackForward == 0f && BackUp == 0f && Mathf.Abs(Length - 1f) < 0.0001f && Mathf.Abs(Width - 0.032f) < 0.0001f && RollFront == 0f && RollBack == 0f) { return Swivels; } return false; } } public GunConfig Clone() { return (GunConfig)MemberwiseClone(); } public void Sanitize() { FrontForward = C(FrontForward, -0.5f, 0.5f, 0f); FrontUp = C(FrontUp, -0.3f, 0.3f, 0f); BackForward = C(BackForward, -0.5f, 0.5f, 0f); BackUp = C(BackUp, -0.3f, 0.3f, 0f); Length = C(Length, 0.3f, 4f, 1f); Width = C(Width, 0.012f, 0.07f, 0.032f); RollFront = C(RollFront, -180f, 180f, 0f); RollBack = C(RollBack, -180f, 180f, 0f); if (!Enum.IsDefined(typeof(SlingStyle), Style)) { Style = SlingStyle.Default; } if (!Enum.IsDefined(typeof(SlingMode), Mode)) { Mode = SlingMode.Auto; } static float C(float v, float lo, float hi, float d) { if (!float.IsFinite(v)) { return d; } return Mathf.Clamp(v, lo, hi); } } } internal static class GunStore { private static readonly Dictionary<string, GunConfig> Guns = new Dictionary<string, GunConfig>(); private static bool _dirty; private static float _saveAt; private static string PathName => Path.Combine(MelonEnvironment.UserDataDirectory, "OpenSling_Guns.json"); internal static string FilePath => PathName; internal static GunConfig Get(string barcode) { if (string.IsNullOrEmpty(barcode) || !Guns.TryGetValue(barcode, out GunConfig value)) { return new GunConfig(); } return value; } internal static bool Has(string barcode) { return Guns.ContainsKey(barcode); } internal static void Set(string barcode, GunConfig config) { if (!string.IsNullOrEmpty(barcode)) { config.Sanitize(); if (config.IsDefault) { Guns.Remove(barcode); } else { Guns[barcode] = config.Clone(); } _dirty = true; _saveAt = Time.unscaledTime + 0.75f; } } internal static void Reset(string barcode) { if (Guns.Remove(barcode)) { _dirty = true; _saveAt = Time.unscaledTime + 0.25f; } } internal static void Load() { try { if (!File.Exists(PathName)) { return; } Dictionary<string, GunConfig> dictionary = JsonSerializer.Deserialize<Dictionary<string, GunConfig>>(File.ReadAllText(PathName)); if (dictionary == null) { return; } foreach (KeyValuePair<string, GunConfig> item in dictionary) { if (item.Value != null) { item.Value.Sanitize(); Guns[item.Key] = item.Value; } } Main.Log.Msg($"Loaded sling settings for {Guns.Count} gun(s)."); } catch (Exception ex) { Main.Log.Warning("Couldn't read " + PathName + ": " + ex.Message); } } internal static void SaveIfDirty() { if (_dirty && Time.unscaledTime >= _saveAt) { SaveNow(); } } internal static void SaveNow() { if (!_dirty) { return; } _dirty = false; try { File.WriteAllText(PathName, JsonSerializer.Serialize(Guns, new JsonSerializerOptions { WriteIndented = true })); } catch (Exception e) { Main.LogOnce("save", e); } } } internal static class LitShader { private static Shader? _cached; private static readonly string[] Preferred = new string[5] { "Universal Render Pipeline/Lit", "Universal Render Pipeline/Lit (PBR Workflow)", "SLZ/LitMAS/LitMAS Opaque", "SLZ/LitMAS/LitMAS Standard", "Universal Render Pipeline/Simple Lit" }; internal static string Info { get; private set; } = ""; private static bool Ok(Shader? s) { try { return (Object)(object)s != (Object)null && !((Il2CppObjectBase)s).WasCollected && s.isSupported; } catch { return false; } } internal static Shader? Get() { if (Ok(_cached)) { return _cached; } _cached = null; try { string[] preferred = Preferred; for (int i = 0; i < preferred.Length; i++) { Shader val = Shader.Find(preferred[i]); if (Ok(val)) { return Pick(val, "found"); } } Il2CppArrayBase<Shader> val2 = Resources.FindObjectsOfTypeAll<Shader>(); preferred = Preferred; foreach (string text in preferred) { foreach (Shader item in val2) { if (Ok(item) && ((Object)item).name == text) { return Pick(item, "loaded"); } } } foreach (Shader item2 in val2) { if (Ok(item2) && ((Object)item2).name.Contains("LitMAS") && !((Object)item2).name.Contains("Transparent")) { return Pick(item2, "loaded"); } } RigManager rigManager = Player.RigManager; if ((Object)(object)rigManager != (Object)null) { foreach (Renderer componentsInChild in ((Component)rigManager).GetComponentsInChildren<Renderer>(true)) { if ((Object)(object)componentsInChild == (Object)null) { continue; } foreach (Material item3 in (Il2CppArrayBase<Material>)(object)componentsInChild.sharedMaterials) { if ((Object)(object)item3 != (Object)null && Ok(item3.shader) && item3.renderQueue < 2500 && (item3.HasProperty("_BaseColor") || item3.HasProperty("_Color"))) { return Pick(item3.shader, "player's"); } } } } } catch (Exception e) { Main.LogOnce("lit-shader", e); } Info = "no lit shader found"; return null; } private static Shader Pick(Shader sh, string how) { _cached = sh; Info = ((Object)sh).name + " (" + how + ")"; Main.Log.Msg("Sling shader: " + Info); return sh; } } public sealed class Main : MelonMod { internal static Instance Log = null; private static readonly HashSet<string> Logged = new HashSet<string>(); public override void OnInitializeMelon() { Log = ((MelonBase)this).LoggerInstance; Settings.Create(); GunStore.Load(); Settings.BuildMenu(); Net.Init(); SelfTest.OnInit(); Hooking.OnLevelLoaded += delegate { SlingManager.Clear(); SelfTest.OnLevelLoaded(); }; Hooking.OnLevelUnloaded += SlingManager.Clear; Log.Msg("Loaded" + (Net.FusionAvailable ? " (Fusion sync on)" : "") + ". BoneMenu > OpenSling."); } public override void OnUpdate() { SelfTest.DriveInput(); SlingManager.Update(); GunStore.SaveIfDirty(); Net.Tick(); } public override void OnFixedUpdate() { SelfTest.FixedTick(); SlingManager.FixedUpdate(); } public override void OnLateUpdate() { SelfTest.DriveInput(); SlingManager.LateUpdate(); } public override void OnApplicationQuit() { GunStore.SaveNow(); } internal static void LogOnce(string key, Exception e) { if (Logged.Add(key)) { Log.Error($"[{key}] {e}"); } } } internal static class Net { private static readonly Dictionary<ushort, GunConfig> RemoteConfigs = new Dictionary<ushort, GunConfig>(); private static float _nextConfigResend; internal static bool FusionAvailable { get; private set; } internal static bool InServer { get { if (FusionAvailable) { return FusionInServer(); } return false; } } internal static void Init() { try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { if (assemblies[i].GetName().Name == "LabFusion") { InitFusion(); FusionAvailable = true; break; } } } catch (Exception ex) { Main.Log.Warning("Fusion sync unavailable: " + ex.Message); FusionAvailable = false; } } [MethodImpl(MethodImplOptions.NoInlining)] private static void InitFusion() { FusionSync.Init(); } [MethodImpl(MethodImplOptions.NoInlining)] private static bool FusionInServer() { return FusionSync.InServer; } internal static GunConfig? RemoteConfig(ushort id) { if (!RemoteConfigs.TryGetValue(id, out GunConfig value)) { return null; } return value; } internal static void Attach(Sling s) { Refresh(s); } internal static void Refresh(Sling s) { if (!FusionAvailable) { s.Networked = false; s.IsOwner = true; return; } bool isOwner = s.IsOwner; bool networked = s.Networked; ushort entityId = s.EntityId; if (!FusionEntity(s, out var id, out var owner)) { s.Networked = false; s.IsOwner = true; return; } s.Networked = true; s.EntityId = id; s.IsOwner = owner; if (owner && (!isOwner || !networked || entityId != id)) { ConfigChanged(s); } if (!owner && RemoteConfigs.TryGetValue(id, out GunConfig value) && !Same(value, s.Config)) { s.Apply(value); } } [MethodImpl(MethodImplOptions.NoInlining)] private static bool FusionEntity(Sling s, out ushort id, out bool owner) { id = 0; owner = true; try { return FusionSync.TryEntity(s.Gun, out id, out owner); } catch { return false; } } internal static void ConfigChanged(Sling s) { if (!InServer || !s.Networked || !s.IsOwner) { return; } try { SendConfig(s.EntityId, GunStore.Get(s.Barcode)); } catch (Exception e) { Main.LogOnce("send-config", e); } } [MethodImpl(MethodImplOptions.NoInlining)] private static void SendConfig(ushort id, GunConfig c) { FusionSync.SendConfig(id, c); } internal static void SendRope(Sling s) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) if (!s.Networked || !s.IsOwner || Time.time < s.NextSend || !InServer) { return; } s.NextSend = Time.time + 0.1f; bool flag = false; Vector3[] array = (Vector3[])(object)new Vector3[16]; for (int i = 0; i < 16; i++) { array[i] = s.T.InverseTransformPoint(s.P[i]); Vector3 val = array[i] - s.SentLocal[i]; if (((Vector3)(ref val)).sqrMagnitude > 4.0000004E-06f) { flag = true; } } if (!flag) { return; } Array.Copy(array, s.SentLocal, 16); try { SendRopeFusion(s.EntityId, array); } catch (Exception e) { Main.LogOnce("send-rope", e); } } [MethodImpl(MethodImplOptions.NoInlining)] private static void SendRopeFusion(ushort id, Vector3[] local) { FusionSync.SendRope(id, local); } internal static void Tick() { if (!FusionAvailable) { return; } if (!InServer) { if (RemoteConfigs.Count > 0) { RemoteConfigs.Clear(); } return; } FusionDrain(); if (!(Time.unscaledTime >= _nextConfigResend)) { return; } _nextConfigResend = Time.unscaledTime + 10f; foreach (Sling item in SlingManager.All) { ConfigChanged(item); } } [MethodImpl(MethodImplOptions.NoInlining)] private static void FusionDrain() { FusionSync.Drain(); } internal static void PlayerJoined() { _nextConfigResend = 0f; } internal static void OnConfig(ushort id, GunConfig c) { c.Sanitize(); RemoteConfigs[id] = c; Sling sling = SlingManager.FindByEntity(id); if (sling != null && !sling.IsOwner) { if (c.Mode == SlingMode.Never) { SlingManager.Rescan(); } else { sling.Apply(c); } } } internal static void OnRope(ushort id, Vector3[] local) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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) Sling sling = SlingManager.FindByEntity(id); if (sling == null || sling.IsOwner) { return; } for (int i = 0; i < 16 && i < local.Length; i++) { Vector3 val = local[i]; if (!float.IsFinite(val.x) || !float.IsFinite(val.y) || !float.IsFinite(val.z) || ((Vector3)(ref val)).sqrMagnitude > 25f) { return; } } Array.Copy(local, sling.RemoteLocal, 16); sling.RemoteTime = Time.time; } private static bool Same(GunConfig a, GunConfig b) { if (a.Mode == b.Mode && a.Style == b.Style && a.FrontForward == b.FrontForward && a.FrontUp == b.FrontUp && a.BackForward == b.BackForward && a.BackUp == b.BackUp && a.Length == b.Length && a.Width == b.Width && a.RollFront == b.RollFront && a.RollBack == b.RollBack) { return a.Swivels == b.Swivels; } return false; } } internal static class SelfTest { private sealed class MoveRun { public bool Sling; public float Walked; public float HandGap; public float Jitter; public float Pull; public float MaxStretch; public int Samples; public int Over4; public readonly List<float> Jumps = new List<float>(); } private static readonly List<string> Report = new List<string>(); private static int pass; private static int fail; private static int shotIndex; private static bool running; private static bool loadRequested; private static Vector3 shotTarget; private const int Ground = 1089; private static Vector2 _move; private static bool _jump; private static bool _driving; private static int _jumpFrame = -1; private static int _releaseFrame = -1; private static int _gripFrame = -1; private static bool _grip; private static Rigidbody? _push; private static Vector3 _pushAccel; private static string Flag => Path.Combine(MelonEnvironment.UserDataDirectory, "OpenSling_AutoTest.txt"); private static string ReportPath => Path.Combine(MelonEnvironment.UserDataDirectory, "OpenSling_SelfTest.txt"); private static string ShotDir => Path.Combine(MelonEnvironment.UserDataDirectory, "OpenSling_Shots"); internal static void OnInit() { if (File.Exists(Flag)) { Application.runInBackground = true; } } internal static void OnLevelLoaded() { if (File.Exists(Flag) && !running) { string text = ""; try { text = ((Scannable)SceneStreamer.Session.Level).Barcode.ID; } catch { } if (text == "c2534c5a-61b3-4f97-9059-79155363656e") { running = true; MelonCoroutines.Start(Run()); } else if (!loadRequested) { loadRequested = true; MelonCoroutines.Start(LoadBaseline()); } } } private static IEnumerator LoadBaseline() { yield return (object)new WaitForSeconds(5f); try { SceneStreamer.Load(new Barcode("c2534c5a-61b3-4f97-9059-79155363656e"), (Barcode)null); } catch { } } private static void Check(string name, bool ok, string detail = "") { if (ok) { pass++; } else { fail++; } string text = (ok ? "PASS" : "FAIL") + " " + name + ((detail.Length > 0) ? (" -- " + detail) : ""); Report.Add(text); Main.Log.Msg("[SelfTest] " + text); } private static void Note(string text) { Report.Add(" " + text); Main.Log.Msg("[SelfTest] " + text); } private static void Shot(string name, float dist = 1.4f) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Expected O, but got Unknown //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Expected O, but got Unknown //IL_0191: Unknown result type (might be due to invalid IL or missing references) GameObject val = null; RenderTexture val2 = null; Texture2D val3 = null; try { Directory.CreateDirectory(ShotDir); string path = Path.Combine(ShotDir, $"{shotIndex++:D2}_{name}.png"); Vector3 val4 = (((Object)(object)Player.Head != (Object)null) ? Player.Head.position : (shotTarget + Vector3.back)) - shotTarget; val4.y = 0f; val4 = ((((Vector3)(ref val4)).sqrMagnitude > 0.01f) ? ((Vector3)(ref val4)).normalized : Vector3.back); val = new GameObject("OpenSlingTestCam"); Camera val5 = val.AddComponent<Camera>(); val.transform.position = shotTarget + val4 * dist + Vector3.up * 0.35f + Vector3.Cross(Vector3.up, val4) * 0.5f; val.transform.LookAt(shotTarget); val5.fieldOfView = 55f; val2 = (val5.targetTexture = new RenderTexture(1280, 720, 24)); val5.Render(); RenderTexture active = RenderTexture.active; RenderTexture.active = val2; val3 = new Texture2D(1280, 720, (TextureFormat)3, false); val3.ReadPixels(new Rect(0f, 0f, 1280f, 720f), 0, 0); val3.Apply(); RenderTexture.active = active; val5.targetTexture = null; File.WriteAllBytes(path, Il2CppArrayBase<byte>.op_Implicit((Il2CppArrayBase<byte>)(object)ImageConversion.EncodeToPNG(val3))); Note("screenshot " + Path.GetFileName(path)); } catch (Exception ex) { Note("screenshot failed: " + ex.Message); } finally { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } if ((Object)(object)val2 != (Object)null) { val2.Release(); Object.Destroy((Object)(object)val2); } if ((Object)(object)val3 != (Object)null) { Object.Destroy((Object)(object)val3); } } } private static float Floor(Vector3 p) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) RaycastHit val = default(RaycastHit); if (!Physics.Raycast(p + Vector3.up * 0.5f, Vector3.down, ref val, 5f, 1089, (QueryTriggerInteraction)1)) { return p.y - 1f; } return ((RaycastHit)(ref val)).point.y; } private static IEnumerator Spawn(string barcode, Vector3 pos, Action<Gun?> done) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) HashSet<IntPtr> before = new HashSet<IntPtr>(((IEnumerable<Gun>)Object.FindObjectsOfType<Gun>()).Select((Gun g) => ((Il2CppObjectBase)g).Pointer)); GameObject go = null; HelperMethods.SpawnCrate(barcode, pos, Quaternion.LookRotation(Vector3.right), Vector3.one, true, (Action<GameObject>)delegate(GameObject g) { go = g; }, (Action<GameObject>)null); float until = Time.time + 20f; Gun found = null; while ((Object)(object)found == (Object)null && Time.time < until) { if ((Object)(object)go != (Object)null) { found = ((IEnumerable<Gun>)go.GetComponentsInChildren<Gun>(true)).FirstOrDefault((Func<Gun, bool>)((Gun g) => (Object)(object)Sling.FirePoint(g) != (Object)null)); } if ((Object)(object)found == (Object)null && Time.frameCount % 15 == 0) { foreach (Gun item in Object.FindObjectsOfType<Gun>()) { if ((Object)(object)item != (Object)null && (Object)(object)Sling.FirePoint(item) != (Object)null && !before.Contains(((Il2CppObjectBase)item).Pointer)) { Vector3 val = ((Component)item).transform.position - pos; if (((Vector3)(ref val)).sqrMagnitude < 4f) { found = item; break; } } } } yield return null; } yield return (object)new WaitForSeconds(0.5f); done(found); } private static IEnumerator Run() { while (HelperMethods.IsLoading() || (Object)(object)Player.RigManager == (Object)null) { yield return null; } yield return (object)new WaitForSeconds(6f); Report.Clear(); fail = 0; pass = 0; Note("===== OpenSling self test ====="); bool savedAuto = Settings.AutoSling.Value; Settings.AutoSling.Value = true; Vector3 head = Player.Head.position; Vector3 fwd = Player.Head.forward; fwd.y = 0f; ((Vector3)(ref fwd)).Normalize(); Vector3 side = Vector3.Cross(Vector3.up, fwd); Vector3 spot = head + fwd * 1.3f; spot.y = Floor(spot) + 0.6f; Gun rifle = null; Gun pistol = null; yield return Spawn("c1534c5a-a6b5-4177-beb8-04d947756e41", spot, delegate(Gun? val10) { rifle = val10; }); yield return Spawn("c1534c5a-fcfc-4f43-8fb0-d29531393131", spot + side * 0.8f, delegate(Gun? val10) { pistol = val10; }); Check("rifle and pistol spawned", (Object)(object)rifle != (Object)null && (Object)(object)pistol != (Object)null); if ((Object)(object)rifle == (Object)null) { Finish(savedAuto); yield break; } yield return (object)new WaitForSeconds(3f); Sling sling = SlingManager.Ensure(rifle); Check("rifle got a sling", sling != null, SlingManager.Explain(rifle)); Check("pistol didn't (pistols are left alone)", (Object)(object)pistol == (Object)null || SlingManager.Find(pistol) == null); if (sling == null) { Finish(savedAuto); yield break; } SlingManager.Describe(rifle, out string barcode, out string title, out List<string> tags); Note($"rifle: {title} [{string.Join(", ", tags)}], length {sling.GunLength:0.00} m, sling {sling.Rest:0.00} m"); Vector3 forward = Sling.FirePoint(rifle).forward; float num = Vector3.Dot(sling.Front - Sling.FirePoint(rifle).position, forward); float num2 = Vector3.Dot(sling.Back - Sling.FirePoint(rifle).position, forward); Check("front swivel toward the muzzle, back at the stock", num > num2 + 0.3f, $"front {num:0.00} m, back {num2:0.00} m along the barrel"); Vector3 val = sling.T.TransformDirection(sling.Up); _ = sling.T.position; Check("swivels on the underside", Vector3.Dot(sling.Front - Sling.FirePoint(rifle).position, val) < 0.02f && Vector3.Dot(sling.Back - Sling.FirePoint(rifle).position, val) < 0.02f); float floorY = spot.y - 0.6f; float num3 = sling.P.Min((Vector3 p) => p.y); Check("strap rests on the floor, not through it", num3 > floorY - 0.015f, $"lowest point {num3 - floorY:0.000} m above the floor"); shotTarget = sling.T.position; Shot("A_rifle_on_floor"); GameObject viewRoot = sling.ViewRoot; int num4 = (((Object)(object)viewRoot != (Object)null) ? viewRoot.GetComponentsInChildren<Collider>(true).Length : (-1)); int num5 = (((Object)(object)viewRoot != (Object)null) ? viewRoot.GetComponentsInChildren<Grip>(true).Length : (-1)); Check("sling has no colliders or grips (not grabbable)", num4 == 0 && num5 == 0, $"{num4} colliders, {num5} grips"); GameObject bar = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)bar).name = "OpenSling_TestBar"; Vector3 barPos = spot + Vector3.up * 1.2f; bar.transform.position = barPos; bar.transform.localScale = new Vector3(0.08f, 0.08f, 1.5f); bar.transform.rotation = Quaternion.LookRotation(fwd); yield return (object)new WaitForSeconds(0.2f); Rigidbody rb = sling.Rb; float num6 = Vector3.Distance(sling.FrontLocal, sling.BackLocal) * 0.5f; float num7 = Mathf.Sqrt(Mathf.Max(0.01f, Mathf.Pow(sling.Rest * 0.49f, 2f) - num6 * num6)) - 0.04f; rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; ((Component)rb).transform.SetPositionAndRotation(barPos + Vector3.down * num7, Quaternion.LookRotation(side, Vector3.up)); rb.position = ((Component)rb).transform.position; rb.rotation = ((Component)rb).transform.rotation; yield return null; Vector3 val2 = barPos + Vector3.up * 0.055f; Vector3[] array = (Vector3[])(object)new Vector3[16]; for (int num8 = 0; num8 < 16; num8++) { float num9 = (float)num8 / 15f; array[num8] = ((num9 < 0.5f) ? Vector3.Lerp(sling.Front, val2, num9 * 2f) : Vector3.Lerp(val2, sling.Back, (num9 - 0.5f) * 2f)); } sling.SetPoints(array); float startY = rb.position.y; Note($" apex set {sling.P[8].y - floorY:0.000}, bar seen by queries at apex: {((IEnumerable<Collider>)Physics.OverlapSphere(val2 + Vector3.down * 0.02f, 0.03f, Sling.Mask, (QueryTriggerInteraction)1)).Any((Collider x) => (Object)(object)((Component)x).gameObject == (Object)(object)bar)}"); for (int k = 0; k < 4; k++) { yield return null; Note($" frame {k}: apex {sling.P[8].y - floorY:0.000} gun {rb.position.y - floorY:0.000} stretch {sling.Stretch * 100f:0.0}% pull {sling.LastForce:0}"); } for (int k = 0; k < 12; k++) { yield return (object)new WaitForSeconds(0.5f); int num10 = 0; for (int num11 = 1; num11 < 16; num11++) { if (sling.P[num11].y > sling.P[num10].y) { num10 = num11; } } Note($" hang t={(float)k * 0.5f + 0.5f:0.0}s gun y {rb.position.y - floorY:0.00} rope top {sling.P[num10].y - floorY:0.00} (bar top {barPos.y + 0.04f - floorY:0.00}) stretch {sling.Stretch * 100f:0.0}% pull {sling.LastForce:0} N kin {rb.isKinematic}"); } float y = rb.position.y; Check("hung over a bar, it holds the gun up", y > floorY + 0.5f && Mathf.Abs(y - startY) < 0.35f, $"gun {y - floorY:0.00} m off the floor (moved {y - startY:+0.00;-0.00} m), stretch {sling.Stretch * 100f:0.0}%, pull {sling.LastForce:0} N"); shotTarget = barPos + Vector3.down * 0.3f; Shot("B_hung_on_bar", 1.6f); float maxStretch = 0f; List<float> yank = new List<float>(); float tYank = Time.time + 1f; while (Time.time < tYank) { _push = rb; _pushAccel = Vector3.down * 9.81f * 3f; maxStretch = Mathf.Max(maxStretch, sling.Stretch); yank.Add(sling.Stretch); yield return null; } _push = null; yank.Sort(); Note($" yank stretch: median {yank[yank.Count / 2] * 100f:0.0}%, 90% of the time under {yank[(int)((float)yank.Count * 0.9f)] * 100f:0.0}%, peak {maxStretch * 100f:0.0}%"); float num12 = yank[(int)((float)yank.Count * 0.9f)]; Check("can't be stretched much (holds at its limit)", num12 < 0.12f && maxStretch < 0.2f, $"90% of the time under {num12 * 100f:0.0}%, peak {maxStretch * 100f:0.0}% (limit {6f:0}%) under 4x the gun's weight"); Object.Destroy((Object)(object)bar); yield return (object)new WaitForSeconds(1.5f); Vector3 frontLocal = sling.FrontLocal; EditMode.ApplyTo(barcode, delegate(GunConfig cfg) { cfg.FrontForward = 0.05f; }); Sling sling2 = SlingManager.Find(rifle); float num13 = ((sling2 != null) ? (Vector3.Dot(sling2.FrontLocal - frontLocal, sling2.Fwd) * sling2.T.lossyScale.x) : (-1f)); Check("edit: front swivel moves", Mathf.Abs(num13 - 0.05f) < 0.005f, $"moved {num13 * 100f:0.0} cm"); GunStore.SaveNow(); bool ok = File.Exists(GunStore.FilePath) && File.ReadAllText(GunStore.FilePath).Contains(barcode); Check("edit is saved", ok, GunStore.FilePath); EditMode.ApplyTo(barcode, delegate(GunConfig cfg) { cfg.Length = 1.5f; }); sling2 = SlingManager.Find(rifle); Check("edit: sling length", sling2 != null && Mathf.Abs(sling2.Rest - sling2.BaseLength * 1.5f) < 0.01f, $"{sling2?.Rest ?? 0f:0.00} m"); GunStore.Reset(barcode); EditMode.Refresh(barcode); sling2 = SlingManager.Find(rifle); Check("reset gun puts it back", sling2 != null && Vector3.Distance(sling2.FrontLocal, frontLocal) < 0.001f && Mathf.Abs(sling2.Rest - sling2.BaseLength) < 0.001f); rb.velocity = Vector3.zero; ((Component)rb).transform.SetPositionAndRotation(spot + Vector3.up * 0.3f, Quaternion.LookRotation(side, Vector3.up)); rb.position = ((Component)rb).transform.position; rb.isKinematic = true; yield return (object)new WaitForSeconds(1.5f); SlingStyle[] array2 = new SlingStyle[5] { SlingStyle.Black, SlingStyle.Leather, SlingStyle.BlackTightener, SlingStyle.Green, SlingStyle.Brown }; for (int k = 0; k < array2.Length; k++) { SlingStyle st = array2[k]; EditMode.ApplyTo(barcode, delegate(GunConfig cfg) { cfg.Style = st; }); yield return (object)new WaitForSeconds(0.4f); shotTarget = rb.position + Vector3.down * 0.15f; Shot("C_style_" + st, 1.1f); } GunStore.Reset(barcode); EditMode.Refresh(barcode); rb.isKinematic = false; EditMode.ApplyTo(barcode, delegate(GunConfig cfg) { cfg.Mode = SlingMode.Never; }); Check("excluded gun loses its sling", SlingManager.Find(rifle) == null); GunStore.Reset(barcode); EditMode.Refresh(barcode); Check("un-excluded, it's back", SlingManager.Ensure(rifle) != null); Settings.AutoSling.Value = false; SlingManager.Rescan(); yield return (object)new WaitForSeconds(1.2f); Check("Auto Sling off: no slings on guns", SlingManager.Find(rifle) == null); EditMode.ApplyTo(barcode, delegate(GunConfig cfg) { cfg.Mode = SlingMode.Always; }); Check("...unless set to Always for that gun", SlingManager.Ensure(rifle) != null); GunStore.Reset(barcode); EditMode.ApplyTo(barcode, delegate(GunConfig cfg) { cfg.Mode = SlingMode.Always; cfg.Width = 0.05f; cfg.RollFront = 90f; }); Sling sw = SlingManager.Find(rifle); Check("edit: width", sw != null && Mathf.Abs(sw.Config.Width - 0.05f) < 0.0001f); Vector3 val5; if (sw != null) { Vector3 outFrontWorld = sw.OutFrontWorld; Vector3 val3 = sw.T.TransformDirection(sw.Up); Vector3 val4 = sw.T.TransformDirection(sw.Fwd); val5 = Vector3.Cross(val3, val4); Vector3 normalized = ((Vector3)(ref val5)).normalized; float num14 = Mathf.Abs(Vector3.Dot(outFrontWorld, normalized)); float num15 = Vector3.Dot(outFrontWorld, -val3); Vector3 val6 = sw.SocketFrontWorld - (Sling.FirePoint(rifle).position + val4 * Vector3.Dot(sw.SocketFrontWorld - Sling.FirePoint(rifle).position, val4)); Check("front rotation 90: swivel on the side of the gun", num14 > 0.95f && Mathf.Abs(num15) < 0.2f, $"points {num14:0.00} sideways, {num15:0.00} down; socket {Vector3.Dot(val6, normalized) * 100f:0.0} cm to the side of the barrel line"); Check("back end unchanged (rotation is per end)", Vector3.Dot(sw.OutBackWorld, -val3) > 0.95f); rb.isKinematic = true; ((Component)rb).transform.SetPositionAndRotation(spot + Vector3.up * 0.3f, Quaternion.LookRotation(side, Vector3.up)); rb.position = ((Component)rb).transform.position; yield return (object)new WaitForSeconds(1.2f); shotTarget = sw.SocketFrontWorld; Shot("D_front_rotated_90", 0.45f); rb.isKinematic = false; } EditMode.ApplyTo(barcode, delegate(GunConfig cfg) { cfg.Mode = SlingMode.Always; cfg.Swivels = false; }); Sling sling3 = SlingManager.Find(rifle); Check("swivels off (per gun): strap meets the gun", sling3 != null && !sling3.Config.Swivels && Vector3.Distance(sling3.Front, sling3.SocketFrontWorld) < 0.01f); Check("textures: every style has its picture", (Object)(object)Materials.For(SlingStyle.Leather).mainTexture != (Object)null && (Object)(object)Materials.For(SlingStyle.Brown).mainTexture != (Object)null && (Object)(object)Materials.For(SlingStyle.Green).mainTexture != (Object)null && (Object)(object)Materials.For(SlingStyle.Black).mainTexture != (Object)null); GunStore.Reset(barcode); EditMode.Refresh(barcode); EditMode.ApplyTo(barcode, delegate(GunConfig cfg) { cfg.Mode = SlingMode.Always; }); rb.isKinematic = true; ((Component)rb).transform.SetPositionAndRotation(spot + Vector3.up * 0.3f, Quaternion.LookRotation(side, Vector3.up)); rb.position = ((Component)rb).transform.position; yield return (object)new WaitForSeconds(1.5f); Sling sling4 = SlingManager.Find(rifle); if (sling4 != null) { shotTarget = sling4.SocketBackWorld; Shot("D_swivel_closeup", 0.35f); shotTarget = sling4.SocketFrontWorld; Shot("D_swivel_front", 0.35f); } rb.isKinematic = false; Hand hand = Player.RightHand; Grip grip = rifle.triggerGrip; bool[] array3; if ((Object)(object)hand != (Object)null && (Object)(object)grip != (Object)null && Controllers(out XRController right, out XRController left)) { List<MoveRun> runs = new List<MoveRun>(); EditMode.ApplyTo(barcode, delegate(GunConfig cfg) { cfg.Mode = SlingMode.Always; }); rb.isKinematic = true; ((Component)rb).transform.position = spot + Vector3.up * 1.5f; rb.position = ((Component)rb).transform.position; Vector3 val7 = head - Vector3.up * 1.6f + Vector3.up * 0.05f - side * 1.5f - fwd * 1f; Player.RigManager.Teleport(val7, fwd, true); yield return (object)new WaitForSeconds(1f); _move = Vector2.zero; _jump = false; _driving = true; for (int k = 0; k < 8; k++) { _grip = false; yield return (object)new WaitForSeconds(0.2f); rb.isKinematic = true; Vector3 val8 = ((Component)hand).transform.position - ((Component)grip).transform.position; Transform transform = ((Component)rb).transform; transform.position += val8; rb.position = ((Component)rb).transform.position; yield return (object)new WaitForSeconds(0.15f); _grip = true; _gripFrame = Time.frameCount; yield return (object)new WaitForSeconds(0.15f); try { if (!hand.HasAttachedObject()) { grip.OnGrabConfirm(hand, true); } } catch (Exception ex) { Note("grab confirm failed: " + ex.Message); } yield return (object)new WaitForSeconds(0.2f); rb.isKinematic = false; yield return (object)new WaitForSeconds(0.5f); bool flag = false; try { int num16; if (hand.HasAttachedObject()) { val5 = ((Component)grip).transform.position - ((Component)hand).transform.position; num16 = ((((Vector3)(ref val5)).magnitude < 0.4f) ? 1 : 0); } else { num16 = 0; } flag = (byte)num16 != 0; } catch { } DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(49, 3); defaultInterpolatedStringHandler.AppendLiteral(" grab attempt "); defaultInterpolatedStringHandler.AppendFormatted(k + 1); defaultInterpolatedStringHandler.AppendLiteral(": holding "); defaultInterpolatedStringHandler.AppendFormatted(((Object)(object)hand.m_CurrentAttachedGO != (Object)null) ? ((Object)hand.m_CurrentAttachedGO).name : "nothing"); defaultInterpolatedStringHandler.AppendLiteral(", grip "); val5 = ((Component)grip).transform.position - ((Component)hand).transform.position; defaultInterpolatedStringHandler.AppendFormatted(((Vector3)(ref val5)).magnitude * 100f, "0"); defaultInterpolatedStringHandler.AppendLiteral(" cm from the hand"); Note(defaultInterpolatedStringHandler.ToStringAndClear()); if (flag) { break; } } array3 = new bool[2] { true, false }; foreach (bool withSling in array3) { EditMode.ApplyTo(barcode, delegate(GunConfig cfg) { cfg.Mode = (withSling ? SlingMode.Always : SlingMode.Never); }); yield return (object)new WaitForSeconds(1f); Sling sling5 = SlingManager.Find(rifle); bool flag2 = false; try { int num17; if (hand.HasAttachedObject()) { val5 = ((Component)grip).transform.position - ((Component)hand).transform.position; num17 = ((((Vector3)(ref val5)).magnitude < 0.4f) ? 1 : 0); } else { num17 = 0; } flag2 = (byte)num17 != 0; } catch { } if (withSling) { Check("holding the rifle (sling on it, and it knows it's held)", flag2 && sling5 != null && sling5.Held); } else { Check("holding the rifle again (no sling this time)", flag2 && sling5 == null); } MoveRun run = new MoveRun { Sling = withSling }; yield return Move(run, rifle, ((Component)grip).transform, ((Component)hand).transform, sling5); runs.Add(run); Note($" {(withSling ? "with sling " : "without sling")}: walked {run.Walked:0.00} m in 2.5 s, jumps {string.Join(" / ", run.Jumps.Select((float j) => j.ToString("0.00")))} m, gun in hand: avg {run.HandGap * 100f:0.0} cm off, jitter {run.Jitter * 1000f:0.0} mm/frame, strap pull while held {run.Pull:0} N, most stretch {run.MaxStretch * 100f:0.0}% (over 4% in {run.Over4} of {run.Samples} frames)"); if (withSling) { shotTarget = ((Component)rifle).transform.position; Shot("E_walking_with_sling", 1.6f); } } _driving = false; try { hand.DetachObject(); } catch { } MoveRun moveRun = runs[0]; MoveRun moveRun2 = runs[1]; Check("walking speed the same with the sling", moveRun2.Walked > 0.3f && Mathf.Abs(moveRun.Walked - moveRun2.Walked) / moveRun2.Walked < 0.05f, $"{moveRun.Walked:0.00} m vs {moveRun2.Walked:0.00} m"); float num18 = Median(moveRun.Jumps); float num19 = Median(moveRun2.Jumps); Check("jumping not held back by the sling", num19 > 0.1f && num18 >= num19 * 0.92f, $"{num18:0.00} m vs {num19:0.00} m"); Check("the sling never pulls on a held gun", moveRun.Pull <= 0.001f, $"{moveRun.Pull:0.0} N"); Check("strap barely stretches while walking and jumping", moveRun.MaxStretch < 0.04f, $"most {moveRun.MaxStretch * 100f:0.0}%"); Check("gun stays smooth in the hand with the sling", moveRun.Jitter <= moveRun2.Jitter * 1.3f + 0.002f && moveRun.HandGap <= moveRun2.HandGap + 0.01f, $"jitter {moveRun.Jitter * 1000f:0.0} vs {moveRun2.Jitter * 1000f:0.0} mm/frame, gap {moveRun.HandGap * 100f:0.0} vs {moveRun2.HandGap * 100f:0.0} cm"); } else { Check("could drive the player (FlatPlayer controllers, hand, gun grip)", ok: false, $"hand {(Object)(object)hand != (Object)null}, grip {(Object)(object)grip != (Object)null}, controllers {Controllers(out left, out right)}"); } GunStore.Reset(barcode); EditMode.Refresh(barcode); List<float> times = new List<float>(); Hand fhand = Player.RightHand; Rigidbody componentInParent = ((Component)rifle).GetComponentInParent<Rigidbody>(); ForcePullGrip fpg = ((componentInParent != null) ? ((Component)componentInParent).GetComponentInChildren<ForcePullGrip>(true) : null); bool sawPulling = false; array3 = new bool[2] { true, false }; float took; float t0; foreach (bool withSling2 in array3) { EditMode.ApplyTo(barcode, delegate(GunConfig cfg) { cfg.Mode = (withSling2 ? SlingMode.Always : SlingMode.Never); }); try { if (fhand != null) { fhand.DetachObject(); } } catch { } rb.isKinematic = false; rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; Vector3 val9 = Player.Head.position + fwd * 2.2f; val9.y = Floor(val9) + 0.1f; ((Component)rb).transform.SetPositionAndRotation(val9, Quaternion.LookRotation(side, Vector3.up)); rb.position = ((Component)rb).transform.position; yield return (object)new WaitForSeconds(2.5f); if ((Object)(object)fpg == (Object)null || (Object)(object)fhand == (Object)null) { break; } _move = Vector2.zero; _jump = false; _grip = true; _gripFrame = Time.frameCount; _driving = true; t0 = Time.time; took = 9f; try { fpg.Pull(fhand); } catch (Exception ex2) { Note("force pull failed: " + ex2.Message); } Sling sp = SlingManager.Find(rifle); while (Time.time - t0 < 3f) { if (sp != null && sp.Pulling) { sawPulling = true; } bool flag3 = false; try { int num20; if (!fhand.HasAttachedObject()) { val5 = rb.position - ((Component)fhand).transform.position; num20 = ((((Vector3)(ref val5)).magnitude < 0.25f) ? 1 : 0); } else { num20 = 1; } flag3 = (byte)num20 != 0; } catch { } if (flag3) { took = Time.time - t0; break; } yield return null; } times.Add(took); _driving = false; _grip = false; try { fhand.DetachObject(); } catch { } yield return (object)new WaitForSeconds(0.5f); } if (times.Count == 2) { Check("force grab: comes to the hand as fast with the sling", times[1] < 3f && times[0] <= times[1] * 1.25f + 0.15f, $"{times[0]:0.00} s with the sling, {times[1]:0.00} s without (sling saw the pull: {sawPulling})"); } else { Check("force grab: could force pull (ForcePullGrip, hand)", ok: false, $"grip {(Object)(object)fpg != (Object)null}, hand {(Object)(object)fhand != (Object)null}"); } EditMode.ApplyTo(barcode, delegate(GunConfig cfg) { cfg.Mode = SlingMode.Always; }); _driving = false; _grip = false; try { Hand rightHand = Player.RightHand; if (rightHand != null) { rightHand.DetachObject(); } Hand leftHand = Player.LeftHand; if (leftHand != null) { leftHand.DetachObject(); } } catch { } yield return (object)new WaitForSeconds(1f); Sling sling6 = SlingManager.Find(rifle); Note($" before dropping: held {sling6?.Held ?? false}, right hand holding {(Object)(object)Player.RightHand != (Object)null && Player.RightHand.HasAttachedObject()}"); took = 0f; t0 = 0f; for (int k = 0; k < 5; k++) { rb.isKinematic = false; rb.velocity = Vector3.zero; rb.angularVelocity = Random.insideUnitSphere * 3f; ((Component)rb).transform.SetPositionAndRotation(spot + Vector3.up * 1.4f + side * (0.3f * (float)k - 0.6f), Random.rotation); rb.position = ((Component)rb).transform.position; rb.rotation = ((Component)rb).transform.rotation; float tEnd = Time.time + 2.2f; while (Time.time < tEnd) { float num21 = took; val5 = rb.velocity; took = Mathf.Max(num21, ((Vector3)(ref val5)).magnitude); yield return null; } yield return (object)new WaitForSeconds(1.3f); float num22 = t0; val5 = rb.velocity; float magnitude = ((Vector3)(ref val5)).magnitude; val5 = rb.angularVelocity; t0 = Mathf.Max(num22, magnitude + ((Vector3)(ref val5)).magnitude * 0.1f); } Check("dropped 5 times: never flung by the strap", took < 6.5f, $"fastest {took:0.0} m/s"); Check("dropped 5 times: settles still (no jitter)", t0 < 0.08f, $"still moving {t0:0.000} after 3.5 s"); Sling sling7 = SlingManager.Find(rifle); if (sling7 != null) { int samples; float num23 = sling7.FlatScore(out samples); Check("strap lies flat on the floor", samples < 3 || num23 > 0.8f, $"face-down {num23:0.00} over {samples} resting points"); shotTarget = sling7.Front; Shot("F_looped_end", 0.3f); shotTarget = (sling7.Front + sling7.Back) * 0.5f; Shot("F_lying_flat", 1f); } try { SceneStreamer.Load(new Barcode("c2534c5a-2c4c-4b44-b076-203b5363656e"), (Barcode)null); } catch (Exception ex3) { Note("level load failed: " + ex3.Message); } t0 = Time.realtimeSinceStartup + 20f; while (!HelperMethods.IsLoading() && Time.realtimeSinceStartup < t0) { yield return null; } t0 = Time.realtimeSinceStartup + 120f; while (HelperMethods.IsLoading() && Time.realtimeSinceStartup < t0) { yield return null; } yield return (object)new WaitForSeconds(8f); Vector3 position = Player.Head.position; Vector3 f2 = Player.Head.forward; f2.y = 0f; ((Vector3)(ref f2)).Normalize(); Vector3 sp2 = position + f2 * 1.2f; sp2.y = Floor(sp2) + 0.7f; Gun g2 = null; yield return Spawn("c1534c5a-a6b5-4177-beb8-04d947756e41", sp2, delegate(Gun? val10) { g2 = val10; }); if ((Object)(object)g2 != (Object)null) { EditMode.ApplyTo(barcode, delegate(GunConfig cfg) { cfg.Mode = SlingMode.Always; cfg.Style = SlingStyle.Leather; }); Sling sp = SlingManager.Ensure(g2); Rigidbody componentInParent2 = ((Component)g2).GetComponentInParent<Rigidbody>(); if ((Object)(object)componentInParent2 != (Object)null) { componentInParent2.isKinematic = true; ((Component)componentInParent2).transform.SetPositionAndRotation(sp2 + Vector3.up * 0.5f, Quaternion.LookRotation(Vector3.Cross(Vector3.up, f2), Vector3.up)); componentInParent2.position = ((Component)componentInParent2).transform.position; } yield return (object)new WaitForSeconds(1.5f); bool flag4 = sp != null && !Materials.Broken(Materials.For(SlingStyle.Leather)) && (Object)(object)Materials.For(SlingStyle.Leather).mainTexture != (Object)null; bool flag5 = !Materials.Broken(Materials.Metal); Check("after a level change: textured strap and swivels still draw", flag4 && flag5, $"strap {(flag4 ? "ok" : "broken")}, swivels {(flag5 ? "ok" : "broken")}, shader {LitShader.Info}"); if (sp != null) { shotTarget = (sp.Front + sp.Back) * 0.5f + Vector3.down * 0.15f; Shot("G_tuscany_leather", 1f); } GunStore.Reset(barcode); } else { Check("spawn a rifle in Tuscany", ok: false); } Note($"PERF slings step avg {((SlingManager.StepSamples > 0) ? (SlingManager.StepMs / (double)SlingManager.StepSamples) : 0.0):0.000} ms, max {SlingManager.StepMsMax:0.00} ms ({SlingManager.Count} slings)"); Note("Fusion sync: " + (Net.FusionAvailable ? "available" : "LabFusion not loaded")); Finish(savedAuto); static float Median(List<float> l) { List<float> list = l.OrderBy((float x) => x).ToList(); if (list.Count <= 0) { return 0f; } return list[list.Count / 2]; } } private static bool Controllers(out XRController? left, out XRController? right) { left = (right = null); try { Type type = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "FlatPlayer")?.GetType("FlatPlayer.FlatBooter"); object? obj = type?.GetField("LeftController", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); object? obj2 = ((obj is Il2CppObjectBase) ? obj : null); left = ((obj2 != null) ? ((Il2CppObjectBase)obj2).TryCast<XRController>() : null); object? obj3 = type?.GetField("RightController", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); object? obj4 = ((obj3 is Il2CppObjectBase) ? obj3 : null); right = ((obj4 != null) ? ((Il2CppObjectBase)obj4).TryCast<XRController>() : null); } catch { } if (left != null) { return right != null; } return false; } internal static void DriveInput() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (_driving && Controllers(out XRController left, out XRController right)) { left.Joystick2DAxis = _move; right.AButton = _jump; right.AButtonDown = _jump && Time.frameCount - _jumpFrame <= 3; right.AButtonUp = !_jump && Time.frameCount - _releaseFrame <= 3; float num = (_grip ? 1f : 0f); float gripForce = (right.Grip = num); right.GripForce = gripForce; right.GripButton = _grip; right.GripButtonDown = _grip && Time.frameCount - _gripFrame <= 4; right.GripButtonUp = false; } } private static IEnumerator Move(MoveRun run, Gun gun, Transform grip, Transform hand, Sling? sling) { Transform pelvis = ((Rig)Player.RigManager.physicsRig).m_pelvis; _driving = true; yield return (object)new WaitForSeconds(0.5f); Vector3 start = pelvis.position; float gapSum = 0f; float jitSum = 0f; int n = 0; Vector3 lastOff = grip.position - hand.position; _move = new Vector2(0f, 1f); float until = Time.time + 2.5f; while (Time.time < until) { Sample(); yield return null; } _move = Vector2.zero; Vector3 val = pelvis.position - start; val.y = 0f; run.Walked = ((Vector3)(ref val)).magnitude; yield return (object)new WaitForSeconds(0.8f); for (int j = 0; j < 5; j++) { float baseY = pelvis.position.y; float peak = baseY; _jump = true; _jumpFrame = Time.frameCount; float release = Time.time + 0.35f; float end = Time.time + 2.2f; while (Time.time < end) { if (_jump && Time.time >= release) { _jump = false; _releaseFrame = Time.frameCount; } peak = Mathf.Max(peak, pelvis.position.y); Sample(); yield return null; } run.Jumps.Add(peak - baseY); } _jump = false; run.HandGap = ((n > 0) ? (gapSum / (float)n) : 0f); run.Jitter = ((n > 0) ? (jitSum / (float)n) : 0f); void Sample() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) Vector3 val2 = grip.position - hand.position; gapSum += ((Vector3)(ref val2)).magnitude; float num = jitSum; Vector3 val3 = val2 - lastOff; jitSum = num + ((Vector3)(ref val3)).magnitude; lastOff = val2; n++; if (sling != null) { run.Pull += sling.LastForce; run.MaxStretch = Mathf.Max(run.MaxStretch, sling.Stretch); run.Samples++; if (sling.Stretch > 0.04f) { run.Over4++; } } } } internal static void FixedTick() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_push != (Object)null && !((Il2CppObjectBase)_push).WasCollected) { _push.AddForce(_pushAccel, (ForceMode)5); } } private static void Finish(bool savedAuto) { Settings.AutoSling.Value = savedAuto; SlingManager.Rescan(); GunStore.SaveNow(); Note($"===== DONE: {pass} passed, {fail} failed ====="); try { File.WriteAllLines(ReportPath, Report); } catch { } running = false; try { if (File.Exists(Flag) && File.ReadAllText(Flag).Contains("quit")) { Application.Quit(); } } catch { } } } internal sealed class WaitForFixedUpdateFrames : IEnumerator { private int frames = 3; public object? Current => null; public bool MoveNext() { return frames-- > 0; } public void Reset() { } } internal static class Settings { private static MelonPreferences_Category _cat; internal static MelonPreferences_Entry<bool> Enabled; internal static MelonPreferences_Entry<bool> AutoSling; internal static MelonPreferences_Entry<int> Style; private static MelonPreferences_Entry<int> _version; internal static SlingStyle DefaultStyle { get { SlingStyle value = (SlingStyle)Style.Value; if (!Enum.IsDefined(typeof(SlingStyle), value) || value == SlingStyle.Default) { return SlingStyle.Black; } return value; } } internal static void Create() { _cat = MelonPreferences.CreateCategory("OpenSling"); Enabled = _cat.CreateEntry<bool>("Enabled", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); AutoSling = _cat.CreateEntry<bool>("AutoSling", false, (string)null, "Every long gun gets a sling (pistols and utility tools never do). Off: add one per gun in Edit Mode.", false, false, (ValueValidator)null, (string)null); Style = _cat.CreateEntry<int>("DefaultStyle", 0, (string)null, "0 Black, 1 Leather, 2 Black with tightener, 3 Green, 4 Brown", false, false, (ValueValidator)null, (string)null); _version = _cat.CreateEntry<int>("SettingsVersion", 1, (string)null, (string)null, true, false, (ValueValidator)null, (string)null); if (_version.Value < 2) { AutoSling.Value = false; _version.Value = 2; _cat.SaveToFile(false); } } private static void Save() { _cat.SaveToFile(false); } internal static void BuildMenu() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) Page obj = Page.Root.CreatePage("OpenSling", new Color(0.55f, 0.35f, 0.2f), 0, true); obj.CreateBool("Enabled", Color.white, Enabled.Value, (Action<bool>)delegate(bool v) { Enabled.Value = v; Save(); SlingManager.Rescan(); }); obj.CreateBool("Auto Sling Guns", Color.green, AutoSling.Value, (Action<bool>)delegate(bool v) { AutoSling.Value = v; Save(); SlingManager.Rescan(); }); obj.CreateEnum("Default Style", Color.yellow, (Enum)DefaultStyle, (Action<Enum>)delegate(Enum v) { Style.Value = (int)(SlingStyle)(object)v; Save(); SlingManager.Rescan(); }); EditMode.Build(obj); } } internal static class EditMode { internal static bool On; internal static Sling? Held; private static Gun? _heldGun; private static string _heldBarcode = ""; private static float _nextCheck; private static FunctionElement? _label; private static EnumElement? _mode; private static EnumElement? _style; private static BoolElement? _swivels; private static FloatElement? _ff; private static FloatElement? _fu; private static FloatElement? _bf; private static FloatElement? _bu; private static FloatElement? _len; private static FloatElement? _width; private static FloatElement? _rollF; private static FloatElement? _rollB; internal static void Build(Page root) { //IL_0006: 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_0049: 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_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Unknown result type (might be due to invalid IL or missing references) //IL_0365: Unknown result type (might be due to invalid IL or missing references) root.CreateBool("Edit Mode", Color.cyan, false, (Action<bool>)delegate(bool v) { On = v; _nextCheck = 0f; }); Page obj = root.CreatePage("Edit Held Gun", Color.cyan, 0, true); _label = obj.CreateFunction("Gun: (hold one)", Color.white, (Action)delegate { _nextCheck = 0f; }); _mode = obj.CreateEnum("Sling On This Gun", Color.green, (Enum)SlingMode.Auto, (Action<Enum>)delegate(Enum v) { Change(delegate(GunConfig c) { c.Mode = (SlingMode)(object)v; }); }); _style = obj.CreateEnum("Style", Color.yellow, (Enum)SlingStyle.Default, (Action<Enum>)delegate(Enum v) { Change(delegate(GunConfig c) { c.Style = (SlingStyle)(object)v; }); }); _ff = obj.CreateFloat("Front Forward/Back", Color.green, 0f, 0.01f, -0.5f, 0.5f, (Action<float>)delegate(float v) { Change(delegate(GunConfig c) { c.FrontForward = v; }); }); _fu = obj.CreateFloat("Front Up/Down", Color.green, 0f, 0.005f, -0.3f, 0.3f, (Action<float>)delegate(float v) { Change(delegate(GunConfig c) { c.FrontUp = v; }); }); _bf = obj.CreateFloat("Back Forward/Back", Color.red, 0f, 0.01f, -0.5f, 0.5f, (Action<float>)delegate(float v) { Change(delegate(GunConfig c) { c.BackForward = v; }); }); _bu = obj.CreateFloat("Back Up/Down", Color.red, 0f, 0.005f, -0.3f, 0.3f, (Action<float>)delegate(float v) { Change(delegate(GunConfig c) { c.BackUp = v; }); }); _len = obj.CreateFloat("Sling Length", Color.magenta, 1f, 0.05f, 0.3f, 4f, (Action<float>)delegate(float v) { Change(delegate(GunConfig c) { c.Length = v; }); }); _width = obj.CreateFloat("Sling Width (m)", Color.magenta, 0.032f, 0.002f, 0.012f, 0.07f, (Action<float>)delegate(float v) { Change(delegate(GunConfig c) { c.Width = v; }); }); _swivels = obj.CreateBool("Show Swivels", Color.gray, true, (Action<bool>)delegate(bool v) { Change(delegate(GunConfig c) { c.Swivels = v; }); }); _rollF = obj.CreateFloat("Front Rotation (deg)", Color.green, 0f, 15f, -180f, 180f, (Action<float>)delegate(float v) { Change(delegate(GunConfig c) { c.RollFront = v; }); }); _rollB = obj.CreateFloat("Back Rotation (deg)", Color.red, 0f, 15f, -180f, 180f, (Action<float>)delegate(float v) { Change(delegate(GunConfig c) { c.RollBack = v; }); }); obj.CreateFunction("Reset This Gun", Color.red, (Action)ResetHeld); } private static Gun? HeldGun() { try { Gun componentInHand = Player.GetComponentInHand<Gun>(Player.RightHand); if ((Object)(object)componentInHand == (Object)null) { componentInHand = Player.GetComponentInHand<Gun>(Player.LeftHand); } return componentInHand; } catch { return null; } } internal static void Update() { if (Time.unscaledTime < _nextCheck) { return; } _nextCheck = Time.unscaledTime + 0.25f; Gun val = HeldGun(); if ((Object)(object)val != (Object)null && (Object)(object)_heldGun != (Object)null && ((Il2CppObjectBase)val).Pointer == ((Il2CppObjectBase)_heldGun).Pointer) { Held = SlingManager.Find(val); return; } _heldGun = val; Held = (((Object)(object)val != (Object)null) ? SlingManager.Find(val) : null); _heldBarcode = ""; if ((Object)(object)val != (Object)null && SlingManager.Describe(val, out string barcode, out string title, out List<string> _)) { _heldBarcode = barcode; SetLabel("Gun: " + title); Show(GunStore.Get(barcode)); } else { SetLabel("Gun: (hold one)"); } } private static void SetLabel(string text) { try { if (_label != null) { ((Element)_label).ElementName = text; } } catch { } } private static void Show(GunConfig c) { try { if (_mode != null) { _mode.Value = c.Mode; } if (_style != null) { _style.Value = c.Style; } if (_ff != null) { _ff.Value = c.FrontForward; } if (_fu != null) { _fu.Value = c.FrontUp; } if (_bf != null) { _bf.Value = c.BackForward; } if (_bu != null) { _bu.Value = c.BackUp; } if (_len != null) { _len.Value = c.Length; } if (_width != null) { _width.Value = c.Width; } if (_rollF != null) { _rollF.Value = c.RollFront; } if (_swivels != null) { _swivels.Value = c.Swivels; } if (_rollB != null) { _rollB.Value = c.RollBack; } } catch (Exception e) { Main.LogOnce("edit-show", e); } } private static void Change(Action<GunConfig> edit) { if (On && !string.IsNullOrEmpty(_heldBarcode)) { ApplyTo(_heldBarcode, edit); } } internal static void ApplyTo(string barcode, Action<GunConfig> edit) { GunConfig gunConfig = GunStore.Get(barcode).Clone(); edit(gunConfig); GunStore.Set(barcode, gunConfig); Refresh(barcode); } private static void ResetHeld() { if (!string.IsNullOrEmpty(_heldBarcode)) { GunStore.Reset(_heldBarcode); Show(new GunConfig()); Refresh(_heldBarcode); } } internal static void Refresh(string barcode) { SlingManager.Rescan(); foreach (Sling item in SlingManager.All) { if (item.Barcode == barcode) { Net.ConfigChanged(item); } } if ((Object)(object)_heldGun != (Object)null) { SlingManager.Ensure(_heldGun); } } } internal sealed class Sling { internal const int N = 16; internal const float Radius = 0.012f; internal const float MaxStretch = 0.06f; private const float EndGive = 0.35f; public readonly Gun Gun; public readonly Rigidbody? Rb; public readonly Transform T; public readonly string Barcode; public readonly string Title; public readonly bool TooShort; public Vector3 FrontBase; public Vector3 BackBase; public Vector3 Fwd; public Vector3 Up; public float BaseLength; public float GunLength; public GunConfig Config = new GunConfig(); public SlingStyle Style; public Vector3 FrontLocal; public Vector3 BackLocal; public float Rest; internal readonly Vector3[] P = (Vector3[])(object)new Vector3[16]; internal readonly Vector3[] Prev = (Vector3[])(object)new Vector3[16]; internal readonly Vector3[] Last = (Vector3[])(object)new Vector3[16]; private readonly bool[] contact = new bool[16]; internal readonly Vector3[] ContactNormal = (Vector3[])(object)new Vector3[16]; private readonly bool[] contactSolid = new bool[16]; private readonly string[] contactWhat = new string[16]; internal string LastSupportBy = ""; private readonly Vector3[] Mid = (Vector3[])(object)new Vector3[16]; private readonly bool[] held = new bool[16]; private float endGive = 0.35f; private bool placed; private bool visible; private int stillSteps; private bool asleep; private Vector3 sleepPos; private Quaternion sleepRot; private int sleepCheck; private int sleepHits; internal float Stretch; internal float LastForce; internal float LastSupport; internal bool Networked; internal bool IsOwner = true; internal ushort EntityId; internal readonly Vector3[] RemoteLocal = (Vector3[])(object)new Vector3[16]; internal float RemoteTime = -10f; internal readonly Vector3[] SentLocal = (Vector3[])(object)new Vector3[16]; internal float NextSend; private readonly HashSet<IntPtr> own = new HashSet<IntPtr>(); private readonly Il2CppArrayBase<Grip> grips; private readonly Il2CppArrayBase<InteractableHost> hostsAll; internal const float StrapMass = 0.15f; internal float HeldForce; private readonly SlingView view; private static readonly Il2CppStructArray<RaycastHit> Hits = new Il2CppStructArray<RaycastHit>(8L); private static readonly Il2CppReferenceArray<Collider> Overlaps = new Il2CppReferenceArray<Collider>(16L); private static int _mask = -1; private List<Collider> fitCols = new List<Collider>(); private Vector3 fitOrigin; private float fitMidU; private float fitReach; public float FrontF; public float BackF; public Vector3 SocketFront; public Vector3 SocketBack; public Vector3 OutFront; public Vector3 OutBack; internal const float SwivelDrop = 0.03f; private static SphereCollider? _probe; public bool Pulling { get { try { foreach (InteractableHost item in hostsAll) { if ((Object)(object)item != (Object)null && item.IsPulling) { return true; } } } catch { } return false; } } public Vector3 Front => T.TransformPoint(FrontLocal); public Vector3 Back => T.TransformPoint(BackLocal); public Vector3 SocketFrontWorld => T.TransformPoint(SocketFront); public Vector3 SocketBackWorld => T.TransformPoint(SocketBack); public Vector3 OutFrontWorld => T.TransformDirection(OutFront); public Vector3 OutBackWorld => T.TransformDirection(OutBack); public bool Held { get { try { foreach (Grip grip in grips) { if ((Object)(object)grip != (Object)null && grip.attachedHands != null && grip.attachedHands.Count > 0) { return true; } } } catch { } return false; } } internal static int Mask { get { if (_mask == -1) { int num = -1; string[] array = new string[4] { "Ignore Raycast", "UI", "TransparentFX", "Water" }; for (int i = 0; i < array.Length; i++) { int num2 = LayerMask.NameToLayer(array[i]); if (num2 >= 0) { num &= ~(1 << num2); } } _mask = num; } return _mask; } } public bool Active { get { if ((Object)(object)Gun != (Object)null && !((Il2CppObjectBase)Gun).WasCollected) { return ((Component)Gun).gameObject.activeInHierarchy; } return false; } } private static SphereCollider Probe { get { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0034: 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) //IL_0057: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_probe == (Object)null || ((Il2CppObjectBase)_probe).WasCollected) { GameObject val = new GameObject("OpenSling_Probe"); Object.DontDestroyOnLoad((Object)val); int num = LayerMask.NameToLayer("Ignore Raycast"); val.layer = ((num >= 0) ? num : 2); val.transform.position = new Vector3(0f, -10000f, 0f); _probe = val.AddComponent<SphereCollider>(); ((Collider)_probe).isTrigger = true; _probe.radius = 0.012f; } return _probe; } } internal GameObject? ViewRoot => view.Root; private bool Solid(Collider col) { try { Rigidbody attachedRigidbody = col.attachedRigidbody; if ((Object)(object)attachedRigidbody == (Object)null || attachedRigidbody.isKinematic) { return true; } if ((Object)(object)Rb != (Object)null && ((Il2CppObjectBase)attachedRigidbody).Pointer == ((Il2CppObjectBase)Rb).Pointer) { return false; } return (Object)(object)Rb == (Object)null || attachedRigidbody.mass >= Rb.mass * 2f; } catch { return false; } } internal bool Touching(int i) { return contact[i]; } internal static Transform? FirePoint(Gun gun) { try { return gun.firePointTransform; } catch { return null; } } public Sling(Gun gun, string barcode, string title, Rigidbody? rb) { Gun = gun; Barcode = barcode; Title = title; Rb = rb; T = (((Object)(object)rb != (Object)null) ? ((Component)rb).transform : ((Component)gun).transform); foreach (Collider componentsInChild in ((Component)T).GetComponentsInChildren<Collider>(true)) { if ((Object)(object)componentsInChild != (Object)null) { own.Add(((Il2CppObjectBase)componentsInChild).Pointer); } } grips = ((Component)T).GetComponentsInChildren<Grip>(true); hostsAll = ((Component)T).GetComponentsInChildren<InteractableHost>(true); Fit(); TooShort = GunLength < 0.32f; view = new SlingView(this); } private void Fit() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) Transform val = (Transform)(((Object)(object)FirePoint(Gun) != (Object)null) ? ((object)FirePoint(Gun)) : ((object)T)); Vector3 forward = val.forward; Vector3 val2 = Vector3.ProjectOnPlane(T.up, forward); if (((Vector3)(ref val2)).sqrMagnitude < 0.01f) { val2 = Vector3.ProjectOnPlane(val.up, forward); } ((Vector3)(ref val2)).Normalize(); Vector3.Cross(val2, forward); Vector3 position = val.position; float num = float.MaxValue; float num2 = float.MinValue; float num3 = float.MaxValue; float num4 = float.MinValue; List<Collider> list = new List<Collider>(); foreach (Collider componentsInChild in ((Component)T).GetComponentsInChildren<Collider>(true)) { if (!((Object)(object)componentsInChild == (Object)null) && !componentsInChild.isTrigger && Corners(componentsInChild, out Vector3[] world)) { list.Add(componentsInChild); Vector3[] array = world; for (int i = 0; i < array.Length; i++) { Vector3 val3 = array[i] - position; float num5 = Vector3.Dot(val3, forward); float num6 = Vector3.Dot(val3, val2); num = Mathf.Min(num, num5); num2 = Mathf.Max(num2, num5); num3 = Mathf.Min(num3, num6); num4 = Mathf.Max(num4, num6); } } } if (list.Count == 0 || num > num2) { num = -0.5f; num2 = 0f; num3 = -0.08f; num4 = 0.04f; } GunLength = num2 - num; fitCols = list; fitOrigin = T.InverseTransformPoint(position); fitMidU = (num3 + num4) * 0.5f; fitReach = Mathf.Max(0.2f, num4 - num3 + 0.2f); Vector3 outward = T.InverseTransformDirection(forward); Fwd = ((Vector3)(ref outward)).normalized; outward = T.InverseTransformDirection(val2); Up = ((Vector3)(ref outward)).normalized; FrontF = num2 - Mathf.Clamp(GunLength * 0.22f, 0.06f, 0.3f); BackF = num + Mathf.Clamp(GunLength * 0.06f, 0.02f, 0.08f); FrontBase = Surface(FrontF, 0f, out outward); BackBase = Surface(BackF, 0f, out outward); float num7 = Vector3.Distance(FrontBase, BackBase) * T.lossyScale.x; BaseLength = Mathf.Max(num7 * 1.35f, 0.8f); } internal Vector3 Surface(float f, float rotation, out Vector3 outward) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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) //IL_004a: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) Vector3 val = T.TransformDirection(Fwd); Vector3 val2 = T.TransformDirection(Up); Vector3 val3 = Quaternion.AngleAxis(rotation, val) * -val2; Vector3 val4 = T.TransformPoint(fitOrigin) + val * f + val2 * fitMidU; Ray val5 = default(Ray); ((Ray)(ref val5))..ctor(val4 + val3 * fitReach, -val3); float num = float.MaxValue; Vector3 val6 = val4 + val3 * 0.02f; RaycastHit val7 = default(RaycastHit); foreach (Collider fitCol in fitCols) { try { if ((Object)(object)fitCol != (Object)null && fitCol.Raycast(val5, ref val7, fitReach * 2f) && ((RaycastHit)(ref val7)).distance < num) { num = ((RaycastHit)(ref val7)).distance; val6 = ((RaycastHit)(ref val7)).point; } } catch { } } Vector3 val8 = T.InverseTransformDirection(val3); outward = ((Vector3)(ref val8)).normalized; return T.InverseTransformPoint(val6 - val3 * 0.002f); } private static bool Corners(Collider c, out Vector3[] world) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: 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_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) world = Array.Empty<Vector3>(); BoxCollider val = ((Il2CppObjectBase)c).TryCast<BoxCollider>(); Vector3 center; Vector3 val2; if (val != null) { center = val.center; val2 = val.size; } else { SphereCollider val3 = ((Il2CppObjectBase)c).TryCast<SphereCollider>(); if (val3 != null) { center = val3.center; val2 = Vector3.one * val3.radius * 2f; } else { CapsuleCollider val4 = ((Il2CppObjectBase)c).TryCast<CapsuleCollider>(); if (val4 != null) { center = val4.center; val2 = Vector3.one * val4.radius * 2f; ((Vector3)(ref val2))[val4.direction] = Mathf.Max(val4.height, val4.radius * 2f); } else { MeshCollider val5 = ((Il2CppObjectBase)c).TryCast<MeshCollider>(); if (val5 == null || !((Object)(object)val5.sharedMesh != (Object)null)) { return false; } Bounds bounds = val5.sharedMesh.bounds; center = ((Bounds)(ref bounds)).center; bounds = val5.sharedMesh.bounds; val2 = ((Bounds)(ref bounds)).size; } } } Transform transform = ((Component)c).transform; world = (Vector3[])(object)new Vector3[8]; int num = 0; for (int i = -1; i <= 1; i += 2) { for (int j = -1; j <= 1; j += 2) { for (int k = -1; k <= 1; k += 2) { world[num++] = transform.TransformPoint(center + Vector3.Scale(val2 * 0.5f, new Vector3((float)i, (float)j, (float)k))); } } } return true; } public void Apply(GunConfig config) { //IL_003e: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) Config = config; Style = ((config.Style == SlingStyle.Default) ? Settings.DefaultStyle : config.Style); SocketFront = Surface(FrontF + config.FrontForward, config.RollFront, out OutFront) + Up * config.FrontUp; SocketBack = Surface(BackF + config.BackForward, config.RollBack, out OutBack) + Up * config.BackUp; float num = (config.Swivels ? 0.03f : 0.004f); FrontLocal = SocketFront + OutFront * num; BackLocal = SocketBack + OutBack * num; float num2 = BaseLength * config.Length; bool num3 = Mathf.Abs(num2 - Rest) > 0.001f; Rest = num2; view.SetStyle(Style); if (num3) { Wake(); } } public void Place() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) Vector3 front = Front; Vector3 back = Back; float num = Vector3.Distance(front, back); float num2 = ((num < Rest) ? Mathf.Sqrt(3f * num * Mathf.Max(0f, Rest - num) / 8f) : 0f); for (int i = 0; i < 16; i++) { float num3 = (float)i / 15f; P[i] = (Prev[i] = (Last[i] = Vector3.Lerp(front, back, num3) + Vector3.down * (num2 * 4f * num3 * (1f - num3)))); contact[i] = false; } placed = true; Wake(); } public void Wake() { asleep = false; stillSteps = 0; } internal void SetPoints(Vector3[] pts) { //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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_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_002a: 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_0030: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < 16; i++) { P[i] = (Prev[i] = (Last[i] = pts[i])); } placed = true; Wake(); } public void Step(float dt, bool nearPlayer) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to i