using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Njoror.Configuration; using Njoror.Logic; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Njoror { [BepInPlugin("com.bigai.njoror_fairwinds", "Njoror_FairWinds", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class NjororPlugin : BaseUnityPlugin { public const string PluginGUID = "com.bigai.njoror_fairwinds"; public const string PluginName = "Njoror_FairWinds"; public const string PluginVersion = "1.0.0"; private Harmony? _harmony; public static NjororPlugin Instance { get; private set; } public static ManualLogSource Log { get; private set; } public static void LogDebug(string message) { if (ModConfig.EnableDebugLogging.Value) { Log.LogInfo((object)message); } } private void Awake() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; try { ModConfig.Initialize(((BaseUnityPlugin)this).Config); SailingStateNetwork.Initialize(); _harmony = new Harmony("com.bigai.njoror_fairwinds"); _harmony.PatchAll(Assembly.GetExecutingAssembly()); int num = 0; foreach (MethodBase patchedMethod in _harmony.GetPatchedMethods()) { num++; LogDebug("[Njoror_FairWinds][Diag] Bound Harmony target: " + patchedMethod.DeclaringType?.FullName + "::" + patchedMethod.Name); } LogDebug(string.Format("[{0}] All Harmony patches applied successfully ({1} target(s)).", "Njoror_FairWinds", num)); LogDebug("[Njoror_FairWinds] Fair winds, ocean storm modulation, and serpent controls active."); } catch (Exception arg) { Log.LogError((object)string.Format("[{0}] Failed to initialize: {1}", "Njoror_FairWinds", arg)); } } private void OnDestroy() { Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } LogDebug("[Njoror_FairWinds] Unloaded."); } } } namespace Njoror.Patches { [HarmonyPatch(typeof(EnvMan), "UpdateWind")] public static class EnvManWindPatch { [HarmonyPostfix] public static void Postfix(EnvMan __instance, ref Vector4 ___m_wind) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_0081: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return; } try { Vector3 baseWindDirection = default(Vector3); ((Vector3)(ref baseWindDirection))..ctor(___m_wind.x, ___m_wind.y, ___m_wind.z); Vector3 direction; float intensity; if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { if (OceanWindEngine.TryGetTimedWindOverride(baseWindDirection, out var windDirection, out var decisionMade)) { ___m_wind = new Vector4(windDirection.x, windDirection.y, windDirection.z, ___m_wind.w); } if (decisionMade) { SailingStateNetwork.BroadcastAuthoritativeWind(new Vector3(___m_wind.x, ___m_wind.y, ___m_wind.z), ___m_wind.w); } } else if (SailingStateNetwork.TryGetAuthoritativeWind(out direction, out intensity)) { ___m_wind = new Vector4(direction.x, direction.y, direction.z, intensity); } } catch (Exception arg) { NjororPlugin.Log.LogError((object)$"[Njoror] Error during wind adjustment: {arg}"); } } } [HarmonyPatch(typeof(EnvMan), "SetTargetWind")] public static class EnvManTargetWindPatch { [HarmonyPrefix] public static void Prefix(ref Vector3 dir, ref float intensity) { //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) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || !ModConfig.CheckDeflectOnWindChange.Value) { return; } try { dir = OceanWindEngine.AdjustWindForSailing(dir); intensity = OceanWindEngine.AdjustWindIntensity(intensity); SailingStateNetwork.BroadcastAuthoritativeWind(dir, intensity); NjororPlugin.LogDebug($"[Njoror][Diag] Wind-cycle fair-wind check completed: direction={dir}, intensity={intensity:F3}."); } catch (Exception arg) { NjororPlugin.Log.LogError((object)$"[Njoror] Error during wind-cycle adjustment: {arg}"); } } } [HarmonyPatch(typeof(EnvMan), "GetAvailableEnvironments")] public static class EnvManWeatherPatch { [HarmonyPostfix] public static void Postfix(List __result) { NjororPlugin.LogDebug("[Njoror][Diag] EnvMan.GetAvailableEnvironments postfix entered."); if (__result == null) { NjororPlugin.LogDebug("[Njoror][Diag] Environment tuning skipped: result was null."); return; } try { OceanWindEngine.ApplyEnvironmentWeights(__result); } catch (Exception arg) { NjororPlugin.Log.LogError((object)$"[Njoror] Error during weather weight adjustment: {arg}"); } } } [HarmonyPatch(typeof(SpawnSystem), "Awake")] public static class SpawnSystemSerpentPatch { [HarmonyPostfix] public static void Postfix(SpawnSystem __instance) { NjororPlugin.LogDebug("[Njoror][Diag] SpawnSystem.Awake postfix entered."); if ((Object)(object)__instance == (Object)null) { NjororPlugin.LogDebug("[Njoror][Diag] Serpent tuning skipped: SpawnSystem instance was null."); return; } if (__instance.m_spawnLists == null) { NjororPlugin.LogDebug("[Njoror][Diag] Serpent tuning skipped: spawn list was null."); return; } try { if (!ModConfig.EnableSerpentTuning.Value) { NjororPlugin.LogDebug("[Njoror][Diag] Serpent tuning skipped: disabled by configuration."); return; } foreach (SpawnSystemList spawnList in __instance.m_spawnLists) { if ((Object)(object)spawnList == (Object)null || spawnList.m_spawners == null) { continue; } foreach (SpawnData spawner in spawnList.m_spawners) { if (spawner != null && (Object)(object)spawner.m_prefab != (Object)null && ((Object)spawner.m_prefab).name.IndexOf("Serpent", StringComparison.OrdinalIgnoreCase) >= 0) { spawner.m_spawnInterval = ModConfig.SerpentSpawnIntervalSeconds.Value; spawner.m_spawnChance = ModConfig.NighttimeSerpentSpawnChance.Value; spawner.m_spawnAtDay = ModConfig.DaytimeSerpentSpawnChance.Value > 0f || ModConfig.AllowCalmWeatherDaySerpents.Value; NjororPlugin.LogDebug($"[Njoror][Diag] Configured Serpent spawner: Interval={spawner.m_spawnInterval}s, NightChance={spawner.m_spawnChance}%, DayChance={ModConfig.DaytimeSerpentSpawnChance.Value}%"); } } } } catch (Exception arg) { NjororPlugin.Log.LogError((object)$"[Njoror] Error configuring Serpent spawners: {arg}"); } } } } namespace Njoror.Logic { public static class OceanWindEngine { private static readonly Random _rng = new Random(); private static Vector3 _timedWindDirection; private static bool _hasTimedWindDirection; private static float _nextTimedCheckAt; public static Vector3 AdjustWindForSailing(Vector3 baseWindDir) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_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_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) NjororPlugin.LogDebug("[Njoror][Diag] AdjustWindForSailing entered."); if (!ModConfig.EnableFairWinds.Value) { NjororPlugin.LogDebug("[Njoror][Diag] Fair winds skipped: disabled by configuration."); return baseWindDir; } if (!SailingStateNetwork.TryGetActiveSailingState(out var heading, out var inOcean)) { NjororPlugin.LogDebug("[Njoror][Diag] Fair winds skipped: no fresh client sailing-state report."); return baseWindDir; } Vector3 val = baseWindDir; val.y = 0f; ((Vector3)(ref val)).Normalize(); float num = Vector3.Dot(heading, val); if (ModConfig.AlwaysTailwindInOcean.Value && inOcean) { NjororPlugin.LogDebug("[Njoror][Diag] Ocean tailwind applied."); return heading; } if (num < -0.6f) { double num2 = _rng.NextDouble() * 100.0; if (num2 < (double)ModConfig.HeadwindMitigationPercent.Value) { float num3 = ((_rng.Next(2) == 0) ? 1f : (-1f)); Vector3 val2 = Quaternion.Euler(0f, num3 * 80f, 0f) * heading; val2.y = 0f; NjororPlugin.Log.LogInfo((object)$"[Njoror] Headwind deflected; roll={num2:F2}."); return ((Vector3)(ref val2)).normalized; } NjororPlugin.LogDebug($"[Njoror][Diag] Headwind retained; roll={num2:F2}."); } NjororPlugin.LogDebug("[Njoror][Diag] Fair winds retained the base direction."); return baseWindDir; } public static float AdjustWindIntensity(float baseIntensity) { if (!ModConfig.EnableFairWinds.Value) { return baseIntensity; } float value = ModConfig.MinimumWindSpeedMultiplier.Value; return Mathf.Max(baseIntensity * value, 0.25f); } public static bool TryGetTimedWindOverride(Vector3 baseWindDirection, out Vector3 windDirection, out bool decisionMade) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) windDirection = baseWindDirection; decisionMade = false; if (ModConfig.CheckDeflectOnWindChange.Value || ModConfig.CheckDeflectTimeSeconds.Value <= 0) { _hasTimedWindDirection = false; return false; } if (Time.unscaledTime >= _nextTimedCheckAt) { _nextTimedCheckAt = Time.unscaledTime + (float)ModConfig.CheckDeflectTimeSeconds.Value; _timedWindDirection = AdjustWindForSailing(baseWindDirection); _hasTimedWindDirection = true; decisionMade = true; NjororPlugin.LogDebug($"[Njoror][Diag] Timed fair-wind check completed; next check in {ModConfig.CheckDeflectTimeSeconds.Value}s."); } if (!_hasTimedWindDirection) { return false; } windDirection = _timedWindDirection; return true; } public static void ApplyEnvironmentWeights(List environments) { NjororPlugin.LogDebug("[Njoror][Diag] ApplyEnvironmentWeights entered."); if (!ModConfig.EnableWeatherTuning.Value) { NjororPlugin.LogDebug("[Njoror][Diag] Environment tuning skipped: disabled by configuration."); return; } if (environments == null) { NjororPlugin.LogDebug("[Njoror][Diag] Environment tuning skipped: environment list was null."); return; } foreach (EnvEntry environment in environments) { if (environment != null && environment.m_env != null) { string text = environment.m_env.m_name.ToLower(); if (text.Contains("thunder") || text.Contains("storm")) { environment.m_weight *= ModConfig.StormFrequencyMultiplier.Value; } else if (text.Contains("rain") || text.Contains("fog")) { environment.m_weight *= ModConfig.RainFrequencyMultiplier.Value; } else if (text.Contains("clear") || text.Contains("sun")) { environment.m_weight *= ModConfig.ClearWeatherFrequencyMultiplier.Value; } } } NjororPlugin.LogDebug($"[Njoror][Diag] Environment tuning processed {environments.Count} entry(s)."); } } public sealed class SailingStateNetwork : MonoBehaviour { private struct SailingState { public Vector3 Heading { get; } public bool InOcean { get; } public float ReceivedAt { get; } public SailingState(Vector3 heading, bool inOcean, float receivedAt) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) Heading = heading; InOcean = inOcean; ReceivedAt = receivedAt; } } private const string SailingStateRpc = "Njoror_SailingState"; private const string AuthoritativeWindRpc = "Njoror_AuthoritativeWind"; private const float ReportIntervalSeconds = 0.5f; private const float StateExpirySeconds = 2f; private const float MinimumWindExpirySeconds = 5f; private const float MinimumHeadingMagnitude = 0.8f; private const float ShipDetectionRadius = 12f; private static readonly Dictionary ServerStates = new Dictionary(); private static bool _rpcRegistered; private static Vector3 _authoritativeWindDirection; private static float _authoritativeWindIntensity; private static float _authoritativeWindReceivedAt; private static bool _hasAuthoritativeWind; private float _nextReportTime; public static void Initialize() { //IL_0005: 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: Expected O, but got Unknown GameObject val = new GameObject("Njoror_SailingStateNetwork"); Object.DontDestroyOnLoad((Object)val); val.AddComponent(); NjororPlugin.LogDebug("[Njoror] Sailing-state network initialized."); } private void Update() { EnsureRpcRegistered(); if (!((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer() && !(Time.unscaledTime < _nextReportTime)) { _nextReportTime = Time.unscaledTime + 0.5f; ReportLocalSailingState(); } } private static void EnsureRpcRegistered() { if (_rpcRegistered || ZRoutedRpc.instance == null) { return; } _rpcRegistered = true; try { ZRoutedRpc.instance.Register("Njoror_SailingState", (Action)RPC_SailingState); } catch (ArgumentException) { } catch (Exception ex2) { ManualLogSource log = NjororPlugin.Log; if (log != null) { log.LogWarning((object)("[Njoror] Failed to register SailingState RPC: " + ex2.Message)); } } try { ZRoutedRpc.instance.Register("Njoror_AuthoritativeWind", (Action)RPC_AuthoritativeWind); } catch (ArgumentException) { } catch (Exception ex4) { ManualLogSource log2 = NjororPlugin.Log; if (log2 != null) { log2.LogWarning((object)("[Njoror] Failed to register AuthoritativeWind RPC: " + ex4.Message)); } } NjororPlugin.LogDebug("[Njoror] Sailing-state and authoritative-wind RPCs registered."); } private static void ReportLocalSailingState() { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; Ship val = (((Object)(object)localPlayer != (Object)null) ? localPlayer.GetControlledShip() : null); string arg = "ship helm"; if ((Object)(object)val == (Object)null && (Object)(object)localPlayer != (Object)null) { val = ((Character)localPlayer).GetStandingOnShip(); arg = "GetStandingOnShip"; } if ((Object)(object)val == (Object)null && (Object)(object)localPlayer != (Object)null) { val = FindNearbyShip(((Component)localPlayer).transform.position); arg = "nearby ship fallback"; } bool flag = (Object)(object)val != (Object)null; Vector3 val2 = (((Object)(object)val != (Object)null) ? FlattenAndNormalize(((Component)val).transform.forward) : Vector3.zero); ZRoutedRpc.instance.InvokeRoutedRPC(0L, "Njoror_SailingState", new object[2] { flag, val2 }); NjororPlugin.LogDebug($"[Njoror][Diag] Reported local sailing state: active={flag}, heading={val2}, detection={arg}."); } private static Ship? FindNearbyShip(Vector3 playerPosition) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_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) Ship result = null; float num = 144f; Ship[] array = Object.FindObjectsOfType(); foreach (Ship val in array) { if (!((Object)(object)val == (Object)null)) { Vector3 val2 = ((Component)val).transform.position - playerPosition; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude < num) { result = val; num = sqrMagnitude; } } } return result; } private static void RPC_SailingState(long sender, bool reportedSailing, Vector3 reportedHeading) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Invalid comparison between Unknown and I4 //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } ZNetPeer peer = ZNet.instance.GetPeer(sender); if (peer == null || ((ZDOID)(ref peer.m_characterID)).IsNone()) { NjororPlugin.LogDebug($"[Njoror][Diag] Rejected sailing state from {sender}: no connected character."); return; } ZDO val = ((ZDOMan.instance != null) ? ZDOMan.instance.GetZDO(peer.m_characterID) : null); if (val == null) { NjororPlugin.LogDebug($"[Njoror][Diag] Rejected sailing state from {sender}: character ZDO unavailable."); return; } if (!reportedSailing) { ServerStates.Remove(sender); NjororPlugin.LogDebug($"[Njoror][Diag] Cleared sailing state for {sender}."); return; } Vector3 val2 = FlattenAndNormalize(reportedHeading); if (((Vector3)(ref val2)).sqrMagnitude < 0.64000005f) { NjororPlugin.LogDebug($"[Njoror][Diag] Rejected sailing state from {sender}: invalid heading."); return; } Vector3 position = val.GetPosition(); bool flag = WorldGenerator.instance != null && (int)WorldGenerator.instance.GetBiome(position.x, position.z, 0.02f, false) == 256; ServerStates[sender] = new SailingState(val2, flag, Time.unscaledTime); NjororPlugin.LogDebug($"[Njoror][Diag] Accepted sailing state from {sender}: ocean={flag}, heading={val2}."); } private static void RPC_AuthoritativeWind(long sender, Vector3 direction, float intensity) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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) if (!((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer()) { direction = FlattenAndNormalize(direction); if (((Vector3)(ref direction)).sqrMagnitude < 0.64000005f || intensity < 0.05f || intensity > 1f) { NjororPlugin.LogDebug($"[Njoror][Diag] Rejected authoritative wind from {sender}: invalid payload."); return; } _authoritativeWindDirection = direction; _authoritativeWindIntensity = intensity; _authoritativeWindReceivedAt = Time.unscaledTime; _hasAuthoritativeWind = true; NjororPlugin.LogDebug($"[Njoror][Diag] Received authoritative wind: direction={direction}, intensity={intensity:F3}."); } } public static void BroadcastAuthoritativeWind(Vector3 direction, float intensity) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || ZRoutedRpc.instance == null) { return; } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer != null) { ZRoutedRpc.instance.InvokeRoutedRPC(peer.m_uid, "Njoror_AuthoritativeWind", new object[2] { direction, intensity }); } } NjororPlugin.LogDebug($"[Njoror][Diag] Broadcast authoritative wind: direction={direction}, intensity={intensity:F3}."); } public static bool TryGetAuthoritativeWind(out Vector3 direction, out float intensity) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_004b: Unknown result type (might be due to invalid IL or missing references) direction = Vector3.zero; intensity = 0f; float num = Mathf.Max(5f, (float)ModConfig.CheckDeflectTimeSeconds.Value + 2f); if (!_hasAuthoritativeWind || Time.unscaledTime - _authoritativeWindReceivedAt > num) { return false; } direction = _authoritativeWindDirection; intensity = _authoritativeWindIntensity; return true; } public static bool TryGetActiveSailingState(out Vector3 heading, out bool inOcean) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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) heading = Vector3.zero; inOcean = false; if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return false; } long num = 0L; float num2 = float.MinValue; foreach (KeyValuePair serverState in ServerStates) { if (!(Time.unscaledTime - serverState.Value.ReceivedAt > 2f) && serverState.Value.ReceivedAt > num2) { num = serverState.Key; num2 = serverState.Value.ReceivedAt; heading = serverState.Value.Heading; inOcean = serverState.Value.InOcean; } } if (num == 0L) { return false; } return true; } private static Vector3 FlattenAndNormalize(Vector3 vector) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) vector.y = 0f; if (!(((Vector3)(ref vector)).sqrMagnitude > 0f)) { return Vector3.zero; } return ((Vector3)(ref vector)).normalized; } } } namespace Njoror.Configuration { public static class ModConfig { public static ConfigEntry EnableFairWinds { get; private set; } public static ConfigEntry HeadwindMitigationPercent { get; private set; } public static ConfigEntry MinimumWindSpeedMultiplier { get; private set; } public static ConfigEntry AlwaysTailwindInOcean { get; private set; } public static ConfigEntry CheckDeflectOnWindChange { get; private set; } public static ConfigEntry CheckDeflectTimeSeconds { get; private set; } public static ConfigEntry EnableWeatherTuning { get; private set; } public static ConfigEntry StormFrequencyMultiplier { get; private set; } public static ConfigEntry RainFrequencyMultiplier { get; private set; } public static ConfigEntry ClearWeatherFrequencyMultiplier { get; private set; } public static ConfigEntry EnableSerpentTuning { get; private set; } public static ConfigEntry DaytimeSerpentSpawnChance { get; private set; } public static ConfigEntry NighttimeSerpentSpawnChance { get; private set; } public static ConfigEntry SerpentSpawnIntervalSeconds { get; private set; } public static ConfigEntry AllowCalmWeatherDaySerpents { get; private set; } public static ConfigEntry EnableDebugLogging { get; private set; } public static void Initialize(ConfigFile config) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Expected O, but got Unknown //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Expected O, but got Unknown //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Expected O, but got Unknown //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Expected O, but got Unknown //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Expected O, but got Unknown //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Expected O, but got Unknown EnableFairWinds = config.Bind("1 - Fair Winds", "EnableFairWinds", true, "Enable fair winds while a client with Njoror reports that it is aboard a ship. The server validates and applies the global wind change."); HeadwindMitigationPercent = config.Bind("1 - Fair Winds", "HeadwindMitigationPercent", 60f, new ConfigDescription("Chance % to deflect a direct dead-ahead headwind into a tackable crosswind/quarter wind when sailing.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 100f), Array.Empty())); MinimumWindSpeedMultiplier = config.Bind("1 - Fair Winds", "MinimumWindSpeedMultiplier", 1f, new ConfigDescription("Minimum wind velocity scaling factor (1.0 = Vanilla, >1.0 ensures ships always have at least moderate breeze).", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 2.5f), Array.Empty())); AlwaysTailwindInOcean = config.Bind("1 - Fair Winds", "AlwaysTailwindInOcean", false, "If enabled, an active Njoror client sailing in the Ocean biome receives a global tailwind or broad reach."); CheckDeflectOnWindChange = config.Bind("1 - Fair Winds", "CheckDeflectOnWindChange", true, "If enabled, evaluate fair-wind deflection only when Valheim selects a new wind target. This takes priority over timed checks."); CheckDeflectTimeSeconds = config.Bind("1 - Fair Winds", "CheckDeflectTimeSeconds", 0, new ConfigDescription("When CheckDeflectOnWindChange is disabled, re-evaluate fair winds at this interval. Set to 0 to disable timed checks.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 3600), Array.Empty())); EnableWeatherTuning = config.Bind("2 - Weather & Storms", "EnableWeatherTuning", true, "Enable dynamic modulation of ocean storms and atmospheric weather conditions."); StormFrequencyMultiplier = config.Bind("2 - Weather & Storms", "StormFrequencyMultiplier", 1f, new ConfigDescription("Multiplier for the frequency and duration of ThunderStorms (1.0 = Vanilla, 0.5 = Calmer, 2.0 = Violent).", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 3f), Array.Empty())); RainFrequencyMultiplier = config.Bind("2 - Weather & Storms", "RainFrequencyMultiplier", 1f, new ConfigDescription("Multiplier for regular rain and overcast conditions (1.0 = Vanilla).", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 3f), Array.Empty())); ClearWeatherFrequencyMultiplier = config.Bind("2 - Weather & Storms", "ClearWeatherFrequencyMultiplier", 1f, new ConfigDescription("Multiplier for clear, sunny weather frequency (1.0 = Vanilla, >1.0 for more clear sailing days).", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 3f), Array.Empty())); EnableSerpentTuning = config.Bind("3 - Sea Serpents", "EnableSerpentTuning", true, "Enable custom encounter rate tuning for Ocean Sea Serpents."); DaytimeSerpentSpawnChance = config.Bind("3 - Sea Serpents", "DaytimeSerpentSpawnChance", 0f, new ConfigDescription("Base chance % for a Sea Serpent to spawn during clear/calm Day conditions. (Vanilla default is 0.0% / storms only).", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 30f), Array.Empty())); NighttimeSerpentSpawnChance = config.Bind("3 - Sea Serpents", "NighttimeSerpentSpawnChance", 5f, new ConfigDescription("Base chance % for a Sea Serpent to spawn during Night hours. (Vanilla default is 5.0%).", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 50f), Array.Empty())); SerpentSpawnIntervalSeconds = config.Bind("3 - Sea Serpents", "SerpentSpawnIntervalSeconds", 1000f, new ConfigDescription("Time interval (seconds) between Ocean spawner serpent spawn checks. (Vanilla default is 1000.0s).", (AcceptableValueBase)(object)new AcceptableValueRange(100f, 2000f), Array.Empty())); AllowCalmWeatherDaySerpents = config.Bind("3 - Sea Serpents", "AllowCalmWeatherDaySerpents", false, "If true, Sea Serpents can spawn during daytime even when it is not storming or raining."); EnableDebugLogging = config.Bind("4 - Diagnostics", "EnableDebugLogging", false, "Enable detailed Njoror diagnostic logs. Errors and successful headwind deflections are always logged."); } } }