Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of VBDiving v0.1.1
plugins/VBDiving.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; 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.UI; using VBDiving.Effects; using VBDiving.Mobs; using VBDiving.Patches; using VBDiving.Syncronization; using VBDiving.Utills; 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] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } public enum DiveControl { Button, Legacy } namespace VBDiving { internal class BreathHud : MonoBehaviour { private GameObject _root; private RectTransform _container; private readonly List<Image> _bubbles = new List<Image>(); private Sprite _bubbleSprite; private TextMeshProUGUI _breathText; private bool _isInitialized; private bool _initializationAttempted; 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() { _isInitialized = false; _initializationAttempted = false; } private void Start() { TryInitialize(); } private void TryInitialize() { if (!_isInitialized && !_initializationAttempted && Object.op_Implicit((Object)(object)Player.m_localPlayer)) { _initializationAttempted = true; TMP_FontAsset val = FindFont(); if (!Object.op_Implicit((Object)(object)val)) { VBDiving.LogDebug("[BreathHud] Font not found yet, will retry later"); _initializationAttempted = false; ((MonoBehaviour)this).StartCoroutine(RetryInitialize()); } else { CreateHud(val); ApplyPositionAndScale(); _isInitialized = true; VBDiving.LogDebug("[BreathHud] Successfully initialized"); } } } private IEnumerator RetryInitialize() { for (int i = 0; i < 10; i++) { yield return (object)new WaitForSeconds(1f); TMP_FontAsset font = FindFont(); if (Object.op_Implicit((Object)(object)font) && Object.op_Implicit((Object)(object)Player.m_localPlayer)) { CreateHud(font); ApplyPositionAndScale(); _isInitialized = true; VBDiving.LogDebug("[BreathHud] Successfully initialized on retry"); yield break; } } VBDiving.LogDebug("[BreathHud] Failed to initialize after retries, using fallback"); CreateHudWithFallbackFont(); ApplyPositionAndScale(); _isInitialized = true; } private TMP_FontAsset FindFont() { TMP_FontAsset val = ((IEnumerable<TMP_FontAsset>)Resources.FindObjectsOfTypeAll<TMP_FontAsset>()).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset f) => ((Object)f).name == "Valheim-Norsebold")); if (!Object.op_Implicit((Object)(object)val)) { val = ((IEnumerable<TMP_FontAsset>)Resources.FindObjectsOfTypeAll<TMP_FontAsset>()).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset f) => ((Object)f).name == "LiberationSans SDF")); } if (!Object.op_Implicit((Object)(object)val)) { val = Resources.FindObjectsOfTypeAll<TMP_FontAsset>().FirstOrDefault(); } return val; } private void CreateHudWithFallbackFont() { CreateHud(null); ((MonoBehaviour)this).StartCoroutine(AssignFontLater()); } private IEnumerator AssignFontLater() { yield return (object)new WaitForSeconds(2f); TMP_FontAsset font = FindFont(); if (Object.op_Implicit((Object)(object)font) && Object.op_Implicit((Object)(object)_breathText)) { ((TMP_Text)_breathText).font = font; VBDiving.LogDebug("[BreathHud] Font assigned after delay"); } } private void Update() { if (!_isInitialized) { TryInitialize(); return; } 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; PlayerDiveController localInstance = PlayerDiveController.LocalInstance; bool flag3 = Object.op_Implicit((Object)(object)localInstance) && (localInstance.toggleDive || localInstance.is_diving); bool flag4 = flag || flag2 || flag3; SetVisible(flag4); if (flag4) { 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(TMP_FontAsset font) { //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_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) _root = new GameObject("BreathHud"); Object.DontDestroyOnLoad((Object)(object)_root); Canvas val = _root.AddComponent<Canvas>(); val.renderMode = (RenderMode)0; val.sortingOrder = 5000; CanvasScaler val2 = _root.AddComponent<CanvasScaler>(); val2.uiScaleMode = (ScaleMode)1; val2.referenceResolution = new Vector2(1920f, 1080f); val2.matchWidthOrHeight = 0.5f; _root.AddComponent<GraphicRaycaster>(); GameObject val3 = new GameObject("Container"); val3.transform.SetParent(_root.transform, false); _container = val3.AddComponent<RectTransform>(); 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<RectTransform>(); 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<Image>(); val6.sprite = _bubbleSprite; val6.preserveAspect = true; ((Graphic)val6).color = new Color(0.8f, 0.92f, 1f, 0.8f); _bubbles.Add(val6); } GameObject val7 = new GameObject("BreathText"); val7.transform.SetParent((Transform)(object)_container, false); _breathText = val7.AddComponent<TextMeshProUGUI>(); if (Object.op_Implicit((Object)(object)font)) { ((TMP_Text)_breathText).font = font; } else { TMP_FontAsset val8 = Resources.FindObjectsOfTypeAll<TMP_FontAsset>().FirstOrDefault(); if (Object.op_Implicit((Object)(object)val8)) { ((TMP_Text)_breathText).font = val8; } } ((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); } } [BepInPlugin("VitByr.VBDiving", "VBDiving", "0.1.1")] [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.1.1"; internal static VBDiving Instance; internal static Harmony Harmony; internal static ConfigEntry<bool> EnableMod; internal static ConfigEntry<float> MaxBreathSeconds; internal static ConfigEntry<float> MaxBreathBonusAtSkill100; internal static ConfigEntry<float> BreathRecoveryPerSecond; internal static ConfigEntry<float> SprintSwimMultiplier; internal static ConfigEntry<float> BaseUnderwaterStaminaRegenPerSecond; internal static ConfigEntry<bool> DebugLogging; internal static ConfigEntry<DiveControl> UseLegacyDiveControls; internal static float SwimStaminaDrainMinSkill = 4f; internal static float SwimStaminaDrainMaxSkill = 2f; internal static ConfigEntry<float> BreathHudOffsetX; internal static ConfigEntry<float> BreathHudOffsetY; internal static ConfigEntry<float> BreathHudScale; internal static ConfigEntry<bool> BreathHudShowLabels; internal static ConfigEntry<bool> SyncMonsterConfigs; internal static ConfigEntry<bool> UseServerMonsterConfigsOnly; internal static ConfigEntry<bool> SyncDiveEffectsConfigs; internal static ConfigEntry<bool> UseServerDiveEffectsConfigsOnly; private ConfigFileWatcher _configWatcher; internal static string ConfigFolderPath; public static ConfigEntry<Language> c_ConfigLanguage; public static CustomRPC _diveEffectsConfigRPC; public bool _hasRequestedDiveEffectsConfigs; public static CustomRPC _monsterConfigRPC; public bool _hasRequestedConfigs; private void Awake() { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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; MonsterDiveSystem.Initialize(); DiveEffectsConfigSystem.Initialize(); ((Component)this).gameObject.AddComponent<BreathHud>(); ((Component)this).gameObject.AddComponent<DiveImmersionEffect>(); ((MonoBehaviour)this).StartCoroutine(InitDiveControllerWhenReady()); Harmony = new Harmony("VitByr.VBDiving"); Harmony.PatchAll(); MonsterSync.SetupMonsterConfigSync(); DiveEffectSync.SetupDiveEffectsConfigSync(); } 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<PlayerDiveController>(ref playerDiveController)) { ((Component)player).gameObject.AddComponent<PlayerDiveController>(); ((BaseUnityPlugin)this).Logger.LogDebug((object)"DiveController added to local player"); } } private void CreateConfig() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; string text = "00 - Main"; c_ConfigLanguage = ((BaseUnityPlugin)this).Config.Bind<Language>(text, "Language", Language.Russian, new ConfigDescription("Select interface language / Выберите язык интерфейса\nRequired Restart / Требуется рестарт", (AcceptableValueBase)null, Array.Empty<object>())); EnableMod = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, text, "EnableMod", true, (c_ConfigLanguage.Value == Language.Russian) ? "Включить или отключить мод." : "Enable or disable the mod.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); SyncMonsterConfigs = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, text, "SyncMonsterConfigs", true, (c_ConfigLanguage.Value == Language.Russian) ? "Синхронизировать конфиги монстров с сервера." : "Synchronize monster configs from the server.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); UseServerMonsterConfigsOnly = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, text, "UseServerMonsterConfigsOnly", true, (c_ConfigLanguage.Value == Language.Russian) ? "Использовать ТОЛЬКО конфиги с сервера (игнорировать локальные файлы). Если false - серверные конфиги имеют приоритет над локальными." : "Use ONLY configs from the server (ignore local files). If false, server configs have priority over local ones.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); SyncDiveEffectsConfigs = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, text, "SyncDiveEffectsConfigs", true, (c_ConfigLanguage.Value == Language.Russian) ? "Синхронизировать конфиги подводных эффектов с сервера." : "Synchronize underwater effects configurations from the server.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); UseServerDiveEffectsConfigsOnly = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, text, "UseServerDiveEffectsConfigsOnly", true, (c_ConfigLanguage.Value == Language.Russian) ? "Использовать ТОЛЬКО конфиги с сервера (игнорировать локальные файлы). Если false - серверные конфиги имеют приоритет над локальными." : "Use ONLY configs from the server (ignore local files). If false, server configs have priority over local ones.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); UseLegacyDiveControls = ((BaseUnityPlugin)this).Config.Bind<DiveControl>("01 - Control", "UseLegacyDiveControls", DiveControl.Legacy, (c_ConfigLanguage.Value == Language.Russian) ? "Button: зажать L.Ctrl для погружения, Space для всплытия.\nLegacy: нажать L.Ctrl для переключения режима ныряния, затем направление взгляда + W для движения вверх/вниз." : "Button: hold down L.Ctrl for diving, Space for surfacing.\nLegacy: press L.Ctrl to switch diving mode, then gaze direction + W to move up/down."); MaxBreathSeconds = ConfigFileExtensions.BindConfig<float>(((BaseUnityPlugin)this).Config, "02 - Breath", "MaxBreathSeconds", 30f, (c_ConfigLanguage.Value == Language.Russian) ? "Максимальное время под водой при навыке плавания 0." : "The maximum time underwater with the swimming skill is 0.", true, (int?)null, (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 600f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); MaxBreathBonusAtSkill100 = ConfigFileExtensions.BindConfig<float>(((BaseUnityPlugin)this).Config, "02 - Breath", "MaxBreathBonusAtSkill100", 150f, (c_ConfigLanguage.Value == Language.Russian) ? "Дополнительное время под водой при навыке плавания 100." : "Extra time underwater with a swimming skill of 100.", true, (int?)null, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); BreathRecoveryPerSecond = ConfigFileExtensions.BindConfig<float>(((BaseUnityPlugin)this).Config, "02 - Breath", "BreathRecoveryPerSecond", 30f, (c_ConfigLanguage.Value == Language.Russian) ? "Скорость восстановления дыхания." : "The rate of respiration recovery.", true, (int?)null, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); BreathHudOffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("03 - BreathHud", "OffsetX", 0f, (c_ConfigLanguage.Value == Language.Russian) ? "Смещение индикатора по горизонтали от центра экрана (в процентах от ширины экрана).\nОтрицательное = левее, положительное = правее." : "The horizontal offset of the indicator from the center of the screen (as a percentage of the screen width).\nNegative = to the left, positive = to the right."); BreathHudOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("03 - BreathHud", "OffsetY", -30f, (c_ConfigLanguage.Value == Language.Russian) ? "Смещение индикатора по вертикали от центра экрана (в процентах от высоты экрана).\nОтрицательное = ниже, положительное = выше." : "The vertical offset of the indicator from the center of the screen (as a percentage of the screen height).\nNegative = lower, positive = higher."); BreathHudScale = ConfigFileExtensions.BindConfig<float>(((BaseUnityPlugin)this).Config, "03 - BreathHud", "Scale", 1f, (c_ConfigLanguage.Value == Language.Russian) ? "Масштаб индикатора дыхания." : "The scale of the breathing indicator.", false, (int?)null, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.3f, 3f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); BreathHudShowLabels = ((BaseUnityPlugin)this).Config.Bind<bool>("03 - BreathHud", "ShowLabels", true, (c_ConfigLanguage.Value == Language.Russian) ? "Показывать числовое значение дыхания справа от пузырьков." : "Show the numerical value of the breath to the right of the bubbles."); SprintSwimMultiplier = ConfigFileExtensions.BindConfig<float>(((BaseUnityPlugin)this).Config, "04 - Swimming", "SprintSwimMultiplier", 2.5f, (c_ConfigLanguage.Value == Language.Russian) ? "Множитель скорости при спринте в воде на максимальном навыке." : "Speed multiplier when sprinting in water at swimming skill of 100.", true, (int?)null, (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); BaseUnderwaterStaminaRegenPerSecond = ConfigFileExtensions.BindConfig<float>(((BaseUnityPlugin)this).Config, "04 - Swimming", "BaseUnderwaterStaminaRegenPerSecond", 1.25f, (c_ConfigLanguage.Value == Language.Russian) ? "Базовая скорость восстановления выносливости на поверхности без движения." : "Basic endurance recovery rate on a non-moving surface.", true, (int?)null, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); PlayerEquipInWater.EquipInWaterList = ConfigFileExtensions.BindConfig<string>(((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", (c_ConfigLanguage.Value == Language.Russian) ? "Разрешить использовать оружие/инструмент в воде" : "Allow the use of weapons/tools in the water", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); PlayerEquipInWater.EquipInWaterList.SettingChanged += delegate { HashSet<string> hashSet2 = new HashSet<string>(); string[] array2 = PlayerEquipInWater.EquipInWaterList.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (string item2 in array2) { hashSet2.Add(item2); } PlayerEquipInWater.EquipInWaterItems = hashSet2; }; HashSet<string> hashSet = new HashSet<string>(); 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<bool>("Debug", "DebugLogging", false, (c_ConfigLanguage.Value == Language.Russian) ? "Включить отладочные логи." : "Enable debugging logs"); ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; ((BaseUnityPlugin)this).Config.Save(); } private void CreateConfigWatcher() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown _configWatcher = new ConfigFileWatcher(((BaseUnityPlugin)this).Config, 1000L); _configWatcher.OnConfigFileReloaded += delegate { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Config file reloaded from disk."); }; } 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.op_Implicit((Object)(object)ZNet.instance) && ZNetExtension.IsClientInstance(ZNet.instance)) { ((MonoBehaviour)this).StartCoroutine(RequestConfigsAfterSync()); } } if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer()) { if (SyncMonsterConfigs.Value) { MonsterSync.SendMonsterConfigsToAllClients(); } if (SyncDiveEffectsConfigs.Value) { DiveEffectSync.SendDiveEffectsConfigsToAllClients(); } } } private IEnumerator RequestConfigsAfterSync() { yield return (object)new WaitForSeconds(2f); MonsterSync.RequestMonsterConfigsFromServer(); DiveEffectSync.RequestDiveEffectsConfigsFromServer(); } 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); } } } } 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<MonsterAI>(); 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<Rigidbody>(); 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<string, MonsterDiveYamlGroup> { public MonsterDiveYamlRoot() : base((IEqualityComparer<string>?)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<string> Prefabs { get; set; } = new List<string>(); } internal static readonly string MonsterDiveConfigFolderPath; private static readonly object MonsterDiveConfigLock; private static readonly IDeserializer MonsterDiveYamlDeserializer; private static readonly Dictionary<int, RouteCacheEntry> RouteCache; private static readonly Dictionary<int, SteerCacheEntry> SteerCache; private static readonly Dictionary<int, OriginalDiveFlags> OriginalDiveFlagsByInstance; private const int MaxCacheEntries = 2048; private static readonly object PrefabSetLock; private static Dictionary<string, ConfiguredDiveProfile> _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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown MonsterDiveConfigLock = new object(); RouteCache = new Dictionary<int, RouteCacheEntry>(); SteerCache = new Dictionary<int, SteerCacheEntry>(); OriginalDiveFlagsByInstance = new Dictionary<int, OriginalDiveFlags>(); PrefabSetLock = new object(); _configuredDiveProfilesByPrefabName = new Dictionary<string, ConfiguredDiveProfile>(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", "Monsters"); Directory.CreateDirectory(text); MonsterDiveConfigFolderPath = text; MonsterDiveYamlDeserializer = ((BuilderSkeleton<DeserializerBuilder>)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); MonsterSync.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<string, ConfiguredDiveProfile> dictionary = new Dictionary<string, ConfiguredDiveProfile>(StringComparer.OrdinalIgnoreCase); List<string> 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<string, ConfiguredDiveProfile> 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<string, ConfiguredDiveProfile> 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<string, ConfiguredDiveProfile> dictionary = new Dictionary<string, ConfiguredDiveProfile>(StringComparer.OrdinalIgnoreCase); string fileName = Path.GetFileName(filePath); foreach (KeyValuePair<string, MonsterDiveYamlGroup> 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 == true; 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<string, ConfiguredDiveProfile> 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<MonsterDiveYamlRoot>(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<string> 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<int> 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<string, ConfiguredDiveProfile> 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<string, ConfiguredDiveProfile> dictionary = new Dictionary<string, ConfiguredDiveProfile>(StringComparer.OrdinalIgnoreCase); string[] array = configData.Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries); string[] array2 = array; foreach (string text in array2) { string[] array3 = text.Split('|'); 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<string, ConfiguredDiveProfile> dictionary2 = new Dictionary<string, ConfiguredDiveProfile>(StringComparer.OrdinalIgnoreCase); LoadLocalConfigsToDictionary(dictionary2); foreach (KeyValuePair<string, ConfiguredDiveProfile> 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<string, ConfiguredDiveProfile> targetDict) { if (!Directory.Exists(MonsterDiveConfigFolderPath)) { return; } List<string> 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<string, MonsterDiveYamlGroup> 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 == true; 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()) { MonsterSync.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<int, MonsterSwimState> States = new Dictionary<int, MonsterSwimState>(); 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.Utills { public enum Language { Russian, English } internal sealed class PlayerDiveController : MonoBehaviour { internal const float DefaultSwimDepth = 1.4f; internal const float DivingThreshold = 1.45f; internal const float MaxSwimDepth = 100f; internal const float DepthChangeSpeed = 0.05f; [NonSerialized] internal bool toggleDive; [NonSerialized] internal bool is_diving; [NonSerialized] internal bool isUnderwater; private float _baseSwimSpeed; private float _diveAxis; private float _legacyDiveVertical; private bool _legacyDiveActive; public bool _but_crouch => InputHelper.GetCrouch(); public bool _but_jump => InputHelper.GetJump(); public bool _but_forward => InputHelper.GetForward(); internal static PlayerDiveController LocalInstance { get; private set; } internal Player Player { get; private set; } = null; private void Awake() { Player = ((Component)this).GetComponent<Player>(); 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.4f; _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).IsSwimming()) { if (toggleDive) { toggleDive = false; is_diving = false; _legacyDiveActive = false; _legacyDiveVertical = 0f; } } else if (VBDiving.UseLegacyDiveControls.Value == DiveControl.Button) { HandleButtonControls(); } else if (_but_crouch && !toggleDive) { toggleDive = true; ((Character)Player).m_swimDepth = Mathf.Max(((Character)Player).m_swimDepth, 1.5f); } } private void HandleButtonControls() { if (_but_crouch) { toggleDive = true; _legacyDiveActive = true; _legacyDiveVertical = 1f; return; } if (_but_jump) { _legacyDiveActive = true; _legacyDiveVertical = -1f; return; } _legacyDiveVertical = 0f; if (((Character)Player).m_swimDepth <= 1.45f) { toggleDive = false; _legacyDiveActive = false; } else { _legacyDiveActive = false; } } internal void UpdateDiveState() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) if (!((Character)Player).InWater()) { ((Character)Player).m_swimDepth = 1.4f; return; } if (((Character)Player).m_swimDepth > 1.45f && Mathf.Max(0f, ((Character)Player).GetLiquidLevel() - ((Component)Player).transform.position.y) > 1.45f) { is_diving = true; isUnderwater = true; return; } if (is_diving) { is_diving = false; if (((Character)Player).m_swimDepth <= 1.45f) { toggleDive = false; ((Character)Player).m_swimDepth = 1.4f; } } isUnderwater = false; } internal void UpdateDiveDepth(Vector3 lookDir) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020a: 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 == DiveControl.Button) { UpdateLegacyDiveMovement(); } else { if (!toggleDive) { return; } if (lookDir.y < -0.5f) { _diveAxis = 1f; } else if (lookDir.y > 0.5f) { _diveAxis = 0f; } if (!_but_forward) { return; } float num2; if (_diveAxis == 1f) { float num = Mathf.Abs(lookDir.y); num2 = num * 0.05f; if (num2 < 0.005f && num > 0.9f) { num2 = 0.005f; } } else if (_diveAxis == 0f) { num2 = lookDir.y * 0.05f; if (num2 < 0.005f && lookDir.y > 0.9f) { num2 = 0.005f; } } else { num2 = 0f; } if (num2 > 0.05f) { num2 = 0.05f; } ApplyVerticalMovement(num2); if (!(((Character)Player).m_swimDepth > 1.45f)) { 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.4f) { ((Character)Player).m_swimDepth = 1.4f; return; } float num = legacyDiveVertical * 0.05f; float num2 = ((Character)Player).m_swimDepth + num; num2 = Mathf.Clamp(num2, 1.4f, 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;