Decompiled source of WolverineClaws v1.0.1
Mods/WolverineClaws.dll
Decompiled 16 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.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using HarmonyLib; using Il2Cpp; using Il2CppActiveRagdoll; using Il2CppHurricaneVR.Framework.ControllerInput; using Il2CppHurricaneVR.Framework.Core; using Il2CppHurricaneVR.Framework.Core.Grabbers; using Il2CppHurricaneVR.Framework.Core.HandPoser; using Il2CppHurricaneVR.Framework.Core.Stabbing; using Il2CppHurricaneVR.Framework.Shared; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Il2CppSystem.Reflection; using MelonLoader; using MelonLoader.Preferences; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using WolverineClaws; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(ClawsMod), "WolverineClaws", "1.0.1", "coope", null)] [assembly: MelonGame("Kubunautilus", "BrutalistickVR")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("WolverineClaws")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("WolverineClaws")] [assembly: AssemblyTitle("WolverineClaws")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace WolverineClaws { internal static class ClawBlood { private class Entry { public Renderer Rend; public PaintTarget Target; public Material Blood; public Material Metal; public bool Bloody; } [HarmonyPatch(typeof(PaintTarget), "PaintObject")] private static class PaintObjectPatch { private static void Prefix(PaintTarget target) { Mark(target); } } [HarmonyPatch(typeof(PaintTarget), "ForcePaintObject")] private static class ForcePaintObjectPatch { private static void Prefix(PaintTarget target) { Mark(target); } } [HarmonyPatch(typeof(PaintTarget), "ForcePaintObjectMultiple")] private static class ForcePaintObjectMultiplePatch { private static void Prefix(PaintTarget target) { Mark(target); } } [HarmonyPatch(typeof(PaintTarget), "ClearAllPaint")] private static class ClearAllPaintPatch { private static void Postfix() { foreach (Entry value in Targets.Values) { if ((Object)(object)value.Rend != (Object)null && value.Bloody && (Object)(object)value.Metal != (Object)null) { value.Rend.sharedMaterial = value.Metal; value.Bloody = false; } } } } private static readonly Dictionary<IntPtr, Entry> Targets = new Dictionary<IntPtr, Entry>(); public static bool Register(PaintTarget pt, Renderer rend, Material metal, Instance log) { Prune(); if ((Object)(object)pt == (Object)null || (Object)(object)rend == (Object)null) { return false; } if (!pt.validTarget) { string name = ((Object)rend).name; Material sharedMaterial = rend.sharedMaterial; object obj; if (sharedMaterial == null) { obj = null; } else { Shader shader = sharedMaterial.shader; obj = ((shader != null) ? ((Object)shader).name : null); } log.Warning(name + ": blood target not valid (material '" + (string?)obj + "')"); return false; } if (!pt.setupComplete) { pt.SetupPaint(); } Material sharedMaterial2 = rend.sharedMaterial; Targets[((Il2CppObjectBase)pt).Pointer] = new Entry { Rend = rend, Target = pt, Blood = sharedMaterial2, Metal = metal }; if ((Object)(object)metal != (Object)null) { rend.sharedMaterial = metal; } return true; } public static void Release(GameObject claws) { if ((Object)(object)claws == (Object)null) { return; } Transform transform = claws.transform; foreach (KeyValuePair<IntPtr, Entry> item in Targets.ToList()) { Entry value = item.Value; if ((Object)(object)value.Rend == (Object)null || !((Component)value.Rend).transform.IsChildOf(transform)) { continue; } try { if ((Object)(object)value.Target != (Object)null) { value.Target.ReleaseRenderTextures(); } } catch { } if ((Object)(object)value.Blood != (Object)null && (Object)(object)value.Blood != (Object)(object)value.Metal) { Object.Destroy((Object)(object)value.Blood); } Targets.Remove(item.Key); } } public static bool IsBloody(Renderer rend) { return Targets.Values.Any((Entry e) => (Object)(object)e.Rend != (Object)null && (Object)(object)e.Rend == (Object)(object)rend && e.Bloody); } private static void Prune() { foreach (IntPtr item in (from kv in Targets where (Object)(object)kv.Value.Rend == (Object)null select kv.Key).ToList()) { Targets.Remove(item); } } private static void Mark(PaintTarget t) { if (!((Object)(object)t == (Object)null) && Targets.TryGetValue(((Il2CppObjectBase)t).Pointer, out var value) && !value.Bloody && !((Object)(object)value.Rend == (Object)null)) { value.Rend.sharedMaterial = value.Blood; value.Bloody = true; } } } internal static class ClawSever { private class Claw { public GameObject Obj; public Rigidbody Rb; public Il2CppReferenceArray<Collider> Solid; public Transform[] Bottom = (Transform[])(object)new Transform[3]; public Transform[] Top = (Transform[])(object)new Transform[3]; public Vector3[] PrevBottom = (Vector3[])(object)new Vector3[3]; public Vector3[] PrevTop = (Vector3[])(object)new Vector3[3]; public bool HasPrev; public bool[] Near = new bool[3]; public int Idle; } private class Track { public Vector3 Entry; public float Seen; public string Name; public float MinProg = 1f; public float MaxSide; public float EntryMag; public float Half; public bool Tip; public bool Cut; public bool Valid; public int Steps; } private static readonly float MinSpeed = (float.TryParse(Environment.GetEnvironmentVariable("WC_SEVERSPEED"), out var result) ? result : 0.75f); public static Instance Log; public static int Severed; private static readonly List<Claw> Claws = new List<Claw>(); private static readonly Dictionary<(IntPtr, IntPtr), Track> Tracks = new Dictionary<(IntPtr, IntPtr), Track>(); private static readonly HashSet<IntPtr> _seenThisStep = new HashSet<IntPtr>(); private static readonly Dictionary<IntPtr, SliceableObject> _partOf = new Dictionary<IntPtr, SliceableObject>(); private static bool _anyNear; public static bool Disabled { get { if (!ClawSharpness.Disabled) { return Environment.GetEnvironmentVariable("WC_NOSEVER") == "1"; } return true; } } public static void Add(GameObject obj, Instance log) { if (Log == null) { Log = log; } if ((Object)(object)obj == (Object)null) { return; } foreach (Claw claw2 in Claws) { if ((Object)(object)claw2.Obj != (Object)null && ((Il2CppObjectBase)claw2.Obj).Pointer == ((Il2CppObjectBase)obj).Pointer) { return; } } Claw claw = new Claw { Obj = obj, Rb = obj.GetComponent<Rigidbody>() }; List<Collider> list = new List<Collider>(); foreach (Collider componentsInChild in obj.GetComponentsInChildren<Collider>(true)) { if ((Object)(object)componentsInChild != (Object)null && !componentsInChild.isTrigger) { list.Add(componentsInChild); } } claw.Solid = new Il2CppReferenceArray<Collider>(list.ToArray()); for (int i = 0; i < 3; i++) { Transform val = obj.transform.Find($"Colliders/Blade{i}"); claw.Bottom[i] = ((val != null) ? val.Find("SlashPoints/Bottom") : null); claw.Top[i] = ((val != null) ? val.Find("SlashPoints/Top") : null); } Claws.Add(claw); } private static SliceableObject PartOf(Collider col, Rigidbody self) { if (_partOf.TryGetValue(((Il2CppObjectBase)col).Pointer, out var value)) { return value; } if (_partOf.Count > 4000) { _partOf.Clear(); } Rigidbody attachedRigidbody = col.attachedRigidbody; value = (((Object)(object)attachedRigidbody == (Object)null || (Object)(object)attachedRigidbody == (Object)(object)self) ? null : ((Component)col).GetComponentInParent<SliceableObject>()); _partOf[((Il2CppObjectBase)col).Pointer] = value; return value; } public static void ForgetColliders() { _partOf.Clear(); } public static void Tick() { //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_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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: 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_0124: 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_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_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_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: 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_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) if (Claws.Count == 0) { return; } float time = Time.time; float fixedDeltaTime = Time.fixedDeltaTime; for (int num = Claws.Count - 1; num >= 0; num--) { Claw claw = Claws[num]; if ((Object)(object)claw.Obj == (Object)null) { Claws.RemoveAt(num); } else { for (int i = 0; i < 3; i++) { Transform val = claw.Bottom[i]; Transform val2 = claw.Top[i]; if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { continue; } Vector3 position = val.position; Vector3 position2 = val2.position; Vector3 val3 = claw.PrevBottom[i]; Vector3 val4 = claw.PrevTop[i]; claw.PrevBottom[i] = position; claw.PrevTop[i] = position2; if (!claw.HasPrev || Disabled) { continue; } Vector3 val5 = position2 - position; float magnitude = ((Vector3)(ref val5)).magnitude; if (magnitude < 0.0001f) { continue; } Vector3 axis = (position2 - position) / magnitude; Vector3 val6 = (position + position2 - val3 - val4) * 0.5f; _seenThisStep.Clear(); if (((Vector3)(ref val6)).magnitude < 0.005f && !claw.Near[i] && claw.Idle % 5 != 0) { continue; } int num2 = Mathf.Clamp(Mathf.CeilToInt(((Vector3)(ref val6)).magnitude / 0.015f), 1, 10); _anyNear = false; for (int num3 = num2; num3 >= 1; num3--) { float num4 = (float)num3 / (float)num2; foreach (Collider item in (Il2CppArrayBase<Collider>)(object)Physics.OverlapCapsule(Vector3.Lerp(val3, position, num4), Vector3.Lerp(val4, position2, num4), 0.006f, -1, (QueryTriggerInteraction)1)) { if ((Object)(object)item != (Object)null) { Consider(claw, i, item, position, position2, val3, val4, magnitude, axis, time, fixedDeltaTime); } } } claw.Near[i] = _anyNear; } claw.HasPrev = true; claw.Idle++; } } if (Tracks.Count <= 0) { return; } List<(IntPtr, IntPtr)> list = null; foreach (KeyValuePair<(IntPtr, IntPtr), Track> track in Tracks) { if (!(time - track.Value.Seen > 0.15f)) { continue; } (list ?? (list = new List<(IntPtr, IntPtr)>())).Add(track.Key); Track value = track.Value; if (ClawSharpness.Tracing && !value.Cut) { Instance log = Log; if (log != null) { log.Msg($"SEVER no cut {value.Name}: {value.Steps} steps, came in {value.EntryMag * 100f:F1} cm from its middle (surface at {value.Half * 100f:F1} cm{(value.Valid ? "" : ", too close to the middle to count")}), got {(1f - value.MinProg) * 100f:F0}% of the way to/past it (100% = middle), fastest sideways {value.MaxSide:F1} m/s{(value.Tip ? ", tip/base only at times" : "")}"); } } } if (list == null) { return; } foreach (var item2 in list) { Tracks.Remove(item2); } } private static Vector3 Across(Vector3 centre, Vector3 a, Vector3 b, out float s, out float len) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_0035: 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_003b: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_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_005e: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_0072: Unknown result type (might be due to invalid IL or missing references) Vector3 val = b - a; len = ((Vector3)(ref val)).magnitude; Vector3 val2 = ((len > 1E-05f) ? ((b - a) / len) : Vector3.forward); s = Mathf.Clamp(Vector3.Dot(centre - a, val2), 0f, len); Vector3 val3 = centre - (a + val2 * s); return val3 - val2 * Vector3.Dot(val3, val2); } private static void Consider(Claw c, int i, Collider col, Vector3 p0, Vector3 p1, Vector3 q0, Vector3 q1, float len, Vector3 axis, float now, float dt) { //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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_00bb: 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_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_0285: 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_00e7: 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_00eb: 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_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0151: 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_0153: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_0316: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) SliceableObject val = PartOf(col, c.Rb); if ((Object)(object)val == (Object)null) { return; } _anyNear = true; if (!_seenThisStep.Add(((Il2CppObjectBase)val).Pointer) || !val.canBeSliced || (Object)(object)val.sliceOnInputCustom == (Object)null) { return; } Rigidbody attachedRigidbody = col.attachedRigidbody; if ((Object)(object)attachedRigidbody == (Object)null) { return; } Collider val2 = (((Object)(object)val.mainCollider != (Object)null) ? val.mainCollider : col); Bounds bounds = val2.bounds; Vector3 center = ((Bounds)(ref bounds)).center; float s; float len2; Vector3 val3 = Across(center, p0, p1, out s, out len2); (IntPtr, IntPtr) key = (((Il2CppObjectBase)c.Bottom[i]).Pointer, ((Il2CppObjectBase)val).Pointer); if (!Tracks.TryGetValue(key, out var value)) { float len3; Vector3 val4 = Across(center, q0, q1, out len2, out len3); float num = 0f; if (((Vector3)(ref val4)).sqrMagnitude > 1E-08f) { Vector3 normalized = ((Vector3)(ref val4)).normalized; RaycastHit val5 = default(RaycastHit); if (val2.Raycast(new Ray(center - normalized * 1f, normalized), ref val5, 1f)) { num = 1f - ((RaycastHit)(ref val5)).distance; } } bool flag = ((Vector3)(ref val4)).magnitude >= Mathf.Max(0.012f, num * 0.4f); value = new Track { Entry = (flag ? val4 : Vector3.zero), Valid = flag, Name = $"Blade{i} x {((Object)val).name}", EntryMag = ((Vector3)(ref val4)).magnitude, Half = num }; Tracks[key] = value; } value.Seen = now; value.Steps++; if (((Vector3)(ref value.Entry)).sqrMagnitude < 1E-08f) { return; } value.MinProg = Mathf.Min(value.MinProg, Vector3.Dot(val3, value.Entry) / ((Vector3)(ref value.Entry)).sqrMagnitude); Vector3 val6 = p0 + axis * s; Vector3 val7 = q0 + (q1 - q0) * (s / len); Vector3 val8 = (val6 - val7) / dt - attachedRigidbody.GetPointVelocity(val6); Vector3 side = val8 - axis * Vector3.Dot(val8, axis); value.MaxSide = Mathf.Max(value.MaxSide, ((Vector3)(ref side)).magnitude); bool flag2 = s <= 0.005f || s >= len - 0.005f; if (flag2) { value.Tip = true; } if (!(Vector3.Dot(val3, value.Entry) > 0f || flag2)) { if (((Vector3)(ref side)).magnitude < MinSpeed) { value.Entry = Vector3.zero; return; } value.Entry = Vector3.zero; value.Cut = true; Cut(c, val, val6, axis, side, val8, attachedRigidbody); } } private static void Cut(Claw c, SliceableObject part, Vector3 at, Vector3 axis, Vector3 side, Vector3 rel, Rigidbody partRb) { //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_0003: 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_001c: 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_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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.Cross(axis, side); if (((Vector3)(ref val)).sqrMagnitude < 1E-08f) { return; } Plane val2 = default(Plane); ((Plane)(ref val2))..ctor(((Vector3)(ref val)).normalized, at); string name = ((Object)part).name; try { SliceableBodyPart val3 = ((Il2CppObjectBase)part).TryCast<SliceableBodyPart>(); if ((Object)(object)val3 != (Object)null) { ((SliceableObject)val3).SliceObject(val2, at, rel, c.Rb, c.Solid, part.directlyConnectedRb, 0.3f); } else { part.SliceObject(val2, at, rel, c.Rb, c.Solid, part.directlyConnectedRb, 0.3f); } Severed++; Instance log = Log; if (log != null) { log.Msg($"CLAW cut off '{((Object)((Component)partRb).transform.root).name}/{name}' at {((Vector3)(ref side)).magnitude:F1} m/s"); } } catch (Exception ex) { Instance log2 = Log; if (log2 != null) { log2.Warning("Cutting '" + name + "' failed: " + ex.Message); } } } } internal static class ClawSharpness { [HarmonyPatch(typeof(SharpWeaponManager), "HandleCollision")] private static class ClawCollision { private static void Prefix(SharpWeaponManager __instance, Collision collision) { if (Disabled || (Object)(object)__instance == (Object)null || !ClawManagers.Contains(((Il2CppObjectBase)__instance).Pointer)) { return; } try { TraceImpulse(collision); } catch { } try { LogContact(collision); } catch { } try { CutThroughArmour(collision, __instance); } catch { } try { PassThrough(collision, __instance); } catch { } try { Soften(collision); } catch { } } } [HarmonyPatch(typeof(SharpWeaponManager), "HandleSlashJoints")] private static class LoosenAfterStep { private static void Postfix(SharpWeaponManager __instance) { try { Loosen(__instance); } catch { } } } [HarmonyPatch(typeof(SharpWeaponManager), "HandleSlashJointCreation")] private static class LoosenAfterCreate { private static void Postfix(SharpWeaponManager __instance) { try { Loosen(__instance); } catch { } } } private class Pass { public SharpWeaponManager Claws; public Rigidbody Part; public Collider[] Mine; public Collider[] Theirs; public float LastNear; } [HarmonyPatch(typeof(SharpWeaponManager), "AssignNewJointValues")] private static class LoosenAfterAssign { private static void Postfix(SharpWeaponManager __instance) { try { Loosen(__instance); } catch { } } } [HarmonyPatch(typeof(SharpWeaponManager), "ForceLockJointOnAxes")] private static class LoosenAfterLock { private static void Postfix(SharpWeaponManager __instance) { try { Loosen(__instance); } catch { } } } [HarmonyPatch(typeof(SliceableBodyPart), "ObjectSlashed")] private static class BodySlashed { private static void Prefix() { Slashes++; } } [HarmonyPatch(typeof(SliceableBodyPart), "SliceObject")] private static class BodySliced { private static void Prefix(SliceableBodyPart __instance) { Slices++; if (Tracing) { Instance log = Log; if (log != null) { log.Msg("SEVERED '" + ((__instance != null) ? ((Object)__instance).name : null) + "'"); } } } } private const float CoverageToSever = 0.2f; private static readonly float ResistanceScale = (float.TryParse(Environment.GetEnvironmentVariable("WC_BODYSCALE"), out var result) ? result : 0.02f); private static readonly HashSet<IntPtr> ClawManagers = new HashSet<IntPtr>(); private static readonly HashSet<IntPtr> Softened = new HashSet<IntPtr>(); private static readonly HashSet<IntPtr> Armour = new HashSet<IntPtr>(); public static Instance Log; private static readonly HashSet<IntPtr> Logged = new HashSet<IntPtr>(); public static bool Tracing; public static readonly Dictionary<string, float> Impulses = new Dictionary<string, float>(); private static readonly float Hold = (float.TryParse(Environment.GetEnvironmentVariable("WC_HOLD"), out var result2) ? result2 : 0f); private static bool _loggedLoosen; private static readonly Dictionary<(IntPtr, IntPtr), Pass> Passing = new Dictionary<(IntPtr, IntPtr), Pass>(); public static int Slashes; public static int Slices; public static bool Disabled => Environment.GetEnvironmentVariable("WC_OLDSHARP") == "1"; public static int SoftenedCount => Softened.Count; public static int PassingCount => Passing.Count; public static void Apply(GameObject claws, Instance log) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) if (Log == null) { Log = log; } if (Disabled || (Object)(object)claws == (Object)null) { return; } SharpWeaponManager component = claws.GetComponent<SharpWeaponManager>(); if ((Object)(object)component == (Object)null) { log.Warning("No SharpWeaponManager on the claws; sharpness not applied"); return; } component.canRunThrough = true; component.stabRequiredImpulseMagnitude = 0.1f; component.slashRequiredImpulseMagnitude = 0.15f; component.slashingThreshold = 0f; component.isSlashDualSided = true; component.slashForwardAngleRange = new Vector2(85f, 89.9f); component.slashUpAngleRange = new Vector2(85f, 89.9f); component.stabAngleRange = new Vector2(85f, 89.9f); SlashingSharpnessScriptableObject slashingSharpnessData = component.slashingSharpnessData; if ((Object)(object)slashingSharpnessData != (Object)null) { slashingSharpnessData.frictionCoefficient = 0.02f; slashingSharpnessData.flatStabFrictionMultiplier = 0.05f; slashingSharpnessData.stabDepthForMaxStabMultiplier = 0.01f; slashingSharpnessData.minimumChopSpring = 0.5f; slashingSharpnessData.maximumChopSpring = 5f; slashingSharpnessData.minimumStabSpring = 0.1f; slashingSharpnessData.maximumStabSpring = 1f; slashingSharpnessData.chopLockVelocityThreshold = 100f; slashingSharpnessData.chopUnlockForceThreshold = 1f; slashingSharpnessData.chopInstantUnlockForceThreshold = 2f; slashingSharpnessData.stabLockVelocityThreshold = 100f; slashingSharpnessData.stabUnlockForceThreshold = 1f; slashingSharpnessData.stabInstantUnlockForceThreshold = 2f; slashingSharpnessData.useStabOutsideLockForces = true; slashingSharpnessData.stabUnlockOutsideForceThreshold = 1f; slashingSharpnessData.stabInstantUnlockOutsideForceThreshold = 2f; } else { log.Warning("Claws have no cutting profile; only partial sharpness applied"); } if ((Object)(object)slashingSharpnessData != (Object)null) { if (float.TryParse(Environment.GetEnvironmentVariable("WC_LOCKVEL"), out var result)) { slashingSharpnessData.stabLockVelocityThreshold = result; slashingSharpnessData.chopLockVelocityThreshold = result; } if (float.TryParse(Environment.GetEnvironmentVariable("WC_UNLOCK"), out var result2)) { slashingSharpnessData.stabUnlockForceThreshold = result2; slashingSharpnessData.stabInstantUnlockForceThreshold = result2 * 2f; slashingSharpnessData.chopUnlockForceThreshold = result2; slashingSharpnessData.chopInstantUnlockForceThreshold = result2 * 2f; slashingSharpnessData.stabUnlockOutsideForceThreshold = result2; slashingSharpnessData.stabInstantUnlockOutsideForceThreshold = result2 * 2f; } if (float.TryParse(Environment.GetEnvironmentVariable("WC_SPRING"), out var result3)) { slashingSharpnessData.minimumStabSpring = result3 * 0.1f; slashingSharpnessData.maximumStabSpring = result3; slashingSharpnessData.minimumChopSpring = result3 * 0.1f; slashingSharpnessData.maximumChopSpring = result3; } if (float.TryParse(Environment.GetEnvironmentVariable("WC_FRICTION"), out var result4)) { slashingSharpnessData.frictionCoefficient = result4; } } SlicerWeaponController component2 = claws.GetComponent<SlicerWeaponController>(); if ((Object)(object)component2 != (Object)null) { component2.sliceThreshold = 0f; component2.continueSliceThreshold = 0f; component2.slicePower = 3; } ClawManagers.Add(((Il2CppObjectBase)component).Pointer); } private static void CutThroughArmour(Collision c, SharpWeaponManager claws) { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //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_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: 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) Collider collider = c.collider; if ((Object)(object)collider == (Object)null) { return; } ArmorPiece componentInParent = ((Component)collider).GetComponentInParent<ArmorPiece>(); if ((Object)(object)componentInParent == (Object)null) { return; } foreach (Collider componentsInChild in ((Component)claws).GetComponentsInChildren<Collider>()) { foreach (Collider componentsInChild2 in ((Component)componentInParent).GetComponentsInChildren<Collider>()) { Physics.IgnoreCollision(componentsInChild, componentsInChild2, true); } } if (!Armour.Add(((Il2CppObjectBase)componentInParent).Pointer)) { return; } Vector3 val; if (c.contactCount <= 0) { Bounds bounds = collider.bounds; val = ((Bounds)(ref bounds)).center; } else { ContactPoint contact = c.GetContact(0); val = ((ContactPoint)(ref contact)).point; } Vector3 val2 = val; try { componentInParent.armorHealth = 0; if ((Object)(object)componentInParent.fracOnInput != (Object)null) { componentInParent.fracOnInput.ForceFracture(val2); } } catch { } Instance log = Log; if (log != null) { log.Msg("CLAW cut through armour '" + ((Object)componentInParent).name + "'"); } } private static void LogContact(Collision c) { Rigidbody val = ((c != null) ? c.rigidbody : null); Collider val2 = ((c != null) ? c.collider : null); if ((Object)(object)val2 == (Object)null) { return; } IntPtr item = (((Object)(object)val != (Object)null) ? ((Il2CppObjectBase)val).Pointer : ((Il2CppObjectBase)val2).Pointer); if (!Logged.Add(item) || Logged.Count > 400) { return; } SliceableObject val3 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponentInParent<SliceableObject>() : null); object obj; if (!((Object)(object)((Component)val2).GetComponentInParent<ArmorPiece>() != (Object)null)) { if (!((Object)(object)val3 != (Object)null)) { obj = "not cuttable"; } else { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(30, 3); defaultInterpolatedStringHandler.AppendLiteral("flesh '"); defaultInterpolatedStringHandler.AppendFormatted(((Object)val3).name); defaultInterpolatedStringHandler.AppendLiteral("' coverage="); defaultInterpolatedStringHandler.AppendFormatted(val3.sliceCoverageToProcSlice, "F2"); defaultInterpolatedStringHandler.AppendLiteral(" settings='"); SliceableObjectSettings sliceableObjectSettings = val3.sliceableObjectSettings; defaultInterpolatedStringHandler.AppendFormatted((sliceableObjectSettings != null) ? ((Object)sliceableObjectSettings).name : null); defaultInterpolatedStringHandler.AppendLiteral("'"); obj = defaultInterpolatedStringHandler.ToStringAndClear(); } } else { obj = "ARMOUR"; } string value = (string)obj; Instance log = Log; if (log != null) { log.Msg($"CLAW hit '{((Object)((Component)val2).transform.root).name}/{((Object)val2).name}': {value}"); } } private static void Soften(Collision c) { Rigidbody val = ((c != null) ? c.rigidbody : null); if ((Object)(object)val == (Object)null) { return; } SliceableObject val2 = ((Component)val).GetComponent<SliceableObject>(); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)val).GetComponentInParent<SliceableObject>(); } if (!((Object)(object)val2 == (Object)null) && Softened.Add(((Il2CppObjectBase)val2).Pointer)) { if (val2.sliceCoverageToProcSlice > 0.2f) { val2.sliceCoverageToProcSlice = 0.2f; } SliceableObjectSettings sliceableObjectSettings = val2.sliceableObjectSettings; if ((Object)(object)sliceableObjectSettings != (Object)null) { SliceableObjectSettings val3 = Object.Instantiate<SliceableObjectSettings>(sliceableObjectSettings); ((Object)val3).name = ((Object)sliceableObjectSettings).name + " (claw-softened)"; val3.frictionForce1 *= ResistanceScale; val3.frictionForce2 *= ResistanceScale; val3.chopMaxFrictionForce *= ResistanceScale; val3.stabMaxFrictionForce *= ResistanceScale; val2.sliceableObjectSettings = val3; } } } private static void TraceImpulse(Collision c) { //IL_002b: 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) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) if (Tracing && c != null && !((Object)(object)c.collider == (Object)null)) { object obj; if (c.contactCount <= 0) { obj = "?"; } else { ContactPoint contact = c.GetContact(0); Collider thisCollider = ((ContactPoint)(ref contact)).thisCollider; obj = ((thisCollider != null) ? ((Object)thisCollider).name : null); } string value = (string)obj; string key = $"{value} x '{((Object)((Component)c.collider).transform.root).name}/{((Object)c.collider).name}' (layer {LayerMask.LayerToName(((Component)c.collider).gameObject.layer)})"; Impulses.TryGetValue(key, out var value2); Dictionary<string, float> impulses = Impulses; float num = value2; Vector3 impulse = c.impulse; impulses[key] = num + ((Vector3)(ref impulse)).magnitude; } } private static void Loosen(SharpWeaponManager swm) { //IL_0046: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: 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_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) //IL_0108: Unknown result type (might be due to invalid IL or missing references) if (Disabled || Environment.GetEnvironmentVariable("WC_NOLOOSEN") == "1" || (Object)(object)swm == (Object)null || !ClawManagers.Contains(((Il2CppObjectBase)swm).Pointer)) { return; } List<SlashJointInfo> slashInfos = swm.slashInfos; if (slashInfos == null) { return; } JointDrive val = default(JointDrive); ((JointDrive)(ref val)).positionSpring = 0f; ((JointDrive)(ref val)).positionDamper = Hold; ((JointDrive)(ref val)).maximumForce = ((Hold > 0f) ? float.MaxValue : 0f); JointDrive val2 = val; for (int i = 0; i < slashInfos.Count; i++) { SlashJointInfo obj = slashInfos[i]; ConfigurableJoint val3 = ((obj != null) ? obj.slashStickyJoint : null); if ((Object)(object)val3 == (Object)null) { continue; } val3.xMotion = (ConfigurableJointMotion)2; val3.yMotion = (ConfigurableJointMotion)2; val3.zMotion = (ConfigurableJointMotion)2; val3.angularXMotion = (ConfigurableJointMotion)2; val3.angularYMotion = (ConfigurableJointMotion)2; val3.angularZMotion = (ConfigurableJointMotion)2; val3.xDrive = val2; val3.yDrive = val2; val3.zDrive = val2; val3.angularXDrive = val2; val3.angularYZDrive = val2; val3.slerpDrive = val2; if (!_loggedLoosen) { _loggedLoosen = true; Instance log = Log; if (log != null) { log.Msg("CLAW joint loosened: claws pass through"); } } } } private static Collider[] Blades(SharpWeaponManager claws) { List<Collider> list = new List<Collider>(); foreach (Collider componentsInChild in ((Component)claws).GetComponentsInChildren<Collider>(true)) { if ((Object)(object)componentsInChild != (Object)null && !componentsInChild.isTrigger && ((Object)componentsInChild).name != "Handle") { list.Add(componentsInChild); } } return list.ToArray(); } private static void PassThrough(Collision c, SharpWeaponManager claws) { //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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) if (Environment.GetEnvironmentVariable("WC_NOPASS") == "1") { return; } Rigidbody rigidbody = c.rigidbody; if ((Object)(object)rigidbody == (Object)null || (Object)(object)((Component)rigidbody).GetComponentInParent<SliceableObject>() == (Object)null || (Object)(object)((Component)c.collider).GetComponentInParent<ArmorPiece>() != (Object)null) { return; } bool flag = false; ContactPoint contact; for (int i = 0; i < c.contactCount; i++) { contact = c.GetContact(i); Collider thisCollider = ((ContactPoint)(ref contact)).thisCollider; if ((Object)(object)thisCollider != (Object)null && ((Object)thisCollider).name != "Handle") { flag = true; break; } } if (!flag) { return; } (IntPtr, IntPtr) key = (((Il2CppObjectBase)claws).Pointer, ((Il2CppObjectBase)rigidbody).Pointer); Collider[] mine; if (Passing.TryGetValue(key, out var value)) { value.LastNear = Time.time; contact = c.GetContact(0); if (Physics.GetIgnoreCollision(((ContactPoint)(ref contact)).thisCollider, c.collider)) { return; } mine = value.Mine; foreach (Collider val in mine) { Collider[] theirs = value.Theirs; foreach (Collider val2 in theirs) { if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null) { Physics.IgnoreCollision(val, val2, true); } } } if (Tracing) { Instance log = Log; if (log != null) { log.Msg("CLAW re-ignored '" + ((Object)rigidbody).name + "' (collision had come back)"); } } return; } List<Collider> list = new List<Collider>(); foreach (Collider componentsInChild in ((Component)rigidbody).GetComponentsInChildren<Collider>()) { if ((Object)(object)componentsInChild != (Object)null && !componentsInChild.isTrigger && (Object)(object)componentsInChild.attachedRigidbody == (Object)(object)rigidbody) { list.Add(componentsInChild); } } if (!list.Contains(c.collider)) { list.Add(c.collider); } value = new Pass { Claws = claws, Part = rigidbody, Mine = Blades(claws), Theirs = list.ToArray(), LastNear = Time.time }; mine = value.Mine; foreach (Collider val3 in mine) { Collider[] theirs = value.Theirs; foreach (Collider val4 in theirs) { Physics.IgnoreCollision(val3, val4, true); } } Passing[key] = value; if (Tracing) { Instance log2 = Log; if (log2 != null) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(84, 5); defaultInterpolatedStringHandler.AppendLiteral("CLAW passing through '"); defaultInterpolatedStringHandler.AppendFormatted(((Object)rigidbody).name); defaultInterpolatedStringHandler.AppendLiteral("' ("); defaultInterpolatedStringHandler.AppendFormatted(value.Mine.Length); defaultInterpolatedStringHandler.AppendLiteral(" claw colliders x "); defaultInterpolatedStringHandler.AppendFormatted(value.Theirs.Length); defaultInterpolatedStringHandler.AppendLiteral(" of its colliders; hit by "); contact = c.GetContact(0); Collider thisCollider2 = ((ContactPoint)(ref contact)).thisCollider; defaultInterpolatedStringHandler.AppendFormatted((thisCollider2 != null) ? ((Object)thisCollider2).name : null); defaultInterpolatedStringHandler.AppendLiteral(", ignored now="); contact = c.GetContact(0); defaultInterpolatedStringHandler.AppendFormatted(Physics.GetIgnoreCollision(((ContactPoint)(ref contact)).thisCollider, c.collider)); defaultInterpolatedStringHandler.AppendLiteral(")"); log2.Msg(defaultInterpolatedStringHandler.ToStringAndClear()); } } } public static void Tick() { //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_00ad: Unknown result type (might be due to invalid IL or missing references) if (Passing.Count == 0) { return; } List<(IntPtr, IntPtr)> list = null; foreach (KeyValuePair<(IntPtr, IntPtr), Pass> item in Passing) { Pass value = item.Value; bool flag = (Object)(object)value.Claws == (Object)null || (Object)(object)value.Part == (Object)null; if (!flag) { bool flag2 = false; Collider[] mine = value.Mine; foreach (Collider val in mine) { if ((Object)(object)val == (Object)null) { continue; } Bounds bounds = val.bounds; ((Bounds)(ref bounds)).Expand(0.06f); Collider[] theirs = value.Theirs; foreach (Collider val2 in theirs) { if ((Object)(object)val2 != (Object)null && ((Bounds)(ref bounds)).Intersects(val2.bounds)) { flag2 = true; break; } } if (flag2) { break; } } if (flag2) { value.LastNear = Time.time; } else if (Time.time - value.LastNear > 0.2f) { mine = value.Mine; foreach (Collider val3 in mine) { Collider[] theirs = value.Theirs; foreach (Collider val4 in theirs) { if ((Object)(object)val3 != (Object)null && (Object)(object)val4 != (Object)null) { Physics.IgnoreCollision(val3, val4, false); } } } if (Tracing) { Instance log = Log; if (log != null) { log.Msg("CLAW clear of '" + ((Object)value.Part).name + "', collision back"); } } flag = true; } } if (flag) { (list ?? (list = new List<(IntPtr, IntPtr)>())).Add(item.Key); } } if (list == null) { return; } foreach (var item2 in list) { Passing.Remove(item2); } } public static void ResetCounters() { Slashes = 0; Slices = 0; } } public class ClawsMod : MelonMod { private class Side { public bool Left; public HVRHandGrabber Hand; public GameObject Claws; public HVRGrabbable Grabbable; public bool AutoChecked; public bool PrevTrigger; public int Button = -1; public bool Anchored; public Transform AnchorRef; public Vector3[] AnchorPos = (Vector3[])(object)new Vector3[3]; public Quaternion[] AnchorRot = (Quaternion[])(object)new Quaternion[3]; public Vector3 AnchorDir; public float AnchorSpan; public float Slide; public int Corrections; public int BaseJoints; public int SkippedInCut; } private enum ClawBtn { BY, AX, Menu, Trackpad, StickClick, FistTrigger, KeyboardOnly } private struct ClawAnchor { public Vector3[] Base; public Quaternion[] Rot; public Vector3 Dir; public float Span; public Vector3 Centre; public Vector3 Axis; public Vector3 Dorsal; public Transform Ref; public float Curl; } private const float GripThreshold = 0.6f; private const float TriggerThreshold = 0.6f; private readonly Side _left = new Side { Left = true }; private readonly Side _right = new Side { Left = false }; private float _nextHandSearch; private MeleeScriptableObject _baseSo; private MelonPreferences_Category _cat; private MelonPreferences_Entry<float> _clawLength; private MelonPreferences_Entry<float> _clawSpacing; private MelonPreferences_Entry<float> _knuckleOffset; private MelonPreferences_Entry<float> _clawYaw; private MelonPreferences_Entry<float> _clawPitch; private MelonPreferences_Entry<float> _clawSplay; private MelonPreferences_Entry<bool> _requireGrip; private MelonPreferences_Entry<bool> _debugDump; private MelonPreferences_Entry<bool> _inputDebug; private MelonPreferences_Entry<bool> _anchorToKnuckles; private MelonPreferences_Entry<Key> _keyLeft; private MelonPreferences_Entry<Key> _keyRight; private readonly bool _perfOnly = Environment.GetEnvironmentVariable("WC_PERFONLY") == "1"; private readonly bool _perf = Environment.GetEnvironmentVariable("WC_PERF") == "1"; private readonly Stopwatch _sw = new Stopwatch(); private double _perfModMs; private double _perfWorst; private int _perfFrames; private float _perfT; private int _tickWarnings; private double _perfFixedMs; private int _perfSteps; private readonly Stopwatch _swFixed = new Stopwatch(); private readonly bool _autoTest = Environment.GetEnvironmentVariable("WC_AUTOTEST") == "1"; private bool _autoDone; private bool _scenesListed; private float _autoAt; private MelonPreferences_Entry<string> _clawButton; private const float KnuckleLift = -0.02f; private const float RootSink = 0.05f; private readonly bool _noLock = Environment.GetEnvironmentVariable("WC_NOLOCK") == "1"; private readonly bool _oldSharp = Environment.GetEnvironmentVariable("WC_OLDSHARP") == "1"; private readonly bool _oldStab = Environment.GetEnvironmentVariable("WC_OLDSTAB") == "1"; private bool _swingActive; private float _renderedWorstD; private float _renderedWorstA; private int _renderedSamples; private readonly bool _photo = Environment.GetEnvironmentVariable("WC_PHOTO") == "1"; private readonly bool _bloodTest = Environment.GetEnvironmentVariable("WC_BLOODTEST") == "1"; private readonly bool _driveTest; private readonly bool _slashTest; private readonly bool _hitTest; private readonly bool _swingTest; private int _shotW; private int _shotH; private static string ShotDir => Environment.GetEnvironmentVariable("WC_SHOTDIR") ?? Path.Combine(MelonEnvironment.UserDataDirectory, "WolverineClaws"); private void DumpInputMap() { StringBuilder stringBuilder = new StringBuilder(); IntPtr intPtr = IntPtr.Zero; foreach (ProcessModule module in Process.GetCurrentProcess().Modules) { if (module.ModuleName.Equals("GameAssembly.dll", StringComparison.OrdinalIgnoreCase)) { intPtr = module.BaseAddress; } } StringBuilder stringBuilder2 = stringBuilder; StringBuilder stringBuilder3 = stringBuilder2; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(18, 1, stringBuilder2); handler.AppendLiteral("GameAssembly base "); handler.AppendFormatted(intPtr.ToInt64(), "X"); stringBuilder3.AppendLine(ref handler); BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.NonPublic; Assembly[] array = new Assembly[2] { typeof(MeleeWeaponWrapper).Assembly, typeof(HVRController).Assembly }; for (int i = 0; i < array.Length; i++) { Type[] types = array[i].GetTypes(); foreach (Type type in types) { FieldInfo[] fields = type.GetFields(bindingAttr); foreach (FieldInfo fieldInfo in fields) { try { if (fieldInfo.FieldType != typeof(IntPtr)) { continue; } IntPtr intPtr2 = (IntPtr)fieldInfo.GetValue(null); if (intPtr2 == IntPtr.Zero) { continue; } if (fieldInfo.Name.StartsWith("NativeMethodInfoPtr_")) { IntPtr intPtr3 = Marshal.ReadIntPtr(intPtr2); if (intPtr3 != IntPtr.Zero && intPtr != IntPtr.Zero) { stringBuilder2 = stringBuilder; StringBuilder stringBuilder4 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(4, 3, stringBuilder2); handler.AppendLiteral("M "); handler.AppendFormatted(6442450944L + (intPtr3.ToInt64() - intPtr.ToInt64()), "X"); handler.AppendLiteral(" "); handler.AppendFormatted(type.FullName); handler.AppendLiteral("."); handler.AppendFormatted(fieldInfo.Name.Substring(20)); stringBuilder4.AppendLine(ref handler); } } else if (fieldInfo.Name.StartsWith("NativeFieldInfoPtr_")) { uint value = IL2CPP.il2cpp_field_get_offset(intPtr2); stringBuilder2 = stringBuilder; StringBuilder stringBuilder5 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(5, 3, stringBuilder2); handler.AppendLiteral("F "); handler.AppendFormatted(type.FullName); handler.AppendLiteral(" +"); handler.AppendFormatted(value); handler.AppendLiteral(" "); handler.AppendFormatted(fieldInfo.Name.Substring(19)); stringBuilder5.AppendLine(ref handler); } } catch { } } } } Directory.CreateDirectory(ShotDir); File.WriteAllText(Path.Combine(ShotDir, "inputmap.txt"), stringBuilder.ToString()); ((MelonBase)this).LoggerInstance.Msg("INPUTMAP written"); } private void ScanButtonEvents(string scene) { StringBuilder stringBuilder = new StringBuilder("BUTTONSCAN " + scene + "\n"); foreach (MonoBehaviour item in Resources.FindObjectsOfTypeAll<MonoBehaviour>()) { if ((Object)(object)item == (Object)null) { continue; } string name = ((MemberInfo)((Object)item).GetIl2CppType()).Name; if (!name.EndsWith("ButtonEvents") && !name.Contains("ButtonEvent")) { switch (name) { case "TimeStopController": case "ForceGrabToggle": case "NightLightToggle": case "PlayerKickManager": case "HVRInputModule": break; default: continue; } } string text = ((Object)((Component)item).gameObject).name; Transform parent = ((Component)item).transform.parent; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } StringBuilder stringBuilder2 = stringBuilder; StringBuilder stringBuilder3 = stringBuilder2; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(19, 3, stringBuilder2); handler.AppendLiteral(" "); handler.AppendFormatted(name); handler.AppendLiteral(" on '"); handler.AppendFormatted(text); handler.AppendLiteral("' (active="); handler.AppendFormatted(((Component)item).gameObject.activeInHierarchy); handler.AppendLiteral(")\n"); stringBuilder3.Append(ref handler); foreach (FieldInfo item2 in (Il2CppArrayBase<FieldInfo>)(object)((Object)item).GetIl2CppType().GetFields((BindingFlags)52)) { try { if (!((MemberInfo)item2.FieldType).Name.Contains("Event")) { continue; } Object value = item2.GetValue((Object)(object)item); UnityEventBase val = ((value != null) ? ((Il2CppObjectBase)value).TryCast<UnityEventBase>() : null); if (val != null) { int persistentEventCount = val.GetPersistentEventCount(); for (int i = 0; i < persistentEventCount; i++) { Object persistentTarget = val.GetPersistentTarget(i); stringBuilder2 = stringBuilder; StringBuilder stringBuilder4 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(12, 3, stringBuilder2); handler.AppendLiteral(" "); handler.AppendFormatted(((MemberInfo)item2).Name); handler.AppendLiteral(" -> "); handler.AppendFormatted((persistentTarget != (Object)null) ? (((MemberInfo)((Object)persistentTarget).GetIl2CppType()).Name + "('" + persistentTarget.name + "')") : "null"); handler.AppendLiteral("."); handler.AppendFormatted(val.GetPersistentMethodName(i)); handler.AppendLiteral("\n"); stringBuilder4.Append(ref handler); } } } catch { } } } ((MelonBase)this).LoggerInstance.Msg(stringBuilder.ToString()); } private static string Props(object o, string filter = null) { if (o == null) { return "null"; } StringBuilder stringBuilder = new StringBuilder(); PropertyInfo[] properties = o.GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public); foreach (PropertyInfo propertyInfo in properties) { Type propertyType = propertyInfo.PropertyType; if ((propertyType.IsPrimitive || propertyType.IsEnum || propertyType == typeof(Vector2) || propertyType == typeof(Vector3) || propertyType == typeof(string)) && (filter == null || Regex.IsMatch(propertyInfo.Name, filter))) { try { StringBuilder stringBuilder2 = stringBuilder; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(2, 2, stringBuilder2); handler.AppendLiteral(" "); handler.AppendFormatted(propertyInfo.Name); handler.AppendLiteral("="); handler.AppendFormatted<object>(propertyInfo.GetValue(o)); stringBuilder2.Append(ref handler); } catch { } } } return stringBuilder.ToString(); } private void DumpSharpness(string tag) { //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_0637: Unknown result type (might be due to invalid IL or missing references) //IL_0643: Unknown result type (might be due to invalid IL or missing references) StringBuilder stringBuilder = new StringBuilder("SHARPDUMP " + tag + "\n"); HashSet<IntPtr> hashSet = new HashSet<IntPtr>(); foreach (MeleeWeaponWrapper item in Resources.FindObjectsOfTypeAll<MeleeWeaponWrapper>()) { if ((Object)(object)item == (Object)null || (Object)(object)item.meleeWeaponSO == (Object)null) { continue; } MeleeScriptableObject meleeWeaponSO = item.meleeWeaponSO; if (!hashSet.Add(((Il2CppObjectBase)meleeWeaponSO).Pointer) && !((Object)item).name.Contains("Wolverine")) { continue; } StringBuilder stringBuilder2 = stringBuilder; StringBuilder stringBuilder3 = stringBuilder2; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(18, 3, stringBuilder2); handler.AppendLiteral("== "); handler.AppendFormatted(((Object)item).name); handler.AppendLiteral(" (SO '"); handler.AppendFormatted(((Object)meleeWeaponSO).name); handler.AppendLiteral("' type="); handler.AppendFormatted<MeleeWeaponType>(meleeWeaponSO.meleeWeaponType); handler.AppendLiteral(")\n"); stringBuilder3.Append(ref handler); stringBuilder.Append(" SO:" + Props(meleeWeaponSO) + "\n"); stringBuilder.Append(" wrapper:" + Props(item) + $" slashLines={((item.slashLines != null) ? ((Il2CppArrayBase<SlashLineInfo>)(object)item.slashLines).Length : (-1))} bladeColliders={((item.bladeColliders != null) ? ((Il2CppArrayBase<GameObject>)(object)item.bladeColliders).Length : (-1))}\n"); SharpWeaponManager component = ((Component)item).GetComponent<SharpWeaponManager>(); if ((Object)(object)component != (Object)null) { stringBuilder.Append(" SharpWeaponManager:" + Props(component, "Required|Threshold|canSlash|isSlash|isStab|AngleRange|slashDistance|Multiplier|flat|canRunThrough|tipAndBottom") + "\n"); SlashingSharpnessScriptableObject slashingSharpnessData = component.slashingSharpnessData; if ((Object)(object)slashingSharpnessData != (Object)null) { stringBuilder.Append(" sharpnessData '" + ((Object)slashingSharpnessData).name + "':" + Props(slashingSharpnessData) + "\n"); } else { stringBuilder.Append(" sharpnessData: null\n"); } } SlicerWeaponController component2 = ((Component)item).GetComponent<SlicerWeaponController>(); if ((Object)(object)component2 != (Object)null) { stringBuilder.Append(" SlicerWeaponController:" + Props(component2, "Threshold|Power|ignore|check") + "\n"); } if (!((Object)item).name.Contains("Wolverine") && !((Object)item).name.Contains("Lightsaber") && !((Object)item).name.Contains("Knife (Unsocketed")) { continue; } SortedSet<string> sortedSet = new SortedSet<string>(); foreach (Component componentsInChild in ((Component)item).GetComponentsInChildren<Component>(true)) { if ((Object)(object)componentsInChild != (Object)null) { sortedSet.Add(((MemberInfo)((Object)componentsInChild).GetIl2CppType()).Name); } } stringBuilder.Append(" components: " + string.Join(" ", sortedSet) + "\n"); foreach (Collider componentsInChild2 in ((Component)item).GetComponentsInChildren<Collider>(true)) { stringBuilder2 = stringBuilder; StringBuilder stringBuilder4 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(54, 6, stringBuilder2); handler.AppendLiteral(" collider '"); handler.AppendFormatted(((Object)componentsInChild2).name); handler.AppendLiteral("' "); handler.AppendFormatted(((MemberInfo)((Object)componentsInChild2).GetIl2CppType()).Name); handler.AppendLiteral(" trigger="); handler.AppendFormatted(componentsInChild2.isTrigger); handler.AppendLiteral(" tag="); handler.AppendFormatted(((Component)componentsInChild2).tag); handler.AppendLiteral(" modifiable="); handler.AppendFormatted(componentsInChild2.hasModifiableContacts); handler.AppendLiteral(" enabled="); handler.AppendFormatted(componentsInChild2.enabled); handler.AppendLiteral("\n"); stringBuilder4.Append(ref handler); } if (item.stabbingColliders != null) { foreach (Collider item2 in (Il2CppArrayBase<Collider>)(object)item.stabbingColliders) { if ((Object)(object)item2 != (Object)null) { stringBuilder2 = stringBuilder; StringBuilder stringBuilder5 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(26, 1, stringBuilder2); handler.AppendLiteral(" stabbingCollider '"); handler.AppendFormatted(((Object)item2).name); handler.AppendLiteral("'\n"); stringBuilder5.Append(ref handler); } } } if (item.bladeColliders != null) { foreach (GameObject item3 in (Il2CppArrayBase<GameObject>)(object)item.bladeColliders) { if ((Object)(object)item3 != (Object)null) { stringBuilder2 = stringBuilder; StringBuilder stringBuilder6 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(23, 1, stringBuilder2); handler.AppendLiteral(" bladeCollider '"); handler.AppendFormatted(((Object)item3).name); handler.AppendLiteral("'\n"); stringBuilder6.Append(ref handler); } } } if (item.slashLines != null) { foreach (SlashLineInfo item4 in (Il2CppArrayBase<SlashLineInfo>)(object)item.slashLines) { if (item4 != null) { stringBuilder2 = stringBuilder; StringBuilder stringBuilder7 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(54, 5, stringBuilder2); handler.AppendLiteral(" slashLine bottom='"); Transform slashBottom = item4.slashBottom; handler.AppendFormatted((slashBottom != null) ? ((Object)slashBottom).name : null); handler.AppendLiteral("' top='"); Transform slashTop = item4.slashTop; handler.AppendFormatted((slashTop != null) ? ((Object)slashTop).name : null); handler.AppendLiteral("' fwd='"); Transform slashForward = item4.slashForward; handler.AppendFormatted((slashForward != null) ? ((Object)slashForward).name : null); handler.AppendLiteral("' allowed="); handler.AppendFormatted((item4.allowedColliders != null) ? ((Il2CppArrayBase<Collider>)(object)item4.allowedColliders).Length : (-1)); handler.AppendLiteral(" len="); handler.AppendFormatted(((Object)(object)item4.slashBottom != (Object)null && (Object)(object)item4.slashTop != (Object)null) ? Vector3.Distance(item4.slashBottom.position, item4.slashTop.position) : 0f, "F3"); handler.AppendLiteral("\n"); stringBuilder7.Append(ref handler); } } } Il2CppArrayBase<ConfigurableJoint> components = ((Component)item).GetComponents<ConfigurableJoint>(); stringBuilder2 = stringBuilder; StringBuilder stringBuilder8 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(36, 1, stringBuilder2); handler.AppendLiteral(" configurable joints on root: "); handler.AppendFormatted(components.Length); handler.AppendLiteral("\n"); stringBuilder8.Append(ref handler); foreach (HVRStabber componentsInChild3 in ((Component)item).GetComponentsInChildren<HVRStabber>(true)) { stringBuilder.Append(" HVRStabber on '" + ((Object)componentsInChild3).name + "':" + Props(componentsInChild3, "^(StabAnything|IgnoreVelocityCheck|ProjectionDistance|ProjectionAngle|IsDualStabber|CanRunThrough|ContactOffset|Length)$") + $" stabColliders={((componentsInChild3.StabbingColliders != null) ? ((Il2CppArrayBase<Collider>)(object)componentsInChild3.StabbingColliders).Length : (-1))} tip={(((Object)(object)componentsInChild3.Tip != (Object)null) ? ((Object)componentsInChild3.Tip).name : "-")} base={(((Object)(object)componentsInChild3.Base != (Object)null) ? ((Object)componentsInChild3.Base).name : "-")}\n"); if ((Object)(object)componentsInChild3.Settings != (Object)null) { stringBuilder.Append(" Settings '" + ((Object)componentsInChild3.Settings).name + "':" + Props(componentsInChild3.Settings) + "\n"); } if ((Object)(object)componentsInChild3.FallbackSettings != (Object)null) { stringBuilder.Append(" Fallback '" + ((Object)componentsInChild3.FallbackSettings).name + "':" + Props(componentsInChild3.FallbackSettings) + "\n"); } } } int num = 0; foreach (HVRStabbable item5 in Resources.FindObjectsOfTypeAll<HVRStabbable>()) { if (!((Object)(object)item5 == (Object)null) && !((Object)(object)item5.Settings == (Object)null) && num < 4) { stringBuilder.Append($"== HVRStabbable '{((Object)item5).name}' settings '{((Object)item5.Settings).name}':" + Props(item5.Settings) + "\n"); num++; } } ((MelonBase)this).LoggerInstance.Msg(stringBuilder.ToString()); } private IEnumerator ScanLater(string scene) { float t = Time.time + 3f; while (Time.time < t) { yield return null; } if (Environment.GetEnvironmentVariable("WC_BUTTONSCAN") == "1") { try { ScanButtonEvents(scene); } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Warning("BUTTONSCAN: " + ex.Message); } } if (Environment.GetEnvironmentVariable("WC_SHARPDUMP") == "1") { try { DumpSharpness(scene); } catch (Exception ex2) { ((MelonBase)this).LoggerInstance.Warning("SHARPDUMP: " + ex2.Message); } t = Time.time + 14f; while (Time.time < t) { yield return null; } try { DumpSharpness(scene + " (after claws)"); } catch (Exception ex3) { ((MelonBase)this).LoggerInstance.Warning("SHARPDUMP: " + ex3.Message); } } } public override void OnInitializeMelon() { if (Environment.GetEnvironmentVariable("WC_INPUTMAP") == "1") { try { DumpInputMap(); } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Error("INPUTMAP: " + ex); } } _cat = MelonPreferences.CreateCategory("WolverineClaws"); _clawLength = _cat.CreateEntry<float>("ClawLength", 0.3f, (string)null, "Blade length in metres", false, false, (ValueValidator)null, (string)null); _clawSpacing = _cat.CreateEntry<float>("ClawSpacing", 0.022f, (string)null, "Gap between the three claws (along the knuckles)", false, false, (ValueValidator)null, (string)null); _knuckleOffset = _cat.CreateEntry<float>("KnuckleOffset", 0.035f, (string)null, "How far in front of the grip the claws start", false, false, (ValueValidator)null, (string)null); _clawYaw = _cat.CreateEntry<float>("ClawYaw", 0f, (string)null, "Rotate claws around the grip axis (try 90/180/270 if they point the wrong way)", false, false, (ValueValidator)null, (string)null); _clawPitch = _cat.CreateEntry<float>("ClawPitch", 0f, (string)null, "Tilt claws up/down", false, false, (ValueValidator)null, (string)null); _clawSplay = _cat.CreateEntry<float>("ClawSplay", 2.5f, (string)null, "How much the outer claws fan out, in degrees", false, false, (ValueValidator)null, (string)null); _requireGrip = _cat.CreateEntry<bool>("RequireFist", false, (string)null, "(unused) old fist+trigger control", false, false, (ValueValidator)null, (string)null); _debugDump = _cat.CreateEntry<bool>("DebugDump", false, (string)null, "Log the built claw hierarchy", false, false, (ValueValidator)null, (string)null); _anchorToKnuckles = _cat.CreateEntry<bool>("AnchorToKnuckles", true, (string)null, "Place claws between the knuckles of your actual hand (any hand size). Off = fixed placement using KnuckleOffset/ClawYaw/ClawPitch", false, false, (ValueValidator)null, (string)null); _inputDebug = _cat.CreateEntry<bool>("InputDebug", false, (string)null, "Log each B/Y press (to troubleshoot controls)", false, false, (ValueValidator)null, (string)null); _clawButton = _cat.CreateEntry<string>("ClawButton", "Auto", (string)null, "Button that pops the claws: Auto (B/Y; Menu on Vive wands; touchpad click on original WMR), BY, AX, Menu, Trackpad, StickClick, FistTrigger (squeeze grip on an empty hand + pull trigger) or KeyboardOnly", false, false, (ValueValidator)null, (string)null); _keyLeft = _cat.CreateEntry<Key>("KeyLeft", (Key)100, (string)null, "Keyboard toggle for left claws (testing)", false, false, (ValueValidator)null, (string)null); _keyRight = _cat.CreateEntry<Key>("KeyRight", (Key)101, (string)null, "Keyboard toggle for right claws (testing)", false, false, (ValueValidator)null, (string)null); ((MelonBase)this).LoggerInstance.Msg("SNIKT. Tap B (right hand) or Y (left hand) with an empty hand to pop the claws; tap again to retract. Vive wands: Menu; original WMR: touchpad click. ClawButton = " + _clawButton.Value); } public override void OnSceneWasInitialized(int buildIndex, string sceneName) { if (_perfOnly) { return; } ClawVisuals.OnSceneChanged(); try { ClawVisuals.GetMaterial(((MelonBase)this).LoggerInstance); ClawVisuals.ClawMesh(_clawLength.Value); ClawVisuals.ClawMesh(_clawLength.Value * 0.94f); } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Warning("Texture generation failed: " + ex.Message); } } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { ClawSever.ForgetColliders(); _left.Hand = (_right.Hand = null); _left.Claws = (_right.Claws = null); _left.Grabbable = (_right.Grabbable = null); _left.Anchored = (_right.Anchored = false); _baseSo = null; _nextHandSearch = 0f; _autoAt = 0f; ((MelonBase)this).LoggerInstance.Msg("Scene: " + sceneName); if (Environment.GetEnvironmentVariable("WC_BUTTONSCAN") == "1" || Environment.GetEnvironmentVariable("WC_SHARPDUMP") == "1") { MelonCoroutines.Start(ScanLater(sceneName)); } if (_autoTest && !_scenesListed) { _scenesListed = true; int sceneCountInBuildSettings = SceneManager.sceneCountInBuildSettings; for (int i = 0; i < sceneCountInBuildSettings; i++) { ((MelonBase)this).LoggerInstance.Msg($" build scene {i}: {SceneUtility.GetScenePathByBuildIndex(i)}"); } string environmentVariable = Environment.GetEnvironmentVariable("WC_SCENE"); if (!string.IsNullOrEmpty(environmentVariable)) { MelonCoroutines.Start(LoadLater(environmentVariable)); } } } public override void OnFixedUpdate() { if (_perf) { _swFixed.Restart(); _perfSteps++; } try { ClawSharpness.Tick(); } catch (Exception ex) { if (_tickWarnings++ < 5) { ((MelonBase)this).LoggerInstance.Warning("Pass-through tick: " + ex.Message); } } try { ClawSever.Tick(); } catch (Exception ex2) { if (_tickWarnings++ < 5) { ((MelonBase)this).LoggerInstance.Warning("Sever tick: " + ex2.Message); } } if (_perf) { _perfFixedMs += _swFixed.Elapsed.TotalMilliseconds; } } public override void OnUpdate() { //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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) if (!_perf) { UpdateCore(); return; } Scene activeScene; if (_perfOnly) { float unscaledDeltaTime = Time.unscaledDeltaTime; _perfFrames++; _perfT += unscaledDeltaTime; _perfWorst = Math.Max(_perfWorst, (double)unscaledDeltaTime * 1000.0); if (_perfT >= 5f) { Instance loggerInstance = ((MelonBase)this).LoggerInstance; DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(26, 3); defaultInterpolatedStringHandler.AppendLiteral("PERFONLY "); activeScene = SceneManager.GetActiveScene(); defaultInterpolatedStringHandler.AppendFormatted(((Scene)(ref activeScene)).name); defaultInterpolatedStringHandler.AppendLiteral(": "); defaultInterpolatedStringHandler.AppendFormatted((float)_perfFrames / _perfT, "F1"); defaultInterpolatedStringHandler.AppendLiteral(" fps, worst "); defaultInterpolatedStringHandler.AppendFormatted(_perfWorst, "F1"); defaultInterpolatedStringHandler.AppendLiteral(" ms"); loggerInstance.Msg(defaultInterpolatedStringHandler.ToStringAndClear()); _perfFrames = 0; _perfT = 0f; _perfWorst = 0.0; } return; } _sw.Restart(); UpdateCore(); _perfModMs += _sw.Elapsed.TotalMilliseconds; float unscaledDeltaTime2 = Time.unscaledDeltaTime; _perfFrames++; _perfT += unscaledDeltaTime2; _perfWorst = Math.Max(_perfWorst, (double)unscaledDeltaTime2 * 1000.0); if (_perfT >= 5f) { Instance loggerInstance2 = ((MelonBase)this).LoggerInstance; DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(69, 7); defaultInterpolatedStringHandler.AppendLiteral("PERF "); activeScene = SceneManager.GetActiveScene(); defaultInterpolatedStringHandler.AppendFormatted(((Scene)(ref activeScene)).name); defaultInterpolatedStringHandler.AppendLiteral(": "); defaultInterpolatedStringHandler.AppendFormatted((float)_perfFrames / _perfT, "F1"); defaultInterpolatedStringHandler.AppendLiteral(" fps, worst "); defaultInterpolatedStringHandler.AppendFormatted(_perfWorst, "F1"); defaultInterpolatedStringHandler.AppendLiteral(" ms, mod "); defaultInterpolatedStringHandler.AppendFormatted(_perfModMs / (double)_perfFrames * 1000.0, "F1"); defaultInterpolatedStringHandler.AppendLiteral(" us/frame + "); defaultInterpolatedStringHandler.AppendFormatted((_perfSteps > 0) ? (_perfFixedMs / (double)_perfSteps * 1000.0) : 0.0, "F1"); defaultInterpolatedStringHandler.AppendLiteral(" us/physics step, claws L="); defaultInterpolatedStringHandler.AppendFormatted((Object)(object)_left.Claws != (Object)null); defaultInterpolatedStringHandler.AppendLiteral(" R="); defaultInterpolatedStringHandler.AppendFormatted((Object)(object)_right.Claws != (Object)null); loggerInstance2.Msg(defaultInterpolatedStringHandler.ToStringAndClear()); _perfFrames = 0; _perfT = 0f; _perfWorst = 0.0; _perfModMs = 0.0; _perfFixedMs = 0.0; _perfSteps = 0; } } private void UpdateCore() { if (Time.time >= _nextHandSearch && ((Object)(object)_left.Hand == (Object)null || (Object)(object)_right.Hand == (Object)null)) { _nextHandSearch = Time.time + 2f; FindHands(); } Tick(_left); Tick(_right); if (!_autoTest || _autoDone || !((Object)(object)_left.Hand != (Object)null) || !((Object)(object)_right.Hand != (Object)null) || !((Object)(object)ModLoaderMelee.instanceOfThis != (Object)null)) { return; } if (_autoAt == 0f) { _autoAt = Time.time + (float.TryParse(Environment.GetEnvironmentVariable("WC_POPDELAY"), out var result) ? result : 8f); } else if (Time.time >= _autoAt) { _autoDone = true; ((MelonBase)this).LoggerInstance.Msg("AUTOTEST pop"); if (!_photo && !_bloodTest && !_hitTest && !_swingTest && !_slashTest && !_driveTest) { Pop(_left); } Pop(_right); } } private IEnumerator LoadLater(string scene) { float until = Time.time + 6f; while (Time.time < until) { yield return null; } ((MelonBase)this).LoggerInstance.Msg("AUTOTEST loading " + scene); SceneManager.LoadScene(scene); } private void FindHands() { foreach (HVRHandGrabber item in Object.FindObjectsByType<HVRHandGrabber>((FindObjectsSortMode)0)) { if (!((Object)(object)item == (Object)null) && ((Component)item).gameObject.activeInHierarchy) { if (item.IsLeftHand) { _left.Hand = item; } else { _right.Hand = item; } } } if (_autoTest) { ((MelonBase)this).LoggerInstance.Msg($"hands L={(Object)(object)_left.Hand != (Object)null} R={(Object)(object)_right.Hand != (Object)null} loader={(Object)(object)ModLoaderMelee.instanceOfThis != (Object)null}"); } } private void Tick(Side s) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)s.Claws != (Object)null && (Object)(object)s.Hand != (Object)null && (Object)(object)s.Grabbable != (Object)null && (Object)(object)((HVRGrabberBase)s.Hand).GrabbedTarget != (Object)(object)s.Grabbable) { Retract(s); } Keyboard current = Keyboard.current; bool flag = current != null && ((ButtonControl)current[s.Left ? _keyLeft.Value : _keyRight.Value]).wasPressedThisFrame; if ((Object)(object)s.Hand != (Object)null) { HVRController val = s.Hand.Controller; if ((Object)(object)val == (Object)null) { HVRInputManager instance = HVRInputManager.Instance; if ((Object)(object)instance != (Object)null) { val = (s.Left ? instance.LeftController : instance.RightController); } } if ((Object)(object)val != (Object)null) { bool flag2 = ClawButtonDown(s, val); if (flag2 && !s.PrevTrigger) { flag = true; if (_inputDebug.Value) { ((MelonBase)this).LoggerInstance.Msg(Name(s) + " " + ButtonLabel(s.Button, s.Left) + " pressed"); } } s.PrevTrigger = flag2; } } if (flag) { if ((Object)(object)s.Claws != (Object)null) { Retract(s); } else { Pop(s); } } } private ClawBtn ButtonFor(HVRController c) { //IL_003d: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Invalid comparison between Unknown and I4 string text = (_clawButton?.Value ?? "Auto").Trim(); if (!text.Equals("Auto", StringComparison.OrdinalIgnoreCase) && Enum.TryParse<ClawBtn>(text, ignoreCase: true, out var result)) { return result; } HVRControllerType controllerType = c.ControllerType; if ((int)controllerType != 2) { if ((int)controllerType == 3) { return ClawBtn.Menu; } return ClawBtn.BY; } return ClawBtn.Trackpad; } private static string ButtonLabel(int b, bool left) { return (ClawBtn)Math.Max(b, 0) switch { ClawBtn.BY => left ? "Y" : "B", ClawBtn.AX => left ? "X" : "A", ClawBtn.Menu => "Menu", ClawBtn.Trackpad => "trackpad click", ClawBtn.StickClick => "stick click", ClawBtn.FistTrigger => "fist + trigger", _ => "keyboard only", }; } private bool ClawButtonDown(Side s, HVRController c) { //IL_00b0: 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_00dc: 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_0108: 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_0155: 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) ClawBtn clawBtn = ButtonFor(c); if (clawBtn != (ClawBtn)s.Button) { s.Button = (int)clawBtn; ((MelonBase)this).LoggerInstance.Msg($"{(s.Left ? "Left" : "Right")} controller: {c.ControllerType} -> claws on {ButtonLabel(s.Button, s.Left)}"); } switch (clawBtn) { case ClawBtn.BY: if (!c.SecondaryButtonState.Active) { return c.SecondaryButton; } return true; case ClawBtn.AX: if (!c.PrimaryButtonState.Active) { return c.PrimaryButton; } return true; case ClawBtn.Menu: if (!c.MenuButtonState.Active) { return c.MenuButton; } return true; case ClawBtn.Trackpad: if (!c.TrackpadButtonState.Active) { return c.TrackPadClicked; } return true; case ClawBtn.StickClick: if (!c.JoystickButtonState.Active) { return c.JoystickClicked; } return true; case ClawBtn.FistTrigger: { HVRGrabbable grabbedTarget = ((HVRGrabberBase)s.Hand).GrabbedTarget; if (((Object)(object)grabbedTarget == (Object)null || ((Object)(object)s.Grabbable != (Object)null && (Object)(object)grabbedTarget == (Object)(object)s.Grabbable)) && (c.GripButtonState.Active || c.Grip > 0.7f)) { if (!c.TriggerButtonState.Active) { return c.Trigger > 0.7f; } return true; } return false; } default: return false; } } private void Pop(Side s) { //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)s.Hand == (Object)null) { FindHands(); if ((Object)(object)s.Hand == (Object)null) { ((MelonBase)this).LoggerInstance.Warning("No hand found yet"); return; } } ModLoaderMelee instanceOfThis = ModLoaderMelee.instanceOfThis; if ((Object)(object)instanceOfThis == (Object)null) { ((MelonBase)this).LoggerInstance.Warning("ModLoaderMelee not present in this scene"); return; } if (((HVRGrabberBase)s.Hand).IsGrabbing && (Object)(object)((HVRGrabberBase)s.Hand).GrabbedTarget != (Object)null) { ((MelonBase)this).LoggerInstance.Msg(Name(s) + " hand is holding " + ((Object)((HVRGrabberBase)s.Hand).GrabbedTarget).name + "; drop it first"); return; } try { MeleeScriptableObject so; Il2CppReferenceArray<GameObject> grabObjs; Il2CppReferenceArray<Collider> stabCols; MeleeWeaponWrapper wrapper; GameObject val = BuildRaw(s, out so, out grabObjs, out stabCols, out wrapper); GameObject val2 = instanceOfThis.CreateMeleePrefab(val, so, grabObjs, stabCols, wrapper); GameObject val3 = val; HVRGrabbable val4 = val3.GetComponent<HVRGrabbable>(); if ((Object)(object)val4 == (Object)null) { val4 = val3.GetComponentInChildren<HVRGrabbable>(true); } if (_debugDump.Value) { ((MelonBase)this).LoggerInstance.Msg("Claw weapon:\n" + Dump(val3.transform, 0)); if ((Object)(object)val2 != (Object)null) { ((MelonBase)this).LoggerInstance.Msg("Socket returned: " + ((Object)val2).name + " parent=" + (Object.op_Implicit((Object)(object)val2.transform.parent) ? ((Object)val2.transform.parent).name : "-")); } } if ((Object)(object)val4 == (Object)null) { ((MelonBase)this).LoggerInstance.Error("CreateMeleePrefab produced no HVRGrabbable"); Object.Destroy((Object)(object)val3); if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)val2); } return; } int value = ((instanceOfThis.loadedPrefabs != null) ? instanceOfThis.loadedPrefabs.Count : (-1)); if (instanceOfThis.loadedPrefabs != null) { instanceOfThis.loadedPrefabs.Remove(val); if ((Object)(object)val2 != (Object)null) { instanceOfThis.loadedPrefabs.Remove(val2); } } if (ModLoaderMelee.unSocketedPrefabs != null) { ModLoaderMelee.unSocketedPrefabs.Remove(val); if ((Object)(object)val2 != (Object)null) { ModLoaderMelee.unSocketedPrefabs.Remove(val2); } } if (_autoTest) { ((MelonBase)this).LoggerInstance.Msg($"loadedPrefabs {value} -> {((instanceOfThis.loadedPrefabs != null) ? instanceOfThis.loadedPrefabs.Count : (-1))}"); } val4.StartingSocket = null; val4.LinkStartingSocket = false; val3.transform.SetParent((Transform)null, true); if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)val3) { Object.Destroy((Object)(object)val2); } ((Object)val3).name = "WolverineClaws_" + Name(s); Transform transform = ((Component)s.Hand).transform; val3.transform.SetPositionAndRotation(transform.position, transform.rotation); if (_anchorToKnuckles.Value) { SetBladesVisible(val3, on: false); } val3.SetActive(true); val4.OverrideGrabTrigger = true; val4.GrabTrigger = (HVRGrabTrigger)2; val4.ForceGrabbable = false; foreach (HVRPosableGrabPoint componentsInChild in val3.GetComponentsInChildren<HVRPosableGrabPoint>(true)) { componentsInChild.LineCanRotate = false; componentsInChild.LineInitialCanRotate = false; componentsInChild.LineFreeRotation = false; componentsInChild.LineCanReposition = false; componentsInChild.LineInitialCanReposition = false; componentsInChild.CanLineFlip = false; } s.Claws = val3; s.Grabbable = null; MelonCoroutines.Start(GrabSoon(s, val3, val4)); } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Error("Pop failed: " + ex); } } private IEnumerator GrabSoon(Side s, GameObject obj, HVRGrabbable grab) { yield return null; yield return null; if ((Object)(object)obj == (Object)null || (Object)(object)s.Claws != (Object)(object)obj) { yield break; } Transform transform = ((Component)s.Hand).transform; obj.transform.SetPositionAndRotation(transform.position, transform.rotation); bool flag = false; try { flag = ((HVRGrabberBase)s.Hand).TryGrab(grab, true); } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Error("TryGrab: " + ex); } ((MelonBase)this).LoggerInstance.Msg($"SNIKT ({Name(s)}) grab={flag}"); if (flag) { s.Grabbable = grab; s.Anchored = false; Rigidbody component = obj.GetComponent<Rigidbody>(); if ((Object)(object)component != (Object)null && !_noLock) { component.useGravity = false; } if (_anchorToKnuckles.Value) { MelonCoroutines.Start(SnapToKnuckles(s, obj)); } MelonCoroutines.Start(SetupBloodSoon(obj)); ClawSharpness.Apply(obj, ((MelonBase)this).LoggerInstance); ClawSever.Add(obj, ((MelonBase)this).LoggerInstance); MelonCoroutines.Start(ReapplySharpness(obj)); try { HVRManager instance = HVRManager.Instance; if ((Object)(object)instance != (Object)null) { List<Collider> val = new List<Collider>(); foreach (Collider componentsInChild in obj.GetComponentsInChildren<Collider>(true)) { val.Add(componentsInChild); } instance.IgnorePlayerCollision(((Il2CppObjectBase)val).Cast<IEnumerable<Collider>>()); } Transform root = ((Component)s.Hand).transform.root; Il2CppArrayBase<Collider> componentsInChildren = obj.GetComponentsInChildren<Collider>(true); foreach (Collider componentsInChild2 in ((Component)root).GetComponentsInChildren<Collider>(true)) { foreach (Collider item in componentsInChildren) { if ((Object)(object)componentsInChild2 != (Object)null && (Object)(object)item != (Object)null) { Physics.IgnoreCollision(item, componentsInChild2, true); } } } Side side = (s.Left ? _right : _left); if ((Object)(object)side.Claws != (Object)null) { foreach (Collider componentsInChild3 in side.Claws.GetComponentsInChildren<Collider>(true)) { foreach (Collider item2 in componentsInChildren) { if ((Object)(object)componentsInChild3 != (Object)null && (Object)(object)item2 != (Object)null) { Physics.IgnoreCollision(item2, componentsInChild3, true); } } } } } catch (Exception ex2) { ((MelonBase)this).LoggerInstance.Warning("IgnorePlayerCollision: " + ex2.Message); } if (_photo) { float wait = Time.time + 1.2f; while (Time.time < wait) { yield return null; } if ((Object)(object)obj != (Object)null && !s.Left) { PhotoSet(s, obj); } } else if (_driveTest) { float wait = Time.time + 2f; while (Time.time < wait) { yield return null; } if ((Object)(object)obj != (Object)null && !s.Left) { yield return Environment.GetEnvironmentVariable("WC_DRIVETEST") switch { "2" => DriveTest2(s, obj), "3" => RefWeaponTest(s, obj), "4" => SwipeTest(s, obj), "5" => IconShots(s, obj), _ => DriveTest(s, obj), }; } } else if (_slashTest) { float wait = Time.time + 2f; while (Time.time < wait) { yield return null; } if ((Object)(object)obj != (Object)null && !s.Left) { yield return SlashTest(s, obj); } } else if (_swingTest) { float wait = Time.time + 1f; while (Time.time < wait) { yield return null; } if ((Object)(object)obj != (Object)null && !s.Left) { yield return SwingTest(s, obj); } } else if (_hitTest) { float wait = Time.time + 2f; while (Time.time < wait) { yield return null; } if ((Object)(object)obj != (Object)null && !s.Left) { yield return HitTest(s, obj); } } else if (_bloodTest) { float wait = Time.time + 1.2f; while (Time.time < wait) { yield return null; } if ((Object)(object)obj != (Object)null && !s.Left) { yield return BloodTest(s, obj); } } else { if (!_autoTest || s.AutoChecked) { yield break; } s.AutoChecked = true; float wait = Time.time + 2f; while (Time.time < wait) { yield return null; } if ((Object)(object)obj == (Object)null) { ((MelonBase)this).LoggerInstance.Msg("AUTOTEST " + Name(s) + ": claws gone"); yield break; } HVRGrabbable grabbedTarget = ((HVRGrabberBase)s.Hand).GrabbedTarget; ((MelonBase)this).LoggerInstance.Msg($"AUTOTEST {Name(s)}: held={(((Object)(object)grabbedTarget != (Object)null) ? ((Object)grabbedTarget).name : "none")} dist={Vector3.Distance(obj.transform.position, ((Component)s.Hand).transform.position):F3} active={obj.activeInHierarchy}"); Transform transform2 = ((Component)s.Hand).transform; Shot(transform2.position + transform2.up * 0.25f + transform2.right * (s.Left ? (-0.35f) : 0.35f) + transform2.forward * 0.1f, transform2.position + transform2.forward * 0.12f, ShotDir + "\\" + Name(s) + "_side.png"); Shot(transform2.position + transform2.up * 0.5f + transform2.forward * 0.1f, transform2.position + transform2.forward * 0.12f, ShotDir + "\\" + Name(s) + "_top.png"); Transform val2 = obj.transform.Find("Colliders/Blade1"); if ((Object)(object)val2 != (Object)null) { float value = _clawLength.Value; Vector3 val3 = val2.position + val2.up * value * 0.55f; Shot(val3 + val2.right * 0.24f + val2.forward * 0.06f, val3, ShotDir + "\\" + Name(s) + "_close.png"); Vector3 val4 = val2.position + val2.up * value * 0.88f; Shot(val4 + val2.right * 0.07f + val2.forward * 0.035f - val2.up * 0.02f, val4, ShotDir + "\\" + Name(s) + "_tip.png"); if (MeasureKnuckles(s, out var a, log: false)) { Vector3 centre = a.Centre; Vector3 at = centre + a.Dir * 0.06f; Shot(centre + a.Axis * 0.32f + a.Dir * 0.06f + a.Dorsal * 0.04f, at, ShotDir + "\\" + Name(s) + "_k_side.png", a.Dorsal); Shot(centre + a.Dorsal * 0.3f + a.Dir * 0.04f, at, ShotDir + "\\" + Name(s) + "_k_top.png", a.Dir); Shot(centre + a.Dir * 0.4f + a.Dorsal * 0.1f, centre, ShotDir + "\\" + Name(s) + "_k_front.png", a.Dorsal); } } wait = Time.time + 1f; while (Time.time < wait) { yield return null; } Retract(s); yield return null; ((MelonBase)this).LoggerInstance.Msg($"AUTOTEST {Name(s)} after retract: claws={(Object)(object)obj != (Object)null} handGrabbing={((HVRGrabberBase)s.Hand).IsGrabbing}"); wait = Time.time + 1f; while (Time.time < wait) { yield return null; } ((MelonBase)this).LoggerInstance.Msg("AUTOTEST " + Name(s) + " re-pop"); Pop(s); } } else { Retract(s); } } private static Transform BoneT(HVRPosableFinger f, int i) { if (f == null || f.Bones == null || f.Bones.Count <= i) { return null; } HVRPosableBone val = f.Bones[i]; if (val == null) { return null; } return val.Transform; } private static Vector3? Knuckle(HVRPosableFinger f) { //IL_0068: 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) Transform val = BoneT(f, 0); if ((Object)(object)val == (Object)null) { if (f == null || !((Object)(object)f.Root != (Object)null)) { return null; } return f.Root.position; } if (((Object)val).name.ToLower().Contains("metacarpal")) { Transform val2 = BoneT(f, 1); if ((Object)(object)val2 != (Object)null) { val = val2; } } return val.position; } private bool MeasureKnuckles(Side s, out ClawAnchor a, bool log) { //IL_00ce: 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_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_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_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_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknow