using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using PluginConfig.API; using PluginConfig.API.Decorators; using PluginConfig.API.Fields; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("UltraHook")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Lets V1's Whiplash latch onto solid surfaces and pull toward them.")] [assembly: AssemblyFileVersion("1.3.4.0")] [assembly: AssemblyInformationalVersion("1.3.4+f78cfaa84619023ccf773a408748cf475c69cbf5")] [assembly: AssemblyProduct("UltraHook")] [assembly: AssemblyTitle("UltraHook")] [assembly: AssemblyVersion("1.3.4.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace UltraHook { internal static class GrappleHook { private enum Phase { Idle, Pulling, Taut } private sealed class RaycastHitDistanceComparer : IComparer { public static readonly RaycastHitDistanceComparer Instance = new RaycastHitDistanceComparer(); public int Compare(RaycastHit x, RaycastHit y) { return ((RaycastHit)(ref x)).distance.CompareTo(((RaycastHit)(ref y)).distance); } } private const int IgnoreRaycastLayer = 2; private const int SolidClinkLayer = 26; private const float ThrowSpeed = 250f; private const float NoSwingExtraDamping = 5f; private const float TipEndTolerance = 0.05f; private const float EndpointContactTolerance = 0.05f; private const int AttachGraceFrames = 2; private const float MinNormalSqr = 1E-06f; private static readonly AnimationCurve MomentumCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); private static readonly FieldRef StateRef = AccessTools.FieldRefAccess("state"); private static readonly FieldRef ReturningRef = AccessTools.FieldRefAccess("returning"); private static readonly FieldRef HookPointRef = AccessTools.FieldRefAccess("hookPoint"); private static readonly FieldRef ThrowDirectionRef = AccessTools.FieldRefAccess("throwDirection"); private static readonly FieldRef EnviroMaskRef = AccessTools.FieldRefAccess("enviroMask"); private static readonly FieldRef ThrowMaskRef = AccessTools.FieldRefAccess("throwMask"); private static readonly FieldRef CaughtPointRef = AccessTools.FieldRefAccess("caughtPoint"); private static readonly FieldRef CaughtTransformRef = AccessTools.FieldRefAccess("caughtTransform"); private static readonly FieldRef CaughtColliderRef = AccessTools.FieldRefAccess("caughtCollider"); private static readonly FieldRef LightTargetRef = AccessTools.FieldRefAccess("lightTarget"); private static readonly FieldInfo CaughtObjectsField = AccessTools.Field(typeof(HookArm), "caughtObjects"); private static readonly FieldInfo PortalTraversalsField = AccessTools.Field(typeof(HookArm), "portalTraversals"); private static readonly FieldInfo CaughtEidField = AccessTools.Field(typeof(HookArm), "caughtEid"); private static readonly FieldInfo CaughtHookField = AccessTools.Field(typeof(HookArm), "caughtHook"); private static readonly FieldInfo HitSoundField = AccessTools.Field(typeof(HookArm), "hitSound"); private static readonly FieldInfo AudField = AccessTools.Field(typeof(HookArm), "aud"); private static readonly RaycastHit[] CastBuffer = (RaycastHit[])(object)new RaycastHit[64]; private static readonly Collider[] OverlapBuffer = (Collider[])(object)new Collider[64]; private static readonly HashSet SelfColliders = new HashSet(); private static bool _selfCollidersBuilt; private static GameObject _anchor; private static SphereCollider _anchorCollider; private static CapsuleCollider _playerCollider; private static Phase _phase; private static bool _tipTracking; private static Vector3 _prevTipPosition; private static Collider _hookedCollider; private static bool _trackCollider; private static Vector3 _localAnchor; private static Vector3 _worldAnchor; private static Vector3 _anchorNormal; private static int _graceFrames; private static bool _active; private static float _initialDistance; private static float _currentRopeLength; private static float _storedReleaseSpeed; private static Vector3 _filteredRopeDir; private static Vector3 _naturalVelocity; private static bool _jumpSuppressed; private static bool _savedLightTarget; private static bool _playerReleaseRequested; private static bool _groundSuppressed; private static float _groundTimer; private static GroundCheckGroup _suppressedGc; private static GroundCheckGroup _suppressedSlope; private static int _diagSweepCount; private static int _diagRayCount; private static bool AnchorActive { get { if ((Object)(object)_anchor != (Object)null) { return _anchor.activeSelf; } return false; } } private static float TipRadius => Mathf.Max(UltraHookConfig.SphereCastRadius, 0.02f); private static Rigidbody PlayerRigidbody { get { NewMovement instance = MonoSingleton.Instance; if (!((Object)(object)instance != (Object)null)) { return null; } return instance.rb; } } internal static bool OnFixedUpdatePre(HookArm hook) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_00c9: Invalid comparison between Unknown and I4 //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) TickGroundSuppression(); if (_graceFrames > 0) { _graceFrames--; } HookState val = StateRef.Invoke(hook); HandleDetection(hook, val); if (AnchorActive && (int)val != 0) { if (_trackCollider && !ColliderUsable(_hookedCollider)) { if (UltraHookConfig.DebugLogging) { Plugin.Log.LogInfo((object)"UltraHook detach: AnchorColliderDestroyed or AnchorColliderDisabled"); } ForceDetach(hook); return true; } if (_trackCollider) { _worldAnchor = ((Component)_hookedCollider).transform.TransformPoint(_localAnchor); } _anchor.transform.position = _worldAnchor; Rigidbody playerRigidbody = PlayerRigidbody; if ((Object)(object)playerRigidbody != (Object)null) { _naturalVelocity = playerRigidbody.velocity; } } if (UltraHookConfig.SwingMode && AnchorActive && (int)val == 3) { HookPointRef.Invoke(hook) = _worldAnchor; hook.beingPulled = true; return false; } return true; } internal static void OnFixedUpdatePost(HookArm hook) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_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_0101: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_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_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_031b: 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_0321: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Unknown result type (might be due to invalid IL or missing references) if (!AnchorActive || (int)StateRef.Invoke(hook) != 3) { _active = false; SetPhase(Phase.Idle, "NotPulling"); return; } Rigidbody playerRigidbody = PlayerRigidbody; if ((Object)(object)playerRigidbody == (Object)null) { return; } float fixedDeltaTime = Time.fixedDeltaTime; Vector3 position = playerRigidbody.position; Vector3 val = _worldAnchor - position; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude < 0.0001f) { return; } Vector3 val2 = val / magnitude; float num = ResolvedMinRopeLength(); if (!_active) { _active = true; SetPhase(Phase.Pulling, "StartedTerrainPull"); _initialDistance = Mathf.Max(magnitude, num); _currentRopeLength = magnitude; _storedReleaseSpeed = 0f; _filteredRopeDir = val2; } float num2 = 1f - Mathf.Exp((0f - UltraHookConfig.DirectionFilterSpeed) * fixedDeltaTime); Vector3 val3 = Vector3.Slerp(_filteredRopeDir, val2, num2); _filteredRopeDir = ((Vector3)(ref val3)).normalized; Vector3 naturalVelocity = _naturalVelocity; float num3 = Vector3.Dot(naturalVelocity, val2); Vector3 val4 = naturalVelocity - val2 * num3; _currentRopeLength = Mathf.Max(num, _currentRopeLength - UltraHookConfig.ReelSpeed * fixedDeltaTime); AccumulateMomentum(magnitude, num, num3); float num4 = num + UltraHookConfig.TautTolerance; bool flag = false; float storedReleaseSpeed = _storedReleaseSpeed; if (_phase == Phase.Pulling && magnitude <= num4) { SetPhase(Phase.Taut, "ReachedRopeEndpoint"); flag = true; ClearStoredPullMomentum(); } else if (_phase == Phase.Taut && magnitude > num4 + 1f) { SetPhase(Phase.Pulling, "RopeExtendedPastEndpoint"); } float num5 = UltraHookConfig.MaxAngularSpeed * Mathf.Max(magnitude, num); val4 = Vector3.ClampMagnitude(val4, num5); float num6 = UltraHookConfig.TangentialDamping + (UltraHookConfig.SwingMode ? 0f : 5f); val4 *= Mathf.Exp((0f - num6) * fixedDeltaTime); float num7; if (flag) { num7 = 0f; val4 = ProjectOffSurface(val4); } else if (_phase == Phase.Pulling) { float num8 = Mathf.Max(0f, magnitude - _currentRopeLength); float num9 = Mathf.Clamp(UltraHookConfig.MinPullSpeed + num8 * UltraHookConfig.PullSpeedGain, UltraHookConfig.MinPullSpeed, UltraHookConfig.MaxPullSpeed); num7 = Mathf.MoveTowards(num3, num9, UltraHookConfig.PullAcceleration * fixedDeltaTime); } else { float num10 = Mathf.Clamp((magnitude - num) * UltraHookConfig.TautCorrectionGain, 0f - UltraHookConfig.MaxOutwardCorrectionSpeed, UltraHookConfig.MaxInwardCorrectionSpeed); num7 = Mathf.MoveTowards(num3, num10, UltraHookConfig.TautAcceleration * fixedDeltaTime); } playerRigidbody.velocity = val4 + val2 * num7; if (UltraHookConfig.DebugLogging) { if (flag) { ManualLogSource log = Plugin.Log; object[] obj = new object[5] { num3, storedReleaseSpeed, _storedReleaseSpeed, playerRigidbody.velocity, null }; val3 = playerRigidbody.velocity; obj[4] = ((Vector3)(ref val3)).magnitude; log.LogInfo((object)("UltraHook taut entry (PullMomentumConsumedAtEndpoint, EndpointRadialVelocityRemoved, EnteredTautWithTangentialVelocity): " + string.Format("radialBefore={0:0.00} storedBefore={1:0.00} storedAfter={2:0.00} velAfter={3} mag={4:0.00}", obj))); } if (_phase == Phase.Taut && _storedReleaseSpeed > 0.01f) { Plugin.Log.LogWarning((object)$"UltraHook UnexpectedMomentumAppliedDuringTaut: storedReleaseSpeed={_storedReleaseSpeed:0.00}"); } Debug.DrawLine(position, _worldAnchor, Color.cyan); Debug.DrawRay(position, val4, Color.yellow); Debug.DrawRay(position, val2 * num7, Color.green); } } private static void AccumulateMomentum(float distance, float minRope, float radialSpeed) { if (!UltraHookConfig.Momentum) { _storedReleaseSpeed = 0f; } else if (_phase == Phase.Pulling) { float num = Mathf.Max(_initialDistance - minRope, 0.001f); float num2 = Mathf.Clamp01((_initialDistance - distance) / num); float num3 = MomentumCurve.Evaluate(num2) * UltraHookConfig.MaxMomentumBonus; _storedReleaseSpeed = Mathf.Min(Mathf.Max(_storedReleaseSpeed, Mathf.Max(0f, radialSpeed) + num3), UltraHookConfig.MaxReleaseSpeed); } } private static void ClearStoredPullMomentum() { _storedReleaseSpeed = 0f; } private static Vector3 ProjectOffSurface(Vector3 velocity) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (((Vector3)(ref _anchorNormal)).sqrMagnitude < 1E-06f) { return velocity; } float num = Vector3.Dot(velocity, _anchorNormal); if (num < 0f) { velocity -= _anchorNormal * num; } return velocity; } private static void HandleDetection(HookArm hook, HookState state) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) if ((int)state != 1 || !UltraHookConfig.Enabled || !hook.equipped || ReturningRef.Invoke(hook)) { _tipTracking = false; return; } Vector3 val = HookPointRef.Invoke(hook); if (!_tipTracking) { _tipTracking = true; _prevTipPosition = val; } if (Count(CaughtObjectsField, hook) > 0 || Count(PortalTraversalsField, hook) > 0) { _prevTipPosition = val; } else { SweepTip(hook, val); } } private static void SweepTip(HookArm hook, Vector3 tip) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: 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_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: 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_00ed: 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_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: 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_00f5: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ThrowDirectionRef.Invoke(hook); if (((Vector3)(ref val)).sqrMagnitude < 1E-08f) { _prevTipPosition = tip; return; } val = ((Vector3)(ref val)).normalized; float num = 250f * Time.fixedDeltaTime; Vector3 prevTipPosition = _prevTipPosition; Vector3 val2 = tip + val * num; _prevTipPosition = tip; Vector3 val3 = val2 - prevTipPosition; float magnitude = ((Vector3)(ref val3)).magnitude; if (magnitude < 0.0001f) { return; } Vector3 sweepDir = val3 / magnitude; int num2 = DetectionMask(hook); int catchMask = ((LayerMask)(ref ThrowMaskRef.Invoke(hook))).value & ~num2; bool queriesHitBackfaces = Physics.queriesHitBackfaces; if (UltraHookConfig.BackfaceCompatibility) { Physics.queriesHitBackfaces = true; } try { if (TryTerrainImpact(prevTipPosition, sweepDir, magnitude, num2, catchMask, out var collider, out var point, out var normal, out var distance)) { CommitTerrainAnchor(hook, collider, point, normal, val, prevTipPosition, val2, distance); } else if (TryEndpointOverlap(val2, num2, val, out collider, out point, out normal)) { CommitTerrainAnchor(hook, collider, point, normal, val, prevTipPosition, val2, Vector3.Distance(prevTipPosition, point)); } } finally { Physics.queriesHitBackfaces = queriesHitBackfaces; } } private static bool TryTerrainImpact(Vector3 start, Vector3 sweepDir, float length, int detectMask, int catchMask, out Collider collider, out Vector3 point, out Vector3 normal, out float distance) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) collider = null; point = Vector3.zero; normal = Vector3.zero; distance = float.MaxValue; bool flag = false; float num = length + 0.05f; int num2 = (_diagSweepCount = Physics.SphereCastNonAlloc(start, TipRadius, sweepDir, CastBuffer, num, detectMask, (QueryTriggerInteraction)1)); if (num2 >= CastBuffer.Length && UltraHookConfig.DebugLogging) { Plugin.Log.LogWarning((object)"UltraHook TipSweepBufferFull"); } Array.Sort(CastBuffer, 0, num2, RaycastHitDistanceComparer.Instance); for (int i = 0; i < num2; i++) { RaycastHit val = CastBuffer[i]; if (!(((RaycastHit)(ref val)).distance <= 0f) && IsHookableHit(((RaycastHit)(ref val)).collider)) { collider = ((RaycastHit)(ref val)).collider; point = ((RaycastHit)(ref val)).point; normal = ((RaycastHit)(ref val)).normal; distance = ((RaycastHit)(ref val)).distance; flag = true; break; } } RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(start, sweepDir, ref val2, num, detectMask, (QueryTriggerInteraction)1) && IsHookableHit(((RaycastHit)(ref val2)).collider)) { _diagRayCount = 1; if (!flag || ((RaycastHit)(ref val2)).distance < distance) { collider = ((RaycastHit)(ref val2)).collider; point = ((RaycastHit)(ref val2)).point; normal = ((RaycastHit)(ref val2)).normal; distance = ((RaycastHit)(ref val2)).distance; flag = true; } } else { _diagRayCount = 0; } if (!flag) { return false; } if (catchMask != 0 && CatchableStruckCloser(start, sweepDir, distance, catchMask)) { collider = null; return false; } return true; } private static bool CatchableStruckCloser(Vector3 start, Vector3 sweepDir, float terrainDistance, int catchMask) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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) int num = Physics.SphereCastNonAlloc(start, TipRadius, sweepDir, CastBuffer, terrainDistance, catchMask, (QueryTriggerInteraction)2); for (int i = 0; i < num; i++) { RaycastHit val = CastBuffer[i]; Collider collider = ((RaycastHit)(ref val)).collider; if (!((Object)(object)collider == (Object)null) && !((Object)(object)collider == (Object)(object)_anchorCollider) && !IsSelf(collider) && ((RaycastHit)(ref val)).distance <= terrainDistance - 0.01f) { return true; } } return false; } private static bool TryEndpointOverlap(Vector3 endpoint, int detectMask, Vector3 fallbackDir, out Collider collider, out Vector3 point, out Vector3 normal) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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) collider = null; point = endpoint; normal = -fallbackDir; int num = Physics.OverlapSphereNonAlloc(endpoint, TipRadius, OverlapBuffer, detectMask, (QueryTriggerInteraction)1); float num2 = float.MaxValue; for (int i = 0; i < num; i++) { Collider val = OverlapBuffer[i]; if (IsHookableHit(val)) { Vector3 val2 = val.ClosestPoint(endpoint); float num3 = Vector3.Distance(endpoint, val2); if (num3 <= 0.05f && num3 < num2) { num2 = num3; collider = val; point = val2; Vector3 val3 = endpoint - val2; normal = ((((Vector3)(ref val3)).sqrMagnitude > 1E-06f) ? ((Vector3)(ref val3)).normalized : (-fallbackDir)); } } } return (Object)(object)collider != (Object)null; } private static void CommitTerrainAnchor(HookArm hook, Collider collider, Vector3 point, Vector3 normal, Vector3 travelDir, Vector3 from, Vector3 to, float distance) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_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_0038: 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_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: 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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: 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_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((((Vector3)(ref normal)).sqrMagnitude > 1E-06f) ? ((Vector3)(ref normal)).normalized : (-travelDir)); Vector3 val2 = point + val * UltraHookConfig.SurfaceOffset; Transform anchor = GetAnchor(); anchor.position = val2; ((Component)anchor).gameObject.SetActive(true); CaughtTransformRef.Invoke(hook) = anchor; CaughtPointRef.Invoke(hook) = Vector3.zero; HookPointRef.Invoke(hook) = val2; CaughtColliderRef.Invoke(hook) = (Collider)(object)_anchorCollider; LightTargetRef.Invoke(hook) = false; CaughtEidField.SetValue(hook, null); CaughtHookField.SetValue(hook, null); StateRef.Invoke(hook) = (HookState)2; _hookedCollider = collider; _trackCollider = ColliderUsable(collider); _localAnchor = (_trackCollider ? ((Component)collider).transform.InverseTransformPoint(val2) : val2); _worldAnchor = val2; _anchorNormal = val; _active = false; _phase = Phase.Idle; _tipTracking = false; _graceFrames = 2; object? value = HitSoundField.GetValue(hook); GameObject val3 = (GameObject)((value is GameObject) ? value : null); if (val3 != null && (Object)(object)val3 != (Object)null) { Object.Instantiate(val3, point, Quaternion.identity); } object? value2 = AudField.GetValue(hook); AudioSource val4 = (AudioSource)((value2 is AudioSource) ? value2 : null); if (val4 != null && (Object)(object)val4 != (Object)null) { val4.Stop(); } if (UltraHookConfig.DebugLogging) { LogImpact(collider, point, val, distance, travelDir, from, to); } } internal static void OnRelease() { //IL_0076: 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_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) bool flag = UltraHookConfig.SwingMode && AnchorActive && _active && _phase == Phase.Taut; if (_active) { Rigidbody playerRigidbody = PlayerRigidbody; if ((Object)(object)playerRigidbody != (Object)null && UltraHookConfig.Momentum && _storedReleaseSpeed > 0f) { Vector3 normalized; if (!(((Vector3)(ref _filteredRopeDir)).sqrMagnitude > 0.5f)) { Vector3 velocity = playerRigidbody.velocity; normalized = ((Vector3)(ref velocity)).normalized; } else { normalized = ((Vector3)(ref _filteredRopeDir)).normalized; } Vector3 val = normalized; if (((Vector3)(ref val)).sqrMagnitude > 0.5f) { float num = Vector3.Dot(playerRigidbody.velocity, val); float num2 = Mathf.Max(num, _storedReleaseSpeed); playerRigidbody.velocity += val * (num2 - num); } } BeginGroundSuppression(); } if (UltraHookConfig.DebugLogging) { if (flag && !_playerReleaseRequested) { Plugin.Log.LogWarning((object)"UltraHook UnexpectedEndpointDetach: released during a persistent swing without an explicit hook input"); } else { Plugin.Log.LogInfo((object)string.Format("UltraHook release: reason={0} phase={1} swing={2}", _playerReleaseRequested ? "ExplicitSwingRelease" : "NonSwingOrForced", _phase, UltraHookConfig.SwingMode)); } } _playerReleaseRequested = false; ResetLatchState(); } internal static void SuppressJumpCancel(HookArm hook) { if (AnchorActive && (int)StateRef.Invoke(hook) == 3) { if (HookInputPressedThisFrame()) { _playerReleaseRequested = true; } _savedLightTarget = LightTargetRef.Invoke(hook); LightTargetRef.Invoke(hook) = true; _jumpSuppressed = true; } } private static bool HookInputPressedThisFrame() { InputManager instance = MonoSingleton.Instance; if ((Object)(object)instance != (Object)null && instance.InputSource != null) { return instance.InputSource.Hook.WasPerformedThisFrame; } return false; } internal static void RestoreJumpCancel(HookArm hook) { if (_jumpSuppressed) { LightTargetRef.Invoke(hook) = _savedLightTarget; _jumpSuppressed = false; } } internal static void ScaleLineDistance(ref float result) { float maxHookDistance = UltraHookConfig.MaxHookDistance; if (float.IsPositiveInfinity(maxHookDistance)) { if (result > 299f) { result = 299f; } } else if (maxHookDistance > 0f && !Mathf.Approximately(maxHookDistance, 300f)) { result *= 300f / maxHookDistance; } } private static void BeginGroundSuppression() { float groundSnapSuppressTime = UltraHookConfig.GroundSnapSuppressTime; if (groundSnapSuppressTime <= 0f) { return; } NewMovement instance = MonoSingleton.Instance; if (!((Object)(object)instance == (Object)null)) { EndGroundSuppression(); _suppressedGc = instance.gc; _suppressedSlope = instance.slopeCheck; if ((Object)(object)_suppressedGc != (Object)null) { _suppressedGc.ForceOff(); } if ((Object)(object)_suppressedSlope != (Object)null) { _suppressedSlope.ForceOff(); } _groundSuppressed = true; _groundTimer = groundSnapSuppressTime; } } private static void TickGroundSuppression() { if (_groundSuppressed) { _groundTimer -= Time.fixedDeltaTime; if (_groundTimer <= 0f) { EndGroundSuppression(); } } } private static void EndGroundSuppression() { if (_groundSuppressed) { if ((Object)(object)_suppressedGc != (Object)null) { _suppressedGc.StopForceOff(); } if ((Object)(object)_suppressedSlope != (Object)null) { _suppressedSlope.StopForceOff(); } _suppressedGc = null; _suppressedSlope = null; _groundSuppressed = false; } } private static void ForceDetach(HookArm hook) { _active = false; hook.StopThrow(0f, false); } private static void ResetLatchState() { _active = false; _phase = Phase.Idle; _tipTracking = false; _graceFrames = 0; _storedReleaseSpeed = 0f; _hookedCollider = null; _trackCollider = false; if ((Object)(object)_anchor != (Object)null && _anchor.activeSelf) { _anchor.SetActive(false); } } internal static void Cleanup() { EndGroundSuppression(); if ((Object)(object)_anchor != (Object)null) { Object.Destroy((Object)(object)_anchor); } _anchor = null; _anchorCollider = null; _playerCollider = null; _active = false; _phase = Phase.Idle; _jumpSuppressed = false; _tipTracking = false; _graceFrames = 0; _trackCollider = false; _hookedCollider = null; _playerReleaseRequested = false; SelfColliders.Clear(); _selfCollidersBuilt = false; } private static Transform GetAnchor() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown if ((Object)(object)_anchor == (Object)null) { _anchor = new GameObject("UltraHookAnchor") { layer = 2 }; Object.DontDestroyOnLoad((Object)(object)_anchor); _anchorCollider = _anchor.AddComponent(); _anchorCollider.radius = 0.1f; ((Collider)_anchorCollider).isTrigger = true; _anchor.SetActive(false); } return _anchor.transform; } private static int DetectionMask(HookArm hook) { return (UltraHookConfig.HookableMask | ((LayerMask)(ref EnviroMaskRef.Invoke(hook))).value | 0x4000000) & ~UltraHookConfig.UnhookableMask & -5; } private static bool IsHookableHit(Collider collider) { if ((Object)(object)collider == (Object)null || !collider.enabled || collider.isTrigger) { return false; } if ((Object)(object)collider == (Object)(object)_anchorCollider || IsSelf(collider)) { return false; } return true; } private static bool IsSelf(Collider collider) { if ((Object)(object)collider == (Object)null) { return false; } EnsureSelfColliders(); if (SelfColliders.Contains(collider)) { return true; } NewMovement instance = MonoSingleton.Instance; if ((Object)(object)instance != (Object)null && (Object)(object)collider.attachedRigidbody != (Object)null) { return (Object)(object)collider.attachedRigidbody == (Object)(object)instance.rb; } return false; } private static void EnsureSelfColliders() { if (_selfCollidersBuilt) { return; } NewMovement instance = MonoSingleton.Instance; if ((Object)(object)instance == (Object)null) { return; } SelfColliders.Clear(); Collider[] componentsInChildren = ((Component)instance).GetComponentsInChildren(true); foreach (Collider item in componentsInChildren) { SelfColliders.Add(item); } HookArm instance2 = MonoSingleton.Instance; if ((Object)(object)instance2 != (Object)null) { componentsInChildren = ((Component)instance2).GetComponentsInChildren(true); foreach (Collider item2 in componentsInChildren) { SelfColliders.Add(item2); } } _selfCollidersBuilt = true; } private static bool ColliderUsable(Collider collider) { if ((Object)(object)collider != (Object)null && collider.enabled) { return ((Component)collider).gameObject.activeInHierarchy; } return false; } private static void SetPhase(Phase next, string reason) { if (_phase != next) { if (UltraHookConfig.DebugLogging) { Plugin.Log.LogInfo((object)($"UltraHook phase: {_phase} -> {next} ({reason}) swing={UltraHookConfig.SwingMode} " + $"anchorActive={AnchorActive} rope={_currentRopeLength:0.00} min={ResolvedMinRopeLength():0.00} grace={_graceFrames}")); } _phase = next; } } private static float ResolvedMinRopeLength() { float num = PlayerRadius(); return Mathf.Max(UltraHookConfig.MinRopeLength, num + 0.3f); } private static float PlayerRadius() { if ((Object)(object)_playerCollider == (Object)null) { NewMovement instance = MonoSingleton.Instance; if ((Object)(object)instance != (Object)null) { _playerCollider = ((Component)instance).GetComponent(); } } if (!((Object)(object)_playerCollider != (Object)null)) { return 0.5f; } return _playerCollider.radius; } private static int Count(FieldInfo listField, HookArm hook) { if (!(listField.GetValue(hook) is ICollection collection)) { return 0; } return collection.Count; } private static void LogImpact(Collider collider, Vector3 point, Vector3 normal, float distance, Vector3 travelDir, Vector3 from, Vector3 to) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_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) float num = Vector3.Dot(-travelDir, normal); string text = (((Object)(object)collider != (Object)null) ? $"{LayerMask.LayerToName(((Component)collider).gameObject.layer)}({((Component)collider).gameObject.layer})" : "none"); Plugin.Log.LogInfo((object)($"UltraHook tip impact: collider={((collider != null) ? ((Object)collider).name : null)} layer={text} point={point} normal={normal} dist={distance:0.00} " + $"impactDot={num:0.00} sweepHits={_diagSweepCount} rayHits={_diagRayCount} segment={Vector3.Distance(from, to):0.00}")); } } [HarmonyPatch(typeof(HookArm))] internal static class HookArmPatches { private static bool _errorLogged; [HarmonyPrefix] [HarmonyPatch("FixedUpdate")] private static bool FixedUpdatePrefix(HookArm __instance) { try { return GrappleHook.OnFixedUpdatePre(__instance); } catch (Exception arg) { LogOnce($"UltraHook detection/tracking failed and is now inert for this session: {arg}"); return true; } } [HarmonyPostfix] [HarmonyPatch("FixedUpdate")] private static void FixedUpdatePostfix(HookArm __instance) { try { GrappleHook.OnFixedUpdatePost(__instance); } catch (Exception arg) { LogOnce($"UltraHook pull update failed and is now inert for this session: {arg}"); } } [HarmonyPrefix] [HarmonyPatch("Update")] private static void UpdatePrefix(HookArm __instance) { try { GrappleHook.SuppressJumpCancel(__instance); } catch (Exception arg) { LogOnce($"UltraHook jump-suppress failed and is now inert for this session: {arg}"); } } [HarmonyFinalizer] [HarmonyPatch("Update")] private static void UpdateFinalizer(HookArm __instance) { GrappleHook.RestoreJumpCancel(__instance); } [HarmonyPostfix] [HarmonyPatch("GetTotalLineDistance")] private static void GetTotalLineDistancePostfix(ref float __result) { try { GrappleHook.ScaleLineDistance(ref __result); } catch (Exception arg) { LogOnce($"UltraHook max-distance failed and is now inert for this session: {arg}"); } } [HarmonyPostfix] [HarmonyPatch("StopThrow")] private static void StopThrowPostfix() { try { GrappleHook.OnRelease(); } catch (Exception arg) { LogOnce($"UltraHook release failed and is now inert for this session: {arg}"); } } [HarmonyPostfix] [HarmonyPatch("Cancel")] private static void CancelPostfix() { try { GrappleHook.OnRelease(); } catch (Exception arg) { LogOnce($"UltraHook release failed and is now inert for this session: {arg}"); } } private static void LogOnce(string message) { if (!_errorLogged) { _errorLogged = true; Plugin.Log.LogError((object)message); } } } [BepInPlugin("ultrahook.kiyroprower.ultrakill", "UltraHook", "1.3.4")] [BepInProcess("ULTRAKILL.exe")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string Guid = "ultrahook.kiyroprower.ultrakill"; public const string PluginConfiguratorGuid = "com.eternalUnion.pluginConfigurator"; internal static ManualLogSource Log; private Harmony _harmony; private void Awake() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; UltraHookConfig.Initialize(((BaseUnityPlugin)this).Logger); _harmony = new Harmony("ultrahook.kiyroprower.ultrakill"); _harmony.PatchAll(typeof(HookArmPatches)); Log.LogInfo((object)("UltraHook loaded (ultrahook.kiyroprower.ultrakill). Wall latching " + (UltraHookConfig.Enabled ? "enabled" : "disabled") + ", swing mode " + (UltraHookConfig.SwingMode ? "on" : "off") + ".")); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } GrappleHook.Cleanup(); } } internal static class UltraHookConfig { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static PostBoolValueChangeEvent <>9__107_0; internal void b__107_0(bool _) { UpdateMomentumVisibility(); } } public const float VanillaMaxHookDistance = 300f; public const float DefaultSphereCastRadius = 0.12f; public const float DefaultSurfaceOffset = 0.5f; public const float DefaultMinRopeLength = 2.5f; public const float DefaultReelSpeed = 40f; public const float DefaultMinPullSpeed = 25f; public const float DefaultMaxPullSpeed = 90f; public const float DefaultPullAcceleration = 220f; public const float DefaultPullSpeedGain = 8f; public const float DefaultTautTolerance = 0.5f; public const float DefaultTautCorrectionGain = 10f; public const float DefaultTautAcceleration = 60f; public const float DefaultMaxInwardCorrectionSpeed = 20f; public const float DefaultMaxOutwardCorrectionSpeed = 30f; public const float DefaultMaxAngularSpeed = 6f; public const float DefaultTangentialDamping = 1.5f; public const float DefaultMaxMomentumBonus = 60f; public const float DefaultMaxReleaseSpeed = 150f; public const float DefaultDirectionFilterSpeed = 12f; public const float DefaultGroundSnapSuppressTime = 0.08f; private static PluginConfigurator _configurator; private static ManualLogSource _log; private static BoolField _enabledField; private static BoolField _swingModeField; private static BoolField _momentumField; private static StringField _maxHookDistanceField; private static FloatSliderField _sphereCastRadiusField; private static FloatSliderField _surfaceOffsetField; private static BoolField _backfaceField; private static StringField _extraHookableLayersField; private static StringField _unhookableLayersField; private static FloatSliderField _minRopeLengthField; private static FloatSliderField _reelSpeedField; private static FloatSliderField _minPullSpeedField; private static FloatSliderField _maxPullSpeedField; private static FloatSliderField _pullAccelerationField; private static FloatSliderField _pullSpeedGainField; private static FloatSliderField _tautToleranceField; private static FloatSliderField _tautCorrectionGainField; private static FloatSliderField _tautAccelerationField; private static FloatSliderField _maxInwardCorrectionField; private static FloatSliderField _maxOutwardCorrectionField; private static FloatSliderField _maxAngularSpeedField; private static FloatSliderField _tangentialDampingField; private static FloatSliderField _maxMomentumBonusField; private static FloatSliderField _maxReleaseSpeedField; private static FloatSliderField _directionFilterSpeedField; private static FloatSliderField _groundSnapSuppressField; private static BoolField _debugLoggingField; private static ConfigHeader _momentumBonusDescription; private static ConfigHeader _releaseSpeedDescription; private static ConfigHeader _directionFilterDescription; private static readonly Color TitleColor = new Color(1f, 0.62f, 0.16f); private static readonly Color EnabledColor = new Color(0.56f, 0.86f, 0.56f); private static readonly Color SwingColor = new Color(0.45f, 0.8f, 1f); private static readonly Color MomentumColor = new Color(1f, 0.8f, 0.35f); public static bool Enabled { get { if (_enabledField != null) { return _enabledField.value; } return true; } } public static bool SwingMode { get { if (_swingModeField != null) { return _swingModeField.value; } return false; } } public static bool Momentum { get { if (_momentumField != null) { return _momentumField.value; } return true; } } public static bool BackfaceCompatibility { get { if (_backfaceField != null) { return _backfaceField.value; } return false; } } public static bool DebugLogging { get { if (_debugLoggingField != null) { return _debugLoggingField.value; } return false; } } public static float SphereCastRadius => Slider(_sphereCastRadiusField, 0.12f, 0.01f); public static float SurfaceOffset => Slider(_surfaceOffsetField, 0.5f, 0.01f); public static float MinRopeLength => Slider(_minRopeLengthField, 2.5f, 0.5f); public static float ReelSpeed => Slider(_reelSpeedField, 40f, 0f); public static float MinPullSpeed => Slider(_minPullSpeedField, 25f, 0f); public static float MaxPullSpeed => Slider(_maxPullSpeedField, 90f, MinPullSpeed); public static float PullAcceleration => Slider(_pullAccelerationField, 220f, 1f); public static float PullSpeedGain => Slider(_pullSpeedGainField, 8f, 0f); public static float TautTolerance => Slider(_tautToleranceField, 0.5f, 0f); public static float TautCorrectionGain => Slider(_tautCorrectionGainField, 10f, 0f); public static float TautAcceleration => Slider(_tautAccelerationField, 60f, 1f); public static float MaxInwardCorrectionSpeed => Slider(_maxInwardCorrectionField, 20f, 0f); public static float MaxOutwardCorrectionSpeed => Slider(_maxOutwardCorrectionField, 30f, 0f); public static float MaxAngularSpeed => Slider(_maxAngularSpeedField, 6f, 0.1f); public static float TangentialDamping => Slider(_tangentialDampingField, 1.5f, 0f); public static float MaxMomentumBonus => Slider(_maxMomentumBonusField, 60f, 0f); public static float MaxReleaseSpeed => Slider(_maxReleaseSpeedField, 150f, 0f); public static float DirectionFilterSpeed => Slider(_directionFilterSpeedField, 12f, 0.1f); public static float GroundSnapSuppressTime => Slider(_groundSnapSuppressField, 0.08f, 0f); public static int HookableMask { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) LayerMask val = LayerMaskDefaults.Get((LMD)1); int value = ((LayerMask)(ref val)).value; StringField extraHookableLayersField = _extraHookableLayersField; int num = value | ParseLayers((extraHookableLayersField != null) ? extraHookableLayersField.value : null); StringField unhookableLayersField = _unhookableLayersField; return num & ~ParseLayers((unhookableLayersField != null) ? unhookableLayersField.value : null) & -5; } } public static int UnhookableMask { get { StringField unhookableLayersField = _unhookableLayersField; return ParseLayers((unhookableLayersField != null) ? unhookableLayersField.value : null); } } public static float MaxHookDistance { get { if (_maxHookDistanceField == null) { return 300f; } string text = _maxHookDistanceField.value?.Trim(); if (string.IsNullOrEmpty(text)) { return 300f; } if (text.Equals("inf", StringComparison.OrdinalIgnoreCase) || text.Equals("infinite", StringComparison.OrdinalIgnoreCase)) { return float.PositiveInfinity; } if (!float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !(result > 0f)) { return 300f; } return result; } } public static void Initialize(ManualLogSource log) { _log = log; try { CreateMenu(); _log.LogInfo((object)"Config menu initialized."); } catch (Exception ex) { _log.LogWarning((object)("PluginConfigurator menu could not be initialized: " + ex.GetType().Name + ": " + ex.Message)); } } private static void CreateMenu() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_006b: 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_008d: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Expected O, but got Unknown //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Expected O, but got Unknown //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Expected O, but got Unknown //IL_056e: Unknown result type (might be due to invalid IL or missing references) //IL_0578: Expected O, but got Unknown //IL_00a6: 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_00b1: Expected O, but got Unknown if (_configurator != null) { return; } _configurator = PluginConfigurator.Create("UltraHook", "ultrahook.kiyroprower.ultrakill"); ConfigPanel rootPanel = _configurator.rootPanel; _enabledField = new BoolField(rootPanel, "Enabled", "ultrahook.enabled", true, true); AddDescription(rootPanel, "Let the Whiplash grapple onto solid surfaces.", EnabledColor); _swingModeField = new BoolField(rootPanel, "Swing Mode", "ultrahook.swingMode", false, true); AddDescription(rootPanel, "On, the hook is a rope you swing on and it stays attached until you press the hook key again. Off, it reels V1 straight to the surface.", SwingColor); _momentumField = new BoolField(rootPanel, "Momentum", "ultrahook.momentum", true, true); BoolField momentumField = _momentumField; object obj = <>c.<>9__107_0; if (obj == null) { PostBoolValueChangeEvent val = delegate { UpdateMomentumVisibility(); }; <>c.<>9__107_0 = val; obj = (object)val; } momentumField.postValueChangeEvent += (PostBoolValueChangeEvent)obj; AddDescription(rootPanel, "Build launch speed as the pull travels. Cancel with the hook key to keep it, ride to the end and it fades.", MomentumColor); AddTitle(rootPanel, "Detection"); _maxHookDistanceField = new StringField(rootPanel, "Max Hook Distance", "ultrahook.maxHookDistance", 300f.ToString("0", CultureInfo.InvariantCulture), true); AddDescription(rootPanel, "How far the hook can reach. Default is the vanilla range. Type \"inf\" for unlimited."); _sphereCastRadiusField = Slider(rootPanel, "Sphere Cast Radius", "ultrahook.sphereRadius", 0.05f, 0.5f, 0.12f, 2); AddDescription(rootPanel, "Thickness of the travelling hook tip. Larger values catch edges, seams, and shallow angles more easily."); _surfaceOffsetField = Slider(rootPanel, "Surface Offset", "ultrahook.surfaceOffset", 0.1f, 3f, 0.5f, 2); AddDescription(rootPanel, "How far off the surface the anchor sits. Lower values pull V1 closer into the surface."); _backfaceField = new BoolField(rootPanel, "Backface Compatibility", "ultrahook.backface", false, true); AddDescription(rootPanel, "Allow the aim probe to hit the reverse side of one-sided meshes. Enable only if some surfaces refuse to hook."); _extraHookableLayersField = new StringField(rootPanel, "Extra Hookable Layers", "ultrahook.extraLayers", "", true); AddDescription(rootPanel, "Advanced. Extra layer numbers to treat as hookable, separated by spaces or commas."); _unhookableLayersField = new StringField(rootPanel, "Unhookable Layers", "ultrahook.unhookableLayers", "", true); AddDescription(rootPanel, "Advanced. Layer numbers to never hook, separated by spaces or commas."); AddTitle(rootPanel, "Pull"); _minRopeLengthField = Slider(rootPanel, "Minimum Rope Length", "ultrahook.minRope", 1f, 10f, 2.5f, 1); AddDescription(rootPanel, "How far from the anchor V1 settles when the rope goes taut. Keeps V1 clear of the surface."); _reelSpeedField = Slider(rootPanel, "Reel Speed", "ultrahook.reelSpeed", 0f, 150f, 40f, 0); AddDescription(rootPanel, "How fast the virtual rope shortens toward its minimum length."); _minPullSpeedField = Slider(rootPanel, "Minimum Pull Speed", "ultrahook.minPull", 0f, 120f, 25f, 0); AddDescription(rootPanel, "Slowest speed V1 is drawn toward the anchor at."); _maxPullSpeedField = Slider(rootPanel, "Maximum Pull Speed", "ultrahook.maxPull", 10f, 250f, 90f, 0); AddDescription(rootPanel, "Fastest speed V1 is drawn toward the anchor at."); _pullAccelerationField = Slider(rootPanel, "Pull Acceleration", "ultrahook.pullAccel", 10f, 1000f, 220f, 0); AddDescription(rootPanel, "How quickly the pull speed ramps up. Lower feels heavier."); _pullSpeedGainField = Slider(rootPanel, "Pull Speed Gain", "ultrahook.pullGain", 0f, 40f, 8f, 1); AddDescription(rootPanel, "How much the pull speeds up when the rope is stretched far past its length."); AddTitle(rootPanel, "Taut and Swing"); _tautToleranceField = Slider(rootPanel, "Taut Tolerance", "ultrahook.tautTolerance", 0f, 3f, 0.5f, 2); AddDescription(rootPanel, "How close to the minimum length the rope is before it counts as taut."); _tautCorrectionGainField = Slider(rootPanel, "Taut Correction Gain", "ultrahook.tautGain", 0f, 40f, 10f, 1); AddDescription(rootPanel, "How firmly the taut rope holds its length."); _tautAccelerationField = Slider(rootPanel, "Taut Acceleration", "ultrahook.tautAccel", 5f, 400f, 60f, 0); AddDescription(rootPanel, "How quickly the taut correction is applied."); _maxInwardCorrectionField = Slider(rootPanel, "Max Inward Correction Speed", "ultrahook.maxInward", 0f, 120f, 20f, 0); AddDescription(rootPanel, "Fastest the taut rope pulls V1 back in when it drifts too far out."); _maxOutwardCorrectionField = Slider(rootPanel, "Max Outward Correction Speed", "ultrahook.maxOutward", 0f, 120f, 30f, 0); AddDescription(rootPanel, "Fastest the taut rope lets V1 ease back out when it is pushed too close."); _maxAngularSpeedField = Slider(rootPanel, "Max Angular Speed", "ultrahook.maxAngular", 0.5f, 20f, 6f, 1); AddDescription(rootPanel, "Caps how fast V1 can swing around the anchor. Prevents runaway orbiting."); _tangentialDampingField = Slider(rootPanel, "Tangential Damping", "ultrahook.tangentialDamping", 0f, 10f, 1.5f, 2); AddDescription(rootPanel, "How quickly swinging motion bleeds off. Higher settles the swing sooner."); AddTitle(rootPanel, "Momentum"); _maxMomentumBonusField = Slider(rootPanel, "Max Momentum Bonus", "ultrahook.maxMomentum", 0f, 200f, 60f, 0); _momentumBonusDescription = AddDescription(rootPanel, "Extra launch speed a full-length pull can bank for the cancel."); _maxReleaseSpeedField = Slider(rootPanel, "Max Release Speed", "ultrahook.maxRelease", 0f, 400f, 150f, 0); _releaseSpeedDescription = AddDescription(rootPanel, "Hard cap on the speed a cancel can fling V1 at."); _directionFilterSpeedField = Slider(rootPanel, "Direction Filter Speed", "ultrahook.dirFilter", 1f, 60f, 12f, 0); _directionFilterDescription = AddDescription(rootPanel, "How quickly the release direction tracks the rope. Lower smooths out sudden angle changes."); UpdateMomentumVisibility(); AddTitle(rootPanel, "Release and Diagnostics"); _groundSnapSuppressField = Slider(rootPanel, "Ground Snap Suppression", "ultrahook.groundSuppress", 0f, 0.3f, 0.08f, 2); AddDescription(rootPanel, "Seconds after a cancel where ground snapping is held off so the launch is not redirected upward."); _debugLoggingField = new BoolField(rootPanel, "Debug Logging", "ultrahook.debug", false, true); AddDescription(rootPanel, "Log failed hook attempts and draw debug lines. For troubleshooting only."); } private static void UpdateMomentumVisibility() { bool hidden = !Momentum; SetHidden(_maxMomentumBonusField, _momentumBonusDescription, hidden); SetHidden(_maxReleaseSpeedField, _releaseSpeedDescription, hidden); SetHidden(_directionFilterSpeedField, _directionFilterDescription, hidden); } private static void SetHidden(FloatSliderField field, ConfigHeader description, bool hidden) { if (field != null) { ((ConfigField)field).hidden = hidden; } if (description != null) { ((ConfigField)description).hidden = hidden; } } private static FloatSliderField Slider(ConfigPanel panel, string name, string guid, float min, float max, float value, int decimals) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown return new FloatSliderField(panel, name, guid, new Tuple(min, max), value, decimals, true); } private static float Slider(FloatSliderField field, float fallback, float min) { if (field != null) { return Mathf.Max(field.value, min); } return fallback; } private static int ParseLayers(string raw) { if (string.IsNullOrWhiteSpace(raw)) { return 0; } int num = 0; string[] array = raw.Split(new char[4] { ' ', ',', ';', '\t' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { if (int.TryParse(array[i], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && result >= 0 && result <= 31) { num |= 1 << result; } } return num; } private static ConfigHeader AddTitle(ConfigPanel panel, string text) { //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_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown return new ConfigHeader(panel, text, 18) { textColor = TitleColor }; } private static ConfigHeader AddDescription(ConfigPanel panel, string text) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return AddDescription(panel, text, Color.gray); } private static ConfigHeader AddDescription(ConfigPanel panel, string text, Color color) { //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_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown return new ConfigHeader(panel, text, 14) { textColor = color }; } } }