using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Entities; using Jotunn.Extensions; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.UI; using VBDiving.Effects; using VBDiving.Mobs; using VBDiving.Patches; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("SwimmingReworked")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("SwimmingReworked")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("1.0.3")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.3.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace VBDiving { internal class BreathHud : MonoBehaviour { private GameObject _root; private RectTransform _container; private readonly List _bubbles = new List(); private Sprite _bubbleSprite; private TextMeshProUGUI _breathText; private float _cachedOffsetX; private float _cachedOffsetY; private float _cachedScale; private bool _cachedShowLabels; private const int MaxBubbles = 12; private const float BubbleSize = 12f; private void Awake() { CreateHud(); } private void Start() { ApplyPositionAndScale(); } private void Update() { Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)Camera.main)) { SetVisible(visible: false); return; } CheckConfigChanges(); float currentBreath = SwimAPI.GetCurrentBreath(localPlayer); float maxBreath = SwimAPI.GetMaxBreath(localPlayer); float percent = Mathf.Clamp01(SwimAPI.GetBreathPercent(localPlayer)); bool flag = WaterHelper.IsHeadUnderwater(localPlayer); bool flag2 = currentBreath < maxBreath - 0.01f; bool flag3 = flag || flag2; SetVisible(flag3); if (flag3) { float skillLevel = ((Character)localPlayer).GetSkillLevel((SkillType)103); UpdateBubblesHorizontal(percent, skillLevel); if (Object.op_Implicit((Object)(object)_breathText) && ((Component)_breathText).gameObject.activeSelf) { ((TMP_Text)_breathText).text = $"{Mathf.CeilToInt(currentBreath)}"; } } } private void UpdateBubblesHorizontal(float percent, float swimSkillLevel) { //IL_015a: 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_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) int num = 2 + Mathf.FloorToInt(swimSkillLevel / 10f); num = Mathf.Clamp(num, 2, 12); int num2 = Mathf.CeilToInt(percent * (float)num); float num3 = 12f; float num4 = (float)num * 12f; float num5 = 0f - num4 / 2f + 6f; for (int i = 0; i < _bubbles.Count; i++) { Image val = _bubbles[i]; bool flag = i < num; ((Component)val).gameObject.SetActive(flag); if (flag) { bool flag2 = i < num2; float num6 = num5 + (float)i * num3; if (flag2) { RectTransform rectTransform = ((Graphic)val).rectTransform; float num7 = Mathf.Sin(Time.time * 5f + (float)i * 0.5f) * 2f; rectTransform.anchoredPosition = new Vector2(num6, num7); float num8 = 0.6f + 0.4f * Mathf.PingPong(Time.time * 2f + (float)i * 0.3f, 1f); ((Graphic)val).color = new Color(0.8f, 0.92f, 1f, num8); } else { RectTransform rectTransform2 = ((Graphic)val).rectTransform; float num9 = Mathf.Sin(Time.time * 5f + (float)i * 0.5f) * 2f; rectTransform2.anchoredPosition = new Vector2(num6, num9); ((Graphic)val).color = new Color(0.3f, 0.4f, 0.5f, 0.3f); } } } } private void CheckConfigChanges() { //IL_00b6: 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) if (!Object.op_Implicit((Object)(object)VBDiving.Instance)) { return; } float value = VBDiving.BreathHudOffsetX.Value; float value2 = VBDiving.BreathHudOffsetY.Value; float value3 = VBDiving.BreathHudScale.Value; bool value4 = VBDiving.BreathHudShowLabels.Value; bool flag = !Mathf.Approximately(_cachedOffsetX, value) || !Mathf.Approximately(_cachedOffsetY, value2); bool flag2 = !Mathf.Approximately(_cachedScale, value3); bool flag3 = _cachedShowLabels != value4; if (flag) { ApplyPosition(value, value2); _cachedOffsetX = value; _cachedOffsetY = value2; } if (flag2) { ((Transform)_container).localScale = Vector3.one * value3; _cachedScale = value3; } if (flag3) { if (Object.op_Implicit((Object)(object)_breathText)) { ((Component)_breathText).gameObject.SetActive(value4); } _cachedShowLabels = value4; } } private void ApplyPositionAndScale() { //IL_0048: 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) if (Object.op_Implicit((Object)(object)_container)) { float value = VBDiving.BreathHudOffsetX.Value; float value2 = VBDiving.BreathHudOffsetY.Value; float value3 = VBDiving.BreathHudScale.Value; ApplyPosition(value, value2); ((Transform)_container).localScale = Vector3.one * value3; _cachedOffsetX = value; _cachedOffsetY = value2; _cachedScale = value3; _cachedShowLabels = VBDiving.BreathHudShowLabels.Value; if (Object.op_Implicit((Object)(object)_breathText)) { ((Component)_breathText).gameObject.SetActive(_cachedShowLabels); } } } private void ApplyPosition(float offsetXPercent, float offsetYPercent) { //IL_0028: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)_container)) { _container.anchorMin = new Vector2(0.5f, 0.5f); _container.anchorMax = new Vector2(0.5f, 0.5f); _container.pivot = new Vector2(0.5f, 0.5f); float num = offsetXPercent / 100f * (float)Screen.width; float num2 = offsetYPercent / 100f * (float)Screen.height; _container.anchoredPosition = new Vector2(num, num2); if (VBDiving.DebugLogging.Value) { VBDiving.LogDebug($"BreathHud position applied: X={num}, Y={num2}"); } } } private void SetVisible(bool visible) { if (Object.op_Implicit((Object)(object)_root) && _root.activeSelf != visible) { _root.SetActive(visible); } } private void CreateHud() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Expected O, but got Unknown //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0168: 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_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Expected O, but got Unknown //IL_0263: 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_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) _root = new GameObject("BreathHud"); Object.DontDestroyOnLoad((Object)(object)_root); Canvas val = _root.AddComponent(); val.renderMode = (RenderMode)0; val.sortingOrder = 5000; CanvasScaler val2 = _root.AddComponent(); val2.uiScaleMode = (ScaleMode)1; val2.referenceResolution = new Vector2(1920f, 1080f); val2.matchWidthOrHeight = 0.5f; _root.AddComponent(); GameObject val3 = new GameObject("Container"); val3.transform.SetParent(_root.transform, false); _container = val3.AddComponent(); float num = 144f; _container.sizeDelta = new Vector2(num, 30f); _bubbleSprite = CreateBubbleSprite(64); for (int i = 0; i < 12; i++) { GameObject val4 = new GameObject($"Bubble_{i}"); val4.transform.SetParent((Transform)(object)_container, false); RectTransform val5 = val4.AddComponent(); val5.sizeDelta = new Vector2(12f, 12f); val5.anchorMin = new Vector2(0.5f, 0.5f); val5.anchorMax = new Vector2(0.5f, 0.5f); val5.pivot = new Vector2(0.5f, 0.5f); Image val6 = val4.AddComponent(); val6.sprite = _bubbleSprite; val6.preserveAspect = true; ((Graphic)val6).color = new Color(0.8f, 0.92f, 1f, 0.8f); _bubbles.Add(val6); } GameObject val7 = new GameObject("BreathText"); val7.transform.SetParent((Transform)(object)_container, false); _breathText = val7.AddComponent(); ((TMP_Text)_breathText).fontSize = 16f; ((TMP_Text)_breathText).fontSizeMin = 10f; ((TMP_Text)_breathText).fontSizeMax = 24f; ((TMP_Text)_breathText).alignment = (TextAlignmentOptions)4097; ((Graphic)_breathText).color = new Color(0.8f, 0.92f, 1f, 0.9f); RectTransform rectTransform = ((TMP_Text)_breathText).rectTransform; rectTransform.sizeDelta = new Vector2(60f, 25f); rectTransform.anchorMin = new Vector2(1f, 0.5f); rectTransform.anchorMax = new Vector2(1f, 0.5f); rectTransform.pivot = new Vector2(0f, 0.5f); rectTransform.anchoredPosition = new Vector2(8f, 0f); SetVisible(visible: false); } private Sprite CreateBubbleSprite(int size) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(size, size, (TextureFormat)4, false); ((Texture)val).filterMode = (FilterMode)1; ((Texture)val).wrapMode = (TextureWrapMode)1; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor((float)(size - 1) * 0.5f, (float)(size - 1) * 0.5f); float num = (float)size * 0.42f; float num2 = num * 0.72f; Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(val2.x - (float)size * 0.12f, val2.y + (float)size * 0.12f); float num3 = (float)size * 0.12f; Vector2 val4 = default(Vector2); Color val5 = default(Color); for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { ((Vector2)(ref val4))..ctor((float)j, (float)i); float num4 = Vector2.Distance(val4, val2); if (num4 > num) { val.SetPixel(j, i, Color.clear); continue; } float num5 = Mathf.InverseLerp(num, num2, num4); float num6 = Mathf.Lerp(0.15f, 0.95f, num5); ((Color)(ref val5))..ctor(0.82f, 0.93f, 1f, num6); float num7 = Vector2.Distance(val4, val3); if (num7 < num3) { float num8 = 1f - num7 / num3; val5 = Color.Lerp(val5, new Color(1f, 1f, 1f, num6), num8 * 0.65f); } val.SetPixel(j, i, val5); } } val.Apply(); return Sprite.Create(val, new Rect(0f, 0f, (float)size, (float)size), new Vector2(0.5f, 0.5f), 100f); } } internal static class InputHelper { public static bool GetRun() { return ZInput.GetButton("Run"); } public static bool GetJump() { return ZInput.GetButton("Jump"); } public static bool GetCrouch() { return ZInput.GetButton("Crouch"); } public static float GetHorizontal() { return Input.GetAxisRaw("Horizontal"); } public static float GetVertical() { return Input.GetAxisRaw("Vertical"); } public static float GetDiveVertical() { float num = 0f; if (GetJump()) { num += 1f; } if (GetCrouch()) { num -= 1f; } return num; } } internal sealed class PlayerDiveController : MonoBehaviour { private const float HeadUnderwaterTolerance = 0.01f; internal const float DefaultSwimDepth = 1.3f; internal const float DivingThreshold = 1.5f; internal const float MinSwimDepth = 1.3f; internal const float MaxSwimDepth = 100f; internal const float DepthChangeSpeed = 0.025f; private const float LegacyDepthChangeSpeed = 0.04f; [NonSerialized] internal bool toggleDive; [NonSerialized] internal bool is_diving; [NonSerialized] internal bool isUnderwater; [NonSerialized] internal string lastDiveCancel = "None"; private bool _underwaterMovementActive; private float _baseSwimSpeed; private int _swimmingUpdateContextDepth; private int _swimmingUpdateContextFrame = -1; private float _diveAxis; private float _legacyDiveVertical; private bool _legacyDiveActive; internal static PlayerDiveController? LocalInstance { get; private set; } internal Player Player { get; private set; } = null; private void Awake() { Player = ((Component)this).GetComponent(); if (!Object.op_Implicit((Object)(object)Player)) { Object.Destroy((Object)(object)this); return; } if ((Object)(object)Player != (Object)(object)Player.m_localPlayer) { Object.Destroy((Object)(object)this); return; } LocalInstance = this; ((Character)Player).m_swimDepth = 1.3f; _baseSwimSpeed = ((Character)Player).m_swimSpeed; } private void OnDestroy() { if ((Object)(object)LocalInstance == (Object)(object)this) { LocalInstance = null; } } internal void HandleDiveToggle() { if (!((Character)Player).InWater() || ((Character)Player).IsOnGround() || !((Character)Player).IsSwimming()) { if (toggleDive) { toggleDive = false; is_diving = false; _legacyDiveActive = false; _legacyDiveVertical = 0f; lastDiveCancel = "PlayerOnLand"; } } else if (VBDiving.UseLegacyDiveControls.Value) { HandleLegacyControls(); } else if (ZInput.GetButtonDown("Crouch") || ZInput.GetButtonDown("JoyCrouch")) { if (!toggleDive) { toggleDive = true; lastDiveCancel = "None"; } else if (toggleDive && ((Character)Player).m_swimDepth <= 1.5f) { toggleDive = false; lastDiveCancel = "PlayerCancelled"; } } } private void HandleLegacyControls() { bool flag = ZInput.GetButton("Crouch") || ZInput.GetButton("JoyCrouch"); bool flag2 = ZInput.GetButton("Jump") || ZInput.GetButton("JoyJump"); if (flag && !flag2) { toggleDive = true; _legacyDiveActive = true; _legacyDiveVertical = 1f; lastDiveCancel = "None"; } else if (flag2 && !flag) { _legacyDiveActive = true; _legacyDiveVertical = -1f; if (((Character)Player).m_swimDepth <= 1.4f) { toggleDive = false; _legacyDiveActive = false; _legacyDiveVertical = 0f; lastDiveCancel = "PlayerSurfaced"; } } else if (flag && flag2) { toggleDive = true; _legacyDiveActive = true; _legacyDiveVertical = 1f; } else { _legacyDiveVertical = 0f; if (((Character)Player).m_swimDepth <= 1.5f) { toggleDive = false; _legacyDiveActive = false; lastDiveCancel = "PlayerSurfaced"; } else { _legacyDiveActive = false; } } } internal void UpdateDiveState() { //IL_000c: 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) if (ShieldGenerator.IsInsideShield(((Component)Player).transform.position)) { DisableUnderwaterMovement(); return; } if (!((Character)Player).InWater()) { ((Character)Player).m_swimDepth = 1.3f; return; } if (((Character)Player).m_swimDepth > 1.5f && Mathf.Max(0f, ((Character)Player).GetLiquidLevel() - ((Component)Player).transform.position.y) > 1.5f) { is_diving = true; isUnderwater = true; return; } if (is_diving) { is_diving = false; if (!VBDiving.UseLegacyDiveControls.Value || ((Character)Player).m_swimDepth <= 1.4f) { toggleDive = false; } lastDiveCancel = "PlayerSurfaced"; } isUnderwater = false; } internal void UpdateDiveDepth(Vector3 lookDir) { //IL_0062: 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_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_0125: 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_019e: 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_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: 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) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) if (!((Character)Player).InWater() || ((Character)Player).IsOnGround() || !((Character)Player).IsSwimming()) { return; } if (VBDiving.UseLegacyDiveControls.Value) { UpdateLegacyDiveMovement(); } else { if (!toggleDive) { return; } if (lookDir.y < -0.15f) { _diveAxis = 1f; } else if (lookDir.y > 0.15f) { _diveAxis = 0f; } if (!ZInput.GetButton("Forward") && !ZInput.GetButton("JoyLStickUp")) { return; } float num2; if (_diveAxis == 1f) { float num = Mathf.Abs(lookDir.y); num2 = num * 0.025f; if (num2 < 0.005f && num > 0.9f) { num2 = 0.005f; } } else if (_diveAxis == 0f) { num2 = lookDir.y * 0.025f; if (num2 < 0.005f && lookDir.y > 0.9f) { num2 = 0.005f; } } else { num2 = 0f; } if (num2 > 0.025f) { num2 = 0.025f; } ApplyVerticalMovement(num2); if (!(((Character)Player).m_swimDepth > 1.5f)) { return; } Vector3 moveDir = lookDir; if (Mathf.Abs(lookDir.y) > 0.95f) { Vector3 forward = ((Component)Player).transform.forward; forward.y = 0f; if (((Vector3)(ref forward)).magnitude > 0.01f) { ((Vector3)(ref forward)).Normalize(); Vector3 val = lookDir * 0.7f + forward * 0.3f; moveDir = ((Vector3)(ref val)).normalized; } } ((Character)Player).SetMoveDir(moveDir); } } private void UpdateLegacyDiveMovement() { //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_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: 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_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: 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_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_00de: 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_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_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_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: 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_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0153: 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_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: 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_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) float legacyDiveVertical = _legacyDiveVertical; if (Mathf.Abs(legacyDiveVertical) < 0.01f) { return; } if (legacyDiveVertical < 0f && ((Character)Player).m_swimDepth <= 1.3f) { ((Character)Player).m_swimDepth = 1.3f; return; } float num = legacyDiveVertical * 0.04f; float num2 = ((Character)Player).m_swimDepth + num; num2 = Mathf.Clamp(num2, 1.3f, 100f); ((Character)Player).m_swimDepth = num2; Vector3 val2; Vector3 normalized; if (legacyDiveVertical > 0f) { Vector3 lookDir = ((Character)Player).GetLookDir(); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(lookDir.x, 0f, lookDir.z); if (((Vector3)(ref val)).magnitude > 0.1f) { val2 = ((Vector3)(ref val)).normalized * 0.7f + Vector3.down * 0.3f; normalized = ((Vector3)(ref val2)).normalized; } else { Vector3 forward = ((Component)Player).transform.forward; forward.y = 0f; if (((Vector3)(ref forward)).magnitude < 0.1f) { forward = Vector3.forward; } val2 = ((Vector3)(ref forward)).normalized * 0.3f + Vector3.down * 0.7f; normalized = ((Vector3)(ref val2)).normalized; } } else { Vector3 lookDir2 = ((Character)Player).GetLookDir(); Vector3 val3 = default(Vector3); ((Vector3)(ref val3))..ctor(lookDir2.x, 0f, lookDir2.z); if (((Vector3)(ref val3)).magnitude > 0.1f) { val2 = ((Vector3)(ref val3)).normalized * 0.7f + Vector3.up * 0.3f; normalized = ((Vector3)(ref val2)).normalized; } else { Vector3 forward2 = ((Component)Player).transform.forward; forward2.y = 0f; if (((Vector3)(ref forward2)).magnitude < 0.1f) { forward2 = Vector3.forward; } val2 = ((Vector3)(ref forward2)).normalized * 0.3f + Vector3.up * 0.7f; normalized = ((Vector3)(ref val2)).normalized; } } ((Character)Player).SetMoveDir(normalized); } private void ApplyVerticalMovement(float multiplier) { if (_diveAxis == 1f) { Player player = Player; ((Character)player).m_swimDepth = ((Character)player).m_swimDepth + multiplier; } else if (_diveAxis == 0f) { if (((Character)Player).m_swimDepth > 1.3f) { Player player2 = Player; ((Character)player2).m_swimDepth = ((Character)player2).m_swimDepth - multiplier; } if (((Character)Player).m_swimDepth < 1.3f) { ((Character)Player).m_swimDepth = 1.3f; } } if (((Character)Player).m_swimDepth > 100f) { ((Character)Player).m_swimDepth = 100f; } } internal void DisableUnderwaterMovement() { _underwaterMovementActive = false; toggleDive = false; is_diving = false; _legacyDiveActive = false; _legacyDiveVertical = 0f; ResetSwimDepthToDefault(); ((Character)Player).m_swimSpeed = _baseSwimSpeed; } internal void ResetSwimDepthIfNotInWater() { if (!WaterHelper.IsBodyInWater(Player)) { DisableUnderwaterMovement(); } } internal void ResetSwimDepthToDefault() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) ((Character)Player).m_swimDepth = 1.3f; if (WaterHelper.IsBodyInWater(Player) && !toggleDive && !is_diving && !_legacyDiveActive) { float liquidLevel = ((Character)Player).GetLiquidLevel(); Vector3 position = ((Component)Player).transform.position; position.y = liquidLevel - 1.3f; ((Component)Player).transform.position = position; } } internal bool CanDive() { if (!WaterHelper.IsBodyInWater(Player) || ((Character)Player).IsOnGround()) { return false; } return true; } internal bool IsHeadUnderwater() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) float num = (Object.op_Implicit((Object)(object)((Character)Player).m_eye) ? ((Character)Player).m_eye.position.y : ((Component)Player).transform.position.y); return ((Character)Player).GetLiquidLevel() - num > 0.01f; } internal void RefreshUnderwaterMovementState() { if (!WaterHelper.IsBodyInWater(Player) || !IsHeadUnderwater()) { _underwaterMovementActive = false; } else if (IsUnderSurface()) { _underwaterMovementActive = true; } } internal bool ShouldForceSwimming() { return _underwaterMovementActive && WaterHelper.IsBodyInWater(Player) && IsHeadUnderwater(); } internal bool ShouldForceDive() { return ShouldForceSwimming() && !((Character)Player).IsOnGround(); } internal bool IsUnderSurface() { return ((Character)Player).m_swimDepth > 1.3f; } internal bool IsDiving() { return ((Character)Player).m_swimDepth > 1.5f; } internal bool IsSurfacing() { return !IsDiving() && IsUnderSurface(); } internal bool IsIdleInWater() { //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) int result; if (WaterHelper.IsBodyInWater(Player) && (WaterHelper.IsBodyInWater(Player) || ShouldForceSwimming())) { Vector3 velocity = ((Character)Player).GetVelocity(); result = ((((Vector3)(ref velocity)).magnitude < 1f) ? 1 : 0); } else { result = 0; } return (byte)result != 0; } internal void BeginSwimmingUpdateContext() { _swimmingUpdateContextDepth++; _swimmingUpdateContextFrame = Time.frameCount; } internal void EndSwimmingUpdateContext() { if (_swimmingUpdateContextDepth > 0) { _swimmingUpdateContextDepth--; } if (_swimmingUpdateContextDepth == 0) { _swimmingUpdateContextFrame = -1; } } internal bool IsInSwimmingUpdateContext() { return _swimmingUpdateContextDepth > 0 && _swimmingUpdateContextFrame == Time.frameCount; } internal void UpdateSwimSpeed() { float num = 1f; if (InputHelper.GetRun()) { float skillFactor = Player.m_skills.GetSkillFactor((SkillType)103); float num2 = Mathf.Max(1f, VBDiving.SprintSwimMultiplier.Value); num = Mathf.Lerp(1f, num2, Mathf.Pow(skillFactor, 1.5f)); } ((Character)Player).m_swimSpeed = _baseSwimSpeed * num; } } public static class SwimAPI { public static event Action OnEnterWater; public static event Action OnExitWater; public static event Action OnHeadUnderwater; public static event Action OnHeadAboveWater; public static event Action OnOutOfBreath; public static float GetBreathPercent(Player player) { if (!Object.op_Implicit((Object)(object)player)) { return 1f; } SwimState swimState = SwimStateManager.Get(player); float maxBreath = GetMaxBreath(player); if (maxBreath <= 0f) { return 0f; } return Mathf.Clamp01(swimState.Breath / maxBreath); } public static bool IsUnderwater(Player player) { if (!Object.op_Implicit((Object)(object)player)) { return false; } return WaterHelper.IsHeadUnderwater(player); } public static bool IsSwimming(Player player) { if (!Object.op_Implicit((Object)(object)player)) { return false; } return WaterHelper.IsBodyInWater(player); } public static float GetCurrentBreath(Player player) { if (!Object.op_Implicit((Object)(object)player)) { return 0f; } return SwimStateManager.Get(player).Breath; } public static float GetBaseMaxBreath(Player player) { if (!Object.op_Implicit((Object)(object)player)) { return VBDiving.MaxBreathSeconds.Value; } float skillFactor = ((Character)player).GetSkillFactor((SkillType)103); return VBDiving.MaxBreathSeconds.Value + VBDiving.MaxBreathBonusAtSkill100.Value * skillFactor; } public static float GetMaxBreath(Player player) { if (!Object.op_Implicit((Object)(object)player)) { return VBDiving.MaxBreathSeconds.Value; } SwimState swimState = SwimStateManager.Get(player); return GetBaseMaxBreath(player) + swimState.ExtraBreathBonus; } public static bool IsOutOfBreath(Player player) { return GetCurrentBreath(player) <= 0f; } public static float GetSwimSkillFactor(Player player) { if (!Object.op_Implicit((Object)(object)player)) { return 0f; } return ((Character)player).GetSkillFactor((SkillType)103); } public static bool HasInfiniteBreath(Player player) { if (!Object.op_Implicit((Object)(object)player)) { return false; } SwimState swimState = SwimStateManager.Get(player); return Time.time < swimState.InfiniteBreathUntil; } public static float GetExternalSwimSpeedMultiplier(Player player) { if (!Object.op_Implicit((Object)(object)player)) { return 1f; } SwimState swimState = SwimStateManager.Get(player); if (Time.time >= swimState.SwimSpeedMultiplierUntil) { swimState.SwimSpeedMultiplier = 1f; return 1f; } return swimState.SwimSpeedMultiplier; } public static void RestoreBreath(Player player, float amount) { if (Object.op_Implicit((Object)(object)player) && !(amount <= 0f)) { SwimState swimState = SwimStateManager.Get(player); swimState.Breath = Mathf.Min(GetMaxBreath(player), swimState.Breath + amount); } } public static void DrainBreath(Player player, float amount) { if (Object.op_Implicit((Object)(object)player) && !(amount <= 0f)) { SwimState swimState = SwimStateManager.Get(player); swimState.Breath = Mathf.Max(0f, swimState.Breath - amount); } } public static void SetInfiniteBreath(Player player, float duration) { if (Object.op_Implicit((Object)(object)player) && !(duration <= 0f)) { SwimState swimState = SwimStateManager.Get(player); swimState.InfiniteBreathUntil = Mathf.Max(swimState.InfiniteBreathUntil, Time.time + duration); swimState.Breath = GetMaxBreath(player); } } public static void AddBreathBonus(Player player, float bonusSeconds) { if (Object.op_Implicit((Object)(object)player)) { SwimState swimState = SwimStateManager.Get(player); swimState.ExtraBreathBonus = Mathf.Max(0f, swimState.ExtraBreathBonus + bonusSeconds); swimState.Breath = Mathf.Min(swimState.Breath, GetMaxBreath(player)); } } public static void SetBreathBonus(Player player, float bonusSeconds) { if (Object.op_Implicit((Object)(object)player)) { SwimState swimState = SwimStateManager.Get(player); swimState.ExtraBreathBonus = Mathf.Max(0f, bonusSeconds); swimState.Breath = Mathf.Min(swimState.Breath, GetMaxBreath(player)); } } public static void AddSwimSpeedBonus(Player player, float multiplier, float duration) { if (Object.op_Implicit((Object)(object)player) && !(multiplier <= 0f) && !(duration <= 0f)) { SwimState swimState = SwimStateManager.Get(player); swimState.SwimSpeedMultiplier = Mathf.Max(swimState.SwimSpeedMultiplier, multiplier); swimState.SwimSpeedMultiplierUntil = Mathf.Max(swimState.SwimSpeedMultiplierUntil, Time.time + duration); } } internal static void UpdateEvents(Player player) { if (Object.op_Implicit((Object)(object)player)) { SwimState swimState = SwimStateManager.Get(player); bool flag = IsSwimming(player); bool flag2 = IsUnderwater(player); bool flag3 = IsOutOfBreath(player); if (flag && !swimState.WasSwimming) { SwimAPI.OnEnterWater?.Invoke(player); } else if (!flag && swimState.WasSwimming) { SwimAPI.OnExitWater?.Invoke(player); } if (flag2 && !swimState.WasHeadUnderwater) { SwimAPI.OnHeadUnderwater?.Invoke(player); } else if (!flag2 && swimState.WasHeadUnderwater) { SwimAPI.OnHeadAboveWater?.Invoke(player); } if (flag3 && !swimState.WasOutOfBreath) { SwimAPI.OnOutOfBreath?.Invoke(player); } swimState.WasSwimming = flag; swimState.WasHeadUnderwater = flag2; swimState.WasOutOfBreath = flag3; } } } [BepInPlugin("VitByr.VBDiving", "VBDiving", "0.0.4")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInIncompatibility("sighsorry.DiveIn")] [BepInIncompatibility("ch.easy.develope.vh.diving.mod")] [BepInIncompatibility("blacks7ar.VikingsDoSwim")] [BepInIncompatibility("projjm.improvedswimming")] [BepInIncompatibility("dzk.SwimmingReworked")] [SynchronizationMode(/*Could not decode attribute arguments.*/)] internal class VBDiving : BaseUnityPlugin { public const string PluginGUID = "VitByr.VBDiving"; public const string PluginName = "VBDiving"; public const string PluginVersion = "0.0.4"; internal static VBDiving Instance; internal static Harmony Harmony; internal static ConfigEntry EnableMod; internal static ConfigEntry MaxBreathSeconds; internal static ConfigEntry MaxBreathBonusAtSkill100; internal static ConfigEntry BreathRecoveryPerSecond; internal static ConfigEntry SprintSwimMultiplier; internal static ConfigEntry BaseUnderwaterStaminaRegenPerSecond; internal static ConfigEntry DebugLogging; internal static ConfigEntry UseLegacyDiveControls; internal static float SwimStaminaDrainMinSkill = 4f; internal static float SwimStaminaDrainMaxSkill = 2f; internal static ConfigEntry BreathHudOffsetX; internal static ConfigEntry BreathHudOffsetY; internal static ConfigEntry BreathHudScale; internal static ConfigEntry BreathHudShowLabels; internal static ConfigEntry SyncMonsterConfigs; internal static ConfigEntry UseServerMonsterConfigsOnly; private ConfigFileWatcher _configWatcher; internal static string ConfigFolderPath; private CustomRPC _monsterConfigRPC; private bool _hasRequestedConfigs; private void Awake() { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown Instance = this; ConfigFolderPath = Path.Combine(Paths.ConfigPath, "VitByr", "VBDiving"); Directory.CreateDirectory(ConfigFolderPath); CreateConfig(); CreateConfigWatcher(); SynchronizationManager.OnConfigurationSynchronized += OnConfigurationSynchronized; SynchronizationManager.OnAdminStatusChanged += OnAdminStatusChanged; ((Component)this).gameObject.AddComponent(); ((Component)this).gameObject.AddComponent(); ((MonoBehaviour)this).StartCoroutine(InitDiveControllerWhenReady()); Harmony = new Harmony("VitByr.VBDiving"); Harmony.PatchAll(); SetupMonsterConfigSync(); MonsterDiveSystem.Initialize(); } private IEnumerator InitDiveControllerWhenReady() { while (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { yield return null; } Player player = Player.m_localPlayer; PlayerDiveController playerDiveController = default(PlayerDiveController); if (!((Component)player).TryGetComponent(ref playerDiveController)) { ((Component)player).gameObject.AddComponent(); ((BaseUnityPlugin)this).Logger.LogDebug((object)"DiveController added to local player"); } } private void SetupMonsterConfigSync() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0029: Expected O, but got Unknown _monsterConfigRPC = NetworkManager.Instance.AddRPC("VBDiving_SyncMonsterConfigs", new CoroutineHandler(OnServerReceiveRequest), new CoroutineHandler(OnClientReceiveConfigs)); if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[VBDiving] Server mode: loading monster configs"); MonsterDiveSystem.LoadAllMonsterDiveConfigs(); } else if ((Object)(object)ZNet.instance != (Object)null && ZNetExtension.IsClientInstance(ZNet.instance)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[VBDiving] Client mode: will request monster configs from server"); } } private IEnumerator OnServerReceiveRequest(long sender, ZPackage package) { int flag = package.ReadInt(); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[VBDiving] Server received request from client {sender}, flag={flag}"); if (flag == 0) { SendMonsterConfigsToClient(sender); } yield break; } private IEnumerator OnClientReceiveConfigs(long sender, ZPackage package) { int flag = package.ReadInt(); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[VBDiving] Client received configs from server, flag={flag}"); if (flag == 1) { string configData = package.ReadString(); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[VBDiving] Received monster configs from server ({configData.Length} bytes)"); if (string.IsNullOrEmpty(configData)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[VBDiving] Received empty config data from server"); } else if (UseServerMonsterConfigsOnly.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[VBDiving] Using server configs only (ignoring local)"); MonsterDiveSystem.LoadSerializedConfigs(configData, useServerOnly: true); } else { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[VBDiving] Merging server configs with local (server priority)"); MonsterDiveSystem.LoadSerializedConfigs(configData); } } yield break; } private void SendMonsterConfigsToAllClients() { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown if (!SyncMonsterConfigs.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[VBDiving] SyncMonsterConfigs is disabled, not sending"); return; } string serializedConfigs = MonsterDiveSystem.GetSerializedConfigs(); if (string.IsNullOrEmpty(serializedConfigs)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[VBDiving] No configs to send to clients"); return; } ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[VBDiving] Sending monster configs to all clients ({serializedConfigs.Length} bytes)"); ZPackage val = new ZPackage(); val.Write(1); val.Write(serializedConfigs); foreach (ZNetPeer peer in ZNet.instance.m_peers) { if (peer.m_uid != ZRoutedRpc.instance.GetServerPeerID()) { _monsterConfigRPC.SendPackage(peer.m_uid, val); } } } private void SendMonsterConfigsToClient(long clientId) { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown if (!SyncMonsterConfigs.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[VBDiving] SyncMonsterConfigs is disabled, not sending to client"); return; } string serializedConfigs = MonsterDiveSystem.GetSerializedConfigs(); if (string.IsNullOrEmpty(serializedConfigs)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"[VBDiving] No configs to send to client {clientId}"); return; } ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[VBDiving] Sending monster configs to client {clientId} ({serializedConfigs.Length} bytes)"); ((BaseUnityPlugin)this).Logger.LogDebug((object)("[VBDiving] Configs preview: " + serializedConfigs.Substring(0, Math.Min(200, serializedConfigs.Length)) + "...")); ZPackage val = new ZPackage(); val.Write(1); val.Write(serializedConfigs); _monsterConfigRPC.SendPackage(clientId, val); } internal static void RequestMonsterConfigsFromServer() { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown if (!((Object)(object)Instance == (Object)null) && !((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer() && SyncMonsterConfigs.Value && !Instance._hasRequestedConfigs) { Instance._hasRequestedConfigs = true; ((BaseUnityPlugin)Instance).Logger.LogInfo((object)"[VBDiving] Requesting monster configs from server..."); ZPackage val = new ZPackage(); val.Write(0); Instance._monsterConfigRPC.SendPackage(ZRoutedRpc.instance.GetServerPeerID(), val); } } internal static void OnServerConfigsChanged() { if ((Object)(object)Instance != (Object)null && (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && SyncMonsterConfigs.Value) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)"[VBDiving] Server configs changed, sending updates to all clients"); Instance.SendMonsterConfigsToAllClients(); } } private void CreateConfig() { //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Expected O, but got Unknown ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; EnableMod = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "00 - Main", "EnableMod", true, "Включить или отключить мод.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); SyncMonsterConfigs = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "00 - Main", "SyncMonsterConfigs", true, "Синхронизировать конфиги монстров с сервера.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); UseServerMonsterConfigsOnly = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "00 - Main", "UseServerMonsterConfigsOnly", true, "Использовать ТОЛЬКО конфиги с сервера (игнорировать локальные файлы). Если false - серверные конфиги имеют приоритет над локальными.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); UseLegacyDiveControls = ((BaseUnityPlugin)this).Config.Bind("01 - Control", "UseLegacyDiveControls", true, "Если true: зажать Crouch для погружения, Jump для всплытия.\nЕсли false: нажать Crouch для переключения режима ныряния, затем направление взгляда + Forward для движения вверх/вниз."); MaxBreathSeconds = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "02 - Breath", "MaxBreathSeconds", 30f, "Максимальное время под водой при навыке плавания 0.", true, (int?)null, (AcceptableValueBase)(object)new AcceptableValueRange(1f, 600f), (Action)null, (ConfigurationManagerAttributes)null); MaxBreathBonusAtSkill100 = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "02 - Breath", "MaxBreathBonusAtSkill100", 150f, "Дополнительное время под водой при навыке плавания 100.", true, (int?)null, (AcceptableValueBase)(object)new AcceptableValueRange(0f, 600f), (Action)null, (ConfigurationManagerAttributes)null); BreathRecoveryPerSecond = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "02 - Breath", "BreathRecoveryPerSecond", 30f, "Скорость восстановления дыхания.", true, (int?)null, (AcceptableValueBase)(object)new AcceptableValueRange(0f, 300f), (Action)null, (ConfigurationManagerAttributes)null); BreathHudOffsetX = ((BaseUnityPlugin)this).Config.Bind("03 - BreathHud", "OffsetX", 0f, "Смещение индикатора по горизонтали от центра экрана (в процентах от ширины экрана).\nОтрицательное = левее, положительное = правее."); BreathHudOffsetY = ((BaseUnityPlugin)this).Config.Bind("03 - BreathHud", "OffsetY", -30f, "Смещение индикатора по вертикали от центра экрана (в процентах от высоты экрана).\nОтрицательное = ниже, положительное = выше."); BreathHudScale = ((BaseUnityPlugin)this).Config.Bind("03 - BreathHud", "Scale", 1f, new ConfigDescription("Масштаб индикатора дыхания.", (AcceptableValueBase)(object)new AcceptableValueRange(0.3f, 3f), Array.Empty())); BreathHudShowLabels = ((BaseUnityPlugin)this).Config.Bind("03 - BreathHud", "ShowLabels", true, "Показывать числовое значение дыхания справа от пузырьков."); SprintSwimMultiplier = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "04 - Swimming", "SprintSwimMultiplier", 2.25f, "Множитель скорости при спринте в воде.", true, (int?)null, (AcceptableValueBase)(object)new AcceptableValueRange(1f, 5f), (Action)null, (ConfigurationManagerAttributes)null); BaseUnderwaterStaminaRegenPerSecond = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "04 - Swimming", "BaseUnderwaterStaminaRegenPerSecond", 1.25f, "Базовая скорость восстановления выносливости на поверхности без движения.", true, (int?)null, (AcceptableValueBase)(object)new AcceptableValueRange(0f, 50f), (Action)null, (ConfigurationManagerAttributes)null); PlayerEquipInWater.EquipInWaterList = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "06 - EquipInWater", "EiW_Custom", "KnifeFlint,KnifeCopper,KnifeChitin,KnifeSilver,KnifeBlackMetal,KnifeButcher,KnifeSkollAndHati,SpearFlint,SpearBronze,SpearElderbark,SpearWolfFang,SpearChitin,SpearCarapace,PickaxeAntler,PickaxeBronze,PickaxeIron,PickaxeBlackMetal,Hammer,Hoe,FistFenrirClaw", "Разрешить использовать оружие/инструмент в воде", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); PlayerEquipInWater.EquipInWaterList.SettingChanged += delegate { HashSet hashSet2 = new HashSet(); string[] array2 = PlayerEquipInWater.EquipInWaterList.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (string item2 in array2) { hashSet2.Add(item2); } PlayerEquipInWater.EquipInWaterItems = hashSet2; }; HashSet hashSet = new HashSet(); string[] array = PlayerEquipInWater.EquipInWaterList.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (string item in array) { hashSet.Add(item); } PlayerEquipInWater.EquipInWaterItems = hashSet; DebugLogging = ((BaseUnityPlugin)this).Config.Bind("Debug", "DebugLogging", false, "Включить отладочные логи."); ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; ((BaseUnityPlugin)this).Config.Save(); } private void CreateConfigWatcher() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown _configWatcher = new ConfigFileWatcher(((BaseUnityPlugin)this).Config, 1000L); _configWatcher.OnConfigFileReloaded += delegate { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Config file reloaded from disk."); }; } internal static float GetClampedSkillFactor(Player player, SkillType skillType) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) float skillLevel = ((Character)player).GetSkillLevel(skillType); float num = Mathf.Min(skillLevel, 100f); return num / 100f; } internal static float GetClampedSwimFactor(Player player) { float skillLevel = ((Character)player).GetSkillLevel((SkillType)103); float num = Mathf.Min(skillLevel, 100f); return num / 100f; } private void OnConfigurationSynchronized(object sender, ConfigurationSynchronizationEventArgs e) { if (e.InitialSynchronization) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Initial config sync received."); if ((Object)(object)ZNet.instance != (Object)null && ZNetExtension.IsClientInstance(ZNet.instance)) { ((MonoBehaviour)this).StartCoroutine(RequestConfigsAfterSync()); } } else { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Config sync update received."); } if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && SyncMonsterConfigs.Value) { SendMonsterConfigsToAllClients(); } } private IEnumerator RequestConfigsAfterSync() { yield return (object)new WaitForSeconds(2f); RequestMonsterConfigsFromServer(); } private void OnAdminStatusChanged() { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Admin status changed: " + (SynchronizationManager.Instance.PlayerIsAdmin ? "admin" : "not admin"))); } private void OnDestroy() { SynchronizationManager.OnConfigurationSynchronized -= OnConfigurationSynchronized; SynchronizationManager.OnAdminStatusChanged -= OnAdminStatusChanged; if (_configWatcher != null) { _configWatcher = null; } } internal static bool IsEnabled() { return Object.op_Implicit((Object)(object)Instance) && EnableMod.Value; } internal static void LogDebug(string msg) { if (Object.op_Implicit((Object)(object)Instance) && DebugLogging.Value) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)msg); } } } internal class SwimState { public float Breath; public bool WasHeadUnderwater; public bool WasSwimming; public float LastSurfaceTime; public float SuffocationTickTimer; public float ExtraBreathBonus; public float InfiniteBreathUntil; public float SwimSpeedMultiplier = 1f; public float SwimSpeedMultiplierUntil; public bool WasOutOfBreath; } internal static class SwimStateManager { private static readonly Dictionary States = new Dictionary(); public static SwimState Get(Player player) { long playerID = player.GetPlayerID(); if (!States.TryGetValue(playerID, out var value)) { value = new SwimState { Breath = SwimAPI.GetBaseMaxBreath(player), WasHeadUnderwater = false, WasSwimming = false, LastSurfaceTime = 0f, SuffocationTickTimer = 0f, ExtraBreathBonus = 0f, InfiniteBreathUntil = 0f, SwimSpeedMultiplier = 1f, SwimSpeedMultiplierUntil = 0f, WasOutOfBreath = false }; States[playerID] = value; } return value; } public static void Remove(Player player) { if (Object.op_Implicit((Object)(object)player)) { States.Remove(player.GetPlayerID()); } } } internal static class WaterHelper { public static bool TryGetWaterLevel(Vector3 position, out float waterLevel) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) waterLevel = Floating.GetLiquidLevel(position, 1f, (LiquidType)0); return waterLevel > -10000f; } public static Vector3 GetHeadPosition(Player player) { //IL_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_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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)player)) { return Vector3.zero; } return ((Character)player).GetHeadPoint(); } public static Vector3 GetChestPosition(Player player) { //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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)player)) { return Vector3.zero; } return ((Component)player).transform.position + Vector3.up * 1f; } public static bool IsBodyInWater(Player player) { //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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)player)) { return false; } Vector3 chestPosition = GetChestPosition(player); float waterLevel; return TryGetWaterLevel(chestPosition, out waterLevel) && chestPosition.y < waterLevel; } public static bool IsHeadUnderwater(Player player) { //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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)player)) { return false; } Vector3 headPosition = GetHeadPosition(player); float waterLevel; return TryGetWaterLevel(headPosition, out waterLevel) && headPosition.y < waterLevel - 0.02f; } public static bool IsNearSurface(Player player, float tolerance = 0.35f) { //IL_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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)player)) { return false; } Vector3 headPosition = GetHeadPosition(player); float waterLevel; return TryGetWaterLevel(headPosition, out waterLevel) && Mathf.Abs(headPosition.y - waterLevel) <= tolerance; } } } namespace VBDiving.Patches { [HarmonyPatch(typeof(Character), "CustomFixedUpdate")] internal static class CharacterSurfaceFix { [HarmonyPostfix] private static void Postfix(Character __instance) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0098: 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_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) if (!VBDiving.IsEnabled() || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } Player val = (Player)__instance; if (!WaterHelper.IsBodyInWater(val)) { return; } PlayerDiveController localInstance = PlayerDiveController.LocalInstance; if (!Object.op_Implicit((Object)(object)localInstance) || localInstance.toggleDive || localInstance.is_diving || localInstance.IsHeadUnderwater()) { return; } float liquidLevel = ((Character)val).GetLiquidLevel(); float num = liquidLevel - 1.3f; if (((Component)val).transform.position.y < num - 0.1f) { Vector3 position = ((Component)val).transform.position; position.y = Mathf.Lerp(position.y, num, Time.fixedDeltaTime * 8f); ((Component)val).transform.position = position; Rigidbody component = ((Component)val).GetComponent(); if (Object.op_Implicit((Object)(object)component) && component.linearVelocity.y < 0f) { Vector3 linearVelocity = component.linearVelocity; linearVelocity.y = Mathf.Max(linearVelocity.y, 0f); component.linearVelocity = linearVelocity; } } ((Character)val).m_swimDepth = 1.3f; } } [HarmonyPatch] internal static class CharacterWaterStatePatch { [HarmonyPostfix] [HarmonyPatch(typeof(Character), "IsOnGround")] private static void CharacterIsOnGroundPostfix(Character __instance, ref bool __result) { if (VBDiving.IsEnabled()) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (Object.op_Implicit((Object)(object)val) && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && WaterHelper.IsBodyInWater(val)) { __result = false; } } } [HarmonyPostfix] [HarmonyPatch(typeof(Character), "InWater")] private static void CharacterInWaterPostfix(Character __instance, ref bool __result) { if (VBDiving.IsEnabled()) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (Object.op_Implicit((Object)(object)val) && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && WaterHelper.IsBodyInWater(val)) { __result = true; } } } } [HarmonyPatch] internal static class DiveControllerPatches { [HarmonyPostfix] [HarmonyPatch(typeof(Player), "Awake")] private static void PlayerAwakePostfix(Player __instance) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { EnsureLocalDiver(); } } [HarmonyPrefix] [HarmonyPatch(typeof(Character), "UpdateMotion")] private static void CharacterUpdateMotionPrefix(Character __instance, ref float ___m_lastGroundTouch, ref float ___m_swimTimer) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } PlayerDiveController playerDiveController = EnsureLocalDiver(); if (Object.op_Implicit((Object)(object)playerDiveController)) { playerDiveController.ResetSwimDepthIfNotInWater(); if (playerDiveController.is_diving || WaterHelper.IsBodyInWater((Player)(object)((__instance is Player) ? __instance : null))) { ___m_lastGroundTouch = 0.3f; ___m_swimTimer = 0f; } } } [HarmonyPrefix] [HarmonyPatch(typeof(Character), "UpdateSwimming")] private static void CharacterUpdateSwimmingPrefix(Character __instance) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (Object.op_Implicit((Object)(object)val)) { PlayerDiveController playerDiveController = EnsureLocalDiver(); if (Object.op_Implicit((Object)(object)playerDiveController)) { playerDiveController.UpdateSwimSpeed(); ApplySwimStaminaSettings(val); } } } private static void ApplySwimStaminaSettings(Player player) { if (WaterHelper.IsBodyInWater(player)) { float num = VBDiving.SwimStaminaDrainMinSkill; float num2 = VBDiving.SwimStaminaDrainMaxSkill; if (WaterHelper.IsHeadUnderwater(player)) { num *= 2f; num2 *= 2f; } if (InputHelper.GetRun() && player.GetStamina() > 0f) { num *= 1.5f; num2 *= 1.5f; } player.m_swimStaminaDrainMinSkill = num; player.m_swimStaminaDrainMaxSkill = num2; } } [HarmonyPrefix] [HarmonyPatch(typeof(Character), "CustomFixedUpdate")] private static void CharacterCustomFixedUpdatePrefix(Character __instance, ref Vector3 ___m_moveDir, ref Vector3 ___m_lookDir) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || !__instance.IsPlayer()) { return; } PlayerDiveController playerDiveController = EnsureLocalDiver(); if (Object.op_Implicit((Object)(object)playerDiveController)) { playerDiveController.HandleDiveToggle(); playerDiveController.UpdateDiveState(); if (!__instance.InWater()) { __instance.m_swimDepth = 1.3f; } else if (playerDiveController.toggleDive && __instance.InWater() && !__instance.IsOnGround() && __instance.IsSwimming()) { playerDiveController.UpdateDiveDepth(___m_lookDir); } else if ((__instance.IsOnGround() || !playerDiveController.is_diving) && !playerDiveController.isUnderwater) { __instance.m_swimDepth = 1.3f; } } } [HarmonyPrefix] [HarmonyPatch(typeof(Character), "UpdateRotation")] private static void CharacterUpdateRotationPrefix(Character __instance, out Quaternion? __state) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { __state = null; return; } PlayerDiveController localInstance = PlayerDiveController.LocalInstance; if (Object.op_Implicit((Object)(object)localInstance) && localInstance.is_diving) { __state = ((Component)__instance).transform.rotation; } else { __state = null; } } [HarmonyPostfix] [HarmonyPatch(typeof(Character), "UpdateRotation")] private static void CharacterUpdateRotationPostfix(Character __instance, float turnSpeed, float dt, ref Quaternion? __state) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_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) if (__state.HasValue && Object.op_Implicit((Object)(object)__instance) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !(((Component)__instance).transform.rotation != __state.Value)) { PlayerDiveController localInstance = PlayerDiveController.LocalInstance; if (Object.op_Implicit((Object)(object)localInstance) && localInstance.is_diving) { Player player = localInstance.Player; Quaternion val = ((((Character)player).AlwaysRotateCamera() || ((Character)player).m_moveDir == Vector3.zero) ? ((Character)player).m_lookYaw : Quaternion.LookRotation(((Character)player).m_moveDir)); float num = turnSpeed * ((Character)player).GetAttackSpeedFactorRotation(); ((Component)player).transform.rotation = Quaternion.RotateTowards(((Component)player).transform.rotation, val, num * dt); } } } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "SetControls")] private static void PlayerSetControlsPrefix(Player __instance, ref bool crouch) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && ((Character)__instance).InWater()) { crouch = false; } } private static PlayerDiveController? EnsureLocalDiver() { Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer)) { return null; } PlayerDiveController playerDiveController = PlayerDiveController.LocalInstance; if (Object.op_Implicit((Object)(object)playerDiveController) && (Object)(object)playerDiveController.Player == (Object)(object)localPlayer) { return playerDiveController; } if (!((Component)localPlayer).TryGetComponent(ref playerDiveController)) { playerDiveController = ((Component)localPlayer).gameObject.AddComponent(); } return playerDiveController; } } [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] internal static class GameCameraPatch { private static float _originalMaxDistance; private static float _originalMinWaterDistance; private static bool _cachedOriginalValues; [HarmonyPrefix] private static void Prefix(GameCamera __instance, Camera ___m_camera) { if (!VBDiving.IsEnabled()) { return; } Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)localPlayer) && Object.op_Implicit((Object)(object)___m_camera)) { PlayerDiveController localInstance = PlayerDiveController.LocalInstance; if (!_cachedOriginalValues) { _originalMaxDistance = __instance.m_maxDistance; _originalMinWaterDistance = __instance.m_minWaterDistance; _cachedOriginalValues = true; } bool flag = Object.op_Implicit((Object)(object)localInstance) && localInstance.toggleDive; bool flag2 = Object.op_Implicit((Object)(object)localInstance) && localInstance.is_diving; if (flag || flag2) { __instance.m_minWaterDistance = -5000f; return; } __instance.m_minWaterDistance = _originalMinWaterDistance; __instance.m_maxDistance = _originalMaxDistance; } } [HarmonyPostfix] private static void Postfix(GameCamera __instance, Camera ___m_camera) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: 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_0106: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_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_0145: Unknown result type (might be due to invalid IL or missing references) if (!VBDiving.IsEnabled()) { return; } Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)___m_camera)) { return; } PlayerDiveController localInstance = PlayerDiveController.LocalInstance; bool flag = Object.op_Implicit((Object)(object)localInstance) && localInstance.toggleDive; bool flag2 = Object.op_Implicit((Object)(object)localInstance) && localInstance.is_diving; float waterLevel2; if (flag || flag2) { if (WaterHelper.TryGetWaterLevel(((Component)___m_camera).transform.position, out var waterLevel)) { float y = ((Component)___m_camera).transform.position.y; if (y > waterLevel - 0.5f) { Vector3 position = ((Component)___m_camera).transform.position; position.y = waterLevel - 0.5f; ((Component)___m_camera).transform.position = position; } } } else if (WaterHelper.IsBodyInWater(localPlayer) && WaterHelper.TryGetWaterLevel(((Component)___m_camera).transform.position, out waterLevel2)) { float y2 = ((Component)___m_camera).transform.position.y; float num = waterLevel2 + 0.3f; if (y2 < num) { Vector3 position2 = ((Component)___m_camera).transform.position; position2.y = num; ((Component)___m_camera).transform.position = position2; } } } } [HarmonyPatch] internal static class PlayerEquipInWater { internal static ConfigEntry EquipInWaterList; internal static HashSet EquipInWaterItems = new HashSet(); private static readonly CodeMatch[] Matches = (CodeMatch[])(object)new CodeMatch[5] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Character), "IsSwimming", (Type[])null, (Type[])null), (string)null), new CodeMatch((OpCode?)OpCodes.Brfalse, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Character), "IsOnGround", (Type[])null, (Type[])null), (string)null) }; public static bool VB_CheckWaterItem(ItemData item) { if (item == null) { HandleNullItemCase(); return false; } return IsItemAllowed(item.m_shared.m_name); } private static void HandleNullItemCase() { Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)localPlayer)) { CheckAndUnequipItem(((Humanoid)localPlayer).m_leftItem); CheckAndUnequipItem(((Humanoid)localPlayer).m_rightItem); } } private static void CheckAndUnequipItem(ItemData item) { if (item != null && !IsItemAllowed(((Object)item.m_dropPrefab).name)) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Humanoid)localPlayer).UnequipItem(item, true); } } } private static bool IsItemAllowed(string itemName) { return EquipInWaterItems.Contains(itemName); } private static IEnumerable TargetMethods() { return new <>z__ReadOnlyArray(new MethodBase[3] { AccessTools.Method(typeof(Player), "Update", (Type[])null, (Type[])null), AccessTools.Method(typeof(Humanoid), "EquipItem", (Type[])null, (Type[])null), AccessTools.Method(typeof(Humanoid), "UpdateEquipment", (Type[])null, (Type[])null) }); } public static IEnumerable Transpiler(IEnumerable instructions, MethodBase original) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null).MatchStartForward(Matches); try { switch (original.Name) { case "Update": val.Advance(1).RemoveInstructions(6); break; case "EquipItem": val.Advance(6).Insert((IEnumerable)GenerateInjectionCode(val, OpCodes.Ldarg_1)); break; case "UpdateEquipment": val.Advance(6).Insert((IEnumerable)GenerateInjectionCode(val, OpCodes.Ldnull)); break; } } catch (ArgumentException ex) { Debug.LogError((object)("IL Transpiler Error in VB_EquipInWater: " + ex.Message)); Debug.LogError((object)"Plugin initialization failed. Valheim will shutdown."); Environment.Exit(1); } return val.InstructionEnumeration(); } private static List GenerateInjectionCode(CodeMatcher matcher, OpCode loadOpCode) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown List list = new List(); list.Add(new CodeInstruction(loadOpCode, (object)null)); list.Add(new CodeInstruction(OpCodes.Call, (object)typeof(PlayerEquipInWater).GetMethod("VB_CheckWaterItem"))); list.Add(new CodeInstruction(OpCodes.Brfalse, matcher.InstructionAt(-1).operand)); return list; } } [HarmonyPatch(typeof(Player), "FixedUpdate")] internal static class PlayerFixedUpdatePatch { private static void Postfix(Player __instance) { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: 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) if (!VBDiving.IsEnabled() || !Object.op_Implicit((Object)(object)__instance) || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || ((Character)__instance).IsDebugFlying()) { return; } bool flag = WaterHelper.IsBodyInWater(__instance); bool flag2 = WaterHelper.IsHeadUnderwater(__instance); Rigidbody component = ((Component)__instance).GetComponent(); if (!Object.op_Implicit((Object)(object)component)) { return; } if (!flag) { Traverse.Create((object)__instance).Field("m_staminaRegenTimer").SetValue((object)0f); component.useGravity = true; HandleBreath(__instance, headUnderwater: false); return; } component.useGravity = true; HandleBreath(__instance, flag2); Vector2 val = new Vector2(component.linearVelocity.x, component.linearVelocity.z); float magnitude = ((Vector2)(ref val)).magnitude; bool flag3 = magnitude > 0.5f; if (!flag2 && !IsDivingDeep(__instance) && !flag3) { Traverse.Create((object)__instance).Field("m_staminaRegenTimer").SetValue((object)0f); HandleWaterStaminaRegen(__instance); } else { Traverse.Create((object)__instance).Field("m_staminaRegenTimer").SetValue((object)10f); } PlayerDiveController localInstance = PlayerDiveController.LocalInstance; if (Object.op_Implicit((Object)(object)localInstance)) { localInstance.UpdateSwimSpeed(); } } private static bool IsDivingDeep(Player player) { PlayerDiveController localInstance = PlayerDiveController.LocalInstance; if (Object.op_Implicit((Object)(object)localInstance)) { return localInstance.toggleDive || localInstance.is_diving || localInstance.IsUnderSurface(); } return ((Character)player).m_swimDepth > 1.4f; } private static void HandleBreath(Player player, bool headUnderwater) { SwimState swimState = SwimStateManager.Get(player); float fixedDeltaTime = Time.fixedDeltaTime; float maxBreath = SwimAPI.GetMaxBreath(player); if (headUnderwater) { swimState.Breath -= fixedDeltaTime; if (swimState.Breath < 0f) { swimState.Breath = 0f; } if (swimState.Breath <= 0f && ((Character)player).HaveStamina(0f)) { ((Character)player).UseStamina(5f * fixedDeltaTime); } } else { swimState.Breath += VBDiving.BreathRecoveryPerSecond.Value * fixedDeltaTime; if (swimState.Breath > maxBreath) { swimState.Breath = maxBreath; } } SwimAPI.UpdateEvents(player); swimState.WasHeadUnderwater = headUnderwater; } private static void HandleWaterStaminaRegen(Player player) { float value = VBDiving.BaseUnderwaterStaminaRegenPerSecond.Value; float value2 = Traverse.Create((object)player).Field("m_stamina").GetValue(); float maxStamina = ((Character)player).GetMaxStamina(); if (value2 < maxStamina) { value2 += value * Time.fixedDeltaTime; if (value2 > maxStamina) { value2 = maxStamina; } Traverse.Create((object)player).Field("m_stamina").SetValue((object)value2); } } } [HarmonyPatch(typeof(Player), "UpdateStats", new Type[] { typeof(float) })] internal static class PlayerUpdateStatsPatch { private static void Postfix(Player __instance, float dt) { if (VBDiving.IsEnabled() && Object.op_Implicit((Object)(object)__instance) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && WaterHelper.IsBodyInWater(__instance)) { bool flag = WaterHelper.IsHeadUnderwater(__instance); PlayerDiveController localInstance = PlayerDiveController.LocalInstance; bool flag2 = Object.op_Implicit((Object)(object)localInstance) && (localInstance.toggleDive || localInstance.is_diving || localInstance.IsUnderSurface()); if (flag || flag2) { Traverse.Create((object)__instance).Field("m_staminaRegenTimer").SetValue((object)float.MaxValue); } if (Object.op_Implicit((Object)(object)localInstance)) { localInstance.UpdateSwimSpeed(); } } } } [HarmonyPatch(typeof(WaterVolume), "UpdateMaterials")] internal static class SurfacePatch { private static readonly Dictionary UnderwaterCopies = new Dictionary(); private const float SurfaceOffset = -0.05f; private const float OverlapScale = 1.02f; private static void Postfix(WaterVolume __instance) { if (!VBDiving.IsEnabled() || !Object.op_Implicit((Object)(object)__instance) || !Object.op_Implicit((Object)(object)__instance.m_waterSurface)) { return; } MeshRenderer component = ((Component)__instance.m_waterSurface).GetComponent(); MeshFilter component2 = ((Component)__instance.m_waterSurface).GetComponent(); if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component2)) { return; } bool flag = IsCameraUnderwater(); if (!UnderwaterCopies.TryGetValue(component, out var value) || (Object)(object)value == (Object)null) { value = CreateUnderwaterSurfaceCopy(((Component)component).gameObject, component, component2); if (Object.op_Implicit((Object)(object)value)) { UnderwaterCopies[component] = value; } } if (Object.op_Implicit((Object)(object)value)) { ((Renderer)component).enabled = !flag; value.SetActive(flag); } } private static GameObject CreateUnderwaterSurfaceCopy(GameObject original, MeshRenderer originalRenderer, MeshFilter originalFilter) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("VBDiving_UnderwaterSurface"); val.transform.SetParent(original.transform, false); val.transform.localPosition = new Vector3(0f, -0.05f, 0f); val.transform.localRotation = Quaternion.Euler(180f, 0f, 0f); val.transform.localScale = new Vector3(1.02f, 1f, -1.02f); MeshFilter val2 = val.AddComponent(); val2.sharedMesh = originalFilter.sharedMesh; MeshRenderer val3 = val.AddComponent(); ((Renderer)val3).sharedMaterial = ((Renderer)originalRenderer).sharedMaterial; ((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)val3).receiveShadows = false; ((Renderer)val3).lightProbeUsage = (LightProbeUsage)0; ((Renderer)val3).reflectionProbeUsage = (ReflectionProbeUsage)0; ((Renderer)val3).allowOcclusionWhenDynamic = false; ((Renderer)val3).forceRenderingOff = false; ((Renderer)val3).enabled = true; val.SetActive(false); return val; } private static bool IsCameraUnderwater() { //IL_003a: 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) if (!Object.op_Implicit((Object)(object)GameCamera.instance)) { return false; } Camera component = ((Component)GameCamera.instance).GetComponent(); if (!Object.op_Implicit((Object)(object)component)) { return false; } if (!WaterHelper.TryGetWaterLevel(((Component)component).transform.position, out var waterLevel)) { return false; } return ((Component)component).transform.position.y < waterLevel - 0.15f; } } [HarmonyPatch(typeof(Player), "UseStamina")] internal static class UseStaminaPatch { private static bool AllowStaminaUseFromSwimSprint; private static bool Prefix(Player __instance, ref float v) { if (!VBDiving.IsEnabled()) { return true; } if (AllowStaminaUseFromSwimSprint) { return true; } if (!Object.op_Implicit((Object)(object)__instance) || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } if (!WaterHelper.IsBodyInWater(__instance)) { return true; } return true; } } [HarmonyPatch(typeof(WaterVolume), "UpdateMaterials")] internal static class WaterShaderPatch { private static readonly int ColorTopId = Shader.PropertyToID("_ColorTop"); private static readonly int ColorBottomId = Shader.PropertyToID("_ColorBottom"); private static readonly int ColorBottomShallowId = Shader.PropertyToID("_ColorBottomShallow"); private static readonly int SurfaceColorId = Shader.PropertyToID("_SurfaceColor"); private static readonly int DepthFadeId = Shader.PropertyToID("_DepthFade"); private static readonly int CullId = Shader.PropertyToID("_Cull"); private static Color _originalColorTop; private static Color _originalColorBottom; private static Color _originalColorBottomShallow; private static Color _originalSurfaceColor; private static float _originalDepthFade; private static bool _originalValuesSaved; private static Material _instanceMaterial; private static MeshRenderer _lastRenderer; private static void Postfix(WaterVolume __instance) { if (VBDiving.IsEnabled() && Object.op_Implicit((Object)(object)__instance.m_waterSurface)) { MeshRenderer waterSurface = __instance.m_waterSurface; if (!Object.op_Implicit((Object)(object)_instanceMaterial) || (Object)(object)_lastRenderer != (Object)(object)waterSurface) { _instanceMaterial = ((Renderer)waterSurface).material; _lastRenderer = waterSurface; SaveOriginalValues(_instanceMaterial); } if (_instanceMaterial.HasProperty(CullId)) { _instanceMaterial.SetInt(CullId, 0); } if (Object.op_Implicit((Object)(object)PlayerDiveController.LocalInstance) && PlayerDiveController.LocalInstance.isUnderwater) { ApplyUnderwaterSettings(_instanceMaterial); } else { ApplyWaterSettings(_instanceMaterial); } } } private static void SaveOriginalValues(Material mat) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (mat.HasProperty(ColorTopId)) { _originalColorTop = mat.GetColor(ColorTopId); } if (mat.HasProperty(ColorBottomId)) { _originalColorBottom = mat.GetColor(ColorBottomId); } if (mat.HasProperty(ColorBottomShallowId)) { _originalColorBottomShallow = mat.GetColor(ColorBottomShallowId); } if (mat.HasProperty(SurfaceColorId)) { _originalSurfaceColor = mat.GetColor(SurfaceColorId); } if (mat.HasProperty(DepthFadeId)) { _originalDepthFade = mat.GetFloat(DepthFadeId); } _originalValuesSaved = true; } private static void ApplyWaterSettings(Material mat) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) if (mat.HasProperty(ColorTopId)) { mat.SetColor(ColorTopId, new Color(0.2f, 0.25f, 0.2f, 0.95f)); } if (mat.HasProperty(ColorBottomId)) { mat.SetColor(ColorBottomId, new Color(0.15f, 0.2f, 0.2f, 0.95f)); } if (mat.HasProperty(ColorBottomShallowId)) { mat.SetColor(ColorBottomShallowId, new Color(0.2f, 0.25f, 0.2f, 0.95f)); } if (mat.HasProperty(SurfaceColorId)) { mat.SetColor(SurfaceColorId, new Color(0.3f, 0.35f, 0.35f, 0.95f)); } if (mat.HasProperty(DepthFadeId)) { mat.SetFloat(DepthFadeId, _originalDepthFade * 1f); } } private static void ApplyUnderwaterSettings(Material mat) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) if (mat.HasProperty(ColorTopId)) { mat.SetColor(ColorTopId, new Color(0.2f, 0.25f, 0.2f, 0.95f)); } if (mat.HasProperty(ColorBottomId)) { mat.SetColor(ColorBottomId, new Color(0.15f, 0.2f, 0.2f, 0.95f)); } if (mat.HasProperty(ColorBottomShallowId)) { mat.SetColor(ColorBottomShallowId, new Color(0.2f, 0.25f, 0.2f, 0.95f)); } if (mat.HasProperty(SurfaceColorId)) { mat.SetColor(SurfaceColorId, new Color(0.3f, 0.35f, 0.35f, 0.95f)); } if (mat.HasProperty(DepthFadeId)) { mat.SetFloat(DepthFadeId, _originalDepthFade * 1.25f); } } } } namespace VBDiving.Mobs { [HarmonyPatch] internal static class MonsterDivePatches { [HarmonyPostfix] [HarmonyPatch(typeof(MonsterAI), "Awake")] private static void MonsterAIAwakePostfix(MonsterAI __instance) { if (VBDiving.IsEnabled() && MonsterDiveSystem.IsConfiguredMonster(__instance)) { MonsterDiveSystem.EnsureDiveFlags(__instance); } } [HarmonyPrefix] [HarmonyPatch(typeof(MonsterAI), "UpdateAI")] private static void MonsterAIUpdateAIPrefix(MonsterAI __instance) { if (VBDiving.IsEnabled() && MonsterDiveSystem.IsConfiguredMonster(__instance)) { MonsterDiveSystem.EnsureDiveFlags(__instance); } } [HarmonyPrefix] [HarmonyPatch(typeof(BaseAI), "HavePath")] private static bool BaseAIHavePathPrefix(BaseAI __instance, Vector3 target, ref bool __result) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (!VBDiving.IsEnabled()) { return true; } MonsterAI val = (MonsterAI)(object)((__instance is MonsterAI) ? __instance : null); if (val == null) { return true; } if (!MonsterDiveSystem.IsConfiguredMonster(val) || !MonsterDiveSystem.ShouldUseWaterDiveMode(val)) { return true; } Character character = ((BaseAI)val).m_character; if (!Object.op_Implicit((Object)(object)character)) { return true; } __result = MonsterDiveSystem.HasReasonableUnderwaterRoute(__instance, character, target); return false; } [HarmonyPrefix] [HarmonyPatch(typeof(BaseAI), "MoveTo")] private static bool BaseAIMoveToPrefix(BaseAI __instance, float dt, Vector3 point, float dist, bool run, ref bool __result) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: 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) if (!VBDiving.IsEnabled()) { return true; } MonsterAI val = (MonsterAI)(object)((__instance is MonsterAI) ? __instance : null); if (val == null) { return true; } if (!MonsterDiveSystem.IsConfiguredMonster(val) || !MonsterDiveSystem.ShouldUseWaterDiveMode(val)) { return true; } Character character = ((BaseAI)val).m_character; if (!Object.op_Implicit((Object)(object)character)) { return true; } float num = MonsterDiveSystem.UpdateSwimDepthTowardsTarget(val, character, point, dt); float num2 = Mathf.Max(dist, run ? 1f : 0.5f); float num3 = Utils.DistanceXZ(point, ((Component)__instance).transform.position); float num4 = Mathf.Abs(point.y - ((Component)__instance).transform.position.y); float num5 = Mathf.Abs(num - ((Component)__instance).transform.position.y); if (num3 < num2 && (num4 < 0.75f || num5 < 0.35f)) { __instance.StopMoving(); __result = true; return false; } Vector3 val2 = point - ((Component)__instance).transform.position; if (((Vector3)(ref val2)).sqrMagnitude <= 0.0001f) { __instance.StopMoving(); __result = true; return false; } Vector3 val3 = MonsterDiveSystem.BuildSteerDirectionWithAvoidance(__instance, character, point); if (((Vector3)(ref val3)).sqrMagnitude <= 0.0001f) { __instance.StopMoving(); __result = true; return false; } __instance.MoveTowards(val3, run); __result = false; return false; } [HarmonyPrefix] [HarmonyPatch(typeof(Character), "IsOnGround")] private static bool CharacterIsOnGroundPrefix(Character __instance, ref bool __result) { if (!VBDiving.IsEnabled()) { return true; } if (__instance is Player) { return true; } MonsterAI component = ((Component)__instance).GetComponent(); if (!Object.op_Implicit((Object)(object)component)) { return true; } if (!MonsterDiveSystem.IsConfiguredMonster(component)) { return true; } if (MonsterDiveSystem.ShouldUseWaterDiveMode(component)) { __result = false; return false; } return true; } [HarmonyPostfix] [HarmonyPatch(typeof(MonsterAI), "UpdateAI")] private static void MonsterAIUpdateAIPostfix(MonsterAI __instance, float dt) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00de: 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_0110: Unknown result type (might be due to invalid IL or missing references) if (!VBDiving.IsEnabled() || !MonsterDiveSystem.IsConfiguredMonster(__instance)) { return; } Character character = ((BaseAI)__instance).m_character; if (!Object.op_Implicit((Object)(object)character) || !MonsterDiveSystem.ShouldUseWaterDiveMode(__instance)) { return; } character.m_lastGroundTouch = 1f; if (character.IsOnGround() && character.InWater()) { float liquidLevel = character.GetLiquidLevel(); float num = liquidLevel - character.m_swimDepth; if (((Component)character).transform.position.y < num + 0.5f) { Vector3 position = ((Component)character).transform.position; position.y = num; ((Component)character).transform.position = position; Rigidbody component = ((Component)character).GetComponent(); if (Object.op_Implicit((Object)(object)component) && component.linearVelocity.y < 0f) { Vector3 linearVelocity = component.linearVelocity; linearVelocity.y = 0f; component.linearVelocity = linearVelocity; } } } character.m_swimTimer = 0f; } } internal static class MonsterDiveSystem { private readonly struct RouteCacheEntry { public readonly float Time; public readonly Vector3Int PositionBucket; public readonly Vector3Int TargetBucket; public readonly bool Result; public RouteCacheEntry(float time, Vector3Int positionBucket, Vector3Int targetBucket, bool result) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) Time = time; PositionBucket = positionBucket; TargetBucket = targetBucket; Result = result; } } private readonly struct SteerCacheEntry { public readonly float Time; public readonly Vector3Int PositionBucket; public readonly Vector3Int TargetBucket; public readonly Vector3 Direction; public SteerCacheEntry(float time, Vector3Int positionBucket, Vector3Int targetBucket, Vector3 direction) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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) Time = time; PositionBucket = positionBucket; TargetBucket = targetBucket; Direction = direction; } } private readonly struct PassiveDepthProfile { public readonly float MinDepth; public readonly float CenterDepth; public readonly float MaxPassiveDepth; public readonly float MaxAgroDepth; public PassiveDepthProfile(float minDepth, float centerDepth, float maxPassiveDepth, float maxAgroDepth) { MinDepth = Mathf.Max(0f, minDepth); MaxAgroDepth = Mathf.Max(0f, maxAgroDepth); MaxPassiveDepth = Mathf.Clamp(maxPassiveDepth, MinDepth, MaxAgroDepth); CenterDepth = Mathf.Clamp(centerDepth, MinDepth, MaxPassiveDepth); } public PassiveDepthProfile(float centerDepth, float minDepth, float maxDepth) { MinDepth = Mathf.Max(0f, minDepth); MaxAgroDepth = Mathf.Max(0f, maxDepth); MaxPassiveDepth = Mathf.Clamp(maxDepth, MinDepth, MaxAgroDepth); CenterDepth = Mathf.Clamp(centerDepth, MinDepth, MaxPassiveDepth); } } private readonly struct OriginalDiveFlags { public readonly MonsterAI MonsterAI; public readonly bool AvoidWater; public readonly bool CanSwim; public OriginalDiveFlags(MonsterAI monsterAI, bool avoidWater, bool canSwim) { MonsterAI = monsterAI; AvoidWater = avoidWater; CanSwim = canSwim; } } private readonly struct ConfiguredDiveProfile { public readonly string GroupName; public readonly PassiveDepthProfile DepthProfile; public readonly float ActiveDepthAdjustSpeed; public readonly bool UseBreath; public readonly float MaxBreathSeconds; public readonly float BreathRecoverySpeed; public readonly float SurfaceTime; public readonly float SurfaceThresholdPercent; public ConfiguredDiveProfile(string groupName, PassiveDepthProfile depthProfile, float activeDepthAdjustSpeed, bool useBreath, float maxBreathSeconds, float breathRecoverySpeed, float surfaceTime, float surfaceThresholdPercent) { GroupName = groupName; DepthProfile = depthProfile; ActiveDepthAdjustSpeed = activeDepthAdjustSpeed; UseBreath = useBreath; MaxBreathSeconds = (useBreath ? Mathf.Max(0f, maxBreathSeconds) : 0f); BreathRecoverySpeed = (useBreath ? Mathf.Max(0.1f, breathRecoverySpeed) : 0f); SurfaceTime = (useBreath ? Mathf.Max(0f, surfaceTime) : 0f); SurfaceThresholdPercent = (useBreath ? Mathf.Clamp01(surfaceThresholdPercent) : 0f); } } private sealed class MonsterDiveYamlRoot : Dictionary { public MonsterDiveYamlRoot() : base((IEqualityComparer?)StringComparer.OrdinalIgnoreCase) { } } private sealed class MonsterDiveYamlGroup { public float? MinDepth { get; set; } public float? CenterDepth { get; set; } public float? MaxDepth { get; set; } public float? MaxPassiveDepth { get; set; } public float? MaxAgroDepth { get; set; } public float? DepthAdjustSpeed { get; set; } public bool? UseBreath { get; set; } public float? MaxBreathSeconds { get; set; } public float? BreathRecoverySpeed { get; set; } public float? SurfaceTime { get; set; } public float? SurfaceThresholdPercent { get; set; } public List Prefabs { get; set; } = new List(); } internal static readonly string MonsterDiveConfigFolderPath; private static readonly object MonsterDiveConfigLock; private static readonly IDeserializer MonsterDiveYamlDeserializer; private static readonly Dictionary RouteCache; private static readonly Dictionary SteerCache; private static readonly Dictionary OriginalDiveFlagsByInstance; private const int MaxCacheEntries = 2048; private static readonly object PrefabSetLock; private static Dictionary _configuredDiveProfilesByPrefabName; private static FileSystemWatcher _configFolderWatcher; private static DateTime _lastReloadTime; private static readonly object _reloadLock; private const long ReloadDelayTicks = 10000000L; private static readonly float[] SteerAngles; private static readonly float[] RouteAngles; static MonsterDiveSystem() { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown MonsterDiveConfigLock = new object(); RouteCache = new Dictionary(); SteerCache = new Dictionary(); OriginalDiveFlagsByInstance = new Dictionary(); PrefabSetLock = new object(); _configuredDiveProfilesByPrefabName = new Dictionary(StringComparer.OrdinalIgnoreCase); _reloadLock = new object(); SteerAngles = new float[8] { 0f, -35f, 35f, -70f, 70f, -120f, 120f, 180f }; RouteAngles = new float[5] { 0f, -35f, 35f, -70f, 70f }; string text = Path.Combine(Paths.ConfigPath, "VitByr", "VBDiving"); Directory.CreateDirectory(text); MonsterDiveConfigFolderPath = text; MonsterDiveYamlDeserializer = ((BuilderSkeleton)new DeserializerBuilder()).WithNamingConvention(UnderscoredNamingConvention.Instance).WithDuplicateKeyChecking().Build(); } public static void Initialize() { LoadAllMonsterDiveConfigs(); SetupConfigFolderWatcher(); if ((Object)(object)ZNet.instance != (Object)null && ZNetExtension.IsClientInstance(ZNet.instance) && VBDiving.SyncMonsterConfigs.Value) { Debug.Log((object)"[VBDiving] Client will request monster configs from server after connection"); ((MonoBehaviour)VBDiving.Instance).StartCoroutine(RequestConfigsDelayed()); } } private static IEnumerator RequestConfigsDelayed() { yield return (object)new WaitForSeconds(3f); VBDiving.RequestMonsterConfigsFromServer(); } public static void LoadAllMonsterDiveConfigs() { if (!VBDiving.IsEnabled()) { Debug.LogWarning((object)"[VBDiving] Mod disabled, skipping monster dive config loading"); return; } lock (MonsterDiveConfigLock) { if (ShouldUseServerConfigs() && (Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer()) { Debug.Log((object)"[VBDiving] Skipping local config load on client - waiting for server sync"); } if (!Directory.Exists(MonsterDiveConfigFolderPath)) { Directory.CreateDirectory(MonsterDiveConfigFolderPath); CreateDefaultConfigFileIfNotExists(); } Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); List list = Directory.GetFiles(MonsterDiveConfigFolderPath, "*.yaml").Concat(Directory.GetFiles(MonsterDiveConfigFolderPath, "*.yml")).ToList(); if (list.Count == 0) { Debug.Log((object)("[VBDiving] No monster dive config files found in " + MonsterDiveConfigFolderPath + ", creating default")); CreateDefaultConfigFileIfNotExists(); list = Directory.GetFiles(MonsterDiveConfigFolderPath, "*.yaml").ToList(); } Debug.Log((object)$"[VBDiving] Found {list.Count} monster config file(s)"); foreach (string item in list) { try { LoadConfigFromFile(item, dictionary); } catch (Exception ex) { Debug.LogError((object)("[VBDiving] Failed to load config file " + Path.GetFileName(item) + ": " + ex.Message)); } } lock (PrefabSetLock) { if (_configuredDiveProfilesByPrefabName.Count > 0 && !ZNet.instance.IsServer() && ShouldUseServerConfigs()) { foreach (KeyValuePair item2 in dictionary) { if (!_configuredDiveProfilesByPrefabName.ContainsKey(item2.Key)) { _configuredDiveProfilesByPrefabName[item2.Key] = item2.Value; } } Debug.Log((object)$"[VBDiving] Merged {dictionary.Count} local prefabs with existing server configs"); } else { _configuredDiveProfilesByPrefabName = dictionary; } } ClearRuntimeCaches(); Debug.Log((object)$"[VBDiving] Loaded {_configuredDiveProfilesByPrefabName.Count} monster prefab configurations"); } } private static void ReloadAndResyncConfigs() { if (!VBDiving.IsEnabled() || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } lock (_reloadLock) { try { LoadAllMonsterDiveConfigs(); Debug.Log((object)"[VBDiving] Configs reloaded on server"); } catch (Exception ex) { Debug.LogError((object)("[VBDiving] Error reloading configs: " + ex.Message)); } } } private static void LoadConfigFromFile(string filePath, Dictionary allProfiles) { string text = File.ReadAllText(filePath); if (string.IsNullOrWhiteSpace(text)) { Debug.LogWarning((object)("[VBDiving] Empty config file: " + Path.GetFileName(filePath))); return; } MonsterDiveYamlRoot monsterDiveYamlRoot = ParseYamlRoot(text); if (monsterDiveYamlRoot == null) { return; } Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); string fileName = Path.GetFileName(filePath); foreach (KeyValuePair item in monsterDiveYamlRoot) { string text2 = item.Key?.Trim() ?? ""; if (string.IsNullOrEmpty(text2)) { continue; } MonsterDiveYamlGroup monsterDiveYamlGroup = item.Value ?? new MonsterDiveYamlGroup(); float valueOrDefault = monsterDiveYamlGroup.MinDepth.GetValueOrDefault(); float valueOrDefault2 = monsterDiveYamlGroup.CenterDepth.GetValueOrDefault(); float num; float maxPassiveDepth; if (monsterDiveYamlGroup.MaxAgroDepth.HasValue || monsterDiveYamlGroup.MaxPassiveDepth.HasValue) { num = Mathf.Max(0f, monsterDiveYamlGroup.MaxAgroDepth ?? monsterDiveYamlGroup.MaxDepth ?? 30f); maxPassiveDepth = monsterDiveYamlGroup.MaxPassiveDepth ?? num; } else { num = Mathf.Max(0f, monsterDiveYamlGroup.MaxDepth ?? 30f); maxPassiveDepth = num; } PassiveDepthProfile depthProfile = new PassiveDepthProfile(valueOrDefault, valueOrDefault2, maxPassiveDepth, num); float activeDepthAdjustSpeed = Mathf.Max(0f, monsterDiveYamlGroup.DepthAdjustSpeed ?? 2f); bool valueOrDefault3 = monsterDiveYamlGroup.UseBreath.GetValueOrDefault(); float maxBreathSeconds = Mathf.Max(0f, monsterDiveYamlGroup.MaxBreathSeconds ?? 60f); float breathRecoverySpeed = Mathf.Max(0.1f, monsterDiveYamlGroup.BreathRecoverySpeed ?? 1f); float surfaceTime = Mathf.Max(0f, monsterDiveYamlGroup.SurfaceTime ?? 3f); float surfaceThresholdPercent = Mathf.Clamp01(monsterDiveYamlGroup.SurfaceThresholdPercent ?? 0.33f); ConfiguredDiveProfile value = new ConfiguredDiveProfile(text2, depthProfile, activeDepthAdjustSpeed, valueOrDefault3, maxBreathSeconds, breathRecoverySpeed, surfaceTime, surfaceThresholdPercent); if (monsterDiveYamlGroup.Prefabs == null) { continue; } foreach (string prefab in monsterDiveYamlGroup.Prefabs) { string text3 = prefab?.Trim() ?? ""; if (!string.IsNullOrEmpty(text3)) { if (allProfiles.ContainsKey(text3) || dictionary.ContainsKey(text3)) { Debug.LogWarning((object)("[VBDiving] Prefab '" + text3 + "' already configured, skipping duplicate from " + fileName)); } else { dictionary[text3] = value; } } } } foreach (KeyValuePair item2 in dictionary) { allProfiles[item2.Key] = item2.Value; } Debug.Log((object)$"[VBDiving] Loaded {dictionary.Count} prefabs from {fileName}"); } private static MonsterDiveYamlRoot ParseYamlRoot(string yamlText) { try { MonsterDiveYamlRoot monsterDiveYamlRoot = MonsterDiveYamlDeserializer.Deserialize(yamlText); return monsterDiveYamlRoot ?? new MonsterDiveYamlRoot(); } catch (Exception ex) { Debug.LogError((object)("[VBDiving] Failed to parse YAML: " + ex.Message)); return null; } } private static void CreateDefaultConfigFileIfNotExists() { string text = Path.Combine(MonsterDiveConfigFolderPath, "Vanilla.yaml"); IEnumerable source = Directory.GetFiles(MonsterDiveConfigFolderPath, "*.yaml").Concat(Directory.GetFiles(MonsterDiveConfigFolderPath, "*.yml")); if (!source.Any()) { string contents = BuildDefaultMonsterDiveYaml(); File.WriteAllText(text, contents); Debug.Log((object)("[VBDiving] Created example monster dive config at: " + text)); } } private static void SetupConfigFolderWatcher() { if (_configFolderWatcher == null) { _configFolderWatcher = new FileSystemWatcher(MonsterDiveConfigFolderPath) { NotifyFilter = (NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.CreationTime), IncludeSubdirectories = false, EnableRaisingEvents = true }; _configFolderWatcher.Changed += OnConfigFileChanged; _configFolderWatcher.Created += OnConfigFileChanged; _configFolderWatcher.Deleted += OnConfigFileChanged; _configFolderWatcher.Renamed += OnConfigFileRenamed; Debug.Log((object)("[VBDiving] Watching monster config folder: " + MonsterDiveConfigFolderPath)); } } private static void OnConfigFileChanged(object sender, FileSystemEventArgs e) { if (e.Name.EndsWith(".tmp") || e.Name.StartsWith("~") || (!e.Name.EndsWith(".yaml", StringComparison.OrdinalIgnoreCase) && !e.Name.EndsWith(".yml", StringComparison.OrdinalIgnoreCase))) { return; } DateTime now = DateTime.Now; if (now.Ticks - _lastReloadTime.Ticks < 10000000) { return; } lock (_reloadLock) { try { Debug.Log((object)$"[VBDiving] Config change detected ({e.ChangeType}: {e.Name}). Reloading all configs..."); LoadAllMonsterDiveConfigs(); if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { NotifyServerConfigsChanged(); } _lastReloadTime = now; } catch (Exception ex) { Debug.LogError((object)("[VBDiving] Error reloading monster configs: " + ex.Message)); } } } private static void OnConfigFileRenamed(object sender, RenamedEventArgs e) { if (!e.Name.EndsWith(".yaml", StringComparison.OrdinalIgnoreCase) && !e.Name.EndsWith(".yml", StringComparison.OrdinalIgnoreCase)) { return; } DateTime now = DateTime.Now; if (now.Ticks - _lastReloadTime.Ticks < 10000000) { return; } lock (_reloadLock) { try { Debug.Log((object)("[VBDiving] Config file renamed: " + e.OldName + " -> " + e.Name + ". Reloading all configs...")); if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { ReloadAndResyncConfigs(); } else { LoadAllMonsterDiveConfigs(); } _lastReloadTime = now; } catch (Exception ex) { Debug.LogError((object)("[VBDiving] Error reloading monster configs: " + ex.Message)); } } } private static string BuildDefaultMonsterDiveYaml() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("# Monster dive configuration for VBDiving"); stringBuilder.AppendLine("# You can create multiple .yaml files in this folder"); stringBuilder.AppendLine("# Files are loaded in alphabetical order, later files will NOT override earlier ones"); stringBuilder.AppendLine(); stringBuilder.AppendLine("# Параметры глубины:"); stringBuilder.AppendLine("# min_depth - минимальная глубина (у поверхности)"); stringBuilder.AppendLine("# center_depth - предпочтительная/центральная глубина (в пассивном режиме)"); stringBuilder.AppendLine("# max_passive_depth - максимальная глубина в пассивном режиме"); stringBuilder.AppendLine("# max_agro_depth - максимальная глубина в агрессивном режиме (абсолютный предел)"); stringBuilder.AppendLine(); stringBuilder.AppendLine("# Surface patrol group (патрулирует у поверхности)"); stringBuilder.AppendLine("surface_patrol:"); stringBuilder.AppendLine(" min_depth: 1"); stringBuilder.AppendLine(" center_depth: 2"); stringBuilder.AppendLine(" max_passive_depth: 3 # В спокойствии не глубже 3м"); stringBuilder.AppendLine(" max_agro_depth: 15 # В бою может нырнуть до 10м"); stringBuilder.AppendLine(" depth_adjust_speed: 2"); stringBuilder.AppendLine(" use_breath: true"); stringBuilder.AppendLine(" max_breath_seconds: 60"); stringBuilder.AppendLine(" breath_recovery_speed: 2"); stringBuilder.AppendLine(" surface_time: 3"); stringBuilder.AppendLine(" surface_threshold_percent: 0.33"); stringBuilder.AppendLine(" prefabs:"); stringBuilder.AppendLine(" - Leech"); stringBuilder.AppendLine(); stringBuilder.AppendLine("# Deep hunters (охотники глубин)"); stringBuilder.AppendLine("deep_hunters:"); stringBuilder.AppendLine(" min_depth: 1"); stringBuilder.AppendLine(" center_depth: 5"); stringBuilder.AppendLine(" max_passive_depth: 20 # В спокойствии между 1-20м"); stringBuilder.AppendLine(" max_agro_depth: 50 # В бою может уйти до 50м"); stringBuilder.AppendLine(" depth_adjust_speed: 5"); stringBuilder.AppendLine(" use_breath: true"); stringBuilder.AppendLine(" max_breath_seconds: 120"); stringBuilder.AppendLine(" breath_recovery_speed: 1.5"); stringBuilder.AppendLine(" surface_time: 5"); stringBuilder.AppendLine(" surface_threshold_percent: 0.25"); stringBuilder.AppendLine(" prefabs:"); stringBuilder.AppendLine(" - Serpent"); stringBuilder.AppendLine(" - BonemawSerpent"); stringBuilder.AppendLine(); stringBuilder.AppendLine("# Water creatures without breath (водные без дыхания)"); stringBuilder.AppendLine("water_creatures:"); stringBuilder.AppendLine(" min_depth: 1"); stringBuilder.AppendLine(" center_depth: 5"); stringBuilder.AppendLine(" max_passive_depth: 5 # В спокойствии у поверхности"); stringBuilder.AppendLine(" max_agro_depth: 15"); stringBuilder.AppendLine(" depth_adjust_speed: 3"); stringBuilder.AppendLine(" use_breath: false"); stringBuilder.AppendLine(" prefabs:"); stringBuilder.AppendLine(" - Fish1"); stringBuilder.AppendLine(" - Fish2"); stringBuilder.AppendLine(" - Fish3"); stringBuilder.AppendLine(" - Fish4"); stringBuilder.AppendLine(" - Fish5"); stringBuilder.AppendLine(" - Fish6"); stringBuilder.AppendLine(" - Fish7"); stringBuilder.AppendLine(" - Fish8"); stringBuilder.AppendLine(" - Fish9"); stringBuilder.AppendLine(" - Fish10"); stringBuilder.AppendLine(" - Fish11"); stringBuilder.AppendLine(" - Fish12"); stringBuilder.AppendLine(); return stringBuilder.ToString(); } private static void ClearRuntimeCaches() { RouteCache.Clear(); SteerCache.Clear(); } private static Vector3Int ToCacheBucket(Vector3 value) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) float num = 1f; return new Vector3Int(Mathf.RoundToInt(value.x / num), Mathf.RoundToInt(value.y / num), Mathf.RoundToInt(value.z / num)); } private static void TrimCachesIfNeeded() { if (RouteCache.Count > 2048) { RouteCache.Clear(); } if (SteerCache.Count > 2048) { SteerCache.Clear(); } } private static bool TryGetConfiguredDiveProfile(MonsterAI monsterAI, out ConfiguredDiveProfile profile) { if (!Object.op_Implicit((Object)(object)monsterAI)) { profile = default(ConfiguredDiveProfile); return false; } string prefabName = Utils.GetPrefabName(((Component)monsterAI).gameObject); return _configuredDiveProfilesByPrefabName.TryGetValue(prefabName, out profile); } public static bool IsConfiguredMonster(MonsterAI monsterAI) { ConfiguredDiveProfile profile; return TryGetConfiguredDiveProfile(monsterAI, out profile); } public static bool ShouldUseWaterDiveMode(MonsterAI monsterAI) { Character character = ((BaseAI)monsterAI).m_character; return Object.op_Implicit((Object)(object)character) && character.InWater() && character.InLiquidDepth() > 0.05f; } private static bool IsPassiveDiveState(MonsterAI monsterAI) { return !((BaseAI)monsterAI).IsAlerted() && !Object.op_Implicit((Object)(object)monsterAI.m_targetCreature) && !Object.op_Implicit((Object)(object)monsterAI.m_targetStatic); } private static float GetPassiveDesiredDepth(MonsterAI monsterAI, PassiveDepthProfile profile) { int num = Mathf.Abs(((Object)monsterAI).GetInstanceID()); float num2 = Time.time + (float)(num % 997) * 0.173f; float num3 = Mathf.Sin(Mathf.Repeat(num2, 12f) / 12f * (float)Math.PI * 2f); float num4 = Mathf.Max(0f, profile.MaxPassiveDepth - profile.CenterDepth); float num5 = Mathf.Max(0f, profile.CenterDepth - profile.MinDepth); float num6 = ((!(num3 >= 0f)) ? (profile.CenterDepth + num3 * num5) : (profile.CenterDepth + num3 * num4)); return Mathf.Clamp(num6, profile.MinDepth, profile.MaxPassiveDepth); } public static void EnsureDiveFlags(MonsterAI monsterAI) { int instanceID = ((Object)monsterAI).GetInstanceID(); if (!OriginalDiveFlagsByInstance.ContainsKey(instanceID)) { Character character = ((BaseAI)monsterAI).m_character; OriginalDiveFlagsByInstance[instanceID] = new OriginalDiveFlags(monsterAI, ((BaseAI)monsterAI).m_avoidWater, Object.op_Implicit((Object)(object)character) && character.m_canSwim); if (OriginalDiveFlagsByInstance.Count > 2048) { List list = OriginalDiveFlagsByInstance.Keys.Where((int k) => !Object.op_Implicit((Object)(object)OriginalDiveFlagsByInstance[k].MonsterAI)).ToList(); foreach (int item in list) { OriginalDiveFlagsByInstance.Remove(item); } } } ((BaseAI)monsterAI).m_avoidWater = false; if (Object.op_Implicit((Object)(object)((BaseAI)monsterAI).m_character)) { ((BaseAI)monsterAI).m_character.m_canSwim = true; } } public static Vector3 BuildSteerDirectionWithAvoidance(BaseAI ai, Character character, Vector3 targetPoint) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0239: 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) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0147: 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_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: 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_01b6: Unknown result type (might be due to invalid IL or missing references) int instanceID = ((Object)ai).GetInstanceID(); Vector3Int val = ToCacheBucket(((Component)ai).transform.position); Vector3Int val2 = ToCacheBucket(targetPoint); float time = Time.time; if (SteerCache.TryGetValue(instanceID, out var value) && time - value.Time <= 0.5f && value.PositionBucket == val && value.TargetBucket == val2) { return value.Direction; } Vector3 val3 = targetPoint - ((Component)ai).transform.position; if (((Vector3)(ref val3)).sqrMagnitude <= 0.0001f) { return Vector3.zero; } ((Vector3)(ref val3)).Normalize(); Vector3 val4 = default(Vector3); ((Vector3)(ref val4))..ctor(val3.x, 0f, val3.z); float radius = character.GetRadius(); float num = Mathf.Clamp(Utils.DistanceXZ(targetPoint, ((Component)ai).transform.position), radius + 1f, 6f); if (((Vector3)(ref val4)).sqrMagnitude > 0.0001f) { ((Vector3)(ref val4)).Normalize(); Vector3 val5 = val4; float num2 = float.NegativeInfinity; for (int i = 0; i < SteerAngles.Length; i++) { float num3 = SteerAngles[i]; Vector3 val6 = Quaternion.Euler(0f, num3, 0f) * val4; float num4 = ((!ai.CanMove(val6, radius, num)) ? (ai.Raycast(character.GetCenterPoint(), val6, num * 2f, 0.1f) - Mathf.Abs(num3) * 0.01f) : (1000f - Mathf.Abs(num3))); if (num4 > num2) { num2 = num4; val5 = val6; } } Vector3 val7 = new Vector3(val5.x, val3.y, val5.z); Vector3 normalized = ((Vector3)(ref val7)).normalized; TrimCachesIfNeeded(); SteerCache[instanceID] = new SteerCacheEntry(time, val, val2, normalized); return normalized; } TrimCachesIfNeeded(); SteerCache[instanceID] = new SteerCacheEntry(time, val, val2, val3); return val3; } public static bool HasReasonableUnderwaterRoute(BaseAI ai, Character character, Vector3 targetPoint) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: 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_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0113: 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_0163: 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_016a: 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_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: 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_019d: Unknown result type (might be due to invalid IL or missing references) int instanceID = ((Object)ai).GetInstanceID(); Vector3Int val = ToCacheBucket(((Component)ai).transform.position); Vector3Int val2 = ToCacheBucket(targetPoint); float time = Time.time; if (RouteCache.TryGetValue(instanceID, out var value) && time - value.Time <= 1f && value.PositionBucket == val && value.TargetBucket == val2) { return value.Result; } float num = Utils.DistanceXZ(targetPoint, ((Component)ai).transform.position); float radius = character.GetRadius(); if (num <= radius + 0.6f) { RouteCache[instanceID] = new RouteCacheEntry(time, val, val2, result: true); return true; } Vector3 val3 = targetPoint - ((Component)ai).transform.position; Vector3 val4 = default(Vector3); ((Vector3)(ref val4))..ctor(val3.x, 0f, val3.z); if (((Vector3)(ref val4)).sqrMagnitude <= 0.0001f) { RouteCache[instanceID] = new RouteCacheEntry(time, val, val2, result: true); return true; } ((Vector3)(ref val4)).Normalize(); float num2 = Mathf.Clamp(num, radius + 1f, 6f); for (int i = 0; i < RouteAngles.Length; i++) { Vector3 val5 = Quaternion.Euler(0f, RouteAngles[i], 0f) * val4; if (ai.Raycast(character.GetCenterPoint(), val5, num2, 0.1f) >= num2 * 0.9f) { RouteCache[instanceID] = new RouteCacheEntry(time, val, val2, result: true); return true; } } RouteCache[instanceID] = new RouteCacheEntry(time, val, val2, result: false); return false; } public static void UpdateMonsterBreath(MonsterAI monsterAI, Character character, float dt) { if (!IsConfiguredMonster(monsterAI) || !TryGetConfiguredDiveProfile(monsterAI, out var profile) || !profile.UseBreath) { return; } MonsterSwimState monsterSwimState = MonsterSwimStateManager.Get(monsterAI); if (monsterSwimState.MaxBreath <= 0f) { monsterSwimState.MaxBreath = profile.MaxBreathSeconds; monsterSwimState.Breath = monsterSwimState.MaxBreath; } bool flag = IsMonsterUnderwater(monsterAI, character); if (!flag && character.IsOnGround() && character.InWater()) { flag = true; } if (flag) { monsterSwimState.Breath -= dt; monsterSwimState.SurfaceTimer = 0f; if (monsterSwimState.Breath < 0f) { monsterSwimState.Breath = 0f; monsterSwimState.IsSurfacing = true; } float num = monsterSwimState.Breath / monsterSwimState.MaxBreath; if (num <= profile.SurfaceThresholdPercent) { monsterSwimState.IsSurfacing = true; } } else { monsterSwimState.Breath += dt * profile.BreathRecoverySpeed; monsterSwimState.SurfaceTimer += dt; if (monsterSwimState.Breath >= monsterSwimState.MaxBreath) { monsterSwimState.Breath = monsterSwimState.MaxBreath; if (monsterSwimState.SurfaceTimer >= profile.SurfaceTime) { monsterSwimState.IsSurfacing = false; } } } monsterSwimState.WasUnderwater = flag; } public static bool IsMonsterUnderwater(MonsterAI monsterAI, Character character) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)character) || !Object.op_Implicit((Object)(object)monsterAI)) { return false; } Vector3 headPoint = character.GetHeadPoint(); float liquidLevel = character.GetLiquidLevel(); return headPoint.y < liquidLevel - 0.1f; } public static float UpdateSwimDepthTowardsTarget(MonsterAI monsterAI, Character character, Vector3 point, float dt) { //IL_00eb: 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) TryGetConfiguredDiveProfile(monsterAI, out var profile); float liquidLevel = character.GetLiquidLevel(); float num = 2f; bool flag = ((BaseAI)monsterAI).IsAlerted() || Object.op_Implicit((Object)(object)monsterAI.m_targetCreature) || Object.op_Implicit((Object)(object)monsterAI.m_targetStatic); float num2 = (flag ? profile.DepthProfile.MaxAgroDepth : profile.DepthProfile.MaxPassiveDepth); MonsterSwimState monsterSwimState = null; float num3; if (profile.UseBreath) { monsterSwimState = MonsterSwimStateManager.Get(monsterAI); if (monsterSwimState.IsSurfacing) { num3 = 0.5f; num = profile.ActiveDepthAdjustSpeed * 1.5f; } else if (flag) { float num4 = liquidLevel - point.y; num3 = Mathf.Clamp(num4, profile.DepthProfile.MinDepth + 0.25f, num2); num = profile.ActiveDepthAdjustSpeed; } else { num3 = GetPassiveDesiredDepth(monsterAI, profile.DepthProfile); } } else if (flag) { float num5 = liquidLevel - point.y; num3 = Mathf.Clamp(num5, profile.DepthProfile.MinDepth + 0.25f, num2); num = profile.ActiveDepthAdjustSpeed; } else { num3 = GetPassiveDesiredDepth(monsterAI, profile.DepthProfile); } if (num <= 0f) { character.m_swimDepth = num3; return liquidLevel - num3; } character.m_swimDepth = Mathf.MoveTowards(character.m_swimDepth, num3, num * Mathf.Max(dt, 0.01f)); return liquidLevel - num3; } public static string GetSerializedConfigs() { lock (MonsterDiveConfigLock) { Debug.Log((object)$"[MonsterDiveSystem] GetSerializedConfigs: {_configuredDiveProfilesByPrefabName.Count} profiles found"); if (_configuredDiveProfilesByPrefabName.Count == 0) { Debug.LogWarning((object)"[MonsterDiveSystem] No profiles to serialize!"); return ""; } StringBuilder stringBuilder = new StringBuilder(); foreach (KeyValuePair item in _configuredDiveProfilesByPrefabName) { string key = item.Key; ConfiguredDiveProfile value = item.Value; stringBuilder.Append(key); stringBuilder.Append('|'); stringBuilder.Append(value.GroupName); stringBuilder.Append('|'); stringBuilder.Append(value.DepthProfile.MinDepth); stringBuilder.Append('|'); stringBuilder.Append(value.DepthProfile.CenterDepth); stringBuilder.Append('|'); stringBuilder.Append(value.DepthProfile.MaxPassiveDepth); stringBuilder.Append('|'); stringBuilder.Append(value.DepthProfile.MaxAgroDepth); stringBuilder.Append('|'); stringBuilder.Append(value.ActiveDepthAdjustSpeed); stringBuilder.Append('|'); stringBuilder.Append(value.UseBreath ? "1" : "0"); stringBuilder.Append('|'); stringBuilder.Append(value.MaxBreathSeconds); stringBuilder.Append('|'); stringBuilder.Append(value.BreathRecoverySpeed); stringBuilder.Append('|'); stringBuilder.Append(value.SurfaceTime); stringBuilder.Append('|'); stringBuilder.Append(value.SurfaceThresholdPercent); stringBuilder.Append('\n'); Debug.Log((object)$"[MonsterDiveSystem] Serialized: {key} -> {value.GroupName} (passive max: {value.DepthProfile.MaxPassiveDepth}, agro max: {value.DepthProfile.MaxAgroDepth})"); } string text = stringBuilder.ToString(); Debug.Log((object)$"[MonsterDiveSystem] Serialized {_configuredDiveProfilesByPrefabName.Count} prefabs, total length: {text.Length}"); return text; } } public static void LoadSerializedConfigs(string configData, bool useServerOnly = false) { Debug.Log((object)$"[MonsterDiveSystem] LoadSerializedConfigs called, data length: {configData?.Length ?? 0}, useServerOnly: {useServerOnly}"); if (string.IsNullOrEmpty(configData)) { Debug.LogWarning((object)"[MonsterDiveSystem] Empty configData received!"); return; } if (!VBDiving.IsEnabled()) { Debug.LogWarning((object)"[VBDiving] Mod disabled, skipping server config loading"); return; } lock (MonsterDiveConfigLock) { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); string[] array = configData.Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries); string[] array2 = array; foreach (string text in array2) { string[] array3 = text.Split(new char[1] { '|' }); if (array3.Length < 12) { Debug.LogWarning((object)$"[MonsterDiveSystem] Invalid line format, expected 12 parts, got {array3.Length}: {text}"); continue; } try { string text2 = array3[0]; string groupName = array3[1]; float minDepth = float.Parse(array3[2]); float centerDepth = float.Parse(array3[3]); float num = float.Parse(array3[4]); float num2 = float.Parse(array3[5]); float activeDepthAdjustSpeed = float.Parse(array3[6]); bool useBreath = array3[7] == "1"; float maxBreathSeconds = float.Parse(array3[8]); float breathRecoverySpeed = float.Parse(array3[9]); float surfaceTime = float.Parse(array3[10]); float surfaceThresholdPercent = float.Parse(array3[11]); PassiveDepthProfile depthProfile = new PassiveDepthProfile(minDepth, centerDepth, num, num2); ConfiguredDiveProfile value = new ConfiguredDiveProfile(groupName, depthProfile, activeDepthAdjustSpeed, useBreath, maxBreathSeconds, breathRecoverySpeed, surfaceTime, surfaceThresholdPercent); dictionary[text2] = value; Debug.Log((object)$"[MonsterDiveSystem] Loaded server config: {text2} -> passive max: {num}, agro max: {num2}"); } catch (Exception ex) { Debug.LogError((object)("[MonsterDiveSystem] Failed to parse config line: " + text + ", error: " + ex.Message)); } } if (dictionary.Count == 0) { Debug.LogWarning((object)"[VBDiving] No valid profiles found in server config data"); return; } if (useServerOnly) { lock (PrefabSetLock) { _configuredDiveProfilesByPrefabName = dictionary; } Debug.Log((object)$"[VBDiving] Loaded {dictionary.Count} monster prefab configurations FROM SERVER ONLY"); } else { lock (PrefabSetLock) { Dictionary dictionary2 = new Dictionary(StringComparer.OrdinalIgnoreCase); LoadLocalConfigsToDictionary(dictionary2); foreach (KeyValuePair item in dictionary) { dictionary2[item.Key] = item.Value; } _configuredDiveProfilesByPrefabName = dictionary2; } Debug.Log((object)$"[VBDiving] Loaded {dictionary.Count} server configs (merged with local, server priority)"); } ClearRuntimeCaches(); } } private static void LoadLocalConfigsToDictionary(Dictionary targetDict) { if (!Directory.Exists(MonsterDiveConfigFolderPath)) { return; } List list = Directory.GetFiles(MonsterDiveConfigFolderPath, "*.yaml").Concat(Directory.GetFiles(MonsterDiveConfigFolderPath, "*.yml")).ToList(); foreach (string item in list) { try { string text = File.ReadAllText(item); if (string.IsNullOrWhiteSpace(text)) { continue; } MonsterDiveYamlRoot monsterDiveYamlRoot = ParseYamlRoot(text); if (monsterDiveYamlRoot == null) { continue; } foreach (KeyValuePair item2 in monsterDiveYamlRoot) { string text2 = item2.Key?.Trim() ?? ""; if (string.IsNullOrEmpty(text2)) { continue; } MonsterDiveYamlGroup monsterDiveYamlGroup = item2.Value ?? new MonsterDiveYamlGroup(); float valueOrDefault = monsterDiveYamlGroup.MinDepth.GetValueOrDefault(); float valueOrDefault2 = monsterDiveYamlGroup.CenterDepth.GetValueOrDefault(); float num; float maxPassiveDepth; if (monsterDiveYamlGroup.MaxAgroDepth.HasValue || monsterDiveYamlGroup.MaxPassiveDepth.HasValue) { num = Mathf.Max(0f, monsterDiveYamlGroup.MaxAgroDepth ?? monsterDiveYamlGroup.MaxDepth ?? 30f); maxPassiveDepth = monsterDiveYamlGroup.MaxPassiveDepth ?? num; } else { num = Mathf.Max(0f, monsterDiveYamlGroup.MaxDepth ?? 30f); maxPassiveDepth = num; } PassiveDepthProfile depthProfile = new PassiveDepthProfile(valueOrDefault, valueOrDefault2, maxPassiveDepth, num); float activeDepthAdjustSpeed = Mathf.Max(0f, monsterDiveYamlGroup.DepthAdjustSpeed ?? 2f); bool valueOrDefault3 = monsterDiveYamlGroup.UseBreath.GetValueOrDefault(); float maxBreathSeconds = Mathf.Max(0f, monsterDiveYamlGroup.MaxBreathSeconds ?? 60f); float breathRecoverySpeed = Mathf.Max(0.1f, monsterDiveYamlGroup.BreathRecoverySpeed ?? 1f); float surfaceTime = Mathf.Max(0f, monsterDiveYamlGroup.SurfaceTime ?? 3f); float surfaceThresholdPercent = Mathf.Clamp01(monsterDiveYamlGroup.SurfaceThresholdPercent ?? 0.33f); ConfiguredDiveProfile value = new ConfiguredDiveProfile(text2, depthProfile, activeDepthAdjustSpeed, valueOrDefault3, maxBreathSeconds, breathRecoverySpeed, surfaceTime, surfaceThresholdPercent); if (monsterDiveYamlGroup.Prefabs == null) { continue; } foreach (string prefab in monsterDiveYamlGroup.Prefabs) { string text3 = prefab?.Trim() ?? ""; if (!string.IsNullOrEmpty(text3)) { targetDict[text3] = value; } } } } catch (Exception ex) { Debug.LogError((object)("[VBDiving] Failed to load local config: " + ex.Message)); } } } private static void NotifyServerConfigsChanged() { if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer()) { VBDiving.OnServerConfigsChanged(); } } public static bool ShouldUseServerConfigs() { if (!Object.op_Implicit((Object)(object)ZNet.instance)) { return false; } if (ZNet.instance.IsServer()) { return false; } return VBDiving.SyncMonsterConfigs?.Value ?? true; } } internal class MonsterSwimState { public float Breath; public float MaxBreath; public bool WasUnderwater; public bool IsSurfacing; public float SurfaceTimer; public bool WasOutOfBreath; public float LastSurfaceTime; public float SuffocationTickTimer; } internal static class MonsterSwimStateManager { private static readonly Dictionary States = new Dictionary(); public static MonsterSwimState Get(MonsterAI monsterAI) { int instanceID = ((Object)monsterAI).GetInstanceID(); if (!States.TryGetValue(instanceID, out var value)) { value = new MonsterSwimState(); States[instanceID] = value; } return value; } public static void Remove(MonsterAI monsterAI) { if (Object.op_Implicit((Object)(object)monsterAI)) { States.Remove(((Object)monsterAI).GetInstanceID()); } } public static void Clear() { States.Clear(); } } } namespace VBDiving.Effects { internal class DiveImmersionEffect : MonoBehaviour { private struct EnvState { public EnvSetup m_currentEnv; public float m_fogDensityDay; public float m_fogDensityNight; public float m_lightIntensityDay; public float m_lightIntensityNight; public Color m_ambColorDay; public Color m_ambColorNight; public Color m_fogColorDay; public Color m_fogColorNight; public void Save(EnvSetup env) { //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_0050: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_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) m_currentEnv = env; if (env != null) { m_fogDensityDay = env.m_fogDensityDay; m_fogDensityNight = env.m_fogDensityNight; m_lightIntensityDay = env.m_lightIntensityDay; m_lightIntensityNight = env.m_lightIntensityNight; m_ambColorDay = env.m_ambColorDay; m_ambColorNight = env.m_ambColorNight; m_fogColorDay = env.m_fogColorDay; m_fogColorNight = env.m_fogColorNight; } } public void Restore() { //IL_005e: 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_006f: 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_0085: 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_0096: Unknown result type (might be due to invalid IL or missing references) if (m_currentEnv != null) { m_currentEnv.m_fogDensityDay = m_fogDensityDay; m_currentEnv.m_fogDensityNight = m_fogDensityNight; m_currentEnv.m_lightIntensityDay = m_lightIntensityDay; m_currentEnv.m_lightIntensityNight = m_lightIntensityNight; m_currentEnv.m_ambColorDay = m_ambColorDay; m_currentEnv.m_ambColorNight = m_ambColorNight; m_currentEnv.m_fogColorDay = m_fogColorDay; m_currentEnv.m_fogColorNight = m_fogColorNight; } } } private EnvState _savedEnvState; private bool _envStateSaved; internal static bool IsUnderwaterImmersionActive; private AudioLowPassFilter _lowPass; private bool _active; private float _intensity; private Behaviour _ownedHeatDistort; private Type _heatDistortType; private const float FadeSpeed = 4f; private const float HeatDistortionIntensity = 0.25f; private static readonly Color HeatDistortionColor = new Color(0.2f, 0.4f, 0.5f, 0.5f); private void ModifyEnvironmentForUnderwater(float intensity) { //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: 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_0110: 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_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: 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_0137: 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_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) EnvMan instance = EnvMan.instance; if (Object.op_Implicit((Object)(object)instance)) { if (!_envStateSaved) { _savedEnvState.Save(instance.m_currentEnv); _envStateSaved = true; } if (_savedEnvState.m_currentEnv != null) { EnvSetup currentEnv = instance.m_currentEnv; currentEnv.m_fogDensityDay = Mathf.Lerp(_savedEnvState.m_fogDensityDay, 0.05f, intensity); currentEnv.m_fogDensityNight = Mathf.Lerp(_savedEnvState.m_fogDensityNight, 0.15f, intensity); currentEnv.m_lightIntensityDay = Mathf.Lerp(_savedEnvState.m_lightIntensityDay, 0.5f, intensity); currentEnv.m_lightIntensityNight = Mathf.Lerp(_savedEnvState.m_lightIntensityNight, 0.15f, intensity); Color val = default(Color); ((Color)(ref val))..ctor(0.2f, 0.3f, 0.3f); currentEnv.m_ambColorDay = Color.Lerp(_savedEnvState.m_ambColorDay, val, intensity); currentEnv.m_ambColorNight = Color.Lerp(_savedEnvState.m_ambColorNight, val * 0.5f, intensity); currentEnv.m_fogColorDay = Color.Lerp(_savedEnvState.m_fogColorDay, val, intensity); currentEnv.m_fogColorNight = Color.Lerp(_savedEnvState.m_fogColorNight, val, intensity); } } } private void Update() { if (!VBDiving.IsEnabled()) { ResetEffects(); return; } if (ShouldUseDiveEffect()) { _active = true; } else if (_active && ShouldExitDiveEffect()) { _active = false; } _intensity = Mathf.MoveTowards(_intensity, _active ? 1f : 0f, Time.deltaTime * 4f); bool flag = (IsUnderwaterImmersionActive = _intensity > 0.001f); EnsureHeatDistortion(); if (Object.op_Implicit((Object)(object)_ownedHeatDistort)) { _ownedHeatDistort.enabled = flag; ApplyHeatDistortionValues(); } if (flag) { ApplyAudio(); ModifyEnvironmentForUnderwater(_intensity); return; } RestoreAudio(); if (_envStateSaved) { _savedEnvState.Restore(); _envStateSaved = false; } } private void ResetEffects() { _active = false; _intensity = 0f; IsUnderwaterImmersionActive = false; if (_envStateSaved) { _savedEnvState.Restore(); _envStateSaved = false; } RestoreAudio(); if (Object.op_Implicit((Object)(object)_ownedHeatDistort)) { _ownedHeatDistort.enabled = false; } } private bool ShouldUseDiveEffect() { Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)GameCamera.instance)) { return false; } PlayerDiveController localInstance = PlayerDiveController.LocalInstance; if (!Object.op_Implicit((Object)(object)localInstance)) { return false; } if (localInstance.is_diving) { return true; } if (localInstance.IsHeadUnderwater() || localInstance.IsUnderSurface()) { return true; } return false; } private bool ShouldExitDiveEffect() { Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)GameCamera.instance)) { return true; } PlayerDiveController localInstance = PlayerDiveController.LocalInstance; if (!Object.op_Implicit((Object)(object)localInstance)) { return true; } if (!localInstance.toggleDive && !localInstance.is_diving && !localInstance.IsHeadUnderwater()) { return true; } if (!localInstance.IsUnderSurface() && !localInstance.toggleDive) { return true; } return false; } private void EnsureHeatDistortion() { if (Object.op_Implicit((Object)(object)_ownedHeatDistort)) { return; } GameCamera instance = GameCamera.instance; Camera val = ((instance != null) ? ((Component)instance).GetComponent() : null); if (!Object.op_Implicit((Object)(object)val)) { return; } _heatDistortType = AccessTools.TypeByName("HeatDistortImageEffect"); if (_heatDistortType == null) { return; } Component component = ((Component)val).GetComponent(_heatDistortType); ref Behaviour ownedHeatDistort = ref _ownedHeatDistort; Component obj = ((Component)val).gameObject.AddComponent(_heatDistortType); ownedHeatDistort = (Behaviour)(object)((obj is Behaviour) ? obj : null); if (Object.op_Implicit((Object)(object)_ownedHeatDistort)) { if (Object.op_Implicit((Object)(object)component)) { CopyFields(component, (Component)(object)_ownedHeatDistort); } _ownedHeatDistort.enabled = false; ApplyHeatDistortionValues(); } } private void ApplyHeatDistortionValues() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)_ownedHeatDistort)) { Type type = ((object)_ownedHeatDistort).GetType(); SetField(type, _ownedHeatDistort, "m_intensity", 0.25f * _intensity); SetField(type, _ownedHeatDistort, "m_color", HeatDistortionColor); } } private static void CopyFields(Component source, Component target) { if (!Object.op_Implicit((Object)(object)source) || !Object.op_Implicit((Object)(object)target)) { return; } Type type = ((object)source).GetType(); FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { if (!fieldInfo.IsInitOnly && !fieldInfo.IsLiteral) { try { fieldInfo.SetValue(target, fieldInfo.GetValue(source)); } catch { } } } } private static void SetField(Type type, object instance, string fieldName, T value) { FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { return; } try { field.SetValue(instance, value); } catch { } } private void ApplyAudio() { AudioListener val = Object.FindFirstObjectByType(); if (!Object.op_Implicit((Object)(object)val)) { return; } if (!Object.op_Implicit((Object)(object)_lowPass)) { _lowPass = ((Component)val).gameObject.GetComponent(); if (!Object.op_Implicit((Object)(object)_lowPass)) { _lowPass = ((Component)val).gameObject.AddComponent(); } } ((Behaviour)_lowPass).enabled = true; _lowPass.cutoffFrequency = Mathf.Lerp(22000f, 1500f, _intensity); _lowPass.lowpassResonanceQ = Mathf.Lerp(1f, 1.3f, _intensity); } private void RestoreAudio() { if (Object.op_Implicit((Object)(object)_lowPass)) { ((Behaviour)_lowPass).enabled = false; _lowPass = null; } } private void OnDestroy() { ResetEffects(); if (Object.op_Implicit((Object)(object)_ownedHeatDistort)) { Object.Destroy((Object)(object)_ownedHeatDistort); } } } } internal sealed class <>z__ReadOnlyArray : IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList, ICollection, IList { int IReadOnlyCollection.Count => _items.Length; T IReadOnlyList.this[int index] => _items[index]; int ICollection.Count => _items.Length; bool ICollection.IsReadOnly => true; T IList.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } public <>z__ReadOnlyArray(T[] items) { _items = items; } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } void ICollection.Add(T item) { throw new NotSupportedException(); } void ICollection.Clear() { throw new NotSupportedException(); } bool ICollection.Contains(T item) { return ((ICollection)_items).Contains(item); } void ICollection.CopyTo(T[] array, int arrayIndex) { ((ICollection)_items).CopyTo(array, arrayIndex); } bool ICollection.Remove(T item) { throw new NotSupportedException(); } int IList.IndexOf(T item) { return ((IList)_items).IndexOf(item); } void IList.Insert(int index, T item) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } }