using System; using System.Collections; 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.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Njord.Core; using Njord.HUD; using Njord.Patches; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = "")] [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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Njord { public static class NjordBoatController { public static string GetShipPrefabName(object ship) { Component val = (Component)((ship is Component) ? ship : null); if (val == null) { return "Unknown"; } return ((Object)val.gameObject).name.Replace("(Clone)", "").Trim(); } public static float GetBaseline(NjordSailState state, string shipName) { NjordRuntimeConfig runtimeConfig = NjordSync.RuntimeConfig; if (runtimeConfig == null) { return 0f; } return state switch { NjordSailState.Forward => runtimeConfig.BaseForwardForce, NjordSailState.Half => runtimeConfig.BaseForwardForce, NjordSailState.Full => runtimeConfig.BaseForwardForce, _ => 0f, }; } public static float ApplyAcceleration(float baseline, float dt) { NjordRuntimeConfig runtimeConfig = NjordSync.RuntimeConfig; if (runtimeConfig == null) { return 0f; } float num = baseline * runtimeConfig.AccelerationMultiplier; if (float.IsNaN(num) || float.IsInfinity(num)) { return 0f; } return num; } public static float GetSailMult(NjordSailState state) { NjordRuntimeConfig runtimeConfig = NjordSync.RuntimeConfig; if (runtimeConfig == null) { return 1f; } return state switch { NjordSailState.Forward => runtimeConfig.SailForwardForce, NjordSailState.Half => runtimeConfig.HalfSailForce, NjordSailState.Full => runtimeConfig.FullSailForce, _ => 1f, }; } public static float GetReverseForce(float dt) { NjordRuntimeConfig runtimeConfig = NjordSync.RuntimeConfig; if (runtimeConfig == null) { return 0f; } float num = runtimeConfig.BaseReverseForce * runtimeConfig.ReverseKick; if (float.IsNaN(num) || float.IsInfinity(num)) { return 0f; } return num; } } public static class Njord_ShipControlTracker { public const float READY_DELAY = 0.35f; private static Dictionary _controlMap; private static Dictionary _windAngleMap; private static Dictionary _windGraceTimerMap; private static Dictionary _wasInDeadZoneMap; private static float _lastLookupLogTime = -10f; private const float LOOKUP_LOG_INTERVAL = 2f; public static long CurrentController { get; private set; } = 0L; public static bool ShouldShowHud { get; private set; } = false; public static float ReadyTimer { get; private set; } = 0f; public static bool SteeringGateReady { get; private set; } = false; private static Dictionary ControlMap { get { if (_controlMap == null) { _controlMap = new Dictionary(); } return _controlMap; } } private static Dictionary WindAngleMap { get { if (_windAngleMap == null) { _windAngleMap = new Dictionary(); } return _windAngleMap; } } private static Dictionary WindGraceTimerMap { get { if (_windGraceTimerMap == null) { _windGraceTimerMap = new Dictionary(); } return _windGraceTimerMap; } } private static Dictionary WasInDeadZoneMap { get { if (_wasInDeadZoneMap == null) { _wasInDeadZoneMap = new Dictionary(); } return _wasInDeadZoneMap; } } public static bool GetShipWasInDeadZone(Ship ship, bool defaultValue) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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) if ((Object)(object)ship == (Object)null) { return defaultValue; } ZNetView component = ((Component)ship).GetComponent(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return defaultValue; } ZDOID uid = component.GetZDO().m_uid; if (WasInDeadZoneMap.TryGetValue(uid, out var value)) { return value; } return defaultValue; } public static void SetShipWasInDeadZone(Ship ship, bool val) { //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_0034: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)ship == (Object)null)) { ZNetView component = ((Component)ship).GetComponent(); if (!((Object)(object)component == (Object)null) && component.IsValid()) { ZDOID uid = component.GetZDO().m_uid; WasInDeadZoneMap[uid] = val; } } } public static float GetShipGraceTimer(Ship ship) { //IL_0033: 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_003e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ship == (Object)null) { return 0f; } ZNetView component = ((Component)ship).GetComponent(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return 0f; } ZDOID uid = component.GetZDO().m_uid; if (WindGraceTimerMap.TryGetValue(uid, out var value)) { return value; } return 0f; } public static void SetShipGraceTimer(Ship ship, float timer) { //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_0034: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)ship == (Object)null)) { ZNetView component = ((Component)ship).GetComponent(); if (!((Object)(object)component == (Object)null) && component.IsValid()) { ZDOID uid = component.GetZDO().m_uid; WindGraceTimerMap[uid] = timer; } } } public static float GetShipWindAngle(Ship ship) { //IL_0033: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ship == (Object)null) { return 0f; } ZNetView component = ((Component)ship).GetComponent(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return 0f; } ZDOID uid = component.GetZDO().m_uid; if (WindAngleMap.TryGetValue(uid, out var value)) { return value; } float num = Mathf.DeltaAngle(0f, ship.GetWindAngle()); WindAngleMap[uid] = num; return num; } public static void SetShipWindAngle(Ship ship, float angle) { //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_0034: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)ship == (Object)null)) { ZNetView component = ((Component)ship).GetComponent(); if (!((Object)(object)component == (Object)null) && component.IsValid()) { ZDOID uid = component.GetZDO().m_uid; WindAngleMap[uid] = angle; } } } public static long GetControllerForShip(object shipObj) { //IL_003c: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) if (shipObj == null) { return 0L; } Ship val = (Ship)((shipObj is Ship) ? shipObj : null); if (val == null) { return 0L; } ZNetView component = ((Component)val).GetComponent(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return 0L; } ZDO zDO = component.GetZDO(); if (zDO == null) { return 0L; } ZDOID uid = zDO.m_uid; if (ControlMap.TryGetValue(uid, out var value)) { if (NjordConfig.Debug_Enable.Value && NjordConfig.Debug_AuthControl.Value && Time.time - _lastLookupLogTime >= 2f) { NjordDebug.Debug($"[Tracker] Lookup: {((Object)val).name} ({uid}) → controller={value}"); _lastLookupLogTime = Time.time; } return value; } if (NjordConfig.Debug_Enable.Value && NjordConfig.Debug_AuthControl.Value && Time.time - _lastLookupLogTime >= 2f) { NjordDebug.Debug($"[Tracker] Lookup: {((Object)val).name} ({uid}) → no entry"); _lastLookupLogTime = Time.time; } return 0L; } private static bool LocalPlayerHasControl() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null) { return false; } long playerID = Player.m_localPlayer.GetPlayerID(); if (playerID == 0L) { return false; } foreach (KeyValuePair item in ControlMap) { if (item.Value == playerID) { if (NjordConfig.Debug_Enable.Value && NjordConfig.Debug_AuthControl.Value) { NjordDebug.Debug($"[Tracker] LocalPlayerHasControl → TRUE (ship {item.Key})"); } return true; } } if (NjordConfig.Debug_Enable.Value && NjordConfig.Debug_AuthControl.Value) { NjordDebug.Debug("[Tracker] LocalPlayerHasControl → FALSE"); } return false; } private static void RecalculateHudState() { bool flag = (Object)(object)Player.m_localPlayer != (Object)null; bool flag2 = LocalPlayerHasControl(); bool value = Plugin.HudEnabledByUser.Value; bool flag3 = flag && flag2 && value; if (ShouldShowHud != flag3 && NjordConfig.Debug_Enable.Value && NjordConfig.Debug_AuthControl.Value) { NjordDebug.Debug($"[Tracker] HUD state changed → {flag3} (hasPlayer={flag}, hasControl={flag2}, hudEnabled={value})"); } ShouldShowHud = flag3; } public static void SetControl(Ship ship, long playerID) { //IL_002f: 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_003a: 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) if ((Object)(object)ship == (Object)null) { return; } ZNetView component = ((Component)ship).GetComponent(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return; } ZDO zDO = component.GetZDO(); if (zDO != null) { ZDOID uid = zDO.m_uid; ControlMap[uid] = playerID; CurrentController = playerID; Njord_Telemetry.ClearErrors(); if (NjordConfig.Debug_Enable.Value && NjordConfig.Debug_AuthControl.Value) { NjordDebug.Debug($"[Tracker] SetControl: ship={((Object)ship).name} ({uid}) → player={playerID}"); } RecalculateHudState(); } } public static void ClearControl(Ship ship) { //IL_002f: 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_003a: 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_00c7: 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) if ((Object)(object)ship == (Object)null) { return; } ZNetView component = ((Component)ship).GetComponent(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return; } ZDO zDO = component.GetZDO(); if (zDO == null) { return; } ZDOID uid = zDO.m_uid; ControlMap.Remove(uid); WindAngleMap.Remove(uid); Player localPlayer = Player.m_localPlayer; long num = ((localPlayer != null) ? localPlayer.GetPlayerID() : 0); if (num == CurrentController) { if (NjordConfig.Debug_Enable.Value && NjordConfig.Debug_AuthControl.Value) { NjordDebug.Debug($"[Tracker] ClearControl: local player lost control of {((Object)ship).name} ({uid})"); } CurrentController = 0L; } else if (NjordConfig.Debug_Enable.Value && NjordConfig.Debug_AuthControl.Value) { NjordDebug.Debug($"[Tracker] ClearControl: removed entry for {((Object)ship).name} ({uid}), local player unaffected"); } RecalculateHudState(); } public static void UpdateController(long controller, float dt) { if (NjordConfig.Debug_Enable.Value && NjordConfig.Debug_AuthControl.Value && Time.time - _lastLookupLogTime >= 2f) { NjordDebug.Debug($"[AuthoritySync] UpdateController: controller={controller}, dt={dt:F4}"); } long num = (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : 0); if (controller == 0L || (num != 0L && controller == num)) { CurrentController = controller; } if (controller != 0L) { ReadyTimer += dt; if (ReadyTimer >= 0.35f) { SteeringGateReady = true; } } else { ReadyTimer = 0f; SteeringGateReady = false; } RecalculateHudState(); } } public static class NjordDebug { private static bool _startupPrinted; private static bool IsEnabled() { try { return NjordConfig.Debug_Enable != null && NjordConfig.Debug_Enable.Value; } catch { return false; } } public static void Startup() { if (!_startupPrinted) { _startupPrinted = true; if (Plugin.Log != null) { Plugin.Log.LogInfo((object)"⚓ [Njord] The longship wakes. The sea remembers your hand."); } } } public static void Info(string msg) { if (IsEnabled()) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Njord] " + msg)); } } } public static void Debug(string msg) { if (IsEnabled()) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[Njord] " + msg)); } } } public static void Warn(string msg) { if (IsEnabled()) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Njord] " + msg)); } } } public static void Log(string msg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Njord] " + msg)); } } public static void Error(string msg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)("[Njord] " + msg)); } } } [BepInPlugin("wubarrk.njord", "Njord", "1.3.0")] public class Plugin : BaseUnityPlugin { internal static Plugin Instance; internal static Harmony Harmony; internal static ManualLogSource Log; public static ConfigEntry HudPositionX; public static ConfigEntry HudPositionY; public static ConfigEntry HudEnabledByUser; private bool _hudCreated; public static bool OdinShipDetected { get; private set; } private void Awake() { //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; NjordDebug.Startup(); Log.LogInfo((object)"The sea stirs. The runes awaken."); OdinShipDetected = Chainloader.PluginInfos.ContainsKey("marlthon.OdinShip"); if (OdinShipDetected) { Log.LogInfo((object)"Njord smiles upon the shipwrights: OdinShip detected! Taking the helm."); } else { Log.LogInfo((object)"Njord watches the waves: OdinShip not detected. We sail on."); } NjordConfig.Bind(((BaseUnityPlugin)this).Config); HudPositionX = ((BaseUnityPlugin)this).Config.Bind("HUD", "HudPositionX", 40f, "Njord HUD X position."); HudPositionY = ((BaseUnityPlugin)this).Config.Bind("HUD", "HudPositionY", 200f, "Njord HUD Y position."); HudEnabledByUser = ((BaseUnityPlugin)this).Config.Bind("HUD", "HudEnabled", true, "If false, Njord HUD is hidden (F7 toggles)."); NjordSync.Initialize(); Harmony = new Harmony("wubarrk.njord"); NjordPatchCaller.ApplyPatches(); NjordHudManager.Initialize(); RegisterConsoleCommands(); if (NjordConfig.Debug_Enable.Value) { Log.LogInfo((object)"Njord console commands registered (including njord.dumpvfx)."); try { Version version = Assembly.GetExecutingAssembly().GetName().Version; Log.LogInfo((object)$"Njord DLL version: {version}"); } catch { } } Log.LogInfo((object)"Njord, god of the sea, obeys your command."); } private void Update() { if (!_hudCreated && (Object)(object)ZNet.instance != (Object)null) { _hudCreated = true; NjordHudManager.CreateHud(); } if (Input.GetKeyDown((KeyCode)289)) { if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { NjordSync.ServerReloadAndBroadcast(); NjordDebug.Info("Njord config reloaded (server) and broadcast to all clients."); MessageHud instance = MessageHud.instance; if (instance != null) { instance.ShowMessage((MessageType)1, "Njord config reloaded (server)", 0, (Sprite)null, false); } } else { NjordSync.Client_RequestConfigUpdate(); NjordDebug.Info("Njord config update request sent to server."); MessageHud instance2 = MessageHud.instance; if (instance2 != null) { instance2.ShowMessage((MessageType)1, "Njord config update request sent", 0, (Sprite)null, false); } } } if (Input.GetKeyDown((KeyCode)288)) { HudEnabledByUser.Value = !HudEnabledByUser.Value; } } private void OnGUI() { NjordHudManager.OnGUI(); } private void RegisterConsoleCommands() { ConsoleCommand("njord.reload", delegate { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { Log.LogWarning((object)"njord.reload can only be run on the server."); } else { NjordSync.ServerReloadAndBroadcast(); Log.LogInfo((object)"Njord config reloaded from disk and broadcast to all clients."); } }); ConsoleCommand("njord.push", delegate { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { Log.LogWarning((object)"njord.push can only be run on the server."); } else { typeof(NjordSync).GetMethod("ServerReloadAndBroadcast", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null); Log.LogInfo((object)"Njord runtime config pushed to all clients."); } }); ConsoleCommand("njord.dumpvfx", delegate { try { NjordRuneSpriteTrail.DumpEmitters(); try { NjordRunePiggyback.DumpEmitters(); } catch { } Log.LogInfo((object)"Njord: dumped VFX emitter state to Njord debug log."); try { MessageHud instance = MessageHud.instance; if (instance != null) { instance.ShowMessage((MessageType)1, "Njord: VFX dump written to log.", 0, (Sprite)null, false); } } catch { } } catch (Exception ex) { Log.LogWarning((object)("njord.dumpvfx failed: " + ex.Message)); } }); ConsoleCommand("njord.vfx.orientation", delegate(string[] args) { try { if (args.Length < 1) { Log.LogInfo((object)"Usage: njord.vfx.orientation "); } else { string text = args[0].ToLowerInvariant(); switch (text) { case "flat": NjordRunePiggyback_SetOrientation("Flat"); break; case "flatinv": NjordRunePiggyback_SetOrientation("FlatInverted"); break; case "upright": NjordRunePiggyback_SetOrientation("Upright"); break; case "camera": NjordRunePiggyback_SetOrientation("CameraFacing"); break; default: Log.LogInfo((object)"Unknown orientation. Valid: flat, flatinv, upright, camera"); return; } Log.LogInfo((object)("Njord: set VFX spawn orientation -> " + text)); } } catch (Exception ex) { Log.LogWarning((object)("njord.vfx.orientation failed: " + ex.Message)); } }); ConsoleCommand("njord.testtrail", delegate { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_0058: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_0080: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) try { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { Log.LogWarning((object)"njord.testtrail: no local player"); } else { Transform transform = ((Component)localPlayer).transform; NjordRuntimeConfig njordRuntimeConfig = NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig(); Color vFX_Color = njordRuntimeConfig.VFX_Color; float num = 0.6f; Vector3 val = transform.position - transform.forward * 1f + Vector3.up * 0.5f; for (int i = 0; i < 8; i++) { Vector3 pos = val - transform.forward * ((float)i * num); NjordRunePiggyback.SpawnAtWorldPosition(pos, vFX_Color); } Log.LogInfo((object)"njord.testtrail: spawned test trail behind player"); } } catch (Exception ex) { Log.LogWarning((object)("njord.testtrail failed: " + ex.Message)); } }); if (NjordConfig.Debug_Enable.Value) { Log.LogInfo((object)"Registered console command 'njord.dumpvfx'."); } } public static void NjordRunePiggyback_SetOrientation(string name) { try { Type typeFromHandle = typeof(NjordRunePiggyback); Type nestedType = typeFromHandle.GetNestedType("OrientationMode", BindingFlags.Public | BindingFlags.NonPublic); if (!(nestedType == null)) { object value = Enum.Parse(nestedType, name); FieldInfo field = typeFromHandle.GetField("_spawnOrientation", BindingFlags.Static | BindingFlags.NonPublic); if (field != null) { field.SetValue(null, value); } } } catch { } } private void ConsoleCommand(string name, Action action) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0028: 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_00fd: Expected O, but got Unknown //IL_00f8: Unknown result type (might be due to invalid IL or missing references) try { new ConsoleCommand(name, "", (ConsoleEvent)delegate(ConsoleEventArgs args) { action(args.Args); }, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); if (NjordConfig.Debug_Enable.Value) { Log.LogInfo((object)("Registered console command '" + name + "' (immediate).")); } return; } catch (Exception ex) { if (NjordConfig.Debug_Enable.Value) { Log.LogInfo((object)("Immediate registration of console command '" + name + "' failed, will wait for Terminal: " + ex.Message)); } } Type typeFromHandle = typeof(Terminal); object obj = null; FieldInfo field = typeFromHandle.GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { obj = field.GetValue(null); } else { PropertyInfo property = typeFromHandle.GetProperty("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { obj = property.GetValue(null); } } if (obj != null) { try { new ConsoleCommand(name, "", (ConsoleEvent)delegate(ConsoleEventArgs args) { action(args.Args); }, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); if (NjordConfig.Debug_Enable.Value) { Log.LogInfo((object)("Registered console command '" + name + "' after Terminal detected via reflection.")); } return; } catch (Exception ex2) { Log.LogWarning((object)("Failed to register console command '" + name + "' after reflection detect: " + ex2.Message)); return; } } ((MonoBehaviour)this).StartCoroutine(WaitAndRegister(name, action)); } private IEnumerator WaitAndRegister(string name, Action action) { float timeout = 10f; float start = Time.time; ConsoleEvent val = default(ConsoleEvent); while (Time.time - start < timeout) { Type typeFromHandle = typeof(Terminal); FieldInfo field = typeFromHandle.GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); object obj = null; if (field != null) { obj = field.GetValue(null); } else { PropertyInfo property = typeFromHandle.GetProperty("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { obj = property.GetValue(null); } } if (obj != null) { try { ConsoleEvent obj2 = val; if (obj2 == null) { ConsoleEvent val2 = delegate(ConsoleEventArgs args) { action(args.Args); }; ConsoleEvent val3 = val2; val = val2; obj2 = val3; } new ConsoleCommand(name, "", obj2, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); if (NjordConfig.Debug_Enable.Value) { Log.LogInfo((object)("Registered console command '" + name + "' after Terminal became available.")); } yield break; } catch (Exception ex) { Log.LogWarning((object)("Failed to register console command '" + name + "' after wait: " + ex.Message)); yield break; } } yield return null; } Log.LogWarning((object)("Timed out waiting for Terminal to register console command '" + name + "'.")); } } public static class NjordRunePiggyback { public enum OrientationMode { Flat, FlatInverted, Upright, CameraFacing } private class Emitter : MonoBehaviour { private Transform _stern; private Color _color = Color.white; private float _spacing = 0.6f; private Vector3 _lastSpawnPos = Vector3.zero; private Action _returnToPool; private Sprite _sprite; private Texture2D _tex; private bool _active = true; private ParticleSystem _wakePS; private Particle[] _buffer = (Particle[])(object)new Particle[512]; private float _wakeInterval = 0.1f; private float _lastWake; private float _lastSternTime; private Vector3 _lastSternPos = Vector3.zero; private float _minSpeed = 0.5f; private float _lastLogTime = -10f; public void Initialize(Transform stern, Color color, float rateMultiplier, Action returnToPool, Sprite sprite, Texture2D tex) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) _stern = stern; _color = color; _returnToPool = returnToPool; _sprite = sprite; _tex = tex; _spacing = 0.6f; _wakeInterval = 0.1f; _minSpeed = 0.5f; try { if (NjordConfig.Debug_Enable != null && NjordConfig.Debug_Enable.Value) { _minSpeed = Mathf.Min(_minSpeed, 0.1f); } } catch { } _lastSpawnPos = (((Object)(object)_stern != (Object)null) ? (_stern.TransformPoint(new Vector3(0f, -0.25f, -1f)) - Vector3.one * 1000f) : Vector3.zero); _lastSternPos = (((Object)(object)_stern != (Object)null) ? _stern.position : Vector3.zero); _lastSternTime = Time.time; _active = true; try { ParticleSystem[] componentsInChildren = ((Component)_stern).GetComponentsInChildren(true); ParticleSystem val = null; ParticleSystem[] array = componentsInChildren; foreach (ParticleSystem val2 in array) { if (!((Object)(object)val2 == (Object)null)) { string text = ((Object)((Component)val2).gameObject).name.ToLowerInvariant(); if (text.Contains("wake") || text.Contains("trail") || text.Contains("speed") || text.Contains("mask")) { val = val2; break; } } } if ((Object)(object)val == (Object)null && componentsInChildren.Length != 0) { val = componentsInChildren[0]; } _wakePS = val; if (IsDebugEnabled()) { try { Plugin.Log.LogInfo((object)("[VFX-Piggyback] Emitter init: wakePS=" + (((Object)(object)_wakePS != (Object)null) ? ((Object)((Component)_wakePS).gameObject).name : "(none)"))); } catch { } } if (!((Object)(object)_wakePS == (Object)null)) { return; } _active = false; if (IsDebugEnabled()) { try { Plugin.Log.LogInfo((object)"[VFX-Piggyback] No wake PS found; emitter disabled (sprite trail used instead)"); return; } catch { return; } } } catch { } } public void UpdateParams(Transform stern, Color color, float rateMultiplier) { //IL_0012: 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) _stern = stern ?? _stern; _color = color; _spacing = 0.6f; } public void SetActive(bool v) { _active = v; } private void Update() { //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0250: 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_025a: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0207: 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_0216: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_01be: 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_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: 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_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: 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) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) if (!_active || (Object)(object)_stern == (Object)null) { return; } NjordRuntimeConfig njordRuntimeConfig = NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig(); float time = Time.time; float num = Mathf.Max(1E-06f, time - _lastSternTime); float num2 = Vector3.Distance(_stern.position, _lastSternPos) / num; _lastSternPos = _stern.position; _lastSternTime = time; if ((Object)(object)_wakePS != (Object)null) { if (Time.time - _lastWake < _wakeInterval) { return; } _lastWake = Time.time; int particles = _wakePS.GetParticles(_buffer); if (IsDebugEnabled()) { try { Plugin.Log.LogDebug((object)$"[VFX-Piggyback] Wake sample: count={particles} speed={num2} minSpeed={_minSpeed}"); } catch { } } if (particles <= 0) { return; } int num3 = Mathf.Min(4, particles); int num4 = Mathf.Max(1, particles / num3); for (int i = 0; i < particles; i += num4) { Vector3 worldPos = ((Component)_wakePS).transform.TransformPoint(((Particle)(ref _buffer[i])).position); if (num2 < _minSpeed) { if (!(Time.time - _lastLogTime > 1f)) { continue; } if (IsDebugEnabled()) { try { Plugin.Log.LogInfo((object)$"[VFX-Piggyback] Skipping wake spawn: speed {num2} < min {_minSpeed}"); } catch { } } _lastLogTime = Time.time; } else { TrySpawnAt(worldPos); } } return; } Vector3 val = _stern.TransformPoint(new Vector3(0f, -0.25f, -1f)); Vector3 val2 = val; int num5 = 0; try { num5 = ((LayerMask.NameToLayer("Water") >= 0) ? (1 << LayerMask.NameToLayer("Water")) : 0); } catch { num5 = 0; } if (num5 == 0) { num5 = -1; } if (num5 != 0) { Vector3 val3 = val + Vector3.up * 2f; RaycastHit val4 = default(RaycastHit); if (Physics.Raycast(val3, Vector3.down, ref val4, 10f, num5)) { val2.y = ((RaycastHit)(ref val4)).point.y + 0.02f; } } Vector3 val5 = val2 - _lastSpawnPos; for (float num6 = Vector3.Dot(val5, _stern.forward); num6 >= _spacing; num6 = Vector3.Dot(val5, _stern.forward)) { _lastSpawnPos += _stern.forward * _spacing; Vector3 lastSpawnPos = _lastSpawnPos; lastSpawnPos.y = val2.y; if (num2 >= _minSpeed) { TrySpawnAt(lastSpawnPos); } else if (Time.time - _lastLogTime > 1f) { if (IsDebugEnabled()) { try { Plugin.Log.LogInfo((object)$"[VFX-Piggyback] Skipping trail spawn: speed {num2} < min {_minSpeed}"); } catch { } } _lastLogTime = Time.time; } val5 = val2 - _lastSpawnPos; } } public bool TrySpawnAt(Vector3 worldPos) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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) //IL_0086: 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) if (!_active || (Object)(object)_stern == (Object)null) { return false; } float num = Vector3.Distance(worldPos, _lastSpawnPos); if (num < _spacing) { if (Time.time - _lastLogTime > 1f) { if (IsDebugEnabled()) { try { Plugin.Log.LogInfo((object)$"[VFX-Piggyback] TrySpawnAt rejected: dist {num} < spacing {_spacing}"); } catch { } } _lastLogTime = Time.time; } return false; } _lastSpawnPos = worldPos; SpawnVisual(worldPos, _color, _sprite, _tex, null, _stern); return true; } private void DoSpawn(Vector3 pos) { //IL_0000: 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) SpawnVisual(pos, _color, _sprite, _tex, null, _stern); } } private class RuneFader : MonoBehaviour { private SpriteRenderer _sr; private Vector3 _vel; private float _life; private float _age; private float _startScale; private Color _startColor; private Action _onFinish; public void Init(Action onFinish) { _sr = ((Component)this).GetComponent(); _onFinish = onFinish; } public void Play(Vector3 velocity, float life, float startScale, Color color) { //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_0035: 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_0050: 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_006d: Unknown result type (might be due to invalid IL or missing references) _vel = velocity; _life = Mathf.Max(0.01f, life); _age = 0f; _startScale = Mathf.Max(0.01f, startScale); _startColor = color; if ((Object)(object)_sr != (Object)null) { _sr.color = color; ((Component)_sr).transform.localScale = Vector3.one * _startScale; } } private void Update() { //IL_001b: 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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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_005d: 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) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) float deltaTime = Time.deltaTime; _age += deltaTime; Transform transform = ((Component)this).transform; transform.position += _vel * deltaTime; float num = Mathf.Clamp01(_age / _life); if ((Object)(object)_sr != (Object)null) { Color startColor = _startColor; startColor.a = Mathf.Lerp(_startColor.a, 0f, num); _sr.color = startColor; float num2 = Mathf.Lerp(_startScale, _startScale * 0.4f, num); ((Component)_sr).transform.localScale = Vector3.one * num2; } if (_age >= _life) { _onFinish?.Invoke(((Component)this).gameObject); } } } private const int POOL_INITIAL = 64; private const int POOL_MAX = 1024; private static Queue _pool = new Queue(); private static GameObject _poolRoot; private static Texture2D _runeTex; private static Sprite _runeSprite; private static Mesh _debugQuadMesh; private static bool _inited = false; private static OrientationMode _spawnOrientation = OrientationMode.Flat; private static readonly Dictionary _emitters = new Dictionary(); private static bool IsDebugEnabled() { try { NjordRuntimeConfig njordRuntimeConfig = NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig(); if (njordRuntimeConfig != null && njordRuntimeConfig.Debug_Enable) { return true; } } catch { } try { if (NjordConfig.Debug_Enable != null && NjordConfig.Debug_Enable.Value) { return true; } } catch { } return false; } private static void EnsureInit() { //IL_0032: 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) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_0073: 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_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) if (_inited) { return; } _inited = true; _runeTex = NjordRuneTextureGenerator.GenerateRune((Color)(((??)NjordConfig.VFX_Color?.Value) ?? new Color(0.3f, 0.6f, 1f, 1f))); if ((Object)(object)_runeTex != (Object)null) { _runeSprite = Sprite.Create(_runeTex, new Rect(0f, 0f, (float)((Texture)_runeTex).width, (float)((Texture)_runeTex).height), new Vector2(0.5f, 0.5f), 100f); } else { Texture2D val = new Texture2D(16, 16, (TextureFormat)4, false); Color[] array = (Color[])(object)new Color[256]; for (int i = 0; i < array.Length; i++) { array[i] = Color.white; } val.SetPixels(array); val.Apply(false); _runeTex = val; _runeSprite = Sprite.Create(_runeTex, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); } _poolRoot = new GameObject("NjordRunePiggybackPool"); Object.DontDestroyOnLoad((Object)(object)_poolRoot); for (int j = 0; j < 64; j++) { _pool.Enqueue(CreatePooledGO()); } } private static Mesh GetOrCreateDebugQuadMesh() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: 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_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) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_debugQuadMesh != (Object)null) { return _debugQuadMesh; } Mesh val = new Mesh(); ((Object)val).name = "Njord_DebugQuadMesh"; Vector3[] vertices = (Vector3[])(object)new Vector3[4] { new Vector3(-0.5f, 0f, -0.5f), new Vector3(0.5f, 0f, -0.5f), new Vector3(0.5f, 0f, 0.5f), new Vector3(-0.5f, 0f, 0.5f) }; int[] triangles = new int[6] { 0, 1, 2, 0, 2, 3 }; Vector2[] uv = (Vector2[])(object)new Vector2[4] { new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(0f, 1f) }; val.vertices = vertices; val.triangles = triangles; val.uv = uv; val.RecalculateNormals(); val.RecalculateBounds(); _debugQuadMesh = val; return _debugQuadMesh; } private static GameObject CreatePooledGO() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown //IL_00f3: 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) GameObject val = new GameObject("NjordRune"); val.transform.SetParent(_poolRoot.transform, false); SpriteRenderer val2 = val.AddComponent(); val2.sprite = _runeSprite; ((Renderer)val2).sortingLayerName = "Default"; ((Renderer)val2).sortingOrder = 5000; ((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0; try { Shader val3 = Shader.Find("Sprites/Default"); if ((Object)(object)val3 != (Object)null) { Material val4 = new Material(val3); if (val4.HasProperty("_MainTex") && (Object)(object)_runeTex != (Object)null) { val4.SetTexture("_MainTex", (Texture)(object)_runeTex); } ((Renderer)val2).material = val4; } } catch { } RuneFader runeFader = val.AddComponent(); runeFader.Init(ReturnToPool); try { GameObject val5 = new GameObject("Njord_DebugQuad"); val5.transform.SetParent(val.transform, false); val5.transform.localPosition = Vector3.zero; val5.transform.localRotation = Quaternion.identity; MeshFilter val6 = val5.AddComponent(); val6.mesh = GetOrCreateDebugQuadMesh(); MeshRenderer val7 = val5.AddComponent(); ((Renderer)val7).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)val7).receiveShadows = false; ((Renderer)val7).enabled = false; } catch { } val.SetActive(false); return val; } private static GameObject GetFromPool() { if (!_inited) { EnsureInit(); } if (_pool.Count > 0) { return _pool.Dequeue(); } if (_pool.Count + 1 <= 1024) { return CreatePooledGO(); } return null; } private static void ReturnToPool(GameObject go) { if (!((Object)(object)go == (Object)null)) { go.SetActive(false); go.transform.SetParent(_poolRoot.transform, false); if (_pool.Count < 1024) { _pool.Enqueue(go); } else { Object.Destroy((Object)(object)go); } } } public static void SpawnBurst(Vector3 pos, Color color, int count) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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) //IL_009c: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_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_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: 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_00ea: Unknown result type (might be due to invalid IL or missing references) if (!NjordConfig.VFX_Enable.Value) { return; } EnsureInit(); float life = 2.5f; float startScale = 1.125f; for (int i = 0; i < Mathf.Max(1, count); i++) { GameObject fromPool = GetFromPool(); if (!((Object)(object)fromPool == (Object)null)) { SpriteRenderer component = fromPool.GetComponent(); if ((Object)(object)component != (Object)null) { component.sprite = _runeSprite; component.color = color; } fromPool.transform.position = pos + Random.insideUnitSphere * 0.35f; fromPool.transform.rotation = Quaternion.Euler(90f, Random.Range(0f, 360f), 0f); fromPool.SetActive(true); RuneFader component2 = fromPool.GetComponent(); if ((Object)(object)component2 != (Object)null) { Vector3 velocity = (Random.onUnitSphere + Vector3.back * 1.5f) * 0.4f; component2.Play(velocity, life, startScale, color); } } } } public static void StartTrailForShip(object ship, Transform stern, Color color, float rateMultiplier = 1f) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0086: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (ship == null || (Object)(object)stern == (Object)null || !NjordConfig.VFX_Enable.Value) { return; } EnsureInit(); if (_emitters.TryGetValue(ship, out var value) && (Object)(object)value != (Object)null) { value.SetActive(v: true); value.UpdateParams(stern, color, rateMultiplier); return; } GameObject val = new GameObject($"NjordRuneEmitter_{ship.GetHashCode()}"); val.transform.SetParent(stern, true); val.transform.position = stern.TransformPoint(new Vector3(0f, -0.25f, -1f)); Emitter emitter = val.AddComponent(); try { emitter.Initialize(stern, color, rateMultiplier, ReturnToPool, _runeSprite, _runeTex); _emitters[ship] = emitter; if (IsDebugEnabled()) { try { NjordDebug.Info($"[VFX-Piggyback] Created emitter for ship {ship} (stern={((stern != null) ? ((Object)stern).name : null)})"); } catch { } } if (IsDebugEnabled()) { try { Plugin.Log.LogInfo((object)$"[VFX-Piggyback] Created emitter for ship {ship} (stern={((stern != null) ? ((Object)stern).name : null)})"); return; } catch { return; } } } catch (Exception ex) { if (IsDebugEnabled()) { try { Plugin.Log.LogWarning((object)$"[VFX-Piggyback] Failed to initialize emitter for ship {ship}: {ex.Message}"); } catch { } } if (IsDebugEnabled()) { try { NjordDebug.Warn($"[VFX-Piggyback] Failed to initialize emitter for ship {ship}: {ex.Message}"); } catch { } } try { if ((Object)(object)emitter != (Object)null && (Object)(object)((Component)emitter).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)emitter).gameObject); } } catch { } } } public static void StopTrailForShip(object ship) { if (ship != null && _emitters.TryGetValue(ship, out var value) && (Object)(object)value != (Object)null) { value.SetActive(v: false); } } public static void RemoveEmitterForShip(object ship) { if (ship == null) { return; } if (_emitters.TryGetValue(ship, out var value) && (Object)(object)value != (Object)null) { try { if ((Object)(object)((Component)value).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)value).gameObject); } } catch { } } _emitters.Remove(ship); } public static void DumpEmitters() { try { if (IsDebugEnabled()) { try { Plugin.Log.LogInfo((object)$"[VFX-Piggyback] Emitters: count={_emitters.Count} pool={_pool.Count}"); } catch { } } foreach (KeyValuePair emitter in _emitters) { object key = emitter.Key; Emitter value = emitter.Value; if ((Object)(object)value == (Object)null) { if (IsDebugEnabled()) { try { Plugin.Log.LogInfo((object)$"[VFX-Piggyback] Emitter for {key}: null"); } catch { } } } else if (IsDebugEnabled()) { try { ManualLogSource log = Plugin.Log; object arg = ((Behaviour)value).isActiveAndEnabled; GameObject gameObject = ((Component)value).gameObject; log.LogInfo((object)$"[VFX-Piggyback] Emitter for {key}: active={arg} go={((gameObject != null) ? ((Object)gameObject).name : null)}"); } catch { } } } } catch { } } public static void SpawnAtWorldPosition(Vector3 pos, Color color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) SpawnVisual(pos, color, _runeSprite, _runeTex, null, null); } private static void SpawnVisual(Vector3 pos, Color color, Sprite sprite, Texture2D tex, Vector3? velocityOverride, Transform stern) { //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_03ca: 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_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Unknown result type (might be due to invalid IL or missing references) //IL_042e: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: 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_0217: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_025c: 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_0299: Unknown result type (might be due to invalid IL or missing references) //IL_029d: 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_00db: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_036a: Unknown result type (might be due to invalid IL or missing references) //IL_0371: Expected O, but got Unknown //IL_03aa: Unknown result type (might be due to invalid IL or missing references) if (!NjordConfig.VFX_Enable.Value) { return; } EnsureInit(); GameObject fromPool = GetFromPool(); if ((Object)(object)fromPool == (Object)null) { return; } SpriteRenderer component = fromPool.GetComponent(); if ((Object)(object)component != (Object)null) { component.sprite = sprite ?? _runeSprite; component.color = color; ((Renderer)component).sortingLayerName = "Default"; ((Renderer)component).sortingOrder = 32767; } fromPool.transform.position = pos; try { switch (_spawnOrientation) { case OrientationMode.Flat: fromPool.transform.rotation = Quaternion.Euler(90f, Random.Range(0f, 360f), 0f); break; case OrientationMode.FlatInverted: fromPool.transform.rotation = Quaternion.Euler(-90f, Random.Range(0f, 360f), 0f); break; case OrientationMode.Upright: fromPool.transform.rotation = Quaternion.Euler(0f, Random.Range(0f, 360f), 0f); break; case OrientationMode.CameraFacing: if ((Object)(object)Camera.main != (Object)null) { fromPool.transform.rotation = Quaternion.LookRotation(((Component)Camera.main).transform.forward); } else { fromPool.transform.rotation = Quaternion.Euler(90f, Random.Range(0f, 360f), 0f); } break; default: fromPool.transform.rotation = Quaternion.Euler(90f, Random.Range(0f, 360f), 0f); break; } } catch { fromPool.transform.rotation = Quaternion.Euler(90f, Random.Range(0f, 360f), 0f); } fromPool.SetActive(true); float life = 2.5f; float startScale = 0.75f; Vector3 velocity = (velocityOverride.HasValue ? velocityOverride.Value : ((!((Object)(object)stern != (Object)null)) ? (Vector3.back * 0.6f + Random.insideUnitSphere * 0.2f) : (-stern.forward * Random.Range(0.6f, 1.2f) + stern.right * Random.Range(-0.25f, 0.25f) + stern.up * Random.Range(-0.05f, 0.05f)))); RuneFader component2 = fromPool.GetComponent(); if ((Object)(object)component2 != (Object)null) { try { component2.Play(velocity, life, startScale, color); } catch { try { component2.Play(velocity, life, startScale, color); } catch { } } } try { fromPool.layer = 0; SpriteRenderer component3 = fromPool.GetComponent(); if ((Object)(object)component3 != (Object)null) { ((Renderer)component3).sortingOrder = 32767; } } catch { } try { if (IsDebugEnabled()) { Transform val = fromPool.transform.Find("Njord_DebugQuad"); if ((Object)(object)val != (Object)null) { MeshRenderer component4 = ((Component)val).GetComponent(); if ((Object)(object)component4 != (Object)null) { if ((Object)(object)((Renderer)component4).sharedMaterial == (Object)null) { Shader val2 = Shader.Find("Unlit/Texture") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Sprites/Default"); if ((Object)(object)val2 != (Object)null) { try { Material val3 = new Material(val2); if (val3.HasProperty("_MainTex") && (Object)(object)tex != (Object)null) { val3.SetTexture("_MainTex", (Texture)(object)tex); } if (val3.HasProperty("_Color")) { val3.SetColor("_Color", color); } ((Renderer)component4).material = val3; } catch { } } } val.localScale = Vector3.one * 0.3f; ((Renderer)component4).enabled = true; try { ((Renderer)component4).material.renderQueue = 5000; } catch { } if (IsDebugEnabled()) { try { Plugin.Log.LogInfo((object)$"[VFX-Piggyback] Spawned debug quad at {pos}"); } catch { } } } } } } catch { } if (!IsDebugEnabled()) { return; } try { Plugin.Log.LogInfo((object)$"[VFX-Piggyback] DoSpawn at {pos}"); } catch { } } } public static class NjordRuneSpriteTrail { private class Emitter : MonoBehaviour { private Transform _stern; private Color _color = Color.white; private float _life = 1.2f; private float _scale = 0.7f; private float _spacing = 0.6f; private Vector3 _lastSpawnPos; private Action _returnToPool; private Sprite _sprite; private bool _active = true; private bool _useTelemetry; private float _cachedWaterY = float.MinValue; private float _lastWaterSampleTime = -10f; private const float WATER_SAMPLE_INTERVAL = 0.1f; private const float WATER_SURFACE_OFFSET = 0.02f; private int _waterMask; private bool _usedAllLayersFallback; private bool _loggedLayerResolution; private float _lastSpawnDebugLog = -10f; private const float SPAWN_DEBUG_LOG_INTERVAL = 1f; private bool _debugNotified; public void Initialize(Transform stern, Color color, float rateMultiplier, Action returnToPool, Sprite sprite, bool useTelemetry) { //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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0260: 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) _stern = stern; _useTelemetry = useTelemetry; _color = color; _sprite = sprite; _returnToPool = returnToPool; _active = true; NjordRuntimeConfig njordRuntimeConfig = NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig(); _life = 2.5f; _scale = 0.41343752f; _spacing = 0.49980003f; _lastSpawnPos = (((Object)(object)_stern != (Object)null) ? _stern.position : Vector3.zero); if (_useTelemetry && (Object)(object)_stern != (Object)null) { try { NjordDebug.Debug($"[VFX-Sprite] Telemetry emitter seeded cachedY={_cachedWaterY = GetRealisticTelemetryWaterY():F2}"); } catch { } } string text = null; string text2 = null; List list = new List(); if (!string.IsNullOrEmpty(text)) { list.Add(text); } list.AddRange(new string[7] { "Water", "water", "WaterSurface", "Ocean", "Sea", "SeaWater", "WaterPlane" }); foreach (string item in list) { if (!string.IsNullOrEmpty(item)) { int num = LayerMask.NameToLayer(item); if (num >= 0) { _waterMask = 1 << num; text2 = item; _usedAllLayersFallback = false; break; } } } if (text2 == null) { ConfigEntry debug_Enable = NjordConfig.Debug_Enable; if (debug_Enable != null && debug_Enable.Value) { _waterMask = -1; _usedAllLayersFallback = true; } else { _waterMask = 0; _usedAllLayersFallback = false; } } if (!_loggedLayerResolution) { string arg = text2 ?? (_usedAllLayersFallback ? "(AllLayers)" : "(none)"); NjordDebug.Debug($"[VFX-Sprite] Resolved water layer -> '{arg}' mask={_waterMask}"); _loggedLayerResolution = true; } if (_useTelemetry || !((Object)(object)_stern != (Object)null)) { return; } try { int num2 = _waterMask; if (num2 == 0) { ConfigEntry debug_Enable2 = NjordConfig.Debug_Enable; if (debug_Enable2 != null && debug_Enable2.Value) { num2 = -1; } } RaycastHit val = default(RaycastHit); if (num2 != 0 && (Physics.Raycast(_stern.position, Vector3.down, ref val, 10f, num2) || Physics.Raycast(_stern.position, Vector3.up, ref val, 10f, num2))) { _cachedWaterY = ((RaycastHit)(ref val)).point.y; NjordDebug.Debug($"[VFX-Sprite] Immediate water sample cachedY={_cachedWaterY:F2}"); } } catch { } } public void UpdateParams(Transform stern, Color color, float rateMultiplier) { //IL_0012: 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) _stern = stern ?? _stern; _color = color; _spacing = 0.6f; } public void SetActive(bool v) { _active = v; } private float GetRealisticTelemetryWaterY() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) float num = (((Object)(object)_stern != (Object)null) ? _stern.position.y : 0f); float waterLevel = Njord_Telemetry.WaterLevel; float boatY = Njord_Telemetry.BoatY; if (float.IsNaN(waterLevel) || float.IsInfinity(waterLevel)) { return num; } float num2 = waterLevel; if ((Object)(object)_stern != (Object)null && !float.IsNaN(boatY) && !float.IsInfinity(boatY) && Mathf.Abs(boatY) > 0.0001f) { num2 = waterLevel + (num - boatY); } return Mathf.Clamp(num2, num - 3f, num + 3f); } private void Update() { //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_01af: 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_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0216: 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_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_0246: 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_025b: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: 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 (!_active) { return; } if ((Object)(object)_stern == (Object)null) { _active = false; NjordDebug.Warn("[VFX-Sprite] Emitter stern destroyed; deactivating."); return; } if (_useTelemetry) { try { float waterLevel = Njord_Telemetry.WaterLevel; float boatY = Njord_Telemetry.BoatY; if (!float.IsNaN(waterLevel) && !float.IsInfinity(waterLevel)) { float num = waterLevel; if (!float.IsNaN(boatY) && Mathf.Abs(boatY) > 0.0001f) { num = waterLevel + (_stern.position.y - boatY); } _cachedWaterY = Mathf.Clamp(num, _stern.position.y - 3f, _stern.position.y + 3f); } } catch { } } else if (Time.time - _lastWaterSampleTime > 0.1f) { _lastWaterSampleTime = Time.time; int num2 = _waterMask; if (num2 == 0) { ConfigEntry debug_Enable = NjordConfig.Debug_Enable; if (debug_Enable != null && debug_Enable.Value) { num2 = -1; } } if (num2 != 0) { try { RaycastHit val = default(RaycastHit); if (Physics.Raycast(_stern.position, Vector3.down, ref val, 10f, num2) || Physics.Raycast(_stern.position, Vector3.up, ref val, 10f, num2)) { _cachedWaterY = ((RaycastHit)(ref val)).point.y; } } catch { } } } if (_cachedWaterY == float.MinValue) { _cachedWaterY = _stern.position.y; } float num3 = _stern.position.x - _lastSpawnPos.x; float num4 = _stern.position.z - _lastSpawnPos.z; if (!(num3 * num3 + num4 * num4 < _spacing * _spacing)) { Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(_stern.position.x, _cachedWaterY + 0.02f, _stern.position.z); Vector3 val3 = new Vector3(_stern.right.x, 0f, _stern.right.z); Vector3 normalized = ((Vector3)(ref val3)).normalized; SpawnOneAt(val2 + normalized * Random.Range(-0.15f, 0.15f), 1.1475f); SpawnOneAt(val2 - normalized * 0.9f + normalized * Random.Range(-0.15f, 0.15f), 0.837f); SpawnOneAt(val2 + normalized * 0.9f + normalized * Random.Range(-0.15f, 0.15f), 0.837f); SpawnOneAt(val2 - normalized * 1.8f + normalized * Random.Range(-0.15f, 0.15f), 1.1475f); SpawnOneAt(val2 + normalized * 1.8f + normalized * Random.Range(-0.15f, 0.15f), 1.1475f); _lastSpawnPos = _stern.position; } } public bool TrySpawnAt(Vector3 worldPos) { //IL_0077: 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_007e: 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_002b: Unknown result type (might be due to invalid IL or missing references) if (!_active || (Object)(object)_stern == (Object)null) { return false; } float num = worldPos.x - _lastSpawnPos.x; float num2 = worldPos.z - _lastSpawnPos.z; if (num * num + num2 * num2 < _spacing * _spacing) { return false; } if (_useTelemetry) { try { worldPos.y = GetRealisticTelemetryWaterY() + 0.02f; } catch { } } _lastSpawnPos = worldPos; SpawnOneAt(worldPos); return true; } private void SpawnOneAt(Vector3 spawnPos, float scaleMultiplier = 1f) { //IL_03c3: Unknown result type (might be due to invalid IL or missing references) //IL_03cd: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: 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_044c: Unknown result type (might be due to invalid IL or missing references) //IL_0453: Unknown result type (might be due to invalid IL or missing references) //IL_045e: Unknown result type (might be due to invalid IL or missing references) //IL_0463: Unknown result type (might be due to invalid IL or missing references) //IL_046a: Unknown result type (might be due to invalid IL or missing references) //IL_046f: Unknown result type (might be due to invalid IL or missing references) //IL_047a: Unknown result type (might be due to invalid IL or missing references) //IL_0481: Unknown result type (might be due to invalid IL or missing references) //IL_0486: Unknown result type (might be due to invalid IL or missing references) //IL_048b: Unknown result type (might be due to invalid IL or missing references) //IL_048e: Unknown result type (might be due to invalid IL or missing references) //IL_049f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Expected O, but got Unknown //IL_03ad: Unknown result type (might be due to invalid IL or missing references) //IL_03b4: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Expected O, but got Unknown //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown //IL_0355: Unknown result type (might be due to invalid IL or missing references) if (_useTelemetry) { try { spawnPos.y = GetRealisticTelemetryWaterY() + 0.02f; } catch { } } GameObject fromPool = GetFromPool(); if ((Object)(object)fromPool == (Object)null) { return; } SpriteRenderer component = fromPool.GetComponent(); if ((Object)(object)component != (Object)null) { component.sprite = ((_runeSprites != null && _runeSprites.Length != 0) ? _runeSprites[Random.Range(0, _runeSprites.Length)] : _sprite); component.color = _color; if ((Object)(object)component.sprite == (Object)null) { NjordDebug.Warn($"[VFX-Sprite] SpawnOneAt: sprite is null for spawned GO at {spawnPos}"); } try { NjordRuntimeConfig njordRuntimeConfig = NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig(); if (njordRuntimeConfig != null && njordRuntimeConfig.Debug_Enable) { Shader val = Shader.Find("Sprites/Default"); if ((Object)(object)val != (Object)null) { try { ((Renderer)component).material = new Material(val); } catch { } } } } catch { } } fromPool.transform.position = spawnPos; fromPool.transform.rotation = Quaternion.Euler(Random.Range(0f, 360f), Random.Range(0f, 360f), Random.Range(0f, 360f)); fromPool.SetActive(true); try { NjordRuntimeConfig njordRuntimeConfig2 = NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig(); if (njordRuntimeConfig2 != null && njordRuntimeConfig2.Debug_Enable) { if (Time.time - _lastSpawnDebugLog > 1f) { string text = (((Object)(object)component == (Object)null || (Object)(object)component.sprite == (Object)null) ? "(sprite-null)" : "(sprite-ok)"); NjordDebug.Info($"[VFX-Sprite] SpawnOneAt: pos={spawnPos} cachedY={_cachedWaterY} {text} goLayer={fromPool.layer} sortingOrder={(((Object)(object)component != (Object)null) ? ((Renderer)component).sortingOrder : (-1))} active={fromPool.activeSelf}"); _lastSpawnDebugLog = Time.time; } if (!_debugNotified) { try { MessageHud instance = MessageHud.instance; if (instance != null) { instance.ShowMessage((MessageType)1, "Njord VFX debug spawns active", 0, (Sprite)null, false); } } catch { } _debugNotified = true; } try { if ((Object)(object)component != (Object)null) { Shader val2 = Shader.Find("Sprites/Default"); if ((Object)(object)val2 != (Object)null) { try { ((Renderer)component).material = new Material(val2); } catch { } } ((Renderer)component).sortingOrder = 32767; } fromPool.layer = 0; try { Transform val3 = fromPool.transform.Find("Njord_DebugQuad"); if ((Object)(object)val3 != (Object)null) { MeshRenderer component2 = ((Component)val3).GetComponent(); MeshFilter component3 = ((Component)val3).GetComponent(); if ((Object)(object)component2 != (Object)null && (Object)(object)component3 != (Object)null) { if ((Object)(object)((Renderer)component2).sharedMaterial == (Object)null) { Shader val4 = Shader.Find("Unlit/Texture") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Sprites/Default"); if ((Object)(object)val4 != (Object)null) { try { Material val5 = new Material(val4); if (val5.HasProperty("_MainTex") && (Object)(object)_runeTex != (Object)null) { val5.SetTexture("_MainTex", (Texture)(object)_runeTex); } if (val5.HasProperty("_Color")) { val5.SetColor("_Color", _color); } val5.renderQueue = 5000; ((Renderer)component2).material = val5; } catch { } } } try { NjordRuntimeConfig njordRuntimeConfig3 = NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig(); float num = Mathf.Max(0.25f, njordRuntimeConfig3.Debug_Enable ? 1.5f : 0.6f); val3.localScale = Vector3.one * num; } catch { val3.localScale = Vector3.one * 0.6f; } ((Renderer)component2).enabled = true; try { ((Renderer)component2).material.renderQueue = 5000; } catch { } } } } catch { } } catch { } } } catch { } RuneSprite_Fader component4 = fromPool.GetComponent(); if ((Object)(object)component4 != (Object)null) { float num2 = Random.Range(1.5f, 3.5f); float num3 = Random.Range(0.2f, 0.7f); float num4 = Random.Range(-0.4f, 0.4f); Vector3 velocity = Vector3.up * num2 + -_stern.forward * num3 + _stern.right * num4; component4.Play(velocity, _life, _scale * scaleMultiplier, _color); } } } private class RuneSprite_Fader : MonoBehaviour { private SpriteRenderer _sr; private Vector3 _vel; private Vector3 _angularVelocity; private float _life; private float _age; private float _startScale; private Color _startColor; private Action _onFinish; private const float GRAVITY = -0.35f; private const float DRAG = 2.8f; public void Init(Action onFinish) { _sr = ((Component)this).GetComponent(); _onFinish = onFinish; } public void Play(Vector3 velocity, float life, float startScale, Color color) { //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_0035: 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_006a: 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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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) _vel = velocity; _life = Mathf.Max(0.01f, life); _age = 0f; _startScale = Mathf.Max(0.01f, startScale); _startColor = color; _angularVelocity = new Vector3(Random.Range(-240f, 240f), Random.Range(-240f, 240f), Random.Range(-240f, 240f)); if ((Object)(object)_sr != (Object)null) { _sr.color = color; ((Component)_sr).transform.localScale = Vector3.one * _startScale; } } private void Update() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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_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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_016d: 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) //IL_0189: Unknown result type (might be due to invalid IL or missing references) float deltaTime = Time.deltaTime; _age += deltaTime; _vel *= Mathf.Exp(-2.8f * deltaTime); _vel.y += -0.35f * deltaTime; Transform transform = ((Component)this).transform; transform.position += _vel * deltaTime; ((Component)this).transform.Rotate(_angularVelocity * deltaTime, (Space)0); float num = Mathf.Clamp01(_age / _life); if ((Object)(object)_sr != (Object)null) { float num2; if (num < 0.3f) { num2 = 1f; } else { float num3 = (num - 0.3f) / 0.7f; num3 *= num3; num2 = 1f - num3; num2 *= 1f + 0.28f * Mathf.Sin(_age * 18f); num2 = Mathf.Clamp01(num2); } Color startColor = _startColor; startColor.a = _startColor.a * num2; _sr.color = startColor; float num4 = ((num < 0.3f) ? _startScale : Mathf.Lerp(_startScale, 0f, (num - 0.3f) / 0.7f)); ((Component)_sr).transform.localScale = Vector3.one * Mathf.Max(0f, num4); ((Component)_sr).transform.localScale = Vector3.one * num4; } if (_age >= _life) { _onFinish?.Invoke(((Component)this).gameObject); } } } private class WakeSampler : MonoBehaviour { private ParticleSystem _ps; private Particle[] _buffer = (Particle[])(object)new Particle[512]; private float _interval = 0.1f; private float _last; private Color _color = Color.white; private Emitter _emitterRef; public void Init(ParticleSystem ps, Color color, float rate, Emitter emitterRef) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) _ps = ps; _color = color; _interval = Mathf.Max(0.05f, 1f / Mathf.Max(1f, rate)); _last = Time.time - _interval; _emitterRef = emitterRef; } private void Update() { //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) //IL_00ad: 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) try { NjordRuntimeConfig njordRuntimeConfig = NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig(); if (!njordRuntimeConfig.VFX_Enable || (Object)(object)_ps == (Object)null || (Object)(object)_emitterRef == (Object)null || Time.time - _last < _interval) { return; } _last = Time.time; int particles = _ps.GetParticles(_buffer); if (particles <= 0) { return; } int num = Mathf.Min(4, particles); int num2 = Mathf.Max(1, particles / num); for (int i = 0; i < particles; i += num2) { Vector3 worldPos = ((Component)_ps).transform.TransformPoint(((Particle)(ref _buffer[i])).position); try { _emitterRef.TrySpawnAt(worldPos); } catch { } } } catch { } } } private const int POOL_INITIAL = 64; private const int POOL_MAX = 1024; private const float VISIBILITY_MULT = 5f; private static Queue _pool = new Queue(); private static GameObject _poolRoot; private static Sprite[] _runeSprites; private static Sprite _runeSprite; private static Texture2D _runeTex; private static Mesh _debugQuadMesh; private static readonly Dictionary _emitters = new Dictionary(); private static readonly Dictionary _wakeSamplers = new Dictionary(); private static bool _inited = false; private static void EnsureInit(Color color) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: 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_0100: Expected O, but got Unknown //IL_0094: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //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) if (_inited) { return; } _inited = true; _runeSprites = (Sprite[])(object)new Sprite[16]; for (int i = 0; i < 16; i++) { Texture2D val = NjordRuneTextureGenerator.GenerateRune(Color.white, i); if ((Object)(object)val == (Object)null) { val = new Texture2D(16, 16, (TextureFormat)4, false); Color[] array = (Color[])(object)new Color[256]; for (int j = 0; j < array.Length; j++) { array[j] = Color.white; } val.SetPixels(array); val.Apply(false); } _runeSprites[i] = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); } _runeTex = NjordRuneTextureGenerator.GenerateRune(Color.white, 0); _runeSprite = _runeSprites[0]; NjordDebug.Debug($"[VFX-Sprite] Generated {16} rune sprites."); _poolRoot = new GameObject("NjordRuneSpritePool"); Object.DontDestroyOnLoad((Object)(object)_poolRoot); for (int k = 0; k < 64; k++) { _pool.Enqueue(CreatePooledGO()); } NjordDebug.Log("[VFX-Sprite] Initialized rune sprite trail pool."); } private static GameObject CreatePooledGO() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown //IL_009b: 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) GameObject val = new GameObject("NjordRuneSprite"); val.transform.SetParent(_poolRoot.transform, false); SpriteRenderer val2 = val.AddComponent(); val2.sprite = _runeSprite; ((Renderer)val2).sortingLayerName = "Default"; ((Renderer)val2).sortingOrder = 5000; ((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0; RuneSprite_Fader runeSprite_Fader = val.AddComponent(); runeSprite_Fader.Init(ReturnToPool); try { GameObject val3 = new GameObject("Njord_DebugQuad"); val3.transform.SetParent(val.transform, false); val3.transform.localPosition = Vector3.zero; val3.transform.localRotation = Quaternion.identity; MeshFilter val4 = val3.AddComponent(); val4.mesh = GetOrCreateDebugQuadMesh(); MeshRenderer val5 = val3.AddComponent(); ((Renderer)val5).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)val5).receiveShadows = false; ((Renderer)val5).enabled = false; val3.SetActive(true); } catch { } val.SetActive(false); return val; } private static GameObject GetFromPool() { if (_pool.Count > 0) { return _pool.Dequeue(); } if (_pool.Count + 1 <= 1024) { return CreatePooledGO(); } return null; } private static void ReturnToPool(GameObject go) { if (!((Object)(object)go == (Object)null)) { go.SetActive(false); go.transform.SetParent(_poolRoot.transform, false); if (_pool.Count < 1024) { _pool.Enqueue(go); } else { Object.Destroy((Object)(object)go); } } } private static Mesh GetOrCreateDebugQuadMesh() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: 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_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) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_debugQuadMesh != (Object)null) { return _debugQuadMesh; } Mesh val = new Mesh(); ((Object)val).name = "Njord_DebugQuadMesh"; Vector3[] vertices = (Vector3[])(object)new Vector3[4] { new Vector3(-0.5f, 0f, -0.5f), new Vector3(0.5f, 0f, -0.5f), new Vector3(0.5f, 0f, 0.5f), new Vector3(-0.5f, 0f, 0.5f) }; int[] triangles = new int[6] { 0, 1, 2, 0, 2, 3 }; Vector2[] uv = (Vector2[])(object)new Vector2[4] { new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(0f, 1f) }; val.vertices = vertices; val.triangles = triangles; val.uv = uv; val.RecalculateNormals(); val.RecalculateBounds(); _debugQuadMesh = val; return _debugQuadMesh; } public static void SpawnBurst(Vector3 pos, Color color, int count) { //IL_0018: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) NjordRuntimeConfig njordRuntimeConfig = NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig(); if (!njordRuntimeConfig.VFX_Enable) { return; } EnsureInit(color); float life = 12.5f; float startScale = 1.125f; for (int i = 0; i < Mathf.Max(1, count); i++) { GameObject fromPool = GetFromPool(); if (!((Object)(object)fromPool == (Object)null)) { SpriteRenderer component = fromPool.GetComponent(); if ((Object)(object)component != (Object)null) { component.sprite = ((_runeSprites != null) ? _runeSprites[Random.Range(0, _runeSprites.Length)] : _runeSprite); component.color = color; } fromPool.transform.position = pos + Random.insideUnitSphere * 0.35f; fromPool.transform.rotation = Quaternion.Euler(90f, Random.Range(0f, 360f), 0f); fromPool.SetActive(true); RuneSprite_Fader component2 = fromPool.GetComponent(); if ((Object)(object)component2 != (Object)null) { Vector3 velocity = (Random.onUnitSphere + Vector3.back * 1.5f) * 0.4f; component2.Play(velocity, life, startScale, color); } } } } public static void SpawnAtWorldPosition(Vector3 pos, Color color) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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_00db: 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) //IL_00f2: 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) NjordRuntimeConfig njordRuntimeConfig = NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig(); if (!njordRuntimeConfig.VFX_Enable) { return; } EnsureInit(color); GameObject fromPool = GetFromPool(); if (!((Object)(object)fromPool == (Object)null)) { SpriteRenderer component = fromPool.GetComponent(); if ((Object)(object)component != (Object)null) { component.sprite = ((_runeSprites != null) ? _runeSprites[Random.Range(0, _runeSprites.Length)] : _runeSprite); component.color = color; } fromPool.transform.position = pos; fromPool.transform.rotation = Quaternion.Euler(90f, Random.Range(0f, 360f), 0f); fromPool.SetActive(true); RuneSprite_Fader component2 = fromPool.GetComponent(); if ((Object)(object)component2 != (Object)null) { Vector3 velocity = Vector3.back * 0.6f + Random.insideUnitSphere * 0.2f; float life = 2.5f; float startScale = 0.3f; component2.Play(velocity, life, startScale, color); } } } public static void StartTrailForShip(object ship, Transform stern, Color color, float rateMultiplier = 1f) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: 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_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0124: 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_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: 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_01d2: Unknown result type (might be due to invalid IL or missing references) if (ship == null || (Object)(object)stern == (Object)null) { return; } NjordRuntimeConfig njordRuntimeConfig = NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig(); if (!njordRuntimeConfig.VFX_Enable) { return; } EnsureInit(color); if (_emitters.TryGetValue(ship, out var value) && (Object)(object)value != (Object)null) { value.SetActive(v: true); value.UpdateParams(stern, color, rateMultiplier); return; } Transform val = stern; try { Component val2 = (Component)((ship is Component) ? ship : null); if (val2 != null && (Object)(object)val2.transform != (Object)null) { val = val2.transform; } } catch { } GameObject val3 = new GameObject($"NjordRuneSpriteEmitter_{ship.GetHashCode()}"); val3.transform.SetParent(val, true); long controllerForShip = Njord_ShipControlTracker.GetControllerForShip(ship); Player localPlayer = Player.m_localPlayer; long num = ((localPlayer != null) ? localPlayer.GetPlayerID() : 0); bool flag = controllerForShip != 0L && num != 0L && controllerForShip == num; Emitter emitter = val3.AddComponent(); emitter.Initialize(stern, color, rateMultiplier, ReturnToPool, _runeSprite, flag); try { if (flag) { val3.transform.position = stern.position - stern.forward * 1f + stern.up * 0.5f; } else { float num2 = 0.25f; float num3 = 1f; float num4 = 0f; Component val4 = (Component)((ship is Component) ? ship : null); if (val4 != null) { string text = ((Object)val4.gameObject).name.Replace("(Clone)", ""); if (text.Contains("VikingShip_Ashlands")) { num4 = 0.55f; num3 = 2.2f; } else if (text.Contains("VikingShip")) { num3 = 2.2f; } } val3.transform.position = stern.TransformPoint(new Vector3(num4, 0f - num2, 0f - num3)); } } catch { } _emitters[ship] = emitter; NjordDebug.Log("[VFX-Sprite] Created sprite emitter for ship."); } public static void StopTrailForShip(object ship) { if (ship != null && _emitters.TryGetValue(ship, out var value) && (Object)(object)value != (Object)null) { value.SetActive(v: false); } } public static void RemoveEmitterForShip(object ship) { if (ship == null) { return; } if (_emitters.TryGetValue(ship, out var value) && (Object)(object)value != (Object)null) { try { if ((Object)(object)((Component)value).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)value).gameObject); } } catch { } } _emitters.Remove(ship); if (!_wakeSamplers.TryGetValue(ship, out var value2) || !((Object)(object)value2 != (Object)null)) { return; } try { if ((Object)(object)((Component)value2).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)value2).gameObject); } } catch { } _wakeSamplers.Remove(ship); } public static void DumpEmitters() { NjordDebug.Info($"[VFX-Sprite] Emitters: count={_emitters.Count} pool={_pool.Count}"); foreach (KeyValuePair emitter in _emitters) { object key = emitter.Key; Emitter value = emitter.Value; if ((Object)(object)value == (Object)null) { NjordDebug.Info($"[VFX-Sprite] Emitter for {key}: null"); continue; } Type type = ((object)value).GetType(); object obj = type.GetField("_active", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(value); object obj2 = type.GetField("_cachedWaterY", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(value); object obj3 = type.GetField("_lastWaterSampleTime", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(value); object obj4 = type.GetField("_waterMask", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(value); object obj5 = type.GetField("_useTelemetry", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(value); object obj6 = type.GetField("_lastSpawnPos", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(value); object obj7 = type.GetField("_stern", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(value); Object val = (Object)((obj7 is Object) ? obj7 : null); bool flag = ((val != null) ? (val != (Object)null) : (obj7 != null)); NjordDebug.Info($"[VFX-Sprite] Emitter for {key}: active={obj} enabled={((Behaviour)value).isActiveAndEnabled} tele={obj5} cachedY={obj2} lastSpawnPos={obj6} lastSample={obj3} mask={obj4} sternAlive={flag}"); } } } public static class NjordRuneVFX { private static bool _initialized; private static GameObject _prefab; private static Material _material; private static Texture2D _runeTex; internal static ParticleSystem _burstSystem; internal static readonly Dictionary _emitters = new Dictionary(); private const float DefaultTrailRate = 30f; private const int DefaultMaxParticles = 400; internal static readonly Dictionary _lastActive = new Dictionary(); public static void DiscoverShaderIfNeeded() { //IL_007c: 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_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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_0106: 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_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Expected O, but got Unknown //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: 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) if (_initialized) { return; } _initialized = true; if (NjordConfig.Debug_Enable.Value) { NjordDebug.Debug("[VFX] Initializing NjordRuneVFX…"); } NjordRuntimeConfig njordRuntimeConfig = NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig(); string text = "blend"; Texture2D val = (Texture2D)(text.ToLowerInvariant() switch { "soft" => NjordRuneTextureGenerator.GenerateSoftTrail(njordRuntimeConfig.VFX_Color), "rune" => NjordRuneTextureGenerator.GenerateRune(njordRuntimeConfig.VFX_Color), "streak" => NjordRuneTextureGenerator.GenerateStreak(njordRuntimeConfig.VFX_Color), _ => NjordRuneTextureGenerator.GenerateBlend(njordRuntimeConfig.VFX_Color), }); if ((Object)(object)val == (Object)null) { NjordDebug.Error("[VFX] Rune texture generation failed."); return; } _runeTex = val; _material = NjordRuneVFX_Helper.GetOrCreateRuneMaterial(val, njordRuntimeConfig.VFX_Color); if ((Object)(object)_material == (Object)null) { NjordDebug.Error("[VFX] Failed to create rune material (no suitable shader)."); return; } if (_material.HasProperty("_EmissionColor")) { Color vFX_Color = njordRuntimeConfig.VFX_Color; _material.SetColor("_EmissionColor", vFX_Color * 3f); } _material.SetInt("_SrcBlend", 1); _material.SetInt("_DstBlend", 1); _material.SetInt("_ZWrite", 0); _material.DisableKeyword("_ALPHATEST_ON"); _material.EnableKeyword("_ALPHABLEND_ON"); _material.EnableKeyword("_ALPHAPREMULTIPLY_ON"); _material.renderQueue = 3000; _prefab = BuildPrefab(_material); if ((Object)(object)_prefab == (Object)null) { NjordDebug.Error("[VFX] Failed to build rune prefab."); return; } GameObject val2 = Object.Instantiate(_prefab); ((Object)val2).name = "NjordRuneVFX_BurstSystem"; val2.SetActive(true); _burstSystem = val2.GetComponent(); if ((Object)(object)_burstSystem != (Object)null) { EmissionModule emission = _burstSystem.emission; ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(0f); _burstSystem.Stop(); } GameObject val3 = new GameObject("NjordRuneVFX_Manager"); val3.AddComponent(); Object.DontDestroyOnLoad((Object)(object)val3); if (NjordConfig.Debug_Enable.Value) { NjordDebug.Debug("[VFX] NjordRuneVFX initialized successfully."); } } public static void Spawn(Vector3 pos, Color color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) SpawnBurst(pos, color, 6); } public static void Spawn(Vector3 pos) { //IL_000f: 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) NjordRuntimeConfig njordRuntimeConfig = NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig(); Spawn(pos, njordRuntimeConfig.VFX_Color); } private static GameObject BuildPrefab(Material mat) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0064: 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_0075: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: 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) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: 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) //IL_00f1: 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_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0136: 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_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Expected O, but got Unknown //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("NjordRuneVFX_Particle"); ParticleSystem val2 = val.AddComponent(); MainModule main = val2.main; ((MainModule)(ref main)).playOnAwake = false; ((MainModule)(ref main)).loop = true; ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1; ((MainModule)(ref main)).startLifetime = new MinMaxCurve(0.8f, 1.4f); ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0.6f); ((MainModule)(ref main)).startSize = new MinMaxCurve(0.18f, 0.42f); ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(Color.white); ((MainModule)(ref main)).maxParticles = 400; EmissionModule emission = val2.emission; ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(0f); ShapeModule shape = val2.shape; ((ShapeModule)(ref shape)).enabled = true; ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)4; ((ShapeModule)(ref shape)).angle = 10f; ((ShapeModule)(ref shape)).radius = 0.15f; ((ShapeModule)(ref shape)).position = Vector3.zero; ((ShapeModule)(ref shape)).rotation = Vector3.zero; VelocityOverLifetimeModule velocityOverLifetime = val2.velocityOverLifetime; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).enabled = true; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).space = (ParticleSystemSimulationSpace)0; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).x = new MinMaxCurve(0f); ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).y = new MinMaxCurve(-0.05f, 0.05f); ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).z = new MinMaxCurve(-1.6f, -0.6f); ColorOverLifetimeModule colorOverLifetime = val2.colorOverLifetime; ((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true; Gradient val3 = new Gradient(); val3.SetKeys((GradientColorKey[])(object)new GradientColorKey[2] { new GradientColorKey(Color.white, 0f), new GradientColorKey(Color.white, 1f) }, (GradientAlphaKey[])(object)new GradientAlphaKey[2] { new GradientAlphaKey(1f, 0f), new GradientAlphaKey(0f, 1f) }); ((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val3); SizeOverLifetimeModule sizeOverLifetime = val2.sizeOverLifetime; ((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = true; MinMaxCurve size = default(MinMaxCurve); ((MinMaxCurve)(ref size))..ctor(1f, AnimationCurve.EaseInOut(0f, 1f, 1f, 0.2f)); ((SizeOverLifetimeModule)(ref sizeOverLifetime)).size = size; ParticleSystemRenderer component = val.GetComponent(); component.renderMode = (ParticleSystemRenderMode)0; ((Renderer)component).material = mat; ((Renderer)component).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)component).receiveShadows = false; val.SetActive(false); if (NjordConfig.Debug_Enable.Value) { NjordDebug.Debug("[VFX] Rune particle prefab constructed."); } return val; } private static ParticleSystem GetOrCreateEmitterForShip(object ship, Transform stern, Color color) { //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_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_008f: 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_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Expected O, but got Unknown //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Expected O, but got Unknown if (ship == null || (Object)(object)stern == (Object)null) { return null; } if (!_initialized) { DiscoverShaderIfNeeded(); } if ((Object)(object)_prefab == (Object)null) { return null; } if (_emitters.TryGetValue(ship, out var value) && (Object)(object)value != (Object)null) { return value; } GameObject val = Object.Instantiate(_prefab, stern.position, stern.rotation); ((Object)val).name = $"NjordRuneVFX_Emitter_{ship.GetHashCode()}"; Vector3 position = stern.TransformPoint(new Vector3(0f, -0.6f, -0.6f)); val.transform.position = position; val.transform.rotation = stern.rotation; val.transform.SetParent(stern, true); val.SetActive(true); value = val.GetComponent(); if ((Object)(object)value == (Object)null) { return null; } ParticleSystemRenderer component = val.GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)_material != (Object)null) { ((Renderer)component).material = new Material(_material); Material material = ((Renderer)component).material; if (material.HasProperty("_Color")) { material.SetColor("_Color", color); } if (material.HasProperty("_TintColor")) { material.SetColor("_TintColor", color * 2f); } if (material.HasProperty("_EmissionColor")) { material.SetColor("_EmissionColor", color * 3f); } try { Shader val2 = Shader.Find("Particles/Standard Unlit") ?? Shader.Find("Legacy Shaders/Particles/Alpha Blended") ?? Shader.Find("Particles/Alpha Blended"); if ((Object)(object)val2 != (Object)null) { Material val3 = new Material(val2); Texture2D val4 = _runeTex; if ((Object)(object)val4 == (Object)null) { try { Material material2 = _material; Texture obj = ((material2 != null) ? material2.GetTexture("_MainTex") : null); val4 = (Texture2D)(object)((obj is Texture2D) ? obj : null); } catch { } try { if ((Object)(object)val4 == (Object)null) { Material material3 = _material; Texture obj3 = ((material3 != null) ? material3.mainTexture : null); val4 = (Texture2D)(object)((obj3 is Texture2D) ? obj3 : null); } } catch { } } if ((Object)(object)val4 != (Object)null) { if (val3.HasProperty("_MainTex")) { val3.SetTexture("_MainTex", (Texture)(object)val4); } if (val3.HasProperty("_BaseMap")) { val3.SetTexture("_BaseMap", (Texture)(object)val4); } try { val3.mainTexture = (Texture)(object)val4; } catch { } } if (val3.HasProperty("_Color")) { val3.SetColor("_Color", color); } if (val3.HasProperty("_EmissionColor")) { val3.SetColor("_EmissionColor", color * 3f); } try { val3.SetInt("_SrcBlend", 5); val3.SetInt("_DstBlend", 10); val3.SetInt("_ZWrite", 0); val3.DisableKeyword("_ALPHATEST_ON"); val3.EnableKeyword("_ALPHABLEND_ON"); val3.DisableKeyword("_ALPHAPREMULTIPLY_ON"); val3.renderQueue = 3000; } catch { } ((Renderer)component).material = val3; material = ((Renderer)component).material; } } catch { } } MainModule main = value.main; ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(color); ((MainModule)(ref main)).startLifetime = new MinMaxCurve(0.5f, 1.6f); ((MainModule)(ref main)).startSize = new MinMaxCurve(0.12f, 1f); ((MainModule)(ref main)).maxParticles = 400; value.Stop(true, (ParticleSystemStopBehavior)1); _emitters[ship] = value; _lastActive[ship] = Time.time; if (NjordConfig.Debug_Enable.Value) { NjordDebug.Debug($"[VFX] Created emitter for ship {ship}."); } return value; } public static void StartTrailForShip(object ship, Transform stern, Color color, float rateMultiplier = 1f) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) try { NjordRuneSpriteTrail.StartTrailForShip(ship, stern, color, rateMultiplier); } catch { } } public static void StopTrailForShip(object ship) { try { NjordRuneSpriteTrail.StopTrailForShip(ship); } catch { } } public static void SpawnBurst(Vector3 pos, Color color, int count) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) NjordRuntimeConfig njordRuntimeConfig = NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig(); if (!njordRuntimeConfig.VFX_Enable) { return; } try { NjordRuneSpriteTrail.SpawnBurst(pos, color, count); } catch { } } public static void RemoveEmitterForShip(object ship) { if (ship == null) { return; } try { NjordRuneSpriteTrail.RemoveEmitterForShip(ship); } catch { } if (_emitters.TryGetValue(ship, out var value) && (Object)(object)value != (Object)null) { try { if ((Object)(object)((Component)value).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)value).gameObject); } } catch { } } _emitters.Remove(ship); _lastActive.Remove(ship); if (NjordConfig.Debug_Enable.Value) { NjordDebug.Debug($"[VFX] Removed emitter for ship {ship} (destroy hook)."); } } } public class NjordRuneVFX_Manager : MonoBehaviour { private float _timer; private const float CHECK_INTERVAL = 5f; private void Update() { _timer += Time.deltaTime; if (_timer < 5f) { return; } _timer = 0f; NjordRuntimeConfig njordRuntimeConfig = NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig(); float num = 15f; List list = new List(NjordRuneVFX._emitters.Keys); foreach (object item in list) { if (!NjordRuneVFX._emitters.TryGetValue(item, out var value) || (Object)(object)value == (Object)null) { NjordRuneVFX._emitters.Remove(item); NjordRuneVFX._lastActive.Remove(item); continue; } if (!NjordRuneVFX._lastActive.TryGetValue(item, out var value2)) { value2 = Time.time; } if (!(Time.time - value2 > num)) { continue; } try { if ((Object)(object)((Component)value).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)value).gameObject); } } catch { } NjordRuneVFX._emitters.Remove(item); NjordRuneVFX._lastActive.Remove(item); if (NjordConfig.Debug_Enable.Value) { NjordDebug.Debug($"[VFX] Cleaned up emitter for ship {item} after timeout."); } } } } public static class NjordRuneVFX_Helper { private static readonly Dictionary _materialCache = new Dictionary(); private static bool _initialized = false; private static void Init() { if (!_initialized) { _initialized = true; NjordDebug.Log("\ud83d\udf01 VFX‑Forge: Seeking glowing, additive, unlit shaders worthy of Njord."); } } private unsafe static long MakeCacheKey(Shader shader, Texture2D tex, Color color) { int num = (((Object)(object)shader != (Object)null) ? ((Object)shader).GetInstanceID() : 0); int num2 = (((Object)(object)tex != (Object)null) ? ((Object)tex).GetInstanceID() : 0); int hashCode = ((object)(*(Color*)(&color))/*cast due to .constrained prefix*/).GetHashCode(); return (long)((ulong)((long)num << 32) ^ ((ulong)(uint)num2 << 16) ^ (uint)hashCode); } public static Material GetOrCreateRuneMaterial(Texture2D runeTex, Color color) { //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: 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_0179: Expected O, but got Unknown //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) Init(); Shader val = Shader.Find("Particles/Standard Unlit") ?? Shader.Find("Legacy Shaders/Particles/Alpha Blended") ?? Shader.Find("Particles/Alpha Blended") ?? Shader.Find("Particles/Additive"); if ((Object)(object)val == (Object)null) { float num = float.MinValue; Material[] array = Resources.FindObjectsOfTypeAll(); foreach (Material val2 in array) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.shader == (Object)null)) { Shader shader = val2.shader; string text = ((Object)shader).name.ToLower(); float num2 = 0f; if (text.Contains("particle")) { num2 += 3f; } if (text.Contains("add")) { num2 += 3f; } if (text.Contains("unlit")) { num2 += 2f; } if (text.Contains("transparent")) { num2 += 1.5f; } if (val2.HasProperty("_Color") && val2.HasProperty("_EmissionColor") && num2 > num) { num = num2; val = shader; } } } } if ((Object)(object)val == (Object)null) { NjordDebug.Error("\ud83d\udf01 VFX‑Forge: No glowing shader found. The runes refuse to shine."); return null; } long key = MakeCacheKey(val, runeTex, color); if (_materialCache.TryGetValue(key, out var value) && (Object)(object)value != (Object)null) { return value; } Material val3 = new Material(val); if ((Object)(object)runeTex != (Object)null) { if (val3.HasProperty("_MainTex")) { val3.SetTexture("_MainTex", (Texture)(object)runeTex); } if (val3.HasProperty("_BaseMap")) { val3.SetTexture("_BaseMap", (Texture)(object)runeTex); } try { val3.mainTexture = (Texture)(object)runeTex; } catch { } } if (val3.HasProperty("_Color")) { val3.SetColor("_Color", color); } if (val3.HasProperty("_TintColor")) { val3.SetColor("_TintColor", color); } if (val3.HasProperty("_EmissionColor")) { val3.SetColor("_EmissionColor", color * 3f); } val3.SetInt("_SrcBlend", 1); val3.SetInt("_DstBlend", 1); val3.SetInt("_ZWrite", 0); val3.DisableKeyword("_ALPHATEST_ON"); val3.EnableKeyword("_ALPHABLEND_ON"); val3.DisableKeyword("_ALPHAPREMULTIPLY_ON"); val3.renderQueue = 3000; _materialCache[key] = val3; NjordDebug.Log("\ud83d\udf01 VFX‑Forge: Forged glowing additive rune material from '" + ((Object)val).name + "'."); return val3; } public static void ClearCache() { _materialCache.Clear(); _initialized = false; } } public static class NjordSeaDogEngineVFXTriggers { public static readonly Dictionary LastController = new Dictionary(); public static readonly Dictionary LastSpeed = new Dictionary(); public static readonly Dictionary LastVfxTime = new Dictionary(); public static readonly Dictionary LastTrailLog = new Dictionary(); private static readonly Dictionary _rudderCache = new Dictionary(); public static Transform GetStern(Ship ship) { if ((Object)(object)ship == (Object)null) { return null; } if (_rudderCache.TryGetValue(ship, out var value) && (Object)(object)value != (Object)null) { return value; } try { ShipControlls componentInChildren = ((Component)ship).GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { _rudderCache[ship] = ((Component)componentInChildren).transform; return ((Component)componentInChildren).transform; } } catch { } _rudderCache[ship] = ((Component)ship).transform; return ((Component)ship).transform; } public static void Process(Ship ship, NjordSailState state, string speedStr, long controller, float now, Transform tf, bool debug, NjordRuntimeConfig cfg) { //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_015b: 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_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0174: 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_0083: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) if (!cfg.VFX_Enable) { return; } if (!LastVfxTime.TryGetValue(ship, out var value)) { value = 0f; } if (!LastController.TryGetValue(ship, out var value2)) { value2 = 0L; } if (!LastSpeed.TryGetValue(ship, out var value3)) { value3 = "Stop"; } if (controller != value2) { LastController[ship] = controller; if (controller != 0L) { if (debug) { NjordDebug.Debug("[SeaDog][VFX] Control change: spawning control burst"); } LastVfxTime[ship] = now; Transform stern = GetStern(ship); Vector3 pos = stern.position + Vector3.up * 1.2f; NjordRuneVFX.SpawnBurst(pos, cfg.VFX_Color, 8); } else { try { NjordRuneVFX.StopTrailForShip(ship); } catch { } } } if (speedStr != value3) { LastSpeed[ship] = speedStr; if (speedStr == "Half" || speedStr == "Full") { if (debug) { NjordDebug.Debug("[SeaDog][VFX] Sail state change to " + speedStr + ": spawning burst"); } LastVfxTime[ship] = now; Transform stern2 = GetStern(ship); Vector3 val = stern2.position + Vector3.up * 1.5f; for (int i = 0; i < 4; i++) { Vector3 insideUnitSphere = Random.insideUnitSphere; insideUnitSphere.y = Mathf.Abs(insideUnitSphere.y) + 0.3f; Vector3 pos2 = val + insideUnitSphere * 0.2f; NjordRuneVFX.SpawnBurst(pos2, cfg.VFX_Color, 1); } } } float num = 0f; try { num = ship.GetSpeed(); } catch { num = 0f; } Transform stern3 = GetStern(ship); if (speedStr != "Stop" && speedStr != "Back" && num > 0.5f) { float maxSpeedForShip = NjordShipSpeed.GetMaxSpeedForShip(ship); float num2 = ((maxSpeedForShip > 0f) ? (num / maxSpeedForShip) : Mathf.Clamp01(num / 10f)); float num3 = Mathf.Clamp(0.5f + num2 * 2f, 0.2f, 4f); if (debug) { LastTrailLog.TryGetValue(ship, out var value4); if (now - value4 >= 2f) { NjordDebug.Debug($"[SeaDog][VFX] Starting trail for ship {ship} at stern {((stern3 != null) ? ((Object)stern3).name : null)} rateMul={num3:F2}"); LastTrailLog[ship] = now; } } NjordRuneVFX.StartTrailForShip(ship, stern3, cfg.VFX_Color, num3); LastVfxTime[ship] = now; return; } if (debug) { LastTrailLog.TryGetValue(ship, out var value5); if (now - value5 >= 2f) { NjordDebug.Debug($"[SeaDog][VFX] Stopping trail for ship {ship}"); LastTrailLog[ship] = now; } } NjordRuneVFX.StopTrailForShip(ship); } } } namespace Njord.Patches { [HarmonyPatch(typeof(Player), "StartDoodadControl")] public static class NjordDoodadControlRune { private static void Postfix(Player __instance, IDoodadController shipControl) { if ((Object)(object)__instance == (Object)null || shipControl == null) { return; } ShipControlls val = (ShipControlls)(object)((shipControl is ShipControlls) ? shipControl : null); if (val == null) { return; } Ship ship = val.m_ship; if ((Object)(object)ship == (Object)null) { return; } long playerID = __instance.GetPlayerID(); if (!NjordAuthorityEngine.UseLegacyFallback && (Object)(object)ZNet.instance != (Object)null) { if (ZNet.instance.IsServer()) { NjordAuthorityEngine.Server_OnHelmClaim(ship, playerID); } else { NjordAuthorityEngine.Client_RequestControl(ship); } } Njord_ShipControlTracker.SetControl(ship, playerID); ZNetView component = ((Component)ship).GetComponent(); if ((Object)(object)component != (Object)null && component.IsValid()) { component.ClaimOwnership(); if (NjordConfig.Debug_Enable.Value) { NjordDebug.Debug("[Helm‑Bind] Claimed ZDO ownership for " + ((Object)ship).name + "."); } } if (NjordConfig.Debug_Enable.Value) { NjordDebug.Debug($"[Helm‑Bind] Player {playerID} takes helm of {((Object)ship).name}."); } } } [HarmonyPatch(typeof(ShipControlls), "OnUseStop")] public static class NjordDoodadReleaseRune { private static void Postfix(ShipControlls __instance, Player player) { if ((Object)(object)__instance == (Object)null || (Object)(object)player == (Object)null) { return; } Ship ship = __instance.m_ship; if ((Object)(object)ship == (Object)null) { return; } long playerID = player.GetPlayerID(); long controllerForShip = Njord_ShipControlTracker.GetControllerForShip(ship); if (controllerForShip != playerID) { return; } if (!NjordAuthorityEngine.UseLegacyFallback && (Object)(object)ZNet.instance != (Object)null) { if (ZNet.instance.IsServer()) { NjordAuthorityEngine.Server_OnHelmRelease(ship); } else { NjordAuthorityEngine.Client_ReleaseControl(ship); } } Njord_ShipControlTracker.ClearControl(ship); if (NjordConfig.Debug_Enable.Value) { NjordDebug.Debug($"[Helm‑Release] Player {playerID} released helm of {((Object)ship).name}."); } } } [HarmonyPatch] public static class NjordSeaDogEngine { private static float _telemetryTimer = 0f; private const float TELEMETRY_INTERVAL = 0.2f; private static float _prevNjordSpeed = 0f; private static float _prevVanillaSpeed = 0f; private static float _lastTickLog = -10f; private const float TICK_LOG_INTERVAL = 2f; private static readonly Dictionary _lastDebugLog = new Dictionary(); private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("Ship"); if (type == null) { NjordDebug.Error("NjordSeaDogEngine: Ship type not found."); return null; } MethodInfo methodInfo = AccessTools.Method(type, "CustomFixedUpdate", (Type[])null, (Type[])null); if (methodInfo == null) { NjordDebug.Error("NjordSeaDogEngine: CustomFixedUpdate not found on Ship."); } return methodInfo; } public static float Safe(float v) { if (!float.IsNaN(v) && !float.IsInfinity(v)) { return v; } return 0f; } private static void Prefix(object __instance, float fixedDeltaTime) { //IL_041f: Unknown result type (might be due to invalid IL or missing references) //IL_0723: Unknown result type (might be due to invalid IL or missing references) //IL_072a: Unknown result type (might be due to invalid IL or missing references) //IL_072f: Unknown result type (might be due to invalid IL or missing references) //IL_0788: Unknown result type (might be due to invalid IL or missing references) //IL_078d: Unknown result type (might be due to invalid IL or missing references) //IL_073a: Unknown result type (might be due to invalid IL or missing references) //IL_073c: Unknown result type (might be due to invalid IL or missing references) //IL_0733: Unknown result type (might be due to invalid IL or missing references) //IL_0738: Unknown result type (might be due to invalid IL or missing references) //IL_070c: Unknown result type (might be due to invalid IL or missing references) //IL_0711: Unknown result type (might be due to invalid IL or missing references) //IL_0718: Unknown result type (might be due to invalid IL or missing references) //IL_071d: Unknown result type (might be due to invalid IL or missing references) //IL_074e: Unknown result type (might be due to invalid IL or missing references) //IL_0757: Unknown result type (might be due to invalid IL or missing references) //IL_075d: Unknown result type (might be due to invalid IL or missing references) //IL_07a9: Unknown result type (might be due to invalid IL or missing references) //IL_07b0: Unknown result type (might be due to invalid IL or missing references) //IL_07b5: Unknown result type (might be due to invalid IL or missing references) //IL_07b9: Unknown result type (might be due to invalid IL or missing references) //IL_0848: Unknown result type (might be due to invalid IL or missing references) //IL_084d: Unknown result type (might be due to invalid IL or missing references) //IL_0852: Unknown result type (might be due to invalid IL or missing references) //IL_085d: Unknown result type (might be due to invalid IL or missing references) if (__instance == null || fixedDeltaTime <= 0f) { return; } bool value = NjordConfig.Debug_Enable.Value; bool flag = value && Time.fixedTime - _lastTickLog >= 2f; if (flag) { NjordDebug.Debug($"[SeaDog] Tick dt={fixedDeltaTime:0.000}"); _lastTickLog = Time.fixedTime; } Type type = __instance.GetType(); object obj = AccessTools.Field(type, "m_nview")?.GetValue(__instance); if (obj == null) { return; } MethodInfo methodInfo = AccessTools.Method(obj.GetType(), "IsValid", (Type[])null, (Type[])null); if (methodInfo != null && !(bool)methodInfo.Invoke(obj, null)) { return; } object? obj2 = AccessTools.Field(type, "m_body")?.GetValue(__instance); Rigidbody val = (Rigidbody)((obj2 is Rigidbody) ? obj2 : null); if (val == null || (Object)(object)val == (Object)null || float.IsNaN(val.mass) || val.mass <= 0f) { return; } FieldInfo fieldInfo = AccessTools.Field(type, "m_lastDepth"); if (fieldInfo != null && (float)fieldInfo.GetValue(__instance) <= -9000f) { return; } long controllerForShip = Njord_ShipControlTracker.GetControllerForShip(__instance); long num = (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : 0); bool flag2 = controllerForShip != 0L && num != 0L && controllerForShip == num; Njord_ShipControlTracker.UpdateController(controllerForShip, fixedDeltaTime); if (flag2) { ZNetView val2 = (ZNetView)((obj is ZNetView) ? obj : null); if (val2 != null && val2.IsValid() && !val2.IsOwner()) { val2.ClaimOwnership(); if (flag) { NjordDebug.Debug("[SeaDog] ZDO ownership reclaimed for locally controlled ship."); } } } float num2 = 0f; float num3 = 0f; float num4 = 1f; float num5 = 0f; float num6 = 1f; Ship val3 = (Ship)((__instance is Ship) ? __instance : null); if (val3 != null) { NjordRuntimeConfig njordRuntimeConfig = NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig(); float shipWindAngle = Njord_ShipControlTracker.GetShipWindAngle(val3); if (njordRuntimeConfig.Wind_SystemEnable) { num2 = Mathf.DeltaAngle(0f, val3.GetWindAngle()); num3 = num2; if (njordRuntimeConfig.Wind_AlwaysFull) { num3 = 0f; } else { float num7 = Mathf.Abs(num2); bool flag3 = num7 > 130f; bool shipWasInDeadZone = Njord_ShipControlTracker.GetShipWasInDeadZone(val3, flag3); float shipGraceTimer = Njord_ShipControlTracker.GetShipGraceTimer(val3); if (flag3 != shipWasInDeadZone) { shipGraceTimer = 0f; Njord_ShipControlTracker.SetShipWasInDeadZone(val3, flag3); } else { shipGraceTimer += fixedDeltaTime; } Njord_ShipControlTracker.SetShipGraceTimer(val3, shipGraceTimer); float num8 = num2; if (flag3 && njordRuntimeConfig.Wind_NoDeadZone) { FieldInfo fieldInfo2 = AccessTools.Field(type, "m_rudder") ?? AccessTools.Field(type, "m_rudderValue"); float num9 = ((fieldInfo2 != null) ? ((float)fieldInfo2.GetValue(__instance)) : 0f); float num10 = 115f; num8 = ((num9 > 0.05f) ? (0f - num10) : ((!(num9 < -0.05f)) ? ((num2 > 0f) ? num10 : (0f - num10)) : num10)); } else if (!flag3 && njordRuntimeConfig.Wind_BlendToFull) { num8 = 0f; } num3 = ((!(shipGraceTimer < njordRuntimeConfig.Wind_GracePeriodDelay)) ? num8 : num2); } num5 = Mathf.MoveTowardsAngle(shipWindAngle, num3, njordRuntimeConfig.Wind_BlendRate * fixedDeltaTime); Njord_ShipControlTracker.SetShipWindAngle(val3, num5); Njord_Telemetry.WindUIBlend = num5; float num11 = Mathf.Abs(num5); num4 = ((num11 > 130f) ? 0f : ((!(num11 > 90f)) ? Mathf.Lerp(1f, 0.75f, num11 / 90f) : Mathf.Lerp(0.75f, 0f, (num11 - 90f) / 40f))); } else { num6 = val3.GetWindAngleFactor(); } } AccessTools.Field(type, "m_sailForceFactor")?.SetValue(__instance, 0f); AccessTools.Field(type, "m_sailForceOffset")?.SetValue(__instance, 0f); AccessTools.Field(type, "m_backwardForce")?.SetValue(__instance, 0f); AccessTools.Field(type, "m_sailForce")?.SetValue(__instance, Vector3.zero); string text = AccessTools.Method(type, "GetSpeedSetting", (Type[])null, (Type[])null)?.Invoke(__instance, null)?.ToString() ?? "Stop"; NjordSailState njordSailState = text switch { "Back" => NjordSailState.Backward, "Half" => NjordSailState.Half, "Full" => NjordSailState.Full, "Slow" => NjordSailState.Forward, "Stop" => NjordSailState.Forward, _ => NjordSailState.Forward, }; string shipPrefabName = NjordBoatController.GetShipPrefabName(__instance); float v = NjordBoatController.GetBaseline(njordSailState, shipPrefabName); if (text == "Stop") { v = 0f; } v = Safe(v); float v2 = NjordBoatController.ApplyAcceleration(v, fixedDeltaTime); v2 = Safe(v2); float sailMult = NjordBoatController.GetSailMult(njordSailState); sailMult = Safe(sailMult); if (text == "Half" || text == "Full") { NjordRuntimeConfig njordRuntimeConfig2 = NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig(); sailMult = ((!njordRuntimeConfig2.Wind_SystemEnable) ? (sailMult * num6) : (sailMult * num4)); } float num12 = Safe(v2 * sailMult * 0.85f); float num13 = Safe(NjordBoatController.GetReverseForce(fixedDeltaTime)); num12 = Mathf.Clamp(num12, 0f, 2000f); num13 = Mathf.Clamp(num13, 0f, 2000f); Ship val4 = (Ship)((__instance is Ship) ? __instance : null); if (val4 != null) { NjordRuntimeConfig njordRuntimeConfig3 = NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig(); if (njordRuntimeConfig3.Debug_Enable && njordRuntimeConfig3.Debug_PhysicsWind && (!_lastDebugLog.TryGetValue(val4, out var value2) || Time.time - value2 > 1f)) { _lastDebugLog[val4] = Time.time; string text2 = (njordRuntimeConfig3.Wind_SystemEnable ? "ON " : "OFF"); NjordDebug.Info($"[Physics] {shipPrefabName} | mode={text} | baseline={v:F1} | accel={v2:F1} | mult={sailMult:F2} | fwForce={num12:F1}"); if (njordRuntimeConfig3.Wind_SystemEnable) { NjordDebug.Info($"[Wind] Sys:{text2} | AlwaysFull:{njordRuntimeConfig3.Wind_AlwaysFull} | NatAngle:{num2:F1}° | TgtAngle:{num3:F1}° | CurAngle:{num5:F1}° | Throttle:{num4:F2}"); } } } object? obj3 = AccessTools.Property(type, "transform")?.GetValue(__instance); Transform val5 = (Transform)((obj3 is Transform) ? obj3 : null); if ((Object)(object)val5 == (Object)null) { return; } if (flag2) { Vector3 val6; switch (njordSailState) { case NjordSailState.Backward: val6 = -val5.forward * num13; break; case NjordSailState.Forward: case NjordSailState.Half: case NjordSailState.Full: val6 = val5.forward * num12; break; default: val6 = Vector3.zero; break; } Vector3 val7 = val6; if (((Vector3)(ref val7)).sqrMagnitude > 0.0001f) { val.AddForce(val7 * val.mass * fixedDeltaTime, (ForceMode)1); } } Ship val8 = (Ship)((__instance is Ship) ? __instance : null); if (val8 != null) { float maxSpeedForShip = NjordShipSpeed.GetMaxSpeedForShip(val8); if (maxSpeedForShip > 0f) { Vector3 linearVelocity = val.linearVelocity; float magnitude = ((Vector3)(ref linearVelocity)).magnitude; if (magnitude > maxSpeedForShip && magnitude > 0.0001f) { Vector3 linearVelocity2 = ((Vector3)(ref linearVelocity)).normalized * maxSpeedForShip; val.linearVelocity = linearVelocity2; if (value && flag) { NjordDebug.Debug($"[SeaDog][Limiter] {((Object)val8).name} {magnitude:0.00} → {maxSpeedForShip:0.00}"); } } } } if (!flag2) { return; } Ship val9 = (Ship)((__instance is Ship) ? __instance : null); if (val9 == null) { return; } if (value && flag) { NjordDebug.Debug($"[SeaDog] Controlled ship tick: speedState={text}, vel={val9.GetSpeed():0.0}"); } _telemetryTimer += fixedDeltaTime; if (_telemetryTimer >= 0.2f) { _telemetryTimer = 0f; Vector3 position = ((Component)val9).transform.position; WaterVolume val10 = null; float waterLevel = Floating.GetWaterLevel(position, ref val10); float num14 = position.y - waterLevel - val9.m_waterLevelOffset; bool floating = num14 <= val9.m_disableLevel; WearNTear component = ((Component)val9).GetComponent(); if ((Object)(object)component != (Object)null) { Type typeFromHandle = typeof(WearNTear); object? obj4 = AccessTools.Field(typeFromHandle, "m_nview")?.GetValue(component); ZNetView val11 = (ZNetView)((obj4 is ZNetView) ? obj4 : null); if ((Object)(object)val11 != (Object)null && val11.IsValid()) { float num15 = Mathf.Max(1f, Safe(component.m_health)); float v3 = val11.GetZDO().GetFloat(ZDOVars.s_health, num15); v3 = Mathf.Max(0f, Safe(v3)); Njord_Telemetry.SetHP(v3, num15); } else { Njord_Telemetry.SetHP(0f, 1f); } } else { Njord_Telemetry.SetHP(0f, 1f); } float num16 = Safe(val9.GetSpeed()); float num17 = Safe(v); Njord_Telemetry.UpdateBasic(val9, waterLevel, num14, floating, Njord_ShipControlTracker.ReadyTimer, Njord_ShipControlTracker.SteeringGateReady); Njord_Telemetry.UpdateSpeed(_prevNjordSpeed, num16, _prevVanillaSpeed, num17); _prevNjordSpeed = num16; _prevVanillaSpeed = num17; } NjordSeaDogEngineVFXTriggers.Process(val9, njordSailState, text, controllerForShip, Time.time, val5, value, NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig()); } } [HarmonyPatch(typeof(Hud), "UpdateShipHud")] public static class NjordTheWindsCall { [HarmonyPostfix] public static void Postfix(Hud __instance, Player player, float dt) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_0351: 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_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0285: 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_0225: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_034d: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || (Object)(object)player == (Object)null) { return; } Ship controlledShip = player.GetControlledShip(); if ((Object)(object)controlledShip == (Object)null) { return; } NjordRuntimeConfig runtimeConfig = NjordSync.RuntimeConfig; if (runtimeConfig == null || !runtimeConfig.Wind_SystemEnable) { return; } float shipWindAngle = Njord_ShipControlTracker.GetShipWindAngle(controlledShip); FieldInfo fieldInfo = AccessTools.Field(typeof(Hud), "m_shipWindIconRoot"); if (fieldInfo != null) { object? value = fieldInfo.GetValue(__instance); RectTransform val = (RectTransform)((value is RectTransform) ? value : null); if ((Object)(object)val != (Object)null) { ((Transform)val).localRotation = Quaternion.Euler(0f, 0f, shipWindAngle); } } Image shipWindIcon = __instance.m_shipWindIcon; if ((Object)(object)shipWindIcon == (Object)null) { return; } float num = Mathf.DeltaAngle(0f, controlledShip.GetWindAngle()); float num2 = num; float num3 = Mathf.Abs(num); bool flag = num3 > 130f; if (runtimeConfig.Wind_AlwaysFull) { num2 = 0f; } else { float num4 = num; if (flag && runtimeConfig.Wind_NoDeadZone) { FieldInfo fieldInfo2 = AccessTools.Field(typeof(Ship), "m_rudder") ?? AccessTools.Field(typeof(Ship), "m_rudderValue"); float num5 = ((fieldInfo2 != null) ? ((float)fieldInfo2.GetValue(controlledShip)) : 0f); float num6 = 115f; num4 = ((num5 > 0.05f) ? (0f - num6) : ((!(num5 < -0.05f)) ? ((num > 0f) ? num6 : (0f - num6)) : num6)); } else if (!flag && runtimeConfig.Wind_BlendToFull) { num4 = 0f; } float shipGraceTimer = Njord_ShipControlTracker.GetShipGraceTimer(controlledShip); num2 = ((!(shipGraceTimer < runtimeConfig.Wind_GracePeriodDelay)) ? num4 : num); } float num7 = Mathf.Abs(shipWindAngle); Color color = Color.white; if (Mathf.Abs(Mathf.DeltaAngle(shipWindAngle, num2)) > 2f && (runtimeConfig.Wind_AlwaysFull || runtimeConfig.Wind_NoDeadZone || runtimeConfig.Wind_BlendToFull)) { float num8 = (Mathf.Sin(Time.time * 6f) + 1f) / 2f; color = ((!flag) ? Color.Lerp(new Color(0.4f, 0.7f, 1f, 1f), new Color(0.1f, 0.3f, 1f, 1f), num8) : Color.Lerp(new Color(1f, 0.4f, 0.4f, 1f), new Color(1f, 0.1f, 0.1f, 1f), num8)); } else if (flag) { ((Color)(ref color))..ctor(1f, 0.2f, 0.2f, 1f); } else if (num7 <= 45f) { color = Color.green; } else if (num7 <= 90f) { float num9 = (num7 - 45f) / 45f; color = Color.Lerp(new Color(0.3f, 0.6f, 1f, 1f), Color.green, 1f - num9); } else { float num10 = (num7 - 90f) / 40f; color = Color.Lerp(Color.white, new Color(0.3f, 0.6f, 1f, 1f), 1f - num10); } ((Graphic)shipWindIcon).color = color; } } [HarmonyPatch(typeof(Ship), "OnDestroy")] public static class Njord_Ship_Destroy_Patch { [HarmonyPostfix] public static void Postfix(Ship __instance) { try { if ((Object)(object)__instance != (Object)null) { NjordRuneVFX.RemoveEmitterForShip(__instance); } } catch { } } } [HarmonyPatch(typeof(Player), "OnSpawned")] public static class Njord_PlayerSpawned_Init { [HarmonyPostfix] public static void Postfix(Player __instance) { ((MonoBehaviour)__instance).StartCoroutine(DelayedNjordInit()); } private static IEnumerator DelayedNjordInit() { yield return null; yield return null; yield return null; yield return null; NjordDebug.Info("\ud83c\udf0a NjordSync initializing AFTER player spawn…"); NjordSync.Initialize(); NjordAuthorityEngine.Initialize(); NjordDebug.Info("\ud83c\udf0a NjordSync + Authority fully initialized."); } } [HarmonyPatch(typeof(Ship), "ApplyControlls")] public static class Patch_Ship_ApplyControlls { [HarmonyPostfix] public static void Postfix(Ship __instance) { if (!((Object)(object)__instance == (Object)null)) { float fixedDeltaTime = Time.fixedDeltaTime; Type type = ((object)__instance).GetType(); FieldInfo fieldInfo = AccessTools.Field(type, "m_rudder") ?? AccessTools.Field(type, "m_rudderValue"); float num = 0f; if (fieldInfo != null) { num = (float)fieldInfo.GetValue(__instance); } float steeringMultiplier = NjordSync.RuntimeConfig.SteeringMultiplier; float njord = num * steeringMultiplier; Njord_Telemetry.ReportRudder(num, njord, steeringMultiplier); } } } } namespace Njord.HUD { public static class NjordHudManager { private static bool _initialized = false; private static bool _hudCreated = false; private static bool _stylesCreated = false; private static Rect _hudRect; private static bool _dragging = false; private static Vector2 _dragStartMouse; private static Vector2 _dragStartHud; private static GUIStyle _headerStyle; private static GUIStyle _sectionStyle; private static GUIStyle _labelStyle; private static GUIStyle _smallLabelStyle; private static GUIStyle _hpBgStyle; private static GUIStyle _hpFillStyle; private static readonly Color _bgColor = new Color(0f, 0f, 0f, 0.7f); private const float WIDTH = 360f; private const float HEIGHT = 570f; public static void Initialize() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (!_initialized) { _initialized = true; _hudRect = new Rect(Plugin.HudPositionX.Value, Plugin.HudPositionY.Value, 360f, 570f); } } public static void CreateHud() { if (!_hudCreated) { _hudCreated = true; NjordDebug.Info("[HUD] Njord HUD initialized."); } } public static void OnGUI() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) if (_initialized && _hudCreated && Njord_ShipControlTracker.ShouldShowHud) { CreateStylesIfNeeded(); GUI.color = _bgColor; GUI.Box(_hudRect, GUIContent.none); GUI.color = Color.white; GUILayout.BeginArea(_hudRect); GUILayout.BeginVertical(Array.Empty()); GUILayout.Label("⚓ NJORD READOUT ⚓", _headerStyle, Array.Empty()); GUILayout.Space(4f); GUILayout.Label("Vessel: " + Njord_Telemetry.VesselName, _labelStyle, Array.Empty()); string text = "Status: " + (Njord_Telemetry.IsFloating ? "Floating ✓" : "Not Floating ✗") + " Steering Gate: " + (Njord_Telemetry.GateReady ? "Open ✓" : "Closed ✗"); GUILayout.Label(text, _smallLabelStyle, Array.Empty()); GUILayout.Space(4f); GUILayout.Label("── Waterline ─────────────────────────────", _sectionStyle, Array.Empty()); string text2 = (Njord_Telemetry.WaterError ? "—" : Njord_Telemetry.WaterLevel.ToString("F2")); string text3 = (Njord_Telemetry.WaterError ? "—" : Njord_Telemetry.BoatY.ToString("F2")); string arg = (Njord_Telemetry.DepthError ? "—" : Njord_Telemetry.Depth.ToString("F3")); GUILayout.Label("Water Level: " + text2, _labelStyle, Array.Empty()); GUILayout.Label("Boat Y: " + text3, _labelStyle, Array.Empty()); GUILayout.Label($"Depth: {arg} (Disable: {Njord_Telemetry.DisableLevel:F3})", _labelStyle, Array.Empty()); GUILayout.Label($"Readiness: {Njord_Telemetry.ReadinessTimer:F2} / {Njord_Telemetry.ReadinessMax:F2}", _labelStyle, Array.Empty()); GUILayout.Space(4f); GUILayout.Label("── Hull Integrity ───────────────────────", _sectionStyle, Array.Empty()); float hPCurrent = Njord_Telemetry.HPCurrent; float num = Mathf.Max(Njord_Telemetry.HPMax, 1f); float num2 = Mathf.Clamp01(hPCurrent / num); GUILayout.Label($"HP: {hPCurrent:F0} / {num:F0} ({num2 * 100f:F1}%)", _labelStyle, Array.Empty()); Rect lastRect = GUILayoutUtility.GetLastRect(); float num3 = 340f; float num4 = 10f; Rect val = default(Rect); ((Rect)(ref val))..ctor(10f, ((Rect)(ref lastRect)).yMax + 2f, num3, num4); GUI.Box(val, GUIContent.none, _hpBgStyle); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref val)).x, ((Rect)(ref val)).y, ((Rect)(ref val)).width * num2, ((Rect)(ref val)).height); GUI.Box(val2, GUIContent.none, _hpFillStyle); GUILayout.Space(22f); GUILayout.Label("── Steering ─────────────────────────────", _sectionStyle, Array.Empty()); string text4 = (Njord_Telemetry.RudderError ? "—" : Njord_Telemetry.RudderVanilla.ToString("F2")); string text5 = (Njord_Telemetry.RudderError ? "—" : Njord_Telemetry.RudderNjord.ToString("F2")); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Vanilla: " + text4, _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }); GUILayout.Label("Njord: " + text5, _labelStyle, Array.Empty()); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label($"Mult: {Njord_Telemetry.SteeringMultiplier:F2}x", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }); GUILayout.Label($"Gain: {Njord_Telemetry.SteeringGainPerSecond:+0.00;-0.00;0.00}", _labelStyle, Array.Empty()); GUILayout.EndHorizontal(); GUILayout.Space(4f); GUILayout.Label("── Speed ────────────────────────────────", _sectionStyle, Array.Empty()); string text6 = (Njord_Telemetry.SpeedError ? "—" : Njord_Telemetry.NjordSpeedCurr.ToString("F1")); string text7 = (Njord_Telemetry.SpeedError ? "—" : Njord_Telemetry.MortalSpeedCurr.ToString("F1")); string text8 = (Njord_Telemetry.SpeedError ? "—" : (Njord_Telemetry.NjordSpeedCurr - Njord_Telemetry.MortalSpeedCurr).ToString("0.0")); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Njord: " + text6 + " m/s", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }); GUILayout.Label("Mortal: " + text7 + " m/s", _labelStyle, Array.Empty()); GUILayout.EndHorizontal(); GUILayout.Label("Gift of the Deep: " + text8 + " m/s", _labelStyle, Array.Empty()); GUILayout.Space(4f); GUILayout.Label("── Wind ─────────────────────────────────", _sectionStyle, Array.Empty()); GUILayout.Label($"UI Blend: {Njord_Telemetry.WindUIBlend:F2}", _labelStyle, Array.Empty()); GUILayout.Label($"UI Color: ({Njord_Telemetry.WindUIColor.r:F2}, {Njord_Telemetry.WindUIColor.g:F2}, {Njord_Telemetry.WindUIColor.b:F2})", _labelStyle, Array.Empty()); GUILayout.Space(6f); GUILayout.Label("Press F7 to toggle HUD (drag anywhere to move)", _smallLabelStyle, Array.Empty()); GUILayout.EndVertical(); GUILayout.EndArea(); HandleDragging(); } } private static void HandleDragging() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Invalid comparison between Unknown and I4 //IL_0020: 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_00d4: Invalid comparison between Unknown and I4 //IL_0033: 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_0051: 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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Invalid comparison between Unknown and I4 //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) Event current = Event.current; if (current != null) { if ((int)current.type == 0 && current.button == 0 && ((Rect)(ref _hudRect)).Contains(current.mousePosition)) { _dragging = true; _dragStartMouse = current.mousePosition; _dragStartHud = new Vector2(((Rect)(ref _hudRect)).x, ((Rect)(ref _hudRect)).y); current.Use(); } if (_dragging && (int)current.type == 3 && current.button == 0) { Vector2 val = current.mousePosition - _dragStartMouse; ((Rect)(ref _hudRect)).x = _dragStartHud.x + val.x; ((Rect)(ref _hudRect)).y = _dragStartHud.y + val.y; current.Use(); } if (_dragging && ((int)current.type == 1 || (int)current.rawType == 1)) { _dragging = false; Plugin.HudPositionX.Value = ((Rect)(ref _hudRect)).x; Plugin.HudPositionY.Value = ((Rect)(ref _hudRect)).y; current.Use(); } } } private static void CreateStylesIfNeeded() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_002c: 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_0050: Expected O, but got Unknown //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_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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_0092: Expected O, but got Unknown //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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Expected O, but got Unknown //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Expected O, but got Unknown //IL_0127: 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_014b: Expected O, but got Unknown //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Expected O, but got Unknown //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Expected O, but got Unknown if (!_stylesCreated) { _stylesCreated = true; GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 16, fontStyle = (FontStyle)1 }; val.normal.textColor = new Color(0.9f, 0.8f, 0.5f); _headerStyle = val; GUIStyle val2 = new GUIStyle(GUI.skin.label) { fontSize = 13, fontStyle = (FontStyle)1 }; val2.normal.textColor = new Color(0.85f, 0.75f, 0.55f); _sectionStyle = val2; GUIStyle val3 = new GUIStyle(GUI.skin.label) { fontSize = 12 }; val3.normal.textColor = new Color(0.95f, 0.9f, 0.8f); _labelStyle = val3; GUIStyle val4 = new GUIStyle(GUI.skin.label) { fontSize = 11 }; val4.normal.textColor = new Color(0.95f, 0.9f, 0.8f); _smallLabelStyle = val4; Texture2D val5 = new Texture2D(1, 1); val5.SetPixel(0, 0, new Color(0.2f, 0.05f, 0.05f, 0.8f)); val5.Apply(); _hpBgStyle = new GUIStyle(GUI.skin.box); _hpBgStyle.normal.background = val5; Texture2D val6 = new Texture2D(1, 1); val6.SetPixel(0, 0, new Color(0.1f, 0.7f, 0.1f, 0.9f)); val6.Apply(); _hpFillStyle = new GUIStyle(GUI.skin.box); _hpFillStyle.normal.background = val6; } } } public static class NjordReleaseIndicator { private static GUIStyle labelStyle; private static void EnsureStyle() { //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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown if (labelStyle == null) { GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 14, fontStyle = (FontStyle)1 }; val.normal.textColor = Color.white; labelStyle = val; } } public static void Draw() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Player.m_localPlayer == (Object)null) && Njord_ShipControlTracker.CurrentController != 0L && Plugin.HudEnabledByUser.Value) { EnsureStyle(); float num = 40f; float num2 = (float)Screen.height - 220f; GUI.Label(new Rect(num, num2, 400f, 40f), "Release [E] to leave helm", labelStyle); } } } } namespace Njord.Core { public static class NjordAuthorityEngine { private static readonly Dictionary ServerAuthorityMap = new Dictionary(); private static bool _initialized = false; public static bool UseLegacyFallback { get; private set; } = false; public static void Initialize() { if (_initialized) { return; } try { if (ZRoutedRpc.instance == null) { NjordDebug.Error("[Authority] ZRoutedRpc not ready; enabling legacy fallback."); UseLegacyFallback = true; return; } ZRoutedRpc.instance.Register("Njord_RequestControl", (Action)RPC_RequestControl); ZRoutedRpc.instance.Register("Njord_ReleaseControl", (Action)RPC_ReleaseControl); ZRoutedRpc.instance.Register("Njord_RequestAuthorityState", (Action)RPC_RequestAuthorityState); ZRoutedRpc.instance.Register("Njord_AuthorityUpdate", (Action)RPC_AuthorityUpdate); ZRoutedRpc.instance.Register("Njord_AuthoritySyncAll", (Action)RPC_AuthoritySyncAll); _initialized = true; NjordDebug.Info("[Authority] NjordAuthorityEngine initialized (RPC-only, server-authoritative)."); } catch (Exception arg) { NjordDebug.Error($"[Authority] Initialization failed; enabling legacy fallback. Exception: {arg}"); UseLegacyFallback = true; } } public static void Server_OnHelmClaim(Ship ship, long playerID) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (!UseLegacyFallback && !((Object)(object)ship == (Object)null) && IsServer() && TryGetShipZdoID(ship, out var id)) { ServerAuthorityMap[id] = playerID; BroadcastAuthorityUpdate(id, playerID); ZNetView component = ((Component)ship).GetComponent(); if ((Object)(object)component != (Object)null && component.IsValid()) { component.ClaimOwnership(); } } } public static void Server_OnHelmRelease(Ship ship) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (!UseLegacyFallback && !((Object)(object)ship == (Object)null) && IsServer() && TryGetShipZdoID(ship, out var id)) { ServerAuthorityMap[id] = 0L; BroadcastAuthorityUpdate(id, 0L); ZNetView component = ((Component)ship).GetComponent(); if ((Object)(object)component != (Object)null && component.IsValid() && !component.IsOwner()) { component.ClaimOwnership(); } } } public static void Client_RequestControl(Ship ship) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) if (!UseLegacyFallback && !((Object)(object)ship == (Object)null) && !IsServer() && TryGetShipZdoID(ship, out var id)) { long num = (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : 0); if (num != 0L && ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC("Njord_RequestControl", new object[2] { id, num }); } } } public static void Client_ReleaseControl(Ship ship) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) if (!UseLegacyFallback && !((Object)(object)ship == (Object)null) && !IsServer() && TryGetShipZdoID(ship, out var id)) { long num = (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : 0); if (num != 0L && ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC("Njord_ReleaseControl", new object[2] { id, num }); } } } private static void RPC_RequestControl(long sender, ZDOID shipID, long playerID) { //IL_0018: 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_0032: 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) if (UseLegacyFallback || !IsServer() || playerID == 0L) { return; } ServerAuthorityMap[shipID] = playerID; BroadcastAuthorityUpdate(shipID, playerID); ZDOMan instance = ZDOMan.instance; ZDO val = ((instance != null) ? instance.GetZDO(shipID) : null); if (val != null) { val.SetOwner(sender); if (NjordConfig.Debug_Enable.Value) { NjordDebug.Debug($"[Authority] ZDO ownership → peer {sender} for ship {shipID}"); } } } private static void RPC_ReleaseControl(long sender, ZDOID shipID, long playerID) { //IL_0014: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) if (UseLegacyFallback || !IsServer() || (ServerAuthorityMap.TryGetValue(shipID, out var value) && value != playerID)) { return; } ServerAuthorityMap[shipID] = 0L; BroadcastAuthorityUpdate(shipID, 0L); ZDOMan instance = ZDOMan.instance; ZDO val = ((instance != null) ? instance.GetZDO(shipID) : null); if (val == null) { return; } ZNetScene instance2 = ZNetScene.instance; ZNetView val2 = ((instance2 != null) ? instance2.FindInstance(val) : null); if (!((Object)(object)val2 != (Object)null)) { return; } ZNetView component = ((Component)val2).GetComponent(); if ((Object)(object)component != (Object)null && component.IsValid()) { component.ClaimOwnership(); if (NjordConfig.Debug_Enable.Value) { NjordDebug.Debug($"[Authority] ZDO ownership reclaimed by server for ship {shipID}"); } } } private static void RPC_RequestAuthorityState(long sender, ZDOID shipID) { //IL_0017: 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) if (!UseLegacyFallback && IsServer()) { long value = 0L; ServerAuthorityMap.TryGetValue(shipID, out value); if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(sender, "Njord_AuthorityUpdate", new object[2] { shipID, value }); } } } private static void RPC_AuthorityUpdate(long sender, ZDOID shipID, long controllerID) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (UseLegacyFallback) { return; } ZDO zDO = ZDOMan.instance.GetZDO(shipID); if (zDO == null) { return; } ZNetView val = ZNetScene.instance.FindInstance(zDO); if ((Object)(object)val == (Object)null) { return; } Ship component = ((Component)val).GetComponent(); if (!((Object)(object)component == (Object)null)) { if (controllerID != 0L) { Njord_ShipControlTracker.SetControl(component, controllerID); } else { Njord_ShipControlTracker.ClearControl(component); } } } private static void RPC_AuthoritySyncAll(long sender, ZPackage pkg) { //IL_0033: 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) if (UseLegacyFallback) { return; } int num = pkg.ReadInt(); long num2 = (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : 0); long controller = 0L; for (int i = 0; i < num; i++) { ZDOID val = pkg.ReadZDOID(); long num3 = pkg.ReadLong(); if (num2 != 0L && num3 == num2) { controller = num3; } } Njord_ShipControlTracker.UpdateController(controller, 0f); } private static bool IsServer() { if ((Object)(object)ZNet.instance != (Object)null) { return ZNet.instance.IsServer(); } return false; } private static bool TryGetShipZdoID(Ship ship, out ZDOID id) { //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_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) id = ZDOID.None; if ((Object)(object)ship == (Object)null) { return false; } ZNetView component = ((Component)ship).GetComponent(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return false; } ZDO zDO = component.GetZDO(); if (zDO == null) { return false; } id = zDO.m_uid; return true; } private static void BroadcastAuthorityUpdate(ZDOID shipID, long controllerID) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "Njord_AuthorityUpdate", new object[2] { shipID, controllerID }); } } } public static class NjordConfig { public static ConfigEntry Wind_SystemEnable; public static ConfigEntry Wind_AlwaysFull; public static ConfigEntry Wind_NoDeadZone; public static ConfigEntry Wind_BlendToFull; public static ConfigEntry Wind_BlendRate; public static ConfigEntry Wind_GracePeriodDelay; public static ConfigEntry SteeringMultiplier; public static ConfigEntry AccelerationMultiplier; public static ConfigEntry BaseForwardForce; public static ConfigEntry BaseReverseForce; public static ConfigEntry SailForwardForce; public static ConfigEntry HalfSailForce; public static ConfigEntry FullSailForce; public static ConfigEntry ReverseKick; public static ConfigEntry MaxSpeed_Raft; public static ConfigEntry MaxSpeed_Karve; public static ConfigEntry MaxSpeed_Longship; public static ConfigEntry MaxSpeed_Drakkar; public static ConfigEntry MaxSpeed_MercantShip; public static ConfigEntry MaxSpeed_CargoShip; public static ConfigEntry MaxSpeed_BigCargoShip; public static ConfigEntry MaxSpeed_RowingCanoe; public static ConfigEntry MaxSpeed_DoubleRowingCanoe; public static ConfigEntry MaxSpeed_LittleBoat; public static ConfigEntry MaxSpeed_WarShip; public static ConfigEntry VFX_Enable; public static ConfigEntry VFX_Color; public static ConfigEntry Debug_Enable; public static ConfigEntry Debug_PhysicsWind; public static ConfigEntry Debug_AuthControl; public static void Bind(ConfigFile file) { //IL_03ea: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Expected O, but got Unknown //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Expected O, but got Unknown //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Expected O, but got Unknown //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Expected O, but got Unknown //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Expected O, but got Unknown //IL_0369: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Expected O, but got Unknown //IL_03a1: Unknown result type (might be due to invalid IL or missing references) //IL_03ab: Expected O, but got Unknown Wind_SystemEnable = file.Bind("2 - Wind System", "Wind_SystemEnable", true, "Master switch for Njord wind physics and UI."); Wind_AlwaysFull = file.Bind("2 - Wind System", "Wind_AlwaysFull", true, "Always gives perfect tailwind, ignoring all other rules."); Wind_NoDeadZone = file.Bind("2 - Wind System", "Wind_NoDeadZone", false, "[EXPERIMENTAL] Enables nudging the wind just out of the dead zone (to the 130° edge)."); Wind_BlendToFull = file.Bind("2 - Wind System", "Wind_BlendToFull", false, "[EXPERIMENTAL] Enables nudging the wind from the crosswind line to the perfect tailwind line."); Wind_BlendRate = file.Bind("2 - Wind System", "Wind_BlendRate", 30f, "How fast the wind adjusts (degrees per second)."); Wind_GracePeriodDelay = file.Bind("2 - Wind System", "Wind_GracePeriodDelay", 2.5f, "Delay in seconds before the wind system starts assisting."); SteeringMultiplier = file.Bind("3 - Steering", "SteeringMultiplier", 1.85f, "Multiplier applied to rudder steering."); AccelerationMultiplier = file.Bind("4 - Acceleration", "AccelerationMultiplier", 2.2f, "Acceleration multiplier."); BaseForwardForce = file.Bind("4 - Acceleration", "BaseForwardForce", 0.85f, "Base forward force."); BaseReverseForce = file.Bind("4 - Acceleration", "BaseReverseForce", 0.2f, "Base reverse force."); SailForwardForce = file.Bind("5 - Sails", "SailForwardForce", 0.3f, "Forward force when sails are down."); HalfSailForce = file.Bind("5 - Sails", "HalfSailForce", 1.2f, "Forward force at half sail."); FullSailForce = file.Bind("5 - Sails", "FullSailForce", 4.2f, "Forward force at full sail."); ReverseKick = file.Bind("5 - Sails", "ReverseKick", 1.8f, "Reverse kick multiplier."); MaxSpeed_Raft = file.Bind("6 - Speed Limits", "MaxSpeed_Raft", 7f, "Absolute max speed for the Raft (m/s)."); MaxSpeed_Karve = file.Bind("6 - Speed Limits", "MaxSpeed_Karve", 16.8f, "Absolute max speed for the Karve (m/s)."); MaxSpeed_Longship = file.Bind("6 - Speed Limits", "MaxSpeed_Longship", 26f, "Absolute max speed for the Longship (m/s)."); MaxSpeed_Drakkar = file.Bind("6 - Speed Limits", "MaxSpeed_Drakkar", 30f, "Absolute max speed for the Drakkar (m/s)."); if (Plugin.OdinShipDetected) { MaxSpeed_MercantShip = file.Bind("7 - OdinShip Speed Limits", "MaxSpeed_MercantShip", 22f, new ConfigDescription("Max speed for MercantShip (m/s).", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 100f), Array.Empty())); MaxSpeed_CargoShip = file.Bind("7 - OdinShip Speed Limits", "MaxSpeed_CargoShip", 20f, new ConfigDescription("Max speed for CargoShip (m/s).", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 100f), Array.Empty())); MaxSpeed_BigCargoShip = file.Bind("7 - OdinShip Speed Limits", "MaxSpeed_BigCargoShip", 23.5f, new ConfigDescription("Max speed for BigCargoShip (m/s).", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 100f), Array.Empty())); MaxSpeed_RowingCanoe = file.Bind("7 - OdinShip Speed Limits", "MaxSpeed_RowingCanoe", 10f, new ConfigDescription("Max speed for RowingCanoe (m/s).", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 100f), Array.Empty())); MaxSpeed_DoubleRowingCanoe = file.Bind("7 - OdinShip Speed Limits", "MaxSpeed_DoubleRowingCanoe", 12f, new ConfigDescription("Max speed for DoubleRowingCanoe (m/s).", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 100f), Array.Empty())); MaxSpeed_LittleBoat = file.Bind("7 - OdinShip Speed Limits", "MaxSpeed_LittleBoat", 17f, new ConfigDescription("Max speed for LittleBoat (m/s).", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 100f), Array.Empty())); MaxSpeed_WarShip = file.Bind("7 - OdinShip Speed Limits", "MaxSpeed_WarShip", 32f, new ConfigDescription("Max speed for WarShip (m/s).", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 100f), Array.Empty())); } VFX_Enable = file.Bind("8 - VFX", "VFX_Enable", true, "Enable rune VFX."); VFX_Color = file.Bind("8 - VFX", "VFX_Color", new Color(0.3f, 0.6f, 1f, 1f), "Rune VFX color."); Debug_Enable = file.Bind("9 - Debug", "Debug_Enable", false, "Master switch to enable Njord debug logs."); Debug_PhysicsWind = file.Bind("9 - Debug", "Debug_PhysicsWind", false, "Enable logging for Wind calculations and Physics."); Debug_AuthControl = file.Bind("9 - Debug", "Debug_AuthControl", false, "Enable logging for ship ownership and control."); } } public class NjordRuntimeConfig { public float SteeringMultiplier; public float AccelerationMultiplier; public float BaseForwardForce; public float BaseReverseForce; public float SailForwardForce; public float HalfSailForce; public float FullSailForce; public float ReverseKick; public bool Wind_SystemEnable; public bool Wind_AlwaysFull; public bool Wind_NoDeadZone; public bool Wind_BlendToFull; public float Wind_BlendRate; public float Wind_GracePeriodDelay; public bool VFX_Enable; public Color VFX_Color; public bool Debug_Enable; public bool Debug_PhysicsWind; public bool Debug_AuthControl; public float MaxSpeed_Raft; public float MaxSpeed_Karve; public float MaxSpeed_Longship; public float MaxSpeed_Drakkar; public static NjordRuntimeConfig FromConfig() { //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) return new NjordRuntimeConfig { SteeringMultiplier = NjordConfig.SteeringMultiplier.Value, AccelerationMultiplier = NjordConfig.AccelerationMultiplier.Value, BaseForwardForce = NjordConfig.BaseForwardForce.Value, BaseReverseForce = NjordConfig.BaseReverseForce.Value, SailForwardForce = NjordConfig.SailForwardForce.Value, HalfSailForce = NjordConfig.HalfSailForce.Value, FullSailForce = NjordConfig.FullSailForce.Value, ReverseKick = NjordConfig.ReverseKick.Value, Wind_SystemEnable = NjordConfig.Wind_SystemEnable.Value, Wind_AlwaysFull = NjordConfig.Wind_AlwaysFull.Value, Wind_NoDeadZone = NjordConfig.Wind_NoDeadZone.Value, Wind_BlendToFull = NjordConfig.Wind_BlendToFull.Value, Wind_BlendRate = NjordConfig.Wind_BlendRate.Value, Wind_GracePeriodDelay = NjordConfig.Wind_GracePeriodDelay.Value, VFX_Enable = NjordConfig.VFX_Enable.Value, VFX_Color = NjordConfig.VFX_Color.Value, Debug_Enable = NjordConfig.Debug_Enable.Value, Debug_PhysicsWind = NjordConfig.Debug_PhysicsWind.Value, Debug_AuthControl = NjordConfig.Debug_AuthControl.Value, MaxSpeed_Raft = NjordConfig.MaxSpeed_Raft.Value, MaxSpeed_Karve = NjordConfig.MaxSpeed_Karve.Value, MaxSpeed_Longship = NjordConfig.MaxSpeed_Longship.Value, MaxSpeed_Drakkar = NjordConfig.MaxSpeed_Drakkar.Value }; } public void WriteToPackage(ZPackage pkg) { pkg.Write(SteeringMultiplier); pkg.Write(AccelerationMultiplier); pkg.Write(BaseForwardForce); pkg.Write(BaseReverseForce); pkg.Write(SailForwardForce); pkg.Write(HalfSailForce); pkg.Write(FullSailForce); pkg.Write(ReverseKick); pkg.Write(Wind_SystemEnable); pkg.Write(Wind_AlwaysFull); pkg.Write(Wind_NoDeadZone); pkg.Write(Wind_BlendToFull); pkg.Write(Wind_BlendRate); pkg.Write(VFX_Enable); pkg.Write(VFX_Color.r); pkg.Write(VFX_Color.g); pkg.Write(VFX_Color.b); pkg.Write(VFX_Color.a); pkg.Write(Debug_Enable); pkg.Write(Debug_PhysicsWind); pkg.Write(Debug_AuthControl); } public void ReadFromPackage(ZPackage pkg) { //IL_00c9: 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) SteeringMultiplier = pkg.ReadSingle(); AccelerationMultiplier = pkg.ReadSingle(); BaseForwardForce = pkg.ReadSingle(); BaseReverseForce = pkg.ReadSingle(); SailForwardForce = pkg.ReadSingle(); HalfSailForce = pkg.ReadSingle(); FullSailForce = pkg.ReadSingle(); ReverseKick = pkg.ReadSingle(); Wind_SystemEnable = pkg.ReadBool(); Wind_AlwaysFull = pkg.ReadBool(); Wind_NoDeadZone = pkg.ReadBool(); Wind_BlendToFull = pkg.ReadBool(); Wind_BlendRate = pkg.ReadSingle(); VFX_Enable = pkg.ReadBool(); float num = pkg.ReadSingle(); float num2 = pkg.ReadSingle(); float num3 = pkg.ReadSingle(); float num4 = pkg.ReadSingle(); VFX_Color = new Color(num, num2, num3, num4); Debug_Enable = pkg.ReadBool(); Debug_PhysicsWind = pkg.ReadBool(); Debug_AuthControl = pkg.ReadBool(); } } public enum NjordSailState { Forward, Half, Full, Backward } public static class NjordShipSpeed { private static string CleanName(Ship ship) { if ((Object)(object)ship == (Object)null) { return "unknown"; } string name = ((Object)ship).name; if (string.IsNullOrEmpty(name)) { name = ((Object)((Component)ship).gameObject).name; } return name.Replace("(Clone)", "").Trim().ToLowerInvariant(); } public static float GetMaxSpeedForShip(Ship ship) { if ((Object)(object)ship == (Object)null) { return 0f; } string text = CleanName(ship); float num = 0f; if (text.Contains("raft")) { num = NjordConfig.MaxSpeed_Raft.Value; } else if (text.Contains("karve")) { num = NjordConfig.MaxSpeed_Karve.Value; } else if (text.Contains("longship")) { num = NjordConfig.MaxSpeed_Longship.Value; } else if (text.Contains("drakkar")) { num = NjordConfig.MaxSpeed_Drakkar.Value; } if (Plugin.OdinShipDetected) { if (text.Contains("mercantship")) { num = NjordConfig.MaxSpeed_MercantShip.Value; } else if (text.Contains("bigcargoship")) { num = NjordConfig.MaxSpeed_BigCargoShip.Value; } else if (text.Contains("cargoship")) { num = NjordConfig.MaxSpeed_CargoShip.Value; } else if (text.Contains("doublerowingcanoe")) { num = NjordConfig.MaxSpeed_DoubleRowingCanoe.Value; } else if (text.Contains("rowingcanoe")) { num = NjordConfig.MaxSpeed_RowingCanoe.Value; } else if (text.Contains("littleboat")) { num = NjordConfig.MaxSpeed_LittleBoat.Value; } else if (text.Contains("warship")) { num = NjordConfig.MaxSpeed_WarShip.Value; } } if (num <= 0f || float.IsNaN(num) || float.IsInfinity(num)) { return 0f; } return num; } } public static class NjordSync { private const string RPC_CONFIG = "Njord_Config"; private const string RPC_CONFIG_UPDATE = "Njord_ConfigUpdate"; private static bool _initialized; public static NjordRuntimeConfig RuntimeConfig { get; private set; } public static void Initialize() { if (!_initialized && !((Object)(object)ZNet.instance == (Object)null)) { RuntimeConfig = NjordRuntimeConfig.FromConfig(); RegisterRpcs(); if (ZNet.instance.IsServer()) { BroadcastConfig(); } _initialized = true; NjordDebug.Info("[Sync] RuntimeConfig loaded at init: " + $"BaseForward={RuntimeConfig.BaseForwardForce}, " + $"Accel={RuntimeConfig.AccelerationMultiplier}, " + $"Full={RuntimeConfig.FullSailForce}"); } } public static void ReloadRuntimeConfig() { RuntimeConfig = NjordRuntimeConfig.FromConfig(); if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { BroadcastConfig(); } NjordDebug.Info("[Sync] RuntimeConfig reloaded (client or server)."); } private static void RegisterRpcs() { if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.Register("Njord_Config", (Action)RPC_ReceiveConfig); ZRoutedRpc.instance.Register("Njord_ConfigUpdate", (Action)RPC_ReceiveConfigUpdate); } } private static void BroadcastConfig() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown if (ZRoutedRpc.instance != null) { ZPackage val = new ZPackage(); RuntimeConfig.WriteToPackage(val); ZRoutedRpc.instance.InvokeRoutedRPC("Njord_Config", new object[1] { val }); NjordDebug.Info("[Sync] Broadcasted runtime config to all clients."); } } private static void RPC_ReceiveConfig(long sender, ZPackage pkg) { NjordRuntimeConfig njordRuntimeConfig = new NjordRuntimeConfig(); njordRuntimeConfig.ReadFromPackage(pkg); RuntimeConfig = njordRuntimeConfig; NjordDebug.Info("[Sync] Received runtime config from server."); } public static void Client_RequestConfigUpdate() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown if (ZRoutedRpc.instance != null) { ZPackage val = new ZPackage(); RuntimeConfig.WriteToPackage(val); ZRoutedRpc.instance.InvokeRoutedRPC("Njord_ConfigUpdate", new object[1] { val }); NjordDebug.Info("[Sync] Client requested config update."); } } private static void RPC_ReceiveConfigUpdate(long sender, ZPackage pkg) { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer()) { if (!ZNet.instance.IsAdmin(sender.ToString())) { BroadcastConfig(); return; } NjordRuntimeConfig njordRuntimeConfig = new NjordRuntimeConfig(); njordRuntimeConfig.ReadFromPackage(pkg); RuntimeConfig = njordRuntimeConfig; BroadcastConfig(); NjordDebug.Info("[Sync] Admin updated config; broadcasted to clients."); } } public static void ServerReloadAndBroadcast() { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer()) { RuntimeConfig = NjordRuntimeConfig.FromConfig(); BroadcastConfig(); NjordDebug.Info("[Sync] Server reloaded config from disk and broadcast."); } } } public static class Njord_Telemetry { public static string VesselName = "Unknown"; public static bool GateReady = false; public static bool IsFloating = false; public static float WaterLevel = 0f; public static float BoatY = 0f; public static float Depth = 0f; public static float DisableLevel = 0f; public static float ReadinessTimer = 0f; public static float ReadinessMax = 0f; public static float HPCurrent = 0f; public static float HPMax = 1f; public static float RudderVanilla = 0f; public static float RudderNjord = 0f; public static float SteeringMultiplier = 1f; public static float SteeringGainPerSecond = 0f; private static float _lastRudder = 0f; private static float _lastRudderTime = 0f; public static float SpeedCurrent = 0f; public static float SpeedVanillaBaseline = 0f; public static float SpeedGainPerSecond = 0f; private static float _lastSpeed = 0f; private static float _lastSpeedTime = 0f; public static float NjordSpeedPrev = 0f; public static float NjordSpeedCurr = 0f; public static float MortalSpeedPrev = 0f; public static float MortalSpeedCurr = 0f; public static float WindUIBlend = 0f; public static Color WindUIColor = Color.white; public static bool HasError = false; public static bool DepthError = false; public static bool WaterError = false; public static bool SpeedError = false; public static bool RudderError = false; public static void ClearErrors() { HasError = (DepthError = (WaterError = (SpeedError = (RudderError = false)))); } public static void UpdateBasic(Ship ship, float waterLevel, float depth, bool floating, float readinessTimer, bool gateReady) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ship)) { return; } VesselName = ((Object)ship).name.Replace("(Clone)", "").Trim(); GateReady = gateReady; IsFloating = floating; ClearErrors(); if (float.IsNaN(waterLevel) || float.IsInfinity(waterLevel)) { WaterError = true; HasError = true; waterLevel = ((Component)ship).transform.position.y; } WaterLevel = waterLevel; BoatY = ((Component)ship).transform.position.y; if (float.IsNaN(depth) || float.IsInfinity(depth)) { DepthError = true; HasError = true; depth = 0f; } Depth = depth; DisableLevel = ship.m_disableLevel; ReadinessTimer = readinessTimer; ReadinessMax = 0.35f; float time = Time.time; if (_lastSpeedTime > 0f) { float num = time - _lastSpeedTime; if (num > 0f) { SpeedGainPerSecond = (SpeedCurrent - _lastSpeed) / num; } } _lastSpeed = SpeedCurrent; _lastSpeedTime = time; } public static void SetHP(float hp, float maxHp) { HPCurrent = Mathf.Max(0f, hp); HPMax = Mathf.Max(1f, maxHp); } public static void ReportRudder(float vanilla, float njord, float mult) { if (float.IsNaN(njord)) { RudderError = true; HasError = true; njord = 0f; } RudderVanilla = vanilla; RudderNjord = njord; SteeringMultiplier = mult; float time = Time.time; if (_lastRudderTime > 0f) { float num = time - _lastRudderTime; if (num > 0f) { SteeringGainPerSecond = (njord - _lastRudder) / num; } } _lastRudder = njord; _lastRudderTime = time; } public static void SetWindUI(float blend, Color color) { //IL_000b: 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) WindUIBlend = Mathf.Clamp01(blend); WindUIColor = color; } public static void SetVanillaSpeedBaseline(float baseline) { SpeedVanillaBaseline = baseline; } public static void UpdateSpeed(float prevNjord, float currNjord, float prevMortal, float currMortal) { if (float.IsNaN(currNjord)) { SpeedError = true; HasError = true; currNjord = 0f; } NjordSpeedPrev = prevNjord; NjordSpeedCurr = currNjord; MortalSpeedPrev = prevMortal; MortalSpeedCurr = currMortal; SpeedCurrent = currNjord; SpeedVanillaBaseline = currMortal; float time = Time.time; if (_lastSpeedTime > 0f) { float num = time - _lastSpeedTime; if (num > 0f) { SpeedGainPerSecond = (currNjord - _lastSpeed) / num; } } _lastSpeed = currNjord; _lastSpeedTime = time; } } public static class NjordPatchCaller { private static Harmony harmony; public static void ApplyPatches() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown if (harmony == null) { harmony = new Harmony("wubarrk.njord"); } NjordDebug.Log("When Njord stirs, the runes awaken…"); BindRune("Þráð‑Njörðr Rune", typeof(Njord_PlayerSpawned_Init), "Njord tugs the world‑threads taut; the longship joins the weave.", "The Thread‑Rune slips from Njord’s grasp, but the sea waits for no one."); BindRune("Njord’s Fang‑Rune", typeof(NjordSeaDogEngine), "The deep bares its fangs and drives the longship onward.", "The Fang‑Rune cracks, but the sea remembers its path."); BindRune("Hrafn‑Skygg Rune", typeof(NjordTheWindsCall), "The ravens whisper the winds’ hidden counsel.", "The Raven‑Sight Rune dims, yet the sky still watches."); BindRune("Stýri‑Hjarta Rune", typeof(Patch_Ship_ApplyControlls), "The helm‑heart beats in rhythm with mortal will.", "The Helm‑Heart falters, but the rudder keeps its vigil."); BindRune("Band‑Njörðr Rune", typeof(NjordDoodadControlRune), "Njord knots the helmsman’s spirit to the vessel’s wyrd.", "The Binding Rune slips, yet the helm awaits another hand."); BindRune("Leys‑Njörðr Rune", typeof(NjordDoodadReleaseRune), "Njord loosens the knot; the helm drifts free into quiet waters.", "The Loosening Rune fades, but the sea releases its hold."); NjordDebug.Log("The longship answers the call of the deep."); } private static void BindRune(string runeName, Type patchType, string successSaga, string failureSaga) { NjordDebug.Log("Invoking " + runeName + "…"); try { harmony.PatchAll(patchType); NjordDebug.Log(successSaga); } catch (Exception ex) { NjordDebug.Warn(failureSaga ?? ""); NjordDebug.Warn("Rune‑scribe’s note: " + ex.Message); } } } public static class NjordRuneTextureGenerator { private const int Size = 128; public unsafe static Texture2D GenerateRune(Color color) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Abs(((object)(*(Color*)(&color))/*cast due to .constrained prefix*/).GetHashCode()); int runeIndex = num % 16; return GenerateRune(color, runeIndex); } public static Texture2D GenerateSoftTrail(Color color) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_009b: 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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false); ((Texture)val).filterMode = (FilterMode)1; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(64f, 64f); float num = 64f; Vector2 val3 = default(Vector2); Color val4 = default(Color); for (int i = 0; i < 128; i++) { for (int j = 0; j < 128; j++) { ((Vector2)(ref val3))..ctor((float)j + 0.5f, (float)i + 0.5f); float num2 = Vector2.Distance(val3, val2) / num; float num3 = Mathf.Clamp01(1f - num2); num3 = Mathf.SmoothStep(0f, 1f, num3); num3 = Mathf.Pow(num3, 1.6f); ((Color)(ref val4))..ctor(color.r, color.g, color.b, color.a * num3); val.SetPixel(j, i, val4); } } val.Apply(true); return val; } public static Texture2D GenerateStreak(Color color) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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_00b1: 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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false); ((Texture)val).filterMode = (FilterMode)1; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(64f, 64f); float num = 64f; Color val3 = default(Color); for (int i = 0; i < 128; i++) { for (int j = 0; j < 128; j++) { float num2 = Mathf.Abs((float)i + 0.5f - val2.y) / num; float num3 = Mathf.Abs((float)j + 0.5f - val2.x) / (num * 0.6f); float num4 = Mathf.Clamp01(1f - num3); float num5 = Mathf.SmoothStep(1f, 0f, num2); num4 *= Mathf.Pow(num5, 0.9f); ((Color)(ref val3))..ctor(color.r, color.g, color.b, color.a * num4); val.SetPixel(j, i, val3); } } val.Apply(true); return val; } public static Texture2D GenerateBlend(Color color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0034: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_0076: 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) Texture2D val = GenerateSoftTrail(color); Texture2D val2 = GenerateRune(color); Texture2D val3 = new Texture2D(128, 128, (TextureFormat)4, false); ((Texture)val3).filterMode = (FilterMode)1; Color val4 = default(Color); for (int i = 0; i < 128; i++) { for (int j = 0; j < 128; j++) { Color pixel = val.GetPixel(j, i); Color pixel2 = val2.GetPixel(j, i); float num = Mathf.Clamp01(pixel.a + pixel2.a * 0.65f); ((Color)(ref val4))..ctor(color.r, color.g, color.b, color.a * num); val3.SetPixel(j, i, val4); } } val3.Apply(true); return val3; } public static Texture2D GenerateRune(Color color, int runeIndex) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_006d: 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) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_009e: 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_010e: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0163: 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_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: 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_01d8: 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_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_035c: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_0391: Unknown result type (might be due to invalid IL or missing references) //IL_03a1: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03c1: Unknown result type (might be due to invalid IL or missing references) //IL_03d1: Unknown result type (might be due to invalid IL or missing references) //IL_03e1: Unknown result type (might be due to invalid IL or missing references) //IL_03f1: Unknown result type (might be due to invalid IL or missing references) //IL_0401: Unknown result type (might be due to invalid IL or missing references) //IL_0416: Unknown result type (might be due to invalid IL or missing references) //IL_0426: Unknown result type (might be due to invalid IL or missing references) //IL_0436: Unknown result type (might be due to invalid IL or missing references) //IL_0446: Unknown result type (might be due to invalid IL or missing references) //IL_045b: Unknown result type (might be due to invalid IL or missing references) //IL_046b: Unknown result type (might be due to invalid IL or missing references) //IL_047b: Unknown result type (might be due to invalid IL or missing references) //IL_048b: Unknown result type (might be due to invalid IL or missing references) //IL_049b: Unknown result type (might be due to invalid IL or missing references) //IL_04ab: Unknown result type (might be due to invalid IL or missing references) //IL_04bb: Unknown result type (might be due to invalid IL or missing references) //IL_04cb: Unknown result type (might be due to invalid IL or missing references) //IL_04e0: Unknown result type (might be due to invalid IL or missing references) //IL_04f0: Unknown result type (might be due to invalid IL or missing references) //IL_0500: Unknown result type (might be due to invalid IL or missing references) //IL_0510: Unknown result type (might be due to invalid IL or missing references) //IL_0525: Unknown result type (might be due to invalid IL or missing references) //IL_0535: Unknown result type (might be due to invalid IL or missing references) //IL_0545: Unknown result type (might be due to invalid IL or missing references) //IL_0555: Unknown result type (might be due to invalid IL or missing references) //IL_0565: Unknown result type (might be due to invalid IL or missing references) //IL_0575: Unknown result type (might be due to invalid IL or missing references) //IL_0585: Unknown result type (might be due to invalid IL or missing references) //IL_0595: Unknown result type (might be due to invalid IL or missing references) //IL_05a5: Unknown result type (might be due to invalid IL or missing references) //IL_05b5: Unknown result type (might be due to invalid IL or missing references) //IL_05c5: Unknown result type (might be due to invalid IL or missing references) //IL_05d5: Unknown result type (might be due to invalid IL or missing references) //IL_05ea: Unknown result type (might be due to invalid IL or missing references) //IL_05fa: Unknown result type (might be due to invalid IL or missing references) //IL_060a: Unknown result type (might be due to invalid IL or missing references) //IL_061a: Unknown result type (might be due to invalid IL or missing references) //IL_062a: Unknown result type (might be due to invalid IL or missing references) //IL_063a: Unknown result type (might be due to invalid IL or missing references) //IL_064a: Unknown result type (might be due to invalid IL or missing references) //IL_065a: Unknown result type (might be due to invalid IL or missing references) //IL_066f: Unknown result type (might be due to invalid IL or missing references) //IL_067f: Unknown result type (might be due to invalid IL or missing references) //IL_068f: Unknown result type (might be due to invalid IL or missing references) //IL_069f: Unknown result type (might be due to invalid IL or missing references) //IL_06af: Unknown result type (might be due to invalid IL or missing references) //IL_06bf: Unknown result type (might be due to invalid IL or missing references) //IL_06cf: Unknown result type (might be due to invalid IL or missing references) //IL_06df: Unknown result type (might be due to invalid IL or missing references) //IL_06ef: Unknown result type (might be due to invalid IL or missing references) //IL_06ff: Unknown result type (might be due to invalid IL or missing references) //IL_0714: Unknown result type (might be due to invalid IL or missing references) //IL_0724: Unknown result type (might be due to invalid IL or missing references) //IL_0734: Unknown result type (might be due to invalid IL or missing references) //IL_0744: Unknown result type (might be due to invalid IL or missing references) //IL_0754: Unknown result type (might be due to invalid IL or missing references) //IL_0764: Unknown result type (might be due to invalid IL or missing references) //IL_0774: Unknown result type (might be due to invalid IL or missing references) //IL_0784: Unknown result type (might be due to invalid IL or missing references) //IL_0799: Unknown result type (might be due to invalid IL or missing references) //IL_07a9: Unknown result type (might be due to invalid IL or missing references) //IL_07b9: Unknown result type (might be due to invalid IL or missing references) //IL_07c9: Unknown result type (might be due to invalid IL or missing references) //IL_07d9: Unknown result type (might be due to invalid IL or missing references) //IL_07e9: Unknown result type (might be due to invalid IL or missing references) //IL_07f9: Unknown result type (might be due to invalid IL or missing references) //IL_0809: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(128, 128, (TextureFormat)4, true); ((Texture)val).filterMode = (FilterMode)1; ((Texture)val).wrapMode = (TextureWrapMode)1; Color val2 = default(Color); ((Color)(ref val2))..ctor(0f, 0f, 0f, 0f); Color c = default(Color); ((Color)(ref c))..ctor(color.r * 0.6f, color.g * 0.6f, color.b * 0.6f, 0.6f); Color c2 = default(Color); ((Color)(ref c2))..ctor(color.r, color.g, color.b, 1f); Color[] array = (Color[])(object)new Color[16384]; for (int i = 0; i < array.Length; i++) { array[i] = val2; } val.SetPixels(array); switch (runeIndex) { case 0: DrawLine(val, 20, 20, 108, 108, c, 6); DrawLine(val, 108, 20, 20, 108, c, 6); DrawLine(val, 20, 20, 108, 108, c2, 3); DrawLine(val, 108, 20, 20, 108, c2, 3); break; case 1: DrawLine(val, 64, 16, 64, 112, c, 6); DrawLine(val, 64, 64, 32, 96, c, 5); DrawLine(val, 64, 64, 96, 96, c, 5); DrawLine(val, 64, 16, 64, 112, c2, 3); DrawLine(val, 64, 64, 32, 96, c2, 2); DrawLine(val, 64, 64, 96, 96, c2, 2); break; case 2: DrawLine(val, 40, 20, 40, 108, c, 6); DrawLine(val, 40, 96, 96, 112, c, 5); DrawLine(val, 40, 72, 96, 88, c, 5); DrawLine(val, 40, 20, 40, 108, c2, 3); DrawLine(val, 40, 96, 96, 112, c2, 2); DrawLine(val, 40, 72, 96, 88, c2, 2); break; case 3: DrawLine(val, 40, 20, 40, 112, c, 6); DrawLine(val, 40, 96, 88, 112, c, 5); DrawLine(val, 88, 112, 88, 80, c, 5); DrawLine(val, 88, 80, 40, 96, c, 5); DrawLine(val, 40, 20, 40, 112, c2, 3); DrawLine(val, 40, 96, 88, 112, c2, 2); DrawLine(val, 88, 112, 88, 80, c2, 2); DrawLine(val, 88, 80, 40, 96, c2, 2); break; case 4: DrawLine(val, 64, 16, 64, 112, c, 8); DrawLine(val, 64, 16, 64, 112, c2, 4); break; case 5: DrawLine(val, 64, 16, 64, 112, c, 6); DrawLine(val, 64, 40, 32, 72, c, 5); DrawLine(val, 64, 40, 96, 72, c, 5); DrawLine(val, 64, 16, 64, 112, c2, 3); DrawLine(val, 64, 40, 32, 72, c2, 2); DrawLine(val, 64, 40, 96, 72, c2, 2); break; case 6: DrawLine(val, 36, 16, 36, 112, c, 6); DrawLine(val, 92, 16, 92, 112, c, 6); DrawLine(val, 36, 36, 92, 92, c, 5); DrawLine(val, 36, 16, 36, 112, c2, 3); DrawLine(val, 92, 16, 92, 112, c2, 3); DrawLine(val, 36, 36, 92, 92, c2, 2); break; default: DrawLine(val, 80, 20, 40, 20, c, 5); DrawLine(val, 80, 20, 40, 64, c, 5); DrawLine(val, 40, 64, 80, 108, c, 5); DrawLine(val, 80, 108, 40, 108, c, 5); DrawLine(val, 80, 20, 40, 20, c2, 2); DrawLine(val, 80, 20, 40, 64, c2, 2); DrawLine(val, 40, 64, 80, 108, c2, 2); DrawLine(val, 80, 108, 40, 108, c2, 2); break; case 8: DrawLine(val, 64, 16, 64, 112, c, 6); DrawLine(val, 96, 96, 32, 32, c, 5); DrawLine(val, 64, 16, 64, 112, c2, 3); DrawLine(val, 96, 96, 32, 32, c2, 2); break; case 9: DrawLine(val, 32, 48, 32, 112, c, 6); DrawLine(val, 96, 48, 96, 112, c, 6); DrawLine(val, 32, 48, 64, 16, c, 5); DrawLine(val, 64, 16, 96, 48, c, 5); DrawLine(val, 32, 48, 32, 112, c2, 3); DrawLine(val, 96, 48, 96, 112, c2, 3); DrawLine(val, 32, 48, 64, 16, c2, 2); DrawLine(val, 64, 16, 96, 48, c2, 2); break; case 10: DrawLine(val, 48, 16, 48, 112, c, 6); DrawLine(val, 48, 80, 96, 48, c, 5); DrawLine(val, 48, 16, 48, 112, c2, 3); DrawLine(val, 48, 80, 96, 48, c2, 2); break; case 11: DrawLine(val, 64, 112, 96, 72, c, 5); DrawLine(val, 96, 72, 64, 32, c, 5); DrawLine(val, 64, 32, 32, 72, c, 5); DrawLine(val, 32, 72, 64, 112, c, 5); DrawLine(val, 32, 72, 16, 16, c, 5); DrawLine(val, 96, 72, 112, 16, c, 5); DrawLine(val, 64, 112, 96, 72, c2, 2); DrawLine(val, 96, 72, 64, 32, c2, 2); DrawLine(val, 64, 32, 32, 72, c2, 2); DrawLine(val, 32, 72, 64, 112, c2, 2); DrawLine(val, 32, 72, 16, 16, c2, 2); DrawLine(val, 96, 72, 112, 16, c2, 2); break; case 12: DrawLine(val, 20, 20, 64, 64, c, 5); DrawLine(val, 20, 108, 64, 64, c, 5); DrawLine(val, 108, 20, 64, 64, c, 5); DrawLine(val, 108, 108, 64, 64, c, 5); DrawLine(val, 20, 20, 64, 64, c2, 2); DrawLine(val, 20, 108, 64, 64, c2, 2); DrawLine(val, 108, 20, 64, 64, c2, 2); DrawLine(val, 108, 108, 64, 64, c2, 2); break; case 13: DrawLine(val, 36, 16, 36, 112, c, 6); DrawLine(val, 36, 96, 80, 80, c, 5); DrawLine(val, 80, 80, 36, 64, c, 5); DrawLine(val, 36, 64, 80, 48, c, 5); DrawLine(val, 80, 48, 36, 32, c, 5); DrawLine(val, 36, 16, 36, 112, c2, 3); DrawLine(val, 36, 96, 80, 80, c2, 2); DrawLine(val, 80, 80, 36, 64, c2, 2); DrawLine(val, 36, 64, 80, 48, c2, 2); DrawLine(val, 80, 48, 36, 32, c2, 2); break; case 14: DrawLine(val, 32, 16, 32, 112, c, 6); DrawLine(val, 96, 16, 96, 112, c, 6); DrawLine(val, 32, 112, 96, 64, c, 5); DrawLine(val, 96, 112, 32, 64, c, 5); DrawLine(val, 32, 16, 32, 112, c2, 3); DrawLine(val, 96, 16, 96, 112, c2, 3); DrawLine(val, 32, 112, 96, 64, c2, 2); DrawLine(val, 96, 112, 32, 64, c2, 2); break; case 15: DrawLine(val, 64, 16, 108, 64, c, 6); DrawLine(val, 108, 64, 64, 112, c, 6); DrawLine(val, 64, 112, 20, 64, c, 6); DrawLine(val, 20, 64, 64, 16, c, 6); DrawLine(val, 64, 16, 108, 64, c2, 3); DrawLine(val, 108, 64, 64, 112, c2, 3); DrawLine(val, 64, 112, 20, 64, c2, 3); DrawLine(val, 20, 64, 64, 16, c2, 3); break; } val.Apply(true); return val; } private static void DrawLine(Texture2D tex, int x0, int y0, int x1, int y1, Color c, int thickness) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Abs(x1 - x0); int num2 = Mathf.Abs(y1 - y0); int num3 = ((x0 < x1) ? 1 : (-1)); int num4 = ((y0 < y1) ? 1 : (-1)); int num5 = num - num2; while (true) { DrawCircle(tex, x0, y0, thickness, c); if (x0 != x1 || y0 != y1) { int num6 = 2 * num5; if (num6 > -num2) { num5 -= num2; x0 += num3; } if (num6 < num) { num5 += num; y0 += num4; } continue; } break; } } private static void DrawCircle(Texture2D tex, int cx, int cy, int r, Color c) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) for (int i = -r; i <= r; i++) { for (int j = -r; j <= r; j++) { if (j * j + i * i <= r * r) { int num = cx + j; int num2 = cy + i; if (num >= 0 && num < 128 && num2 >= 0 && num2 < 128) { tex.SetPixel(num, num2, c); } } } } } } }