using System; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using FistVR; using HLin_Mods.SharedBubble; using HarmonyLib; using OtherLoader; using UnityEngine; [assembly: Debuggable(DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] namespace HLin_Mods.BubbleLevelSet { [BepInPlugin("HLin_Mods.BubbleLevelSet", "BubbleLevelSet", "2.0.4")] [BepInProcess("h3vr.exe")] [Description("Built with MeatKit")] [BepInDependency("h3vr.otherloader", "1.3.0")] public class BubbleLevelSetPlugin : BaseUnityPlugin { private static readonly string BasePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); internal static ManualLogSource Logger; private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; LoadAssets(); } private void LoadAssets() { Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "HLin_Mods.BubbleLevelSet"); OtherLoader.RegisterDirectLoad(BasePath, "HLin_Mods.BubbleLevelSet", "", "", "hlin-bubblelevel", ""); } } public class BubbleLevel : GravityBubbleLevelController { [Header("BaseObject")] public GameObject baseObject = null; [Header("FVRAttachment")] public FVRFireArmAttachment attachment = null; [Header("LevelBubble")] public GameObject level_bubble = null; [Header("Bubble Travel")] [Tooltip("The level position when the bubble is centered.")] public float centerLocalX = -0.0084f; [Tooltip("The hard left travel stop in the bubble parent's local X space.")] public float minimumLocalX = -0.33f; [Tooltip("The hard right travel stop in the bubble parent's local X space.")] public float maximumLocalX = 0.33f; [Tooltip("Cant angle at which the rail bubble reaches a travel stop.")] [Range(1f, 45f)] public float fullScaleAngleDegrees = 3.25f; [Header("Fluid Motion")] [Tooltip("Spring acceleration that pulls the bubble toward its gravity-derived equilibrium.")] public float restoringAcceleration = 60f; [Tooltip("Linear viscous drag that represents liquid resistance.")] public float fluidDrag = 15f; [Tooltip("Small displacement at which the bubble settles instead of jittering.")] public float staticFrictionDistance = 5E-05f; [Tooltip("Velocity below which the bubble settles instead of jittering.")] public float settleVelocity = 0.0005f; [Tooltip("Safety cap for extreme attachment motion.")] public float maximumVelocity = 1.2f; protected override GameObject BaseObject => baseObject; protected override GameObject LevelBubble => level_bubble; protected override float CenterLocalX => centerLocalX; protected override float MinimumLocalX => minimumLocalX; protected override float MaximumLocalX => maximumLocalX; protected override float FullScaleAngleDegrees => fullScaleAngleDegrees; protected override float RestoringAcceleration => restoringAcceleration; protected override float FluidDrag => fluidDrag; protected override float StaticFrictionDistance => staticFrictionDistance; protected override float SettleVelocity => settleVelocity; protected override float MaximumVelocity => maximumVelocity; private void Awake() { if (!InitializeRuntimeState()) { Debug.LogWarning((object)"BubbleLevel disabled because its base object or bubble reference is missing.", (Object)(object)this); ((Behaviour)this).enabled = false; } } private void FixedUpdate() { StepController(); } } public class BubbleLevelMount : MonoBehaviour { [Header("BaseObject")] public GameObject baseObject = null; [Header("FVRAttachment")] public FVRFireArmAttachment attachment = null; [Header("LevelBubble")] public GameObject level_bubble = null; [Header("BubblePivot")] public Transform customPivot; private void Awake() { if ((Object)(object)attachment == (Object)null || (Object)(object)level_bubble == (Object)null || (Object)(object)customPivot == (Object)null) { Debug.LogWarning((object)"BubbleLevelMount disabled because an attachment, bubble, or pivot reference is missing.", (Object)(object)this); ((Behaviour)this).enabled = false; } } private float GetRoll() { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)attachment.curMount != (Object)null) { FVRFireArmAttachmentMount rootMount = attachment.curMount.GetRootMount(); if ((Object)(object)rootMount != (Object)null) { return 0f - Mathf.DeltaAngle(0f, ((Component)rootMount).transform.eulerAngles.z); } } return Mathf.DeltaAngle(0f, ((Component)attachment).transform.eulerAngles.z); } private void FixedUpdate() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: 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_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: 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_00c7: Unknown result type (might be due to invalid IL or missing references) float roll = GetRoll(); float num = 0f - Mathf.DeltaAngle(0f, level_bubble.transform.localEulerAngles.y); float num2 = Mathf.Clamp(3f * roll - num, -25f, 25f); if (num < 6.301f && num > -6.301f) { if (num < 6.3f && num > 5.8f) { num2 *= (7f - num) * 0.3f; } else if (num > -6.3f && num < -5.8f) { num2 *= (7f + num) * 0.3f; } level_bubble.transform.RotateAround(customPivot.position, Vector3.forward, num2 * Time.fixedDeltaTime); } else if (num >= 6.3f) { level_bubble.transform.RotateAround(customPivot.position, Vector3.forward, -0.02f * Mathf.Abs(num2) * Time.fixedDeltaTime); } else if (num <= -6.3f) { level_bubble.transform.RotateAround(customPivot.position, Vector3.forward, 0.02f * Mathf.Abs(num2) * Time.fixedDeltaTime); } } } public class BubbleLevelMountTest : MonoBehaviour { [Header("BaseObject")] public GameObject baseObject = null; [Header("FVRAttachment")] public FVRFireArmAttachment attachment = null; [Header("LevelBubble")] public GameObject level_bubble = null; [Header("BubblePivot")] public Transform customPivot; [Header("Angular Travel")] public float minimumAngle = -6.3f; public float maximumAngle = 6.3f; [Header("Gravity Reference")] public Vector3 gravityAtLevelLocal = Vector3.back; [Header("Fluid Motion")] public float restoringAcceleration = 70f; public float fluidDrag = 16f; public float staticFrictionAngle = 0.01f; public float settleVelocity = 0.01f; public float maximumAngularVelocity = 120f; private Vector3 initialBubbleOffsetLocal; private Quaternion initialBubbleRotationLocal; private Vector3 levelDirectionLocal; private Vector3 trackAxisLocal; private float bubbleAngle; private float bubbleAngularVelocity; private void Awake() { //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_0068: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: 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) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: 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_00d3: 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_00db: 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) if ((Object)(object)attachment == (Object)null || (Object)(object)level_bubble == (Object)null || (Object)(object)customPivot == (Object)null) { Debug.LogWarning((object)"BubbleLevelMountTest disabled because an attachment, bubble, or pivot reference is missing.", (Object)(object)this); ((Behaviour)this).enabled = false; return; } initialBubbleOffsetLocal = customPivot.InverseTransformPoint(level_bubble.transform.position); initialBubbleRotationLocal = Quaternion.Inverse(customPivot.rotation) * level_bubble.transform.rotation; Vector3 val = customPivot.InverseTransformDirection(-level_bubble.transform.forward); trackAxisLocal = ((Vector3)(ref val)).normalized; Vector3 val2 = Vector3.ProjectOnPlane(gravityAtLevelLocal, trackAxisLocal); levelDirectionLocal = ((Vector3)(ref val2)).normalized; if (((Vector3)(ref trackAxisLocal)).sqrMagnitude < 1E-06f || ((Vector3)(ref initialBubbleOffsetLocal)).sqrMagnitude < 1E-12f || ((Vector3)(ref levelDirectionLocal)).sqrMagnitude < 1E-06f) { Debug.LogWarning((object)"BubbleLevelMountTest disabled because its pivot geometry cannot define a gravity track.", (Object)(object)this); ((Behaviour)this).enabled = false; } } private void FixedUpdate() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_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_005a: Unknown result type (might be due to invalid IL or missing references) if (!((Behaviour)this).enabled || (Object)(object)level_bubble == (Object)null || (Object)(object)customPivot == (Object)null) { return; } Vector3 projectedGravityDirection = GetProjectedGravityDirection(); float num = 0f; if (((Vector3)(ref projectedGravityDirection)).sqrMagnitude >= 1E-06f) { float num2 = SignedAngle(levelDirectionLocal, projectedGravityDirection, trackAxisLocal); num = Mathf.Clamp(0f - num2, minimumAngle, maximumAngle); } float num3 = num - bubbleAngle; if (Mathf.Abs(num3) <= staticFrictionAngle && Mathf.Abs(bubbleAngularVelocity) <= settleVelocity) { bubbleAngle = num; bubbleAngularVelocity = 0f; } else { float num4 = restoringAcceleration * num3 - fluidDrag * bubbleAngularVelocity; bubbleAngularVelocity = Mathf.Clamp(bubbleAngularVelocity + num4 * Time.fixedDeltaTime, 0f - maximumAngularVelocity, maximumAngularVelocity); float num5 = bubbleAngle + bubbleAngularVelocity * Time.fixedDeltaTime; if (num5 <= minimumAngle) { bubbleAngle = minimumAngle; if (bubbleAngularVelocity < 0f) { bubbleAngularVelocity = 0f; } } else if (num5 >= maximumAngle) { bubbleAngle = maximumAngle; if (bubbleAngularVelocity > 0f) { bubbleAngularVelocity = 0f; } } else { bubbleAngle = num5; } } ApplyBubblePose(); } private Vector3 GetProjectedGravityDirection() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_0089: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)customPivot == (Object)null) && !(((Vector3)(ref trackAxisLocal)).sqrMagnitude < 1E-06f)) { Vector3 gravity = Physics.gravity; if (!(((Vector3)(ref gravity)).sqrMagnitude < 1E-06f)) { Vector3 val = customPivot.InverseTransformDirection(Physics.gravity); Vector3 val2 = Vector3.ProjectOnPlane(val, trackAxisLocal); return (!(((Vector3)(ref val2)).sqrMagnitude < 1E-06f)) ? ((Vector3)(ref val2)).normalized : Vector3.zero; } } return Vector3.zero; } private void ApplyBubblePose() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_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_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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) Quaternion val = Quaternion.AngleAxis(bubbleAngle, trackAxisLocal); level_bubble.transform.position = customPivot.TransformPoint(val * initialBubbleOffsetLocal); level_bubble.transform.rotation = customPivot.rotation * val * initialBubbleRotationLocal; } private static float SignedAngle(Vector3 from, Vector3 to, Vector3 axis) { //IL_0001: 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_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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return Mathf.Atan2(Vector3.Dot(axis, Vector3.Cross(from, to)), Vector3.Dot(from, to)) * 57.29578f; } } public class CosineMount : MonoBehaviour { [Header("Wheel")] public GameObject wheel = null; private void Start() { } private void FixedUpdate() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) Vector3 eulerAngles = wheel.transform.eulerAngles; eulerAngles.x = -90f; wheel.transform.eulerAngles = eulerAngles; } } } namespace HLin_Mods.SharedBubble { public static class GravityBubbleLevelMotion { public struct State { public float BubbleVelocity; public Transform BubbleTransform; public Transform MovementSpace; public Vector3 CachedGravity; public Vector3 CachedGravityDirection; public float CachedFullScaleAngle; public float CachedFullScaleGravity; public bool HasCachedGravityDirection; public bool HasCachedFullScaleGravity; public bool Initialized; } public static bool Initialize(GameObject baseObject, GameObject levelBubble, ref State state) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)baseObject == (Object)null || (Object)(object)levelBubble == (Object)null) { return false; } state.BubbleTransform = levelBubble.transform; state.MovementSpace = ((!((Object)(object)state.BubbleTransform.parent != (Object)null)) ? baseObject.transform : state.BubbleTransform.parent); RefreshGravityDirection(Physics.gravity, ref state); state.Initialized = (Object)(object)state.MovementSpace != (Object)null; return state.Initialized; } public static bool Step(GameObject baseObject, GameObject levelBubble, float centerLocalX, float minimumLocalX, float maximumLocalX, float fullScaleAngleDegrees, float restoringAcceleration, float fluidDrag, float staticFrictionDistance, float settleVelocity, float maximumVelocity, ref State state) { //IL_0046: 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_0077: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_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_00b2: 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_00eb: 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_0203: Unknown result type (might be due to invalid IL or missing references) if ((!state.Initialized || (Object)(object)state.BubbleTransform == (Object)null || (Object)(object)state.MovementSpace == (Object)null) && !Initialize(baseObject, levelBubble, ref state)) { return false; } Vector3 gravity = Physics.gravity; if (state.HasCachedGravityDirection) { Vector3 val = gravity - state.CachedGravity; if (!(((Vector3)(ref val)).sqrMagnitude > 1E-06f)) { goto IL_007f; } } RefreshGravityDirection(gravity, ref state); goto IL_007f; IL_007f: Vector3 right = state.MovementSpace.right; if (!state.HasCachedGravityDirection || ((Vector3)(ref right)).sqrMagnitude < 1E-06f) { return true; } float gravityAlongTravel = Mathf.Clamp(Vector3.Dot(state.CachedGravityDirection, right), -1f, 1f); float gravityTarget = GetGravityTarget(GetFullScaleTravel(gravityAlongTravel, fullScaleAngleDegrees, ref state), centerLocalX, minimumLocalX, maximumLocalX); Vector3 localPosition = state.BubbleTransform.localPosition; float num = gravityTarget - localPosition.x; if (Mathf.Abs(num) <= staticFrictionDistance && Mathf.Abs(state.BubbleVelocity) <= settleVelocity) { localPosition.x = gravityTarget; state.BubbleVelocity = 0f; } else { float num2 = restoringAcceleration * num - fluidDrag * state.BubbleVelocity; state.BubbleVelocity = Mathf.Clamp(state.BubbleVelocity + num2 * Time.fixedDeltaTime, 0f - maximumVelocity, maximumVelocity); float num3 = localPosition.x + state.BubbleVelocity * Time.fixedDeltaTime; if (num3 <= minimumLocalX) { localPosition.x = minimumLocalX; if (state.BubbleVelocity < 0f) { state.BubbleVelocity = 0f; } } else if (num3 >= maximumLocalX) { localPosition.x = maximumLocalX; if (state.BubbleVelocity > 0f) { state.BubbleVelocity = 0f; } } else { localPosition.x = num3; } } state.BubbleTransform.localPosition = localPosition; return true; } private static void RefreshGravityDirection(Vector3 gravity, ref State state) { //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_0034: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) state.CachedGravity = gravity; float sqrMagnitude = ((Vector3)(ref gravity)).sqrMagnitude; if (sqrMagnitude < 1E-06f) { state.CachedGravityDirection = Vector3.zero; state.HasCachedGravityDirection = false; } else { state.CachedGravityDirection = gravity / Mathf.Sqrt(sqrMagnitude); state.HasCachedGravityDirection = true; } } private static float GetGravityTarget(float gravityAlongTravel, float centerLocalX, float minimumLocalX, float maximumLocalX) { if (gravityAlongTravel >= 0f) { return centerLocalX - gravityAlongTravel * (centerLocalX - minimumLocalX); } return centerLocalX - gravityAlongTravel * (maximumLocalX - centerLocalX); } private static float GetFullScaleTravel(float gravityAlongTravel, float fullScaleAngleDegrees, ref State state) { float num = Mathf.Clamp(fullScaleAngleDegrees, 1f, 45f); if (!state.HasCachedFullScaleGravity || Mathf.Abs(state.CachedFullScaleAngle - num) > 0.0001f) { state.CachedFullScaleAngle = num; state.CachedFullScaleGravity = Mathf.Sin(num * ((float)Math.PI / 180f)); state.HasCachedFullScaleGravity = true; } return Mathf.Clamp(gravityAlongTravel / state.CachedFullScaleGravity, -1f, 1f); } } } namespace HLin_Mods.BubbleLevelSet { public abstract class GravityBubbleLevelController : MonoBehaviour { private GravityBubbleLevelMotion.State motionState; protected abstract GameObject BaseObject { get; } protected abstract GameObject LevelBubble { get; } protected abstract float CenterLocalX { get; } protected abstract float MinimumLocalX { get; } protected abstract float MaximumLocalX { get; } protected abstract float FullScaleAngleDegrees { get; } protected abstract float RestoringAcceleration { get; } protected abstract float FluidDrag { get; } protected abstract float StaticFrictionDistance { get; } protected abstract float SettleVelocity { get; } protected abstract float MaximumVelocity { get; } protected bool InitializeRuntimeState() { return GravityBubbleLevelMotion.Initialize(BaseObject, LevelBubble, ref motionState); } protected void StepController() { if (!GravityBubbleLevelMotion.Step(BaseObject, LevelBubble, CenterLocalX, MinimumLocalX, MaximumLocalX, FullScaleAngleDegrees, RestoringAcceleration, FluidDrag, StaticFrictionDistance, SettleVelocity, MaximumVelocity, ref motionState)) { ((Behaviour)this).enabled = false; } } } }