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<Canvas>();
obj.renderMode = (RenderMode)0;
obj.sortingOrder = 29500;
_go.AddComponent<CanvasScaler>().uiScaleMode = (ScaleMode)0;
GameObject val = new GameObject("Image");
val.transform.SetParent(_go.transform, false);
_raw = val.AddComponent<RawImage>();
_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<bool> Enabled;
internal static ConfigEntry<KeyCode> ToggleKey;
internal static ConfigEntry<bool> IncludeFirstPerson;
internal static ConfigEntry<float> ChaseHeight;
internal static ConfigEntry<float> ChaseForward;
internal static ConfigEntry<float> ChasePitch;
internal static ConfigEntry<float> FpHeight;
internal static ConfigEntry<float> FpForward;
internal static ConfigEntry<float> FpPitch;
internal static ConfigEntry<bool> MouseLook;
internal static ConfigEntry<float> MouseSensitivity;
internal static ConfigEntry<bool> MouseRecenter;
internal static ConfigEntry<string> PadToggleButton;
internal static ConfigEntry<string> PadRecenterButton;
internal static ConfigEntry<bool> PadLook;
internal static ConfigEntry<float> PadLookSensitivity;
internal static ConfigEntry<bool> PadInvertY;
internal static ConfigEntry<float> CamFollowSpeed;
internal static ConfigEntry<BlurMode> Blur;
internal static ConfigEntry<float> FocusDistance;
internal static ConfigEntry<bool> SteerRelative;
internal static ConfigEntry<SteerScheme> Scheme;
internal static ConfigEntry<float> SteerGain;
internal static ConfigEntry<bool> SuppressPhone;
internal static ConfigEntry<bool> TuningKeys;
internal static ConfigEntry<bool> ShowCredit;
internal static ConfigEntry<CreditCorner> CreditCornerCfg;
internal static ConfigEntry<float> 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<bool>("CrewPOV", "Enabled", true, "Master switch for the camera mod.");
ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("CrewPOV", "ToggleKey", (KeyCode)118, "Cycles the camera: normal -> behind-head -> first person -> normal.");
IncludeFirstPerson = ((BaseUnityPlugin)this).Config.Bind<bool>("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<float>("BehindHead", "Height", 2.7f, "Behind-head camera height (metres).");
ChaseForward = ((BaseUnityPlugin)this).Config.Bind<float>("BehindHead", "Forward", -3.5f, "Behind-head camera distance from the forklift center (negative = behind).");
ChasePitch = ((BaseUnityPlugin)this).Config.Bind<float>("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<float>("FirstPerson", "Height", 2f, "First-person camera height (metres).");
FpForward = ((BaseUnityPlugin)this).Config.Bind<float>("FirstPerson", "Forward", 0f, "First-person camera forward offset from the forklift center (metres).");
FpPitch = ((BaseUnityPlugin)this).Config.Bind<float>("FirstPerson", "Pitch", 8f, "First-person downward tilt (degrees). Higher = look closer in front of you.");
MouseLook = ((BaseUnityPlugin)this).Config.Bind<bool>("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<float>("MouseLook", "Sensitivity", 2f, "Mouse look sensitivity.");
MouseRecenter = ((BaseUnityPlugin)this).Config.Bind<bool>("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<string>("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<string>("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<bool>("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<float>("Controller", "StickSensitivity", 150f, "Right-stick look speed (degrees per second at full deflection).");
PadInvertY = ((BaseUnityPlugin)this).Config.Bind<bool>("Controller", "InvertY", false, "Invert the right stick's up/down for looking.");
CamFollowSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("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<BlurMode>("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<float>("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<bool>("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<SteerScheme>("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<float>("Driving", "SteerStrength", 1f, "RightStickSteer only: how hard a full right-stick deflection turns (higher = sharper turning).");
SuppressPhone = ((BaseUnityPlugin)this).Config.Bind<bool>("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<bool>("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<bool>("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<CreditCorner>("Credit", "Corner", CreditCorner.TopLeft, "Which screen corner the credit logo sits in.");
CreditWidth = ((BaseUnityPlugin)this).Config.Bind<float>("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<DofSnap> _dofs = new List<DofSnap>();
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<CodeInstruction> Steering_Transpiler(IEnumerable<CodeInstruction> instructions)
{
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Expected O, but got Unknown
List<CodeInstruction> list = new List<CodeInstruction>(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<CodeInstruction> TipTap_Transpiler(IEnumerable<CodeInstruction> instructions)
{
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: Expected O, but got Unknown
List<CodeInstruction> list = new List<CodeInstruction>(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<Vector2>)(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<Vector2>)(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<Vector2>)(object)current2.leftStick).ReadValue();
Vector2 val4 = ((InputControl<Vector2>)(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<Vector2>)(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<ButtonControl>(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<Vector2>)(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<Volume>();
DepthOfField val2 = default(DepthOfField);
foreach (Volume val in array)
{
VolumeProfile profile = val.profile;
if ((Object)(object)profile == (Object)null || !profile.TryGet<DepthOfField>(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<DepthOfFieldMode>)(object)val2.mode).value,
focusDistance = ((VolumeParameter<float>)(object)val2.focusDistance).value,
focusOverride = ((VolumeParameter)val2.focusDistance).overrideState,
gStart = ((VolumeParameter<float>)(object)val2.gaussianStart).value,
gStartOverride = ((VolumeParameter)val2.gaussianStart).overrideState,
gEnd = ((VolumeParameter<float>)(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<DepthOfFieldMode>)(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<DepthOfFieldMode>)(object)dof.mode).value == 1)
{
((VolumeParameter)dof.gaussianStart).overrideState = true;
((VolumeParameter<float>)(object)dof.gaussianStart).value = value2;
((VolumeParameter)dof.gaussianEnd).overrideState = true;
((VolumeParameter<float>)(object)dof.gaussianEnd).value = value2 + 40f;
}
else
{
((VolumeParameter)dof.focusDistance).overrideState = true;
((VolumeParameter<float>)(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<float>)(object)dof.dof.focusDistance).value = dof.focusDistance;
((VolumeParameter)dof.dof.gaussianStart).overrideState = dof.gStartOverride;
((VolumeParameter<float>)(object)dof.dof.gaussianStart).value = dof.gStart;
((VolumeParameter)dof.dof.gaussianEnd).overrideState = dof.gEndOverride;
((VolumeParameter<float>)(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<float> val = ((_mode == 1) ? Plugin.ChaseHeight : Plugin.FpHeight);
ConfigEntry<float> val2 = ((_mode == 1) ? Plugin.ChaseForward : Plugin.FpForward);
ConfigEntry<float> 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<float> 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));
}
}
}
}