using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Mirror; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; using UnityEngine.UI; [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("CrewPOV")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0")] [assembly: AssemblyProduct("CrewPOV")] [assembly: AssemblyTitle("CrewPOV")] [assembly: AssemblyVersion("0.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 CrewPOV { public enum CreditCorner { TopLeft, TopRight, BottomLeft, BottomRight } internal static class CrewPovCredit { private static GameObject _go; private static RawImage _raw; private static RectTransform _rt; private static Texture2D _tex; private static bool _created; private static bool _failed; private static CreditCorner _appliedCorner = (CreditCorner)(-1); private static float _appliedWidth = float.NaN; private static Type _shiftMgrType; private static FieldInfo _fPhase; private static Object _shiftMgr; private static bool _reflTried; private static float _nextPhaseCheck; private static bool _inShift; internal static void Tick() { if (_failed) { return; } if (Plugin.ShowCredit == null || !Plugin.ShowCredit.Value) { if ((Object)(object)_go != (Object)null && _go.activeSelf) { _go.SetActive(false); } return; } try { if (!_created) { Create(); } if (!((Object)(object)_go == (Object)null)) { ApplyCorner(); UpdatePhase(); bool flag = !_inShift; if (_go.activeSelf != flag) { _go.SetActive(flag); } } } catch (Exception ex) { _failed = true; Plugin.Log.LogWarning((object)("CrewPOV credit: " + ex.Message)); } } private static void Create() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //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) _created = true; _tex = LoadPng(); if ((Object)(object)_tex == (Object)null) { _failed = true; Plugin.Log.LogWarning((object)"CrewPOV: credit.png not found next to the DLL — credit disabled."); return; } _go = new GameObject("CrewPOV.CreditCanvas"); Object.DontDestroyOnLoad((Object)(object)_go); Canvas obj = _go.AddComponent(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 29500; _go.AddComponent().uiScaleMode = (ScaleMode)0; GameObject val = new GameObject("Image"); val.transform.SetParent(_go.transform, false); _raw = val.AddComponent(); _raw.texture = (Texture)(object)_tex; ((Graphic)_raw).raycastTarget = false; _rt = ((Graphic)_raw).rectTransform; Plugin.Log.LogInfo((object)("CrewPOV: credit canvas created (credit.png " + ((Texture)_tex).width + "x" + ((Texture)_tex).height + ").")); } private static void UpdatePhase() { if (Time.unscaledTime < _nextPhaseCheck) { return; } _nextPhaseCheck = Time.unscaledTime + 1f; if (!_reflTried) { _reflTried = true; _shiftMgrType = AccessTools.TypeByName("ShiftManager"); _fPhase = ((_shiftMgrType != null) ? AccessTools.Field(_shiftMgrType, "_shiftPhase") : null); } if (_fPhase == null) { _inShift = false; return; } try { if (_shiftMgr == (Object)null) { _shiftMgr = Object.FindObjectOfType(_shiftMgrType); } _inShift = _shiftMgr != (Object)null && Convert.ToInt32(_fPhase.GetValue(_shiftMgr)) == 3; } catch { _inShift = false; } } private static Texture2D LoadPng() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown try { string directoryName = Path.GetDirectoryName(typeof(Plugin).Assembly.Location); string text = (string.IsNullOrEmpty(directoryName) ? null : Path.Combine(directoryName, "credit.png")); if (text == null || !File.Exists(text)) { return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val, File.ReadAllBytes(text))) { return null; } ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; return val; } catch { return null; } } private static void ApplyCorner() { //IL_00b0: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: 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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_rt == (Object)null) && !((Object)(object)_tex == (Object)null)) { CreditCorner creditCorner = ((Plugin.CreditCornerCfg != null) ? Plugin.CreditCornerCfg.Value : CreditCorner.TopLeft); float num = ((Plugin.CreditWidth != null) ? Plugin.CreditWidth.Value : 320f); if (creditCorner != _appliedCorner || num != _appliedWidth) { _appliedCorner = creditCorner; _appliedWidth = num; bool flag = creditCorner == CreditCorner.TopLeft || creditCorner == CreditCorner.BottomLeft; bool flag2 = creditCorner == CreditCorner.TopLeft || creditCorner == CreditCorner.TopRight; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(flag ? 0f : 1f, flag2 ? 1f : 0f); RectTransform rt = _rt; RectTransform rt2 = _rt; Vector2 val2 = (_rt.pivot = val); Vector2 anchorMin = (rt2.anchorMax = val2); rt.anchorMin = anchorMin; float num2 = 12f; _rt.anchoredPosition = new Vector2(flag ? num2 : (0f - num2), flag2 ? (0f - num2) : num2); _rt.sizeDelta = new Vector2(num, num * (float)((Texture)_tex).height / (float)Mathf.Max(1, ((Texture)_tex).width)); } } } } [BepInPlugin("com.hunter.crewpov", "CrewPOV", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string Guid = "com.hunter.crewpov"; public const string Name = "CrewPOV"; public const string Version = "1.0.0"; internal static ManualLogSource Log; internal static ConfigEntry Enabled; internal static ConfigEntry ToggleKey; internal static ConfigEntry IncludeFirstPerson; internal static ConfigEntry ChaseHeight; internal static ConfigEntry ChaseForward; internal static ConfigEntry ChasePitch; internal static ConfigEntry FpHeight; internal static ConfigEntry FpForward; internal static ConfigEntry FpPitch; internal static ConfigEntry MouseLook; internal static ConfigEntry MouseSensitivity; internal static ConfigEntry MouseRecenter; internal static ConfigEntry PadToggleButton; internal static ConfigEntry PadRecenterButton; internal static ConfigEntry PadLook; internal static ConfigEntry PadLookSensitivity; internal static ConfigEntry PadInvertY; internal static ConfigEntry CamFollowSpeed; internal static ConfigEntry Blur; internal static ConfigEntry FocusDistance; internal static ConfigEntry SteerRelative; internal static ConfigEntry Scheme; internal static ConfigEntry SteerGain; internal static ConfigEntry SuppressPhone; internal static ConfigEntry TuningKeys; internal static ConfigEntry ShowCredit; internal static ConfigEntry CreditCornerCfg; internal static ConfigEntry CreditWidth; private void Awake() { //IL_03c9: Unknown result type (might be due to invalid IL or missing references) //IL_03d3: Expected O, but got Unknown //IL_03ec: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind("CrewPOV", "Enabled", true, "Master switch for the camera mod."); ToggleKey = ((BaseUnityPlugin)this).Config.Bind("CrewPOV", "ToggleKey", (KeyCode)118, "Cycles the camera: normal -> behind-head -> first person -> normal."); IncludeFirstPerson = ((BaseUnityPlugin)this).Config.Bind("CrewPOV", "IncludeFirstPerson", true, "Keep the real first-person view in the cycle. Turn off if you only want the behind-head camera (boxes on the forks block the first-person view; mouse look helps you peek past them)."); ChaseHeight = ((BaseUnityPlugin)this).Config.Bind("BehindHead", "Height", 2.7f, "Behind-head camera height (metres)."); ChaseForward = ((BaseUnityPlugin)this).Config.Bind("BehindHead", "Forward", -3.5f, "Behind-head camera distance from the forklift center (negative = behind)."); ChasePitch = ((BaseUnityPlugin)this).Config.Bind("BehindHead", "Pitch", 8f, "Behind-head downward tilt (degrees). Higher = the view centers closer to the forklift. Tune live with the 9 and 0 keys while the camera is active."); FpHeight = ((BaseUnityPlugin)this).Config.Bind("FirstPerson", "Height", 2f, "First-person camera height (metres)."); FpForward = ((BaseUnityPlugin)this).Config.Bind("FirstPerson", "Forward", 0f, "First-person camera forward offset from the forklift center (metres)."); FpPitch = ((BaseUnityPlugin)this).Config.Bind("FirstPerson", "Pitch", 8f, "First-person downward tilt (degrees). Higher = look closer in front of you."); MouseLook = ((BaseUnityPlugin)this).Config.Bind("MouseLook", "Enabled", true, "Move the mouse to look around (like turning the driver's head). In behind-head mode this orbits the camera around the forklift, so you can look behind you."); MouseSensitivity = ((BaseUnityPlugin)this).Config.Bind("MouseLook", "Sensitivity", 2f, "Mouse look sensitivity."); MouseRecenter = ((BaseUnityPlugin)this).Config.Bind("MouseLook", "AutoRecenter", false, "Automatically swing the view back behind the forklift after the look input has been still for a couple of seconds. Off by default: click R3 to snap back instead."); PadToggleButton = ((BaseUnityPlugin)this).Config.Bind("Controller", "ToggleButton", "select", "Controller button that cycles the camera (default = the Back/Select button, like the view button in racing games). Options: select, rightStickPress, leftStickPress, dpadUp, dpadDown, dpadLeft, dpadRight, buttonNorth/South/East/West, leftShoulder, rightShoulder. Empty = off."); PadRecenterButton = ((BaseUnityPlugin)this).Config.Bind("Controller", "RecenterButton", "rightStickPress", "Controller button that SNAPS the look-around view back behind the forklift (default = clicking the right stick, R3)."); PadLook = ((BaseUnityPlugin)this).Config.Bind("Controller", "StickLook", true, "Right stick looks around while a mod camera is active (orbits in behind-head, turns your head in first person). Auto-recenter applies the same as mouse look."); PadLookSensitivity = ((BaseUnityPlugin)this).Config.Bind("Controller", "StickSensitivity", 150f, "Right-stick look speed (degrees per second at full deflection)."); PadInvertY = ((BaseUnityPlugin)this).Config.Bind("Controller", "InvertY", false, "Invert the right stick's up/down for looking."); CamFollowSpeed = ((BaseUnityPlugin)this).Config.Bind("CrewPOV", "CameraFollowSpeed", 8f, "How quickly the camera follows the forklift's turning. Lower = smoother and lazier, higher = stiffer. 0 = locked rigidly to the forklift (the old jittery behavior)."); Blur = ((BaseUnityPlugin)this).Config.Bind("Blur", "Mode", BlurMode.Off, "What to do with the game's depth-of-field blur while a mod camera is active. Off (default) = no blur at all (sharpest). Focused = keep the blur but move the sharp focus to FocusDistance so what's near you is crisp (cinematic). Vanilla = leave the game's blur untouched (tuned for the far top-down camera, so it looks wrong up close). Whatever you pick, the normal camera always gets its blur back."); FocusDistance = ((BaseUnityPlugin)this).Config.Bind("Blur", "FocusDistance", 12f, "Focused mode only: how far ahead (metres) the camera is sharply focused. Lower = close things are crisp and the distance blurs; higher = sharp further out. Tune live with the - and = keys while a mod camera is active."); SteerRelative = ((BaseUnityPlugin)this).Config.Bind("Driving", "CameraRelativeSteering", true, "While a mod camera is active, steering follows the forklift instead of fixed map directions. Turn off to keep vanilla steering in all camera modes."); Scheme = ((BaseUnityPlugin)this).Config.Bind("Driving", "ControlScheme", SteerScheme.CameraRelative, "CameraRelative (default): everything on the left stick, pushed direction = drive direction relative to the forklift, right stick looks around. RightStickSteer: left stick up/down = gas and reverse, right stick left/right = steering (racing style; the right stick stops being look-around while driving, mouse still looks)."); SteerGain = ((BaseUnityPlugin)this).Config.Bind("Driving", "SteerStrength", 1f, "RightStickSteer only: how hard a full right-stick deflection turns (higher = sharper turning)."); SuppressPhone = ((BaseUnityPlugin)this).Config.Bind("Controller", "SuppressPhone", true, "Block the TipTap phone (it's bound to the right stick) while a mod camera is active, so looking around doesn't open it. The phone works normally in the vanilla camera."); TuningKeys = ((BaseUnityPlugin)this).Config.Bind("Dev", "TuningKeys", true, "While a mod camera is active: PageUp/PageDown = height, Home/End = forward, 9/0 = pitch (higher = view centers closer to the forklift), -/= = blur focus distance. Changes apply to the ACTIVE camera and are saved to this config."); ShowCredit = ((BaseUnityPlugin)this).Config.Bind("Credit", "ShowCredit", true, "Show the small 'CrewPOV by izaya_here' logo in the corner (menu, lobby and break room only, hidden during shifts). Set to false to hide it."); CreditCornerCfg = ((BaseUnityPlugin)this).Config.Bind("Credit", "Corner", CreditCorner.TopLeft, "Which screen corner the credit logo sits in."); CreditWidth = ((BaseUnityPlugin)this).Config.Bind("Credit", "ImageWidth", 320f, "On-screen width (pixels) of the credit logo."); ModCam.PatchAll(new Harmony("com.hunter.crewpov")); Log.LogInfo((object)(string.Format("{0} {1} loaded. {2} = cycle camera (normal / behind-head", "CrewPOV", "1.0.0", ToggleKey.Value) + (IncludeFirstPerson.Value ? " / first person" : "") + "), mouse = look around.")); } } public enum SteerScheme { RightStickSteer, CameraRelative } public enum BlurMode { Off, Focused, Vanilla } internal static class ModCam { private class DofSnap { public DepthOfField dof; public bool active; public DepthOfFieldMode mode; public float focusDistance; public bool focusOverride; public float gStart; public float gEnd; public bool gStartOverride; public bool gEndOverride; } private const int MODE_OFF = 0; private const int MODE_CHASE = 1; private const int MODE_FP = 2; private static Type _camCtrlType; private static FieldInfo _fCam; private static bool _resolved; private static bool _failed; private static int _mode = 0; private static Camera _cam; private static float _savedNearClip = -1f; private static int _lastFrame = -1; private static float _lookYaw; private static float _lookPitch; private static float _lastMouseMove; private static Vector3 _vanillaFwd = Vector3.forward; private static Vector3 _smoothFwd = Vector3.forward; private static bool _smoothInit; private static float _steerDeltaRad; private static bool _steerValid; private static string _transpileTarget = "?"; private static bool _steerCalledLogged; private static bool _steerAppliedLogged; private static bool _ttCalledLogged; private static bool _ttBlockedLogged; private static bool _padTogglePrev; private static bool _padRecenterPrev; private static readonly List _dofs = new List(); private static float _nextDofScan; private static bool _dofTouched; internal static void PatchAll(Harmony h) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Expected O, but got Unknown _camCtrlType = AccessTools.TypeByName("CameraController"); MethodInfo methodInfo = ((_camCtrlType != null) ? AccessTools.Method(_camCtrlType, "OnUpdatePresentation", (Type[])null, (Type[])null) : null); if (methodInfo == null) { Plugin.Log.LogWarning((object)"CrewPOV: CameraController.OnUpdatePresentation not found — mod disabled."); return; } h.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(ModCam).GetMethod("Post_CamTick", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Plugin.Log.LogInfo((object)"CrewPOV: camera tick hooked."); Type type = AccessTools.TypeByName("VehicleController"); HarmonyMethod val = new HarmonyMethod(typeof(ModCam).GetMethod("Steering_Transpiler", BindingFlags.Static | BindingFlags.NonPublic)); string[] array = new string[4] { "GetSteeringInput", "CheckForDrifting", "GetAccelerationInput", "GetTurnDirForVisual" }; foreach (string text in array) { MethodInfo methodInfo2 = ((type != null) ? AccessTools.Method(type, text, (Type[])null, (Type[])null) : null); if (methodInfo2 != null) { _transpileTarget = "VehicleController." + text; h.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null); } else { Plugin.Log.LogWarning((object)("CrewPOV: VehicleController." + text + " not found.")); } } MethodInfo methodInfo3 = AccessTools.Method(AccessTools.TypeByName("TipTapPhoneVisual"), "OnUpdatePresentation", (Type[])null, (Type[])null); if (methodInfo3 != null) { _transpileTarget = "TipTapPhoneVisual.OnUpdatePresentation"; h.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(ModCam).GetMethod("TipTap_Transpiler", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null); } else { Plugin.Log.LogWarning((object)"CrewPOV: TipTapPhoneVisual.OnUpdatePresentation not found."); } } private static IEnumerable Steering_Transpiler(IEnumerable instructions) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown List list = new List(instructions); MethodInfo methodInfo = AccessTools.Method(typeof(ModCam), "SteerFor", (Type[])null, (Type[])null); int num = 0; for (int i = 0; i < list.Count; i++) { MethodInfo methodInfo2 = list[i].operand as MethodInfo; if (methodInfo2 == null || methodInfo2.Name != "get_Steering") { continue; } for (int j = i + 1; j < list.Count && j <= i + 4; j++) { MethodInfo methodInfo3 = list[j].operand as MethodInfo; if (methodInfo3 != null && methodInfo3.Name == "ReadValue") { list.Insert(j + 1, new CodeInstruction(OpCodes.Call, (object)methodInfo)); num++; i = j + 1; break; } } } Plugin.Log.LogInfo((object)("CrewPOV: [" + _transpileTarget + "] steering reads rewritten: " + num + ((num == 0) ? " <-- PATTERN DID NOT MATCH" : ""))); return list; } private static IEnumerable TipTap_Transpiler(IEnumerable instructions) { //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown List list = new List(instructions); MethodInfo methodInfo = AccessTools.Method(typeof(ModCam), "TipTapPressedFor", (Type[])null, (Type[])null); int num = 0; for (int i = 0; i < list.Count; i++) { MethodInfo methodInfo2 = list[i].operand as MethodInfo; if (methodInfo2 == null || !methodInfo2.Name.StartsWith("get_") || methodInfo2.Name.IndexOf("TipTap", StringComparison.Ordinal) < 0) { continue; } for (int j = i + 1; j < list.Count && j <= i + 4; j++) { MethodInfo methodInfo3 = list[j].operand as MethodInfo; if (methodInfo3 != null && (methodInfo3.Name == "WasPressedThisFrame" || methodInfo3.Name == "WasPerformedThisFrame")) { list.Insert(j + 1, new CodeInstruction(OpCodes.Call, (object)methodInfo)); num++; i = j + 1; break; } } } Plugin.Log.LogInfo((object)("CrewPOV: [" + _transpileTarget + "] TipTap reads rewritten: " + num + ((num < 5) ? " <-- expected 5, check coverage" : ""))); return list; } private static Vector2 SteerFor(Vector2 orig) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0264: 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_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_015f: 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) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) if (!_steerCalledLogged) { _steerCalledLogged = true; Plugin.Log.LogInfo((object)("CrewPOV diag: SteerFor is LIVE (first call; mode=" + _mode + " valid=" + _steerValid + " mag=" + ((Vector2)(ref orig)).magnitude.ToString("0.00") + ").")); } if (_mode == 0 || !_steerValid || !Plugin.SteerRelative.Value) { return orig; } Gamepad current = Gamepad.current; Vector2 val; int num; if (current != null && current.leftStick != null) { val = ((InputControl)(object)current.leftStick).ReadValue(); num = ((((Vector2)(ref val)).magnitude >= 0.12f) ? 1 : 0); } else { num = 0; } bool flag = (byte)num != 0; if (Plugin.Scheme.Value == SteerScheme.RightStickSteer && current != null && current.rightStick != null) { val = ((InputControl)(object)current.rightStick).ReadValue(); if (((Vector2)(ref val)).magnitude >= 0.12f) { flag = true; } } if (!flag) { return orig; } Vector2 val2 = orig; if (Plugin.Scheme.Value == SteerScheme.RightStickSteer) { Gamepad current2 = Gamepad.current; if (current2 != null && current2.leftStick != null && current2.rightStick != null) { Vector2 val3 = ((InputControl)(object)current2.leftStick).ReadValue(); Vector2 val4 = ((InputControl)(object)current2.rightStick).ReadValue(); if (((Vector2)(ref val3)).magnitude > 0.12f || ((Vector2)(ref val4)).magnitude > 0.12f) { val2 = Vector2.ClampMagnitude(new Vector2(val4.x * Plugin.SteerGain.Value, val3.y), 1f); } } } if (!_steerAppliedLogged && ((Vector2)(ref val2)).sqrMagnitude > 0.01f) { _steerAppliedLogged = true; Plugin.Log.LogInfo((object)("CrewPOV diag: steering active (scheme=" + Plugin.Scheme.Value.ToString() + ", delta=" + (_steerDeltaRad * 57.29578f).ToString("0") + " deg, vanillaFwd=" + ((Vector3)(ref _vanillaFwd)).ToString("0.00") + ").")); } float num2 = Mathf.Cos(_steerDeltaRad); float num3 = Mathf.Sin(_steerDeltaRad); return new Vector2(val2.x * num2 + val2.y * num3, (0f - val2.x) * num3 + val2.y * num2); } private static bool TipTapPressedFor(bool orig) { if (!_ttCalledLogged) { _ttCalledLogged = true; Plugin.Log.LogInfo((object)"CrewPOV diag: TipTap corrector is LIVE (first call)."); } if (!orig) { return false; } if (_mode == 0 || !Plugin.SuppressPhone.Value) { return orig; } if (!_ttBlockedLogged) { _ttBlockedLogged = true; Plugin.Log.LogInfo((object)"CrewPOV diag: blocked a TipTap swipe press (mode active)."); } return false; } private static void Post_CamTick(object __instance) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_030e: 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_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) //IL_0347: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_036d: Unknown result type (might be due to invalid IL or missing references) //IL_036f: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_038b: Unknown result type (might be due to invalid IL or missing references) //IL_0390: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_03a1: Unknown result type (might be due to invalid IL or missing references) //IL_03b2: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.Enabled.Value) { return; } int frameCount = Time.frameCount; bool flag = frameCount != _lastFrame; _lastFrame = frameCount; try { if (flag) { if (Input.GetKeyDown(Plugin.ToggleKey.Value)) { CycleMode(); } HandlePadToggle(); CrewPovCredit.Tick(); } if (_mode == 0) { return; } if (!_resolved) { _resolved = true; _fCam = AccessTools.Field(_camCtrlType, "_cam"); if (_fCam == null) { _failed = true; Plugin.Log.LogWarning((object)"CrewPOV: CameraController._cam not found — mod camera unavailable."); } } if (_failed) { _mode = 0; return; } if ((Object)(object)_cam == (Object)null) { object? value = _fCam.GetValue(__instance); _cam = (Camera)((value is Camera) ? value : null); if ((Object)(object)_cam == (Object)null) { return; } _savedNearClip = _cam.nearClipPlane; _cam.nearClipPlane = 0.05f; Vector3 forward = ((Component)_cam).transform.forward; Vector3 val = forward; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude > 0.0001f) { _vanillaFwd = ((Vector3)(ref val)).normalized; } Plugin.Log.LogInfo((object)("CrewPOV diag: vanilla cam forward raw=" + ((Vector3)(ref forward)).ToString("0.00") + " captured=" + ((Vector3)(ref _vanillaFwd)).ToString("0.00") + ((((Vector3)(ref val)).sqrMagnitude <= 0.0001f) ? " (FALLBACK +Z used)" : ""))); } NetworkIdentity localPlayer = NetworkClient.localPlayer; if ((Object)(object)localPlayer == (Object)null) { _steerValid = false; return; } Transform transform = ((Component)localPlayer).transform; if (flag) { if (Plugin.TuningKeys.Value) { HandleTuningKeys(); } if (Plugin.MouseLook.Value) { HandleMouseLook(); } if (Plugin.PadLook.Value) { HandlePadLook(); } MaintainDof(); } float num = ((_mode == 1) ? Plugin.ChaseHeight.Value : Plugin.FpHeight.Value); float num2 = ((_mode == 1) ? Plugin.ChaseForward.Value : Plugin.FpForward.Value); float num3 = ((_mode == 1) ? Plugin.ChasePitch.Value : Plugin.FpPitch.Value); Vector3 forward2 = transform.forward; forward2.y = 0f; if (((Vector3)(ref forward2)).sqrMagnitude < 0.0001f) { forward2 = Vector3.forward; } ((Vector3)(ref forward2)).Normalize(); float value2 = Plugin.CamFollowSpeed.Value; if (!_smoothInit || value2 <= 0f) { _smoothFwd = forward2; _smoothInit = true; } else { _smoothFwd = Vector3.Slerp(_smoothFwd, forward2, 1f - Mathf.Exp((0f - value2) * Time.deltaTime)); _smoothFwd.y = 0f; if (((Vector3)(ref _smoothFwd)).sqrMagnitude < 0.0001f) { _smoothFwd = forward2; } ((Vector3)(ref _smoothFwd)).Normalize(); } _steerDeltaRad = Vector3.SignedAngle(_vanillaFwd, _smoothFwd, Vector3.up) * (MathF.PI / 180f); _steerValid = true; Vector3 val2 = Quaternion.Euler(0f, _lookYaw, 0f) * _smoothFwd; Vector3 position = transform.position + Vector3.up * num + val2 * num2; Quaternion rotation = Quaternion.LookRotation(val2, Vector3.up) * Quaternion.Euler(num3 + _lookPitch, 0f, 0f); ((Component)_cam).transform.position = position; ((Component)_cam).transform.rotation = rotation; } catch (Exception ex) { Plugin.Log.LogWarning((object)("CrewPOV tick: " + ex.Message)); } } private static void CycleMode() { int num = _mode + 1; if (num == 2 && !Plugin.IncludeFirstPerson.Value) { num++; } if (num > 2) { num = 0; } _mode = num; _lookYaw = 0f; _lookPitch = 0f; _smoothInit = false; if (_mode == 0) { _steerValid = false; RestoreDof(); if ((Object)(object)_cam != (Object)null && _savedNearClip > 0f) { _cam.nearClipPlane = _savedNearClip; _cam = null; } } Plugin.Log.LogInfo((object)("CrewPOV: camera = " + ((_mode == 0) ? "normal" : ((_mode == 1) ? "behind-head" : "first person")) + ".")); } private static void HandlePadToggle() { Gamepad current = Gamepad.current; if (current == null) { return; } ButtonControl val = NamedPadButton(current, Plugin.PadToggleButton.Value); int num; if (val != null) { num = (val.isPressed ? 1 : 0); if (num != 0 && !_padTogglePrev) { CycleMode(); } } else { num = 0; } _padTogglePrev = (byte)num != 0; if (_mode == 0) { return; } ButtonControl val2 = NamedPadButton(current, Plugin.PadRecenterButton.Value); int num2; if (val2 != null) { num2 = (val2.isPressed ? 1 : 0); if (num2 != 0 && !_padRecenterPrev) { _lookYaw = 0f; _lookPitch = 0f; } } else { num2 = 0; } _padRecenterPrev = (byte)num2 != 0; } private static void HandlePadLook() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_006c: Unknown result type (might be due to invalid IL or missing references) if (Plugin.Scheme.Value == SteerScheme.RightStickSteer) { return; } Gamepad current = Gamepad.current; if (current == null || current.rightStick == null) { return; } Vector2 val = ((InputControl)(object)current.rightStick).ReadValue(); if (!(((Vector2)(ref val)).magnitude < 0.15f)) { float num = Plugin.PadLookSensitivity.Value * Time.deltaTime; float num2 = (Plugin.PadInvertY.Value ? (0f - val.y) : val.y); _lookYaw += val.x * num; _lookPitch = Mathf.Clamp(_lookPitch - num2 * num, -45f, 45f); if (_lookYaw > 180f) { _lookYaw -= 360f; } if (_lookYaw < -180f) { _lookYaw += 360f; } _lastMouseMove = Time.realtimeSinceStartup; } } private static ButtonControl NamedPadButton(Gamepad pad, string name) { if (pad == null || string.IsNullOrEmpty(name)) { return null; } switch (name) { case "rightStickPress": return pad.rightStickButton; case "leftStickPress": return pad.leftStickButton; case "dpadUp": if (pad.dpad == null) { return null; } return pad.dpad.up; case "dpadDown": if (pad.dpad == null) { return null; } return pad.dpad.down; case "dpadLeft": if (pad.dpad == null) { return null; } return pad.dpad.left; case "dpadRight": if (pad.dpad == null) { return null; } return pad.dpad.right; case "select": return pad.selectButton; case "buttonNorth": return pad.buttonNorth; case "buttonSouth": return pad.buttonSouth; case "buttonEast": return pad.buttonEast; case "buttonWest": return pad.buttonWest; case "leftShoulder": return pad.leftShoulder; case "rightShoulder": return pad.rightShoulder; default: try { return ((InputControl)pad).TryGetChildControl(name); } catch { return null; } } } private static void HandleMouseLook() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_004d: Unknown result type (might be due to invalid IL or missing references) Mouse current = Mouse.current; if (current == null) { return; } Vector2 val = ((InputControl)(object)((Pointer)current).delta).ReadValue(); float num = Plugin.MouseSensitivity.Value * 0.08f; if (((Vector2)(ref val)).sqrMagnitude > 0.01f) { _lookYaw += val.x * num; _lookPitch = Mathf.Clamp(_lookPitch - val.y * num, -45f, 45f); if (_lookYaw > 180f) { _lookYaw -= 360f; } if (_lookYaw < -180f) { _lookYaw += 360f; } _lastMouseMove = Time.realtimeSinceStartup; } else if (Plugin.MouseRecenter.Value && Time.realtimeSinceStartup - _lastMouseMove > 2f) { float num2 = 120f * Time.deltaTime; _lookYaw = Mathf.MoveTowards(_lookYaw, 0f, num2); _lookPitch = Mathf.MoveTowards(_lookPitch, 0f, num2); } } private static void RescanDof() { //IL_00c0: 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_0168: 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) if (Time.unscaledTime < _nextDofScan) { return; } _nextDofScan = Time.unscaledTime + 1f; try { Volume[] array = Object.FindObjectsOfType(); DepthOfField val2 = default(DepthOfField); foreach (Volume val in array) { VolumeProfile profile = val.profile; if ((Object)(object)profile == (Object)null || !profile.TryGet(ref val2)) { continue; } bool flag = false; foreach (DofSnap dof in _dofs) { if ((Object)(object)dof.dof == (Object)(object)val2) { flag = true; break; } } if (!flag) { _dofs.Add(new DofSnap { dof = val2, active = ((VolumeComponent)val2).active, mode = ((VolumeParameter)(object)val2.mode).value, focusDistance = ((VolumeParameter)(object)val2.focusDistance).value, focusOverride = ((VolumeParameter)val2.focusDistance).overrideState, gStart = ((VolumeParameter)(object)val2.gaussianStart).value, gStartOverride = ((VolumeParameter)val2.gaussianStart).overrideState, gEnd = ((VolumeParameter)(object)val2.gaussianEnd).value, gEndOverride = ((VolumeParameter)val2.gaussianEnd).overrideState }); Plugin.Log.LogInfo((object)("CrewPOV: found depth-of-field on volume '" + ((Object)val).name + "' (mode=" + ((object)((VolumeParameter)(object)val2.mode).value/*cast due to .constrained prefix*/).ToString() + ").")); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("CrewPOV dof scan: " + ex.Message)); } } private static void MaintainDof() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Invalid comparison between Unknown and I4 RescanDof(); BlurMode value = Plugin.Blur.Value; if (value == BlurMode.Vanilla) { if (_dofTouched) { RestoreDof(); } return; } try { foreach (DofSnap dof2 in _dofs) { DepthOfField dof = dof2.dof; if ((Object)(object)dof == (Object)null) { continue; } if (value == BlurMode.Off) { ((VolumeComponent)dof).active = false; continue; } ((VolumeComponent)dof).active = true; float value2 = Plugin.FocusDistance.Value; if ((int)((VolumeParameter)(object)dof.mode).value == 1) { ((VolumeParameter)dof.gaussianStart).overrideState = true; ((VolumeParameter)(object)dof.gaussianStart).value = value2; ((VolumeParameter)dof.gaussianEnd).overrideState = true; ((VolumeParameter)(object)dof.gaussianEnd).value = value2 + 40f; } else { ((VolumeParameter)dof.focusDistance).overrideState = true; ((VolumeParameter)(object)dof.focusDistance).value = value2; } } _dofTouched = true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("CrewPOV dof apply: " + ex.Message)); } } private static void RestoreDof() { foreach (DofSnap dof in _dofs) { try { if (!((Object)(object)dof.dof == (Object)null)) { ((VolumeComponent)dof.dof).active = dof.active; ((VolumeParameter)dof.dof.focusDistance).overrideState = dof.focusOverride; ((VolumeParameter)(object)dof.dof.focusDistance).value = dof.focusDistance; ((VolumeParameter)dof.dof.gaussianStart).overrideState = dof.gStartOverride; ((VolumeParameter)(object)dof.dof.gaussianStart).value = dof.gStart; ((VolumeParameter)dof.dof.gaussianEnd).overrideState = dof.gEndOverride; ((VolumeParameter)(object)dof.dof.gaussianEnd).value = dof.gEnd; } } catch { } } if (_dofTouched) { Plugin.Log.LogInfo((object)"CrewPOV: depth-of-field restored (normal camera)."); } _dofTouched = false; _nextDofScan = 0f; } private static void HandleTuningKeys() { ConfigEntry val = ((_mode == 1) ? Plugin.ChaseHeight : Plugin.FpHeight); ConfigEntry val2 = ((_mode == 1) ? Plugin.ChaseForward : Plugin.FpForward); ConfigEntry val3 = ((_mode == 1) ? Plugin.ChasePitch : Plugin.FpPitch); bool flag = false; if (Input.GetKeyDown((KeyCode)280)) { val.Value += 0.1f; flag = true; } if (Input.GetKeyDown((KeyCode)281)) { val.Value -= 0.1f; flag = true; } if (Input.GetKeyDown((KeyCode)278)) { val2.Value += 0.1f; flag = true; } if (Input.GetKeyDown((KeyCode)279)) { val2.Value -= 0.1f; flag = true; } if (Input.GetKeyDown((KeyCode)57)) { val3.Value += 2f; flag = true; } if (Input.GetKeyDown((KeyCode)48)) { val3.Value -= 2f; flag = true; } if (Input.GetKeyDown((KeyCode)45)) { Plugin.FocusDistance.Value = Mathf.Max(0.5f, Plugin.FocusDistance.Value - 1f); flag = true; } if (Input.GetKeyDown((KeyCode)61)) { ConfigEntry focusDistance = Plugin.FocusDistance; focusDistance.Value += 1f; flag = true; } if (flag) { Plugin.Log.LogInfo((object)string.Format("CrewPOV tuning ({0}): Height={1:0.0} Forward={2:0.0} Pitch={3:0} FocusDistance={4:0}", (_mode == 1) ? "behind-head" : "first person", val.Value, val2.Value, val3.Value, Plugin.FocusDistance.Value)); } } } }