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 DeepWater v0.15.3
DeepWater.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.PostProcessing; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("DeepWater")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.15.3.0")] [assembly: AssemblyInformationalVersion("0.15.3+fbc42aa77c068edfbfb244d3613369618f0518fc")] [assembly: AssemblyProduct("DeepWater")] [assembly: AssemblyTitle("DeepWater")] [assembly: AssemblyVersion("0.15.3.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DeepWater { internal sealed class Breath : MonoBehaviour { private static ConfigEntry<bool> _enabled; private static ConfigEntry<bool> _noUnderwaterRegen; private static ConfigEntry<bool> _skills; private static ConfigEntry<float> _baseBreath; private static ConfigEntry<float> _maxBreath; internal static readonly SkillType BreathSkill = (SkillType)StringExtensionMethods.GetStableHashCode("VoxelTerrain.BreathHold"); internal static float Value = -1f; internal static bool HeadUnder; private float _drownTimer; private float _breathSkillTimer; private float _hideTimer; private static SkillDef _breathDef; private static readonly FieldRef<Player, float> _stamina = AccessTools.FieldRefAccess<Player, float>("m_stamina"); private static float _staminaBefore; private static ConfigEntry<float> _swimCost; private static ConfigEntry<float> _fastSwimCost; private static ConfigEntry<float> _fastSwimSpeed; private static readonly FieldRef<Character, bool> _run = AccessTools.FieldRefAccess<Character, bool>("m_run"); private static float _swimStaminaBefore; private static float _savedSwimSpeed = -1f; internal static bool FastSwim; private static Action<Player, Vector3, float> _onSwimming; private GameObject _bar; private RectTransform _barRoot; private GuiBar[] _bars; private Animator _anim; private Component _text; private PropertyInfo _textProp; private bool _barFailed; private static readonly int s_visible = Animator.StringToHash("Visible"); private static readonly FieldRef<Hud, float> _border = AccessTools.FieldRefAccess<Hud, float>("m_staminaBarBorderBuffer"); public static void Bind(ConfigFile cfg, Harmony harmony) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Expected O, but got Unknown //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Expected O, but got Unknown //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Expected O, but got Unknown //IL_01b2: Expected O, but got Unknown //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Expected O, but got Unknown //IL_020e: Expected O, but got Unknown //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Expected O, but got Unknown //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Expected O, but got Unknown //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Expected O, but got Unknown //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Expected O, but got Unknown //IL_0313: Expected O, but got Unknown //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Expected O, but got Unknown _enabled = cfg.Bind<bool>("Gameplay", "HoldBreath", true, "Under water you hold your breath: when it runs out you drown (damage every second). It comes back at the surface."); _baseBreath = cfg.Bind<float>("Gameplay", "BreathSeconds", 30f, new ConfigDescription("How long you can hold your breath at skill 0 (s).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 600f), Array.Empty<object>())); _maxBreath = cfg.Bind<float>("Gameplay", "BreathSecondsAtMaxSkill", 90f, new ConfigDescription("How long you can hold your breath at skill 100 (s).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 1200f), Array.Empty<object>())); _noUnderwaterRegen = cfg.Bind<bool>("Gameplay", "NoStaminaRegenUnderWater", true, "With the head under water stamina doesn't come back, also standing on the bottom (vanilla: full regeneration as on land)."); _skills = cfg.Bind<bool>("Gameplay", "BreathSkill", true, "Skill 'Breath holding': rises under water, longer breath."); _swimCost = cfg.Bind<float>("Gameplay", "SwimStaminaFactor", 0.5f, new ConfigDescription("Stamina cost of normal swimming, times vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>())); _fastSwimCost = cfg.Bind<float>("Gameplay", "FastSwimStaminaFactor", 2f, new ConfigDescription("Stamina cost of fast swimming (hold Run), times vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>())); _fastSwimSpeed = cfg.Bind<float>("Gameplay", "FastSwimSpeed", 1.6f, new ConfigDescription("Fast swimming (hold Run) speed, times normal swimming. 1 = off.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 4f), Array.Empty<object>())); harmony.Patch((MethodBase)AccessTools.Method(typeof(Player), "OnSwimming", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Breath), "OnSwimmingPrefix", (Type[])null), new HarmonyMethod(typeof(Breath), "OnSwimmingPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(Character), "UpdateSwimming", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Breath), "SpeedPrefix", (Type[])null) { priority = 800 }, new HarmonyMethod(typeof(Breath), "SpeedPostfix", (Type[])null) { priority = 0 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(Skills), "IsSkillValid", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Breath), "IsSkillValidPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(Skills), "GetSkillDef", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Breath), "GetSkillDefPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Breath), "LanguagePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(Player), "UpdateStats", new Type[1] { typeof(float) }, (Type[])null), new HarmonyMethod(typeof(Breath), "StatsPrefix", (Type[])null), new HarmonyMethod(typeof(Breath), "StatsPostfix", (Type[])null) { priority = 0 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(Character), "UpdateSwimming", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Breath), "SwimmingPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static bool Ours(SkillType t) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return t == BreathSkill; } private static void IsSkillValidPostfix(SkillType type, ref bool __result) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) if (!__result && Ours(type)) { __result = true; } } private static bool GetSkillDefPrefix(SkillType type, ref SkillDef __result) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown if (!Ours(type)) { return true; } if (_breathDef == null) { _breathDef = new SkillDef { m_skill = BreathSkill, m_increseStep = 1f }; } _breathDef.m_description = (Russian() ? "Дольше задерживать дыхание под водой." : "Hold your breath longer under water."); if ((Object)(object)_breathDef.m_icon == (Object)null) { _breathDef.m_icon = FindIcon(); } __result = _breathDef; return false; } private static Sprite FindIcon() { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Invalid comparison between Unknown and I4 ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null) { return null; } StatusEffect statusEffect = instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("Wet")); if ((Object)(object)statusEffect != (Object)null && (Object)(object)statusEffect.m_icon != (Object)null) { return statusEffect.m_icon; } Player localPlayer = Player.m_localPlayer; Skills val = (((Object)(object)localPlayer != (Object)null) ? ((Character)localPlayer).GetSkills() : null); if ((Object)(object)val != (Object)null) { foreach (SkillDef skill in val.m_skills) { if ((int)skill.m_skill == 103) { return skill.m_icon; } } } return null; } private static bool Russian() { return PlatformPrefs.GetString("language", "English") == "Russian"; } private static void LanguagePostfix(Localization __instance) { AddWords(__instance); } private static void AddWords(Localization loc) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (loc != null) { MethodInfo methodInfo = AccessTools.Method(typeof(Localization), "AddWord", (Type[])null, (Type[])null); if (!(methodInfo == null)) { methodInfo.Invoke(loc, new object[2] { "skill_" + ((object)BreathSkill/*cast due to .constrained prefix*/).ToString().ToLower(), Russian() ? "Задержка дыхания" : "Breath holding" }); } } } private static void StatsPrefix(Player __instance) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { _staminaBefore = _stamina.Invoke(__instance); } } private static void StatsPostfix(Player __instance) { if (_noUnderwaterRegen.Value && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && (HeadUnder || SwimItems.Underwater)) { ref float reference = ref _stamina.Invoke(__instance); if (reference > _staminaBefore) { reference = _staminaBefore; } } } private static void SpeedPrefix(Character __instance) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //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) if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } Player val = (Player)__instance; int fastSwim; if (_fastSwimSpeed.Value > 1.001f && _run.Invoke(__instance)) { Vector3 moveDir = ((Character)val).GetMoveDir(); if (((Vector3)(ref moveDir)).sqrMagnitude > 0.01f) { fastSwim = (((Character)val).HaveStamina(0f) ? 1 : 0); goto IL_0057; } } fastSwim = 0; goto IL_0057; IL_0057: FastSwim = (byte)fastSwim != 0; if (FastSwim) { _savedSwimSpeed = __instance.m_swimSpeed; __instance.m_swimSpeed *= _fastSwimSpeed.Value; } } private static void SpeedPostfix(Character __instance) { if (!(_savedSwimSpeed < 0f) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { __instance.m_swimSpeed = _savedSwimSpeed; _savedSwimSpeed = -1f; } } private static void OnSwimmingPrefix(Player __instance) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { _swimStaminaBefore = _stamina.Invoke(__instance); } } private static void OnSwimmingPostfix(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { ref float reference = ref _stamina.Invoke(__instance); float num = _swimStaminaBefore - reference; if (!(num <= 0f)) { reference = Mathf.Max(0f, _swimStaminaBefore - num * (FastSwim ? _fastSwimCost.Value : _swimCost.Value)); } } } private static void SwimmingPostfix(Character __instance, float dt) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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) if (!_noUnderwaterRegen.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !__instance.IsOnGround() || (!HeadUnder && !SwimItems.Underwater)) { return; } Player val = (Player)__instance; Vector3 arg = ((Character)val).GetMoveDir() * ((Character)val).m_swimSpeed; if (!(((Vector3)(ref arg)).magnitude <= 0.1f)) { if (_onSwimming == null) { _onSwimming = AccessTools.MethodDelegate<Action<Player, Vector3, float>>(AccessTools.Method(typeof(Player), "OnSwimming", (Type[])null, (Type[])null), (object)null, false); } _onSwimming(val, arg, dt); } } public static float MaxBreath(Player p) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) float num = ((_skills.Value && (Object)(object)p != (Object)null) ? ((Character)p).GetSkillFactor(BreathSkill) : 0f); return Mathf.Max(1f, Mathf.Lerp(_baseBreath.Value, Mathf.Max(_baseBreath.Value, _maxBreath.Value), num)); } private void Update() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Expected O, but got Unknown //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead()) { HeadUnder = false; Value = -1f; ShowBar(visible: false, 0f, 0f, 1f); return; } float deltaTime = Time.deltaTime; float liquidLevel = ((Character)localPlayer).GetLiquidLevel(); HeadUnder = ((Character)localPlayer).InWater() && liquidLevel > -1000f && ((Character)localPlayer).GetHeadPoint().y < liquidLevel - 0.05f; float num = MaxBreath(localPlayer); if (Value < 0f) { Value = num; } if (_enabled.Value && HeadUnder && !((Character)localPlayer).InGodMode() && !((Character)localPlayer).InGhostMode()) { Vector3 moveDir = ((Character)localPlayer).GetMoveDir(); bool flag = ((Vector3)(ref moveDir)).sqrMagnitude > 0.01f || ZInput.GetButton("Jump") || ZInput.GetButton("Crouch"); Value = Mathf.Max(0f, Value - deltaTime * (flag ? 1.5f : 1.05f)); if (Value <= 0f) { _drownTimer += deltaTime; if (_drownTimer > 1f) { _drownTimer = 0f; HitData val = new HitData(); val.m_damage.m_damage = Mathf.Ceil(((Character)localPlayer).GetMaxHealth() / 10f); val.m_point = ((Character)localPlayer).GetCenterPoint(); val.m_dir = Vector3.down; val.m_hitType = (HitType)4; ((Character)localPlayer).Damage(val); localPlayer.m_drownEffects.Create(((Character)localPlayer).GetHeadPoint(), ((Component)localPlayer).transform.rotation, (Transform)null, 1f, -1, default(ZDOID)); } } if (_skills.Value) { _breathSkillTimer += deltaTime; if (_breathSkillTimer > 1f) { _breathSkillTimer = 0f; ((Character)localPlayer).RaiseSkill(BreathSkill, (Value < num * 0.25f) ? 0.6f : 0.4f); } } } else { _drownTimer = 0f; if (!HeadUnder) { Value = Mathf.Min(num, Value + deltaTime * Mathf.Max(num / 2f, 16f)); } } Value = Mathf.Min(Value, num); bool flag2 = _enabled.Value && (HeadUnder || Value < num - 0.01f); _hideTimer = (flag2 ? 0f : (_hideTimer + deltaTime)); ShowBar(_hideTimer < 1f, Value, num, deltaTime); } private void ShowBar(bool visible, float value, float max, float dt) { //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_bar == (Object)null && (!visible || _barFailed || !MakeBar())) { return; } if ((Object)(object)_anim != (Object)null && ((Behaviour)_anim).isActiveAndEnabled) { _anim.SetBool(s_visible, visible); } else { _bar.SetActive(visible); } if (visible || (!((Object)(object)_anim == (Object)null) && ((Behaviour)_anim).isActiveAndEnabled)) { if (!_bar.activeSelf) { _bar.SetActive(true); } Hud instance = Hud.instance; float num = Mathf.Clamp(max * 3f, 60f, 400f); _barRoot.SetSizeWithCurrentAnchors((Axis)0, num + (((Object)(object)instance != (Object)null) ? _border.Invoke(instance) : 0f)); GuiBar[] bars = _bars; foreach (GuiBar obj in bars) { obj.SetWidth(num); obj.SetValue((max > 0f) ? (value / max) : 0f); } if ((Object)(object)instance != (Object)null && (Object)(object)instance.m_staminaBar2Root != (Object)null) { _barRoot.anchoredPosition = instance.m_staminaBar2Root.anchoredPosition + new Vector2(0f, 34f); } if ((Object)(object)_text != (Object)null && _textProp != null) { _textProp.SetValue(_text, Mathf.CeilToInt(value).ToString()); } } } private bool MakeBar() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) Hud instance = Hud.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_eitrBarRoot == (Object)null || (Object)(object)instance.m_staminaBar2Root == (Object)null) { return false; } try { _bar = Object.Instantiate<GameObject>(((Component)instance.m_eitrBarRoot).gameObject, ((Transform)instance.m_staminaBar2Root).parent, false); ((Object)_bar).name = "DeepWater breath bar"; _barRoot = (RectTransform)_bar.transform; _barRoot.anchorMin = instance.m_staminaBar2Root.anchorMin; _barRoot.anchorMax = instance.m_staminaBar2Root.anchorMax; _barRoot.pivot = instance.m_staminaBar2Root.pivot; _bars = _bar.GetComponentsInChildren<GuiBar>(true); Color val = default(Color); ((Color)(ref val))..ctor(0.35f, 0.75f, 1f, 1f); for (int i = 0; i < _bars.Length; i++) { _bars[i].SetColor((Color)((i == 0) ? val : new Color(val.r * 0.6f, val.g * 0.6f, val.b * 0.7f, 1f))); } _anim = _bar.GetComponentInChildren<Animator>(true); Component[] componentsInChildren = _bar.GetComponentsInChildren<Component>(true); foreach (Component val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && ((object)val2).GetType().Name.StartsWith("TextMeshPro")) { _text = val2; _textProp = ((object)val2).GetType().GetProperty("text"); break; } } List<string> list = new List<string>(); Transform[] componentsInChildren2 = _bar.GetComponentsInChildren<Transform>(true); foreach (Transform val3 in componentsInChildren2) { list.Add(((Object)val3).name); } Plugin.Log.LogInfo((object)($"Breath bar from the eitr bar: {_bars.Length} bars, animator {(Object)(object)_anim != (Object)null}, text {(Object)(object)_text != (Object)null}; " + "parts: " + string.Join(", ", list))); return _bars.Length != 0; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Breath bar: " + ex.Message)); if ((Object)(object)_bar != (Object)null) { Object.Destroy((Object)(object)_bar); } _bar = null; _barFailed = true; return false; } } } internal sealed class Bubbles { private sealed class State { public bool HeadUnder; public float NextBreath; public float TrailCarry; } private const float Range = 40f; private ParticleSystem _ps; private readonly Dictionary<Player, State> _state = new Dictionary<Player, State>(); private readonly List<Player> _players = new List<Player>(); private readonly List<Player> _gone = new List<Player>(); private Particle[] _buf = (Particle[])(object)new Particle[256]; private Color _tint = new Color(0.4f, 0.52f, 0.55f, 0.5f); public void Update(Shader additive) { //IL_002a: 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)additive == (Object)null) { return; } _players.Clear(); Player.GetPlayersInRange(((Component)localPlayer).transform.position, 40f, _players); bool flag = false; foreach (Player player in _players) { flag |= UpdatePlayer(player, additive); } if (_state.Count > _players.Count) { _gone.Clear(); foreach (Player key in _state.Keys) { if ((Object)(object)key == (Object)null || !_players.Contains(key)) { _gone.Add(key); } } foreach (Player item in _gone) { _state.Remove(item); } } if ((Object)(object)_ps != (Object)null && _ps.particleCount > 0) { CullAboveSurface(); } if (!flag && (Object)(object)_ps != (Object)null && _ps.particleCount == 0 && ((Component)_ps).gameObject.activeSelf) { ((Component)_ps).gameObject.SetActive(false); } } private void CullAboveSurface() { //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) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) int particleCount = _ps.particleCount; if (_buf.Length < particleCount) { _buf = (Particle[])(object)new Particle[Mathf.NextPowerOfTwo(particleCount)]; } particleCount = _ps.GetParticles(_buf, particleCount); int num = 0; for (int i = 0; i < particleCount; i++) { Vector3 position = ((Particle)(ref _buf[i])).position; float liquidLevel = Floating.GetLiquidLevel(position, 1f, (LiquidType)0); if (!(liquidLevel > -9999f) || !(position.y > liquidLevel - 0.03f)) { _buf[num++] = _buf[i]; } } if (num != particleCount) { _ps.SetParticles(_buf, num); } } private bool UpdatePlayer(Player p, Shader additive) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0165: 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_0195: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_019d: 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_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0274: 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_028d: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_0330: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_033a: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_035b: 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_0367: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)p == (Object)null || ((Character)p).IsDead()) { return false; } Vector3 headPoint = ((Character)p).GetHeadPoint(); float liquidLevel = Floating.GetLiquidLevel(headPoint, 1f, (LiquidType)0); if (!_state.TryGetValue(p, out var value)) { Dictionary<Player, State> state = _state; State obj = new State { NextBreath = Time.time + Random.Range(0.5f, 2f) }; value = obj; state[p] = obj; } if (!(liquidLevel > -9999f) || !(headPoint.y < liquidLevel - 0.05f)) { value.HeadUnder = false; return false; } float num = Mathf.Lerp(1f, 0.5f, Mathf.Clamp01((liquidLevel - headPoint.y) / 25f)) * Mathf.Lerp(0.12f, 1f, Mathf.InverseLerp(0.3f, 1f, Underwater.Daylight)); _tint = new Color(0.6f * num, 0.75f * num, 0.8f * num, 0.75f); if ((Object)(object)_ps == (Object)null && (Object)(object)(_ps = Create(additive)) == (Object)null) { return false; } if (!((Component)_ps).gameObject.activeSelf) { ((Component)_ps).gameObject.SetActive(true); _ps.Play(); } if ((Object)(object)p == (Object)(object)Player.m_localPlayer) { ((Component)_ps).transform.position = headPoint; } Vector3 forward = ((Component)p).transform.forward; Vector3 velocity = ((Character)p).GetVelocity(); if (!value.HeadUnder) { value.HeadUnder = true; Vector3 centerPoint = ((Character)p).GetCenterPoint(); for (int i = 0; i < 28; i++) { Emit(centerPoint + Random.insideUnitSphere * 0.45f, liquidLevel, velocity * 0.2f, Random.Range(0.05f, 0.16f)); } value.NextBreath = Time.time + Random.Range(1.5f, 3f); } if (Time.time >= value.NextBreath) { value.NextBreath = Time.time + Random.Range(2.5f, 4.5f); Vector3 val = headPoint + forward * 0.14f - Vector3.up * 0.06f; int num2 = Random.Range(7, 14); for (int j = 0; j < num2; j++) { Emit(val + Random.insideUnitSphere * 0.04f - Vector3.up * ((float)j * 0.03f), liquidLevel, forward * Random.Range(0.1f, 0.35f), Random.Range(0.03f, 0.11f)); } } float magnitude = ((Vector3)(ref velocity)).magnitude; if (magnitude > 0.4f) { value.TrailCarry += Time.deltaTime * Mathf.Min(magnitude, 6f) * 5f; Vector3 centerPoint2 = ((Character)p).GetCenterPoint(); Vector3 val2 = velocity / magnitude; while (value.TrailCarry >= 1f) { value.TrailCarry -= 1f; Vector3 pos = centerPoint2 + Random.insideUnitSphere * 0.35f - val2 * Random.Range(0f, 0.5f); Emit(pos, liquidLevel, -velocity * 0.08f, Random.Range(0.02f, 0.07f)); } } return true; } private void Emit(Vector3 pos, float level, Vector3 push, float size) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) size *= 0.7f; float num = Mathf.Lerp(0.5f, 1.1f, Mathf.InverseLerp(0.02f, 0.16f, size)); float startLifetime = Mathf.Clamp((level - pos.y - 0.05f) / num, 0.15f, 7f); EmitParams val = default(EmitParams); ((EmitParams)(ref val)).position = pos; ((EmitParams)(ref val)).velocity = push + Vector3.up * num + Underwater.Current * 0.6f; ((EmitParams)(ref val)).startSize = size; ((EmitParams)(ref val)).startLifetime = startLifetime; ((EmitParams)(ref val)).startColor = Color32.op_Implicit(_tint); ((EmitParams)(ref val)).applyShapeToPosition = false; EmitParams val2 = val; _ps.Emit(val2, 1); } private static ParticleSystem Create(Shader additive) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Expected O, but got Unknown //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_019a: 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_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Expected O, but got Unknown //IL_0201: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("DeepWater bubbles"); Object.DontDestroyOnLoad((Object)(object)val); ParticleSystem val2 = val.AddComponent<ParticleSystem>(); val2.Stop(true, (ParticleSystemStopBehavior)0); MainModule main = val2.main; ((MainModule)(ref main)).cullingMode = (ParticleSystemCullingMode)3; ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1; ((MainModule)(ref main)).playOnAwake = false; ((MainModule)(ref main)).maxParticles = 1500; ((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(0f); EmissionModule emission = val2.emission; ((EmissionModule)(ref emission)).enabled = false; ShapeModule shape = val2.shape; ((ShapeModule)(ref shape)).enabled = false; NoiseModule noise = val2.noise; ((NoiseModule)(ref noise)).enabled = true; ((NoiseModule)(ref noise)).strength = MinMaxCurve.op_Implicit(0.35f); ((NoiseModule)(ref noise)).frequency = 1.4f; ((NoiseModule)(ref noise)).scrollSpeed = MinMaxCurve.op_Implicit(0.6f); ((NoiseModule)(ref noise)).quality = (ParticleSystemNoiseQuality)0; SizeOverLifetimeModule sizeOverLifetime = val2.sizeOverLifetime; ((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = true; ((SizeOverLifetimeModule)(ref sizeOverLifetime)).size = new MinMaxCurve(1f, AnimationCurve.Linear(0f, 0.8f, 1f, 1.35f)); ColorOverLifetimeModule colorOverLifetime = val2.colorOverLifetime; ((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true; Gradient val3 = new Gradient(); val3.SetKeys((GradientColorKey[])(object)new GradientColorKey[2] { new GradientColorKey(Color.white, 0f), new GradientColorKey(Color.white, 1f) }, (GradientAlphaKey[])(object)new GradientAlphaKey[4] { new GradientAlphaKey(0f, 0f), new GradientAlphaKey(1f, 0.08f), new GradientAlphaKey(0.9f, 0.85f), new GradientAlphaKey(0f, 1f) }); ((ColorOverLifetimeModule)(ref colorOverLifetime)).color = MinMaxGradient.op_Implicit(val3); ParticleSystemRenderer component = val.GetComponent<ParticleSystemRenderer>(); Material val4 = new Material(additive) { name = "DeepWater bubble", mainTexture = (Texture)(object)BubbleTexture(), renderQueue = 3100 }; val4.SetColor("_TintColor", new Color(0.5f, 0.5f, 0.5f, 0.5f)); ((Renderer)component).sharedMaterial = val4; component.renderMode = (ParticleSystemRenderMode)0; ((Renderer)component).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)component).receiveShadows = false; val2.Play(); return val2; } private static Texture2D BubbleTexture() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(24, 24, (TextureFormat)4, true) { name = "voxel bubble", wrapMode = (TextureWrapMode)1 }; Color[] array = (Color[])(object)new Color[576]; for (int i = 0; i < 24; i++) { for (int j = 0; j < 24; j++) { float num = ((float)j + 0.5f) / 24f * 2f - 1f; float num2 = ((float)i + 0.5f) / 24f * 2f - 1f; float num3 = Mathf.Sqrt(num * num + num2 * num2); float num4 = Mathf.Exp(0f - Mathf.Pow((num3 - 0.7f) / 0.22f, 2f)); float num5 = 0.25f * Mathf.Clamp01(1f - num3); float num6 = num + 0.3f; float num7 = num2 - 0.32f; float num8 = Mathf.Exp((0f - (num6 * num6 + num7 * num7)) / 0.05f); float num9 = Mathf.Clamp01(num4 * 0.8f + num5 + num8 * 0.7f) * Mathf.Clamp01((1f - num3) * 4f); array[i * 24 + j] = new Color(1f, 1f, 1f, num9); } } val.SetPixels(array); val.Apply(true); return val; } public void Destroy() { if ((Object)(object)_ps != (Object)null) { Object.Destroy((Object)(object)((Component)_ps).gameObject); } _ps = null; _state.Clear(); } } internal sealed class Caustics { private struct Wave { public float Kx; public float Ky; public float Amp; public float Phase; public int Cycles; } private const int Frames = 120; private const int Size = 256; private Texture2D[] _frames; private Light _sun; private Texture _savedCookie; private float _savedCookieSize; private bool _applied; private ParticleSystem _rays; private float _phase; private float _wind = 0.3f; private Vector3 _drift; private volatile byte[][] _pixels; private bool _generating; public void Update(Camera cam, bool under, float level, float depth, Shader additive) { //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0129: 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_0133: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) Light val = (((Object)(object)EnvMan.instance != (Object)null) ? EnvMan.instance.m_dirLight : null); if ((Object)(object)EnvMan.instance != (Object)null) { _wind = Mathf.MoveTowards(_wind, EnvMan.instance.GetWindIntensity(), Time.deltaTime * 0.1f); } if (!under || (Object)(object)val == (Object)null) { Restore(); StopRays(); return; } if (!Ready()) { UpdateRays(cam, level, depth, val, additive); return; } if (!_applied || (Object)(object)val != (Object)(object)_sun) { Restore(); _sun = val; _savedCookie = val.cookie; _savedCookieSize = val.cookieSize; _applied = true; } float wind = _wind; Vector3 windDir = EnvMan.instance.GetWindDir(); _phase += Time.deltaTime * Mathf.Lerp(7f, 20f, wind * wind); _drift += new Vector3(windDir.x, 0f, windDir.z) * (Time.deltaTime * Mathf.Lerp(0.1f, 0.8f, wind)); if (((Vector3)(ref _drift)).sqrMagnitude > 1000000f) { _drift = Vector3.zero; } if (_phase > 600000f) { _phase -= 600000f; } val.cookie = Current(); val.cookieSize = 8f; ((Component)val).transform.position = -((Component)val).transform.forward * 3000f + _drift; UpdateRays(cam, level, depth, val, additive); } public void Prewarm() { if (_frames == null) { Ready(); } } public void Suspend() { if (_applied && (Object)(object)_sun != (Object)null) { _sun.cookie = _savedCookie; } } public void Resume() { if (_applied && (Object)(object)_sun != (Object)null && _frames != null) { _sun.cookie = Current(); } } private Texture Current() { return (Texture)(object)_frames[(int)_phase % 120]; } public void Restore() { if (_applied) { if ((Object)(object)_sun != (Object)null) { _sun.cookie = _savedCookie; _sun.cookieSize = _savedCookieSize; } _applied = false; } } private void StartGenerate() { _generating = true; ThreadPool.QueueUserWorkItem(delegate { try { _pixels = Build(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Caustics generation failed: " + ex.Message)); } }); } private bool Ready() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown if (_frames != null) { return true; } if (!_generating) { StartGenerate(); } byte[][] pixels = _pixels; if (pixels == null) { return false; } _frames = (Texture2D[])(object)new Texture2D[120]; for (int i = 0; i < 120; i++) { Texture2D val = new Texture2D(256, 256, (TextureFormat)1, true) { name = "voxel caustics " + i, wrapMode = (TextureWrapMode)0, filterMode = (FilterMode)2, anisoLevel = 2 }; val.SetPixelData<byte>(pixels[i], 0, 0); val.Apply(true, true); _frames[i] = val; } _pixels = null; Plugin.Log.LogInfo((object)$"Caustics: {120} frames ({256}x{256}) generated"); return true; } private static byte[][] Build() { Wave[] array = new Wave[8] { new Wave { Kx = 3f, Ky = 1f, Amp = 1f, Phase = 0.3f, Cycles = 1 }, new Wave { Kx = 4f, Ky = -1f, Amp = 0.75f, Phase = 1.9f, Cycles = 2 }, new Wave { Kx = 5f, Ky = 2f, Amp = 0.45f, Phase = 4.1f, Cycles = -2 }, new Wave { Kx = 2f, Ky = -3f, Amp = 0.55f, Phase = 2.7f, Cycles = 1 }, new Wave { Kx = 7f, Ky = 1f, Amp = 0.22f, Phase = 5.3f, Cycles = 3 }, new Wave { Kx = 1f, Ky = 4f, Amp = 0.3f, Phase = 0.9f, Cycles = -1 }, new Wave { Kx = 6f, Ky = -4f, Amp = 0.14f, Phase = 3.3f, Cycles = 3 }, new Wave { Kx = 9f, Ky = 3f, Amp = 0.08f, Phase = 1.4f, Cycles = -3 } }; byte[][] array2 = new byte[120][]; float[] array3 = new float[65536]; float[] array4 = new float[65536]; float num = 3.0625f; for (int i = 0; i < 120; i++) { Array.Clear(array3, 0, array3.Length); float num2 = (float)i / 120f; for (int j = 0; j < 448; j++) { for (int k = 0; k < 448; k++) { float num3 = ((float)k + 0.5f) / 448f; float num4 = ((float)j + 0.5f) / 448f; float num5 = 0f; float num6 = 0f; Wave[] array5 = array; for (int l = 0; l < array5.Length; l++) { Wave wave = array5[l]; float num7 = wave.Amp * Mathf.Cos((float)Math.PI * 2f * (wave.Kx * num3 + wave.Ky * num4 + (float)wave.Cycles * num2) + wave.Phase) * ((float)Math.PI * 2f); num5 += num7 * wave.Kx; num6 += num7 * wave.Ky; } float num8 = (num3 - num5 * 0.003f) * 256f - 0.5f; float num9 = (num4 - num6 * 0.003f) * 256f - 0.5f; int num10 = Mathf.FloorToInt(num8); int num11 = Mathf.FloorToInt(num9); float num12 = num8 - (float)num10; float num13 = num9 - (float)num11; int num14 = (num10 % 256 + 256) % 256; int num15 = (num14 + 1) % 256; int num16 = (num11 % 256 + 256) % 256; int num17 = (num16 + 1) % 256; array3[num16 * 256 + num14] += (1f - num12) * (1f - num13); array3[num16 * 256 + num15] += num12 * (1f - num13); array3[num17 * 256 + num14] += (1f - num12) * num13; array3[num17 * 256 + num15] += num12 * num13; } } for (int m = 0; m < 2; m++) { Blur(array3, array4, 3, horizontal: true); Blur(array4, array3, 3, horizontal: false); } byte[] array6 = new byte[65536]; for (int n = 0; n < array3.Length; n++) { float num18 = array3[n] / num; float num19 = 0.4f + 0.6f * (1f - Mathf.Exp(-0.55f * num18)); array6[n] = (byte)Mathf.Clamp(Mathf.RoundToInt(Mathf.Clamp01(num19) * 255f), 0, 255); } array2[i] = array6; } return array2; } private static void Blur(float[] src, float[] dst, int r, bool horizontal) { float num = 1f / (float)(2 * r + 1); for (int i = 0; i < 256; i++) { for (int j = 0; j < 256; j++) { float num2 = 0f; for (int k = -r; k <= r; k++) { int num3 = (horizontal ? ((j + k + 256) % 256) : j); int num4 = (horizontal ? i : ((i + k + 256) % 256)); num2 += src[num4 * 256 + num3]; } dst[i * 256 + j] = num2 * num; } } } private void UpdateRays(Camera cam, float level, float depth, Light sun, Shader additive) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: 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_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) Vector3 val = -((Component)sun).transform.forward; if ((Object)(object)additive == (Object)null || val.y < 0.1f || depth > 0.6f) { StopRays(); return; } if ((Object)(object)_rays == (Object)null) { _rays = CreateRays(additive); } if (!((Object)(object)_rays == (Object)null)) { Vector3 val2 = -val; Vector3 val3 = new Vector3(val2.x, 0f, val2.z) / 1.333f; Vector3 val4 = new Vector3(val3.x, 0f - Mathf.Sqrt(Mathf.Max(0.05f, 1f - ((Vector3)(ref val3)).sqrMagnitude)), val3.z); Vector3 normalized = ((Vector3)(ref val4)).normalized; Vector3 position = ((Component)cam).transform.position; ((Component)_rays).transform.position = new Vector3(position.x, Mathf.Min(level - 1f, position.y + 10f), position.z); MainModule main = _rays.main; ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0.01f); VelocityOverLifetimeModule velocityOverLifetime = _rays.velocityOverLifetime; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).enabled = true; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).space = (ParticleSystemSimulationSpace)1; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).x = MinMaxCurve.op_Implicit(normalized.x * 0.4f); ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).y = MinMaxCurve.op_Implicit(normalized.y * 0.4f); ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).z = MinMaxCurve.op_Implicit(normalized.z * 0.4f); float num = Mathf.Clamp01(val.y * 2f) * (1f - depth / 0.6f); ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(0.55f, 0.85f, 0.8f, 0.07f * num)); if (!_rays.isEmitting) { _rays.Play(); } } } private void StopRays() { if ((Object)(object)_rays != (Object)null && _rays.isEmitting) { _rays.Stop(true, (ParticleSystemStopBehavior)1); } } private static ParticleSystem CreateRays(Shader additive) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Expected O, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Expected O, but got Unknown //IL_01eb: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("DeepWater god rays"); Object.DontDestroyOnLoad((Object)(object)val); ParticleSystem val2 = val.AddComponent<ParticleSystem>(); val2.Stop(true, (ParticleSystemStopBehavior)0); MainModule main = val2.main; ((MainModule)(ref main)).cullingMode = (ParticleSystemCullingMode)3; ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1; ((MainModule)(ref main)).startLifetime = new MinMaxCurve(4f, 7f); ((MainModule)(ref main)).startSize = new MinMaxCurve(0.8f, 2.2f); ((MainModule)(ref main)).maxParticles = 220; ((MainModule)(ref main)).playOnAwake = false; EmissionModule emission = val2.emission; ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(30f); ShapeModule shape = val2.shape; ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)5; ((ShapeModule)(ref shape)).scale = new Vector3(40f, 2f, 40f); ColorOverLifetimeModule colorOverLifetime = val2.colorOverLifetime; ((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true; Gradient val3 = new Gradient(); val3.SetKeys((GradientColorKey[])(object)new GradientColorKey[2] { new GradientColorKey(Color.white, 0f), new GradientColorKey(Color.white, 1f) }, (GradientAlphaKey[])(object)new GradientAlphaKey[4] { new GradientAlphaKey(0f, 0f), new GradientAlphaKey(1f, 0.35f), new GradientAlphaKey(1f, 0.65f), new GradientAlphaKey(0f, 1f) }); ((ColorOverLifetimeModule)(ref colorOverLifetime)).color = MinMaxGradient.op_Implicit(val3); ParticleSystemRenderer component = val.GetComponent<ParticleSystemRenderer>(); component.renderMode = (ParticleSystemRenderMode)1; component.lengthScale = 0f; component.velocityScale = 45f; ((Renderer)component).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)component).receiveShadows = false; Material val4 = new Material(additive) { name = "DeepWater god ray", mainTexture = (Texture)(object)RayTexture(), renderQueue = 3100 }; val4.SetColor("_TintColor", new Color(0.5f, 0.5f, 0.5f, 0.5f)); ((Renderer)component).sharedMaterial = val4; return val2; } private static Texture2D RayTexture() { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(32, 128, (TextureFormat)4, false) { name = "voxel ray", wrapMode = (TextureWrapMode)1 }; Color[] array = (Color[])(object)new Color[4096]; for (int i = 0; i < 128; i++) { for (int j = 0; j < 32; j++) { float num = 1f - Mathf.Abs(((float)j + 0.5f) / 32f * 2f - 1f); float num2 = Mathf.Sin(((float)i + 0.5f) / 128f * (float)Math.PI); float num3 = Mathf.Pow(num, 2.5f) * num2; array[i * 32 + j] = new Color(1f, 1f, 1f, num3); } } val.SetPixels(array); val.Apply(); return val; } public void Destroy() { Restore(); if ((Object)(object)_rays != (Object)null) { Object.Destroy((Object)(object)((Component)_rays).gameObject); } if (_frames == null) { return; } Texture2D[] frames = _frames; foreach (Texture2D val in frames) { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } } } [BepInPlugin("moxy.deepwater", "DeepWater", "0.15.3")] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "moxy.deepwater"; public const string Version = "0.15.3"; internal static ManualLogSource Log; private ConfigEntry<float> _seaDepth; private float _nextSeaDepth; private Harmony _harmony; private readonly HashSet<int> _seaDepthLogged = new HashSet<int>(); private readonly float[] _seaDepthArr = new float[4]; private static readonly FieldRef<WaterVolume, float[]> _wvDepth = AccessTools.FieldRefAccess<WaterVolume, float[]>("m_normalizedDepth"); private static readonly FieldRef<WaterVolume, float> _wvOneDepth = AccessTools.FieldRefAccess<WaterVolume, float>("m_oneDepth"); private static ManualLogSource Quiet(ManualLogSource real) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown ManualLogSource val = new ManualLogSource(real.SourceName); val.LogEvent += delegate(object s, LogEventArgs e) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) if ((e.Level & 0xF) != 0) { real.Log(e.Level, e.Data); } }; return val; } private void Awake() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; if (!((BaseUnityPlugin)this).Config.Bind<bool>("General", "DeveloperMode", false, "The developer's diagnostic log lines. Off: only warnings and errors are logged.").Value) { Log = Quiet(((BaseUnityPlugin)this).Logger); } _seaDepth = ((BaseUnityPlugin)this).Config.Bind<float>("Water", "MinSeaDepthLook", 1f, new ConfigDescription("The game colours (and sizes the waves of) each 64 m water tile by the depth at its 4 corners: shore tiles turn brown without the blue wave pattern, with a hard edge to the next tile. Every tile is shaded at least this deep (0..1, 1 = like the open sea everywhere, no seams). -1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 1f), Array.Empty<object>())); _harmony = new Harmony("moxy.deepwater"); SwimItems.Bind(((BaseUnityPlugin)this).Config, _harmony); Breath.Bind(((BaseUnityPlugin)this).Config, _harmony); UnderwaterAudio.Patch(_harmony); UnderwaterSfx.Patch(_harmony); Underwater._flipY = ((BaseUnityPlugin)this).Config.Bind<bool>("Look", "UndersideFlipY", false, "Flip the world-above picture seen through the water surface (if it's upside down on your system)."); ((Component)this).gameObject.AddComponent<Underwater>(); ((Component)this).gameObject.AddComponent<Breath>(); Log.LogInfo((object)"DeepWater 0.15.3 loaded."); } private void Update() { if (!(Time.unscaledTime < _nextSeaDepth)) { _nextSeaDepth = Time.unscaledTime + 0.5f; ApplySeaDepth(); } } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void ApplySeaDepth() { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) float value = _seaDepth.Value; if (value < 0f) { return; } foreach (WaterVolume instance in WaterVolume.Instances) { if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_waterSurface == (Object)null || instance.m_forceDepth >= 0f) { continue; } float[] array = _wvDepth.Invoke(instance); if (array == null || array.Length < 4) { continue; } bool flag = false; for (int i = 0; i < 4; i++) { if (array[i] < value) { flag = true; } } if (flag && _seaDepthLogged.Add(((Object)instance).GetInstanceID()) && _seaDepthLogged.Count < 40) { Vector2s zone = ZoneSystem.GetZone(((Component)instance).transform.position); Log.LogInfo((object)$"Water tile {zone.x},{zone.y}: corner depths {array[0]:0.00}/{array[1]:0.00}/{array[2]:0.00}/{array[3]:0.00} raised to {value:0.00}"); } for (int j = 0; j < 4; j++) { if (array[j] < value) { array[j] = value; } _seaDepthArr[j] = array[j]; } _wvOneDepth.Invoke(instance) = ((array[0] == array[1] && array[1] == array[2] && array[2] == array[3]) ? array[0] : (-1f)); Material sharedMaterial = ((Renderer)instance.m_waterSurface).sharedMaterial; if ((Object)(object)sharedMaterial != (Object)null && ((Object)sharedMaterial).name.EndsWith("(Instance)")) { sharedMaterial.SetFloatArray("_depth", _seaDepthArr); } } } } internal static class ShaderBundle { private static AssetBundle _bundle; private static bool _tried; public static Shader Get(string name) { if (!_tried) { _tried = true; string text = Path.Combine(Path.GetDirectoryName(typeof(ShaderBundle).Assembly.Location) ?? ".", "deepwater_shaders"); if (File.Exists(text)) { _bundle = AssetBundle.LoadFromFile(text); } Plugin.Log.LogInfo((object)(((Object)(object)_bundle != (Object)null) ? ("Shader bundle loaded: " + string.Join(", ", _bundle.GetAllAssetNames())) : ("Shader bundle not found at " + text))); } if ((Object)(object)_bundle == (Object)null) { return null; } Shader[] array = _bundle.LoadAllAssets<Shader>(); foreach (Shader val in array) { if ((Object)(object)val != (Object)null && ((Object)val).name == name) { if (!val.isSupported) { return null; } return val; } } return null; } } internal static class SwimItems { private static ConfigEntry<bool> _enabled; private static ConfigEntry<bool> _dive; private static ConfigEntry<float> _diveSpeed; private static ConfigEntry<bool> _cameraUnder; private static ConfigEntry<bool> _rideWaves; private static FieldRef<Character, Rigidbody> _body; private static FieldRef<Character, GameObject> _visual = AccessTools.FieldRefAccess<Character, GameObject>("m_visual"); internal static bool Underwater; private static FieldRef<Character, ZSyncAnimation> _zanim = AccessTools.FieldRefAccess<Character, ZSyncAnimation>("m_zanim"); private static readonly int s_inWaterHash = ZSyncAnimation.GetHash("inWater"); private static float _vy; private static ConfigEntry<float> _floatRegen; private static ConfigEntry<float> _wadeSlow; private static readonly FieldRef<Character, CapsuleCollider> _capsule = AccessTools.FieldRefAccess<Character, CapsuleCollider>("m_collider"); private static readonly FieldRef<Player, float> _stamina = AccessTools.FieldRefAccess<Player, float>("m_stamina"); private static readonly FieldRef<Player, float> _regenTimer = AccessTools.FieldRefAccess<Player, float>("m_staminaRegenTimer"); private static bool _vyActive; internal static float Pitch; public static void Bind(ConfigFile cfg, Harmony harmony) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Expected O, but got Unknown //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Expected O, but got Unknown //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Expected O, but got Unknown //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Expected O, but got Unknown //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Expected O, but got Unknown //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Expected O, but got Unknown _enabled = cfg.Bind<bool>("Gameplay", "UseItemsWhileSwimming", true, "Keep tools and weapons usable while swimming (build, dig, hoe, attack). Your own player only."); HarmonyMethod val = new HarmonyMethod(typeof(SwimItems), "Transpiler", (Type[])null); harmony.Patch((MethodBase)AccessTools.Method(typeof(Humanoid), "UpdateEquipment", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(Humanoid), "EquipItem", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(Player), "Update", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null); _dive = cfg.Bind<bool>("Gameplay", "DiveWithCrouch", true, "While swimming, hold Crouch to dive (Jump swims up faster); the camera may follow you under water."); _diveSpeed = cfg.Bind<float>("Gameplay", "DiveSpeed", 3f, new ConfigDescription("Diving speed (m/s).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 10f), Array.Empty<object>())); _rideWaves = cfg.Bind<bool>("Gameplay", "RideWaves", true, "Floating at the surface you stay on top of the waves (vanilla lets big waves wash over you). Dive with Crouch to go under."); _cameraUnder = cfg.Bind<bool>("Gameplay", "CameraUnderWater", true, "The camera may go below the water surface (vanilla keeps it above)."); _body = AccessTools.FieldRefAccess<Character, Rigidbody>("m_body"); _floatRegen = cfg.Bind<float>("Gameplay", "FloatingStaminaRegen", 0.2f, new ConfigDescription("Stamina regenerates at this fraction of the normal rate while you hold still in the water (vanilla: none while swimming). 0 = off.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); harmony.Patch((MethodBase)AccessTools.Method(typeof(Player), "UpdateStats", new Type[1] { typeof(float) }, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(SwimItems), "StatsPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _wadeSlow = cfg.Bind<float>("Gameplay", "SubmergedWalkSpeed", 0.4f, new ConfigDescription("Creatures walking on the bottom fully under water move at this fraction of their land speed (knee deep already ~70%; vanilla barely slows slow walkers). 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>())); harmony.Patch((MethodBase)AccessTools.Method(typeof(Character), "ApplyLiquidResistance", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(SwimItems), "LiquidResistancePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(Character), "UpdateSwimming", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(SwimItems), "SwimPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(GameCamera), "GetCameraPosition", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(SwimItems), "CameraTranspiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); } private static void LiquidResistancePostfix(Character __instance, ref float speed) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) if (!(_wadeSlow.Value >= 0.999f) && !((Object)(object)__instance == (Object)null) && !__instance.IsPlayer()) { float num = __instance.GetLiquidLevel() - ((Component)__instance).transform.position.y; if (!(num <= 0f)) { CapsuleCollider val = _capsule.Invoke(__instance); float num2 = (((Object)(object)val != (Object)null) ? Mathf.Max(0.5f, val.height * ((Component)__instance).transform.lossyScale.y) : 2f); float num3 = Mathf.Clamp01(num / num2); speed *= Mathf.Lerp(1f, _wadeSlow.Value, Mathf.Sqrt(num3)); } } } private static void StatsPostfix(Player __instance, float dt) { //IL_0039: 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) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) if (_floatRegen.Value <= 0f || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !((Character)__instance).IsSwimming() || ((Character)__instance).IsOnGround() || ((Character)__instance).IsDead()) { return; } Vector3 val = ((Character)__instance).GetMoveDir(); if (((Vector3)(ref val)).sqrMagnitude > 0.01f) { return; } val = ((Character)__instance).GetVelocity(); if (!(((Vector3)(ref val)).sqrMagnitude > 1f) && !ZInput.GetButton("Jump") && !ZInput.GetButton("JoyJump") && !ZInput.GetButton("Crouch") && !ZInput.GetButton("JoyCrouch") && !(_regenTimer.Invoke(__instance) > 0f)) { float maxStamina = ((Character)__instance).GetMaxStamina(); ref float reference = ref _stamina.Invoke(__instance); if (!(reference >= maxStamina)) { float num = (__instance.m_staminaRegen + (1f - reference / maxStamina) * __instance.m_staminaRegen * __instance.m_staminaRegenTimeMultiplier) * _floatRegen.Value; reference = Mathf.Min(maxStamina, reference + num * dt * Game.m_staminaRegenRate); } } } private static void SwimPostfix(Character __instance, float dt) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) if (!_dive.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } Player val = (Player)__instance; Rigidbody val2 = _body.Invoke(__instance); if ((Object)(object)val2 == (Object)null) { return; } bool flag = ZInput.GetButton("Crouch") || ZInput.GetButton("JoyCrouch"); bool flag2 = ZInput.GetButton("Jump") || ZInput.GetButton("JoyJump"); float liquidLevel = __instance.GetLiquidLevel(); bool flag3 = ((Component)__instance).transform.position.y < liquidLevel - __instance.m_swimDepth - 0.3f; if (!flag && (!Underwater || !flag3)) { Underwater = false; _vyActive = false; if (_rideWaves.Value && !__instance.IsOnGround()) { RideWaves(__instance, val2, liquidLevel, dt); } return; } Vector3 lookDir = ((Character)val).GetLookDir(); Vector3 val3 = default(Vector3); ((Vector3)(ref val3))..ctor(lookDir.x, 0f, lookDir.z); val3 = ((((Vector3)(ref val3)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref val3)).normalized : ((Component)val).transform.forward); float num = Mathf.Clamp(Vector3.Dot(__instance.GetMoveDir(), val3), -1f, 1f); float num2 = __instance.m_swimSpeed * 1.2f; float num3 = lookDir.y * num * num2; if (flag) { num3 -= _diveSpeed.Value; } if (flag2) { num3 += _diveSpeed.Value * 0.7f; } Vector3 linearVelocity = val2.linearVelocity; if (!_vyActive) { _vy = Mathf.Min(linearVelocity.y, 0f); _vyActive = true; } _vy = Mathf.MoveTowards(_vy, num3, 15f * dt); linearVelocity.y = _vy; val2.linearVelocity = linearVelocity; val2.useGravity = false; Underwater = true; ZSyncAnimation val4 = _zanim.Invoke(__instance); if ((Object)(object)val4 != (Object)null) { val4.SetBool(s_inWaterHash, true); } float num4 = ((num > 0.1f) ? ((0f - Mathf.Asin(Mathf.Clamp(lookDir.y, -1f, 1f))) * 57.29578f * num) : 0f); if (flag && num <= 0.1f) { num4 = 45f; } if (flag2 && num <= 0.1f) { num4 = -45f; } Pitch = Mathf.MoveTowards(Pitch, num4, 180f * dt); } private static void RideWaves(Character c, Rigidbody body, float level, float dt) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) float num = level - c.m_swimDepth; Vector3 linearVelocity = body.linearVelocity; float num2 = Mathf.Clamp((num - ((Component)c).transform.position.y) * 8f, -8f, 8f); linearVelocity.y = Mathf.MoveTowards(linearVelocity.y, num2, 80f * dt); body.linearVelocity = linearVelocity; body.useGravity = false; } internal static void ApplyTilt(Player p) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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) GameObject val = (((Object)(object)p != (Object)null) ? _visual.Invoke((Character)(object)p) : null); if (!((Object)(object)val == (Object)null)) { if (!Underwater) { Pitch = Mathf.MoveTowards(Pitch, 0f, 180f * Time.deltaTime); } Quaternion val2 = Quaternion.Euler(Pitch, 0f, 0f); Vector3 val3 = Vector3.up * 1f; val.transform.localRotation = val2; val.transform.localPosition = val3 - val2 * val3; } } private static IEnumerable<CodeInstruction> CameraTranspiler(IEnumerable<CodeInstruction> instructions) { MethodInfo orig = AccessTools.Method(typeof(Floating), "GetLiquidLevel", new Type[3] { typeof(Vector3), typeof(float), typeof(LiquidType) }, (Type[])null); MethodInfo ours = AccessTools.Method(typeof(SwimItems), "CameraLiquidLevel", (Type[])null, (Type[])null); foreach (CodeInstruction instruction in instructions) { if (CodeInstructionExtensions.Calls(instruction, orig)) { yield return CodeInstructionExtensions.WithBlocks(CodeInstructionExtensions.WithLabels(new CodeInstruction(OpCodes.Call, (object)ours), (IEnumerable<Label>)instruction.labels), (IEnumerable<ExceptionBlock>)instruction.blocks); } else { yield return instruction; } } } private static float CameraLiquidLevel(Vector3 p, float waveFactor, LiquidType type) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (_cameraUnder.Value) { return -10000f; } return Floating.GetLiquidLevel(p, waveFactor, type); } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { MethodInfo isSwimming = AccessTools.Method(typeof(Character), "IsSwimming", (Type[])null, (Type[])null); MethodInfo ours = AccessTools.Method(typeof(SwimItems), "IsSwimmingForItems", (Type[])null, (Type[])null); foreach (CodeInstruction instruction in instructions) { if (CodeInstructionExtensions.Calls(instruction, isSwimming)) { yield return CodeInstructionExtensions.WithBlocks(CodeInstructionExtensions.WithLabels(new CodeInstruction(OpCodes.Call, (object)ours), (IEnumerable<Label>)instruction.labels), (IEnumerable<ExceptionBlock>)instruction.blocks); } else { yield return instruction; } } } private static bool IsSwimmingForItems(Character c) { if (_enabled != null && _enabled.Value && (Object)(object)c != (Object)null && (Object)(object)c == (Object)(object)Player.m_localPlayer) { return false; } if ((Object)(object)c != (Object)null) { return c.IsSwimming(); } return false; } } [DefaultExecutionOrder(32000)] internal sealed class Underwater : MonoBehaviour { private static readonly Color TarColor = new Color(0.016f, 0.01f, 0.006f, 1f); private bool _tarLook; internal static ConfigEntry<bool> _flipY; private static readonly int SunFogColorId = Shader.PropertyToID("_SunFogColor"); private static readonly int SunColorId = Shader.PropertyToID("_SunColor"); private static readonly int AmbientColorId = Shader.PropertyToID("_AmbientColor"); private Color _waterColor = new Color(0.02f, 0.1f, 0.15f); private float _fogDensity = 0.1f; private static readonly Color ShallowColor = new Color(0.06f, 0.25f, 0.29f, 1f); private static readonly Color MidColor = new Color(0.02f, 0.1f, 0.15f, 1f); private static readonly Color DeepColor = new Color(0.003f, 0.015f, 0.03f, 1f); private const float FullDarkDepth = 40f; private float _blend; private bool _saved; private bool _savedFog; private FogMode _savedMode; private float _sunWritten = -1f; private float _sunBase; private ParticleSystem _motes; private Vector3 _current; private bool _motesBlended; internal static Vector3 Current; private readonly Caustics _caustics = new Caustics(); private readonly Bubbles _bubbles = new Bubbles(); private readonly UnderwaterAudio _audio = new UnderwaterAudio(); private static readonly int s_wet = Shader.PropertyToID("_Wet"); private Shader _additive; private bool _shaderSearched; private float _shaderRetryAt; private readonly Stopwatch _sw = new Stopwatch(); private double _tBubbles; private double _tMotes; private double _tCaustics; private double _tSheet; private double _tAbove; private int _tFrames; private int _tRenders; private float _tStart = -1f; private Material _splitMat; private bool _splitSearched; private Camera _scam; private RenderTexture _srt; private CommandBuffer _splitCb; private Camera _cbCam; private bool _splitOn; private bool _splitTar; private Color _cleanFogColor; private Color _cleanAmbient = Color.gray; private Color _cleanSunFog; private Color _cleanSunCol; private Color _cleanAmbCol; private float _cleanFogDensity = 0.01f; private Color _wFogColor; private Color _wAmbient; private Color _wSunFog; private Color _wSunCol; private Color _wAmbCol; private float _wFogDensity = -1f; private AmplifyOcclusionEffect _sao; private float _nextAoSync; private static FieldInfo[] _aoFields; private Material _fogMat; private bool _fogSearched; private CommandBuffer _fogCb; private Material _ppFogMat; private int _fogPass = -1; internal static float Daylight = 1f; private float _nextDaylightLog; private Color _savedAmbient; private bool _savedAmbientValid; private PostProcessingProfile _profile; private bool _postSaved; private bool _bloomOn; private bool _vignetteOn; private Settings _bloom; private Settings _vignette; private Behaviour _shafts; private AmplifyOcclusionEffect _ao; private ApplicationMethod _aoMethod; private const int GridN = 37; private const float GridStep = 4f; private const float SkirtRadius = 3000f; private int[] _edge; private GameObject _sheet; private MeshRenderer _sheetRenderer; private Mesh _sheetMesh; private Material _sheetMat; private Vector3[] _sv; private Vector3[] _sn; private WaterVolume _sheetWv; private float _gridLevel = float.NaN; private float _ox = float.NaN; private float _oz = float.NaN; private static readonly FieldRef<float> _wTime = AccessTools.StaticFieldRefAccess<float>(AccessTools.Field(typeof(WaterVolume), "s_wrappedDayTimeSeconds")); private static readonly FieldRef<Vector4> _wWind1 = AccessTools.StaticFieldRefAccess<Vector4>(AccessTools.Field(typeof(WaterVolume), "s_globalWind1")); private static readonly FieldRef<Vector4> _wWind2 = AccessTools.StaticFieldRefAccess<Vector4>(AccessTools.Field(typeof(WaterVolume), "s_globalWind2")); private static readonly FieldRef<float> _wAlpha = AccessTools.StaticFieldRefAccess<float>(AccessTools.Field(typeof(WaterVolume), "s_globalWindAlpha")); private readonly Collider[] _wvBuf = (Collider[])(object)new Collider[8]; private int _wvMask; private Camera _rcam; private int _aboveFrame; private int _aboveMask; private readonly Plane[] _planes = (Plane[])(object)new Plane[6]; private double _aboveMs; internal static int _aboveRendered; internal static int _aboveSkipped; private RenderTexture _rt; private bool _noShader; private bool _normalSearched; private bool _farLogged; private Particle[] _moteBuf; public static bool CameraUnder { get; private set; } public static bool CameraInTar { get; private set; } public static bool VisualUnder { get; private set; } private double Lap() { double totalMilliseconds = _sw.Elapsed.TotalMilliseconds; _sw.Restart(); return totalMilliseconds; } private void ReportCost(bool under) { if (!under) { _tStart = -1f; return; } _tFrames++; if (_tStart < 0f) { _tStart = Time.unscaledTime; _tFrames = 0; _tBubbles = (_tMotes = (_tCaustics = (_tSheet = (_tAbove = 0.0)))); _tRenders = _aboveRendered; return; } float num = Time.unscaledTime - _tStart; if (!(num < 5f) && _tFrames != 0) { double num2 = _tFrames; Plugin.Log.LogInfo((object)($"Underwater cost per frame (CPU, {num2 / (double)num:0} fps): above-water camera {_tAbove / num2:0.00} ms " + $"({_aboveRendered - _tRenders} renders in {_tFrames} frames), water sheet {(_tSheet - _tAbove) / num2:0.00} ms, " + $"caustics {_tCaustics / num2:0.00} ms, motes {_tMotes / num2:0.00} ms, bubbles {_tBubbles / num2:0.00} ms")); _tStart = -1f; } } private void LateUpdate() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0432: Unknown result type (might be due to invalid IL or missing references) //IL_0437: Unknown result type (might be due to invalid IL or missing references) //IL_03af: Unknown result type (might be due to invalid IL or missing references) //IL_03c1: Unknown result type (might be due to invalid IL or missing references) //IL_03d7: Unknown result type (might be due to invalid IL or missing references) //IL_03e7: Unknown result type (might be due to invalid IL or missing references) //IL_03f7: Unknown result type (might be due to invalid IL or missing references) //IL_0407: Unknown result type (might be due to invalid IL or missing references) //IL_0572: Unknown result type (might be due to invalid IL or missing references) //IL_0577: Unknown result type (might be due to invalid IL or missing references) //IL_0584: Unknown result type (might be due to invalid IL or missing references) //IL_0553: Unknown result type (might be due to invalid IL or missing references) //IL_0558: Unknown result type (might be due to invalid IL or missing references) //IL_056b: Unknown result type (might be due to invalid IL or missing references) //IL_0458: Unknown result type (might be due to invalid IL or missing references) //IL_046c: Unknown result type (might be due to invalid IL or missing references) //IL_0471: Unknown result type (might be due to invalid IL or missing references) //IL_047f: Unknown result type (might be due to invalid IL or missing references) //IL_0484: Unknown result type (might be due to invalid IL or missing references) //IL_048c: Unknown result type (might be due to invalid IL or missing references) //IL_04b0: Unknown result type (might be due to invalid IL or missing references) //IL_04b5: Unknown result type (might be due to invalid IL or missing references) //IL_04bc: Unknown result type (might be due to invalid IL or missing references) //IL_04c7: Unknown result type (might be due to invalid IL or missing references) //IL_04f6: Unknown result type (might be due to invalid IL or missing references) //IL_04fb: Unknown result type (might be due to invalid IL or missing references) //IL_0503: Unknown result type (might be due to invalid IL or missing references) //IL_0517: Unknown result type (might be due to invalid IL or missing references) //IL_051c: Unknown result type (might be due to invalid IL or missing references) //IL_0524: Unknown result type (might be due to invalid IL or missing references) //IL_0533: Unknown result type (might be due to invalid IL or missing references) //IL_0589: Unknown result type (might be due to invalid IL or missing references) //IL_058b: Unknown result type (might be due to invalid IL or missing references) //IL_0592: Unknown result type (might be due to invalid IL or missing references) //IL_0597: Unknown result type (might be due to invalid IL or missing references) //IL_05a5: Unknown result type (might be due to invalid IL or missing references) //IL_05aa: Unknown result type (might be due to invalid IL or missing references) //IL_05b2: Unknown result type (might be due to invalid IL or missing references) //IL_05e2: Unknown result type (might be due to invalid IL or missing references) //IL_05e7: Unknown result type (might be due to invalid IL or missing references) //IL_05fa: Unknown result type (might be due to invalid IL or missing references) //IL_060b: Unknown result type (might be due to invalid IL or missing references) //IL_0646: Unknown result type (might be due to invalid IL or missing references) //IL_064b: Unknown result type (might be due to invalid IL or missing references) //IL_0653: Unknown result type (might be due to invalid IL or missing references) //IL_0667: Unknown result type (might be due to invalid IL or missing references) //IL_066c: Unknown result type (might be due to invalid IL or missing references) //IL_067f: Unknown result type (might be due to invalid IL or missing references) //IL_068a: Unknown result type (might be due to invalid IL or missing references) //IL_0699: Unknown result type (might be due to invalid IL or missing references) //IL_06aa: Unknown result type (might be due to invalid IL or missing references) //IL_06ac: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { SwimItems.ApplyTilt(localPlayer); _caustics.Prewarm(); } CaptureClean(); _savedAmbient = _cleanAmbient; _savedAmbientValid = true; DaylightFactor(); _sw.Restart(); _bubbles.Update(AdditiveShader()); double num = Lap(); Camera mainCamera = Utils.GetMainCamera(); CameraUnder = false; if ((Object)(object)mainCamera == (Object)null) { SetMotes(null, on: false, 0f, 0f); SetSurface(null, on: false, 0f, 0f); RestorePost(); return; } Vector3 position = ((Component)mainCamera).transform.position; float liquidLevel = Floating.GetLiquidLevel(position, 1f, (LiquidType)0); float num2 = NearHalfHeight(mainCamera); CameraUnder = liquidLevel > -9999f && position.y < liquidLevel - num2 - 0.05f; float num3 = ((liquidLevel > -9999f) ? (-10000f) : Floating.GetLiquidLevel(position, 1f, (LiquidType)1)); CameraInTar = num3 > -9999f && position.y < num3 - num2 - 0.02f; bool flag = SplitWanted(position, liquidLevel, num2); bool flag2 = !flag && !CameraInTar && num3 > -9999f && position.y < num3 + num2 + 0.05f; _splitOn = (flag || flag2) && EnsureSplitMaterial(); _splitTar = _splitOn && flag2; if (_splitOn) { RenderSplitAbove(mainCamera); } SetSplitComposite(mainCamera, _splitOn); VisualUnder = CameraUnder || (_splitOn && !_splitTar); if (CameraInTar || _splitTar) { _tarLook = true; } else if (VisualUnder) { _tarLook = false; } float num4 = (VisualUnder ? Mathf.Clamp01((liquidLevel - position.y) / 40f) : 0f); _blend = (_splitOn ? 1f : Mathf.MoveTowards(_blend, (CameraUnder || CameraInTar) ? 1f : 0f, Time.deltaTime * 6f)); _audio.Update(CameraUnder ? _blend : 0f, num4); UnderwaterSfx.Update(CameraUnder); if (CameraUnder && _blend > 0f && Shader.GetGlobalFloat(s_wet) < _blend) { Shader.SetGlobalFloat(s_wet, _blend); } Lap(); SetMotes(mainCamera, VisualUnder, num4, liquidLevel); double num5 = Lap(); _caustics.Update(mainCamera, VisualUnder, liquidLevel, num4, VisualUnder ? AdditiveShader() : null); double num6 = Lap(); _aboveMs = 0.0; SetSurface(mainCamera, VisualUnder, liquidLevel, num4); double num7 = Lap(); if (CameraUnder) { _tBubbles += num; _tMotes += num5; _tCaustics += num6; _tSheet += num7; _tAbove += _aboveMs; } ReportCost(CameraUnder); if (_blend <= 0f) { if (_saved) { RenderSettings.fog = _savedFog; RenderSettings.fogMode = _savedMode; _saved = false; RenderSettings.fogColor = _cleanFogColor; RenderSettings.fogDensity = _cleanFogDensity; RenderSettings.ambientLight = _cleanAmbient; Shader.SetGlobalColor(SunFogColorId, _cleanSunFog); Shader.SetGlobalColor(SunColorId, _cleanSunCol); Shader.SetGlobalColor(AmbientColorId, _cleanAmbCol); } RestoreSun(); RestorePost(); return; } if (!_saved) { _savedFog = RenderSettings.fog; _savedMode = RenderSettings.fogMode; _saved = true; } if (_tarLook && !VisualUnder) { Color val = TarColor * Mathf.Max(0.3f, Daylight); RenderSettings.fog = true; RenderSettings.fogMode = (FogMode)2; RenderSettings.fogColor = Color.Lerp(RenderSettings.fogColor, val, _blend); RenderSettings.fogDensity = Mathf.Lerp(RenderSettings.fogDensity, 2.2f, _blend); RenderSettings.ambientLight = Color.Lerp(Render