Decompiled source of qOmniGravityMod v1.1.0

qOmniGravityMod.dll

Decompiled 14 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
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("qOmniGravityMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("qOmniGravityMod")]
[assembly: AssemblyTitle("qOmniGravityMod")]
[assembly: AssemblyVersion("1.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace qOmniGravityMod
{
	public enum OmniMode
	{
		Normal,
		SidewaysLeft,
		SidewaysRight,
		UpsideDown,
		HeightRotation
	}
	public enum RotationStyle
	{
		World,
		Camera
	}
	[BepInPlugin("q.whiteknuckle.omnigravity", "qOmniGravityMod", "1.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "q.whiteknuckle.omnigravity";

		public const string Name = "qOmniGravityMod";

		public const string Version = "1.1.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<OmniMode> Mode;

		internal static ConfigEntry<RotationStyle> Style;

		internal static ConfigEntry<float> MetersPerHalfTurn;

		internal static ConfigEntry<bool> ClockwiseRotation;

		internal static ConfigEntry<bool> LoopRotation;

		internal static ConfigEntry<float> SmoothSpeed;

		internal static ConfigEntry<bool> RotateMouseLook;

		internal static ConfigEntry<KeyCode> CycleModeKey;

		internal static ConfigEntry<KeyCode> CycleStyleKey;

		internal static ConfigEntry<float> WorldStepDegrees;

		internal static float CurrentRoll;

		internal static float CurrentWorldAngle;

		private void Awake()
		{
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Mode = ((BaseUnityPlugin)this).Config.Bind<OmniMode>("General", "Mode", OmniMode.HeightRotation, "Normal, SidewaysLeft, SidewaysRight, UpsideDown, or HeightRotation (world turns as you climb).");
			Style = ((BaseUnityPlugin)this).Config.Bind<RotationStyle>("General", "RotationStyle", RotationStyle.World, "World: real gravity, the superstructure turns around you and you can stand on walls/ceilings. Camera: only the view rolls.");
			CycleModeKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "CycleModeKey", (KeyCode)289, "Key that cycles through modes in-game.");
			CycleStyleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "CycleStyleKey", (KeyCode)290, "Key that switches between World and Camera rotation style.");
			MetersPerHalfTurn = ((BaseUnityPlugin)this).Config.Bind<float>("HeightRotation", "MetersPerHalfTurn", 1000f, "Height climbed for a 180 degree turn. 1000 = sideways at 500m, upside down at 1000m.");
			ClockwiseRotation = ((BaseUnityPlugin)this).Config.Bind<bool>("HeightRotation", "Clockwise", true, "Direction the world turns as you climb.");
			LoopRotation = ((BaseUnityPlugin)this).Config.Bind<bool>("HeightRotation", "KeepRotatingPastHalfTurn", true, "true: keeps turning past upside down (full circle at 2x MetersPerHalfTurn). false: stays upside down.");
			SmoothSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SmoothSpeed", 2f, "How fast the rotation eases to its target angle (higher = snappier).");
			RotateMouseLook = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "RotateMouseLook", true, "Camera style only: rotate mouse/stick input with the view so moving the mouse up always looks up on screen.");
			WorldStepDegrees = ((BaseUnityPlugin)this).Config.Bind<float>("World", "MinStepDegrees", 0.1f, "World style only: smallest rotation applied in one go. Raise it if slow turning costs too much performance.");
			new Harmony("q.whiteknuckle.omnigravity").PatchAll();
			Log.LogInfo((object)string.Format("{0} {1} loaded. Mode = {2} ({3}). {4} = cycle mode, {5} = World/Camera.", "qOmniGravityMod", "1.1.0", Mode.Value, Style.Value, CycleModeKey.Value, CycleStyleKey.Value));
		}

		private void Update()
		{
			//IL_0005: 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)
			if (Input.GetKeyDown(CycleModeKey.Value))
			{
				Mode.Value = (OmniMode)((int)(Mode.Value + 1) % Enum.GetValues(typeof(OmniMode)).Length);
				Log.LogInfo((object)$"Mode -> {Mode.Value}");
			}
			if (Input.GetKeyDown(CycleStyleKey.Value))
			{
				Style.Value = ((Style.Value == RotationStyle.World) ? RotationStyle.Camera : RotationStyle.World);
				Log.LogInfo((object)$"Style -> {Style.Value}");
			}
			WorldRotation.CheckForNewWorld();
			float targetAngle = GetTargetAngle();
			float t = 1f - Mathf.Exp((0f - SmoothSpeed.Value) * Time.unscaledDeltaTime);
			float target = ((Style.Value == RotationStyle.Camera) ? targetAngle : 0f);
			float target2 = ((Style.Value == RotationStyle.World) ? targetAngle : 0f);
			CurrentRoll = Ease(CurrentRoll, target, t);
			CurrentWorldAngle = Ease(CurrentWorldAngle, target2, t);
			WorldRotation.ApplyAngle(CurrentWorldAngle);
		}

		private static float Ease(float current, float target, float t)
		{
			if (Mode.Value != OmniMode.HeightRotation)
			{
				return Mathf.LerpAngle(current, target, t);
			}
			return Mathf.Lerp(current, target, t);
		}

		private static float GetTargetAngle()
		{
			switch (Mode.Value)
			{
			case OmniMode.SidewaysLeft:
				return 90f;
			case OmniMode.SidewaysRight:
				return -90f;
			case OmniMode.UpsideDown:
				return 180f;
			case OmniMode.HeightRotation:
			{
				float num = Mathf.Max(WorldRotation.GetTowerHeight(), 0f) / Mathf.Max(MetersPerHalfTurn.Value, 1f) * 180f;
				if (!LoopRotation.Value)
				{
					num = Mathf.Min(num, 180f);
				}
				if (!ClockwiseRotation.Value)
				{
					return num;
				}
				return 0f - num;
			}
			default:
				return 0f;
			}
		}
	}
	[HarmonyPatch(typeof(CL_CameraControl), "LateUpdate")]
	internal static class CameraRollPatch
	{
		private static void Postfix(CL_CameraControl __instance)
		{
			//IL_004d: 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)
			ENT_Player playerObject = ENT_Player.playerObject;
			if (!((Object)(object)playerObject == (Object)null) && !((Object)(object)playerObject.camRoot != (Object)(object)__instance) && !(Mathf.Abs(Plugin.CurrentRoll) < 0.01f))
			{
				Transform child = ((Component)__instance).transform.GetChild(0);
				child.localRotation = Quaternion.Euler(0f, 0f, Plugin.CurrentRoll) * child.localRotation;
			}
		}
	}
	[HarmonyPatch(typeof(InputManager), "GetLookVector")]
	internal static class LookInputPatch
	{
		private static void Postfix(ref Vector2 __result)
		{
			//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)
			if (Plugin.RotateMouseLook.Value && !(Mathf.Abs(Plugin.CurrentRoll) < 0.01f))
			{
				float num = Plugin.CurrentRoll * (MathF.PI / 180f);
				float num2 = Mathf.Cos(num);
				float num3 = Mathf.Sin(num);
				__result = new Vector2(num2 * __result.x - num3 * __result.y, num3 * __result.x + num2 * __result.y);
			}
		}
	}
	internal static class WorldRotation
	{
		private static readonly Vector3 Axis = Vector3.forward;

		private static float appliedAngle;

		private static WorldLoader trackedLoader;

		private static readonly FieldRef<CL_GameManager, float> WorldOffsetRef = AccessTools.FieldRefAccess<CL_GameManager, float>("currentWorldOffset");

		internal static bool IsRotated => Mathf.Abs(appliedAngle) > 0.01f;

		internal static Transform Tower
		{
			get
			{
				if (!WorldLoader.initialized || !((Object)(object)WorldLoader.instance != (Object)null))
				{
					return null;
				}
				return ((Component)WorldLoader.instance).transform;
			}
		}

		internal static void CheckForNewWorld()
		{
			//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_007f: 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_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)
			WorldLoader val = (WorldLoader.initialized ? WorldLoader.instance : null);
			if (!((Object)(object)val == (Object)(object)trackedLoader))
			{
				trackedLoader = val;
				appliedAngle = 0f;
				Plugin.CurrentWorldAngle = 0f;
				if ((Object)(object)val != (Object)null && (((Component)val).transform.position != Vector3.zero || ((Component)val).transform.rotation != Quaternion.identity))
				{
					Plugin.Log.LogWarning((object)$"WorldLoader does not start at the origin ({((Component)val).transform.position}, {((Component)val).transform.eulerAngles}); tower height may be off.");
				}
			}
		}

		internal static float GetTowerHeight()
		{
			//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)
			CL_GameManager gMan = CL_GameManager.gMan;
			ENT_Player playerObject = ENT_Player.playerObject;
			if ((Object)(object)gMan == (Object)null || (Object)(object)playerObject == (Object)null)
			{
				return 0f;
			}
			Transform tower = Tower;
			if ((Object)(object)tower == (Object)null)
			{
				return gMan.GetPlayerCorrectedHeight();
			}
			return tower.InverseTransformPoint(((Component)playerObject).transform.position).y - WorldOffsetRef.Invoke(gMan);
		}

		internal static void ApplyAngle(float targetAngle)
		{
			//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_0099: Unknown result type (might be due to invalid IL or missing references)
			Transform tower = Tower;
			ENT_Player playerObject = ENT_Player.playerObject;
			if ((Object)(object)tower == (Object)null || (Object)(object)playerObject == (Object)null)
			{
				return;
			}
			float num = targetAngle - appliedAngle;
			bool flag = Mathf.Abs(targetAngle) < 0.01f && Mathf.Abs(appliedAngle) > 0f;
			if (!(Mathf.Abs(num) < Plugin.WorldStepDegrees.Value) || flag)
			{
				if (((Component)playerObject).transform.IsChildOf(tower))
				{
					Plugin.Log.LogError((object)"Player is inside the WorldLoader hierarchy; world rotation disabled.");
					Plugin.Style.Value = RotationStyle.Camera;
				}
				else
				{
					Rotate(Quaternion.AngleAxis(num, Axis), ((Component)playerObject).transform.position, tower, playerObject);
					appliedAngle += num;
				}
			}
		}

		private static void Rotate(Quaternion q, Vector3 pivot, Transform tower, ENT_Player player)
		{
			//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_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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: 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_00dd: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			RotateAround(tower, q, pivot);
			List<GameObject> activeSkyboxes = SkyboxManager.activeSkyboxes;
			if (activeSkyboxes != null)
			{
				foreach (GameObject item in activeSkyboxes)
				{
					if ((Object)(object)item != (Object)null && !item.transform.IsChildOf(tower))
					{
						RotateAround(item.transform, q, pivot);
					}
				}
			}
			List<GameEntity> entities = GameEntity.entities;
			if (entities != null)
			{
				foreach (GameEntity item2 in entities)
				{
					if (!((Object)(object)item2 == (Object)null) && !((Object)(object)item2 == (Object)(object)player) && !((Object)(object)((Component)item2).transform.parent != (Object)null))
					{
						RotateAround(((Component)item2).transform, q, pivot);
						Rigidbody component = ((Component)item2).GetComponent<Rigidbody>();
						if ((Object)(object)component != (Object)null && !component.isKinematic)
						{
							component.linearVelocity = q * component.linearVelocity;
							component.angularVelocity = q * component.angularVelocity;
						}
					}
				}
			}
			Physics.SyncTransforms();
		}

		private static void RotateAround(Transform t, Quaternion q, Vector3 pivot)
		{
			//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_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_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			t.SetPositionAndRotation(pivot + q * (t.position - pivot), q * t.rotation);
		}

		internal static Vector3 ToTower(Vector3 world)
		{
			//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)
			return Tower.InverseTransformPoint(world);
		}

		internal static Vector3 FromTower(Vector3 local)
		{
			//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)
			return Tower.TransformPoint(local);
		}
	}
	[HarmonyPatch(typeof(DEN_DeathFloor), "Update")]
	internal static class DeathFloorPatch
	{
		private struct State
		{
			public bool Swapped;

			public Vector3 PlayerWorld;
		}

		private static void Prefix(DEN_DeathFloor __instance, out State __state)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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)
			__state = default(State);
			ENT_Player playerObject = ENT_Player.playerObject;
			if (WorldRotation.IsRotated && !((Object)(object)playerObject == (Object)null) && !((Object)(object)WorldRotation.Tower == (Object)null))
			{
				__state.Swapped = true;
				__state.PlayerWorld = ((Component)playerObject).transform.position;
				((Component)playerObject).transform.position = WorldRotation.ToTower(__state.PlayerWorld);
				((Component)__instance).transform.position = WorldRotation.ToTower(((Component)__instance).transform.position);
			}
		}

		private static Exception Finalizer(Exception __exception, DEN_DeathFloor __instance, State __state)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (!__state.Swapped)
			{
				return __exception;
			}
			((Component)__instance).transform.position = WorldRotation.FromTower(((Component)__instance).transform.position);
			ENT_Player playerObject = ENT_Player.playerObject;
			if ((Object)(object)playerObject != (Object)null)
			{
				((Component)playerObject).transform.position = __state.PlayerWorld;
			}
			if ((Object)(object)FXManager.fxMan != (Object)null)
			{
				FXManager.fxMan.corruptionHeight = -10000f;
			}
			return __exception;
		}
	}
	[HarmonyPatch(typeof(CL_GameManager), "SetWorldOffset")]
	internal static class WorldOffsetPatch
	{
		private static bool Prefix(float amount)
		{
			if (!WorldRotation.IsRotated)
			{
				return true;
			}
			Plugin.Log.LogWarning((object)$"Skipped world recentering by {amount} because the world is rotated.");
			return false;
		}
	}
}