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 SwimmingReworked v1.0.5
SwimmingReworked.dll
Decompiled a week agousing 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<Image> _bubbles = new List<Image>(); 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<Canvas>(); val.renderMode = (RenderMode)0; val.sortingOrder = 5000; CanvasScaler val2 = _root.AddComponent<CanvasScaler>(); val2.uiScaleMode = (ScaleMode)1; val2.referenceResolution = new Vector2(1920f, 1080f); _root.AddComponent<GraphicRaycaster>(); GameObject val3 = new GameObject("Container"); val3.transform.SetParent(_root.transform, false); _container = val3.AddComponent<RectTransform>(); _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<RectTransform>(); val5.sizeDelta = new Vector2(12f, 12f); Image val6 = val4.AddComponent<Image>(); 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<Text>(); _breathText.font = Resources.GetBuiltinResource<Font>("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<Player> OnEnterWater; public static event Action<Player> OnExitWater; public static event Action<Player> OnHeadUnderwater; public static event Action<Player> OnHeadAboveWater; public static event Action<Player> 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<bool> EnableMod; internal static ConfigEntry<float> MaxBreathSeconds; internal static ConfigEntry<float> MaxBreathBonusAtSkill100; internal static ConfigEntry<float> BreathRecoveryPerSecond; internal static ConfigEntry<float> SuffocationDamagePercentPerTick; internal static ConfigEntry<float> SuffocationTickInterval; internal static ConfigEntry<float> SprintSwimMultiplier; internal static ConfigEntry<float> SprintStaminaPerSecond; internal static ConfigEntry<float> VerticalSwimSpeed; internal static ConfigEntry<float> MinSwimSpeed; internal static ConfigEntry<float> MaxSwimSpeedAtSkill100; internal static ConfigEntry<bool> AllowUnderwaterSprint; internal static ConfigEntry<bool> DisableVanillaSwimStaminaDrain; internal static ConfigEntry<bool> DisableVanillaDrowningFromStamina; internal static ConfigEntry<float> BaseUnderwaterStaminaRegenPerSecond; internal static ConfigEntry<float> MaxSwimSkillBonusStaminaRegenPerSecond; internal static ConfigEntry<bool> DebugLogging; private ConfigFileWatcher _configWatcher; internal static ConfigEntry<float> BreathHudOffsetX; internal static ConfigEntry<float> BreathHudOffsetY; internal static ConfigEntry<float> BreathHudScale; internal static ConfigEntry<bool> 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<BreathHud>(); ((Component)this).gameObject.AddComponent<DiveImmersionEffect>(); 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<float>("Breath HUD", "OffsetX", -40f, "Horizontal offset from right edge of screen (negative = left)."); BreathHudOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Breath HUD", "OffsetY", 0f, "Vertical offset from center of screen."); BreathHudScale = ((BaseUnityPlugin)this).Config.Bind<float>("Breath HUD", "Scale", 1f, "Scale multiplier for the breath indicator."); AcceptableValueBase val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.3f, 3f); BreathHudScale = ((BaseUnityPlugin)this).Config.Bind<float>("Breath HUD", "Scale", 1f, new ConfigDescription("Scale multiplier for the breath indicator.", val, Array.Empty<object>())); BreathHudShowLabels = ((BaseUnityPlugin)this).Config.Bind<bool>("Breath HUD", "ShowLabels", false, "Show numeric breath value next to bubbles."); EnableMod = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "General", "EnableMod", true, "Enable or disable the mod.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config = ((BaseUnityPlugin)this).Config; AcceptableValueBase val2 = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 600f); MaxBreathSeconds = ConfigFileExtensions.BindConfig<float>(config, "Breath", "MaxBreathSeconds", 30f, "Maximum underwater breath at Swim skill 0.", true, (int?)null, val2, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config2 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f); MaxBreathBonusAtSkill100 = ConfigFileExtensions.BindConfig<float>(config2, "Breath", "MaxBreathBonusAtSkill100", 150f, "Additional breath time gained at Swim skill 100.", true, (int?)null, val2, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config3 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f); BreathRecoveryPerSecond = ConfigFileExtensions.BindConfig<float>(config3, "Breath", "BreathRecoveryPerSecond", 30f, "Breath recovered per second when not underwater.", true, (int?)null, val2, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config4 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f); SuffocationDamagePercentPerTick = ConfigFileExtensions.BindConfig<float>(config4, "Breath", "SuffocationDamagePercentPerTick", 10f, "Percent of max health lost each suffocation tick when breath reaches 0.", true, (int?)null, val2, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config5 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 30f); SuffocationTickInterval = ConfigFileExtensions.BindConfig<float>(config5, "Breath", "SuffocationTickInterval", 2f, "Seconds between suffocation damage ticks when breath reaches 0.", true, (int?)null, val2, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config6 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f); SprintSwimMultiplier = ConfigFileExtensions.BindConfig<float>(config6, "Movement", "SprintSwimMultiplier", 1.75f, "Sprint speed multiplier while swimming.", true, (int?)null, val2, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config7 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f); SprintStaminaPerSecond = ConfigFileExtensions.BindConfig<float>(config7, "Movement", "SprintStaminaPerSecond", 8f, "Stamina drained per second while sprint swimming.", true, (int?)null, val2, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config8 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 20f); VerticalSwimSpeed = ConfigFileExtensions.BindConfig<float>(config8, "Movement", "VerticalSwimSpeed", 3f, "Vertical swimming speed while diving.", true, (int?)null, val2, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); AllowUnderwaterSprint = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Movement", "AllowUnderwaterSprint", true, "Allow sprinting underwater.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); DisableVanillaSwimStaminaDrain = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Vanilla Overrides", "DisableVanillaSwimStaminaDrain", true, "Disables vanilla stamina drain for normal swimming.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); DisableVanillaDrowningFromStamina = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Vanilla Overrides", "DisableVanillaDrowningFromStamina", true, "Disables vanilla drowning behavior caused by stamina depletion.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config9 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f); BaseUnderwaterStaminaRegenPerSecond = ConfigFileExtensions.BindConfig<float>(config9, "Movement", "BaseUnderwaterStaminaRegenPerSecond", 2f, "Base stamina regenerated per second while swimming and not sprinting.", true, (int?)null, val2, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config10 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f); MaxSwimSkillBonusStaminaRegenPerSecond = ConfigFileExtensions.BindConfig<float>(config10, "Movement", "MaxSwimSkillBonusStaminaRegenPerSecond", 4f, "Additional stamina regenerated per second at Swim skill 100.", true, (int?)null, val2, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config11 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f); MinSwimSpeed = ConfigFileExtensions.BindConfig<float>(config11, "Movement", "MinSwimSpeed", 1f, "Swim speed multiplier at Swim skill 0.", true, (int?)null, val2, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config12 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f); MaxSwimSpeedAtSkill100 = ConfigFileExtensions.BindConfig<float>(config12, "Movement", "MaxSwimSpeedAtSkill100", 2f, "Swim speed multiplier at Swim skill 100.", true, (int?)null, val2, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("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<long, SwimState> States = new Dictionary<long, SwimState>(); 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<Rigidbody>(); if ((Object)(object)component != (Object)null) { component.useGravity = true; } HandleBreath(__instance, headUnderwater: false); return; } Rigidbody component2 = ((Component)__instance).GetComponent<Rigidbody>(); 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>(); 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<MeshRenderer, GameObject> UnderwaterCopies = new Dictionary<MeshRenderer, GameObject>(); 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<MeshRenderer>(); MeshFilter component2 = ((Component)__instance.m_waterSurface).GetComponent<MeshFilter>(); 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<MeshFilter>(); val2.sharedMesh = originalFilter.sharedMesh; MeshRenderer val3 = val.AddComponent<MeshRenderer>(); ((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<Camera>(); 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<Camera>(); 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<Camera>(); 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<Camera>() : 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<Color>(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<Camera>(); if ((Object)(object)component == (Object)null) { return; } Behaviour[] components = ((Component)component).GetComponents<Behaviour>(); 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<T>(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<T>(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<AudioListener>(); if ((Object)(object)val == (Object)null) { return; } if ((Object)(object)_lowPass == (Object)null) { _lowPass = ((Component)val).gameObject.GetComponent<AudioLowPassFilter>(); if ((Object)(object)_lowPass == (Object)null) { _lowPass = ((Component)val).gameObject.AddComponent<AudioLowPassFilter>(); } } ((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); } } } }