using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn.Entities; using Jotunn.Extensions; using Jotunn.Managers; using Jotunn.Utils; using SwimmingReworked.Effects; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("SwimmingReworked")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("SwimmingReworked")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("1.0.5")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.5.0")] namespace SwimmingReworked { internal class BreathHud : MonoBehaviour { private GameObject _root; private RectTransform _container; private readonly List _bubbles = new List(); private Sprite _bubbleSprite; private Text _breathText; private const int BubbleCount = 10; private float _cachedOffsetX; private float _cachedOffsetY; private float _cachedScale; private bool _cachedShowLabels; private void Awake() { CreateHud(); } private void Update() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)Camera.main == (Object)null) { SetVisible(visible: false); return; } CheckConfigChanges(); float currentBreath = SwimAPI.GetCurrentBreath(localPlayer); float maxBreath = SwimAPI.GetMaxBreath(localPlayer); float percent = Mathf.Clamp01(SwimAPI.GetBreathPercent(localPlayer)); bool flag = WaterHelper.IsBodyInWater(localPlayer) || currentBreath < maxBreath - 0.01f; SetVisible(flag); if (flag) { UpdateBubbles(percent); if ((Object)(object)_breathText != (Object)null && ((Component)_breathText).gameObject.activeSelf) { _breathText.text = $"{currentBreath:F0}/{maxBreath:F0}"; } } } private void CheckConfigChanges() { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)SwimmingReworked.Instance == (Object)null) { return; } float value = SwimmingReworked.BreathHudOffsetX.Value; float value2 = SwimmingReworked.BreathHudOffsetY.Value; float value3 = SwimmingReworked.BreathHudScale.Value; bool value4 = SwimmingReworked.BreathHudShowLabels.Value; if (!Mathf.Approximately(_cachedOffsetX, value) || !Mathf.Approximately(_cachedOffsetY, value2)) { UpdateContainerPosition(value, value2); _cachedOffsetX = value; _cachedOffsetY = value2; } if (!Mathf.Approximately(_cachedScale, value3)) { ((Transform)_container).localScale = Vector3.one * value3; _cachedScale = value3; } if (_cachedShowLabels != value4) { if ((Object)(object)_breathText != (Object)null) { ((Component)_breathText).gameObject.SetActive(value4); } _cachedShowLabels = value4; } } private void UpdateContainerPosition(float offsetX, float offsetY) { //IL_0011: 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_0047: 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) _container.anchorMin = new Vector2(1f, 0.5f); _container.anchorMax = new Vector2(1f, 0.5f); _container.pivot = new Vector2(1f, 0.5f); _container.anchoredPosition = new Vector2(offsetX, offsetY); } private void UpdateBubbles(float percent) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.CeilToInt(percent * 10f); for (int i = 0; i < _bubbles.Count; i++) { Image val = _bubbles[i]; if (((Behaviour)val).enabled = i < num) { float num2 = (float)i / 9f; float num3 = -60f + num2 * 120f + Mathf.PingPong(Time.time * 8f + (float)i * 0.5f, 15f); float num4 = Mathf.Sin(Time.time * 2f + (float)i) * 5f; RectTransform rectTransform = ((Graphic)val).rectTransform; rectTransform.anchoredPosition = new Vector2(num4, num3); float num5 = 0.45f + 0.45f * Mathf.PingPong(Time.time * 1.2f + (float)i * 0.3f, 1f); ((Graphic)val).color = new Color(0.8f, 0.92f, 1f, num5); } } } private void SetVisible(bool visible) { if ((Object)(object)_root != (Object)null && _root.activeSelf != visible) { _root.SetActive(visible); } } private void CreateHud() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Expected O, but got Unknown //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Expected O, but got Unknown //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) _root = new GameObject("BreathHud"); Object.DontDestroyOnLoad((Object)(object)_root); Canvas val = _root.AddComponent(); val.renderMode = (RenderMode)0; val.sortingOrder = 5000; CanvasScaler val2 = _root.AddComponent(); val2.uiScaleMode = (ScaleMode)1; val2.referenceResolution = new Vector2(1920f, 1080f); _root.AddComponent(); GameObject val3 = new GameObject("Container"); val3.transform.SetParent(_root.transform, false); _container = val3.AddComponent(); _container.sizeDelta = new Vector2(80f, 200f); float value = SwimmingReworked.BreathHudOffsetX.Value; float value2 = SwimmingReworked.BreathHudOffsetY.Value; float value3 = SwimmingReworked.BreathHudScale.Value; UpdateContainerPosition(value, value2); ((Transform)_container).localScale = Vector3.one * value3; _cachedOffsetX = value; _cachedOffsetY = value2; _cachedScale = value3; _bubbleSprite = CreateBubbleSprite(64); for (int i = 0; i < 10; i++) { GameObject val4 = new GameObject($"Bubble_{i}"); val4.transform.SetParent((Transform)(object)_container, false); RectTransform val5 = val4.AddComponent(); val5.sizeDelta = new Vector2(12f, 12f); Image val6 = val4.AddComponent(); val6.sprite = _bubbleSprite; val6.preserveAspect = true; ((Graphic)val6).color = new Color(0.8f, 0.92f, 1f, 0.8f); _bubbles.Add(val6); } GameObject val7 = new GameObject("BreathText"); val7.transform.SetParent((Transform)(object)_container, false); _breathText = val7.AddComponent(); _breathText.font = Resources.GetBuiltinResource("Arial.ttf"); _breathText.fontSize = 12; _breathText.alignment = (TextAnchor)5; ((Graphic)_breathText).color = new Color(0.8f, 0.92f, 1f, 0.8f); RectTransform rectTransform = ((Graphic)_breathText).rectTransform; rectTransform.sizeDelta = new Vector2(70f, 20f); rectTransform.anchoredPosition = new Vector2(-35f, -110f); ((Component)_breathText).gameObject.SetActive(SwimmingReworked.BreathHudShowLabels.Value); _cachedShowLabels = SwimmingReworked.BreathHudShowLabels.Value; SetVisible(visible: false); } private Sprite CreateBubbleSprite(int size) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(size, size, (TextureFormat)4, false); ((Texture)val).filterMode = (FilterMode)1; ((Texture)val).wrapMode = (TextureWrapMode)1; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor((float)(size - 1) * 0.5f, (float)(size - 1) * 0.5f); float num = (float)size * 0.42f; float num2 = num * 0.72f; Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(val2.x - (float)size * 0.12f, val2.y + (float)size * 0.12f); float num3 = (float)size * 0.12f; Vector2 val4 = default(Vector2); Color val5 = default(Color); for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { ((Vector2)(ref val4))..ctor((float)j, (float)i); float num4 = Vector2.Distance(val4, val2); if (num4 > num) { val.SetPixel(j, i, Color.clear); continue; } float num5 = Mathf.InverseLerp(num, num2, num4); float num6 = Mathf.Lerp(0.15f, 0.95f, num5); ((Color)(ref val5))..ctor(0.82f, 0.93f, 1f, num6); float num7 = Vector2.Distance(val4, val3); if (num7 < num3) { float num8 = 1f - num7 / num3; val5 = Color.Lerp(val5, new Color(1f, 1f, 1f, num6), num8 * 0.65f); } val.SetPixel(j, i, val5); } } val.Apply(); return Sprite.Create(val, new Rect(0f, 0f, (float)size, (float)size), new Vector2(0.5f, 0.5f), 100f); } } internal static class InputHelper { public static bool GetRun() { return ZInput.GetButton("Run"); } public static bool GetJump() { return ZInput.GetButton("Jump"); } public static bool GetCrouch() { return ZInput.GetButton("Crouch"); } public static float GetHorizontal() { return Input.GetAxisRaw("Horizontal"); } public static float GetVertical() { return Input.GetAxisRaw("Vertical"); } public static float GetDiveVertical() { float num = 0f; if (GetJump()) { num += 1f; } if (GetCrouch()) { num -= 1f; } return num; } } internal static class RuntimeFlags { public static bool AllowStaminaUseFromSwimSprint; } public static class SwimAPI { public static event Action OnEnterWater; public static event Action OnExitWater; public static event Action OnHeadUnderwater; public static event Action OnHeadAboveWater; public static event Action OnOutOfBreath; public static float GetBreathPercent(Player player) { if ((Object)(object)player == (Object)null) { return 1f; } SwimState swimState = SwimStateManager.Get(player); float maxBreath = GetMaxBreath(player); if (maxBreath <= 0f) { return 0f; } return Mathf.Clamp01(swimState.Breath / maxBreath); } public static bool IsUnderwater(Player player) { if ((Object)(object)player == (Object)null) { return false; } return WaterHelper.IsHeadUnderwater(player); } public static bool IsSwimming(Player player) { if ((Object)(object)player == (Object)null) { return false; } return WaterHelper.IsBodyInWater(player); } public static float GetCurrentBreath(Player player) { if ((Object)(object)player == (Object)null) { return 0f; } return SwimStateManager.Get(player).Breath; } public static float GetBaseMaxBreath(Player player) { if ((Object)(object)player == (Object)null) { return SwimmingReworked.MaxBreathSeconds.Value; } float skillFactor = ((Character)player).GetSkillFactor((SkillType)103); return SwimmingReworked.MaxBreathSeconds.Value + SwimmingReworked.MaxBreathBonusAtSkill100.Value * skillFactor; } public static float GetMaxBreath(Player player) { if ((Object)(object)player == (Object)null) { return SwimmingReworked.MaxBreathSeconds.Value; } SwimState swimState = SwimStateManager.Get(player); return GetBaseMaxBreath(player) + swimState.ExtraBreathBonus; } public static bool IsOutOfBreath(Player player) { return GetCurrentBreath(player) <= 0f; } public static float GetSwimSkillFactor(Player player) { if ((Object)(object)player == (Object)null) { return 0f; } return ((Character)player).GetSkillFactor((SkillType)103); } public static bool HasInfiniteBreath(Player player) { if ((Object)(object)player == (Object)null) { return false; } SwimState swimState = SwimStateManager.Get(player); return Time.time < swimState.InfiniteBreathUntil; } public static float GetExternalSwimSpeedMultiplier(Player player) { if ((Object)(object)player == (Object)null) { return 1f; } SwimState swimState = SwimStateManager.Get(player); if (Time.time >= swimState.SwimSpeedMultiplierUntil) { swimState.SwimSpeedMultiplier = 1f; return 1f; } return swimState.SwimSpeedMultiplier; } public static void RestoreBreath(Player player, float amount) { if (!((Object)(object)player == (Object)null) && !(amount <= 0f)) { SwimState swimState = SwimStateManager.Get(player); swimState.Breath = Mathf.Min(GetMaxBreath(player), swimState.Breath + amount); } } public static void DrainBreath(Player player, float amount) { if (!((Object)(object)player == (Object)null) && !(amount <= 0f)) { SwimState swimState = SwimStateManager.Get(player); swimState.Breath = Mathf.Max(0f, swimState.Breath - amount); } } public static void SetInfiniteBreath(Player player, float duration) { if (!((Object)(object)player == (Object)null) && !(duration <= 0f)) { SwimState swimState = SwimStateManager.Get(player); swimState.InfiniteBreathUntil = Mathf.Max(swimState.InfiniteBreathUntil, Time.time + duration); swimState.Breath = GetMaxBreath(player); } } public static void AddBreathBonus(Player player, float bonusSeconds) { if (!((Object)(object)player == (Object)null)) { SwimState swimState = SwimStateManager.Get(player); swimState.ExtraBreathBonus = Mathf.Max(0f, swimState.ExtraBreathBonus + bonusSeconds); swimState.Breath = Mathf.Min(swimState.Breath, GetMaxBreath(player)); } } public static void SetBreathBonus(Player player, float bonusSeconds) { if (!((Object)(object)player == (Object)null)) { SwimState swimState = SwimStateManager.Get(player); swimState.ExtraBreathBonus = Mathf.Max(0f, bonusSeconds); swimState.Breath = Mathf.Min(swimState.Breath, GetMaxBreath(player)); } } public static void AddSwimSpeedBonus(Player player, float multiplier, float duration) { if (!((Object)(object)player == (Object)null) && !(multiplier <= 0f) && !(duration <= 0f)) { SwimState swimState = SwimStateManager.Get(player); swimState.SwimSpeedMultiplier = Mathf.Max(swimState.SwimSpeedMultiplier, multiplier); swimState.SwimSpeedMultiplierUntil = Mathf.Max(swimState.SwimSpeedMultiplierUntil, Time.time + duration); } } internal static void UpdateEvents(Player player) { if (!((Object)(object)player == (Object)null)) { SwimState swimState = SwimStateManager.Get(player); bool flag = IsSwimming(player); bool flag2 = IsUnderwater(player); bool flag3 = IsOutOfBreath(player); if (flag && !swimState.WasSwimming) { SwimAPI.OnEnterWater?.Invoke(player); } else if (!flag && swimState.WasSwimming) { SwimAPI.OnExitWater?.Invoke(player); } if (flag2 && !swimState.WasHeadUnderwater) { SwimAPI.OnHeadUnderwater?.Invoke(player); } else if (!flag2 && swimState.WasHeadUnderwater) { SwimAPI.OnHeadAboveWater?.Invoke(player); } if (flag3 && !swimState.WasOutOfBreath) { SwimAPI.OnOutOfBreath?.Invoke(player); } swimState.WasSwimming = flag; swimState.WasHeadUnderwater = flag2; swimState.WasOutOfBreath = flag3; } } } [BepInPlugin("dzk.SwimmingReworked", "SwimmingReworked", "1.0.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] [SynchronizationMode(/*Could not decode attribute arguments.*/)] internal class SwimmingReworked : BaseUnityPlugin { public const string PluginGUID = "dzk.SwimmingReworked"; public const string PluginName = "SwimmingReworked"; public const string PluginVersion = "1.0.5"; internal static SwimmingReworked Instance; internal static Harmony Harmony; public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization(); internal static ConfigEntry EnableMod; internal static ConfigEntry MaxBreathSeconds; internal static ConfigEntry MaxBreathBonusAtSkill100; internal static ConfigEntry BreathRecoveryPerSecond; internal static ConfigEntry SuffocationDamagePercentPerTick; internal static ConfigEntry SuffocationTickInterval; internal static ConfigEntry SprintSwimMultiplier; internal static ConfigEntry SprintStaminaPerSecond; internal static ConfigEntry VerticalSwimSpeed; internal static ConfigEntry MinSwimSpeed; internal static ConfigEntry MaxSwimSpeedAtSkill100; internal static ConfigEntry AllowUnderwaterSprint; internal static ConfigEntry DisableVanillaSwimStaminaDrain; internal static ConfigEntry DisableVanillaDrowningFromStamina; internal static ConfigEntry BaseUnderwaterStaminaRegenPerSecond; internal static ConfigEntry MaxSwimSkillBonusStaminaRegenPerSecond; internal static ConfigEntry DebugLogging; private ConfigFileWatcher _configWatcher; internal static ConfigEntry BreathHudOffsetX; internal static ConfigEntry BreathHudOffsetY; internal static ConfigEntry BreathHudScale; internal static ConfigEntry BreathHudShowLabels; private void Awake() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown Instance = this; CreateConfig(); CreateConfigWatcher(); SynchronizationManager.OnConfigurationSynchronized += OnConfigurationSynchronized; SynchronizationManager.OnAdminStatusChanged += OnAdminStatusChanged; ((Component)this).gameObject.AddComponent(); ((Component)this).gameObject.AddComponent(); Harmony = new Harmony("dzk.SwimmingReworked"); Harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"SwimmingReworked 1.0.5 loaded"); } private void OnDestroy() { SynchronizationManager.OnConfigurationSynchronized -= OnConfigurationSynchronized; SynchronizationManager.OnAdminStatusChanged -= OnAdminStatusChanged; if (_configWatcher != null) { _configWatcher = null; } } private void CreateConfig() { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; BreathHudOffsetX = ((BaseUnityPlugin)this).Config.Bind("Breath HUD", "OffsetX", -40f, "Horizontal offset from right edge of screen (negative = left)."); BreathHudOffsetY = ((BaseUnityPlugin)this).Config.Bind("Breath HUD", "OffsetY", 0f, "Vertical offset from center of screen."); BreathHudScale = ((BaseUnityPlugin)this).Config.Bind("Breath HUD", "Scale", 1f, "Scale multiplier for the breath indicator."); AcceptableValueBase val = (AcceptableValueBase)(object)new AcceptableValueRange(0.3f, 3f); BreathHudScale = ((BaseUnityPlugin)this).Config.Bind("Breath HUD", "Scale", 1f, new ConfigDescription("Scale multiplier for the breath indicator.", val, Array.Empty())); BreathHudShowLabels = ((BaseUnityPlugin)this).Config.Bind("Breath HUD", "ShowLabels", false, "Show numeric breath value next to bubbles."); EnableMod = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "General", "EnableMod", true, "Enable or disable the mod.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); ConfigFile config = ((BaseUnityPlugin)this).Config; AcceptableValueBase val2 = (AcceptableValueBase)(object)new AcceptableValueRange(1f, 600f); MaxBreathSeconds = ConfigFileExtensions.BindConfig(config, "Breath", "MaxBreathSeconds", 30f, "Maximum underwater breath at Swim skill 0.", true, (int?)null, val2, (Action)null, (ConfigurationManagerAttributes)null); ConfigFile config2 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange(0f, 600f); MaxBreathBonusAtSkill100 = ConfigFileExtensions.BindConfig(config2, "Breath", "MaxBreathBonusAtSkill100", 150f, "Additional breath time gained at Swim skill 100.", true, (int?)null, val2, (Action)null, (ConfigurationManagerAttributes)null); ConfigFile config3 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange(0f, 300f); BreathRecoveryPerSecond = ConfigFileExtensions.BindConfig(config3, "Breath", "BreathRecoveryPerSecond", 30f, "Breath recovered per second when not underwater.", true, (int?)null, val2, (Action)null, (ConfigurationManagerAttributes)null); ConfigFile config4 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange(0f, 100f); SuffocationDamagePercentPerTick = ConfigFileExtensions.BindConfig(config4, "Breath", "SuffocationDamagePercentPerTick", 10f, "Percent of max health lost each suffocation tick when breath reaches 0.", true, (int?)null, val2, (Action)null, (ConfigurationManagerAttributes)null); ConfigFile config5 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 30f); SuffocationTickInterval = ConfigFileExtensions.BindConfig(config5, "Breath", "SuffocationTickInterval", 2f, "Seconds between suffocation damage ticks when breath reaches 0.", true, (int?)null, val2, (Action)null, (ConfigurationManagerAttributes)null); ConfigFile config6 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange(1f, 5f); SprintSwimMultiplier = ConfigFileExtensions.BindConfig(config6, "Movement", "SprintSwimMultiplier", 1.75f, "Sprint speed multiplier while swimming.", true, (int?)null, val2, (Action)null, (ConfigurationManagerAttributes)null); ConfigFile config7 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange(0f, 100f); SprintStaminaPerSecond = ConfigFileExtensions.BindConfig(config7, "Movement", "SprintStaminaPerSecond", 8f, "Stamina drained per second while sprint swimming.", true, (int?)null, val2, (Action)null, (ConfigurationManagerAttributes)null); ConfigFile config8 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 20f); VerticalSwimSpeed = ConfigFileExtensions.BindConfig(config8, "Movement", "VerticalSwimSpeed", 3f, "Vertical swimming speed while diving.", true, (int?)null, val2, (Action)null, (ConfigurationManagerAttributes)null); AllowUnderwaterSprint = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Movement", "AllowUnderwaterSprint", true, "Allow sprinting underwater.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); DisableVanillaSwimStaminaDrain = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Vanilla Overrides", "DisableVanillaSwimStaminaDrain", true, "Disables vanilla stamina drain for normal swimming.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); DisableVanillaDrowningFromStamina = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Vanilla Overrides", "DisableVanillaDrowningFromStamina", true, "Disables vanilla drowning behavior caused by stamina depletion.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); ConfigFile config9 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange(0f, 50f); BaseUnderwaterStaminaRegenPerSecond = ConfigFileExtensions.BindConfig(config9, "Movement", "BaseUnderwaterStaminaRegenPerSecond", 2f, "Base stamina regenerated per second while swimming and not sprinting.", true, (int?)null, val2, (Action)null, (ConfigurationManagerAttributes)null); ConfigFile config10 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange(0f, 50f); MaxSwimSkillBonusStaminaRegenPerSecond = ConfigFileExtensions.BindConfig(config10, "Movement", "MaxSwimSkillBonusStaminaRegenPerSecond", 4f, "Additional stamina regenerated per second at Swim skill 100.", true, (int?)null, val2, (Action)null, (ConfigurationManagerAttributes)null); ConfigFile config11 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 10f); MinSwimSpeed = ConfigFileExtensions.BindConfig(config11, "Movement", "MinSwimSpeed", 1f, "Swim speed multiplier at Swim skill 0.", true, (int?)null, val2, (Action)null, (ConfigurationManagerAttributes)null); ConfigFile config12 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 10f); MaxSwimSpeedAtSkill100 = ConfigFileExtensions.BindConfig(config12, "Movement", "MaxSwimSpeedAtSkill100", 2f, "Swim speed multiplier at Swim skill 100.", true, (int?)null, val2, (Action)null, (ConfigurationManagerAttributes)null); DebugLogging = ((BaseUnityPlugin)this).Config.Bind("Debug", "DebugLogging", false, "Enable debug logs."); ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; ((BaseUnityPlugin)this).Config.Save(); } private void CreateConfigWatcher() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown _configWatcher = new ConfigFileWatcher(((BaseUnityPlugin)this).Config, 1000L); _configWatcher.OnConfigFileReloaded += delegate { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Config file reloaded from disk."); }; } private void OnConfigurationSynchronized(object sender, ConfigurationSynchronizationEventArgs e) { if (e.InitialSynchronization) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Initial config sync received."); } else { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Config sync update received."); } } private void OnAdminStatusChanged() { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Admin status changed: " + (SynchronizationManager.Instance.PlayerIsAdmin ? "admin" : "not admin"))); } internal static bool IsEnabled() { return (Object)(object)Instance != (Object)null && EnableMod.Value; } internal static void LogDebug(string msg) { if ((Object)(object)Instance != (Object)null && DebugLogging.Value) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)msg); } } } internal class SwimState { public float Breath; public bool WasHeadUnderwater; public bool WasSwimming; public float LastSurfaceTime; public float SuffocationTickTimer; public float ExtraBreathBonus; public float InfiniteBreathUntil; public float SwimSpeedMultiplier = 1f; public float SwimSpeedMultiplierUntil; public bool WasOutOfBreath; } internal static class SwimStateManager { private static readonly Dictionary States = new Dictionary(); public static SwimState Get(Player player) { long playerID = player.GetPlayerID(); if (!States.TryGetValue(playerID, out var value)) { value = new SwimState { Breath = SwimAPI.GetBaseMaxBreath(player), WasHeadUnderwater = false, WasSwimming = false, LastSurfaceTime = 0f, SuffocationTickTimer = 0f, ExtraBreathBonus = 0f, InfiniteBreathUntil = 0f, SwimSpeedMultiplier = 1f, SwimSpeedMultiplierUntil = 0f, WasOutOfBreath = false }; States[playerID] = value; } return value; } public static void Remove(Player player) { if (!((Object)(object)player == (Object)null)) { States.Remove(player.GetPlayerID()); } } } internal static class WaterHelper { public static bool TryGetWaterLevel(Vector3 position, out float waterLevel) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) waterLevel = Floating.GetLiquidLevel(position, 1f, (LiquidType)0); return waterLevel > -10000f; } public static Vector3 GetHeadPosition(Player player) { //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_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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)player == (Object)null) { return Vector3.zero; } return ((Character)player).GetHeadPoint(); } public static Vector3 GetChestPosition(Player player) { //IL_001f: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return Vector3.zero; } return ((Component)player).transform.position + Vector3.up * 1f; } public static bool IsBodyInWater(Player player) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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) if ((Object)(object)player == (Object)null) { return false; } Vector3 chestPosition = GetChestPosition(player); float waterLevel; return TryGetWaterLevel(chestPosition, out waterLevel) && chestPosition.y < waterLevel; } public static bool IsHeadUnderwater(Player player) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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) if ((Object)(object)player == (Object)null) { return false; } Vector3 headPosition = GetHeadPosition(player); float waterLevel; return TryGetWaterLevel(headPosition, out waterLevel) && headPosition.y < waterLevel - 0.02f; } public static bool IsNearSurface(Player player, float tolerance = 0.35f) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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) if ((Object)(object)player == (Object)null) { return false; } Vector3 headPosition = GetHeadPosition(player); float waterLevel; return TryGetWaterLevel(headPosition, out waterLevel) && Mathf.Abs(headPosition.y - waterLevel) <= tolerance; } } } namespace SwimmingReworked.Patches { [HarmonyPatch(typeof(CameraEffects), "SetSunShafts")] internal static class CameraEffectsPatch { private static void Prefix(ref bool enabled) { if (DiveImmersionEffect.IsUnderwaterImmersionActive) { enabled = false; } } } [HarmonyPatch(typeof(Character), "Damage")] internal static class CharacterDamageDebugPatch { private static void Prefix(Character __instance, HitData hit) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if (SwimmingReworked.IsEnabled() && SwimmingReworked.DebugLogging.Value) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && WaterHelper.IsBodyInWater(val)) { float totalDamage = hit.GetTotalDamage(); SwimmingReworked.LogDebug($"Damage underwater -> total:{totalDamage}, attacker:{hit.GetAttacker()}, point:{hit.m_point}, dir:{hit.m_dir}"); } } } } [HarmonyPatch(typeof(Character), "Damage")] internal static class CharacterDamagePatch { private static bool Prefix(Character __instance, HitData hit) { if (!SwimmingReworked.IsEnabled()) { return true; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer) { return true; } if (hit == null) { return true; } SwimState swimState = SwimStateManager.Get(val); if (swimState.Breath > 0f && IsVanillaDrowningHit(val, hit)) { if (SwimmingReworked.DebugLogging.Value) { SwimmingReworked.LogDebug($"Blocked vanilla drowning hit: total={hit.GetTotalDamage():F1}"); } return false; } return true; } private static bool IsVanillaDrowningHit(Player player, HitData hit) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) if (!WaterHelper.IsHeadUnderwater(player)) { return false; } if ((Object)(object)hit.GetAttacker() != (Object)null) { return false; } float totalDamage = hit.GetTotalDamage(); if (totalDamage <= 0f) { return false; } Vector3 dir = hit.m_dir; bool flag = dir.y < -0.9f; bool flag2 = Mathf.Abs(totalDamage - 2f) < 0.01f; return flag && flag2; } } [HarmonyPatch] internal static class CharacterSwimmingPatch { [HarmonyPatch(typeof(Character), "CustomFixedUpdate")] [HarmonyPrefix] private static void CharacterCustomFixedUpdatePrefix(Character __instance, ref Vector3 ___m_lookDir) { if (!SwimmingReworked.IsEnabled()) { return; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer) { return; } if (!WaterHelper.IsBodyInWater(val)) { ((Character)val).m_swimDepth = 1.5f; return; } float diveVertical = InputHelper.GetDiveVertical(); if (diveVertical < -0.01f) { ((Character)val).m_swimDepth = ((Character)val).m_swimDepth + SwimmingReworked.VerticalSwimSpeed.Value * 0.02f; } else if (diveVertical > 0.01f) { ((Character)val).m_swimDepth = ((Character)val).m_swimDepth - SwimmingReworked.VerticalSwimSpeed.Value * 0.02f; } ((Character)val).m_swimDepth = Mathf.Clamp(((Character)val).m_swimDepth, 1.5f, 100f); } [HarmonyPatch(typeof(Character), "UpdateMotion")] [HarmonyPrefix] private static void CharacterUpdateMotionPrefix(Character __instance, ref float ___m_lastGroundTouch, ref float ___m_swimTimer) { if (SwimmingReworked.IsEnabled()) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && WaterHelper.IsBodyInWater(val)) { ___m_lastGroundTouch = 0.3f; ___m_swimTimer = 0f; } } } [HarmonyPatch(typeof(Character), "UpdateSwimming")] [HarmonyPrefix] private static bool CharacterUpdateSwimmingPrefix(float dt, ref Character __instance) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: 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_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_0398: Unknown result type (might be due to invalid IL or missing references) //IL_03cb: Unknown result type (might be due to invalid IL or missing references) //IL_03d0: Unknown result type (might be due to invalid IL or missing references) //IL_03d4: Unknown result type (might be due to invalid IL or missing references) //IL_03f5: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_0386: Unknown result type (might be due to invalid IL or missing references) //IL_0456: Unknown result type (might be due to invalid IL or missing references) //IL_047b: Unknown result type (might be due to invalid IL or missing references) //IL_0480: Unknown result type (might be due to invalid IL or missing references) //IL_0483: Unknown result type (might be due to invalid IL or missing references) //IL_0488: Unknown result type (might be due to invalid IL or missing references) //IL_0492: Unknown result type (might be due to invalid IL or missing references) //IL_049d: Unknown result type (might be due to invalid IL or missing references) //IL_04af: Unknown result type (might be due to invalid IL or missing references) //IL_04b4: Unknown result type (might be due to invalid IL or missing references) //IL_0438: Unknown result type (might be due to invalid IL or missing references) if (!SwimmingReworked.IsEnabled()) { return true; } Character obj = __instance; Player val = (Player)(object)((obj is Player) ? obj : null); if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer) { return true; } bool flag = ((Character)val).IsOnGround(); Vector3 position = ((Component)val).transform.position; if (Mathf.Max(0f, ((Character)val).m_maxAirAltitude - position.y) > 0.5f && ((Character)val).m_onLand != null) { ((Character)val).m_onLand(new Vector3(position.x, ((Character)val).m_waterLevel, position.z)); } ((Character)val).m_maxAirAltitude = position.y; float skillFactor = val.m_skills.GetSkillFactor((SkillType)103); float num = Mathf.Lerp(SwimmingReworked.MinSwimSpeed.Value, SwimmingReworked.MaxSwimSpeedAtSkill100.Value, skillFactor); num *= SwimAPI.GetExternalSwimSpeedMultiplier(val); num *= ((Character)val).GetAttackSpeedFactorMovement(); bool flag2 = false; float num2 = SwimmingReworked.SprintStaminaPerSecond.Value * dt; if (((Character)val).IsEncumbered()) { num *= 0.3f; } if (((Character)val).InMinorAction()) { num = 0f; } else if (InputHelper.GetRun() && !((Character)val).IsEncumbered() && val.GetStamina() > num2 + 0.01f) { num *= SwimmingReworked.SprintSwimMultiplier.Value; try { RuntimeFlags.AllowStaminaUseFromSwimSprint = true; ((Character)val).UseStamina(num2); } finally { RuntimeFlags.AllowStaminaUseFromSwimSprint = false; } } ((Character)val).m_seman.ApplyStatusEffectSpeedMods(ref num, ((Character)val).m_moveDir); Vector3 val2 = ((Character)val).m_moveDir * num; if (((Vector3)(ref val2)).magnitude > 0f && ((Character)val).IsOnGround()) { Vector3 val3 = Vector3.ProjectOnPlane(val2, ((Character)val).m_lastGroundNormal); val2 = ((Vector3)(ref val3)).normalized * ((Vector3)(ref val2)).magnitude; } ((Character)val).m_currentVel = Vector3.Lerp(((Character)val).m_currentVel, val2, ((Character)val).m_swimAcceleration); if (((Vector3)(ref val2)).magnitude > 0.1f) { ((Character)val).AddNoise(15f); } ((Character)val).AddPushbackForce(ref ((Character)val).m_currentVel); Vector3 val4 = ((Character)val).m_currentVel - ((Character)val).m_body.linearVelocity; val4.y = 0f; if (((Vector3)(ref val4)).magnitude > 20f) { val4 = ((Vector3)(ref val4)).normalized * 20f; } if (((Vector3)(ref val2)).magnitude > 0.1f) { val.m_swimSkillImproveTimer += dt; if (val.m_swimSkillImproveTimer > 1f) { val.m_swimSkillImproveTimer = 0f; ((Character)val).RaiseSkill((SkillType)103, 1f); } } else { val.m_swimSkillImproveTimer = 0f; } ((Character)val).m_body.AddForce(val4, (ForceMode)2); float num3 = ((Character)val).m_waterLevel - ((Character)val).m_swimDepth; if (((Component)val).transform.position.y < num3) { float num4 = Mathf.Clamp01((num3 - ((Component)val).transform.position.y) / 2f); float num5 = Mathf.Lerp(0f, 10f, num4); Vector3 linearVelocity = ((Character)val).m_body.linearVelocity; linearVelocity.y = Mathf.MoveTowards(linearVelocity.y, num5, 50f * dt); ((Character)val).m_body.linearVelocity = linearVelocity; } else { float num6 = Mathf.Clamp01((((Component)val).transform.position.y - num3) / 1f); float num7 = Mathf.Lerp(0f, 10f, num6); Vector3 linearVelocity2 = ((Character)val).m_body.linearVelocity; linearVelocity2.y = Mathf.MoveTowards(linearVelocity2.y, 0f - num7, 30f * dt); ((Character)val).m_body.linearVelocity = linearVelocity2; } float num8 = 0f; if (((Vector3)(ref ((Character)val).m_moveDir)).magnitude > 0.1f || ((Character)val).AlwaysRotateCamera()) { float swimTurnSpeed = ((Character)val).m_swimTurnSpeed; ((Character)val).m_seman.ApplyStatusEffectSpeedMods(ref swimTurnSpeed, ((Character)val).m_moveDir); num8 = ((Character)val).UpdateRotation(swimTurnSpeed, dt, true); } ((Character)val).m_body.angularVelocity = Vector3.zero; ((Character)val).UpdateEyeRotation(); ((Character)val).m_body.useGravity = true; Vector3 forward = ((Component)val).transform.forward; float num9 = Vector3.Dot(((Character)val).m_currentVel, forward); float num10 = Vector3.Dot(((Character)val).m_currentVel, ((Component)val).transform.right); float num11 = Vector3.Dot(((Character)val).m_body.linearVelocity, forward); ((Character)val).m_currentTurnVel = Mathf.SmoothDamp(((Character)val).m_currentTurnVel, num8, ref ((Character)val).m_currentTurnVelChange, 0.5f, 99f); int hash = ZSyncAnimation.GetHash("forward_speed"); int hash2 = ZSyncAnimation.GetHash("sideway_speed"); int hash3 = ZSyncAnimation.GetHash("turn_speed"); int hash4 = ZSyncAnimation.GetHash("inWater"); int hash5 = ZSyncAnimation.GetHash("onGround"); int hash6 = ZSyncAnimation.GetHash("encumbered"); int hash7 = ZSyncAnimation.GetHash("flying"); ((Character)val).m_zanim.SetFloat(hash, ((Character)val).IsPlayer() ? num9 : num11); ((Character)val).m_zanim.SetFloat(hash2, num10); ((Character)val).m_zanim.SetFloat(hash3, ((Character)val).m_currentTurnVel); ((Character)val).m_zanim.SetBool(hash4, !flag); ((Character)val).m_zanim.SetBool(hash5, false); ((Character)val).m_zanim.SetBool(hash6, false); ((Character)val).m_zanim.SetBool(hash7, false); return false; } } [HarmonyPatch] internal static class CharacterWaterStatePatch { [HarmonyPrefix] [HarmonyPatch(typeof(Character), "IsSwimming")] private static bool CharacterIsSwimmingPrefix(Character __instance, ref bool __result) { if (!SwimmingReworked.IsEnabled()) { return true; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer) { return true; } StackTrace stackTrace = new StackTrace(); for (int i = 2; i < stackTrace.FrameCount && i < 14; i++) { MethodBase methodBase = stackTrace.GetFrame(i)?.GetMethod(); if (!(methodBase == null)) { string text = methodBase.DeclaringType?.FullName + "." + methodBase.Name; if (text.Contains("EquipItem") || text.Contains("UpdateEquipment") || text.Contains("HideHandItems") || text.Contains("UnequipItem")) { __result = false; return false; } } } if (WaterHelper.IsBodyInWater(val)) { __result = true; return false; } return true; } [HarmonyPostfix] [HarmonyPatch(typeof(Character), "IsOnGround")] private static void CharacterIsOnGroundPostfix(Character __instance, ref bool __result) { if (SwimmingReworked.IsEnabled()) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && WaterHelper.IsBodyInWater(val)) { __result = false; } } } [HarmonyPostfix] [HarmonyPatch(typeof(Character), "InWater")] private static void CharacterInWaterPostfix(Character __instance, ref bool __result) { if (SwimmingReworked.IsEnabled()) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && WaterHelper.IsBodyInWater(val)) { __result = true; } } } } [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] internal static class GameCameraPatch { private static float _originalMaxDistance; private static float _originalMinWaterDistance; private static bool _cachedOriginalValues; private static void Prefix(GameCamera __instance, Camera ___m_camera) { if (!SwimmingReworked.IsEnabled()) { return; } Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)___m_camera == (Object)null)) { bool flag = WaterHelper.IsBodyInWater(localPlayer); if (!_cachedOriginalValues) { _originalMaxDistance = __instance.m_maxDistance; _originalMinWaterDistance = __instance.m_minWaterDistance; _cachedOriginalValues = true; } if (flag) { __instance.m_minWaterDistance = -5000f; __instance.m_maxDistance = _originalMaxDistance; } else { __instance.m_minWaterDistance = _originalMinWaterDistance; __instance.m_maxDistance = _originalMaxDistance; } } } } [HarmonyPatch] internal static class PlayerEquipInWater { internal static bool _allowCombat; [HarmonyPrefix] [HarmonyPatch(typeof(Player), "Update")] private static void PlayerUpdate_Prefix(Player __instance) { if (SwimmingReworked.IsEnabled() && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && WaterHelper.IsBodyInWater(__instance)) { bool button = ZInput.GetButton("Attack"); bool button2 = ZInput.GetButton("Block"); if (button || button2) { _allowCombat = true; } } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "Update")] private static void PlayerUpdate_Postfix() { _allowCombat = false; } [HarmonyFinalizer] [HarmonyPatch(typeof(Player), "Update")] private static void PlayerUpdate_Finalizer() { _allowCombat = false; } [HarmonyPostfix] [HarmonyPatch(typeof(Character), "InAttack")] private static void InAttack_Postfix(Character __instance, ref bool __result) { if (SwimmingReworked.IsEnabled() && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && _allowCombat && WaterHelper.IsBodyInWater(Player.m_localPlayer)) { __result = false; } } } [HarmonyPatch(typeof(Player), "FixedUpdate")] internal static class PlayerFixedUpdatePatch { private static void Postfix(Player __instance) { if (!SwimmingReworked.IsEnabled() || (Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } bool flag = WaterHelper.IsBodyInWater(__instance); bool headUnderwater = WaterHelper.IsHeadUnderwater(__instance); if (!flag) { Rigidbody component = ((Component)__instance).GetComponent(); if ((Object)(object)component != (Object)null) { component.useGravity = true; } HandleBreath(__instance, headUnderwater: false); return; } Rigidbody component2 = ((Component)__instance).GetComponent(); if (!((Object)(object)component2 == (Object)null)) { component2.useGravity = true; HandleBreath(__instance, headUnderwater); HandleUnderwaterStaminaRegen(__instance); } } private static void HandleBreath(Player player, bool headUnderwater) { //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) SwimState swimState = SwimStateManager.Get(player); float fixedDeltaTime = Time.fixedDeltaTime; float maxBreath = SwimAPI.GetMaxBreath(player); bool flag = SwimAPI.HasInfiniteBreath(player); if (headUnderwater) { if (flag) { swimState.Breath = maxBreath; swimState.SuffocationTickTimer = 0f; } else { swimState.Breath -= fixedDeltaTime; if (swimState.Breath < 0f) { swimState.Breath = 0f; } if (swimState.Breath <= 0f) { swimState.SuffocationTickTimer += fixedDeltaTime; if (swimState.SuffocationTickTimer >= SwimmingReworked.SuffocationTickInterval.Value) { swimState.SuffocationTickTimer = 0f; float maxHealth = ((Character)player).GetMaxHealth(); float damage = maxHealth * (SwimmingReworked.SuffocationDamagePercentPerTick.Value / 100f); HitData val = new HitData(); val.m_point = ((Component)player).transform.position; val.m_dir = Vector3.zero; val.m_damage.m_damage = damage; ((Character)player).Damage(val); } } else { swimState.SuffocationTickTimer = 0f; } } } else { swimState.Breath += SwimmingReworked.BreathRecoveryPerSecond.Value * fixedDeltaTime; if (swimState.Breath > maxBreath) { swimState.Breath = maxBreath; } swimState.SuffocationTickTimer = 0f; } SwimAPI.UpdateEvents(player); if (SwimmingReworked.DebugLogging.Value && Time.frameCount % 60 == 0) { SwimmingReworked.LogDebug($"Breath={swimState.Breath:F1}/{maxBreath:F1}, underwater={headUnderwater}, infinite={flag}"); } swimState.WasHeadUnderwater = headUnderwater; } private static void HandleUnderwaterStaminaRegen(Player player) { if (!InputHelper.GetRun() || !(player.GetStamina() > 0f)) { float skillFactor = ((Character)player).GetSkillFactor((SkillType)103); float num = SwimmingReworked.BaseUnderwaterStaminaRegenPerSecond.Value + SwimmingReworked.MaxSwimSkillBonusStaminaRegenPerSecond.Value * skillFactor; float value = Traverse.Create((object)player).Field("m_stamina").GetValue(); float maxStamina = ((Character)player).GetMaxStamina(); float num2 = num * Time.fixedDeltaTime; value += num2; if (value > maxStamina) { value = maxStamina; } Traverse.Create((object)player).Field("m_stamina").SetValue((object)value); } } } [HarmonyPatch(typeof(Player), "Update")] internal static class PlayerUpdatePatch { private static void Postfix(Player __instance) { } } [HarmonyPatch(typeof(Player), "UpdateStats", new Type[] { typeof(float) })] internal static class PlayerUpdateStatsPatch { private static void Postfix(Player __instance, float dt) { if (SwimmingReworked.IsEnabled() && !((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && WaterHelper.IsBodyInWater(__instance) && (!InputHelper.GetRun() || !(__instance.GetStamina() > 0f))) { Traverse.Create((object)__instance).Field("m_staminaRegenTimer").SetValue((object)0f); } } } [HarmonyPatch(typeof(WaterVolume), "UpdateMaterials")] internal static class SurfacePatch { private static readonly Dictionary UnderwaterCopies = new Dictionary(); private const float SurfaceOffset = -0.05f; private const float OverlapScale = 1.04f; private static void Postfix(WaterVolume __instance) { if (!SwimmingReworked.IsEnabled() || (Object)(object)__instance == (Object)null || (Object)(object)__instance.m_waterSurface == (Object)null) { return; } MeshRenderer component = ((Component)__instance.m_waterSurface).GetComponent(); MeshFilter component2 = ((Component)__instance.m_waterSurface).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null) { return; } if (!UnderwaterCopies.TryGetValue(component, out var value) || (Object)(object)value == (Object)null) { value = CreateUnderwaterSurfaceCopy(((Component)component).gameObject, component, component2); if ((Object)(object)value != (Object)null) { UnderwaterCopies[component] = value; } } if (!((Object)(object)value == (Object)null)) { value.SetActive(IsCameraUnderwater()); } } private static GameObject CreateUnderwaterSurfaceCopy(GameObject original, MeshRenderer originalRenderer, MeshFilter originalFilter) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0034: 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_0074: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("SwimmingReworked_UnderwaterSurface"); val.transform.SetParent(original.transform, false); val.transform.localPosition = new Vector3(0f, -0.025f, 0f); val.transform.localRotation = Quaternion.Euler(180f, 180f, 0f); val.transform.localScale = new Vector3(1.02f, 1f, 1.02f); MeshFilter val2 = val.AddComponent(); val2.sharedMesh = originalFilter.sharedMesh; MeshRenderer val3 = val.AddComponent(); ((Renderer)val3).sharedMaterial = ((Renderer)originalRenderer).sharedMaterial; ((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)val3).receiveShadows = false; ((Renderer)val3).lightProbeUsage = (LightProbeUsage)0; ((Renderer)val3).reflectionProbeUsage = (ReflectionProbeUsage)0; ((Renderer)val3).allowOcclusionWhenDynamic = false; ((Renderer)val3).forceRenderingOff = false; ((Renderer)val3).enabled = true; val.SetActive(false); return val; } private static bool IsCameraUnderwater() { //IL_0042: 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) if ((Object)(object)GameCamera.instance == (Object)null) { return false; } Camera component = ((Component)GameCamera.instance).GetComponent(); if ((Object)(object)component == (Object)null) { return false; } float waterLevel; return WaterHelper.TryGetWaterLevel(((Component)component).transform.position, out waterLevel) && ((Component)component).transform.position.y < waterLevel - 0.15f; } } [HarmonyPatch(typeof(Player), "UseStamina")] internal static class UseStaminaPatch { private static bool Prefix(Player __instance, ref float v) { if (!SwimmingReworked.IsEnabled()) { return true; } if (!SwimmingReworked.DisableVanillaSwimStaminaDrain.Value) { return true; } if ((Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } if (RuntimeFlags.AllowStaminaUseFromSwimSprint) { return true; } if (!WaterHelper.IsBodyInWater(__instance)) { return true; } StackTrace stackTrace = new StackTrace(); string text = ""; for (int i = 2; i < stackTrace.FrameCount && i < 10; i++) { MethodBase methodBase = stackTrace.GetFrame(i)?.GetMethod(); if (methodBase != null) { text = text + methodBase.Name + "_"; } } if (text.Contains("OnSwimming") || text.Contains("UpdateSwimming")) { return false; } return true; } } [HarmonyPatch(typeof(WaterVolume), "UpdateMaterials")] internal static class WaterShaderPatch { private static readonly int ColorTopId = Shader.PropertyToID("_ColorTop"); private static readonly int ColorBottomId = Shader.PropertyToID("_ColorBottom"); private static readonly int ColorBottomShallowId = Shader.PropertyToID("_ColorBottomShallow"); private static readonly int SurfaceColorId = Shader.PropertyToID("_SurfaceColor"); private static readonly int DepthFadeId = Shader.PropertyToID("_DepthFade"); private static readonly int CullId = Shader.PropertyToID("_Cull"); private static Color _originalColorTop; private static Color _originalColorBottom; private static Color _originalColorBottomShallow; private static Color _originalSurfaceColor; private static float _originalDepthFade; private static bool _originalValuesSaved; private static Material _instanceMaterial; private static MeshRenderer _lastRenderer; private static void Postfix(WaterVolume __instance) { if (SwimmingReworked.IsEnabled() && !((Object)(object)__instance.m_waterSurface == (Object)null)) { MeshRenderer waterSurface = __instance.m_waterSurface; if ((Object)(object)_instanceMaterial == (Object)null || (Object)(object)_lastRenderer != (Object)(object)waterSurface) { _instanceMaterial = ((Renderer)waterSurface).material; _lastRenderer = waterSurface; SaveOriginalValues(_instanceMaterial); } if (_instanceMaterial.HasProperty(CullId)) { _instanceMaterial.SetInt(CullId, 0); } ApplyUnderwaterSettings(_instanceMaterial); } } private static void SaveOriginalValues(Material mat) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_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) //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_0073: 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) if (mat.HasProperty(ColorTopId)) { _originalColorTop = mat.GetColor(ColorTopId); } if (mat.HasProperty(ColorBottomId)) { _originalColorBottom = mat.GetColor(ColorBottomId); } if (mat.HasProperty(ColorBottomShallowId)) { _originalColorBottomShallow = mat.GetColor(ColorBottomShallowId); } if (mat.HasProperty(SurfaceColorId)) { _originalSurfaceColor = mat.GetColor(SurfaceColorId); } if (mat.HasProperty(DepthFadeId)) { _originalDepthFade = mat.GetFloat(DepthFadeId); } _originalValuesSaved = true; } private static void ApplyUnderwaterSettings(Material mat) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_005e: 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_00c6: Unknown result type (might be due to invalid IL or missing references) if (mat.HasProperty(ColorTopId)) { mat.SetColor(ColorTopId, new Color(0.05f, 0.35f, 0.35f, 0.95f)); } if (mat.HasProperty(ColorBottomId)) { mat.SetColor(ColorBottomId, new Color(0.02f, 0.05f, 0.15f, 0.98f)); } if (mat.HasProperty(ColorBottomShallowId)) { mat.SetColor(ColorBottomShallowId, new Color(0.08f, 0.3f, 0.4f, 0.9f)); } if (mat.HasProperty(SurfaceColorId)) { mat.SetColor(SurfaceColorId, new Color(0.1f, 0.35f, 0.45f, 0.85f)); } if (mat.HasProperty(DepthFadeId)) { mat.SetFloat(DepthFadeId, _originalDepthFade * 2f); } } } } namespace SwimmingReworked.Effects { internal class DiveImmersionEffect : MonoBehaviour { internal static bool IsUnderwaterImmersionActive; private AudioLowPassFilter _lowPass; private bool _active; private float _intensity; private bool _fogSaved; private bool _savedFog; private FogMode _savedFogMode; private float _savedFogDensity; private Color _savedFogColor; private Behaviour _ownedHeatDistort; private Type _heatDistortType; private Behaviour _sunShafts; private bool _sunShaftsSaved; private bool _sunShaftsWasEnabled; private float _savedSunShaftIntensity; private float _savedSunShaftBlurRadius; private float _savedSunShaftMaxRadius; private int _savedSunShaftRadialBlurIterations; private const float EnterSwimDepth = 2.15f; private const float ExitSwimDepth = 1.75f; private const float EnterCameraDepth = 0.45f; private const float ExitCameraDepth = 0.2f; private const float FadeSpeed = 2.5f; private const float UnderwaterFogDensity = 0.018f; private const float HeatDistortionIntensity = 2f; private static readonly Color UnderwaterFogColor = new Color(0.025f, 0.1f, 0.13f, 1f); private static readonly Color HeatDistortionColor = new Color(0.05f, 0.35f, 0.55f, 0.2f); private void Update() { if (ShouldUseDiveEffect()) { _active = true; } else if (_active && ShouldExitDiveEffect()) { _active = false; } _intensity = Mathf.MoveTowards(_intensity, _active ? 1f : 0f, Time.deltaTime * 2.5f); bool flag = (IsUnderwaterImmersionActive = _intensity > 0.001f); EnsureHeatDistortion(); if ((Object)(object)_ownedHeatDistort != (Object)null) { _ownedHeatDistort.enabled = flag; ApplyHeatDistortionValues(); } UpdateSunShafts(flag); if (flag) { ApplyFog(); ApplyAudio(); } else { RestoreFog(); RestoreAudio(); } } private void LateUpdate() { if (IsUnderwaterImmersionActive) { UpdateSunShafts(underwater: true); } } private bool ShouldUseDiveEffect() { //IL_007d: 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) if (!SwimmingReworked.IsEnabled()) { return false; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)GameCamera.instance == (Object)null) { return false; } if (!WaterHelper.IsBodyInWater(localPlayer)) { return false; } Camera component = ((Component)GameCamera.instance).GetComponent(); if ((Object)(object)component == (Object)null) { return false; } if (!WaterHelper.TryGetWaterLevel(((Component)component).transform.position, out var waterLevel)) { return false; } float num = waterLevel - ((Component)component).transform.position.y; return ((Character)localPlayer).m_swimDepth >= 2.15f && num >= 0.45f; } private bool ShouldExitDiveEffect() { //IL_0066: 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) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)GameCamera.instance == (Object)null) { return true; } if (!WaterHelper.IsBodyInWater(localPlayer)) { return true; } Camera component = ((Component)GameCamera.instance).GetComponent(); if ((Object)(object)component == (Object)null) { return true; } if (!WaterHelper.TryGetWaterLevel(((Component)component).transform.position, out var waterLevel)) { return true; } float num = waterLevel - ((Component)component).transform.position.y; return ((Character)localPlayer).m_swimDepth <= 1.75f || num <= 0.2f; } private void EnsureHeatDistortion() { if ((Object)(object)_ownedHeatDistort != (Object)null) { return; } GameCamera instance = GameCamera.instance; Camera val = ((instance != null) ? ((Component)instance).GetComponent() : null); if ((Object)(object)val == (Object)null) { return; } _heatDistortType = AccessTools.TypeByName("HeatDistortImageEffect"); if (_heatDistortType == null) { SwimmingReworked.LogDebug("[DiveImmersion] HeatDistortImageEffect type not found."); return; } Component component = ((Component)val).GetComponent(_heatDistortType); ref Behaviour ownedHeatDistort = ref _ownedHeatDistort; Component obj = ((Component)val).gameObject.AddComponent(_heatDistortType); ownedHeatDistort = (Behaviour)(object)((obj is Behaviour) ? obj : null); if ((Object)(object)_ownedHeatDistort == (Object)null) { Debug.LogWarning((object)"[DiveImmersion] Failed to add owned HeatDistortImageEffect."); return; } if ((Object)(object)component != (Object)null) { CopyFields(component, (Component)(object)_ownedHeatDistort); } _ownedHeatDistort.enabled = false; ApplyHeatDistortionValues(); SwimmingReworked.LogDebug("[DiveImmersion] Created owned HeatDistortImageEffect."); } private void ApplyHeatDistortionValues() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_ownedHeatDistort == (Object)null)) { Type type = ((object)_ownedHeatDistort).GetType(); SetField(type, _ownedHeatDistort, "m_intensity", 2f * _intensity); SetField(type, _ownedHeatDistort, "m_color", HeatDistortionColor); } } private void EnsureSunShafts() { if ((Object)(object)_sunShafts != (Object)null || (Object)(object)GameCamera.instance == (Object)null) { return; } Camera component = ((Component)GameCamera.instance).GetComponent(); if ((Object)(object)component == (Object)null) { return; } Behaviour[] components = ((Component)component).GetComponents(); foreach (Behaviour val in components) { if (!((Object)(object)val == (Object)null)) { string text = ((object)val).GetType().FullName ?? ((object)val).GetType().Name; if (text == "UnityStandardAssets.ImageEffects.SunShafts" || text.Contains("SunShafts")) { _sunShafts = val; SwimmingReworked.LogDebug("[DiveImmersion] Found SunShafts: " + text); break; } } } } private void UpdateSunShafts(bool underwater) { EnsureSunShafts(); if ((Object)(object)_sunShafts == (Object)null) { return; } Type type = ((object)_sunShafts).GetType(); if (underwater) { if (!_sunShaftsSaved) { _sunShaftsWasEnabled = _sunShafts.enabled; _savedSunShaftIntensity = GetField(type, _sunShafts, "sunShaftIntensity", 1.15f); _savedSunShaftBlurRadius = GetField(type, _sunShafts, "sunShaftBlurRadius", 2.5f); _savedSunShaftMaxRadius = GetField(type, _sunShafts, "maxRadius", 0.75f); _savedSunShaftRadialBlurIterations = GetField(type, _sunShafts, "radialBlurIterations", 2); _sunShaftsSaved = true; } SetField(type, _sunShafts, "sunShaftIntensity", 0f); SetField(type, _sunShafts, "sunShaftBlurRadius", 0f); SetField(type, _sunShafts, "maxRadius", 0f); SetField(type, _sunShafts, "radialBlurIterations", 0); _sunShafts.enabled = false; } else if (_sunShaftsSaved) { SetField(type, _sunShafts, "sunShaftIntensity", _savedSunShaftIntensity); SetField(type, _sunShafts, "sunShaftBlurRadius", _savedSunShaftBlurRadius); SetField(type, _sunShafts, "maxRadius", _savedSunShaftMaxRadius); SetField(type, _sunShafts, "radialBlurIterations", _savedSunShaftRadialBlurIterations); _sunShafts.enabled = _sunShaftsWasEnabled; _sunShaftsSaved = false; } } private static void CopyFields(Component source, Component target) { if ((Object)(object)source == (Object)null || (Object)(object)target == (Object)null) { return; } Type type = ((object)source).GetType(); FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (!fieldInfo.IsInitOnly && !fieldInfo.IsLiteral) { try { fieldInfo.SetValue(target, fieldInfo.GetValue(source)); } catch { } } } } private static void SetField(Type type, object instance, string fieldName, T value) { FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { return; } try { field.SetValue(instance, value); } catch { } } private static T GetField(Type type, object instance, string fieldName, T fallback) { FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { return fallback; } try { object value = field.GetValue(instance); if (value is T) { T result = (T)value; if (true) { return result; } } } catch { } return fallback; } private void ApplyFog() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_001b: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (!_fogSaved) { _savedFog = RenderSettings.fog; _savedFogMode = RenderSettings.fogMode; _savedFogDensity = RenderSettings.fogDensity; _savedFogColor = RenderSettings.fogColor; _fogSaved = true; } RenderSettings.fog = true; RenderSettings.fogMode = (FogMode)2; RenderSettings.fogDensity = Mathf.Lerp(_savedFogDensity, 0.018f, _intensity); RenderSettings.fogColor = Color.Lerp(_savedFogColor, UnderwaterFogColor, _intensity); } private void RestoreFog() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (_fogSaved) { RenderSettings.fog = _savedFog; RenderSettings.fogMode = _savedFogMode; RenderSettings.fogDensity = _savedFogDensity; RenderSettings.fogColor = _savedFogColor; _fogSaved = false; } } private void ApplyAudio() { AudioListener val = Object.FindFirstObjectByType(); if ((Object)(object)val == (Object)null) { return; } if ((Object)(object)_lowPass == (Object)null) { _lowPass = ((Component)val).gameObject.GetComponent(); if ((Object)(object)_lowPass == (Object)null) { _lowPass = ((Component)val).gameObject.AddComponent(); } } ((Behaviour)_lowPass).enabled = true; _lowPass.cutoffFrequency = Mathf.Lerp(22000f, 1700f, _intensity); _lowPass.lowpassResonanceQ = Mathf.Lerp(1f, 1.25f, _intensity); } private void RestoreAudio() { if ((Object)(object)_lowPass != (Object)null) { ((Behaviour)_lowPass).enabled = false; _lowPass = null; } } private void OnDestroy() { IsUnderwaterImmersionActive = false; UpdateSunShafts(underwater: false); RestoreFog(); RestoreAudio(); if ((Object)(object)_ownedHeatDistort != (Object)null) { Object.Destroy((Object)(object)_ownedHeatDistort); } } } }