Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Tides v1.2.1
plugins/Tides.dll
Decompiled a month agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Tides.Core; using Tides.Systems; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Tides")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Tides")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("1.2.1")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.1.0")] namespace Tides { [BepInPlugin("com.naexn.Tides", "Tides", "1.2.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class Tides : BaseUnityPlugin { public const string PluginGUID = "com.naexn.Tides"; public const string PluginName = "Tides"; public const string PluginVersion = "1.2.1"; public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization(); private void Awake() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) Logger.LogInfo((object)"Tides has landed"); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new TidesInfoCommand()); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new TidesDiagCommand()); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new TidesDebugLilyCommand()); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new TidesDebugCattailCommand()); TidesConfig.CreateConfigValues(((BaseUnityPlugin)this).Config); TideSystem.ApplyConfigModifications(); TidesConfig.RegisterChangeCallbacks(); new Harmony("com.naexn.Tides").PatchAll(); } } public class TidesInfoCommand : ConsoleCommand { public override string Name => "tides"; public override string Help => "Tides Info"; public override void Run(string[] args) { Console.instance.Print($"[Tides Info] current tides offset = {TideSystem._lastTideOffset:F2}m, base ocean level={TideSystem.OceanBaseY}m, max tide amplitude={TideSystem.TideAmplitude}m"); if (Diagnostics.DebugTidesEnabled) { Logger.LogWarning((object)$"[Config Values] base ocean level={TidesConfig.BaseWaterLevel.Value}m, amp={TidesConfig.TideAmplitude.Value}m"); Logger.LogWarning((object)$"[Time] current day={EnvMan.instance.GetCurrentDay()}, m_totalSeconds={EnvMan.instance.m_totalSeconds}, m_dayLengthSec={EnvMan.instance.m_dayLengthSec}, m_smoothDayFraction={EnvMan.instance.m_smoothDayFraction}"); } } public override List<string> CommandOptionList() { return new List<string>(); } } public class TidesDiagCommand : ConsoleCommand { public override string Name => "tides_diag"; public override string Help => "Diag chosen systems tides/swampmovement/vegetation"; public override void Run(string[] args) { switch (args[0].ToLowerInvariant()) { case "off": case "false": case "0": Diagnostics.MasterSwitchOff(); Console.instance.Print("Logging disabled. All diagnostics OFF."); break; case "tides": case "t": Diagnostics.DebugTidesEnabled = true; Console.instance.Print("Logging enabled. Tides diagnostics ON."); break; case "swampmovement": case "swamp": case "s": Diagnostics.DebugSwampMovementEnabled = true; Console.instance.Print("Logging enabled. Swamp movement diagnostics ON."); break; case "vegetation": case "vege": case "v": Diagnostics.DebugVegetationEnabled = true; Console.instance.Print("Logging enabled. Vegetation diagnostics ON."); break; } } public override List<string> CommandOptionList() { return new List<string> { "off", "tides", "vegetation", "swampmovement" }; } } public class TidesDebugLilyCommand : ConsoleCommand { public override string Name => "tides_debug_lily"; public override string Help => "tides debug lily"; public override void Run(string[] args) { Console.instance.Print("tides_debug_lily command response."); VegetationSystem.TestMoveVegetation("clutter_waterlilies"); } public override List<string> CommandOptionList() { return new List<string>(); } } public class TidesDebugCattailCommand : ConsoleCommand { public override string Name => "tides_debug_cattail"; public override string Help => "Test Move Vegetation"; public override void Run(string[] args) { Console.instance.Print("tides_debug_cattail command response."); VegetationSystem.TestMoveVegetation("vass"); } public override List<string> CommandOptionList() { return new List<string>(); } } } namespace Tides.Systems { internal class SwampMovementSystem { private const float BaseWaterLevel = 29.9f; internal static float ComputeSwampVariant(Character c, float baseSpeed) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)c).transform.position; Biome biome = WorldGenerator.instance.GetBiome(position); if ((int)biome != 2) { return baseSpeed; } float groundHeight = ZoneSystem.instance.GetGroundHeight(position); float num = 29.9f - groundHeight; if (num <= 0f) { return baseSpeed; } float num2 = c.m_collider.height / 3f; float num3 = Mathf.Clamp01(num / num2); float num4 = baseSpeed; num4 -= num4 * num4 * num3 * 0.05f; if (Diagnostics.DebugSwampMovementEnabled) { Logger.LogInfo((object)$"SWAMP: Biome={biome}, GroundY={groundHeight}, Depth={num}, DepthFactor={num3}, BaseSpeed={baseSpeed}, ResultSpeed={num4}"); } return num4; } } internal class TideSystem { internal static float TidePeriodDays = 0.5175f; internal static float TideAmplitude = 1.4f; internal static float OceanBaseY = 30f; internal static float _lastTideOffset = 0f; private static bool _debugTidesEnabled = false; private static Transform _waterPlane; public static void UpdateTides() { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || TideAmplitude == 0f) { return; } if ((Object)(object)_waterPlane == (Object)null) { if (Diagnostics.DebugTidesEnabled && _debugTidesEnabled) { Logger.LogWarning((object)"Waterplane is null, trying to get and cache."); } CacheWaterPlane(); } float num = (float)EnvMan.instance.GetDay() + EnvMan.instance.GetDayFraction(); float num2 = (_lastTideOffset = Mathf.Sin(num / TidePeriodDays * (float)Math.PI * 2f) * TideAmplitude); float num3 = OceanBaseY + num2; if ((Object)(object)_waterPlane != (Object)null) { if (Diagnostics.DebugTidesEnabled && _debugTidesEnabled) { Logger.LogWarning((object)"Waterplane is not null, applying transform."); } Vector3 position = _waterPlane.position; position.y = num3; _waterPlane.position = position; } else if (Diagnostics.DebugTidesEnabled && _debugTidesEnabled) { Logger.LogWarning((object)"Waterplane is null, skipping transform."); } foreach (WaterVolume instance in WaterVolume.Instances) { if ((Object)(object)instance == (Object)null) { continue; } Material material = ((Renderer)instance.m_waterSurface).material; if (!((Object)(object)material == (Object)null) && !(((Object)material).name.ToLowerInvariant() != "water (instance)")) { Vector3 position2 = ((Component)instance).transform.position; position2.y = num3; ((Component)instance).transform.position = position2; Vector3 position3 = ((Component)instance.m_waterSurface).transform.position; position3.y = num3; ((Component)instance.m_waterSurface).transform.position = position3; if (Diagnostics.DebugTidesEnabled && _debugTidesEnabled) { Logger.LogInfo((object)$"offset={num2}m, worldDay={num}, Day={EnvMan.instance.GetDay()} + Frac={EnvMan.instance.GetDayFraction()} = WorldDays={(float)EnvMan.instance.GetDay() + EnvMan.instance.GetDayFraction()}, finalY={num3}m , physPos={((Component)instance).transform.position.y}m, visualPos={((Component)instance.m_waterSurface).transform.position.y}m"); _debugTidesEnabled = false; } } } } internal static void ApplyConfigModifications() { float value = TidesConfig.TideAmplitude.Value; float value2 = TidesConfig.BaseWaterLevel.Value; float value3 = TidesConfig.TideSpeedMultiplier.Value; float num = Mathf.Clamp(value, 0f, 3f); float num2 = Mathf.Clamp(value2, 26f, 34f); float num3 = Mathf.Clamp(value3, 0.1f, 5f); if (num != TideAmplitude) { if (Diagnostics.DebugTidesEnabled && _debugTidesEnabled) { Logger.LogInfo((object)$"Tide amplitude modified from {TideAmplitude}m to {num}m"); } TideAmplitude = num; } if (num2 != OceanBaseY) { if (Diagnostics.DebugTidesEnabled && _debugTidesEnabled) { Logger.LogInfo((object)$"Base water level modified from {OceanBaseY}m to {num2}m"); } OceanBaseY = num2; } if (num3 != 1f) { if (Diagnostics.DebugTidesEnabled && _debugTidesEnabled) { Logger.LogInfo((object)$"Tide speed multiplier modified to {num3}x"); } TidePeriodDays = 0.5175f / num3; } } public static void CacheWaterPlane() { GameObject obj = GameObject.Find("WaterPlane"); _waterPlane = ((obj != null) ? obj.transform : null); if (Diagnostics.DebugTidesEnabled && _debugTidesEnabled) { if ((Object)(object)_waterPlane == (Object)null) { Logger.LogWarning((object)"Failed to find WaterPlane."); } Logger.LogWarning((object)"WaterPlane found."); } } } internal static class VegetationSystem { private class WaterLilyInstance { public Matrix4x4 OriginalMatrix; public float MinOffset; public float MaxOffset; } private class WaterLiliesBatch { public InstanceRenderer Renderer; public WaterLilyInstance[] WaterLilies; } private class CattailsBatch { public InstanceRenderer Renderer; public Matrix4x4[] OriginalMatrices; } private const float MinLilyMaxOffset = 0.4f; private const float MaxLilyMaxOffset = 2f; private const float LilyMinGroundHeight = 0.2f; private const float CattailStartDepth = 0.45f; private const float CattailMaxDepth = 1.4f; private const float CattailMaxOffset = -1.1f; private static readonly List<WaterLiliesBatch> _waterLilies = new List<WaterLiliesBatch>(); private static readonly List<CattailsBatch> _cattails = new List<CattailsBatch>(); private static readonly HashSet<InstanceRenderer> _pendingLilies = new HashSet<InstanceRenderer>(); private static readonly HashSet<InstanceRenderer> _pendingCattails = new HashSet<InstanceRenderer>(); private static FieldInfo _instancesField; private static FieldInfo _instanceCountField; private static FieldInfo _dirtyBoundsField; private static bool _initialized; public static void Initialize() { if (!_initialized) { _instancesField = typeof(InstanceRenderer).GetField("m_instances", BindingFlags.Instance | BindingFlags.NonPublic); _instanceCountField = typeof(InstanceRenderer).GetField("m_instanceCount", BindingFlags.Instance | BindingFlags.NonPublic); _dirtyBoundsField = typeof(InstanceRenderer).GetField("m_dirtyBounds", BindingFlags.Instance | BindingFlags.NonPublic); _initialized = true; } } public static void Update(float tideOffset) { Initialize(); InstanceRenderer[] array = _pendingLilies.ToArray(); foreach (InstanceRenderer val in array) { if ((int)_instanceCountField.GetValue(val) > 0) { TryRegister(val); _pendingLilies.Remove(val); } } array = _pendingCattails.ToArray(); foreach (InstanceRenderer val2 in array) { if ((int)_instanceCountField.GetValue(val2) > 0) { RegisterCattails(val2); _pendingCattails.Remove(val2); } } foreach (WaterLiliesBatch waterLily in _waterLilies) { if (!((Object)(object)waterLily.Renderer == (Object)null)) { ApplyWaterLilyOffset(waterLily); } } } public static void TryRegister(InstanceRenderer renderer) { Initialize(); if (!((Object)(object)renderer == (Object)null) && !((Object)(object)renderer.m_material == (Object)null)) { if (((Object)renderer.m_material).name == "clutter_waterlilies") { RegisterWaterLilies(renderer); } else if (((Object)renderer.m_material).name == "vass") { RegisterCattails(renderer); } } } public static void RegisterWaterLilies(InstanceRenderer renderer) { //IL_00c1: 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_00cb: 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_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) foreach (WaterLiliesBatch waterLily in _waterLilies) { if ((Object)(object)waterLily.Renderer == (Object)(object)renderer) { return; } } Matrix4x4[] array = (Matrix4x4[])_instancesField.GetValue(renderer); int num = (int)_instanceCountField.GetValue(renderer); if (num == 0) { if (Diagnostics.DebugVegetationEnabled) { Logger.LogInfo((object)"Waterlily renderer created but has no instances yet"); } if (!_pendingLilies.Contains(renderer)) { _pendingLilies.Add(renderer); } return; } if (Diagnostics.DebugVegetationEnabled) { Logger.LogWarning((object)$"Registering water lilies. Count={num}"); } WaterLilyInstance[] array2 = new WaterLilyInstance[num]; for (int i = 0; i < num; i++) { Vector3 val = Vector4.op_Implicit(((Matrix4x4)(ref array[i])).GetColumn(3)); float groundHeight = ZoneSystem.instance.GetGroundHeight(val); array2[i] = new WaterLilyInstance { OriginalMatrix = array[i], MinOffset = groundHeight + 0.2f - TideSystem.OceanBaseY, MaxOffset = Random.Range(0.4f, 2f) }; } WaterLiliesBatch waterLiliesBatch = new WaterLiliesBatch { Renderer = renderer, WaterLilies = array2 }; _waterLilies.Add(waterLiliesBatch); ApplyWaterLilyOffset(waterLiliesBatch); } public static void RegisterCattails(InstanceRenderer renderer) { foreach (CattailsBatch cattail in _cattails) { if ((Object)(object)cattail.Renderer == (Object)(object)renderer) { return; } } Matrix4x4[] sourceArray = (Matrix4x4[])_instancesField.GetValue(renderer); int num = (int)_instanceCountField.GetValue(renderer); if (num == 0) { if (Diagnostics.DebugVegetationEnabled) { Logger.LogInfo((object)"Cattail renderer created but has no instances yet"); } if (!_pendingCattails.Contains(renderer)) { _pendingCattails.Add(renderer); } return; } if (Diagnostics.DebugVegetationEnabled) { Logger.LogWarning((object)$"Registering cattails. Count={num}"); } Matrix4x4[] array = (Matrix4x4[])(object)new Matrix4x4[num]; Array.Copy(sourceArray, array, num); CattailsBatch cattailsBatch = new CattailsBatch { Renderer = renderer, OriginalMatrices = array }; _cattails.Add(cattailsBatch); ApplyCattailOffset(cattailsBatch); } private static void ApplyWaterLilyOffset(WaterLiliesBatch batch) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) Matrix4x4[] array = (Matrix4x4[])_instancesField.GetValue(batch.Renderer); for (int i = 0; i < batch.WaterLilies.Length; i++) { WaterLilyInstance waterLilyInstance = batch.WaterLilies[i]; Matrix4x4 originalMatrix = waterLilyInstance.OriginalMatrix; float num = Mathf.Clamp(TideSystem._lastTideOffset, waterLilyInstance.MinOffset, waterLilyInstance.MaxOffset); ((Matrix4x4)(ref originalMatrix))[1, 3] = ((Matrix4x4)(ref originalMatrix))[1, 3] + num; array[i] = originalMatrix; } _dirtyBoundsField.SetValue(batch.Renderer, true); } private static void ApplyCattailOffset(CattailsBatch batch) { //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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) Matrix4x4[] array = (Matrix4x4[])_instancesField.GetValue(batch.Renderer); if (Diagnostics.DebugVegetationEnabled) { Logger.LogInfo((object)"Cattail - about to apply offset"); } for (int i = 0; i < batch.OriginalMatrices.Length; i++) { Matrix4x4 val = batch.OriginalMatrices[i]; Vector3 val2 = Vector4.op_Implicit(((Matrix4x4)(ref val)).GetColumn(3)); float groundHeight = ZoneSystem.instance.GetGroundHeight(val2); float num = TideSystem.OceanBaseY - groundHeight; float num2 = CalculateCattailOffset(num); if (Diagnostics.DebugVegetationEnabled) { Logger.LogInfo((object)$"Cattail originally at {num} from base, moved by {num2}"); } ((Matrix4x4)(ref val))[1, 3] = ((Matrix4x4)(ref val))[1, 3] + num2; array[i] = val; } _dirtyBoundsField.SetValue(batch.Renderer, true); } private static float CalculateCattailOffset(float depth) { if (depth <= 0.45f) { return 0f; } float num = Mathf.InverseLerp(0.45f, 1.4f, depth); return Mathf.Lerp(0f, -1.1f, num); } public static void TestMoveVegetation(string vegetation) { foreach (IMonoUpdater instance in InstanceRenderer.Instances) { InstanceRenderer val = (InstanceRenderer)(object)((instance is InstanceRenderer) ? instance : null); if (val == null || (Object)(object)val.m_material == (Object)null) { continue; } if (Diagnostics.DebugVegetationEnabled) { Logger.LogInfo((object)("Renderer found: " + ((Object)val.m_material).name)); } if (((Object)val.m_material).name != vegetation) { continue; } Matrix4x4[] array = (Matrix4x4[])_instancesField.GetValue(val); int num = (int)_instanceCountField.GetValue(val); if (Diagnostics.DebugVegetationEnabled) { Logger.LogInfo((object)$"{vegetation}: {num}"); } for (int i = 0; i < num; i++) { float num2 = ((Matrix4x4)(ref array[i]))[1, 3]; if (Diagnostics.DebugVegetationEnabled) { Logger.LogInfo((object)$"{vegetation} instance {i}: Y={num2}"); } ref Matrix4x4 reference = ref array[i]; ((Matrix4x4)(ref reference))[1, 3] = ((Matrix4x4)(ref reference))[1, 3] + 2f; } _dirtyBoundsField.SetValue(val, true); if (Diagnostics.DebugVegetationEnabled) { Logger.LogInfo((object)("Moved " + vegetation + " +2")); } } } } } namespace Tides.Patches { internal class InstanceRendererPatches { [HarmonyPatch(typeof(InstanceRenderer), "OnEnable")] internal static class InstanceRendererPatch { private static void Postfix(InstanceRenderer __instance) { VegetationSystem.TryRegister(__instance); } } } internal class SwampMovementPatches { [HarmonyPatch(typeof(Character), "ApplyLiquidResistance")] public static class ApplyLiquidResistance_Patch { private static void Prefix(ref float speed, ref float __state) { __state = speed; } private static void Postfix(Character __instance, ref float speed, float __state) { float num = speed; float num2 = SwampMovementSystem.ComputeSwampVariant(__instance, __state); speed = Mathf.Min(num, num2); if (Diagnostics.DebugSwampMovementEnabled) { Logger.LogInfo((object)$"SWAMP RUN: Original={__state}, Vanilla={num}, SwampPeat={num2}, Final={speed}"); } } } } internal class ZNetReadyPatches { [HarmonyPatch(typeof(ZNet), "Update")] internal static class ZNet_Update_Patch { private static void Postfix() { TidesManager.Update(); } } [HarmonyPatch(typeof(ZNet), "Start")] internal static class ZNet_Start_Patch { private static void Postfix() { TidesManager.SetWorldReady(ready: true); } } [HarmonyPatch(typeof(ZNet), "OnDestroy")] internal static class ZNet_Destroy_Patch { private static void Prefix() { TidesManager.SetWorldReady(ready: false); } } } } namespace Tides.Core { internal class Diagnostics { internal static bool DebugTidesEnabled; internal static bool DebugVegetationEnabled; internal static bool DebugSwampMovementEnabled; public static void MasterSwitchOff() { DebugTidesEnabled = false; DebugVegetationEnabled = false; DebugSwampMovementEnabled = false; } } internal class TidesConfig { internal static ConfigEntry<float> TideAmplitude; internal static ConfigEntry<float> BaseWaterLevel; internal static ConfigEntry<float> TideSpeedMultiplier; internal static void CreateConfigValues(ConfigFile config) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown ConfigurationManagerAttributes val = new ConfigurationManagerAttributes { IsAdminOnly = true }; TideAmplitude = config.Bind<float>("General", "Tide Amplitude", 1.4f, new ConfigDescription("Maximum tide amplitude in meters.\n1.4 = recommended amplitude.\nDecides maximum height of high tide and minimal height of low tide from the base ocean level.\n At value 0 there are no tides.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), new object[1] { val })); BaseWaterLevel = config.Bind<float>("General", "Base Ocean Level", 30f, new ConfigDescription("Base ocean level in meters.\n30.0 = normal level.\nHigher values raise the whole ocean level.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(26f, 34f), new object[1] { val })); TideSpeedMultiplier = config.Bind<float>("General", "Tide Speed Multiplier", 1f, new ConfigDescription("Multiplies the speed of the tide cycle.\n1.0 = normal speed.\nHigher values make tides change faster.\nAt 0.1x speed high tide repeats cca once every 5 days.\nAt 5x speed high tide happens cca 10x per day.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), new object[1] { val })); } internal static void RegisterChangeCallbacks() { TideAmplitude.SettingChanged += delegate { TideSystem.ApplyConfigModifications(); }; BaseWaterLevel.SettingChanged += delegate { TideSystem.ApplyConfigModifications(); }; TideSpeedMultiplier.SettingChanged += delegate { TideSystem.ApplyConfigModifications(); }; } } internal class TidesManager { private static bool _worldReady; public static void SetWorldReady(bool ready) { _worldReady = ready; } public static void Update() { if (_worldReady) { TideSystem.UpdateTides(); VegetationSystem.Update(TideSystem._lastTideOffset); if (Diagnostics.DebugTidesEnabled) { Logger.LogInfo((object)$"_lastTideOffset={TideSystem._lastTideOffset}"); } } } } }