Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Unfaded v1.0.8
Unfaded.dll
Decompiled 2 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using Unfaded.Configuration; using Unfaded.Core; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("Unfaded")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.8.0")] [assembly: AssemblyInformationalVersion("1.0.8+7e46e9bf7956adb6ebdb15af98c735f0a1f80358")] [assembly: AssemblyProduct("Unfaded")] [assembly: AssemblyTitle("Unfaded")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.8.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 Unfaded { [BepInPlugin("djc.valheim.unfaded", "Unfaded", "1.0.8")] public sealed class UnfadedPlugin : BaseUnityPlugin { public const string PluginGUID = "djc.valheim.unfaded"; public const string PluginName = "Unfaded"; public const string PluginVersion = "1.0.8"; private Harmony? _harmony; public static UnfadedPlugin? Instance { get; private set; } private void Awake() { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) Instance = this; PluginConfig.BindConfig(((BaseUnityPlugin)this).Config); _harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "djc.valheim.unfaded"); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} v{1} loaded successfully. Blackout: {2}, Respawn: {3}s ([{4}]), KillerCam: {5}, FreeFly: {6}, SlowMo: {7}, RecordHotkey: {8}.", "Unfaded", "1.0.8", PluginConfig.DisableDeathFade.Value ? "Disabled" : "Enabled", PluginConfig.RespawnDelay.Value, PluginConfig.ManualRespawnKey.Value, PluginConfig.EnableKillerCam.Value, PluginConfig.EnableFreeFly.Value, PluginConfig.EnableSlowMotion.Value, PluginConfig.RecordHotkey?.Value)); } private void Update() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (PluginConfig.EnableRecordingHotkey == null || !PluginConfig.EnableRecordingHotkey.Value || PluginConfig.RecordHotkey == null || !Input.GetKeyDown(PluginConfig.RecordHotkey.Value)) { return; } if (RecordingManager.IsRecording) { RecordingManager.StopRecording(out string message); ((BaseUnityPlugin)this).Logger.LogInfo((object)message); if ((Object)(object)Console.instance != (Object)null) { ((Terminal)Console.instance).AddString(message); } } else { RecordingManager.StartRecording(out string message2); ((BaseUnityPlugin)this).Logger.LogInfo((object)message2); if ((Object)(object)Console.instance != (Object)null) { ((Terminal)Console.instance).AddString(message2); } } } private void OnDestroy() { Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } Instance = null; } } } namespace Unfaded.Patches { [HarmonyPatch(typeof(GameCamera))] public static class GameCameraDeathPatch { private static bool s_wasDead = false; private static float s_orbitYaw = 0f; private static float s_orbitPitch = 25f; [HarmonyPostfix] [HarmonyPatch("UpdateCamera")] public static void UpdateCameraPostfix(GameCamera __instance, float dt) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_0183: 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_018f: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: 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_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0232: 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_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0114: 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_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: 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_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: 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_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: 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) //IL_00e6: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_024b: 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_0269: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; bool flag = (Object)(object)localPlayer != (Object)null && ((Character)localPlayer).IsDead(); bool flag2 = DeathStateManager.IsTestSimActive && Time.time < DeathStateManager.TestSimEndTime; if (!flag && !flag2) { if (s_wasDead) { DeathStateManager.ResetOnRespawn(); s_wasDead = false; } } else { if (!PluginConfig.IsModEnabled.Value) { return; } HandleModeSwitchKeys(); if (DeathStateManager.CurrentMode == DeathCameraMode.FreeFly && PluginConfig.EnableFreeFly.Value) { UpdateFreeFlyMode(__instance, dt); return; } Vector3 val = Vector3.zero; if (DeathStateManager.CurrentMode == DeathCameraMode.KillerFocus && PluginConfig.EnableKillerCam.Value) { if ((Object)(object)DeathStateManager.LastKiller != (Object)null && (Object)(object)((Component)DeathStateManager.LastKiller).gameObject != (Object)null) { val = DeathStateManager.LastKiller.GetCenterPoint(); } else { DeathStateManager.CurrentMode = DeathCameraMode.RagdollOrbit; } } if (DeathStateManager.CurrentMode == DeathCameraMode.RagdollOrbit) { if (flag) { Ragdoll ragdoll = localPlayer.GetRagdoll(); val = ((!((Object)(object)ragdoll != (Object)null)) ? (((Component)localPlayer).transform.position + Vector3.up * 1.5f) : ragdoll.GetAverageBodyPosition()); } else if (flag2) { val = ((Component)localPlayer).transform.position + Vector3.up * 1.5f; } } if (PluginConfig.EnableCameraOrbit.Value) { if (!s_wasDead) { s_wasDead = true; s_orbitYaw = ((Component)__instance).transform.eulerAngles.y; s_orbitPitch = Mathf.Clamp(((Component)__instance).transform.eulerAngles.x, 5f, 75f); } Vector2 mouseDelta = ZInput.GetMouseDelta(); s_orbitYaw += mouseDelta.x * PluginConfig.CameraOrbitSensitivity.Value; s_orbitPitch -= mouseDelta.y * PluginConfig.CameraOrbitSensitivity.Value; s_orbitPitch = Mathf.Clamp(s_orbitPitch, -10f, 85f); Vector3 val2 = -(Quaternion.Euler(s_orbitPitch, s_orbitYaw, 0f) * Vector3.forward); float num = Mathf.Clamp(__instance.m_distance, __instance.m_minDistance, __instance.m_maxDistance); Vector3 position = val + val2 * num; RaycastHit val3 = default(RaycastHit); if (Physics.SphereCast(val, 0.25f, val2, ref val3, num, LayerMask.op_Implicit(__instance.m_blockCameraMask))) { position = val + val2 * Mathf.Max(0.5f, ((RaycastHit)(ref val3)).distance - 0.15f); } ((Component)__instance).transform.position = position; ((Component)__instance).transform.LookAt(val); } else { ((Component)__instance).transform.LookAt(val); } } } private static void HandleModeSwitchKeys() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) if (PluginConfig.EnableFreeFly.Value && Input.GetKeyDown(PluginConfig.FreeFlyKey.Value)) { if (DeathStateManager.CurrentMode == DeathCameraMode.FreeFly) { DeathStateManager.CurrentMode = DeathCameraMode.RagdollOrbit; Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, "Spectator: Ragdoll Orbit", 0, (Sprite)null, false); } } else { DeathStateManager.CurrentMode = DeathCameraMode.FreeFly; Player localPlayer2 = Player.m_localPlayer; if (localPlayer2 != null) { ((Character)localPlayer2).Message((MessageType)1, "Spectator: Free-Fly Drone (WASD to Move)", 0, (Sprite)null, false); } } } if (!PluginConfig.EnableKillerCam.Value || !Input.GetKeyDown(PluginConfig.KillerCamKey.Value)) { return; } if (DeathStateManager.CurrentMode == DeathCameraMode.KillerFocus) { DeathStateManager.CurrentMode = DeathCameraMode.RagdollOrbit; Player localPlayer3 = Player.m_localPlayer; if (localPlayer3 != null) { ((Character)localPlayer3).Message((MessageType)1, "Spectator: Ragdoll Orbit", 0, (Sprite)null, false); } } else if ((Object)(object)DeathStateManager.LastKiller != (Object)null) { DeathStateManager.CurrentMode = DeathCameraMode.KillerFocus; Player localPlayer4 = Player.m_localPlayer; if (localPlayer4 != null) { ((Character)localPlayer4).Message((MessageType)1, "Spectator: Killer Focus (" + DeathStateManager.LastKillerName + ")", 0, (Sprite)null, false); } } else { Player localPlayer5 = Player.m_localPlayer; if (localPlayer5 != null) { ((Character)localPlayer5).Message((MessageType)1, "No enemy killer to spectate (environmental death)", 0, (Sprite)null, false); } } } private static void UpdateFreeFlyMode(GameCamera cam, float dt) { //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_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: 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_00b1: 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_00b8: 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_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: 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_012f: 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_0137: 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_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0166: 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) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) Vector2 mouseDelta = ZInput.GetMouseDelta(); DeathStateManager.FreeFlyYaw += mouseDelta.x * PluginConfig.CameraOrbitSensitivity.Value; DeathStateManager.FreeFlyPitch -= mouseDelta.y * PluginConfig.CameraOrbitSensitivity.Value; DeathStateManager.FreeFlyPitch = Mathf.Clamp(DeathStateManager.FreeFlyPitch, -85f, 85f); Quaternion val = Quaternion.Euler(DeathStateManager.FreeFlyPitch, DeathStateManager.FreeFlyYaw, 0f); Vector3 val2 = Vector3.zero; if (Input.GetKey((KeyCode)119)) { val2 += val * Vector3.forward; } if (Input.GetKey((KeyCode)115)) { val2 -= val * Vector3.forward; } if (Input.GetKey((KeyCode)100)) { val2 += val * Vector3.right; } if (Input.GetKey((KeyCode)97)) { val2 -= val * Vector3.right; } if (Input.GetKey((KeyCode)32)) { val2 += Vector3.up; } if (Input.GetKey((KeyCode)306)) { val2 -= Vector3.up; } float num = PluginConfig.FreeFlySpeed.Value; if (Input.GetKey((KeyCode)304)) { num *= 2f; } Vector3 val3 = DeathStateManager.FreeFlyPosition + val2 * num * dt; Vector3 deathPosition = DeathStateManager.DeathPosition; if (deathPosition != Vector3.zero) { float value = PluginConfig.FreeFlyRadius.Value; Vector3 val4 = val3 - deathPosition; if (((Vector3)(ref val4)).magnitude > value) { val3 = deathPosition + ((Vector3)(ref val4)).normalized * value; } } DeathStateManager.FreeFlyPosition = val3; ((Component)cam).transform.position = val3; ((Component)cam).transform.rotation = val; } } public static class GameRespawnPatch { [HarmonyPatch(typeof(Game), "RequestRespawn")] public static class RequestRespawnPatch { [HarmonyPrefix] public static void Prefix(ref float delay, bool afterDeath) { if (PluginConfig.IsModEnabled.Value && afterDeath && delay > 0f) { delay = Mathf.Max(0f, PluginConfig.RespawnDelay.Value); } } } [HarmonyPatch(typeof(Hud), "Update")] public static class HudUpdateInputPatch { private static float s_lastPromptTime; [HarmonyPostfix] public static void Postfix(Hud __instance) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) if (!PluginConfig.IsModEnabled.Value) { return; } Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && ((Character)localPlayer).IsDead() && !((Object)(object)Game.instance == (Object)null) && !Game.instance.WaitingForRespawn() && !Game.instance.IsShuttingDown()) { if (PluginConfig.ShowRespawnPrompt.Value && Time.time - s_lastPromptTime > 4.5f) { s_lastPromptTime = Time.time; string arg = ((object)PluginConfig.ManualRespawnKey.Value/*cast due to .constrained prefix*/).ToString(); string text = string.Format(PluginConfig.RespawnPromptText.Value, arg); ((Character)localPlayer).Message((MessageType)1, text, 0, (Sprite)null, false); } if (PluginConfig.EnableManualRespawn.Value && Input.GetKeyDown(PluginConfig.ManualRespawnKey.Value)) { DeathStateManager.ResetOnRespawn(); Game.instance.RequestRespawn(0f, true); } } } } [HarmonyPatch(typeof(Player), "OnDeath")] public static class PlayerOnDeathPatch { [HarmonyPostfix] public static void Postfix(Player __instance) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if (PluginConfig.IsModEnabled.Value && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { DeathStateManager.RecordLethalHit(__instance, ((Character)__instance).m_lastHit); if (PluginConfig.EnableSlowMotion.Value && (Object)(object)UnfadedPlugin.Instance != (Object)null) { ((MonoBehaviour)UnfadedPlugin.Instance).StartCoroutine(DeathStateManager.SlowMotionRoutine((MonoBehaviour)(object)UnfadedPlugin.Instance)); } if (PluginConfig.EnableDeathRecap.Value) { string text = DeathStateManager.FormatDeathRecap(); ((Character)__instance).Message((MessageType)2, text, 0, (Sprite)null, false); } if (PluginConfig.ShowRespawnPrompt.Value) { string arg = ((object)PluginConfig.ManualRespawnKey.Value/*cast due to .constrained prefix*/).ToString(); string text2 = string.Format(PluginConfig.RespawnPromptText.Value, arg); ((Character)__instance).Message((MessageType)1, text2, 0, (Sprite)null, false); } } } } } [HarmonyPatch(typeof(Hud))] public static class HudBlackScreenPatch { [HarmonyPrefix] [HarmonyPatch("UpdateBlackScreen")] public static bool UpdateBlackScreenPrefix(Hud __instance, Player player, float dt) { if (!PluginConfig.IsModEnabled.Value || !PluginConfig.DisableDeathFade.Value) { return true; } if ((Object)(object)player != (Object)null && ((Character)player).IsDead() && ((Object)(object)Game.instance == (Object)null || !Game.instance.WaitingForRespawn())) { if ((Object)(object)Game.instance != (Object)null && Game.instance.IsShuttingDown()) { return true; } if (player.IsSleeping() || ((Character)player).IsTeleporting()) { return true; } if ((Object)(object)__instance.m_loadingScreen != (Object)null) { __instance.m_loadingScreen.alpha = 0f; ((Component)__instance.m_loadingScreen).gameObject.SetActive(false); } if ((Object)(object)__instance.m_loadingProgress != (Object)null) { __instance.m_loadingProgress.SetActive(false); } if ((Object)(object)__instance.m_sleepingProgress != (Object)null) { __instance.m_sleepingProgress.SetActive(false); } if ((Object)(object)__instance.m_teleportingProgress != (Object)null) { __instance.m_teleportingProgress.SetActive(false); } return false; } return true; } [HarmonyPrefix] [HarmonyPatch("GetFadeDuration")] public static bool GetFadeDurationPrefix(Player player, ref float __result) { if (!PluginConfig.IsModEnabled.Value || (Object)(object)player == (Object)null || !((Character)player).IsDead()) { return true; } if (PluginConfig.DisableDeathFade.Value) { __result = 999999f; return false; } if (PluginConfig.CustomDeathFadeDuration.Value > 0f) { __result = Mathf.Max(0.01f, PluginConfig.CustomDeathFadeDuration.Value); return false; } return true; } } } namespace Unfaded.Core { public enum DeathCameraMode { RagdollOrbit, KillerFocus, FreeFly } public static class DeathStateManager { public static DeathCameraMode CurrentMode { get; set; } = DeathCameraMode.RagdollOrbit; public static Character? LastKiller { get; set; } public static string LastKillerName { get; set; } = ""; public static int LastKillerStars { get; set; } = 0; public static float LastLethalDamage { get; set; } = 0f; public static string LastDamageType { get; set; } = ""; public static Vector3 DeathPosition { get; set; } = Vector3.zero; public static Vector3 FreeFlyPosition { get; set; } = Vector3.zero; public static float FreeFlyYaw { get; set; } = 0f; public static float FreeFlyPitch { get; set; } = 20f; public static bool IsTestSimActive { get; set; } = false; public static float TestSimEndTime { get; set; } = 0f; public static void RecordLethalHit(Player player, HitData hit) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Invalid comparison between Unknown and I4 //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Invalid comparison between Unknown and I4 //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Invalid comparison between Unknown and I4 //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Invalid comparison between Unknown and I4 //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Invalid comparison between Unknown and I4 CurrentMode = DeathCameraMode.RagdollOrbit; DeathPosition = ((Component)player).transform.position; FreeFlyPosition = ((Component)player).transform.position + Vector3.up * 3f - ((Component)player).transform.forward * 4f; FreeFlyYaw = ((Component)player).transform.eulerAngles.y; FreeFlyPitch = 25f; LastLethalDamage = hit.GetTotalDamage(); Character attacker = hit.GetAttacker(); if ((Object)(object)attacker != (Object)null) { LastKiller = attacker; LastKillerName = attacker.GetHoverName(); if (string.IsNullOrEmpty(LastKillerName)) { LastKillerName = attacker.m_name; } LastKillerStars = attacker.GetLevel() - 1; } else { LastKiller = null; LastKillerStars = 0; HitType hitType = hit.m_hitType; if ((int)hitType <= 8) { if ((int)hitType != 3) { if ((int)hitType != 8) { goto IL_0122; } LastKillerName = "Drowning / Water"; } else { LastKillerName = "Gravity / Fall Damage"; } } else if ((int)hitType != 9) { if ((int)hitType != 13) { goto IL_0122; } LastKillerName = "Falling Tree / Timber"; } else { LastKillerName = "Smoke Inhalation"; } } goto IL_012c; IL_0122: LastKillerName = "The Harsh Environment"; goto IL_012c; IL_012c: if (hit.m_damage.m_fire > 0f) { LastDamageType = "Fire"; } else if (hit.m_damage.m_frost > 0f) { LastDamageType = "Frost"; } else if (hit.m_damage.m_lightning > 0f) { LastDamageType = "Lightning"; } else if (hit.m_damage.m_poison > 0f) { LastDamageType = "Poison"; } else if (hit.m_damage.m_spirit > 0f) { LastDamageType = "Spirit"; } else if (hit.m_damage.m_slash > 0f) { LastDamageType = "Slash"; } else if (hit.m_damage.m_pierce > 0f) { LastDamageType = "Pierce"; } else if (hit.m_damage.m_blunt > 0f) { LastDamageType = "Blunt"; } else { LastDamageType = "Physical"; } } public static string FormatDeathRecap() { string text = ((LastKillerStars > 0) ? $" ({LastKillerStars}★)" : ""); string text2 = ((LastLethalDamage > 0f) ? $" [{LastLethalDamage:F0} {LastDamageType}]" : ""); return "\ud83d\udc80 Slain by: <color=#FF6B6B><b>" + LastKillerName + text + "</b></color>" + text2; } public static IEnumerator SlowMotionRoutine(MonoBehaviour runner) { if (!((Object)(object)ZNet.instance != (Object)null) || ZNet.instance.IsServer() || ZNet.instance.GetNrOfPlayers() <= 1) { float targetScale = Mathf.Clamp(PluginConfig.SlowMotionScale.Value, 0.05f, 1f); float duration = Mathf.Max(0.1f, PluginConfig.SlowMotionDuration.Value); Time.timeScale = targetScale; Time.fixedDeltaTime = 0.02f * targetScale; float elapsed = 0f; while (elapsed < duration) { elapsed += Time.unscaledDeltaTime; yield return null; } float restoreDuration = 0.5f; float restoreElapsed = 0f; while (restoreElapsed < restoreDuration) { restoreElapsed += Time.unscaledDeltaTime; float num = restoreElapsed / restoreDuration; Time.timeScale = Mathf.Lerp(targetScale, 1f, num); Time.fixedDeltaTime = 0.02f * Time.timeScale; yield return null; } Time.timeScale = 1f; Time.fixedDeltaTime = 0.02f; } } public static void ResetOnRespawn() { Time.timeScale = 1f; Time.fixedDeltaTime = 0.02f; CurrentMode = DeathCameraMode.RagdollOrbit; LastKiller = null; IsTestSimActive = false; } } public static class RecordingManager { private const byte VK_LWIN = 91; private const byte VK_LMENU = 18; private const byte VK_R = 82; private const uint KEYEVENTF_KEYUP = 2u; public static bool IsRecording { get; private set; } public static DateTime RecordingStartTime { get; private set; } public static DateTime RecordingStopTime { get; private set; } public static string LastRecordedFile { get; private set; } = string.Empty; public static string LastRecordedDirectory { get; private set; } = string.Empty; public static double LastDurationSeconds { get; private set; } public static long LastFileSizeBytes { get; private set; } [DllImport("user32.dll")] private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo); public static string GetActiveOutputDirectory() { string text = PluginConfig.RecordOutputDirectory?.Value; if (!string.IsNullOrWhiteSpace(text) && Directory.Exists(text)) { return text; } string text2 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyVideos), "Captures"); if (Directory.Exists(text2)) { return text2; } string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.MyVideos); if (Directory.Exists(folderPath)) { return folderPath; } if (Directory.Exists("E:\\BF6-Highlights\\raw")) { return "E:\\BF6-Highlights\\raw"; } return Directory.GetCurrentDirectory(); } public static List<string> GetCandidateDirectories() { List<string> list = new List<string>(); string text = PluginConfig.RecordOutputDirectory?.Value; if (!string.IsNullOrWhiteSpace(text) && Directory.Exists(text)) { list.Add(text); } string text2 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyVideos), "Captures"); if (Directory.Exists(text2) && !list.Contains(text2)) { list.Add(text2); } string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.MyVideos); if (Directory.Exists(folderPath) && !list.Contains(folderPath)) { list.Add(folderPath); } if (Directory.Exists("E:\\BF6-Highlights\\raw") && !list.Contains("E:\\BF6-Highlights\\raw")) { list.Add("E:\\BF6-Highlights\\raw"); } return list; } public static void TriggerHardwareCaptureShortcut() { ConfigEntry<bool> enableGameBarTrigger = PluginConfig.EnableGameBarTrigger; if (enableGameBarTrigger == null || !enableGameBarTrigger.Value) { return; } try { keybd_event(91, 0, 0u, UIntPtr.Zero); keybd_event(18, 0, 0u, UIntPtr.Zero); keybd_event(82, 0, 0u, UIntPtr.Zero); keybd_event(82, 0, 2u, UIntPtr.Zero); keybd_event(18, 0, 2u, UIntPtr.Zero); keybd_event(91, 0, 2u, UIntPtr.Zero); } catch (Exception ex) { ZLog.LogWarning((object)("[Unfaded.RecordingManager] Failed to dispatch capture shortcut: " + ex.Message)); } } public static bool StartRecording(out string message) { //IL_00be: Unknown result type (might be due to invalid IL or missing references) if (IsRecording) { double totalSeconds = (DateTime.Now - RecordingStartTime).TotalSeconds; message = $"<color=#FFAA00>[Record]</color> Already recording since <b>{RecordingStartTime:HH:mm:ss}</b> ({totalSeconds:F0}s elapsed).\nType <color=#00FFAA>'record stop'</color> to complete."; return false; } RecordingStartTime = DateTime.Now; IsRecording = true; TriggerHardwareCaptureShortcut(); string activeOutputDirectory = GetActiveOutputDirectory(); ShowHudMessage($"<color=#FF4444>\ud83d\udd34 REC</color> Started at {RecordingStartTime:HH:mm:ss}"); message = $"<color=#00FFAA>[Record]</color> <b>RECORDING STARTED</b> at <b>{RecordingStartTime:HH:mm:ss}</b>\n" + " • Target Directory : <b>" + activeOutputDirectory + "</b>\n • Hotkey Dispatched : <b>[Win + Alt + R]</b> (Windows Game Bar / OBS)\n" + $" • Finish Command : Type <color=#00FFAA>'record stop'</color> (or press {PluginConfig.RecordHotkey?.Value})"; return true; } public static bool StopRecording(out string message) { if (!IsRecording) { message = "<color=#FFAA00>[Record]</color> No active recording in progress. Type <color=#00FFAA>'record start'</color> to begin."; return false; } RecordingStopTime = DateTime.Now; IsRecording = false; TriggerHardwareCaptureShortcut(); double num = (LastDurationSeconds = (RecordingStopTime - RecordingStartTime).TotalSeconds); FileInfo fileInfo = FindNewestVideoFile(RecordingStartTime.AddSeconds(-3.0)); if (fileInfo != null) { LastRecordedFile = fileInfo.FullName; LastRecordedDirectory = fileInfo.DirectoryName ?? string.Empty; LastFileSizeBytes = fileInfo.Length; double num2 = (double)LastFileSizeBytes / 1048576.0; string arg = FormatDuration(num); ShowHudMessage($"<color=#00FFAA>⏹ REC SAVED</color> [{arg}] ({num2:F1} MB)"); message = "==================================================\n <b><color=#00FFAA>Unfaded :: Recording Completed & Saved</color></b>\n==================================================\n" + $" • Start Time : <b>{RecordingStartTime:HH:mm:ss}</b>\n" + $" • Stop Time : <b>{RecordingStopTime:HH:mm:ss}</b>\n" + $" • Duration : <b>{arg}</b> ({num:F1}s)\n" + " • File Name : <b><color=#00FFAA>" + fileInfo.Name + "</color></b>\n" + $" • File Size : <b>{num2:F2} MB</b>\n" + " • Directory : <b>" + LastRecordedDirectory + "</b>\n=================================================="; return true; } string activeOutputDirectory = GetActiveOutputDirectory(); string text = FormatDuration(num); ShowHudMessage("<color=#00FFAA>⏹ REC STOPPED</color> [" + text + "]"); message = "==================================================\n <b><color=#00FFAA>Unfaded :: Recording Stopped</color></b>\n==================================================\n" + $" • Start Time : <b>{RecordingStartTime:HH:mm:ss}</b>\n" + $" • Stop Time : <b>{RecordingStopTime:HH:mm:ss}</b>\n" + $" • Duration : <b>{text}</b> ({num:F1}s)\n" + " • Directory : <b>" + activeOutputDirectory + "</b>\n • Status : Finalizing write buffer in capture folder.\n=================================================="; return true; } public static string GetStatus() { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) if (IsRecording) { double totalSeconds = (DateTime.Now - RecordingStartTime).TotalSeconds; return $"<color=#00FFAA>[Record]</color> State: <b><color=#FF4444>● RECORDING ACTIVE</color></b> ({FormatDuration(totalSeconds)} elapsed, started {RecordingStartTime:HH:mm:ss})\n" + " • Target Directory: " + GetActiveOutputDirectory() + "\n • Finish Command : Type <color=#00FFAA>'record stop'</color>"; } string arg = ((!string.IsNullOrEmpty(LastRecordedFile)) ? $"\n • Last File : {Path.GetFileName(LastRecordedFile)} ({FormatDuration(LastDurationSeconds)}, {(double)LastFileSizeBytes / 1048576.0:F1} MB)\n • Directory : {LastRecordedDirectory}" : ""); return "<color=#00FFAA>[Record]</color> State: <b>IDLE</b>\n • Capture Directory : " + GetActiveOutputDirectory() + "\n" + $" • Hotkey : [{PluginConfig.RecordHotkey?.Value}] (toggle start/stop){arg}\n" + " • Usage : 'record start' | 'record stop' | 'record status' | 'record dir <path>'"; } private static FileInfo? FindNewestVideoFile(DateTime sinceTime) { HashSet<string> validExtensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".mp4", ".mkv", ".mov", ".avi", ".webm" }; FileInfo fileInfo = null; foreach (string candidateDirectory in GetCandidateDirectories()) { if (!Directory.Exists(candidateDirectory)) { continue; } try { FileInfo fileInfo2 = (from f in new DirectoryInfo(candidateDirectory).GetFiles("*.*", SearchOption.TopDirectoryOnly) where validExtensions.Contains(f.Extension) && f.LastWriteTime >= sinceTime orderby f.LastWriteTime descending select f).FirstOrDefault(); if (fileInfo2 != null && (fileInfo == null || fileInfo2.LastWriteTime > fileInfo.LastWriteTime)) { fileInfo = fileInfo2; } } catch (Exception ex) { ZLog.LogWarning((object)("[Unfaded.RecordingManager] Error scanning " + candidateDirectory + ": " + ex.Message)); } } return fileInfo; } public static string FormatDuration(double totalSeconds) { TimeSpan timeSpan = TimeSpan.FromSeconds(totalSeconds); if (!(timeSpan.TotalHours >= 1.0)) { return $"{timeSpan.Minutes:D2}:{timeSpan.Seconds:D2}"; } return $"{(int)timeSpan.TotalHours:D2}:{timeSpan.Minutes:D2}:{timeSpan.Seconds:D2}"; } private static void ShowHudMessage(string text) { try { if ((Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)1, text, 0, (Sprite)null, false, true); } else if ((Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)1, text, 0, (Sprite)null, false); } } catch { } } } } namespace Unfaded.Configuration { public static class PluginConfig { public static ConfigEntry<bool> IsModEnabled; public static ConfigEntry<bool> DisableDeathFade; public static ConfigEntry<float> CustomDeathFadeDuration; public static ConfigEntry<float> RespawnDelay; public static ConfigEntry<bool> EnableManualRespawn; public static ConfigEntry<KeyCode> ManualRespawnKey; public static ConfigEntry<bool> ShowRespawnPrompt; public static ConfigEntry<string> RespawnPromptText; public static ConfigEntry<bool> EnableCameraOrbit; public static ConfigEntry<float> CameraOrbitSensitivity; public static ConfigEntry<bool> EnableDeathRecap; public static ConfigEntry<bool> EnableKillerCam; public static ConfigEntry<KeyCode> KillerCamKey; public static ConfigEntry<bool> EnableSlowMotion; public static ConfigEntry<float> SlowMotionScale; public static ConfigEntry<float> SlowMotionDuration; public static ConfigEntry<bool> EnableFreeFly; public static ConfigEntry<KeyCode> FreeFlyKey; public static ConfigEntry<float> FreeFlyRadius; public static ConfigEntry<float> FreeFlySpeed; public static ConfigEntry<string> RecordOutputDirectory; public static ConfigEntry<bool> EnableRecordingHotkey; public static ConfigEntry<KeyCode> RecordHotkey; public static ConfigEntry<bool> EnableGameBarTrigger; public static void BindConfig(ConfigFile config) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Expected O, but got Unknown //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Expected O, but got Unknown //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Expected O, but got Unknown //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Expected O, but got Unknown //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Expected O, but got Unknown IsModEnabled = config.Bind<bool>("1 - General", "Enabled", true, "Master toggle for Unfaded mod."); DisableDeathFade = config.Bind<bool>("2 - Visuals", "DisableDeathFade", true, "Completely eliminate the 9.5-second black screen fadeout on death, keeping the viewport fully visible."); CustomDeathFadeDuration = config.Bind<float>("2 - Visuals", "CustomDeathFadeDuration", 0f, "Custom death fade duration in seconds. Set to 0 for no fade. Vanilla Valheim is 9.5 seconds."); RespawnDelay = config.Bind<float>("3 - Respawn", "RespawnDelay", 10f, new ConfigDescription("Seconds to wait before automatic respawn after death. Vanilla Valheim is 10.0 seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 120f), Array.Empty<object>())); EnableManualRespawn = config.Bind<bool>("3 - Respawn", "EnableManualRespawn", true, "Allow pressing a key while dead to immediately trigger respawn at your bed/spawnpoint."); ManualRespawnKey = config.Bind<KeyCode>("3 - Respawn", "ManualRespawnKey", (KeyCode)32, "Key that triggers early respawn while dead."); ShowRespawnPrompt = config.Bind<bool>("3 - Respawn", "ShowRespawnPrompt", true, "Show an on-screen HUD prompt indicating spectator controls and the manual respawn hotkey while dead."); RespawnPromptText = config.Bind<string>("3 - Respawn", "RespawnPromptText", "[{0}] Respawn • [K] Killer Cam • [F] Free Fly", "Status bar text displayed during death spectator mode."); EnableCameraOrbit = config.Bind<bool>("4 - Spectator Camera", "EnableCameraOrbit", true, "Allow orbiting the camera around your ragdoll using mouse look while dead."); CameraOrbitSensitivity = config.Bind<float>("4 - Spectator Camera", "CameraOrbitSensitivity", 2f, new ConfigDescription("Mouse look sensitivity multiplier while spectating your corpse.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>())); EnableDeathRecap = config.Bind<bool>("5 - Killer & Recap", "EnableDeathRecap", true, "Display an on-screen Death Recap banner showing the killer's name, star rank, and lethal damage amount."); EnableKillerCam = config.Bind<bool>("5 - Killer & Recap", "EnableKillerCam", true, "Allow toggling the camera focus to the creature that dealt the fatal blow."); KillerCamKey = config.Bind<KeyCode>("5 - Killer & Recap", "KillerCamKey", (KeyCode)107, "Key to toggle camera focus between your ragdoll and your killer."); EnableSlowMotion = config.Bind<bool>("6 - Cinematic Slow-Mo", "EnableSlowMotion", true, "Briefly enter cinematic bullet-time slow motion upon receiving lethal damage so you can watch your Viking ragdoll launch in epic slow-mo."); SlowMotionScale = config.Bind<float>("6 - Cinematic Slow-Mo", "SlowMotionScale", 0.35f, new ConfigDescription("Time scale during the lethal impact (0.1 = super slow, 1.0 = normal speed).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>())); SlowMotionDuration = config.Bind<float>("6 - Cinematic Slow-Mo", "SlowMotionDuration", 1.5f, new ConfigDescription("Real-time seconds of slow motion before returning to regular game speed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 5f), Array.Empty<object>())); EnableFreeFly = config.Bind<bool>("7 - Free-Fly Spectator", "EnableFreeFly", true, "Allow untethering the camera to fly freely around the death site for tactical corpse recovery scouting."); FreeFlyKey = config.Bind<KeyCode>("7 - Free-Fly Spectator", "FreeFlyKey", (KeyCode)102, "Key to toggle free-fly drone mode on and off while dead."); FreeFlyRadius = config.Bind<float>("7 - Free-Fly Spectator", "FreeFlyRadius", 60f, new ConfigDescription("Maximum flight distance in meters from your death location.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 200f), Array.Empty<object>())); FreeFlySpeed = config.Bind<float>("7 - Free-Fly Spectator", "FreeFlySpeed", 15f, new ConfigDescription("Movement speed in meters per second while in free-fly drone mode.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 50f), Array.Empty<object>())); RecordOutputDirectory = config.Bind<string>("8 - Video Recording", "RecordOutputDirectory", "", "Optional custom directory to scan for recorded video files. If blank, auto-detects Captures and OBS directories."); EnableRecordingHotkey = config.Bind<bool>("8 - Video Recording", "EnableRecordingHotkey", true, "Enable hotkey toggle to start and stop video recording without opening console."); RecordHotkey = config.Bind<KeyCode>("8 - Video Recording", "RecordHotkey", (KeyCode)290, "Hotkey to toggle video recording on/off (starts recording on first press, stops and logs summary on second press)."); EnableGameBarTrigger = config.Bind<bool>("8 - Video Recording", "EnableGameBarTrigger", true, "Automatically dispatch Windows Game Bar capture shortcut (Win + Alt + R) on record start/stop."); } } } namespace Unfaded.Commands { [HarmonyPatch(typeof(Terminal), "Awake")] public static class UnfadedCommand { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__0_0; public static ConsoleEvent <>9__0_1; public static Func<string, string> <>9__1_0; internal void <Postfix>b__0_0(ConsoleEventArgs args) { HandleRecordCommand(args); } internal void <Postfix>b__0_1(ConsoleEventArgs args) { if (args.Length < 2 || args[1].Equals("status", StringComparison.OrdinalIgnoreCase) || args[1].Equals("help", StringComparison.OrdinalIgnoreCase)) { PrintStatus(args.Context); return; } string text = args[1].ToLower(); switch (text) { case "record": case "rec": HandleRecordSubcommand(args); break; case "die": case "smite": case "tree": ExecuteSmite(args, text == "tree"); break; case "test": { DeathStateManager.IsTestSimActive = true; DeathStateManager.TestSimEndTime = Time.time + 6f; Terminal context2 = args.Context; if (context2 != null) { context2.AddString("<color=#00FFAA>[Unfaded]</color> <b>Spectator Test Mode Active (6s)</b>! Orbit with mouse, press [K] Killer, [F] Free Fly."); } break; } case "delay": { if (args.Length >= 3 && float.TryParse(args[2], out var result)) { PluginConfig.RespawnDelay.Value = Mathf.Clamp(result, 0f, 120f); Terminal context6 = args.Context; if (context6 != null) { context6.AddString($"<color=#00FFAA>[Unfaded]</color> Respawn delay set to: <b>{PluginConfig.RespawnDelay.Value:F1}s</b>"); } } else { Terminal context7 = args.Context; if (context7 != null) { context7.AddString("<color=#FF6B6B>[Unfaded]</color> Usage: unfaded delay <seconds> (e.g. unfaded delay 5)"); } } break; } case "slowmo": { PluginConfig.EnableSlowMotion.Value = !PluginConfig.EnableSlowMotion.Value; Terminal context4 = args.Context; if (context4 != null) { context4.AddString("<color=#00FFAA>[Unfaded]</color> Cinematic Slow-Mo on lethal hit: <b>" + (PluginConfig.EnableSlowMotion.Value ? "<color=#00FFAA>ENABLED</color>" : "<color=#FF6B6B>DISABLED</color>") + "</b>"); } break; } case "orbit": { PluginConfig.EnableCameraOrbit.Value = !PluginConfig.EnableCameraOrbit.Value; Terminal context5 = args.Context; if (context5 != null) { context5.AddString("<color=#00FFAA>[Unfaded]</color> 360° Corpse Orbit: <b>" + (PluginConfig.EnableCameraOrbit.Value ? "<color=#00FFAA>ENABLED</color>" : "<color=#FF6B6B>DISABLED</color>") + "</b>"); } break; } case "killer": { PluginConfig.EnableKillerCam.Value = !PluginConfig.EnableKillerCam.Value; Terminal context8 = args.Context; if (context8 != null) { context8.AddString("<color=#00FFAA>[Unfaded]</color> Killer Focus Cam: <b>" + (PluginConfig.EnableKillerCam.Value ? "<color=#00FFAA>ENABLED</color>" : "<color=#FF6B6B>DISABLED</color>") + "</b>"); } break; } case "freefly": { PluginConfig.EnableFreeFly.Value = !PluginConfig.EnableFreeFly.Value; Terminal context3 = args.Context; if (context3 != null) { context3.AddString("<color=#00FFAA>[Unfaded]</color> Free-Fly Drone Spectator: <b>" + (PluginConfig.EnableFreeFly.Value ? "<color=#00FFAA>ENABLED</color>" : "<color=#FF6B6B>DISABLED</color>") + "</b>"); } break; } default: { Terminal context = args.Context; if (context != null) { context.AddString("<color=#FF6B6B>[Unfaded]</color> Unknown subcommand. Options: status, record, test, delay <sec>, slowmo, orbit, killer, freefly"); } break; } } } internal string <HandleRecordCommand>b__1_0(string d) { return " • " + d; } } [HarmonyPostfix] public static void Postfix() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown object obj = <>c.<>9__0_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { HandleRecordCommand(args); }; <>c.<>9__0_0 = val; obj = (object)val; } ConsoleEvent val2 = (ConsoleEvent)obj; new ConsoleCommand("record", "Video recording devcommands (start, stop, status, dir)", val2, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); new ConsoleCommand("rec", "Shorthand alias for record (start, stop, status, dir)", val2, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj2 = <>c.<>9__0_1; if (obj2 == null) { ConsoleEvent val3 = delegate(ConsoleEventArgs args) { if (args.Length < 2 || args[1].Equals("status", StringComparison.OrdinalIgnoreCase) || args[1].Equals("help", StringComparison.OrdinalIgnoreCase)) { PrintStatus(args.Context); } else { string text = args[1].ToLower(); switch (text) { case "record": case "rec": HandleRecordSubcommand(args); break; case "die": case "smite": case "tree": ExecuteSmite(args, text == "tree"); break; case "test": { DeathStateManager.IsTestSimActive = true; DeathStateManager.TestSimEndTime = Time.time + 6f; Terminal context2 = args.Context; if (context2 != null) { context2.AddString("<color=#00FFAA>[Unfaded]</color> <b>Spectator Test Mode Active (6s)</b>! Orbit with mouse, press [K] Killer, [F] Free Fly."); } break; } case "delay": { if (args.Length >= 3 && float.TryParse(args[2], out var result)) { PluginConfig.RespawnDelay.Value = Mathf.Clamp(result, 0f, 120f); Terminal context6 = args.Context; if (context6 != null) { context6.AddString($"<color=#00FFAA>[Unfaded]</color> Respawn delay set to: <b>{PluginConfig.RespawnDelay.Value:F1}s</b>"); } } else { Terminal context7 = args.Context; if (context7 != null) { context7.AddString("<color=#FF6B6B>[Unfaded]</color> Usage: unfaded delay <seconds> (e.g. unfaded delay 5)"); } } break; } case "slowmo": { PluginConfig.EnableSlowMotion.Value = !PluginConfig.EnableSlowMotion.Value; Terminal context4 = args.Context; if (context4 != null) { context4.AddString("<color=#00FFAA>[Unfaded]</color> Cinematic Slow-Mo on lethal hit: <b>" + (PluginConfig.EnableSlowMotion.Value ? "<color=#00FFAA>ENABLED</color>" : "<color=#FF6B6B>DISABLED</color>") + "</b>"); } break; } case "orbit": { PluginConfig.EnableCameraOrbit.Value = !PluginConfig.EnableCameraOrbit.Value; Terminal context5 = args.Context; if (context5 != null) { context5.AddString("<color=#00FFAA>[Unfaded]</color> 360° Corpse Orbit: <b>" + (PluginConfig.EnableCameraOrbit.Value ? "<color=#00FFAA>ENABLED</color>" : "<color=#FF6B6B>DISABLED</color>") + "</b>"); } break; } case "killer": { PluginConfig.EnableKillerCam.Value = !PluginConfig.EnableKillerCam.Value; Terminal context8 = args.Context; if (context8 != null) { context8.AddString("<color=#00FFAA>[Unfaded]</color> Killer Focus Cam: <b>" + (PluginConfig.EnableKillerCam.Value ? "<color=#00FFAA>ENABLED</color>" : "<color=#FF6B6B>DISABLED</color>") + "</b>"); } break; } case "freefly": { PluginConfig.EnableFreeFly.Value = !PluginConfig.EnableFreeFly.Value; Terminal context3 = args.Context; if (context3 != null) { context3.AddString("<color=#00FFAA>[Unfaded]</color> Free-Fly Drone Spectator: <b>" + (PluginConfig.EnableFreeFly.Value ? "<color=#00FFAA>ENABLED</color>" : "<color=#FF6B6B>DISABLED</color>") + "</b>"); } break; } default: { Terminal context = args.Context; if (context != null) { context.AddString("<color=#FF6B6B>[Unfaded]</color> Unknown subcommand. Options: status, record, test, delay <sec>, slowmo, orbit, killer, freefly"); } break; } } } }; <>c.<>9__0_1 = val3; obj2 = (object)val3; } new ConsoleCommand("unfaded", "Unfaded death spectator & recording commands (status, record, test, delay, slowmo, orbit, killer, freefly)", (ConsoleEvent)obj2, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } public static void HandleRecordCommand(ConsoleEventArgs args) { if (args.Length < 2 || args[1].Equals("status", StringComparison.OrdinalIgnoreCase)) { string status = RecordingManager.GetStatus(); Terminal context = args.Context; if (context != null) { context.AddString(status); } return; } string text = args[1].ToLower(); switch (text) { case "begin": case "start": case "on": { RecordingManager.StartRecording(out string message4); Terminal context9 = args.Context; if (context9 != null) { context9.AddString(message4); } break; } case "stop": case "end": case "off": { RecordingManager.StopRecording(out string message); Terminal context3 = args.Context; if (context3 != null) { context3.AddString(message); } break; } case "toggle": if (RecordingManager.IsRecording) { RecordingManager.StopRecording(out string message2); Terminal context7 = args.Context; if (context7 != null) { context7.AddString(message2); } } else { RecordingManager.StartRecording(out string message3); Terminal context8 = args.Context; if (context8 != null) { context8.AddString(message3); } } break; case "path": case "dir": case "directory": { if (args.Length >= 3) { string text2 = args.FullLine.Substring(args.FullLine.IndexOf(args[2], StringComparison.Ordinal)).Trim(); if (Directory.Exists(text2)) { PluginConfig.RecordOutputDirectory.Value = text2; Terminal context4 = args.Context; if (context4 != null) { context4.AddString("<color=#00FFAA>[Record]</color> Capture directory updated: <b>" + text2 + "</b>"); } } else { Terminal context5 = args.Context; if (context5 != null) { context5.AddString("<color=#FF6B6B>[Record]</color> Directory not found: " + text2); } } break; } Terminal context6 = args.Context; if (context6 != null) { context6.AddString("<color=#00FFAA>[Record]</color> Active capture directory: <b>" + RecordingManager.GetActiveOutputDirectory() + "</b>\n Candidate folders searched:\n" + string.Join("\n", from d in RecordingManager.GetCandidateDirectories() select " • " + d)); } break; } case "smite": case "tree": ExecuteSmite(args, text == "tree"); break; default: { Terminal context2 = args.Context; if (context2 != null) { context2.AddString("<color=#FF6B6B>[Record]</color> Usage:\n • <color=#00FFAA>record start</color> - Start recording (echos start time, sends Win+Alt+R)\n • <color=#00FFAA>record stop</color> - Stop recording (echos duration, filename, path, size)\n • <color=#00FFAA>record status</color> - View recording status\n • <color=#00FFAA>record dir [path]</color> - Show or set output directory"); } break; } } } private static void HandleRecordSubcommand(ConsoleEventArgs args) { if (args.Length < 3) { Terminal context = args.Context; if (context != null) { context.AddString(RecordingManager.GetStatus()); } return; } switch (args[2].ToLower()) { case "begin": case "start": case "on": { RecordingManager.StartRecording(out string message2); Terminal context8 = args.Context; if (context8 != null) { context8.AddString(message2); } break; } case "stop": case "end": case "off": { RecordingManager.StopRecording(out string message); Terminal context7 = args.Context; if (context7 != null) { context7.AddString(message); } break; } case "status": { Terminal context3 = args.Context; if (context3 != null) { context3.AddString(RecordingManager.GetStatus()); } break; } case "path": case "dir": case "directory": if (args.Length >= 4) { string text = args.FullLine.Substring(args.FullLine.IndexOf(args[3], StringComparison.Ordinal)).Trim(); if (Directory.Exists(text)) { PluginConfig.RecordOutputDirectory.Value = text; Terminal context4 = args.Context; if (context4 != null) { context4.AddString("<color=#00FFAA>[Record]</color> Capture directory updated: <b>" + text + "</b>"); } } else { Terminal context5 = args.Context; if (context5 != null) { context5.AddString("<color=#FF6B6B>[Record]</color> Directory not found: " + text); } } } else { Terminal context6 = args.Context; if (context6 != null) { context6.AddString("<color=#00FFAA>[Record]</color> Active capture directory: <b>" + RecordingManager.GetActiveOutputDirectory() + "</b>"); } } break; default: { Terminal context2 = args.Context; if (context2 != null) { context2.AddString("<color=#FF6B6B>[Record]</color> Usage: unfaded record start | stop | status | dir [path]"); } break; } } } private static void ExecuteSmite(ConsoleEventArgs args, bool asTree) { //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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { Terminal context = args.Context; if (context != null) { context.AddString("<color=#FF6B6B>[Unfaded]</color> Local player not found. Load into a world first."); } return; } HitData val = new HitData { m_hitType = (HitType)(asTree ? 13 : 14), m_pushForce = 120f }; Vector3 val2 = ((Component)localPlayer).transform.forward * -1f + Vector3.up * 0.45f; val.m_dir = ((Vector3)(ref val2)).normalized; val.m_point = ((Component)localPlayer).transform.position; HitData val3 = val; val3.m_damage.m_damage = 9999f; ((Character)localPlayer).Damage(val3); string text = (asTree ? "Falling Tree / Timber" : "Cinematic Smite"); Terminal context2 = args.Context; if (context2 != null) { context2.AddString("<color=#00FFAA>[Unfaded]</color> ⚡ Lethal hit dealt (" + text + ")! Ragdoll launched, spectator active."); } } private static void PrintStatus(Terminal context) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)context == (Object)null)) { context.AddString("=================================================="); context.AddString(" <b><color=#00FFAA>Unfaded :: Death Spectator & Recording</color></b>"); context.AddString("=================================================="); context.AddString(" • Blackout Override : <b>" + (PluginConfig.DisableDeathFade.Value ? "<color=#00FFAA>SUPPRESSED (Clear View)</color>" : "<color=#FF6B6B>ACTIVE (Vanilla)</color>") + "</b>"); context.AddString($" • Respawn Delay : <b>{PluginConfig.RespawnDelay.Value:F1}s</b> (Instant on [{PluginConfig.ManualRespawnKey.Value}])"); context.AddString(string.Format(" • 360° Corpse Orbit : <b>{0}</b> (Sensitivity: {1:F1}x)", PluginConfig.EnableCameraOrbit.Value ? "ENABLED" : "DISABLED", PluginConfig.CameraOrbitSensitivity.Value)); context.AddString(" • Killer Cam [K] : <b>" + (PluginConfig.EnableKillerCam.Value ? "ENABLED" : "DISABLED") + "</b>"); context.AddString(string.Format(" • Free-Fly Drone [F]: <b>{0}</b> (Radius: {1:F0}m)", PluginConfig.EnableFreeFly.Value ? "ENABLED" : "DISABLED", PluginConfig.FreeFlyRadius.Value)); context.AddString(" • Bullet-Time SlowMo: <b>" + (PluginConfig.EnableSlowMotion.Value ? $"ENABLED ({PluginConfig.SlowMotionScale.Value:F2}x for {PluginConfig.SlowMotionDuration.Value:F1}s)" : "DISABLED") + "</b>"); context.AddString(string.Format(" • Video Recording : <b>{0}</b> (Hotkey: [{1}])", RecordingManager.IsRecording ? "<color=#FF4444>ACTIVE</color>" : "<color=#00FFAA>IDLE</color>", PluginConfig.RecordHotkey?.Value)); context.AddString(" • Capture Directory : <b>" + RecordingManager.GetActiveOutputDirectory() + "</b>"); context.AddString(" Recording Commands : record start | record stop | record status | record dir"); context.AddString(" Spectator Commands : unfaded test | unfaded delay <sec> | unfaded slowmo | unfaded killer"); context.AddString("=================================================="); } } } }