using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using CinematicCamera.Patches; using GameNetcodeStuff; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("CinematicCamera")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("CinematicCamera")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("a1037d4d-b8aa-4e06-a09e-fdfccf82e77d")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] namespace CinematicCamera { [BepInPlugin("sysfab.cinematiccamera", "Cinematic Camera", "1.0.0")] public class CinematicCameraBase : BaseUnityPlugin { private const string modGUID = "sysfab.cinematiccamera"; private const string modName = "Cinematic Camera"; private const string modVersion = "1.0.0"; private readonly Harmony harmony = new Harmony("sysfab.cinematiccamera"); public static CinematicCameraBase Instance; internal ManualLogSource Log; internal static ConfigEntry PositionEffects; internal static ConfigEntry RotationEffects; internal static ConfigEntry HealthCondition; internal static ConfigEntry HealthConditionTriggerLimit; internal static ConfigEntry HealthConditionSmoothing; internal static ConfigEntry EnableMouseFactor; internal static ConfigEntry MouseFactorSmoothness; internal static ConfigEntry MouseFactorXMultiplier; internal static ConfigEntry MouseFactorYMultiplier; internal static ConfigEntry MouseFactorZMultiplier; internal static ConfigEntry EnableFallingFactor; internal static ConfigEntry FallingFactorSmoothness; internal static ConfigEntry FallingFactorMultiplier; internal static ConfigEntry EnableMoveFactor; internal static ConfigEntry MoveFactorSmoothness; internal static ConfigEntry MoveFactorStrafeMultiplier; internal static ConfigEntry MoveFactorForwardMultiplier; internal static ConfigEntry MoveFactorBackwardMultiplier; internal static ConfigEntry EnableFallShake; internal static ConfigEntry FallShakeMultiplier; internal static ConfigEntry FallShakeMinVelocity; internal static ConfigEntry FallShakeMaxVelocity; private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; } Log = Logger.CreateLogSource("sysfab.cinematiccamera"); Log.LogInfo((object)"Loading config entries..."); PositionEffects = ((BaseUnityPlugin)this).Config.Bind("Effects", "Position Effects", true, "Mod will change camera's position if enabled"); RotationEffects = ((BaseUnityPlugin)this).Config.Bind("Effects", "Rotation Effects", true, "Mod will change camera's rotation if enabled"); HealthCondition = ((BaseUnityPlugin)this).Config.Bind("Health Condition", "Enabled", false, "Mod will work if health condition (or others) is met"); HealthConditionTriggerLimit = ((BaseUnityPlugin)this).Config.Bind("Health Condition", "Trigger limit", 20, "If health is <= trigger value then mod will start to work"); HealthConditionSmoothing = ((BaseUnityPlugin)this).Config.Bind("Health Condition", "Smoothing", false, "If health is close to trigger value then effect will be small"); EnableMouseFactor = ((BaseUnityPlugin)this).Config.Bind("Mouse Factor", "Enabled", true, "Moving mouse will affect camera"); MouseFactorSmoothness = ((BaseUnityPlugin)this).Config.Bind("Mouse Factor", "Smoothness", 1f, "Smoothness of mouse factor, Default: 1. Values from 0.5 to 2 recommended"); MouseFactorXMultiplier = ((BaseUnityPlugin)this).Config.Bind("Mouse Factor", "X Multiplier", 1f, "X axis multiplier, Default: 1"); MouseFactorYMultiplier = ((BaseUnityPlugin)this).Config.Bind("Mouse Factor", "Y Multiplier", 1f, "Y axis multiplier, Default: 1"); MouseFactorZMultiplier = ((BaseUnityPlugin)this).Config.Bind("Mouse Factor", "Z Multiplier", 1f, "Z axis multiplier, Default: 1"); EnableFallingFactor = ((BaseUnityPlugin)this).Config.Bind("Falling Factor", "Enabled", true, "Falling will affect camera"); FallingFactorSmoothness = ((BaseUnityPlugin)this).Config.Bind("Falling Factor", "Smoothness", 1f, "Smoothness of falling factor, Default: 1. Values from 0.5 to 2 recommended"); FallingFactorMultiplier = ((BaseUnityPlugin)this).Config.Bind("Falling Factor", "Multiplier", 1f, "Falling effect multiplier, Default: 1"); EnableMoveFactor = ((BaseUnityPlugin)this).Config.Bind("Move Factor", "Enabled", true, "Moving will affect camera"); MoveFactorSmoothness = ((BaseUnityPlugin)this).Config.Bind("Move Factor", "Smoothness", 1f, "Smoothness of move factor, Default: 1. Values from 0.5 to 2 recommended"); MoveFactorStrafeMultiplier = ((BaseUnityPlugin)this).Config.Bind("Move Factor", "Strafe Multiplier", 1f, "Strafe multiplier, Default: 1"); MoveFactorForwardMultiplier = ((BaseUnityPlugin)this).Config.Bind("Move Factor", "Forward Multiplier", 1f, "Forward multiplier, Default: 1"); MoveFactorBackwardMultiplier = ((BaseUnityPlugin)this).Config.Bind("Move Factor", "Backward Multiplier", 1f, "Backward multiplier, Default: 1"); EnableFallShake = ((BaseUnityPlugin)this).Config.Bind("Fall Shake", "Enabled", true, "Falling will shake camera"); FallShakeMultiplier = ((BaseUnityPlugin)this).Config.Bind("Fall Shake", "Multiplier", 1f, "Falling shake multiplier, Default: 1"); FallShakeMinVelocity = ((BaseUnityPlugin)this).Config.Bind("Fall Shake", "Min Velocity", 15f, "Minimum velocity to shake camera, Default: 15"); FallShakeMaxVelocity = ((BaseUnityPlugin)this).Config.Bind("Fall Shake", "Max Velocity", 500f, "Maximum velocity to shake camera, Default: 500"); Log.LogInfo((object)"Config entries loaded!"); Log.LogInfo((object)"Cinematic Camera is loaded!"); harmony.PatchAll(typeof(CinematicCameraBase)); harmony.PatchAll(typeof(CameraPatch)); } } } namespace CinematicCamera.Patches { [HarmonyPatch(typeof(PlayerControllerB))] internal class CameraPatch { internal static ConfigEntry PositionEffects = CinematicCameraBase.PositionEffects; internal static ConfigEntry RotationEffects = CinematicCameraBase.RotationEffects; internal static ConfigEntry HealthCondition = CinematicCameraBase.HealthCondition; internal static ConfigEntry HealthConditionTriggerLimit = CinematicCameraBase.HealthConditionTriggerLimit; internal static ConfigEntry HealthConditionSmoothing = CinematicCameraBase.HealthConditionSmoothing; internal static ConfigEntry EnableMouseFactor = CinematicCameraBase.EnableMouseFactor; internal static ConfigEntry MouseFactorSmoothness = CinematicCameraBase.MouseFactorSmoothness; internal static ConfigEntry MouseFactorXMultiplier = CinematicCameraBase.MouseFactorXMultiplier; internal static ConfigEntry MouseFactorYMultiplier = CinematicCameraBase.MouseFactorYMultiplier; internal static ConfigEntry MouseFactorZMultiplier = CinematicCameraBase.MouseFactorZMultiplier; internal static ConfigEntry EnableFallingFactor = CinematicCameraBase.EnableFallingFactor; internal static ConfigEntry FallingFactorSmoothness = CinematicCameraBase.FallingFactorSmoothness; internal static ConfigEntry FallingFactorMultiplier = CinematicCameraBase.FallingFactorMultiplier; internal static ConfigEntry EnableMoveFactor = CinematicCameraBase.EnableMoveFactor; internal static ConfigEntry MoveFactorSmoothness = CinematicCameraBase.MoveFactorSmoothness; internal static ConfigEntry MoveFactorStrafeMultiplier = CinematicCameraBase.MoveFactorStrafeMultiplier; internal static ConfigEntry MoveFactorForwardMultiplier = CinematicCameraBase.MoveFactorForwardMultiplier; internal static ConfigEntry MoveFactorBackwardMultiplier = CinematicCameraBase.MoveFactorBackwardMultiplier; internal static ConfigEntry EnableFallShake = CinematicCameraBase.EnableFallShake; internal static ConfigEntry FallShakeMultiplier = CinematicCameraBase.FallShakeMultiplier; internal static ConfigEntry FallShakeMinVelocity = CinematicCameraBase.FallShakeMinVelocity; internal static ConfigEntry FallShakeMaxVelocity = CinematicCameraBase.FallShakeMaxVelocity; private static PlayerControllerB Instance; private static Vector3 SavedCameraPosition = Vector3.zero; private static Quaternion SavedCameraRotation = Quaternion.identity; private static int inVehicleTicks = 0; private static bool isInVehicle = false; private static Vector3 prevLookVector = Vector3.zero; private static Vector3 lastLookVector = Vector3.zero; private static Vector3 prevVelocity = Vector3.zero; private static Vector3 lastVelocity = Vector3.zero; private static Vector2 prevMove = Vector2.zero; private static Vector2 lastMove = Vector2.zero; private static float fallShakeAmount = 0f; private static float fallShakeSmooth = 0f; private static Vector3 smoothLookVector = Vector3.zero; private static Vector3 smoothVelocity = Vector3.zero; private static Vector2 smoothMove = Vector2.zero; private static float Ticks = 0f; internal static CinematicCameraBase CinematicCamera => CinematicCameraBase.Instance; internal static ManualLogSource Log => CinematicCamera.Log; private static void SaveCameraState() { //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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) SavedCameraPosition = ((Component)Instance.cameraContainerTransform).transform.position; SavedCameraRotation = ((Component)Instance.cameraContainerTransform).transform.localRotation; } private static void RestoreCameraState() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) if (SavedCameraPosition == Vector3.zero && SavedCameraRotation == Quaternion.identity) { Log.LogWarning((object)"RestoreCameraState | Camera state is not saved yet. Skipping restoration."); return; } if ((Object)(object)Instance == (Object)null) { Log.LogError((object)"RestoreCameraState | Instance is null!"); return; } if ((Object)(object)Instance.cameraContainerTransform == (Object)null) { Log.LogError((object)"RestoreCameraState | cameraContainerTransform is null!"); return; } if ((Object)(object)Instance.gameplayCamera == (Object)null) { Log.LogError((object)"RestoreCameraState | gameplayCamera is null!"); return; } if (PositionEffects != null && PositionEffects.Value) { ((Component)Instance.cameraContainerTransform).transform.position = SavedCameraPosition; } if (RotationEffects != null && RotationEffects.Value) { ((Component)Instance.cameraContainerTransform).transform.localRotation = SavedCameraRotation; } } [HarmonyPatch(typeof(PlayerControllerB), "Awake")] [HarmonyPrefix] private static void Awake(ref PlayerControllerB __instance) { Instance = __instance; Log.LogInfo((object)"CameraPatch Awake called"); ((Renderer)GameObject.Find("Systems/Rendering/PlayerHUDHelmetModel/ScavengerHelmet").GetComponent()).enabled = false; } [HarmonyPrefix] [HarmonyPatch("Update")] private static void Update(ref PlayerControllerB __instance) { if ((Object)(object)Instance == (Object)null) { Log.LogWarning((object)"Instance is null in Update"); Instance = __instance; } else { Ticks += Time.deltaTime; RestoreCameraState(); } } [HarmonyPostfix] [HarmonyPatch("LateUpdate")] private static void LateUpdate(ref PlayerControllerB __instance, ref bool ___inTerminalMenu, ref QuickMenuManager ___quickMenuManager, ref bool ___isTypingChat, ref bool ___disableMoveInput, ref bool ___inSpecialInteractAnimation, ref bool ___isClimbingLadder, ref bool ___inShockingMinigame, ref bool ___inVehicleAnimation, ref int ___health) { //IL_0005: 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_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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: 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_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0239: 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_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_03fd: Unknown result type (might be due to invalid IL or missing references) //IL_0402: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Unknown result type (might be due to invalid IL or missing references) //IL_0422: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: 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_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_049e: Unknown result type (might be due to invalid IL or missing references) //IL_04a4: Unknown result type (might be due to invalid IL or missing references) //IL_04ab: Unknown result type (might be due to invalid IL or missing references) //IL_04b6: Unknown result type (might be due to invalid IL or missing references) //IL_04bc: Unknown result type (might be due to invalid IL or missing references) //IL_04c3: Unknown result type (might be due to invalid IL or missing references) SaveCameraState(); prevLookVector = lastLookVector; MovementActions movement = __instance.playerActions.Movement; lastLookVector = Vector2.op_Implicit(((MovementActions)(ref movement)).Look.ReadValue()); prevVelocity = lastVelocity; lastVelocity = __instance.thisController.velocity; prevMove = lastMove; lastMove = IngamePlayerSettings.Instance.playerInput.actions.FindAction("Move", false).ReadValue(); if (___inVehicleAnimation) { inVehicleTicks = 10; } else { inVehicleTicks--; } if (inVehicleTicks > 0) { isInVehicle = true; } else { isInVehicle = false; } if (___inTerminalMenu | ___quickMenuManager.isMenuOpen | ___isTypingChat | ___disableMoveInput | ___inSpecialInteractAnimation | ___isClimbingLadder | ___inShockingMinigame | isInVehicle) { return; } Transform cameraContainerTransform = __instance.cameraContainerTransform; if (EnableMouseFactor.Value) { if (MouseFactorSmoothness.Value > 0f) { smoothLookVector = Vector3.Lerp(smoothLookVector, lastLookVector, Time.deltaTime * 1.4f / MouseFactorSmoothness.Value); } else { smoothLookVector = lastLookVector; } cameraContainerTransform.localRotation *= Quaternion.Euler((0f - smoothLookVector.y) * 0.014f * MouseFactorXMultiplier.Value, smoothLookVector.x * 0.01f * MouseFactorYMultiplier.Value, smoothLookVector.x * 0.018f * MouseFactorZMultiplier.Value); } if (EnableFallingFactor.Value) { if (FallingFactorSmoothness.Value > 0f) { smoothVelocity = Vector3.Lerp(smoothVelocity, lastVelocity, Time.deltaTime * 2.8f / FallingFactorSmoothness.Value); } else { smoothVelocity = lastVelocity; } cameraContainerTransform.localRotation *= Quaternion.Euler(smoothVelocity.y, 0f, 0f); } if (EnableMoveFactor.Value) { if (MoveFactorSmoothness.Value > 0f) { smoothMove = Vector2.Lerp(smoothMove, lastMove, Time.deltaTime * 1.4f / MoveFactorSmoothness.Value); } else { smoothMove = lastMove; } if (Math.Abs(smoothMove.x) > 0.1f) { cameraContainerTransform.localRotation *= Quaternion.Euler(0f, 0f, (0f - smoothMove.x) * MoveFactorStrafeMultiplier.Value); } if (smoothMove.y > 0.1f) { cameraContainerTransform.localRotation *= Quaternion.Euler(smoothMove.y * 0.8f * MoveFactorForwardMultiplier.Value, 0f, 0f); } else if (smoothMove.y < -0.1f) { cameraContainerTransform.localRotation *= Quaternion.Euler(smoothMove.y * 0.8f * MoveFactorBackwardMultiplier.Value, 0f, 0f); } } if (EnableFallShake.Value) { float num = lastVelocity.y - prevVelocity.y; if ((num > FallShakeMinVelocity.Value) & (lastVelocity.y < 0.1f) & (lastVelocity.y > -0.1f)) { fallShakeSmooth = (fallShakeAmount = Mathf.Clamp(Mathf.InverseLerp(FallShakeMinVelocity.Value, FallShakeMaxVelocity.Value, num), 0f, 1f)); } fallShakeSmooth = Mathf.Lerp(fallShakeSmooth, 0f, Time.deltaTime * 1f); cameraContainerTransform.localPosition += Random.insideUnitSphere * (fallShakeSmooth * 0.2f * FallShakeMultiplier.Value); } if (HealthCondition.Value) { float num2 = (HealthConditionSmoothing.Value ? ((___health > HealthConditionTriggerLimit.Value) ? 0f : (1f - (float)(___health / HealthConditionTriggerLimit.Value))) : ((___health > HealthConditionTriggerLimit.Value) ? 0f : 1f)); float num3 = num2; if (num3 > 0f) { cameraContainerTransform.localPosition = Vector3.Lerp(SavedCameraPosition, cameraContainerTransform.localPosition, num3); cameraContainerTransform.localRotation = Quaternion.Slerp(SavedCameraRotation, cameraContainerTransform.localRotation, num3); } else { RestoreCameraState(); } } } } }