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<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);
}
}
}
}