Please disclose if your mod was created primarily 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 Dive In v1.0.1
DiveIn.dll
Decompiled an hour 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.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using ServerSync; using TMPro; using UnityEngine; using UnityEngine.Rendering; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.ObjectPool; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Callbacks; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("DiveIn")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("sighsorry")] [assembly: AssemblyProduct("DiveIn")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")] [assembly: AssemblyFileVersion("1.0.1")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class ExtensionMarkerAttribute : Attribute { private readonly string <Name>k__BackingField; public string Name => <Name>k__BackingField; public ExtensionMarkerAttribute(string name) { <Name>k__BackingField = name; } } } namespace ServerSyncModTemplate { [BepInPlugin("sighsorry.DiveIn", "DiveIn", "1.0.1")] public class ServerSyncModTemplatePlugin : BaseUnityPlugin { private sealed class MonsterDiveYamlRoot { public MonsterDiveYamlGlobal Global { get; set; } = new MonsterDiveYamlGlobal(); public Dictionary<string, MonsterDiveYamlGroup> Groups { get; set; } = new Dictionary<string, MonsterDiveYamlGroup>(StringComparer.OrdinalIgnoreCase); } private sealed class MonsterDiveYamlGlobal { public float SwimDepthMin { get; set; } = DefaultMonsterDiveGlobalSettings.SwimDepthMin; public float SwimDepthMax { get; set; } = DefaultMonsterDiveGlobalSettings.SwimDepthMax; public float SwimDepthAdjustSpeed { get; set; } = DefaultMonsterDiveGlobalSettings.SwimDepthAdjustSpeed; } private sealed class MonsterDiveYamlGroup { public float PassiveMinDepth { get; set; } public float PassiveCenterDepth { get; set; } public float PassiveMaxDepth { get; set; } public List<string> Prefabs { get; set; } = new List<string>(); } private readonly struct MonsterDiveGlobalSettings { public float SwimDepthMin { get; } public float SwimDepthMax { get; } public float SwimDepthAdjustSpeed { get; } public MonsterDiveGlobalSettings(float swimDepthMin, float swimDepthMax, float swimDepthAdjustSpeed) { SwimDepthMin = swimDepthMin; SwimDepthMax = swimDepthMax; SwimDepthAdjustSpeed = swimDepthAdjustSpeed; } } 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 CenterDepth; public readonly float MinDepth; public readonly float MaxDepth; public PassiveDepthProfile(float centerDepth, float minDepth, float maxDepth) { CenterDepth = centerDepth; MinDepth = minDepth; MaxDepth = maxDepth; } } private readonly struct ConfiguredDiveProfile { public readonly string GroupName; public readonly PassiveDepthProfile PassiveDepthProfile; public ConfiguredDiveProfile(string groupName, PassiveDepthProfile passiveDepthProfile) { GroupName = groupName; PassiveDepthProfile = passiveDepthProfile; } } 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; } } public enum Toggle { On = 1, Off = 0 } private readonly struct SwimDepthGoal { public readonly float ClampedTargetY; public readonly bool RequestedOutsideRange; public SwimDepthGoal(float clampedTargetY, bool requestedOutsideRange) { ClampedTargetY = clampedTargetY; RequestedOutsideRange = requestedOutsideRange; } } [HarmonyPatch(typeof(MonsterAI), "Awake")] private static class MonsterAIAwakePatch { private static void Postfix(MonsterAI __instance) { if (IsConfiguredMonster(__instance)) { EnsureDiveFlags(__instance); TryLogOverlapFields(__instance, "MonsterAI.Awake"); } } } [HarmonyPatch(typeof(MonsterAI), "UpdateAI")] private static class MonsterAIUpdateAIPatch { private static void Prefix(MonsterAI __instance) { if (IsConfiguredMonster(__instance)) { EnsureDiveFlags(__instance); TryLogOverlapFields(__instance, "MonsterAI.UpdateAI"); } } } [HarmonyPatch(typeof(BaseAI), "HavePath")] private static class BaseAIHavePathPatch { private static bool Prefix(BaseAI __instance, Vector3 target, ref bool __result) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (!TryGetConfiguredMonster(__instance, out MonsterAI monsterAI) || !ShouldUseWaterDiveMode(monsterAI)) { return true; } Character character = ((BaseAI)monsterAI).m_character; if ((Object)(object)character == (Object)null) { return true; } __result = HasReasonableUnderwaterRoute(__instance, character, target); TryLogOverlapFields(monsterAI, "BaseAI.HavePath"); return false; } } [HarmonyPatch(typeof(BaseAI), "MoveTo")] private static class BaseAIMoveToPatch { private static bool Prefix(BaseAI __instance, float dt, Vector3 point, float dist, bool run, ref bool __result) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_008f: 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_0103: 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_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) if (!TryGetConfiguredMonster(__instance, out MonsterAI monsterAI) || !ShouldUseWaterDiveMode(monsterAI)) { return true; } Character character = ((BaseAI)monsterAI).m_character; if ((Object)(object)character == (Object)null) { return true; } SwimDepthGoal swimDepthGoal = UpdateSwimDepthTowardsTarget(monsterAI, character, point, dt); TryLogOverlapFields(monsterAI, "BaseAI.MoveTo"); float num = Mathf.Max(dist, run ? 1f : 0.5f); float num2 = Utils.DistanceXZ(point, ((Component)__instance).transform.position); float num3 = Mathf.Abs(point.y - ((Component)__instance).transform.position.y); float num4 = Mathf.Abs(swimDepthGoal.ClampedTargetY - ((Component)__instance).transform.position.y); bool flag = num3 < 0.75f || (swimDepthGoal.RequestedOutsideRange && num4 < 0.35f); if (num2 < num && flag) { __instance.StopMoving(); __result = true; return false; } Vector3 val = point - ((Component)__instance).transform.position; if (((Vector3)(ref val)).sqrMagnitude <= 0.0001f) { __instance.StopMoving(); __result = true; return false; } Vector3 val2 = BuildSteerDirectionWithAvoidance(__instance, character, point); if (((Vector3)(ref val2)).sqrMagnitude <= 0.0001f) { __instance.StopMoving(); __result = true; return false; } __instance.MoveTowards(val2, run); __result = false; return false; } } private class ConfigurationManagerAttributes { [UsedImplicitly] public int? Order = null; [UsedImplicitly] public bool? Browsable = null; [UsedImplicitly] public string? Category = null; [UsedImplicitly] public Action<ConfigEntryBase>? CustomDrawer = null; } private class AcceptableShortcuts : AcceptableValueBase { public AcceptableShortcuts() : base(typeof(KeyboardShortcut)) { } public override object Clamp(object value) { return value; } public override bool IsValid(object value) { return true; } public override string ToDescriptionString() { return "# Acceptable values: " + string.Join(", ", UnityInput.Current.SupportedKeyCodes); } } private static readonly string MonsterDiveYamlFileName = "DiveIn.yaml"; private static readonly string MonsterDiveYamlFileFullPath; private static readonly object MonsterDiveYamlLock; private static readonly IDeserializer MonsterDiveYamlDeserializer; private static readonly MonsterDiveGlobalSettings DefaultMonsterDiveGlobalSettings; private FileSystemWatcher _monsterDiveYamlWatcher = null; private DateTime _lastMonsterDiveYamlReloadTime; private static CustomSyncedValue<string> _monsterDiveYamlSync; private static MonsterDiveGlobalSettings _monsterDiveGlobalSettings; internal const float DefaultUnderwaterColorDarknessFactor = 0.02f; internal const float DefaultUnderwaterVisibilityFalloff = 0f; internal const float DefaultMinimumUnderwaterMurkiness = 0.05f; internal const float DefaultMaximumUnderwaterMurkiness = 1f; internal const float DefaultUnderwaterCameraMinWaterDistance = -5000f; internal static ConfigEntry<string> _waterEquipmentBlacklist; internal static ConfigEntry<float> _waterStaminaRegenRateMultiplier; internal static ConfigEntry<float> _waterDepthStaminaDrainStart; internal static ConfigEntry<float> _waterDepthStaminaDrainFull; internal static ConfigEntry<float> _waterDepthStaminaDrainMaxMultiplier; internal static ConfigEntry<float> _playerSwimRunSpeedMultiplier; private static readonly object WaterEquipmentBlacklistLock; private static string _lastWaterEquipmentBlacklistRaw; private static HashSet<string> _waterEquipmentBlacklistSet; internal const string ModName = "DiveIn"; internal const string ModVersion = "1.0.1"; internal const string Author = "sighsorry"; private const string ModGUID = "sighsorry.DiveIn"; private static readonly string ConfigFileName; private static readonly string ConfigFileFullPath; internal static string ConnectionError; private readonly Harmony _harmony = new Harmony("sighsorry.DiveIn"); public static readonly ManualLogSource ServerSyncModTemplateLogger; private static readonly ConfigSync ConfigSync; private static ConfigEntry<float> _diveAiQuality; private static readonly object PrefabSetLock; private static Dictionary<string, ConfiguredDiveProfile> _configuredDiveProfilesByPrefabName; private FileSystemWatcher _watcher = null; private readonly object _reloadLock = new object(); private DateTime _lastConfigReloadTime; private const long RELOAD_DELAY = 10000000L; private const float PassiveWavePeriodSeconds = 12f; private static readonly float[] SteerAngles; private static readonly float[] RouteAngles; 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 ConfigEntry<Toggle> _serverConfigLocked; private void InitializeMonsterDiveYaml() { _monsterDiveYamlSync = new CustomSyncedValue<string>(ConfigSync, "MonsterDiveYaml", string.Empty); _monsterDiveYamlSync.ValueChanged += OnMonsterDiveYamlValueChanged; ConfigSync.SourceOfTruthChanged += OnMonsterDiveSourceOfTruthChanged; if (ConfigSync.IsSourceOfTruth) { LoadMonsterDiveYamlFromDisk(forceWriteDefaultIfMissing: true, syncToPeers: true, "startup"); } else if (!string.IsNullOrWhiteSpace(_monsterDiveYamlSync.Value)) { ApplyMonsterDiveYaml(_monsterDiveYamlSync.Value, "startup synced value"); } } private void SetupMonsterDiveYamlWatcher() { _monsterDiveYamlWatcher = new FileSystemWatcher(Paths.ConfigPath, MonsterDiveYamlFileName); _monsterDiveYamlWatcher.Changed += ReadMonsterDiveYamlValues; _monsterDiveYamlWatcher.Created += ReadMonsterDiveYamlValues; _monsterDiveYamlWatcher.Renamed += ReadMonsterDiveYamlValues; _monsterDiveYamlWatcher.IncludeSubdirectories = true; _monsterDiveYamlWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; _monsterDiveYamlWatcher.EnableRaisingEvents = true; } private void DisposeMonsterDiveYamlWatcher() { _monsterDiveYamlWatcher?.Dispose(); } private void ReadMonsterDiveYamlValues(object sender, FileSystemEventArgs e) { DateTime now = DateTime.Now; if (now.Ticks - _lastMonsterDiveYamlReloadTime.Ticks < 10000000) { return; } lock (_reloadLock) { if (!ConfigSync.IsSourceOfTruth) { ServerSyncModTemplateLogger.LogInfo((object)"Ignoring local monster dive YAML reload because remote synced values are active."); return; } try { LoadMonsterDiveYamlFromDisk(forceWriteDefaultIfMissing: true, syncToPeers: true, "yaml reload"); ServerSyncModTemplateLogger.LogInfo((object)"Monster dive YAML reload complete."); } catch (Exception ex) { ServerSyncModTemplateLogger.LogError((object)("Error reloading monster dive YAML: " + ex.Message)); } } _lastMonsterDiveYamlReloadTime = now; } private void OnMonsterDiveSourceOfTruthChanged(bool isSourceOfTruth) { if (isSourceOfTruth) { LoadMonsterDiveYamlFromDisk(forceWriteDefaultIfMissing: true, syncToPeers: true, "source of truth changed to local"); } else if (!string.IsNullOrWhiteSpace(_monsterDiveYamlSync.Value)) { ApplyMonsterDiveYaml(_monsterDiveYamlSync.Value, "source of truth changed to remote"); } } private void OnMonsterDiveYamlValueChanged() { if (!ConfigSync.IsSourceOfTruth && !string.IsNullOrWhiteSpace(_monsterDiveYamlSync.Value)) { ApplyMonsterDiveYaml(_monsterDiveYamlSync.Value, "synced value changed"); } } private static MonsterDiveYamlGroup CreateDefaultGroup(float minDepth, float centerDepth, float maxDepth) { return new MonsterDiveYamlGroup { PassiveMinDepth = minDepth, PassiveCenterDepth = centerDepth, PassiveMaxDepth = maxDepth, Prefabs = new List<string>() }; } private void LoadMonsterDiveYamlFromDisk(bool forceWriteDefaultIfMissing, bool syncToPeers, string reason) { lock (MonsterDiveYamlLock) { if (!File.Exists(MonsterDiveYamlFileFullPath)) { if (!forceWriteDefaultIfMissing) { return; } string contents = BuildDefaultMonsterDiveYaml(); Directory.CreateDirectory(Paths.ConfigPath); File.WriteAllText(MonsterDiveYamlFileFullPath, contents); } string text = File.ReadAllText(MonsterDiveYamlFileFullPath); if (ApplyMonsterDiveYaml(text, reason) && syncToPeers && _monsterDiveYamlSync.Value != text) { _monsterDiveYamlSync.Value = text; } } } private static bool ApplyMonsterDiveYaml(string yamlText, string reason) { if (string.IsNullOrWhiteSpace(yamlText)) { ServerSyncModTemplateLogger.LogWarning((object)("Monster dive YAML is empty during " + reason + ". Keeping previous settings.")); return false; } MonsterDiveYamlRoot monsterDiveYamlRoot; try { monsterDiveYamlRoot = MonsterDiveYamlDeserializer.Deserialize<MonsterDiveYamlRoot>(yamlText) ?? new MonsterDiveYamlRoot(); } catch (YamlException ex) { string text = ((ex.Start.Line > 0) ? $" at line {ex.Start.Line}, column {ex.Start.Column}" : string.Empty); ServerSyncModTemplateLogger.LogError((object)("Failed to parse monster dive YAML during " + reason + text + ": " + ex.Message)); return false; } catch (Exception ex2) { ServerSyncModTemplateLogger.LogError((object)("Failed to parse monster dive YAML during " + reason + ": " + ex2.Message)); return false; } MonsterDiveGlobalSettings monsterDiveGlobalSettings = NormalizeGlobalSettings(monsterDiveYamlRoot.Global); Dictionary<string, MonsterDiveYamlGroup> definedGroups = GetDefinedGroups(monsterDiveYamlRoot); Dictionary<string, ConfiguredDiveProfile> dictionary = new Dictionary<string, ConfiguredDiveProfile>(StringComparer.OrdinalIgnoreCase); foreach (KeyValuePair<string, MonsterDiveYamlGroup> item in definedGroups) { string key = item.Key; MonsterDiveYamlGroup value = item.Value; PassiveDepthProfile passiveProfile = NormalizePassiveDepthProfile(key, value.PassiveMinDepth, value.PassiveCenterDepth, value.PassiveMaxDepth); AddYamlGroupEntries(dictionary, value.Prefabs, key, passiveProfile); } if (dictionary.Count == 0) { ServerSyncModTemplateLogger.LogWarning((object)("Monster dive YAML loaded during " + reason + ", but no prefabs are assigned to any group.")); } lock (PrefabSetLock) { _monsterDiveGlobalSettings = monsterDiveGlobalSettings; _configuredDiveProfilesByPrefabName = dictionary; } int num = RestoreRemovedMonsterDiveFlags(); ClearRuntimeCaches(); ServerSyncModTemplateLogger.LogInfo((object)$"Loaded monster dive YAML ({reason}). global[min={monsterDiveGlobalSettings.SwimDepthMin:F2}, max={monsterDiveGlobalSettings.SwimDepthMax:F2}, adjust={monsterDiveGlobalSettings.SwimDepthAdjustSpeed:F2}], groups={definedGroups.Count}, prefabs={dictionary.Count}, restoredRemovedInstances={num}."); return true; } private static MonsterDiveGlobalSettings NormalizeGlobalSettings(MonsterDiveYamlGlobal? global) { if (global == null) { return DefaultMonsterDiveGlobalSettings; } float swimDepthMin = global.SwimDepthMin; float swimDepthMax = global.SwimDepthMax; float swimDepthAdjustSpeed = global.SwimDepthAdjustSpeed; float num = Mathf.Max(0.25f, swimDepthMin); float num2 = Mathf.Max(num, swimDepthMax); float num3 = Mathf.Max(0f, swimDepthAdjustSpeed); if (!Mathf.Approximately(num, swimDepthMin) || !Mathf.Approximately(num2, swimDepthMax) || !Mathf.Approximately(num3, swimDepthAdjustSpeed)) { ServerSyncModTemplateLogger.LogWarning((object)("Monster dive YAML normalized global values: swim_depth_min " + swimDepthMin.ToString("0.###", CultureInfo.InvariantCulture) + " -> " + num.ToString("0.###", CultureInfo.InvariantCulture) + ", swim_depth_max " + swimDepthMax.ToString("0.###", CultureInfo.InvariantCulture) + " -> " + num2.ToString("0.###", CultureInfo.InvariantCulture) + ", swim_depth_adjust_speed " + swimDepthAdjustSpeed.ToString("0.###", CultureInfo.InvariantCulture) + " -> " + num3.ToString("0.###", CultureInfo.InvariantCulture) + ".")); } return new MonsterDiveGlobalSettings(num, num2, num3); } private static PassiveDepthProfile NormalizePassiveDepthProfile(string groupName, float minDepth, float centerDepth, float maxDepth) { float num = minDepth; float num2 = centerDepth; float num3 = maxDepth; float num4 = Mathf.Max(0f, num); float num5 = Mathf.Max(0f, num3); if (num5 < num4) { float num6 = num5; num5 = num4; num4 = num6; } float num7 = Mathf.Clamp(num2, num4, num5); if (!Mathf.Approximately(num4, num) || !Mathf.Approximately(num5, num3) || !Mathf.Approximately(num7, num2)) { ServerSyncModTemplateLogger.LogWarning((object)("Monster dive YAML normalized passive profile '" + groupName + "': passive_min_depth " + num.ToString("0.###", CultureInfo.InvariantCulture) + " -> " + num4.ToString("0.###", CultureInfo.InvariantCulture) + ", passive_center_depth " + num2.ToString("0.###", CultureInfo.InvariantCulture) + " -> " + num7.ToString("0.###", CultureInfo.InvariantCulture) + ", passive_max_depth " + num3.ToString("0.###", CultureInfo.InvariantCulture) + " -> " + num5.ToString("0.###", CultureInfo.InvariantCulture) + ".")); } return new PassiveDepthProfile(num7, num4, num5); } private static Dictionary<string, MonsterDiveYamlGroup> GetDefinedGroups(MonsterDiveYamlRoot root) { Dictionary<string, MonsterDiveYamlGroup> dictionary = new Dictionary<string, MonsterDiveYamlGroup>(StringComparer.OrdinalIgnoreCase); if (root.Groups == null || root.Groups.Count == 0) { return dictionary; } foreach (KeyValuePair<string, MonsterDiveYamlGroup> group in root.Groups) { string text = group.Key?.Trim() ?? string.Empty; if (text.Length == 0) { ServerSyncModTemplateLogger.LogWarning((object)"Monster dive YAML contains an empty group name under groups:. Skipping it."); } else { dictionary[text] = group.Value ?? new MonsterDiveYamlGroup(); } } return dictionary; } private static void AddYamlGroupEntries(Dictionary<string, ConfiguredDiveProfile> configuredProfilesByPrefabName, IEnumerable<string>? mobs, string groupName, PassiveDepthProfile passiveProfile) { if (mobs == null) { return; } foreach (string mob in mobs) { string text = mob?.Trim() ?? string.Empty; if (text.Length != 0) { if (configuredProfilesByPrefabName.ContainsKey(text)) { ServerSyncModTemplateLogger.LogWarning((object)("Monster dive YAML duplicate mob '" + text + "' found in " + groupName + ". Keeping first assignment.")); } else { configuredProfilesByPrefabName[text] = new ConfiguredDiveProfile(groupName, passiveProfile); } } } } private static string BuildDefaultMonsterDiveYaml() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("# Monster dive configuration for DiveIn."); stringBuilder.AppendLine("# Unknown keys and duplicate keys are treated as errors and keep the previous applied settings."); stringBuilder.AppendLine("global:"); stringBuilder.AppendLine(" swim_depth_min: " + FormatYamlFloat(DefaultMonsterDiveGlobalSettings.SwimDepthMin) + " # Minimum underwater depth allowed while a configured monster actively chases a target."); stringBuilder.AppendLine(" swim_depth_max: " + FormatYamlFloat(DefaultMonsterDiveGlobalSettings.SwimDepthMax) + " # Maximum underwater depth allowed while a configured monster actively chases a target."); stringBuilder.AppendLine(" swim_depth_adjust_speed: " + FormatYamlFloat(DefaultMonsterDiveGlobalSettings.SwimDepthAdjustSpeed) + " # How quickly a configured monster adjusts its swim depth toward the requested active target depth."); stringBuilder.AppendLine(); stringBuilder.AppendLine("groups:"); AppendDefaultGroup(stringBuilder, "surface_patrol", 0f, 10f, 20f, includeGroupHeaderComment: true, new string[2] { "Serpent", "Leech" }); stringBuilder.AppendLine(); AppendDefaultGroup(stringBuilder, "mid_water", 0f, 15f, 30f); stringBuilder.AppendLine(); AppendDefaultGroup(stringBuilder, "deep_patrol", 10f, 20f, 30f); stringBuilder.AppendLine(); stringBuilder.AppendLine("## RtDOcean sample"); stringBuilder.AppendLine(); AppendDefaultGroup(stringBuilder, "rtd_surface", 0f, 10f, 20f, includeGroupHeaderComment: false, new string[11] { "Neck_RtD", "Animal_Dolphin_RtD", "Animal_Cod_RtD", "Monster_GreatWhiteShark_RtD", "Animal_Turtle_RtD", "Mirmaid_RtD", "BoneFish_RtD", "BoneSquid_RtD", "LuminousLooker_RtD", "MurkPod_RtD", "Animal_HumpbackWhale_RtD" }); stringBuilder.AppendLine(); AppendDefaultGroup(stringBuilder, "rtd_midwater", 0f, 15f, 30f, includeGroupHeaderComment: false, new string[6] { "Belzor_RtD", "Monster_HammerheadShark_RtD", "Animal_Marlin_RtD", "Shark_RtD", "Animal_SpermWhale_RtD", "Monster_Orca_RtD" }); stringBuilder.AppendLine(); AppendDefaultGroup(stringBuilder, "rtd_deep", 10f, 20f, 30f, includeGroupHeaderComment: false, new string[2] { "Animal_Tuna_RtD", "Animal_Squid_RtD" }); stringBuilder.AppendLine(); AppendDefaultGroup(stringBuilder, "rtd_bottom", 20f, 30f, 40f, includeGroupHeaderComment: false, new string[3] { "CatFish_RtD", "Reptile_RtD", "Animal_Manta_RtD" }); return stringBuilder.ToString(); } private static void AppendDefaultGroup(StringBuilder builder, string groupName, float minDepth, float centerDepth, float maxDepth, bool includeGroupHeaderComment = false, IEnumerable<string>? examplePrefabs = null) { string text = (includeGroupHeaderComment ? " # You can use any group name. Add your own groups" : string.Empty); builder.AppendLine(" " + groupName + ":" + text); builder.AppendLine(" passive_min_depth: " + FormatYamlFloat(minDepth) + " # Shallowest passive dive depth used while the monster has no target and is not alerted."); builder.AppendLine(" passive_center_depth: " + FormatYamlFloat(centerDepth) + " # Center depth used by the passive sine-wave swimming pattern."); builder.AppendLine(" passive_max_depth: " + FormatYamlFloat(maxDepth) + " # Deepest passive dive depth used while the monster has no target and is not alerted."); if (examplePrefabs != null) { string[] array = examplePrefabs.Where((string prefab) => !string.IsNullOrWhiteSpace(prefab)).ToArray(); if (array.Length != 0) { builder.AppendLine(" prefabs: # Monster prefab names assigned to this passive profile group."); string[] array2 = array; foreach (string text2 in array2) { builder.AppendLine(" - " + text2); } return; } } builder.AppendLine(" prefabs: [] # Monster prefab names assigned to this passive profile group."); } private static string FormatYamlFloat(float value) { return value.ToString("0.###", CultureInfo.InvariantCulture); } private void InitializePlayerDiveConfig() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Expected O, but got Unknown //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Expected O, but got Unknown //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Expected O, but got Unknown _waterEquipmentBlacklist = config("2a - Player Diving", "Water Equipment Blacklist", "", new ConfigDescription("Comma-separated item prefab names that remain restricted in water. Everything not listed is allowed in water by default. Example: BowFineWood,ShieldBronzeBuckler.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 100 } })); _waterStaminaRegenRateMultiplier = config("2a - Player Diving", "Water Stamina Regen Rate", 0.5f, new ConfigDescription("Multiplier applied to vanilla stamina regeneration while swimming or diving in water. 0 matches vanilla swimming behavior (effective stamina regeneration stays at 0), 1 matches vanilla normal non-swimming stamina regeneration timing and rate.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), new object[1] { new ConfigurationManagerAttributes { Order = 99 } })); _waterDepthStaminaDrainStart = config("2a - Player Diving", "Water Depth Stamina Drain Start", 2.5f, new ConfigDescription("Depth in meters below the surface where extra swim stamina drain begins.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), new object[1] { new ConfigurationManagerAttributes { Order = 98 } })); _waterDepthStaminaDrainFull = config("2a - Player Diving", "Water Depth Stamina Drain Full", 30f, new ConfigDescription("Depth in meters below the surface where the maximum extra swim stamina drain multiplier is reached.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 100f), new object[1] { new ConfigurationManagerAttributes { Order = 97 } })); _waterDepthStaminaDrainMaxMultiplier = config("2a - Player Diving", "Water Depth Stamina Drain Max Multiplier", 2f, new ConfigDescription("Maximum multiplier applied to vanilla moving swim stamina drain at or below the full depth.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), new object[1] { new ConfigurationManagerAttributes { Order = 96 } })); _playerSwimRunSpeedMultiplier = config("2a - Player Diving", "Swim Run Speed Multiplier", 1.5f, new ConfigDescription("Multiplier applied to vanilla base swim speed while holding the run key underwater. 1 matches vanilla swim speed, 1.5 matches swim speed 3 with vanilla base swim speed 2.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f), new object[1] { new ConfigurationManagerAttributes { Order = 95 } })); } internal static bool IsPlayerDivingEnabled() { return true; } internal static bool IsUnderwaterCameraFollowEnabled() { return IsPlayerDiveEnvAllowed(); } internal static bool IsUnderwaterVisualStylingEnabled() { return IsPlayerDiveEnvAllowed(); } internal static bool IsUnderwaterVisualDebugLoggingEnabled() { return false; } internal static float GetUnderwaterCameraMinWaterDistance() { return -5000f; } internal static bool IsPlayerDiveEnvAllowed() { return true; } internal static bool IsWaterRestrictedItem(ItemData? item) { if (item == null || (Object)(object)item.m_dropPrefab == (Object)null) { return false; } RefreshWaterEquipmentBlacklistIfNeeded(); string prefabName = Utils.GetPrefabName(item.m_dropPrefab); return !string.IsNullOrEmpty(prefabName) && _waterEquipmentBlacklistSet.Contains(prefabName); } internal static bool HumanoidHasWaterRestrictedEquipment(Humanoid? humanoid) { if ((Object)(object)humanoid == (Object)null) { return false; } return IsWaterRestrictedItem(humanoid.m_rightItem) || IsWaterRestrictedItem(humanoid.m_hiddenRightItem) || IsWaterRestrictedItem(humanoid.m_leftItem) || IsWaterRestrictedItem(humanoid.m_hiddenLeftItem) || IsWaterRestrictedItem(humanoid.m_chestItem) || IsWaterRestrictedItem(humanoid.m_legItem) || IsWaterRestrictedItem(humanoid.m_helmetItem) || IsWaterRestrictedItem(humanoid.m_shoulderItem) || IsWaterRestrictedItem(humanoid.m_utilityItem) || IsWaterRestrictedItem(humanoid.m_trinketItem); } private static void RefreshWaterEquipmentBlacklistIfNeeded(bool force = false) { string text = _waterEquipmentBlacklist?.Value ?? string.Empty; if (!force && string.Equals(text, _lastWaterEquipmentBlacklistRaw, StringComparison.Ordinal)) { return; } lock (WaterEquipmentBlacklistLock) { if (force || !string.Equals(text, _lastWaterEquipmentBlacklistRaw, StringComparison.Ordinal)) { _waterEquipmentBlacklistSet = (from entry in text.Split(new char[5] { ',', ';', '\n', '\r', '\t' }, StringSplitOptions.RemoveEmptyEntries) select entry.Trim() into entry where entry.Length > 0 select entry).ToHashSet<string>(StringComparer.OrdinalIgnoreCase); _lastWaterEquipmentBlacklistRaw = text; } } } public void Awake() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; _serverConfigLocked = config("1 - General", "Lock Configuration", Toggle.On, "If on, the configuration is locked and can be changed by server admins only."); ConfigSync.AddLockingConfigEntry<Toggle>(_serverConfigLocked); _diveAiQuality = config("3 - Performance", "Dive AI Quality", 50f, new ConfigDescription("Single quality slider for underwater AI behavior. 0 = minimum CPU/minimum smoothness, 100 = maximum CPU/maximum smoothness. Internally adjusts route check cache time, steer cache time, cache cell size, and avoidance sample count.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); InitializePlayerDiveConfig(); InitializeMonsterDiveYaml(); ClearRuntimeCaches(); _harmony.PatchAll(Assembly.GetExecutingAssembly()); SetupWatcher(); SetupMonsterDiveYamlWatcher(); ((BaseUnityPlugin)this).Config.Save(); if (saveOnConfigSet) { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet; } } private void OnDestroy() { UnderwaterVisualState.ResetAll("plugin destroy"); SaveWithRespectToConfigSet(); _watcher?.Dispose(); DisposeMonsterDiveYamlWatcher(); } private void SetupWatcher() { _watcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName); _watcher.Changed += ReadConfigValues; _watcher.Created += ReadConfigValues; _watcher.Renamed += ReadConfigValues; _watcher.IncludeSubdirectories = true; _watcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; _watcher.EnableRaisingEvents = true; } private void ReadConfigValues(object sender, FileSystemEventArgs e) { DateTime now = DateTime.Now; if (now.Ticks - _lastConfigReloadTime.Ticks < 10000000) { return; } lock (_reloadLock) { if (!File.Exists(ConfigFileFullPath)) { ServerSyncModTemplateLogger.LogWarning((object)"Config file does not exist. Skipping reload."); return; } try { SaveWithRespectToConfigSet(reload: true); UnderwaterVisualState.ResetAll("config reload"); ClearRuntimeCaches(); ServerSyncModTemplateLogger.LogInfo((object)"Configuration reload complete."); } catch (Exception ex) { ServerSyncModTemplateLogger.LogError((object)("Error reloading configuration: " + ex.Message)); } } _lastConfigReloadTime = now; } private void SaveWithRespectToConfigSet(bool reload = false) { bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; if (reload) { ((BaseUnityPlugin)this).Config.Reload(); } ((BaseUnityPlugin)this).Config.Save(); if (saveOnConfigSet) { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet; } } private static bool TryGetConfiguredDiveProfile(MonsterAI monsterAI, out ConfiguredDiveProfile configuredDiveProfile) { if ((Object)(object)monsterAI == (Object)null) { configuredDiveProfile = default(ConfiguredDiveProfile); return false; } string prefabName = Utils.GetPrefabName(((Component)monsterAI).gameObject); return _configuredDiveProfilesByPrefabName.TryGetValue(prefabName, out configuredDiveProfile); } private static bool IsConfiguredMonster(MonsterAI monsterAI) { ConfiguredDiveProfile configuredDiveProfile; return TryGetConfiguredDiveProfile(monsterAI, out configuredDiveProfile); } private static bool TryGetConfiguredMonster(BaseAI ai, out MonsterAI monsterAI) { MonsterAI val = (MonsterAI)(object)((ai is MonsterAI) ? ai : null); if (val != null && IsConfiguredMonster(val)) { monsterAI = val; return true; } monsterAI = null; return false; } private static bool ShouldUseWaterDiveMode(MonsterAI monsterAI) { Character character = ((BaseAI)monsterAI).m_character; if ((Object)(object)character == (Object)null) { return false; } return character.InWater() && character.InLiquidDepth() > 0.05f; } private static bool IsPassiveDiveState(MonsterAI monsterAI) { return !((BaseAI)monsterAI).IsAlerted() && (Object)(object)monsterAI.m_targetCreature == (Object)null && (Object)(object)monsterAI.m_targetStatic == (Object)null; } private static void EnsureDiveFlags(MonsterAI monsterAI) { TrackOriginalDiveFlags(monsterAI); if (((BaseAI)monsterAI).m_avoidWater) { ((BaseAI)monsterAI).m_avoidWater = false; } Character character = ((BaseAI)monsterAI).m_character; if ((Object)(object)character != (Object)null && !character.m_canSwim) { character.m_canSwim = true; } } private static void TrackOriginalDiveFlags(MonsterAI monsterAI) { if (!Object.op_Implicit((Object)(object)monsterAI)) { return; } 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)(object)character != (Object)null && character.m_canSwim); if (OriginalDiveFlagsByInstance.Count > 2048) { PruneTrackedOriginalDiveFlags(); } } } private static int RestoreRemovedMonsterDiveFlags() { if (OriginalDiveFlagsByInstance.Count == 0) { return 0; } List<int> list = new List<int>(); int num = 0; foreach (KeyValuePair<int, OriginalDiveFlags> item in OriginalDiveFlagsByInstance) { int key = item.Key; OriginalDiveFlags value = item.Value; MonsterAI monsterAI = value.MonsterAI; if (!Object.op_Implicit((Object)(object)monsterAI)) { list.Add(key); } else if (!IsConfiguredMonster(monsterAI)) { ((BaseAI)monsterAI).m_avoidWater = value.AvoidWater; Character character = ((BaseAI)monsterAI).m_character; if ((Object)(object)character != (Object)null) { character.m_canSwim = value.CanSwim; } list.Add(key); num++; } } foreach (int item2 in list) { OriginalDiveFlagsByInstance.Remove(item2); } return num; } private static void PruneTrackedOriginalDiveFlags() { if (OriginalDiveFlagsByInstance.Count == 0) { return; } List<int> list = new List<int>(); foreach (KeyValuePair<int, OriginalDiveFlags> item in OriginalDiveFlagsByInstance) { int key = item.Key; if (!Object.op_Implicit((Object)(object)item.Value.MonsterAI)) { list.Add(key); } } foreach (int item2 in list) { OriginalDiveFlagsByInstance.Remove(item2); } } 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 cacheCellSize = GetCacheCellSize(); return new Vector3Int(Mathf.RoundToInt(value.x / cacheCellSize), Mathf.RoundToInt(value.y / cacheCellSize), Mathf.RoundToInt(value.z / cacheCellSize)); } private static void ClearRuntimeCaches() { RouteCache.Clear(); SteerCache.Clear(); } private static void TrimCachesIfNeeded() { if (RouteCache.Count > 2048) { RouteCache.Clear(); } if (SteerCache.Count > 2048) { SteerCache.Clear(); } } private static float GetPassiveDesiredDepth(MonsterAI monsterAI) { if (!TryGetConfiguredDiveProfile(monsterAI, out var configuredDiveProfile)) { return 0f; } PassiveDepthProfile passiveDepthProfile = configuredDiveProfile.PassiveDepthProfile; 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, passiveDepthProfile.CenterDepth - passiveDepthProfile.MinDepth); float num5 = Mathf.Max(0f, passiveDepthProfile.MaxDepth - passiveDepthProfile.CenterDepth); return (num3 >= 0f) ? (passiveDepthProfile.CenterDepth + num3 * num5) : (passiveDepthProfile.CenterDepth + num3 * num4); } private static void TryLogOverlapFields(MonsterAI monsterAI, string stage) { } private static float GetQuality01() { return Mathf.Clamp01(_diveAiQuality.Value / 100f); } private static float GetRouteCacheSeconds() { return Mathf.Lerp(1f, 0f, GetQuality01()); } private static float GetSteerCacheSeconds() { return Mathf.Lerp(1f, 0f, GetQuality01()); } private static float GetCacheCellSize() { return Mathf.Lerp(3f, 0.1f, GetQuality01()); } private static int GetAvoidanceSampleCount() { return Mathf.Clamp(Mathf.RoundToInt(Mathf.Lerp(3f, 8f, GetQuality01())), 3, 8); } private static SwimDepthGoal UpdateSwimDepthTowardsTarget(MonsterAI monsterAI, Character character, Vector3 point, float dt) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) float swimDepthMin = _monsterDiveGlobalSettings.SwimDepthMin; float swimDepthMax = _monsterDiveGlobalSettings.SwimDepthMax; float liquidLevel = character.GetLiquidLevel(); float num = liquidLevel - point.y; bool flag = IsPassiveDiveState(monsterAI); float num2 = (flag ? GetPassiveDesiredDepth(monsterAI) : num); bool requestedOutsideRange = flag || num < swimDepthMin || num > swimDepthMax; num2 = Mathf.Clamp(num2, swimDepthMin, swimDepthMax); float clampedTargetY = liquidLevel - num2; float swimDepthAdjustSpeed = _monsterDiveGlobalSettings.SwimDepthAdjustSpeed; if (swimDepthAdjustSpeed <= 0f) { character.m_swimDepth = num2; return new SwimDepthGoal(clampedTargetY, requestedOutsideRange); } float num3 = swimDepthAdjustSpeed * Mathf.Max(dt, 0.01f); character.m_swimDepth = Mathf.Clamp(Mathf.MoveTowards(character.m_swimDepth, num2, num3), swimDepthMin, swimDepthMax); return new SwimDepthGoal(clampedTargetY, requestedOutsideRange); } private static Vector3 BuildSteerDirectionWithAvoidance(BaseAI ai, Character character, Vector3 targetPoint) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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_00c6: 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_00e6: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_0131: 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_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0203: 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) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) float steerCacheSeconds = GetSteerCacheSeconds(); int instanceID = ((Object)ai).GetInstanceID(); Vector3Int val = ToCacheBucket(((Component)ai).transform.position); Vector3Int val2 = ToCacheBucket(targetPoint); float time = Time.time; if (steerCacheSeconds > 0f && SteerCache.TryGetValue(instanceID, out var value) && time - value.Time <= steerCacheSeconds && 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 centerPoint = character.GetCenterPoint(); int num2 = Mathf.Clamp(GetAvoidanceSampleCount(), 3, SteerAngles.Length); Vector3 val5 = val4; float num3 = float.NegativeInfinity; for (int i = 0; i < num2; i++) { float num4 = SteerAngles[i]; Vector3 val6 = Quaternion.Euler(0f, num4, 0f) * val4; float num5; if (ai.CanMove(val6, radius, num)) { num5 = 1000f - Mathf.Abs(num4); } else { float num6 = ai.Raycast(centerPoint, val6, num * 2f, 0.1f); num5 = num6 - Mathf.Abs(num4) * 0.01f; } if (num5 > num3) { num3 = num5; val5 = val6; } } Vector3 val7 = default(Vector3); ((Vector3)(ref val7))..ctor(val5.x, val3.y, val5.z); Vector3 val8 = ((((Vector3)(ref val7)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref val7)).normalized : val3); if (steerCacheSeconds > 0f) { TrimCachesIfNeeded(); SteerCache[instanceID] = new SteerCacheEntry(time, val, val2, val8); } return val8; } if (steerCacheSeconds > 0f) { TrimCachesIfNeeded(); SteerCache[instanceID] = new SteerCacheEntry(time, val, val2, val3); } return val3; } private static bool HasReasonableUnderwaterRoute(BaseAI ai, Character character, Vector3 targetPoint) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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_0053: 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_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: 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_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_0171: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: 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_014d: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) float routeCacheSeconds = GetRouteCacheSeconds(); int instanceID = ((Object)ai).GetInstanceID(); Vector3Int val = ToCacheBucket(((Component)ai).transform.position); Vector3Int val2 = ToCacheBucket(targetPoint); float time = Time.time; if (routeCacheSeconds > 0f && RouteCache.TryGetValue(instanceID, out var value) && time - value.Time <= routeCacheSeconds && value.PositionBucket == val && value.TargetBucket == val2) { return value.Result; } float radius = character.GetRadius(); float num = Utils.DistanceXZ(targetPoint, ((Component)ai).transform.position); if (num <= radius + 0.6f) { if (routeCacheSeconds > 0f) { TrimCachesIfNeeded(); 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) { if (routeCacheSeconds > 0f) { TrimCachesIfNeeded(); RouteCache[instanceID] = new RouteCacheEntry(time, val, val2, result: true); } return true; } ((Vector3)(ref val4)).Normalize(); Vector3 centerPoint = character.GetCenterPoint(); float num2 = Mathf.Clamp(num, radius + 1f, 6f); int num3 = Mathf.Clamp(GetAvoidanceSampleCount(), 3, RouteAngles.Length); for (int i = 0; i < num3; i++) { float num4 = RouteAngles[i]; Vector3 val5 = Quaternion.Euler(0f, num4, 0f) * val4; float num5 = ai.Raycast(centerPoint, val5, num2, 0.1f); if (num5 >= num2 * 0.9f) { if (routeCacheSeconds > 0f) { TrimCachesIfNeeded(); RouteCache[instanceID] = new RouteCacheEntry(time, val, val2, result: true); } return true; } } if (routeCacheSeconds > 0f) { TrimCachesIfNeeded(); RouteCache[instanceID] = new RouteCacheEntry(time, val, val2, result: false); } return false; } private ConfigEntry<T> config<T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags); ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val); SyncedConfigEntry<T> syncedConfigEntry = ConfigSync.AddConfigEntry<T>(val2); syncedConfigEntry.SynchronizedConfig = synchronizedSetting; return val2; } private ConfigEntry<T> config<T>(string group, string name, T value, string description, bool synchronizedSetting = true) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting); } static ServerSyncModTemplatePlugin() { string configPath = Paths.ConfigPath; char directorySeparatorChar = Path.DirectorySeparatorChar; MonsterDiveYamlFileFullPath = configPath + directorySeparatorChar + MonsterDiveYamlFileName; MonsterDiveYamlLock = new object(); MonsterDiveYamlDeserializer = new DeserializerBuilder().WithNamingConvention(UnderscoredNamingConvention.Instance).WithDuplicateKeyChecking().Build(); DefaultMonsterDiveGlobalSettings = new MonsterDiveGlobalSettings(0.25f, 30f, 2f); _monsterDiveYamlSync = null; _monsterDiveGlobalSettings = DefaultMonsterDiveGlobalSettings; _waterEquipmentBlacklist = null; _waterStaminaRegenRateMultiplier = null; _waterDepthStaminaDrainStart = null; _waterDepthStaminaDrainFull = null; _waterDepthStaminaDrainMaxMultiplier = null; _playerSwimRunSpeedMultiplier = null; WaterEquipmentBlacklistLock = new object(); _lastWaterEquipmentBlacklistRaw = string.Empty; _waterEquipmentBlacklistSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); ConfigFileName = "sighsorry.DiveIn.cfg"; string configPath2 = Paths.ConfigPath; directorySeparatorChar = Path.DirectorySeparatorChar; ConfigFileFullPath = configPath2 + directorySeparatorChar + ConfigFileName; ConnectionError = ""; ServerSyncModTemplateLogger = Logger.CreateLogSource("DiveIn"); ConfigSync = new ConfigSync("sighsorry.DiveIn") { DisplayName = "DiveIn", CurrentVersion = "1.0.1", MinimumRequiredVersion = "1.0.1" }; _diveAiQuality = null; PrefabSetLock = new object(); _configuredDiveProfilesByPrefabName = new Dictionary<string, ConfiguredDiveProfile>(StringComparer.OrdinalIgnoreCase); SteerAngles = new float[8] { 0f, -35f, 35f, -70f, 70f, -120f, 120f, 180f }; RouteAngles = new float[5] { 0f, -35f, 35f, -70f, 70f }; RouteCache = new Dictionary<int, RouteCacheEntry>(); SteerCache = new Dictionary<int, SteerCacheEntry>(); OriginalDiveFlagsByInstance = new Dictionary<int, OriginalDiveFlags>(); _serverConfigLocked = null; } } internal static class PlayerDiveUtils { internal static PlayerDiveController? EnsureLocalDiver() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return null; } PlayerDiveController playerDiveController = PlayerDiveController.LocalInstance; if ((Object)(object)playerDiveController != (Object)null && (Object)(object)playerDiveController.Player == (Object)(object)localPlayer) { return playerDiveController; } if (!((Component)localPlayer).TryGetComponent<PlayerDiveController>(ref playerDiveController)) { playerDiveController = ((Component)localPlayer).gameObject.AddComponent<PlayerDiveController>(); } return playerDiveController; } internal static bool TryGetLocalDiver(Player player, out PlayerDiveController diver) { if (!IsValidLocalPlayer(player)) { diver = null; return false; } PlayerDiveController playerDiveController = EnsureLocalDiver(); if ((Object)(object)playerDiveController == (Object)null) { diver = null; return false; } diver = playerDiveController; return true; } internal static bool IsValidLocalPlayer(Player player) { return (Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)Player.m_localPlayer; } } internal sealed class PlayerDiveController : MonoBehaviour { private const float HeadUnderwaterTolerance = 0.01f; internal const float DefaultSwimDepth = 1.4f; private const float DivingSwimDepth = 2.5f; private bool _underwaterMovementActive; private float _baseSwimSpeed; private int _swimmingUpdateContextDepth; private int _swimmingUpdateContextFrame = -1; internal static PlayerDiveController? LocalInstance { get; private set; } internal Player Player { get; private set; } = null; private void Awake() { Player = ((Component)this).GetComponent<Player>(); if ((Object)(object)Player == (Object)null) { 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 DisableUnderwaterMovement() { _underwaterMovementActive = false; ResetSwimDepthToDefault(); ((Character)Player).m_swimSpeed = _baseSwimSpeed; } internal void ResetSwimDepthIfNotInWater() { if (!((Character)Player).InWater()) { DisableUnderwaterMovement(); } } internal void ResetSwimDepthToDefault() { ((Character)Player).m_swimDepth = 1.4f; } internal bool CanDive() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) if (ShouldForceDive()) { return true; } if (!((Character)Player).InWater() || ((Character)Player).IsOnGround() || !((Character)Player).IsSwimming()) { return false; } float num = default(float); Vector3 val = default(Vector3); if (((Character)Player).GetGroundHeight(((Component)Player).transform.position, ref num, ref val) && ((Component)Player).transform.position.y - num < 1f) { return false; } return true; } internal bool IsHeadUnderwater() { //IL_0036: 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) float num = (((Object)(object)((Character)Player).m_eye != (Object)null) ? ((Character)Player).m_eye.position.y : ((Component)Player).transform.position.y); return ((Character)Player).GetLiquidLevel() - num > 0.01f; } internal void RefreshUnderwaterMovementState() { if (!((Character)Player).InWater() || !IsHeadUnderwater()) { _underwaterMovementActive = false; } else if (IsUnderSurface()) { _underwaterMovementActive = true; } } internal bool ShouldForceSwimming() { return _underwaterMovementActive && ((Character)Player).InWater() && IsHeadUnderwater(); } internal bool ShouldForceDive() { return ShouldForceSwimming() && !((Character)Player).IsOnGround(); } internal bool IsUnderSurface() { return ((Character)Player).m_swimDepth > 1.4f; } internal bool IsDiving() { return ((Character)Player).m_swimDepth > 2.5f; } internal bool IsSurfacing() { return !IsDiving() && IsUnderSurface(); } internal bool IsIdleInWater() { //IL_0029: 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) int result; if (((Character)Player).InWater() && (((Character)Player).IsSwimming() || ShouldForceSwimming())) { Vector3 velocity = ((Character)Player).GetVelocity(); result = ((((Vector3)(ref velocity)).magnitude < 1f) ? 1 : 0); } else { result = 0; } return (byte)result != 0; } internal void BeginSwimmingUpdateContext() { _swimmingUpdateContextDepth++; _swimmingUpdateContextFrame = Time.frameCount; } internal void EndSwimmingUpdateContext() { if (_swimmingUpdateContextDepth > 0) { _swimmingUpdateContextDepth--; } if (_swimmingUpdateContextDepth == 0) { _swimmingUpdateContextFrame = -1; } } internal bool IsInSwimmingUpdateContext() { return _swimmingUpdateContextDepth > 0 && _swimmingUpdateContextFrame == Time.frameCount; } internal void RegenWaterStamina(float dt) { float value = ServerSyncModTemplatePlugin._waterStaminaRegenRateMultiplier.Value; if (!(value <= 0f)) { float maxStamina = ((Character)Player).GetMaxStamina(); float num = 1f; if (((Character)Player).IsBlocking()) { num *= 0.8f; } if (((Character)Player).InAttack() || ((Character)Player).InDodge() || ((Character)Player).m_wallRunning || ((Character)Player).IsEncumbered()) { num = 0f; } float num2 = (Player.m_staminaRegen + (1f - Player.m_stamina / maxStamina) * Player.m_staminaRegen * Player.m_staminaRegenTimeMultiplier) * num; float num3 = 1f; ((Character)Player).m_seman.ModifyStaminaRegen(ref num3); num2 *= num3; num2 *= value; if (Player.m_stamina < maxStamina && Player.m_staminaRegenTimer <= 0f) { Player.m_stamina = Mathf.Min(maxStamina, Player.m_stamina + num2 * dt * Game.m_staminaRegenRate); } } } internal void ApplyDepthScaledSwimDrain(float dt) { float depthScaledSwimDrainMultiplier = GetDepthScaledSwimDrainMultiplier(); if (!(depthScaledSwimDrainMultiplier <= 1f)) { float skillFactor = Player.m_skills.GetSkillFactor((SkillType)103); float num = Mathf.Lerp(Player.m_swimStaminaDrainMinSkill, Player.m_swimStaminaDrainMaxSkill, skillFactor); num += num * ((Character)Player).GetEquipmentSwimStaminaModifier(); ((Character)Player).m_seman.ModifySwimStaminaUsage(num, ref num, true); float num2 = depthScaledSwimDrainMultiplier - 1f; if (!(num2 <= 0f)) { ((Character)Player).UseStamina(dt * num * Game.m_moveStaminaRate * num2); } } } internal void UpdateSwimSpeed() { float num = 1f; if (ZInput.GetButton("Run") || ZInput.GetButton("JoyRun")) { num = Mathf.Max(1f, ServerSyncModTemplatePlugin._playerSwimRunSpeedMultiplier.Value); } ((Character)Player).m_swimSpeed = _baseSwimSpeed * num; } internal void Dive(float dt, bool ascend, out Vector3? defaultMoveDir) { //IL_0008: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) defaultMoveDir = ((Character)Player).m_moveDir; ((Character)Player).m_moveDir = GetDiveDirection(ascend); Vector3 val = CalculateSwimVelocity(); float num = ((Character)Player).m_swimDepth - val.y * dt; ((Character)Player).m_swimDepth = Mathf.Max(num, 1.4f); } private Vector3 GetDiveDirection(bool ascend) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0004: 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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_0051: Unknown result type (might be due to invalid IL or missing references) Vector3 val = (ascend ? Vector3.up : Vector3.down); Vector3 val2 = ((Character)Player).m_moveDir; if (((Vector3)(ref val2)).magnitude < 0.1f) { float scale = ((ascend && IsSurfacing()) ? 0.6f : 0.05f); val2 = GetHorizontalLookDirection(scale); } Vector3 val3 = val2 + val; return ((Vector3)(ref val3)).normalized; } private Vector3 GetHorizontalLookDirection(float scale) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_0028: 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) Vector3 lookDir = ((Character)Player).m_lookDir; lookDir.y = 0f; ((Vector3)(ref lookDir)).Normalize(); return lookDir * scale; } private Vector3 CalculateSwimVelocity() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) float num = ((Character)Player).m_swimSpeed * ((Character)Player).GetAttackSpeedFactorMovement(); if (((Character)Player).InMinorActionSlowdown()) { num = 0f; } ((Character)Player).m_seman.ApplyStatusEffectSpeedMods(ref num, ((Character)Player).m_moveDir); Vector3 val = ((Character)Player).m_moveDir * num; val = Vector3.Lerp(((Character)Player).m_currentVel, val, ((Character)Player).m_swimAcceleration); ((Character)Player).AddPushbackForce(ref val); return val; } private float GetDepthScaledSwimDrainMultiplier() { float num = Mathf.Max(1f, ServerSyncModTemplatePlugin._waterDepthStaminaDrainMaxMultiplier.Value); if (num <= 1f) { return 1f; } float num2 = Mathf.Max(0.25f, ServerSyncModTemplatePlugin._waterDepthStaminaDrainFull.Value); float num3 = Mathf.Clamp(ServerSyncModTemplatePlugin._waterDepthStaminaDrainStart.Value, 0f, num2); if (((Character)Player).m_swimDepth <= num3) { return 1f; } float num4 = Mathf.InverseLerp(num3, num2, ((Character)Player).m_swimDepth); return Mathf.SmoothStep(1f, num, num4); } } [HarmonyPatch] internal static class PlayerDivePatches { private readonly struct SwimmingUpdateState { internal PlayerDiveController? Diver { get; } internal Vector3? OriginalMoveDir { get; } internal SwimmingUpdateState(PlayerDiveController? diver, Vector3? originalMoveDir) { Diver = diver; OriginalMoveDir = originalMoveDir; } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "Awake")] private static void PlayerAwakePostfix(Player __instance) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { PlayerDiveUtils.EnsureLocalDiver(); } } [HarmonyPrefix] [HarmonyPatch(typeof(Character), "UpdateMotion")] private static void CharacterUpdateMotionPrefix(Character __instance) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } PlayerDiveController playerDiveController = PlayerDiveUtils.EnsureLocalDiver(); if ((Object)(object)playerDiveController == (Object)null) { return; } if (!ServerSyncModTemplatePlugin.IsPlayerDiveEnvAllowed()) { playerDiveController.DisableUnderwaterMovement(); return; } playerDiveController.ResetSwimDepthIfNotInWater(); playerDiveController.RefreshUnderwaterMovementState(); if (playerDiveController.ShouldForceSwimming()) { ((Character)playerDiveController.Player).m_lastGroundTouch = 0.3f; ((Character)playerDiveController.Player).m_swimTimer = 0f; } } [HarmonyPrefix] [HarmonyPatch(typeof(Character), "UpdateSwimming")] private static void CharacterUpdateSwimmingPrefix(Character __instance, float dt, out SwimmingUpdateState __state) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { __state = new SwimmingUpdateState(null, null); return; } PlayerDiveController playerDiveController = PlayerDiveUtils.EnsureLocalDiver(); if ((Object)(object)playerDiveController == (Object)null) { __state = new SwimmingUpdateState(null, null); return; } playerDiveController.BeginSwimmingUpdateContext(); __state = new SwimmingUpdateState(playerDiveController, null); if (!ServerSyncModTemplatePlugin.IsPlayerDiveEnvAllowed()) { playerDiveController.DisableUnderwaterMovement(); return; } playerDiveController.UpdateSwimSpeed(); if ((ZInput.GetButton("Jump") || ZInput.GetButton("JoyJump")) && playerDiveController.IsUnderSurface()) { playerDiveController.Dive(dt, ascend: true, out var defaultMoveDir); __state = new SwimmingUpdateState(playerDiveController, defaultMoveDir); } else if ((ZInput.GetButton("Crouch") || ZInput.GetButton("JoyCrouch")) && playerDiveController.CanDive()) { playerDiveController.Dive(dt, ascend: false, out var defaultMoveDir2); __state = new SwimmingUpdateState(playerDiveController, defaultMoveDir2); } else if ((__instance.IsOnGround() || !playerDiveController.IsDiving()) && !playerDiveController.IsIdleInWater()) { playerDiveController.ResetSwimDepthToDefault(); } } [HarmonyPostfix] [HarmonyPatch(typeof(Character), "UpdateSwimming")] private static void CharacterUpdateSwimmingPostfix(Character __instance, ref SwimmingUpdateState __state) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) __state.Diver?.EndSwimmingUpdateContext(); if (__state.OriginalMoveDir.HasValue) { __instance.m_moveDir = __state.OriginalMoveDir.Value; __state = default(SwimmingUpdateState); } } [HarmonyPrefix] [HarmonyPatch(typeof(Character), "UpdateRotation")] private static void CharacterUpdateRotationPrefix(Character __instance, out Quaternion? __state) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { __state = null; return; } PlayerDiveController playerDiveController = PlayerDiveUtils.EnsureLocalDiver(); if ((Object)(object)playerDiveController != (Object)null && playerDiveController.IsInSwimmingUpdateContext()) { __state = ((Component)__instance).transform.rotation; } else { __state = null; } } [HarmonyPostfix] [HarmonyPatch(typeof(Character), "UpdateRotation")] private static void CharacterUpdateRotationPostfix(Character __instance, float turnSpeed, float dt, ref Quaternion? __state) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) if (__state.HasValue && !((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !(((Component)__instance).transform.rotation != __state.Value)) { PlayerDiveController playerDiveController = PlayerDiveUtils.EnsureLocalDiver(); if (ServerSyncModTemplatePlugin.IsPlayerDiveEnvAllowed() && !((Object)(object)playerDiveController == (Object)null) && playerDiveController.IsInSwimmingUpdateContext() && playerDiveController.IsUnderSurface()) { Player player = playerDiveController.Player; Quaternion val = ((((Character)player).AlwaysRotateCamera() || ((Character)player).m_moveDir == Vector3.zero) ? ((Character)player).m_lookYaw : Quaternion.LookRotation(((Character)player).m_moveDir)); float num = turnSpeed * ((Character)player).GetAttackSpeedFactorRotation(); ((Component)player).transform.rotation = Quaternion.RotateTowards(((Component)player).transform.rotation, val, num * dt); } } } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "OnSwimming")] private static void PlayerOnSwimmingPrefix(Player __instance, Vector3 targetVel, float dt) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && ServerSyncModTemplatePlugin.IsPlayerDiveEnvAllowed()) { PlayerDiveController playerDiveController = PlayerDiveUtils.EnsureLocalDiver(); if (!((Object)(object)playerDiveController == (Object)null)) { playerDiveController.RegenWaterStamina(dt); } } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "OnSwimming")] private static void PlayerOnSwimmingPostfix(Player __instance, Vector3 targetVel, float dt) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !(((Vector3)(ref targetVel)).magnitude < 0.1f) && ServerSyncModTemplatePlugin.IsPlayerDiveEnvAllowed()) { PlayerDiveController playerDiveController = PlayerDiveUtils.EnsureLocalDiver(); if (!((Object)(object)playerDiveController == (Object)null)) { playerDiveController.ApplyDepthScaledSwimDrain(dt); } } } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "SetControls")] private static void PlayerSetControlsPrefix(Player __instance, ref bool crouch) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && ServerSyncModTemplatePlugin.IsPlayerDiveEnvAllowed() && ((Character)__instance).IsSwimming()) { crouch = false; } } } public static class KeyboardExtensions { [SpecialName] public sealed class <G>$8D1D3E80A18AA9715780B6CB7003B2F1 { [SpecialName] public static class <M>$895AB635D4D087636CF1C26BA650BA11 { } [ExtensionMarker("<M>$895AB635D4D087636CF1C26BA650BA11")] public bool IsKeyDown() { throw new NotSupportedException(); } [ExtensionMarker("<M>$895AB635D4D087636CF1C26BA650BA11")] public bool IsKeyHeld() { throw new NotSupportedException(); } } public static bool IsKeyDown(this KeyboardShortcut shortcut) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) return (int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey) && ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey); } public static bool IsKeyHeld(this KeyboardShortcut shortcut) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) return (int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey) && ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey); } } public static class ToggleExtentions { [SpecialName] public sealed class <G>$57ABA57BD1CE54EF9BE00DAABFE926BC { [SpecialName] public static class <M>$C02B13F2B6FFC3465B74B38D50860BED { } [ExtensionMarker("<M>$C02B13F2B6FFC3465B74B38D50860BED")] public bool IsOn() { throw new NotSupportedException(); } [ExtensionMarker("<M>$C02B13F2B6FFC3465B74B38D50860BED")] public bool IsOff() { throw new NotSupportedException(); } } public static bool IsOn(this ServerSyncModTemplatePlugin.Toggle value) { return value == ServerSyncModTemplatePlugin.Toggle.On; } public static bool IsOff(this ServerSyncModTemplatePlugin.Toggle value) { return value == ServerSyncModTemplatePlugin.Toggle.Off; } } internal static class UnderwaterVisualState { private sealed class WaterSurfaceState { public WaterVolume Volume { get; } public Transform SurfaceTransform { get; } public MeshRenderer? Renderer { get; } public Material? Material { get; } public Vector3 OriginalPosition { get; } public Quaternion OriginalRotation { get; } public ShadowCastingMode OriginalShadowCastingMode { get; } public float[] OriginalDepth { get; } public bool HasOriginalDepth { get; } public float OriginalUseGlobalWind { get; } public bool HasOriginalUseGlobalWind { get; } public bool OverrideApplied { get; set; } public WaterSurfaceState(WaterVolume volume) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) Volume = volume; Transform val = (SurfaceTransform = ((Component)volume.m_waterSurface).transform); Renderer = ((Component)volume.m_waterSurface).GetComponent<MeshRenderer>(); OriginalPosition = val.position; OriginalRotation = val.rotation; OriginalShadowCastingMode = ((Renderer)volume.m_waterSurface).shadowCastingMode; Material = ((Renderer)volume.m_waterSurface).material; OriginalDepth = ReadMaterialDepth(Material); HasOriginalDepth = (Object)(object)Material != (Object)null && Material.HasProperty(DepthPropertyId); OriginalUseGlobalWind = ReadMaterialFloat(Material, UseGlobalWindPropertyId); HasOriginalUseGlobalWind = (Object)(object)Material != (Object)null && Material.HasProperty(UseGlobalWindPropertyId); } } private static readonly int DepthPropertyId = Shader.PropertyToID("_depth"); private static readonly int UseGlobalWindPropertyId = Shader.PropertyToID("_UseGlobalWind"); private static readonly Dictionary<int, WaterSurfaceState> WaterSurfaceStates = new Dictionary<int, WaterSurfaceState>(); private static float? _originalMinWaterDistance; private static GameCamera? _cameraWithOverride; private static bool _cameraOverrideActive; private static bool _fogStateCaptured; private static bool _fogOverrideActive; private static Color _originalFogColor; private static float _originalFogDensity; internal static void ApplyCameraOverride(GameCamera gameCamera) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) float underwaterCameraMinWaterDistance = ServerSyncModTemplatePlugin.GetUnderwaterCameraMinWaterDistance(); if (!_originalMinWaterDistance.HasValue) { _originalMinWaterDistance = gameCamera.m_minWaterDistance; _cameraWithOverride = gameCamera; } if (!_cameraOverrideActive) { LogVisualState("ApplyCamera", $"camera={DescribeGameObject(((Component)gameCamera).gameObject)}, originalMinWaterDistance={_originalMinWaterDistance:F2}, newMinWaterDistance={underwaterCameraMinWaterDistance:F2}, cameraPos={FormatVector3(((Component)gameCamera).transform.position)}"); _cameraOverrideActive = true; } gameCamera.m_minWaterDistance = underwaterCameraMinWaterDistance; } internal static void ApplyFogOverride(PlayerDiveController diver) { //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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) if (!_fogStateCaptured) { _originalFogColor = RenderSettings.fogColor; _originalFogDensity = RenderSettings.fogDensity; _fogStateCaptured = true; } if ((Object)(object)EnvMan.instance == (Object)null) { return; } EnvSetup currentEnvironment = EnvMan.instance.GetCurrentEnvironment(); if (currentEnvironment != null) { Color color = ((!EnvMan.IsNight()) ? currentEnvironment.m_fogColorDay : currentEnvironment.m_fogColorNight); color.a = 1f; color = ChangeColorBrightness(color, ((Character)diver.Player).m_swimDepth * -0.02f); RenderSettings.fogColor = color; float num = _originalFogDensity + ((Character)diver.Player).m_swimDepth * 0f; RenderSettings.fogDensity = Mathf.Clamp(num, 0.05f, 1f); if (!_fogOverrideActive) { LogVisualState("ApplyFog", $"player={DescribeGameObject(((Component)diver.Player).gameObject)}, swimDepth={((Character)diver.Player).m_swimDepth:F2}, originalFogColor={FormatColor(_originalFogColor)}, newFogColor={FormatColor(RenderSettings.fogColor)}, originalFogDensity={_originalFogDensity:F4}, newFogDensity={RenderSettings.fogDensity:F4}, env={DescribeEnvironment()}"); _fogOverrideActive = true; } } } internal static void ApplyWaterSurfaceOverride(WaterVolume volume, float waterLevel) { //IL_006c: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)volume.m_waterSurface == (Object)null) { return; } int instanceID = ((Object)volume).GetInstanceID(); if (!WaterSurfaceStates.TryGetValue(instanceID, out WaterSurfaceState value)) { value = new WaterSurfaceState(volume); WaterSurfaceStates[instanceID] = value; } if (!((Object)(object)value.Renderer == (Object)null)) { ((Component)volume.m_waterSurface).transform.SetPositionAndRotation(new Vector3(value.OriginalPosition.x, waterLevel, value.OriginalPosition.z), value.OriginalRotation * Quaternion.Euler(180f, 0f, 0f)); ((Renderer)volume.m_waterSurface).shadowCastingMode = (ShadowCastingMode)2; ApplyWaterMaterialOverride(value); if (!value.OverrideApplied) { object[] obj = new object[13] { DescribeGameObject(((Component)volume).gameObject), DescribeGameObject(((Component)volume.m_waterSurface).gameObject), waterLevel, FormatVector3(value.OriginalPosition), FormatVector3(((Component)volume.m_waterSurface).transform.position), null, null, null, null, null, null, null, null }; Quaternion val = value.OriginalRotation; obj[5] = FormatEuler(((Quaternion)(ref val)).eulerAngles); val = ((Component)volume.m_waterSurface).transform.rotation; obj[6] = FormatEuler(((Quaternion)(ref val)).eulerAngles); obj[7] = value.OriginalShadowCastingMode; obj[8] = ((Renderer)volume.m_waterSurface).shadowCastingMode; obj[9] = FormatFloatArray(value.OriginalDepth); obj[10] = FormatFloatArray(ReadMaterialDepth(value.Material)); obj[11] = FormatMaterialFloat(value.HasOriginalUseGlobalWind ? new float?(value.OriginalUseGlobalWind) : null); obj[12] = FormatMaterialFloat(ReadMaterialFloatOrNull(value.Material, UseGlobalWindPropertyId)); LogVisualState("ApplyWaterSurface", string.Format("volume={0}, waterSurface={1}, waterLevel={2:F2}, originalPos={3}, appliedPos={4}, originalEuler={5}, appliedEuler={6}, originalShadow={7}, appliedShadow={8}, originalDepth={9}, appliedDepth={10}, originalUseGlobalWind={11}, appliedUseGlobalWind={12}", obj)); value.OverrideApplied = true; } } } internal static void ResetWaterSurface(WaterVolume? volume, string reason = "") { if (!((Object)(object)volume == (Object)null) && WaterSurfaceStates.TryGetValue(((Object)volume).GetInstanceID(), out WaterSurfaceState value)) { RestoreWaterSurfaceState(value, reason); WaterSurfaceStates.Remove(((Object)volume).GetInstanceID()); } } internal static void ResetAll(string reason = "") { ResetCameraAndFog(reason); ResetTrackedWaterSurfacesExcept(null, reason); } internal static void ResetCameraAndFog(string reason = "") { ResetCamera(reason); ResetFog(reason); } internal static void ResetCamera(string reason = "") { GameCamera val = (GameCamera)(((Object)(object)_cameraWithOverride != (Object)null) ? ((object)_cameraWithOverride) : ((object)GameCamera.instance)); float num = (((Object)(object)val != (Object)null) ? val.m_minWaterDistance : float.NaN); if ((Object)(object)val != (Object)null && _originalMinWaterDistance.HasValue) { val.m_minWaterDistance = _originalMinWaterDistance.Value; } if (_cameraOverrideActive) { LogVisualState("ResetCamera", $"reason={reason}, camera={DescribeGameObject(((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null)}, currentMinWaterDistance={num:F2}, restoredMinWaterDistance={_originalMinWaterDistance.GetValueOrDefault(float.NaN):F2}"); } _originalMinWaterDistance = null; _cameraWithOverride = null; _cameraOverrideActive = false; } internal static void ResetFog(string reason = "") { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) bool fogStateCaptured = _fogStateCaptured; if (_fogStateCaptured) { if (_fogOverrideActive) { LogVisualState("ResetFog", $"reason={reason}, currentFogColor={FormatColor(RenderSettings.fogColor)}, restoredFogColor={FormatColor(_originalFogColor)}, currentFogDensity={RenderSettings.fogDensity:F4}, restoredFogDensity={_originalFogDensity:F4}, env={DescribeEnvironment()}"); } RenderSettings.fogColor = _originalFogColor; RenderSettings.fogDensity = _originalFogDensity; _fogStateCaptured = false; } _fogOverrideActive = false; if (fogStateCaptured) { RefreshEnvironment(); } } private static void ResetTrackedWaterSurfacesExcept(int? activeVolumeId, string reason = "") { if (WaterSurfaceStates.Count == 0) { return; } List<int> list = WaterSurfaceStates.Keys.ToList(); foreach (int item in list) { if (!activeVolumeId.HasValue || item != activeVolumeId.Value) { RestoreWaterSurfaceState(WaterSurfaceStates[item], reason); WaterSurfaceStates.Remove(item); } } } private static void RestoreWaterSurfaceState(WaterSurfaceState state, string reason) { //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009f: 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_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)state.Volume == (Object)null) && !((Object)(object)state.Volume.m_waterSurface == (Object)null) && !((Object)(object)state.SurfaceTransform == (Object)null)) { if (state.OverrideApplied) { object[] obj = new object[13] { reason, DescribeGameObject(((Component)state.Volume).gameObject), DescribeGameObject(((Component)state.Volume.m_waterSurface).gameObject), FormatVector3(state.SurfaceTransform.position), FormatVector3(state.OriginalPosition), null, null, null, null, null, null, null, null }; Quaternion val = state.SurfaceTransform.rotation; obj[5] = FormatEuler(((Quaternion)(ref val)).eulerAngles); val = state.OriginalRotation; obj[6] = FormatEuler(((Quaternion)(ref val)).eulerAngles); obj[7] = ((Renderer)state.Volume.m_waterSurface).shadowCastingMode; obj[8] = state.OriginalShadowCastingMode; obj[9] = FormatFloatArray(ReadMaterialDepth(state.Material)); obj[10] = FormatFloatArray(state.OriginalDepth); obj[11] = FormatMaterialFloat(ReadMaterialFloatOrNull(state.Material, UseGlobalWindPropertyId)); obj[12] = FormatMaterialFloat(state.HasOriginalUseGlobalWind ? new float?(state.OriginalUseGlobalWind) : null); LogVisualState("ResetWaterSurface", string.Format("reason={0}, volume={1}, waterSurface={2}, currentPos={3}, restoredPos={4}, currentEuler={5}, restoredEuler={6}, currentShadow={7}, restoredShadow={8}, currentDepth={9}, restoredDepth={10}, currentUseGlobalWind={11}, restoredUseGlobalWind={12}", obj)); } state.SurfaceTransform.SetPositionAndRotation(state.OriginalPosition, state.OriginalRotation); if ((Object)(object)state.Renderer != (Object)null) { ((Renderer)state.Volume.m_waterSurface).shadowCastingMode = state.OriginalShadowCastingMode; } RestoreWaterMaterialState(state); state.OverrideApplied = false; } } private static void ApplyWaterMaterialOverride(WaterSurfaceState state) { Material material = state.Material; if ((Object)(object)material == (Object)null) { return; } if (material.HasProperty(DepthPropertyId)) { if (state.Volume.m_forceDepth >= 0f) { material.SetFloatArray(DepthPropertyId, new float[4] { state.Volume.m_forceDepth, state.Volume.m_forceDepth, state.Volume.m_forceDepth, state.Volume.m_forceDepth }); } else { material.SetFloatArray(DepthPropertyId, state.Volume.m_normalizedDepth); } } if (material.HasProperty(UseGlobalWindPropertyId)) { material.SetFloat(UseGlobalWindPropertyId, state.Volume.m_useGlobalWind ? 1f : 0f); } } private static void RestoreWaterMaterialState(WaterSurfaceState state) { Material material = state.Material; if (!((Object)(object)material == (Object)null)) { if (state.HasOriginalDepth) { material.SetFloatArray(DepthPropertyId, state.OriginalDepth); } if (state.HasOriginalUseG