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 AdvancedFreeCam v2.1.0
AdvancedFreeCam.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using AdvancedFreeCam.Config; using AdvancedFreeCam.Core; using AdvancedFreeCam.Ghost; using AdvancedFreeCam.Network; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; using UnityEngine.Rendering; 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: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("Kai")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+d30f35163e6d79db7219adc71d8de9a9f1edad94")] [assembly: AssemblyProduct("AdvancedFreeCam")] [assembly: AssemblyTitle("AdvancedFreeCam")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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 AdvancedFreeCam { [BepInPlugin("Kai.AdvancedFreeCam", "AdvancedFreeCam", "2.2.0")] public class AdvancedFreeCam : BaseUnityPlugin { private FreeCamManager? _freeCamManager; private FreeCamGhostManager? _ghostManager; private bool _handshakeApplied; private bool _voiceNetworkRegistered; private bool _ghostNetworkRegistered; private ConfigEntry<bool>? _allowHostAliveFreeCam; private ConfigEntry<bool>? _allowClientAliveFreeCam; private ConfigEntry<bool>? _allowClientDeadFreeCam; private ConfigEntry<bool>? _allowHostForceDisable; private ConfigEntry<bool>? _allowFreeCamVoice; private ConfigEntry<bool>? _allowClientFreeCamVoice; private ConfigEntry<bool>? _ghostVisibleToAlivePlayers; private ConfigEntry<bool>? _ghostVisibleToSpectators; private ConfigEntry<bool>? _ghostVisibleToFreeCamPlayers; internal static AdvancedFreeCam Instance { get; private set; } internal static ManualLogSource Logger => Instance._logger; private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; internal Harmony? Harmony { get; set; } internal bool HasAuthoritativeRoomConfig { get; private set; } private void Awake() { Instance = this; ((Component)this).transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; BindConfig(); ApplyHostConfigToRuntime(); _freeCamManager = new FreeCamManager(); _ghostManager = new FreeCamGhostManager(); Patch(); Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!"); } internal void Patch() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0025: Expected O, but got Unknown if (Harmony == null) { Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); Harmony val2 = val; Harmony = val; } Harmony.PatchAll(); } private void Update() { TryRegisterGhostNetwork(); TryApplyHandshake(); SyncRoomConfig(); _freeCamManager?.Tick(Time.deltaTime); _ghostManager?.Tick(); } private void LateUpdate() { FreeCamPhotoMode.LateTick(); } private void BindConfig() { BindHostConfig(); BindControlsConfig(); BindClientConfig(); } private void BindHostConfig() { _allowHostAliveFreeCam = ((BaseUnityPlugin)this).Config.Bind<bool>("Host", "AllowHostAliveFreeCam", true, "Allow the host to enable FreeCam while alive."); _allowClientAliveFreeCam = ((BaseUnityPlugin)this).Config.Bind<bool>("Host", "AllowClientAliveFreeCam", false, "Allow clients to enable FreeCam while alive."); _allowClientDeadFreeCam = ((BaseUnityPlugin)this).Config.Bind<bool>("Host", "AllowClientDeadFreeCam", true, "Allow clients to enable FreeCam while dead / spectating."); _ghostVisibleToAlivePlayers = ((BaseUnityPlugin)this).Config.Bind<bool>("Host", "GhostVisibleToAlivePlayers", false, "Show FreeCam ghost to alive players."); _ghostVisibleToSpectators = ((BaseUnityPlugin)this).Config.Bind<bool>("Host", "GhostVisibleToSpectators", true, "Show FreeCam ghost to spectators / dead players."); _ghostVisibleToFreeCamPlayers = ((BaseUnityPlugin)this).Config.Bind<bool>("Host", "GhostVisibleToFreeCamPlayers", true, "Show FreeCam ghost to other FreeCam players."); } private void BindControlsConfig() { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Expected O, but got Unknown //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Expected O, but got Unknown //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Expected O, but got Unknown //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Expected O, but got Unknown //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Expected O, but got Unknown FreeCamLocalSettings.ToggleFreeCamKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "ToggleFreeCamKey", (KeyCode)289, "Toggle FreeCam on / off."); FreeCamLocalSettings.TogglePhotoModeKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "TogglePhotoModeKey", (KeyCode)122, "Toggle PhotoMode while FreeCam is active."); FreeCamLocalSettings.FreeCamLookSensitivity = ((BaseUnityPlugin)this).Config.Bind<float>("Controls", "FreeCamLookSensitivity", 1.5f, new ConfigDescription("Mouse look sensitivity while using FreeCam.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>())); FreeCamLocalSettings.FreeCamMaxMouseDelta = ((BaseUnityPlugin)this).Config.Bind<float>("Controls", "FreeCamMaxMouseDelta", 8f, new ConfigDescription("Maximum mouse input delta per frame while using FreeCam. Lower values reduce sudden camera swings.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 12f), Array.Empty<object>())); FreeCamLocalSettings.FastMoveKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "FastMoveKey", (KeyCode)304, "Hold to move faster while using FreeCam."); FreeCamLocalSettings.MoveUpKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "MoveUpKey", (KeyCode)32, "Move FreeCam upward."); FreeCamLocalSettings.MoveDownKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "MoveDownKey", (KeyCode)306, "Move FreeCam downward."); FreeCamLocalSettings.FreeCamBaseMoveSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Controls", "FreeCamBaseMoveSpeed", 8f, new ConfigDescription("Default FreeCam movement speed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 200f), Array.Empty<object>())); FreeCamLocalSettings.FreeCamFastMoveMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Controls", "FreeCamFastMoveMultiplier", 3f, new ConfigDescription("Movement speed multiplier while holding FastMoveKey.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f), Array.Empty<object>())); FreeCamLocalSettings.FreeCamMinMoveSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Controls", "FreeCamMinMoveSpeed", 1f, new ConfigDescription("Minimum FreeCam movement speed when adjusted by mouse wheel.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 200f), Array.Empty<object>())); FreeCamLocalSettings.FreeCamMaxMoveSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Controls", "FreeCamMaxMoveSpeed", 50f, new ConfigDescription("Maximum FreeCam movement speed when adjusted by mouse wheel.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 200f), Array.Empty<object>())); FreeCamLocalSettings.FreeCamMouseWheelSpeedStep = ((BaseUnityPlugin)this).Config.Bind<float>("Controls", "FreeCamMouseWheelSpeedStep", 1f, new ConfigDescription("FreeCam speed change amount per mouse wheel step.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 50f), Array.Empty<object>())); } private void BindClientConfig() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown FreeCamLocalSettings.PhotoModeNightVision = ((BaseUnityPlugin)this).Config.Bind<float>("Client", "PhotoModeNightVision", 25f, new ConfigDescription("Ambient-light based night vision strength while PhotoMode is enabled. 0 = off, 100 = max.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); } private void ApplyHostConfigToRuntime() { FreeCamConfig instance = FreeCamConfig.Instance; instance.AllowHostAliveFreeCam = _allowHostAliveFreeCam?.Value ?? true; instance.AllowClientAliveFreeCam = _allowClientAliveFreeCam?.Value ?? false; instance.AllowClientDeadFreeCam = _allowClientDeadFreeCam?.Value ?? true; instance.AllowHostForceDisable = _allowHostForceDisable?.Value ?? true; instance.GhostVisibleToAlivePlayers = _ghostVisibleToAlivePlayers?.Value ?? false; instance.GhostVisibleToSpectators = _ghostVisibleToSpectators?.Value ?? true; instance.GhostVisibleToFreeCamPlayers = _ghostVisibleToFreeCamPlayers?.Value ?? true; } private void SyncRoomConfig() { if (!SemiFunc.IsMultiplayer()) { HasAuthoritativeRoomConfig = true; ApplyHostConfigToRuntime(); } else if (!PhotonNetwork.InRoom) { HasAuthoritativeRoomConfig = false; } else if (PhotonNetwork.IsMasterClient) { ApplyHostConfigToRuntime(); FreeCamRoomConfigSync.PushHostConfigToRoom(); HasAuthoritativeRoomConfig = true; } else { HasAuthoritativeRoomConfig = FreeCamRoomConfigSync.TryApplyRoomConfigToRuntime(); } } private void TryRegisterGhostNetwork() { bool flag = SemiFunc.IsMultiplayer() && PhotonNetwork.InRoom && PhotonNetwork.NetworkingClient != null; if (flag != _ghostNetworkRegistered) { if (flag) { FreeCamGhostNetwork.Register(); _ghostNetworkRegistered = true; } else { FreeCamGhostNetwork.Unregister(); _ghostNetworkRegistered = false; } } } private void TryApplyHandshake() { if (!SemiFunc.IsMultiplayer()) { _handshakeApplied = false; } else if (!PhotonNetwork.InRoom) { _handshakeApplied = false; } else if (PhotonNetwork.LocalPlayer != null && !_handshakeApplied) { FreeCamPlayerHandshake.ApplyLocalProperties(); _handshakeApplied = true; } } internal void SetPhotoModeNightVision(float value) { float value2 = Mathf.Clamp(value, 0f, 100f); if (FreeCamLocalSettings.PhotoModeNightVision != null) { FreeCamLocalSettings.PhotoModeNightVision.Value = value2; } } } } namespace AdvancedFreeCam.Patchs { [HarmonyPatch(typeof(PlayerAvatar), "ReviveRPC")] internal static class Patch_PlayerAvatar_Revive_GhostReset { internal static void Prefix(PlayerAvatar __instance) { if (!((Object)(object)__instance == (Object)null) && __instance.isLocal) { FreeCamManager.Instance?.DisableFreeCam(); } } } [HarmonyPatch(typeof(PlayerAvatar), "PlayerDeathRPC")] internal static class Patch_PlayerAvatar_Death_GhostReset { internal static void Prefix(PlayerAvatar __instance) { if (!((Object)(object)__instance == (Object)null) && __instance.isLocal) { FreeCamManager.Instance?.DisableFreeCam(); } } } [HarmonyPatch(typeof(SemiFunc), "OnLevelGenDone")] internal static class Patch_SemiFunc_OnLevelGenDone_GhostReset { private static void Prefix() { FreeCamGhostManager.Instance?.ClearAll(); FreeCamGhostManager.Instance?.PrewarmFromPlayerList(); } } internal static class Patch_SpectateCameraDeathEffects_FreeCam { [HarmonyPatch(typeof(SpectateCamera), "StateDeath")] private static class SpectateCamera_StateDeath_Patch { private static void Prefix() { //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_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) _suppressingSpectateDeathEffects = false; _hasSnapshot = false; _hasTopCamera = false; if (!ShouldSuppress()) { return; } Camera val = (((Object)(object)GameDirector.instance != (Object)null) ? GameDirector.instance.MainCamera : null); if ((Object)(object)val == (Object)null) { return; } _mainCameraLocalPosition = ((Component)val).transform.localPosition; _mainCameraLocalRotation = ((Component)val).transform.localRotation; _mainCameraFieldOfView = val.fieldOfView; _mainCameraNearClip = val.nearClipPlane; _mainCameraFarClip = val.farClipPlane; _fog = RenderSettings.fog; Camera[] componentsInChildren = ((Component)val).GetComponentsInChildren<Camera>(); foreach (Camera val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)val)) { _topCameraFieldOfView = val2.fieldOfView; _hasTopCamera = true; break; } } _hasSnapshot = true; _suppressingSpectateDeathEffects = true; } private static void Postfix() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (!_suppressingSpectateDeathEffects || !_hasSnapshot) { ResetFlags(); return; } Camera val = (((Object)(object)GameDirector.instance != (Object)null) ? GameDirector.instance.MainCamera : null); if ((Object)(object)val != (Object)null) { ((Component)val).transform.localPosition = _mainCameraLocalPosition; ((Component)val).transform.localRotation = _mainCameraLocalRotation; val.fieldOfView = _mainCameraFieldOfView; val.nearClipPlane = _mainCameraNearClip; val.farClipPlane = _mainCameraFarClip; if (_hasTopCamera) { Camera[] componentsInChildren = ((Component)val).GetComponentsInChildren<Camera>(); foreach (Camera val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)val)) { val2.fieldOfView = _topCameraFieldOfView; break; } } } } RenderSettings.fog = _fog; ResetFlags(); } private static void ResetFlags() { _suppressingSpectateDeathEffects = false; _hasSnapshot = false; _hasTopCamera = false; } } [HarmonyPatch(typeof(CameraGlitch), "PlayShort")] private static class CameraGlitch_PlayShort_Patch { private static bool Prefix() { return !_suppressingSpectateDeathEffects; } } [HarmonyPatch(typeof(CameraShake), "Shake")] private static class CameraShake_Shake_Patch { private static bool Prefix(CameraShake __instance) { if (!_suppressingSpectateDeathEffects) { return true; } if ((Object)(object)GameDirector.instance == (Object)null) { return true; } if ((Object)(object)__instance == (Object)(object)GameDirector.instance.CameraShake) { return false; } if ((Object)(object)__instance == (Object)(object)GameDirector.instance.CameraImpact) { return false; } return true; } } [HarmonyPatch(typeof(CameraNoise), "Override")] private static class CameraNoise_Override_Patch { private static bool Prefix() { return !_suppressingSpectateDeathEffects; } } private static bool _suppressingSpectateDeathEffects; private static bool _hasSnapshot; private static bool _hasTopCamera; private static Vector3 _mainCameraLocalPosition; private static Quaternion _mainCameraLocalRotation; private static float _mainCameraFieldOfView; private static float _topCameraFieldOfView; private static float _mainCameraNearClip; private static float _mainCameraFarClip; private static bool _fog; private static bool IsFreeCamActive() { if (FreeCamManager.Instance != null) { return FreeCamManager.Instance.IsActive; } return false; } private static bool AllPlayersDead() { if ((Object)(object)GameDirector.instance == (Object)null || GameDirector.instance.PlayerList == null) { return false; } if (GameDirector.instance.PlayerList.Count == 0) { return false; } foreach (PlayerAvatar player in GameDirector.instance.PlayerList) { if ((Object)(object)player != (Object)null && !player.isDisabled) { return false; } } return true; } private static bool ShouldSuppress() { if (!IsFreeCamActive()) { return false; } if ((Object)(object)SpectateCamera.instance == (Object)null) { return false; } if (!SpectateCamera.instance.CheckState((State)0)) { return false; } if (AllPlayersDead()) { return false; } return true; } } [HarmonyPatch(typeof(SpectateCamera), "Awake")] internal static class Patch_SpectateCamera_Awake_FreeCamCleanup { private static void Prefix() { FreeCamManager.Instance?.ForceCleanup("SpectateCamera.Awake"); } } [HarmonyPatch(typeof(SpectateCamera), "PlayerSwitch")] internal static class Patch_SpectateCamera_PlayerSwitch_FreeCamInputBlock { private static bool Prefix() { if (FreeCamManager.Instance == null || !FreeCamManager.Instance.IsActive) { return true; } if (Input.GetKeyDown((KeyCode)32) || Input.GetKeyDown((KeyCode)323) || Input.GetKeyDown((KeyCode)324)) { return false; } return true; } } [HarmonyPatch(typeof(RunManager), "ChangeLevel")] internal static class Patch_RunManager_ChangeLevel { private static void Prefix() { FreeCamManager.Instance?.PrepareForLevelTransition("RunManager.ChangeLevel"); } } [HarmonyPatch(typeof(RunManager), "RestartScene")] internal static class Patch_RunManager_RestartScene { private static void Prefix() { FreeCamManager.Instance?.PrepareForLevelTransition("RunManager.RestartScene"); } } } namespace AdvancedFreeCam.Network { internal static class FreeCamEventCodes { internal const byte VoiceState = 71; internal const byte GhostState = 72; } internal static class FreeCamGhostNetwork { private const string PayloadTag = "Kai.AdvancedFreeCam:GhostState"; private const int PayloadVersion = 1; private static readonly SendOptions UnreliableSendOptions; internal static void Register() { PhotonNetwork.NetworkingClient.EventReceived += OnEventReceived; } internal static void Unregister() { PhotonNetwork.NetworkingClient.EventReceived -= OnEventReceived; } internal static void SendState(bool active, Vector3 position, Quaternion rotation) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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_00bb: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if (PhotonNetwork.InRoom) { int[] targetActorsWithAdvancedFreeCam = FreeCamPlayerHandshake.GetTargetActorsWithAdvancedFreeCam(); if (targetActorsWithAdvancedFreeCam.Length != 0) { int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber; object[] array = new object[11] { "Kai.AdvancedFreeCam:GhostState", 1, actorNumber, active, position.x, position.y, position.z, rotation.x, rotation.y, rotation.z, rotation.w }; RaiseEventOptions val = new RaiseEventOptions { TargetActors = targetActorsWithAdvancedFreeCam }; PhotonNetwork.RaiseEvent((byte)72, (object)array, val, UnreliableSendOptions); } } } private static void OnEventReceived(EventData photonEvent) { //IL_0162: 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) if (photonEvent.Code != 72 || !(photonEvent.CustomData is object[] array) || array.Length < 11 || !(array[0] is string text) || text != "Kai.AdvancedFreeCam:GhostState") { return; } object obj = array[1]; if (!(obj is int)) { return; } int num = (int)obj; if (num != 1) { return; } obj = array[2]; if (!(obj is int)) { return; } int actorNumber = (int)obj; obj = array[3]; if (!(obj is bool)) { return; } bool active = (bool)obj; obj = array[4]; if (!(obj is float)) { return; } float num2 = (float)obj; obj = array[5]; if (!(obj is float)) { return; } float num3 = (float)obj; obj = array[6]; if (!(obj is float)) { return; } float num4 = (float)obj; obj = array[7]; if (!(obj is float)) { return; } float num5 = (float)obj; obj = array[8]; if (!(obj is float)) { return; } float num6 = (float)obj; obj = array[9]; if (obj is float) { float num7 = (float)obj; obj = array[10]; if (obj is float) { float num8 = (float)obj; Vector3 position = default(Vector3); ((Vector3)(ref position))..ctor(num2, num3, num4); Quaternion rotation = default(Quaternion); ((Quaternion)(ref rotation))..ctor(num5, num6, num7, num8); FreeCamGhostRegistry.Set(actorNumber, active, position, rotation); } } } static FreeCamGhostNetwork() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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) SendOptions unreliableSendOptions = default(SendOptions); ((SendOptions)(ref unreliableSendOptions)).Reliability = false; UnreliableSendOptions = unreliableSendOptions; } } internal static class FreeCamNetworkKeys { internal const string HasMod = "afc_mod"; internal const string ModVersion = "afc_ver"; internal const string RoomConfigVersion = "afc_cfg_ver"; internal const string AllowHostAliveFreeCam = "afc_h_alive"; internal const string AllowClientAliveFreeCam = "afc_c_alive"; internal const string AllowClientDeadFreeCam = "afc_c_dead"; internal const string AllowHostForceDisable = "afc_force"; internal const string AllowFreeCamVoice = "afc_voice"; internal const string AllowClientFreeCamVoice = "afc_c_voice"; internal const string GhostVisibleToAlivePlayers = "afc_g_alive"; internal const string GhostVisibleToSpectators = "afc_g_spec"; internal const string GhostVisibleToFreeCamPlayers = "afc_g_fc"; } internal static class FreeCamPlayerHandshake { internal const int CurrentProtocolVersion = 101; internal static void ApplyLocalProperties() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown if (PhotonNetwork.LocalPlayer != null) { Hashtable val = new Hashtable { [(object)"afc_mod"] = true, [(object)"afc_ver"] = 101 }; PhotonNetwork.LocalPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } internal static bool HasAdvancedFreeCam(Player? player) { if (player == null) { return false; } if (!((Dictionary<object, object>)(object)player.CustomProperties).TryGetValue((object)"afc_mod", out object value)) { return false; } if (!(value is bool) || !(bool)value) { return false; } return true; } internal static bool TryGetProtocolVersion(Player? player, out int version) { version = 0; if (player == null) { return false; } if (!((Dictionary<object, object>)(object)player.CustomProperties).TryGetValue((object)"afc_ver", out object value)) { return false; } if (!(value is int num)) { return false; } version = num; return true; } internal static int[] GetTargetActorsWithAdvancedFreeCam(bool includeSelf = false) { if (!PhotonNetwork.InRoom) { return Array.Empty<int>(); } List<int> list = new List<int>(); Player[] playerList = PhotonNetwork.PlayerList; foreach (Player val in playerList) { if ((includeSelf || !val.IsLocal) && HasAdvancedFreeCam(val)) { list.Add(val.ActorNumber); } } return list.ToArray(); } } internal static class FreeCamRoomConfigSync { private const int CurrentRoomConfigVersion = 1; internal static void PushHostConfigToRoom() { //IL_0016: 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_0034: 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_0067: 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) //IL_009b: 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_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown if (PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient) { FreeCamConfig instance = FreeCamConfig.Instance; Hashtable val = new Hashtable { [(object)"afc_cfg_ver"] = 1, [(object)"afc_h_alive"] = instance.AllowHostAliveFreeCam, [(object)"afc_c_alive"] = instance.AllowClientAliveFreeCam, [(object)"afc_c_dead"] = instance.AllowClientDeadFreeCam, [(object)"afc_force"] = instance.AllowHostForceDisable, [(object)"afc_g_alive"] = instance.GhostVisibleToAlivePlayers, [(object)"afc_g_spec"] = instance.GhostVisibleToSpectators, [(object)"afc_g_fc"] = instance.GhostVisibleToFreeCamPlayers }; PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } internal static bool TryApplyRoomConfigToRuntime() { if (!PhotonNetwork.InRoom) { return false; } Room currentRoom = PhotonNetwork.CurrentRoom; if (currentRoom == null) { return false; } Hashtable customProperties = ((RoomInfo)currentRoom).CustomProperties; if (customProperties == null || ((Dictionary<object, object>)(object)customProperties).Count == 0) { return false; } if (!((Dictionary<object, object>)(object)customProperties).TryGetValue((object)"afc_cfg_ver", out object value)) { return false; } if (!(value is int num) || num != 1) { return false; } FreeCamConfigSnapshot freeCamConfigSnapshot = new FreeCamConfigSnapshot { AllowHostAliveFreeCam = ReadBool(customProperties, "afc_h_alive", fallback: true), AllowClientAliveFreeCam = ReadBool(customProperties, "afc_c_alive", fallback: false), AllowClientDeadFreeCam = ReadBool(customProperties, "afc_c_dead", fallback: true), AllowHostForceDisable = ReadBool(customProperties, "afc_force", fallback: true), AllowFreeCamVoice = ReadBool(customProperties, "afc_voice", fallback: true), AllowClientFreeCamVoice = ReadBool(customProperties, "afc_c_voice", fallback: false), GhostVisibleToAlivePlayers = ReadBool(customProperties, "afc_g_alive", fallback: false), GhostVisibleToSpectators = ReadBool(customProperties, "afc_g_spec", fallback: true), GhostVisibleToFreeCamPlayers = ReadBool(customProperties, "afc_g_fc", fallback: true) }; freeCamConfigSnapshot.ApplyToRuntime(FreeCamConfig.Instance); return true; } private static bool ReadBool(Hashtable props, string key, bool fallback) { if (!((Dictionary<object, object>)(object)props).TryGetValue((object)key, out object value)) { return fallback; } if (value is bool) { return (bool)value; } return fallback; } } } namespace AdvancedFreeCam.Ghost { internal sealed class FreeCamGhost { private readonly int _actorNumber; private readonly GameObject _root; private readonly Transform _transform; private GameObject _visualRoot; private bool _usingFallback; internal int ActorNumber => _actorNumber; internal Transform Transform => _transform; internal GameObject Root => _root; internal bool UsingFallback => _usingFallback; internal FreeCamGhost(int actorNumber, Vector3 position, Quaternion rotation) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_003f: 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) _actorNumber = actorNumber; _root = new GameObject($"AdvancedFreeCam_Ghost_{actorNumber}"); _transform = _root.transform; _transform.position = position; _transform.rotation = rotation; _visualRoot = FreeCamGhostVisualFactory.CreateDefault(_root.transform, _actorNumber, out _usingFallback); ApplyVisualOffset(); } private void ApplyVisualOffset() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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) if (!((Object)(object)_visualRoot == (Object)null)) { Transform transform = _visualRoot.transform; transform.localPosition += new Vector3(0f, -0.25f, 0f); } } internal void SetTransform(Vector3 position, Quaternion rotation) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) _transform.position = position; _transform.rotation = rotation; } internal void SetVisible(bool visible) { if ((Object)(object)_visualRoot != (Object)null) { _visualRoot.SetActive(visible); } } internal void TryRefreshVisual() { if (_usingFallback && !((Object)(object)FreeCamGhostVisualFactory.FindPlayerAvatarByActorNumber(_actorNumber) == (Object)null)) { if ((Object)(object)_visualRoot != (Object)null) { Object.Destroy((Object)(object)_visualRoot); } _visualRoot = FreeCamGhostVisualFactory.CreateDefault(_root.transform, _actorNumber, out _usingFallback); ApplyVisualOffset(); } } internal void Destroy() { Object.Destroy((Object)(object)_root); } } internal sealed class FreeCamGhostManager { private readonly Dictionary<int, FreeCamGhost> _ghosts = new Dictionary<int, FreeCamGhost>(); private const float RemoteStateTimeout = 0.5f; internal static FreeCamGhostManager? Instance { get; private set; } internal FreeCamGhostManager() { Instance = this; } internal void Tick() { //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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) int num = ((PhotonNetwork.LocalPlayer != null) ? PhotonNetwork.LocalPlayer.ActorNumber : (-1)); HashSet<int> hashSet = new HashSet<int>(); foreach (KeyValuePair<int, FreeCamGhostState> item in FreeCamGhostRegistry.GetAll()) { int key = item.Key; FreeCamGhostState value = item.Value; if (key == num) { RemoveGhost(key); FreeCamGhostRegistry.Remove(key); continue; } hashSet.Add(key); bool flag = Time.time - value.LastUpdatedTime > 0.5f; if (!value.IsActive || flag) { if (_ghosts.TryGetValue(key, out FreeCamGhost value2)) { value2.SetVisible(visible: false); } } else { FreeCamGhost orCreateGhost = GetOrCreateGhost(key, value.Position, value.Rotation); orCreateGhost.SetTransform(value.Position, value.Rotation); orCreateGhost.TryRefreshVisual(); orCreateGhost.SetVisible(ShouldGhostBeVisible()); } } foreach (KeyValuePair<int, FreeCamGhost> ghost in _ghosts) { if (!hashSet.Contains(ghost.Key)) { ghost.Value.SetVisible(visible: false); } } } internal void ClearAll() { foreach (FreeCamGhost value in _ghosts.Values) { value.Destroy(); } _ghosts.Clear(); FreeCamGhostRegistry.ClearAll(); } internal void RemoveGhost(int actorNumber) { if (_ghosts.TryGetValue(actorNumber, out FreeCamGhost value)) { value.Destroy(); _ghosts.Remove(actorNumber); } } private FreeCamGhost GetOrCreateGhost(int actorNumber, Vector3 position, Quaternion rotation) { //IL_0013: 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) if (_ghosts.TryGetValue(actorNumber, out FreeCamGhost value)) { return value; } value = new FreeCamGhost(actorNumber, position, rotation); _ghosts[actorNumber] = value; return value; } internal void PrewarmFromPlayerList() { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)GameDirector.instance == (Object)null) { return; } int num = ((PhotonNetwork.LocalPlayer != null) ? PhotonNetwork.LocalPlayer.ActorNumber : (-1)); foreach (PlayerAvatar player in GameDirector.instance.PlayerList) { if ((Object)(object)player == (Object)null) { continue; } PhotonView component = ((Component)player).GetComponent<PhotonView>(); if (!((Object)(object)component == (Object)null) && component.Owner != null) { int actorNumber = component.Owner.ActorNumber; if (actorNumber != num && !_ghosts.ContainsKey(actorNumber)) { Transform transform = ((Component)player).transform; FreeCamGhost orCreateGhost = GetOrCreateGhost(actorNumber, transform.position, transform.rotation); orCreateGhost.SetVisible(visible: false); } } } } private bool ShouldGhostBeVisible() { if (FreeCamManager.Instance != null && FreeCamManager.Instance.IsActive) { return FreeCamPolicy.ShouldGhostBeVisibleToFreeCamViewer(); } if ((Object)(object)PlayerAvatar.instance != (Object)null && PlayerAvatar.instance.isDisabled) { return FreeCamPolicy.ShouldGhostBeVisibleToSpectatorViewer(); } return FreeCamPolicy.ShouldGhostBeVisibleToAliveViewer(); } } internal static class FreeCamGhostMaterialTuner { private static readonly Color BaseTint = new Color(0.78f, 0.9f, 1f, 0.72f); private static readonly Color EmissionTint = new Color(0.25f, 0.55f, 0.9f, 1f); private const float EmissionIntensity = 1.8f; internal static void ApplyGhostLook(Renderer renderer) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown if ((Object)(object)renderer == (Object)null) { return; } Material[] materials = renderer.materials; Material[] array = (Material[])(object)new Material[materials.Length]; for (int i = 0; i < materials.Length; i++) { Material val = materials[i]; if (!((Object)(object)val == (Object)null)) { Material val2 = new Material(val); ApplyBaseColor(val2); ApplyEmission(val2); ApplyTransparency(val2); array[i] = val2; } } renderer.materials = array; } private static void ApplyBaseColor(Material mat) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) if (mat.HasProperty("_Color")) { Color color = mat.GetColor("_Color"); Color val = Color.Lerp(color, BaseTint, 0.45f); val.a = BaseTint.a; mat.SetColor("_Color", val); } if (mat.HasProperty("_BaseColor")) { Color color2 = mat.GetColor("_BaseColor"); Color val2 = Color.Lerp(color2, BaseTint, 0.45f); val2.a = BaseTint.a; mat.SetColor("_EmissionColor", EmissionTint * 1.8f); } } private static void ApplyEmission(Material mat) { //IL_001f: 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) if (mat.HasProperty("_EmissionColor")) { mat.EnableKeyword("_EMISSION"); mat.SetColor("_EmissionColor", EmissionTint); DynamicGI.SetEmissive((Renderer)null, EmissionTint); } } private static void ApplyTransparency(Material mat) { if (mat.HasProperty("_Surface")) { try { mat.SetFloat("_Surface", 1f); } catch { } } } } internal sealed class FreeCamGhostNameTag : MonoBehaviour { private Camera _targetCamera; private Transform _followTarget; private Vector3 _offset; internal void Initialize(Transform followTarget, Vector3 offset) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) _followTarget = followTarget; _offset = offset; } private void LateUpdate() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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) if ((Object)(object)_followTarget != (Object)null) { ((Component)this).transform.position = _followTarget.position + _offset; } if ((Object)(object)_targetCamera == (Object)null) { _targetCamera = Camera.main; } if (!((Object)(object)_targetCamera == (Object)null)) { Vector3 val = ((Component)this).transform.position - ((Component)_targetCamera).transform.position; if (((Vector3)(ref val)).sqrMagnitude > 0.0001f) { ((Component)this).transform.rotation = Quaternion.LookRotation(((Vector3)(ref val)).normalized, Vector3.up); } } } } internal static class FreeCamGhostPoseApplier { internal static void Apply(GameObject root, FreeCamGhostPoseData pose) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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) int num = 0; int num2 = 0; foreach (FreeCamGhostPoseNode node in pose.Nodes) { Transform val = FindDeepChild(root.transform, node.Name); if ((Object)(object)val == (Object)null) { num2++; AdvancedFreeCam.Logger.LogWarning((object)("[GhostPose] Missing node: " + node.Name)); continue; } val.localPosition = node.LocalPosition; val.localRotation = node.LocalRotation; val.localScale = node.LocalScale; num++; } AdvancedFreeCam.Logger.LogInfo((object)$"[GhostPose] Applied={num}, Missed={num2}"); } private static Transform? FindDeepChild(Transform parent, string targetName) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown if (((Object)parent).name == targetName) { return parent; } foreach (Transform item in parent) { Transform parent2 = item; Transform val = FindDeepChild(parent2, targetName); if ((Object)(object)val != (Object)null) { return val; } } return null; } } internal sealed class FreeCamGhostPoseNode { public string Name = ""; public Vector3 LocalPosition; public Quaternion LocalRotation; public Vector3 LocalScale; } internal sealed class FreeCamGhostPoseData { public readonly List<FreeCamGhostPoseNode> Nodes = new List<FreeCamGhostPoseNode>(); } internal static class FreeCamGhostPoseLibrary { private static FreeCamGhostPoseData? _crawl; internal static FreeCamGhostPoseData Crawl => _crawl ?? (_crawl = BuildCrawl()); private static FreeCamGhostPoseData BuildCrawl() { //IL_001b: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0094: 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_00cc: 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_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_014b: 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_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) FreeCamGhostPoseData freeCamGhostPoseData = new FreeCamGhostPoseData(); Add(freeCamGhostPoseData, "ANIM BOT", new Vector3(0f, 0f, 0f), new Quaternion(0f, 0f, 0f, 1f), new Vector3(0.9f, 0.9f, 0.9f)); Add(freeCamGhostPoseData, "ANIM BODY BOT", new Vector3(0f, -0.507f, 0f), new Quaternion(0f, 0f, 0f, 1f), new Vector3(1f, 1f, 1f)); Add(freeCamGhostPoseData, "ANIM BODY TOP", new Vector3(0f, -0.289f, 0f), new Quaternion(0f, 0f, 0f, 1f), new Vector3(1f, 1f, 1f)); Add(freeCamGhostPoseData, "ANIM HEAD BOT", new Vector3(0f, -0.358802f, 0f), new Quaternion(0f, 0f, 0f, 1f), new Vector3(1f, 1f, 1f)); Add(freeCamGhostPoseData, "ANIM HEAD TOP", new Vector3(0f, 0f, 0f), new Quaternion(0f, 0f, 0f, 1f), new Vector3(1f, 1f, 1f)); Add(freeCamGhostPoseData, "ANIM EYE LEFT", new Vector3(0f, 0f, 0f), new Quaternion(0f, 0f, 0f, 1f), new Vector3(1f, 1f, 1f)); Add(freeCamGhostPoseData, "ANIM EYE RIGHT", new Vector3(0f, 0f, 0f), new Quaternion(0f, 0f, 0f, 1f), new Vector3(1f, 1f, 1f)); return freeCamGhostPoseData; } private static void Add(FreeCamGhostPoseData pose, string name, Vector3 localPosition, Quaternion localRotation, Vector3 localScale) { //IL_0013: 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_001a: 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_0021: 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) pose.Nodes.Add(new FreeCamGhostPoseNode { Name = name, LocalPosition = localPosition, LocalRotation = localRotation, LocalScale = localScale }); } } internal sealed class FreeCamGhostState { public bool IsActive; public Vector3 Position; public Quaternion Rotation = Quaternion.identity; public float LastUpdatedTime; public void Set(bool active, Vector3 position, Quaternion rotation) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) IsActive = active; Position = position; Rotation = rotation; LastUpdatedTime = Time.time; } } internal static class FreeCamGhostRegistry { private static readonly Dictionary<int, FreeCamGhostState> States = new Dictionary<int, FreeCamGhostState>(); internal static void Set(int actorNumber, bool active, Vector3 position, Quaternion rotation) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!States.TryGetValue(actorNumber, out FreeCamGhostState value)) { value = new FreeCamGhostState(); States[actorNumber] = value; } value.Set(active, position, rotation); } internal static bool TryGet(int actorNumber, out FreeCamGhostState state) { return States.TryGetValue(actorNumber, out state); } internal static IReadOnlyDictionary<int, FreeCamGhostState> GetAll() { return States; } internal static void Remove(int actorNumber) { States.Remove(actorNumber); } internal static void ClearAll() { States.Clear(); } } internal sealed class FreeCamGhostTalkAnimation : MonoBehaviour { private PlayerAvatar _avatar; private Transform _target; private Quaternion _baseLocalRotation; private float _rotationMaxAngle = 45f; private float _smooth = 100f; internal void Initialize(PlayerAvatar avatar, Transform target, float rotationMaxAngle = 45f) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) _avatar = avatar; _target = target; _rotationMaxAngle = rotationMaxAngle; if ((Object)(object)_target != (Object)null) { _baseLocalRotation = _target.localRotation; } } private void Update() { //IL_00a3: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_avatar == (Object)null) && !((Object)(object)_target == (Object)null) && GameManager.Multiplayer() && _avatar.voiceChatFetched && !((Object)(object)_avatar.voiceChat == (Object)null)) { float num = 0f; if (_avatar.voiceChat.clipLoudness > 0.005f && _avatar.voiceChat.overrideNoTalkAnimationTimer <= 0f) { num = Mathf.Lerp(0f, 0f - _rotationMaxAngle, _avatar.voiceChat.clipLoudness * 4f); } Quaternion val = _baseLocalRotation * Quaternion.Euler(num, 0f, 0f); _target.localRotation = Quaternion.Slerp(_target.localRotation, val, _smooth * Time.deltaTime); } } } internal static class FreeCamGhostVisualBuilder { private const string CrawlStateName = "Crawl"; private const float CrawlNormalizedTime = 1f; internal static void PrepareCloneAsGhost(GameObject root) { EnsureVisualRootVisible(root); ApplyAnimatorPose(root); DisableCloneBehaviours(root); ConfigureLights(root); ConfigureRenderers(root); } private static void EnsureVisualRootVisible(GameObject root) { PlayerAvatarVisuals component = root.GetComponent<PlayerAvatarVisuals>(); if (!((Object)(object)component == (Object)null) && (Object)(object)component.meshParent != (Object)null) { component.meshParent.SetActive(true); } } private static void ApplyAnimatorPose(GameObject root) { Animator component = root.GetComponent<Animator>(); if ((Object)(object)component == (Object)null) { AdvancedFreeCam.Logger.LogWarning((object)"[Ghost] Animator が見つかりません。"); return; } int num = Animator.StringToHash("Crawl"); if (!component.HasState(0, num)) { AdvancedFreeCam.Logger.LogWarning((object)"[Ghost] Animator State が見つかりません: Crawl"); return; } ((Behaviour)component).enabled = true; component.speed = 1f; component.Play(num, 0, 1f); component.Update(0f); component.Update(0.01f); component.speed = 0f; } private static void DisableCloneBehaviours(GameObject root) { //IL_003e: 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) MonoBehaviour[] componentsInChildren = root.GetComponentsInChildren<MonoBehaviour>(true); MonoBehaviour[] array = componentsInChildren; foreach (MonoBehaviour val in array) { ((Behaviour)val).enabled = false; } ParticleSystem[] componentsInChildren2 = root.GetComponentsInChildren<ParticleSystem>(true); ParticleSystem[] array2 = componentsInChildren2; foreach (ParticleSystem val2 in array2) { EmissionModule emission = val2.emission; ((EmissionModule)(ref emission)).enabled = false; val2.Stop(true, (ParticleSystemStopBehavior)0); ((Component)val2).gameObject.SetActive(false); } } private static void ConfigureLights(GameObject root) { Light[] componentsInChildren = root.GetComponentsInChildren<Light>(true); Light[] array = componentsInChildren; foreach (Light val in array) { string text = ((Object)((Component)val).gameObject).name.ToLowerInvariant(); if (text == "eye light") { ((Behaviour)val).enabled = true; } else { ((Behaviour)val).enabled = false; } } } private static void ConfigureRenderers(GameObject root) { Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true); Renderer[] array = componentsInChildren; foreach (Renderer val in array) { string objectName = ((Object)((Component)val).gameObject).name.ToLowerInvariant(); if (val.enabled = ShouldShowRenderer(objectName)) { val.shadowCastingMode = (ShadowCastingMode)0; val.receiveShadows = false; FreeCamGhostMaterialTuner.ApplyGhostLook(val); } } } private static bool ShouldShowRenderer(string objectName) { switch (objectName) { case "mesh_body_bot": return true; case "mesh_body_top_sphere": return true; case "mesh_body_top_flat": return true; case "mesh_head_bot_sphere": return true; case "mesh_head_bot_flat": return true; case "mesh_head_top": return true; case "mesh_eye_l": return true; case "mesh_eye_r": return true; case "mesh_pupil_l": return true; case "mesh_pupil_r": return true; case "eyelid_upper": return true; case "eyelid_lower": return true; case "mesh_arm_l": return false; case "mesh_arm_r": return false; case "mesh_leg_l": return false; case "mesh_leg_r": return false; default: if (objectName.Contains("mesh_health")) { return false; } if (objectName == "wing mesh") { return false; } if (objectName == "arenacrown") { return false; } if (objectName.Contains("mesh_grabber")) { return false; } objectName.Contains("orb sphere"); return false; } } } internal static class FreeCamGhostVisualCache { private static GameObject? _localCachedVisual; private static bool _rebuildRequested; private static int _waitFrames; internal static bool HasLocalCache => (Object)(object)_localCachedVisual != (Object)null; internal static void RequestRebuild(int waitFrames = 10) { _rebuildRequested = true; _waitFrames = waitFrames; } internal static void Tick() { if (_rebuildRequested && CanBuildNow()) { if (_waitFrames > 0) { _waitFrames--; return; } RebuildLocalCache(); _rebuildRequested = false; } } internal static void RebuildLocalCache() { if (!((Object)(object)PlayerAvatar.instance == (Object)null) && !((Object)(object)PlayerAvatar.instance.playerAvatarVisuals == (Object)null)) { PlayerAvatar instance = PlayerAvatar.instance; GameObject gameObject = ((Component)instance.playerAvatarVisuals).gameObject; GameObject val = Object.Instantiate<GameObject>(gameObject); FreeCamGhostVisualBuilder.PrepareCloneAsGhost(val); _localCachedVisual = val; AdvancedFreeCam.Logger.LogInfo((object)"[GhostCache] Rebuilt local cache."); } } internal static GameObject? InstantiateLocalCache(Transform parent) { if ((Object)(object)_localCachedVisual == (Object)null) { return null; } GameObject val = Object.Instantiate<GameObject>(_localCachedVisual, parent); val.SetActive(true); return val; } internal static void ClearLocalCache() { if ((Object)(object)_localCachedVisual != (Object)null) { Object.Destroy((Object)(object)_localCachedVisual); _localCachedVisual = null; } } private static bool CanBuildNow() { if (!SemiFunc.RunIsLevel() && !SemiFunc.RunIsArena() && !SemiFunc.RunIsShop() && !SemiFunc.RunIsRecording()) { return false; } if ((Object)(object)PlayerAvatar.instance == (Object)null) { return false; } if (PlayerAvatar.instance.isDisabled) { return false; } if ((Object)(object)PlayerAvatar.instance.playerAvatarVisuals == (Object)null) { return false; } return true; } } internal static class FreeCamGhostVisualFactory { internal static GameObject CreateDefault(Transform parent, int actorNumber, out bool usedFallback) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar val = FindPlayerAvatarByActorNumber(actorNumber); if ((Object)(object)val == (Object)null || (Object)(object)val.playerAvatarVisuals == (Object)null) { usedFallback = true; return CreateFallbackVisual(parent); } GameObject gameObject = ((Component)val.playerAvatarVisuals).gameObject; GameObject val2 = Object.Instantiate<GameObject>(gameObject); ((Object)val2).name = $"{((Object)gameObject).name}_FreeCamGhost_{actorNumber}"; val2.transform.SetParent(parent, false); val2.transform.localPosition = Vector3.zero; val2.transform.localRotation = Quaternion.identity; FreeCamGhostVisualBuilder.PrepareCloneAsGhost(val2); TryAttachTalkAnimation(val2, val); TryAttachNameTag(val2, val); usedFallback = false; return val2; } internal static PlayerAvatar? FindPlayerAvatarByActorNumber(int actorNumber) { if ((Object)(object)GameDirector.instance == (Object)null) { return null; } foreach (PlayerAvatar player in GameDirector.instance.PlayerList) { if (!((Object)(object)player == (Object)null)) { PhotonView component = ((Component)player).GetComponent<PhotonView>(); if (!((Object)(object)component == (Object)null) && component.Owner != null && component.Owner.ActorNumber == actorNumber) { return player; } } } return null; } private static GameObject CreateFallbackVisual(Transform parent) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_00d2: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("GhostFallbackVisual"); val.transform.SetParent(parent, false); GameObject val2 = GameObject.CreatePrimitive((PrimitiveType)0); ((Object)val2).name = "Head"; val2.transform.SetParent(val.transform, false); val2.transform.localPosition = new Vector3(0f, 1.4f, 0f); val2.transform.localScale = new Vector3(0.35f, 0.35f, 0.35f); GameObject val3 = GameObject.CreatePrimitive((PrimitiveType)1); ((Object)val3).name = "Body"; val3.transform.SetParent(val.transform, false); val3.transform.localPosition = new Vector3(0f, 0.75f, 0f); val3.transform.localScale = new Vector3(0.7f, 0.75f, 0.5f); DisableCollider(val2); DisableCollider(val3); return val; } private static void DisableCollider(GameObject obj) { Collider component = obj.GetComponent<Collider>(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } } private static void TryAttachTalkAnimation(GameObject clone, PlayerAvatar avatar) { if (!((Object)(object)clone == (Object)null) && !((Object)(object)avatar == (Object)null)) { PlayerAvatarTalkAnimation componentInChildren = clone.GetComponentInChildren<PlayerAvatarTalkAnimation>(true); if ((Object)(object)componentInChildren == (Object)null) { AdvancedFreeCam.Logger.LogWarning((object)"[Ghost] PlayerAvatarTalkAnimation が見つかりません。口パクを付けられません。"); return; } if ((Object)(object)componentInChildren.objectToRotate == (Object)null) { AdvancedFreeCam.Logger.LogWarning((object)"[Ghost] objectToRotate が null です。口パクを付けられません。"); return; } FreeCamGhostTalkAnimation freeCamGhostTalkAnimation = clone.AddComponent<FreeCamGhostTalkAnimation>(); freeCamGhostTalkAnimation.Initialize(avatar, componentInChildren.objectToRotate.transform, componentInChildren.rotationMaxAngle); } } private static void TryAttachNameTag(GameObject clone, PlayerAvatar avatar) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)clone == (Object)null) && !((Object)(object)avatar == (Object)null)) { string text = avatar.playerName; if (string.IsNullOrWhiteSpace(text)) { text = "Unknown"; } Transform val = FindHeadAnchor(clone); if ((Object)(object)val == (Object)null) { val = clone.transform; } Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(0f, 0.55f, 0f); GameObject val3 = new GameObject("GhostNameTag"); val3.transform.SetParent(clone.transform, false); val3.transform.position = val.position + val2; TextMeshPro val4 = val3.AddComponent<TextMeshPro>(); ((TMP_Text)val4).text = text; ((TMP_Text)val4).fontSize = 1.2f; ((TMP_Text)val4).alignment = (TextAlignmentOptions)514; ((Graphic)val4).color = Color.white; ((TMP_Text)val4).outlineWidth = 0.2f; ((TMP_Text)val4).enableWordWrapping = false; ((Graphic)val4).raycastTarget = false; FreeCamGhostNameTag freeCamGhostNameTag = val3.AddComponent<FreeCamGhostNameTag>(); freeCamGhostNameTag.Initialize(val, val2); } } private static Transform FindHeadAnchor(GameObject clone) { Transform[] componentsInChildren = clone.GetComponentsInChildren<Transform>(true); Transform[] array = componentsInChildren; foreach (Transform val in array) { string text = ((Object)val).name.ToLowerInvariant(); if (text.Contains("head") || text.Contains("helmet") || text.Contains("neck")) { return val; } } return clone.transform; } } } namespace AdvancedFreeCam.Core { internal sealed class FreeCamController { private const float DefaultLookSensitivity = 3f; private const float DefaultMoveSmooth = 8f; private const float DefaultRotateSmooth = 14f; private const float MinPitch = -89f; private const float MaxPitch = 89f; private bool _entered; private Vector3 _currentVelocity = Vector3.zero; private Vector3 _targetVelocity = Vector3.zero; private float _yaw; private float _pitch; internal float LookSensitivity { get; set; } = 3f; internal float MoveSmooth { get; set; } = 8f; internal float RotateSmooth { get; set; } = 14f; public void Enter(Vector3 startPosition, Quaternion startRotation) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) Vector3 eulerAngles = ((Quaternion)(ref startRotation)).eulerAngles; _pitch = NormalizeAngle(eulerAngles.x); _yaw = NormalizeAngle(eulerAngles.y); _pitch = Mathf.Clamp(_pitch, -89f, 89f); _currentVelocity = Vector3.zero; _targetVelocity = Vector3.zero; _entered = true; } public void Exit() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) _entered = false; _currentVelocity = Vector3.zero; _targetVelocity = Vector3.zero; } public void Tick(float deltaTime, Transform rigTransform, float moveSpeed) { if (_entered && !((Object)(object)rigTransform == (Object)null)) { UpdateRotation(deltaTime, rigTransform); UpdateMovement(deltaTime, rigTransform, moveSpeed); } } private void UpdateRotation(float deltaTime, Transform rigTransform) { //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_0013: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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) Vector2 val = ReadLookInput(); float freeCamLookSensitivity = FreeCamLocalConfig.GetFreeCamLookSensitivity(); _yaw += val.x * freeCamLookSensitivity; _pitch -= val.y * freeCamLookSensitivity; _pitch = Mathf.Clamp(_pitch, -89f, 89f); Quaternion val2 = Quaternion.Euler(_pitch, _yaw, 0f); rigTransform.rotation = Quaternion.Slerp(rigTransform.rotation, val2, RotateSmooth * deltaTime); } private void UpdateMovement(float deltaTime, Transform rigTransform, float moveSpeed) { //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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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_001b: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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_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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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) Vector3 val = ReadMoveInput(); _targetVelocity = val * moveSpeed; _currentVelocity = Vector3.Lerp(_currentVelocity, _targetVelocity, MoveSmooth * deltaTime); Quaternion val2 = Quaternion.Euler(0f, _yaw, 0f); Vector3 val3 = val2 * Vector3.forward; Vector3 val4 = val2 * Vector3.right; Vector3 val5 = val3 * _currentVelocity.z + val4 * _currentVelocity.x + Vector3.up * _currentVelocity.y; rigTransform.position += val5 * deltaTime; } private static Vector2 ReadLookInput() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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) Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y")); float freeCamMaxMouseDelta = FreeCamLocalConfig.GetFreeCamMaxMouseDelta(); val.x = Mathf.Clamp(val.x, 0f - freeCamMaxMouseDelta, freeCamMaxMouseDelta); val.y = Mathf.Clamp(val.y, 0f - freeCamMaxMouseDelta, freeCamMaxMouseDelta); return val; } private static Vector3 ReadMoveInput() { //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_000f: Unknown result type (might be due to invalid IL or missing references) //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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //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_002f: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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_0067: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.zero; if (Input.GetKey((KeyCode)119)) { val += Vector3.forward; } if (Input.GetKey((KeyCode)115)) { val += Vector3.back; } if (Input.GetKey((KeyCode)97)) { val += Vector3.left; } if (Input.GetKey((KeyCode)100)) { val += Vector3.right; } if (Input.GetKey(FreeCamLocalConfig.GetMoveUpKey())) { val += Vector3.up; } if (Input.GetKey(FreeCamLocalConfig.GetMoveDownKey())) { val += Vector3.down; } if (((Vector3)(ref val)).sqrMagnitude > 1f) { ((Vector3)(ref val)).Normalize(); } return val; } private static float NormalizeAngle(float angle) { if (angle > 180f) { angle -= 360f; } return angle; } } internal static class FreeCamLocalBodyMeshController { private static bool _wasEnabledByFreeCam; internal static void ShowHiddenLocalMeshes() { PlayerAvatarVisuals val = PlayerAvatar.instance?.playerAvatarVisuals; if (!((Object)(object)val == (Object)null) && !((Object)(object)val.meshParent == (Object)null) && (!val.meshParent.activeSelf || !((Object)(object)val.animator != (Object)null) || !((Behaviour)val.animator).enabled)) { val.meshParent.SetActive(true); if ((Object)(object)val.animator != (Object)null) { ((Behaviour)val.animator).enabled = true; } _wasEnabledByFreeCam = true; } } internal static void HideRestoredLocalMeshes() { if (!_wasEnabledByFreeCam) { return; } PlayerAvatarVisuals val = PlayerAvatar.instance?.playerAvatarVisuals; if ((Object)(object)val == (Object)null) { _wasEnabledByFreeCam = false; return; } if ((Object)(object)val.animator != (Object)null) { ((Behaviour)val.animator).enabled = false; } if ((Object)(object)val.meshParent != (Object)null) { val.meshParent.SetActive(false); } _wasEnabledByFreeCam = false; } } internal sealed class FreeCamManager { private readonly FreeCamController _controller = new FreeCamController(); private readonly FreeCamRig _rig = new FreeCamRig(); private FreeCamState _state; private float _currentMoveSpeed = -1f; private float _speedLogTimer; private Transform? _cameraAimTransform; private Transform? _originalParent; private Vector3 _originalLocalPosition; private Quaternion _originalLocalRotation; private bool _isPreparingLevelTransition; private string _lastCleanupLogReason; private float _lastCleanupLogTime = -999f; internal static FreeCamManager? Instance { get; private set; } public bool IsActive => _state == FreeCamState.Active; public Vector3 CurrentPosition { get { //IL_001c: 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) Transform transform = _rig.Transform; if (!((Object)(object)transform != (Object)null)) { return Vector3.zero; } return transform.position; } } public Vector3 CurrentVoicePosition { get { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) Transform transform = _rig.Transform; if ((Object)(object)transform != (Object)null && IsActive) { return transform.position; } Camera val = (((Object)(object)GameDirector.instance != (Object)null) ? GameDirector.instance.MainCamera : null); if ((Object)(object)val != (Object)null) { return ((Component)val).transform.position; } return Vector3.zero; } } public FreeCamManager() { Instance = this; } public void Tick(float deltaTime) { if (!ValidateGameState()) { return; } HandleInput(); if (IsActive) { TickActive(deltaTime); if (FreeCamPhotoMode.IsEnabled) { FreeCamPhotoMode.Tick(); } } } public void ToggleFreeCam() { if (IsActive) { DisableFreeCam(); } else { EnableFreeCam(); } } public void EnableFreeCam() { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_009c: 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) if (IsActive) { return; } _isPreparingLevelTransition = false; if (CanUseFreeCamNow() && FreeCamPolicy.CanToggleFreeCam() && !((Object)(object)CameraAim.Instance == (Object)null)) { _cameraAimTransform = ((Component)CameraAim.Instance).transform; CacheOriginalCameraParent(); _rig.EnsureCreated(); Transform transform = _rig.Transform; if (!((Object)(object)transform == (Object)null)) { transform.position = _cameraAimTransform.position; transform.rotation = _cameraAimTransform.rotation; _cameraAimTransform.SetParent(transform, true); _controller.Enter(transform.position, transform.rotation); _state = FreeCamState.Active; FreeCamLocalBodyMeshController.ShowHiddenLocalMeshes(); AdvancedFreeCam.Logger.LogInfo((object)"FreeCam Enabled"); } } } public void DisableFreeCam() { //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) if (IsActive) { FreeCamPhotoMode.Disable(); if (SemiFunc.IsMultiplayer()) { FreeCamGhostNetwork.SendState(active: false, Vector3.zero, Quaternion.identity); } CleanupInternal(resetAimDisable: true); FreeCamLocalBodyMeshController.HideRestoredLocalMeshes(); AdvancedFreeCam.Logger.LogInfo((object)"FreeCam Disabled"); } } public void ForceCleanup(string reason = "") { //IL_0035: 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) bool flag = IsActive || _rig.IsValid || (Object)(object)_cameraAimTransform != (Object)null; if (SemiFunc.IsMultiplayer() && IsActive) { FreeCamGhostNetwork.SendState(active: false, Vector3.zero, Quaternion.identity); } CleanupInternal(resetAimDisable: true); if (flag) { LogCleanupReasonOnce("FreeCam cleanup", reason); } } public void PrepareForLevelTransition(string reason = "") { //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) bool flag = IsActive || _rig.IsValid || (Object)(object)_cameraAimTransform != (Object)null || FreeCamPhotoMode.IsEnabled; _isPreparingLevelTransition = true; if (SemiFunc.IsMultiplayer() && IsActive) { FreeCamGhostNetwork.SendState(active: false, Vector3.zero, Quaternion.identity); } FreeCamPhotoMode.ForceReset(isChangeLevel: true); _controller.Exit(); _state = FreeCamState.Disabled; if (flag) { LogCleanupReasonOnce("FreeCam prepare level transition", reason); } } private void LogCleanupReasonOnce(string prefix, string reason) { if (!string.IsNullOrWhiteSpace(reason) && (!(_lastCleanupLogReason == reason) || !(Time.unscaledTime - _lastCleanupLogTime < 0.5f))) { _lastCleanupLogReason = reason; _lastCleanupLogTime = Time.unscaledTime; AdvancedFreeCam.Logger.LogWarning((object)(prefix + ": " + reason)); } } private bool ValidateGameState() { if (CanUseFreeCamNow()) { if (_isPreparingLevelTransition) { _isPreparingLevelTransition = false; FinalizePreparedTransitionCleanup(); } return true; } if (_isPreparingLevelTransition) { return false; } if (IsActive || _rig.IsValid || (Object)(object)_cameraAimTransform != (Object)null) { ForceCleanup("Invalid game state"); } return false; } private void HandleSpeedWheelInput() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) if (IsActive && ((!Input.GetKey((KeyCode)308) && !Input.GetKey((KeyCode)307)) || !FreeCamPhotoMode.IsEnabled)) { EnsureMoveSpeedInitialized(); float y = Input.mouseScrollDelta.y; if (!(Mathf.Abs(y) <= 0.001f)) { float freeCamMouseWheelSpeedStep = FreeCamLocalConfig.GetFreeCamMouseWheelSpeedStep(); float freeCamMinMoveSpeed = FreeCamLocalConfig.GetFreeCamMinMoveSpeed(); float freeCamMaxMoveSpeed = FreeCamLocalConfig.GetFreeCamMaxMoveSpeed(); _currentMoveSpeed = Mathf.Clamp(_currentMoveSpeed + y * freeCamMouseWheelSpeedStep, freeCamMinMoveSpeed, freeCamMaxMoveSpeed); AdvancedFreeCam.Logger.LogInfo((object)$"FreeCam speed: {_currentMoveSpeed:0.0}"); } } } private void EnsureMoveSpeedInitialized() { if (!(_currentMoveSpeed > 0f)) { _currentMoveSpeed = FreeCamLocalConfig.GetFreeCamBaseMoveSpeed(); } } private void FinalizePreparedTransitionCleanup() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //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) _rig.Destroy(); _cameraAimTransform = null; _originalParent = null; _originalLocalPosition = Vector3.zero; _originalLocalRotation = Quaternion.identity; } private void HandleInput() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(FreeCamLocalConfig.GetToggleFreeCamKey())) { if (!IsActive && !FreeCamPolicy.CanToggleFreeCam()) { AdvancedFreeCam.Logger.LogInfo((object)"FreeCam denied by policy"); } else { ToggleFreeCam(); } } else { if (!IsActive) { return; } HandleSpeedWheelInput(); if (Input.GetKeyDown(FreeCamLocalConfig.GetTogglePhotoModeKey())) { FreeCamPhotoMode.Toggle(); } if (FreeCamPhotoMode.IsEnabled && (Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307))) { float y = Input.mouseScrollDelta.y; if (Mathf.Abs(y) > 0.001f) { float photoModeNightVision = FreeCamLocalConfig.GetPhotoModeNightVision(); float num = Mathf.Clamp(photoModeNightVision + y * 5f, 0f, 100f); AdvancedFreeCam.Instance.SetPhotoModeNightVision(num); FreeCamPhotoMode.ApplyNightVisionOnly(); AdvancedFreeCam.Logger.LogInfo((object)$"PhotoMode NightVision: {num:0}"); } } } } private void TickActive(float deltaTime) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) CameraAim instance = CameraAim.Instance; if (instance != null) { instance.OverridePlayerAimDisable(true); } PlayerController instance2 = PlayerController.instance; if (instance2 != null) { instance2.InputDisable(0.1f); } Transform transform = _rig.Transform; if ((Object)(object)transform == (Object)null || (Object)(object)_cameraAimTransform == (Object)null || (Object)(object)CameraAim.Instance == (Object)null) { ForceCleanup("Lost references while active"); return; } EnsureMoveSpeedInitialized(); float num = _currentMoveSpeed; if (Input.GetKey(FreeCamLocalConfig.GetFastMoveKey())) { num *= FreeCamLocalConfig.GetFreeCamFastMoveMultiplier(); } _controller.Tick(deltaTime, transform, num); ApplyRigToCameraAim(); if (SemiFunc.IsMultiplayer()) { FreeCamGhostNetwork.SendState(active: true, transform.position, transform.rotation); } } private void CacheOriginalCameraParent() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_cameraAimTransform == (Object)null)) { _originalParent = _cameraAimTransform.parent; _originalLocalPosition = _cameraAimTransform.localPosition; _originalLocalRotation = _cameraAimTransform.localRotation; } } private void CleanupInternal(bool resetAimDisable) { //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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) FreeCamPhotoMode.ForceReset(); RestoreCameraAimSafe(resetAimDisable); _rig.Destroy(); _controller.Exit(); _cameraAimTransform = null; _originalParent = null; _originalLocalPosition = Vector3.zero; _originalLocalRotation = Quaternion.identity; _state = FreeCamState.Disabled; } private bool CanUseFreeCamNow() { if ((Object)(object)RunManager.instance == (Object)null) { return false; } if (RunManager.instance.restarting) { return false; } if (!SemiFunc.RunIsLevel() && !SemiFunc.RunIsShop() && !SemiFunc.RunIsArena() && !SemiFunc.RunIsRecording()) { return false; } if ((Object)(object)PlayerController.instance == (Object)null) { return false; } if ((Object)(object)PlayerAvatar.instance == (Object)null) { return false; } if ((Object)(object)CameraAim.Instance == (Object)null) { return false; } return true; } private void RestoreCameraAimSafe(bool resetAimDisable) { //IL_0037: 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) if ((Object)(object)_cameraAimTransform == (Object)null) { return; } try { if ((Object)(object)_originalParent != (Object)null) { _cameraAimTransform.SetParent(_originalParent, true); _cameraAimTransform.localPosition = _originalLocalPosition; _cameraAimTransform.localRotation = _originalLocalRotation; } else { _cameraAimTransform.SetParent((Transform)null, true); } if (resetAimDisable && (Object)(object)CameraAim.Instance != (Object)null) { CameraAim.Instance.OverridePlayerAimDisableReset(); } } catch (Exception arg) { AdvancedFreeCam.Logger.LogWarning((object)$"RestoreCameraAimSafe failed: {arg}"); } } private void ApplyRigToCameraAim() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_cameraAimTransform == (Object)null)) { _cameraAimTransform.localPosition = Vector3.zero; _cameraAimTransform.localRotation = Quaternion.identity; } } } internal static class FreeCamPhotoMode { private static bool _enabled; private static bool _savedFog; private static bool _fogSaved; private static float _savedFarClipPlane; private static bool _farClipSaved; private static float _savedShadowDistance; private static bool _shadowDistanceSaved; private static float _savedLodBias; private static bool _lodBiasSaved; private static int _savedMaximumLodLevel; private static bool _maximumLodLevelSaved; private static Color _savedAmbientLight; private static bool _ambientLightSaved; private static MenuSpectateList _menuSpectateList; private static SpectateHeadUI _spectateHeadUI; private static SpectateNameUI _spectateNameUI; private static readonly List<GameObject> _disabledMenuPlayerListedObjects = new List<GameObject>(); private const float PhotoModeFarClipPlane = 500f; private const float PhotoModeShadowDistance = 300f; private const float PhotoModeLodBias = 3f; private const int PhotoModeMaximumLodLevel = 0; internal static bool IsEnabled => _enabled; internal static void Toggle() { if (_enabled) { Disable(); } else { Enable(); } } internal static void LateTick() { if (IsEnabled) { ApplyPhotoModeValues(); ApplyNightVision(); } } internal static void Enable() { if (!_enabled) { _enabled = true; SaveCurrentValues(); CacheUIReferences(); ApplyPhotoModeValues(); ApplyNightVision(); HidePhotoModeUI(); HidePhotoModeEquipment(); AdvancedFreeCam.Logger.LogInfo((object)"FreeCam PhotoMode Enabled"); } } internal static void Disable() { if (_enabled) { _enabled = false; RestoreSavedValues(); ClearSavedFlags(); RestorePhotoModeUI(); RestorePhotoModeEquipment(); ResetCachedReferences(); AdvancedFreeCam.Logger.LogInfo((object)"FreeCam PhotoMode Disabled"); } } internal static void ForceReset(bool isChangeLevel = false) { _enabled = false; if (isChangeLevel) { ClearSavedFlags(); ResetCachedReferences(); return; } RestoreSavedValues(); ClearSavedFlags(); RestorePhotoModeUI(); RestorePhotoModeEquipment(); ResetCachedReferences(); } internal static void Tick() { if (_enabled) { ApplyPhotoModeValues(); ApplyNightVision(); HidePhotoModeUI(); HidePhotoModeEquipment(); } } internal static void ApplyNightVisionOnly() { if (_enabled) { ApplyNightVision(); } } private static void SaveCurrentValues() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) _savedFog = RenderSettings.fog; _fogSaved = true; Camera mainCamera = GetMainCamera(); if ((Object)(object)mainCamera != (Object)null) { _savedFarClipPlane = mainCamera.farClipPlane; _farClipSaved = true; } else { _farClipSaved = false; } _savedShadowDistance = QualitySettings.shadowDistance; _shadowDistanceSaved = true; _savedLodBias = QualitySettings.lodBias; _lodBiasSaved = true; _savedMaximumLodLevel = QualitySettings.maximumLODLevel; _maximumLodLevelSaved = true; _savedAmbientLight = RenderSettings.ambientLight; _ambientLightSaved = true; } private static void ApplyPhotoModeValues() { Camera main = Camera.main; if (!((Object)(object)main == (Object)null)) { RenderSettings.fog = false; main.farClipPlane = 500f; QualitySettings.shadowDistance = 300f; QualitySettings.lodBias = Mathf.Max(QualitySettings.lodBias, 3f); QualitySettings.maximumLODLevel = 0; } } private static void ApplyNightVision() { //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_0031: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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) float num = Mathf.Clamp(FreeCamLocalConfig.GetPhotoModeNightVision(), 0f, 100f); if (!(num <= 0.001f)) { float num2 = Mathf.Clamp01(num / 100f); Color ambientLight = RenderSettings.ambientLight; Color ambientLight2 = Color.Lerp(ambientLight, Color.white * 2f, num2); RenderSettings.ambientLight = ambientLight2; } } private static void RestoreSavedValues() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) if (_fogSaved) { RenderSettings.fog = _savedFog; } Camera mainCamera = GetMainCamera(); if ((Object)(object)mainCamera != (Object)null && _farClipSaved) { mainCamera.farClipPlane = _savedFarClipPlane; } if (_shadowDistanceSaved) { QualitySettings.shadowDistance = _savedShadowDistance; } if (_lodBiasSaved) { QualitySettings.lodBias = _savedLodBias; } if (_maximumLodLevelSaved) { QualitySettings.maximumLODLevel = _savedMaximumLodLevel; } if (_ambientLightSaved) { RenderSettings.ambientLight = _savedAmbientLight; } } private static void ClearSavedFlags() { _fogSaved = false; _farClipSaved = false; _shadowDistanceSaved = false; _lodBiasSaved = false; _maximumLodLevelSaved = false; _ambientLightSaved = false; } private static void CacheUIReferences() { if ((Object)(object)_menuSpectateList == (Object)null) { _menuSpectateList = Object.FindObjectOfType<MenuSpectateList>(true); } if ((Object)(object)_spectateHeadUI == (Object)null) { _spectateHeadUI = SpectateHeadUI.instance; if ((Object)(object)_spectateHeadUI == (Object)null) { _spectateHeadUI = Object.FindObjectOfType<SpectateHeadUI>(true); } } if ((Object)(object)_spectateNameUI == (Object)null) { _spectateNameUI = SpectateNameUI.instance; if ((Object)(object)_spectateNameUI == (Object)null) { _spectateNameUI = Object.FindObjectOfType<SpectateNameUI>(true); } } } private static void HidePhotoModeUI() { if ((Object)(object)HUD.instance != (Object)null) { HUD.instance.Hide(); } if ((Object)(object)MissionUI.instance != (Object)null) { ((SemiUI)MissionUI.instance).Hide(); } if ((Object)(object)BatteryUI.instance != (Object)null) { ((SemiUI)BatteryUI.instance).Hide(); } if ((Object)(object)_spectateNameUI != (Object)null) { ((SemiUI)_spectateNameUI).Hide(); } if ((Object)(object)_spectateHeadUI != (Object)null) { ((SemiUI)_spectateHeadUI).Hide(); } if ((Object)(object)_menuSpectateList != (Object)null) { ((SemiUI)_menuSpectateList).Hide(); HideMenuPlayerListedChildren(); } SemiFunc.UIHideHealth(); SemiFunc.UIHideOvercharge(); SemiFunc.UIHideEnergy(); SemiFunc.UIHideInventory(); SemiFunc.UIHideHaul(); SemiFunc.UIHideGoal(); SemiFunc.UIHideCurrency(); SemiFunc.UIHideAim(); SemiFunc.UIHideTumble(); SemiFunc.UIHideWorldSpace(); SemiFunc.UIHideValuableDiscover(); SemiFunc.UIHideShopCost(); } private static void HideMenuPlayerListedChildren() { for (int i = 0; i < _menuSpectateList.listObjects.Count; i++) { GameObject val = _menuSpectateList.listObjects[i]; if (!((Object)(object)val == (Object)null) && val.activeSelf) { val.SetActive(false); if (!_disabledMenuPlayerListedObjects.Contains(val)) { _disabledMenuPlayerListedObjects.Add(val); } } } } private static void RestorePhotoModeUI() { if ((Object)(object)HUD.instance != (Object)null) { HUD.instance.Show(); } if ((Object)(object)_menuSpectateList != (Object)null) { ((Behaviour)_menuSpectateList).enabled = true; ((SemiUI)_menuSpectateList).Show(); } for (int i = 0; i < _disabledMenuPlayerListedObjects.Count; i++) { GameObject val = _disabledMenuPlayerListedObjects[i]; if (!((Object)(object)val == (Object)null) && !val.activeSelf) { val.SetActive(true); } } _disabledMenuPlayerListedObjects.Clear(); if ((Object)(object)_spectateNameUI != (Object)null) { ((Behaviour)_spectateNameUI).enabled = true; ((SemiUI)_spectateNameUI).Show(); } if ((Object)(object)_spectateHeadUI != (Object)null) { ((Behaviour)_spectateHeadUI).enabled = true; ((SemiUI)_spectateHeadUI).Show(); } if ((Object)(object)SpectateCamera.instance != (Object)null) { SemiFunc.UIShowSpectate(); } } private static void HidePhotoModeEquipment() { FlashlightController instance = FlashlightController.Instance; if (!((Object)(object)instance == (Object)null)) { instance.hideFlashlight = true; instance.active = false; instance.LightActive = false; if ((Object)(object)instance.mesh != (Object)null) { ((Renderer)instance.mesh).enabled = false; } if ((Object)(object)instance.spotlight != (Object)null) { ((Behaviour)instance.spotlight).enabled = false; } if ((Object)(object)instance.halo != (Object)null) { instance.halo.enabled = false; } } } private static void RestorePhotoModeEquipment() { FlashlightController instance = FlashlightController.Instance; if (!((Object)(object)instance == (Object)null)) { instance.hideFlashlight = false; } } private static void ResetCachedReferences() { _menuSpectateList = null; _spectateHeadUI = null; _spectateNameUI = null; _disabledMenuPlayerListedObjects.Clear(); } private static Camera GetMainCamera() { if ((Object)(object)GameDirector.instance != (Object)null && (Object)(object)GameDirector.instance.MainCamera != (Object)null) { return GameDirector.instance.MainCamera; } return Camera.main; } } [HarmonyPatch(typeof(SemiFunc), "UIShowSpectate")] internal static class Patch_SemiFunc_UIShowSpectate_PhotoModeBlock { private static bool Prefix() { return !FreeCamPhotoMode.IsEnabled; } } internal static class Patch_MenuSpectateList_PhotoModeBlock { private static bool Prefix(MenuSpectateList __instance) { if (!FreeCamPhotoMode.IsEnabled) { return true; } ((SemiUI)__instance).Hide(); return false; } } [HarmonyPatch(typeof(MenuPlayerListed), "Update")] internal static class Patch_MenuPlayerListed_PhotoModeBlock { private static bool Prefix() { return !FreeCamPhotoMode.IsEnabled; } } [HarmonyPatch(typeof(LobbyChatUI), "Update")] internal static class Patch_LobbyChatUI_PhotoModeBlock { private static bool Prefix(LobbyChatUI __instance) { if (!FreeCamPhotoMode.IsEnabled) { return true; } ((SemiUI)__instance).Hide(); return false; } } [HarmonyPatch(typeof(MenuPlayerHead), "Update")] internal static class Patch_MenuPlayerHead_PhotoModeBlock { private static bool Prefix() { return !FreeCamPhotoMode.IsEnabled; } } internal se