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 Njoror FairWinds v1.0.0
BepInEx\plugins\Njoror_FairWinds\Njoror_FairWinds.dll
Decompiled 11 hours agousing 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<EnvEntry> __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<EnvEntry> 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<long, SailingState> ServerStates = new Dictionary<long, SailingState>(); 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<SailingStateNetwork>(); 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<bool, Vector3>("Njoror_SailingState", (Action<long, bool, Vector3>)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<Vector3, float>("Njoror_AuthoritativeWind", (Action<long, Vector3, float>)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<Ship>(); 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<long, SailingState> 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<bool> EnableFairWinds { get; private set; } public static ConfigEntry<float> HeadwindMitigationPercent { get; private set; } public static ConfigEntry<float> MinimumWindSpeedMultiplier { get; private set; } public static ConfigEntry<bool> AlwaysTailwindInOcean { get; private set; } public static ConfigEntry<bool> CheckDeflectOnWindChange { get; private set; } public static ConfigEntry<int> CheckDeflectTimeSeconds { get; private set; } public static ConfigEntry<bool> EnableWeatherTuning { get; private set; } public static ConfigEntry<float> StormFrequencyMultiplier { get; private set; } public static ConfigEntry<float> RainFrequencyMultiplier { get; private set; } public static ConfigEntry<float> ClearWeatherFrequencyMultiplier { get; private set; } public static ConfigEntry<bool> EnableSerpentTuning { get; private set; } public static ConfigEntry<float> DaytimeSerpentSpawnChance { get; private set; } public static ConfigEntry<float> NighttimeSerpentSpawnChance { get; private set; } public static ConfigEntry<float> SerpentSpawnIntervalSeconds { get; private set; } public static ConfigEntry<bool> AllowCalmWeatherDaySerpents { get; private set; } public static ConfigEntry<bool> 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<bool>("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<float>("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<float>(0f, 100f), Array.Empty<object>())); MinimumWindSpeedMultiplier = config.Bind<float>("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<float>(0.5f, 2.5f), Array.Empty<object>())); AlwaysTailwindInOcean = config.Bind<bool>("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<bool>("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<int>("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<int>(0, 3600), Array.Empty<object>())); EnableWeatherTuning = config.Bind<bool>("2 - Weather & Storms", "EnableWeatherTuning", true, "Enable dynamic modulation of ocean storms and atmospheric weather conditions."); StormFrequencyMultiplier = config.Bind<float>("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<float>(0.1f, 3f), Array.Empty<object>())); RainFrequencyMultiplier = config.Bind<float>("2 - Weather & Storms", "RainFrequencyMultiplier", 1f, new ConfigDescription("Multiplier for regular rain and overcast conditions (1.0 = Vanilla).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 3f), Array.Empty<object>())); ClearWeatherFrequencyMultiplier = config.Bind<float>("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<float>(0.5f, 3f), Array.Empty<object>())); EnableSerpentTuning = config.Bind<bool>("3 - Sea Serpents", "EnableSerpentTuning", true, "Enable custom encounter rate tuning for Ocean Sea Serpents."); DaytimeSerpentSpawnChance = config.Bind<float>("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<float>(0f, 30f), Array.Empty<object>())); NighttimeSerpentSpawnChance = config.Bind<float>("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<float>(1f, 50f), Array.Empty<object>())); SerpentSpawnIntervalSeconds = config.Bind<float>("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<float>(100f, 2000f), Array.Empty<object>())); AllowCalmWeatherDaySerpents = config.Bind<bool>("3 - Sea Serpents", "AllowCalmWeatherDaySerpents", false, "If true, Sea Serpents can spawn during daytime even when it is not storming or raining."); EnableDebugLogging = config.Bind<bool>("4 - Diagnostics", "EnableDebugLogging", false, "Enable detailed Njoror diagnostic logs. Errors and successful headwind deflections are always logged."); } } }