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;
}
}
}