Decompiled source of BossSpirits v1.0.0

BepInEx/plugins/FalseMods/BossSpirits/BossSpirits.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using FalseMods.BossSpirits.Behaviors;
using FalseMods.BossSpirits.Bosses;
using FalseMods.BossSpirits.Configuration;
using FalseMods.BossSpirits.Lifecycle;
using FalseMods.BossSpirits.Native;
using FalseMods.BossSpirits.Networking;
using FalseMods.BossSpirits.Progression;
using FalseMods.BossSpirits.Spirits;
using FalseMods.BossSpirits.Summoning;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;
using UnityEngine.AI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("BossSpirits")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BossSpirits")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e2f4b582-515c-468c-8067-ee08216648da")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace FalseMods.BossSpirits
{
	[BepInPlugin("falsemods.bossspirits", "Boss Spirits", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "falsemods.bossspirits";

		public const string PluginName = "Boss Spirits";

		public const string PluginVersion = "1.0.0";

		private Harmony harmony;

		private void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			harmony = new Harmony("falsemods.bossspirits");
			harmony.PatchAll();
			BossSpiritsConfig.Initialize(((BaseUnityPlugin)this).Config);
			NativeSpiritPrefabRegistry.Initialize();
			SpiritRegistry.RegisterAll();
			ForsakenPowerManager.Initialize();
			SpiritSummonManager.Initialize();
			SpiritLifecycleManager.Initialize();
			SpiritNetworkManager.Initialize();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Boss Spirits Loaded!");
		}

		private void Update()
		{
			ForsakenPowerManager.Update();
			SpiritSpawner.Update();
			SpiritLifecycleManager.Update();
			SpiritSummonManager.Update();
			SpiritNetworkManager.Update();
			ElderWorkAreaPlacementManager.Update();
		}

		private void OnDestroy()
		{
			SpiritLifecycleManager.Shutdown();
			SpiritSummonManager.Shutdown();
			SpiritNetworkManager.Shutdown();
			ElderWorkAreaPlacementManager.Cancel(showMessage: false);
			NativeSpiritPrefabRegistry.Shutdown();
			if (harmony != null)
			{
				harmony.UnpatchSelf();
				harmony = null;
			}
		}
	}
}
namespace FalseMods.BossSpirits.Summoning
{
	public static class SpiritSpawner
	{
		private enum Operation
		{
			None,
			Summon,
			Despawn
		}

		private const string Vfx = "vfx_spawn";

		private const string Sfx = "sfx_spawn";

		private const float Delay = 0.1f;

		private static Operation operation;

		private static float completionTime;

		private static Vector3 position;

		private static Quaternion rotation;

		private static Func<Vector3, Quaternion, GameObject> factory;

		private static Action<GameObject> summonCompletion;

		private static Action despawnCompletion;

		public static bool HasPendingOperation => operation != Operation.None;

		public static void BeginSummon(Vector3 spawnPosition, Quaternion spawnRotation, Func<Vector3, Quaternion, GameObject> spiritFactory, Action<GameObject> completion)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (!HasPendingOperation && spiritFactory != null)
			{
				operation = Operation.Summon;
				position = spawnPosition;
				rotation = spawnRotation;
				factory = spiritFactory;
				summonCompletion = completion;
				despawnCompletion = null;
				completionTime = Time.time + 0.1f;
				PlayPoof(position, rotation);
				Debug.Log((object)"Boss Spirits: Purple summon poof played. Spirit will appear after 0.10 seconds.");
			}
		}

		public static void BeginDespawn(Vector3 effectPosition, Quaternion effectRotation, Action completion)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (!HasPendingOperation && completion != null)
			{
				operation = Operation.Despawn;
				position = effectPosition;
				rotation = effectRotation;
				factory = null;
				summonCompletion = null;
				despawnCompletion = completion;
				completionTime = Time.time + 0.1f;
				PlayPoof(position, rotation);
				Debug.Log((object)"Boss Spirits: Purple despawn poof played. Spirit will disappear after 0.10 seconds.");
			}
		}

		public static void Update()
		{
			if (HasPendingOperation && !(Time.time < completionTime))
			{
				if (operation == Operation.Summon)
				{
					CompleteSummon();
				}
				else
				{
					CompleteDespawn();
				}
			}
		}

		public static void CancelPendingOperation()
		{
			Clear();
		}

		public static void PlayNetworkPoof(Vector3 effectPosition, Quaternion effectRotation)
		{
			//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)
			PlayPoof(effectPosition, effectRotation);
		}

		private static void CompleteSummon()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			Func<Vector3, Quaternion, GameObject> func = factory;
			Action<GameObject> action = summonCompletion;
			Vector3 arg = position;
			Quaternion arg2 = rotation;
			Clear();
			GameObject val;
			try
			{
				val = func(arg, arg2);
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("Boss Spirits: Spirit creation failed.\n" + ex));
				return;
			}
			if (!((Object)(object)val == (Object)null))
			{
				action?.Invoke(val);
				Debug.Log((object)"Boss Spirits: Summoning transition completed.");
			}
		}

		private static void CompleteDespawn()
		{
			Action action = despawnCompletion;
			Clear();
			try
			{
				action();
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("Boss Spirits: Despawn completion failed.\n" + ex));
				return;
			}
			Debug.Log((object)"Boss Spirits: Despawn transition completed.");
		}

		private static void PlayPoof(Vector3 effectPosition, Quaternion effectRotation)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab("vfx_spawn");
			GameObject prefab2 = ZNetScene.instance.GetPrefab("sfx_spawn");
			int num = (((Object)(object)prefab != (Object)null) ? 1 : 0) + (((Object)(object)prefab2 != (Object)null) ? 1 : 0);
			if (num != 0)
			{
				EffectList val = new EffectList();
				val.m_effectPrefabs = (EffectData[])(object)new EffectData[num];
				int num2 = 0;
				if ((Object)(object)prefab != (Object)null)
				{
					val.m_effectPrefabs[num2++] = Data(prefab);
				}
				if ((Object)(object)prefab2 != (Object)null)
				{
					val.m_effectPrefabs[num2] = Data(prefab2);
				}
				val.Create(effectPosition, effectRotation, (Transform)null, 1f, -1);
				Debug.Log((object)"Boss Spirits: Played purple effect pair: vfx_spawn + sfx_spawn");
			}
		}

		private static EffectData Data(GameObject prefab)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			return new EffectData
			{
				m_prefab = prefab,
				m_enabled = true,
				m_variant = -1
			};
		}

		private static void Clear()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			operation = Operation.None;
			completionTime = 0f;
			position = Vector3.zero;
			rotation = Quaternion.identity;
			factory = null;
			summonCompletion = null;
			despawnCompletion = null;
		}
	}
	public static class SpiritSummonManager
	{
		private static ActiveSpirit activeSpirit;

		private static bool despawnPending;

		private static bool initialized;

		public static bool HasActiveSpirit
		{
			get
			{
				if (activeSpirit != null)
				{
					return (Object)(object)activeSpirit.GameObject != (Object)null;
				}
				return false;
			}
		}

		public static ActiveSpirit CurrentActiveSpirit
		{
			get
			{
				if (!HasActiveSpirit)
				{
					return null;
				}
				return activeSpirit;
			}
		}

		public static bool IsTracking(GameObject spiritObject)
		{
			if ((Object)(object)spiritObject != (Object)null && activeSpirit != null)
			{
				return (Object)(object)activeSpirit.GameObject == (Object)(object)spiritObject;
			}
			return false;
		}

		public static void Initialize()
		{
			if (!initialized)
			{
				initialized = true;
				Debug.Log((object)"Boss Spirits: Spirit Summon Manager initialized.");
			}
		}

		public static void Update()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if (initialized && Input.GetKeyDown(BossSpiritsConfig.SummonKey))
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null)
				{
					ToggleSpirit(localPlayer);
				}
			}
		}

		public static void Shutdown()
		{
			ForceCleanup("the plugin shut down");
			initialized = false;
		}

		public static void RequestLifecycleDespawn(string reason)
		{
			if (!despawnPending)
			{
				if (SpiritSpawner.HasPendingOperation)
				{
					SpiritSpawner.CancelPendingOperation();
					Debug.Log((object)("Boss Spirits: Pending summon canceled because " + reason + "."));
				}
				else if (HasActiveSpirit)
				{
					Debug.Log((object)("Boss Spirits: Dismissing " + activeSpirit.Definition.DisplayName + " because " + reason + "."));
					BeginDespawn();
				}
			}
		}

		public static void ForceCleanup(string reason)
		{
			ElderWorkAreaPlacementManager.Cancel(showMessage: false);
			SpiritSpawner.CancelPendingOperation();
			if (activeSpirit != null && (Object)(object)activeSpirit.GameObject != (Object)null)
			{
				SpiritNetworkManager.NotifyLocalDespawning(activeSpirit, playEffect: false);
				DestroySpiritObject(activeSpirit);
			}
			bool num = activeSpirit != null || despawnPending;
			activeSpirit = null;
			despawnPending = false;
			if (num)
			{
				Debug.Log((object)("Boss Spirits: Spirit cleaned up because " + reason + "."));
			}
		}

		private static void ToggleSpirit(Player player)
		{
			if (!SpiritSpawner.HasPendingOperation && !despawnPending)
			{
				string powerName;
				SpiritDefinition definition;
				if (activeSpirit != null && (Object)(object)activeSpirit.GameObject != (Object)null)
				{
					BeginDespawn();
				}
				else if (!ForsakenPowerManager.TryGetEquippedPowerName(player, out powerName))
				{
					Debug.LogWarning((object)"Boss Spirits: No equipped Forsaken power could be identified.");
				}
				else if (!SpiritRegistry.TryGetByForsakenPower(powerName, out definition))
				{
					Debug.LogWarning((object)("Boss Spirits: No Spirit is registered for equipped power: " + powerName));
				}
				else
				{
					BeginSummon(player, definition);
				}
			}
		}

		private static void BeginSummon(Player player, SpiritDefinition definition)
		{
			//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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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_00cd: 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_00d8: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			Vector3 forward = ((Component)player).transform.forward;
			forward.y = 0f;
			if (((Vector3)(ref forward)).sqrMagnitude < 0.001f)
			{
				forward = Vector3.forward;
			}
			((Vector3)(ref forward)).Normalize();
			Vector3 val = ((Component)player).transform.position + forward * definition.SpawnDistance;
			if (definition.Id == "elder")
			{
				val.y = ElderWorkAreaRing.SampleSurfaceHeight(val, ((Component)player).transform.position.y);
			}
			else if ((Object)(object)ZoneSystem.instance != (Object)null)
			{
				val.y = ZoneSystem.instance.GetGroundHeight(val);
			}
			val.y += definition.VerticalOffset;
			Quaternion spawnRotation = Quaternion.LookRotation(-forward, Vector3.up);
			Transform owner = ((Component)player).transform;
			SpiritSpawner.BeginSummon(val, spawnRotation, (Vector3 position, Quaternion rotation) => SpiritModelFactory.Create(definition, position, rotation, owner), delegate(GameObject spiritObject)
			{
				activeSpirit = new ActiveSpirit(definition, spiritObject);
				SpiritNetworkManager.NotifyLocalSummoned(activeSpirit);
				Debug.Log((object)("Boss Spirits: " + definition.DisplayName + " summoned."));
			});
		}

		private static void BeginDespawn()
		{
			//IL_0059: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			if (activeSpirit == null || (Object)(object)activeSpirit.GameObject == (Object)null)
			{
				activeSpirit = null;
				return;
			}
			despawnPending = true;
			ElderWorkAreaPlacementManager.Cancel(showMessage: false);
			ActiveSpirit removing = activeSpirit;
			SpiritNetworkManager.NotifyLocalDespawning(removing, playEffect: true);
			Vector3 position = removing.GameObject.transform.position;
			Quaternion rotation = removing.GameObject.transform.rotation;
			SpiritSpawner.BeginDespawn(position, rotation, delegate
			{
				if ((Object)(object)removing.GameObject != (Object)null)
				{
					DestroySpiritObject(removing);
				}
				if (activeSpirit == removing)
				{
					activeSpirit = null;
				}
				despawnPending = false;
				Debug.Log((object)("Boss Spirits: " + removing.Definition.DisplayName + " despawned."));
			});
		}

		private static void DestroySpiritObject(ActiveSpirit spirit)
		{
			if (spirit != null && !((Object)(object)spirit.GameObject == (Object)null))
			{
				if (NativeSpiritPrefabRegistry.IsNativeDefinition(spirit.Definition))
				{
					NativeSpiritPrefabRegistry.DestroyInstance(spirit.GameObject);
				}
				else
				{
					Object.Destroy((Object)(object)spirit.GameObject);
				}
			}
		}
	}
}
namespace FalseMods.BossSpirits.Spirits
{
	public sealed class ActiveSpirit
	{
		public SpiritDefinition Definition { get; private set; }

		public GameObject GameObject { get; private set; }

		public ActiveSpirit(SpiritDefinition definition, GameObject gameObject)
		{
			Definition = definition;
			GameObject = gameObject;
		}
	}
	public enum SpiritLifecyclePolicy
	{
		StandardCompanion,
		AnchoredWorksite
	}
	public sealed class SpiritDefinition
	{
		public string Id { get; private set; }

		public string DisplayName { get; private set; }

		public string PrefabName { get; private set; }

		public string[] ForsakenPowerNames { get; private set; }

		public float SpawnDistance { get; private set; }

		public float VerticalOffset { get; private set; }

		public bool RemoveParticles { get; private set; }

		public bool RemoveTrailRenderers { get; private set; }

		public float FollowDistance { get; private set; }

		public float StopDistance { get; private set; }

		public float RunDistance { get; private set; }

		public float TeleportDistance { get; private set; }

		public float WalkSpeed { get; private set; }

		public float RunSpeed { get; private set; }

		public float TurnSpeed { get; private set; }

		public float VerticalFollowSpeed { get; private set; }

		public float ObstacleProbeRadius { get; private set; }

		public float ObstacleProbeDistance { get; private set; }

		public float StepHeight { get; private set; }

		public float WalkAnimationSpeed { get; private set; }

		public float RunAnimationSpeed { get; private set; }

		public float TeleportCooldown { get; private set; }

		public float StuckTeleportDelay { get; private set; }

		public float Acceleration { get; private set; }

		public float Deceleration { get; private set; }

		public float SteeringSmoothness { get; private set; }

		public float GroundSmoothTime { get; private set; }

		public SpiritLifecyclePolicy LifecyclePolicy { get; private set; }

		public SpiritDefinition(string id, string displayName, string prefabName, string[] forsakenPowerNames, float spawnDistance, float verticalOffset, bool removeParticles, bool removeTrailRenderers)
			: this(id, displayName, prefabName, forsakenPowerNames, spawnDistance, verticalOffset, removeParticles, removeTrailRenderers, 15f, 13f, 25f, 65f, 4.5f, 10f, 4f, 12f, 0.85f, 7f, 1.5f, 1f, 1f, 1.25f, 4f, 7f, 10f, 7f, 0.12f)
		{
		}

		public SpiritDefinition(string id, string displayName, string prefabName, string[] forsakenPowerNames, float spawnDistance, float verticalOffset, bool removeParticles, bool removeTrailRenderers, float followDistance, float stopDistance, float runDistance, float teleportDistance, float walkSpeed, float runSpeed, float turnSpeed, float verticalFollowSpeed, float obstacleProbeRadius, float obstacleProbeDistance, float stepHeight, float walkAnimationSpeed, float runAnimationSpeed, float teleportCooldown, float stuckTeleportDelay, float acceleration, float deceleration, float steeringSmoothness, float groundSmoothTime)
		{
			Id = id;
			DisplayName = displayName;
			PrefabName = prefabName;
			ForsakenPowerNames = forsakenPowerNames;
			SpawnDistance = spawnDistance;
			VerticalOffset = verticalOffset;
			RemoveParticles = removeParticles;
			RemoveTrailRenderers = removeTrailRenderers;
			FollowDistance = followDistance;
			StopDistance = stopDistance;
			RunDistance = runDistance;
			TeleportDistance = teleportDistance;
			WalkSpeed = walkSpeed;
			RunSpeed = runSpeed;
			TurnSpeed = turnSpeed;
			VerticalFollowSpeed = verticalFollowSpeed;
			ObstacleProbeRadius = obstacleProbeRadius;
			ObstacleProbeDistance = obstacleProbeDistance;
			StepHeight = stepHeight;
			WalkAnimationSpeed = walkAnimationSpeed;
			RunAnimationSpeed = runAnimationSpeed;
			TeleportCooldown = teleportCooldown;
			StuckTeleportDelay = stuckTeleportDelay;
			Acceleration = acceleration;
			Deceleration = deceleration;
			SteeringSmoothness = steeringSmoothness;
			GroundSmoothTime = groundSmoothTime;
			LifecyclePolicy = SpiritLifecyclePolicy.StandardCompanion;
		}

		public SpiritDefinition WithLifecyclePolicy(SpiritLifecyclePolicy lifecyclePolicy)
		{
			LifecyclePolicy = lifecyclePolicy;
			return this;
		}
	}
	public static class SpiritModelFactory
	{
		public static GameObject Create(SpiritDefinition definition, Vector3 position, Quaternion rotation, Transform owner)
		{
			//IL_003d: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			if (definition == null || (Object)(object)owner == (Object)null)
			{
				Debug.LogError((object)"Boss Spirits: Definition or owner was unavailable.");
				return null;
			}
			if (NativeSpiritPrefabRegistry.IsNativeDefinition(definition))
			{
				Player component = ((Component)owner).GetComponent<Player>();
				if ((Object)(object)component == (Object)null)
				{
					Debug.LogError((object)"Boss Spirits: Native Spirit summoning owner was not a Player.");
					return null;
				}
				return NativeSpiritPrefabRegistry.CreateInstance(definition, position, rotation, component);
			}
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				Debug.LogError((object)"Boss Spirits: ZNetScene is unavailable.");
				return null;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(definition.PrefabName);
			if ((Object)(object)prefab == (Object)null)
			{
				Debug.LogError((object)("Boss Spirits: Vanilla prefab was not found: " + definition.PrefabName));
				return null;
			}
			return CreateClone(definition, prefab, position, rotation, owner, addFollowController: true);
		}

		public static GameObject CreateRemote(SpiritDefinition definition, Vector3 position, Quaternion rotation)
		{
			//IL_003c: 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)
			if (definition == null)
			{
				return null;
			}
			if (NativeSpiritPrefabRegistry.IsNativeDefinition(definition))
			{
				return null;
			}
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return null;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(definition.PrefabName);
			if ((Object)(object)prefab == (Object)null)
			{
				return null;
			}
			return CreateClone(definition, prefab, position, rotation, null, addFollowController: false);
		}

		private static GameObject CreateClone(SpiritDefinition definition, GameObject prefab, Vector3 position, Quaternion rotation, Transform owner, bool addFollowController)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0033: 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_0059: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Boss Spirits Visual Staging");
			val.SetActive(false);
			GameObject val2 = null;
			try
			{
				val2 = Object.Instantiate<GameObject>(prefab, val.transform);
				((Object)val2).name = definition.DisplayName;
				val2.transform.localPosition = Vector3.zero;
				val2.transform.localRotation = Quaternion.identity;
				val2.transform.localScale = prefab.transform.localScale;
				StripGameplay(val2, definition);
				if (ContainsUnsafeBehaviours(val2))
				{
					Debug.LogError((object)("Boss Spirits: Unsafe behaviours remain on " + definition.DisplayName));
					Object.DestroyImmediate((Object)(object)val2);
					return null;
				}
				PrepareAnimators(val2);
				val2.transform.SetParent((Transform)null, false);
				val2.transform.position = position;
				val2.transform.rotation = rotation;
				val2.SetActive(true);
				if (addFollowController)
				{
					val2.AddComponent<SpiritFollowController>().Initialize(owner, definition);
				}
				Debug.Log((object)("Boss Spirits: " + definition.DisplayName + (addFollowController ? " local visual and follow behavior created." : " remote visual proxy created.")));
				return val2;
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("Boss Spirits: Error creating " + definition.DisplayName + ".\n" + ex));
				if ((Object)(object)val2 != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val2);
				}
				return null;
			}
			finally
			{
				Object.Destroy((Object)(object)val);
			}
		}

		private static void StripGameplay(GameObject clone, SpiritDefinition definition)
		{
			MonoBehaviour[] componentsInChildren = clone.GetComponentsInChildren<MonoBehaviour>(true);
			for (int num = componentsInChildren.Length - 1; num >= 0; num--)
			{
				if ((Object)(object)componentsInChildren[num] != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren[num]);
				}
			}
			MonoBehaviour[] componentsInChildren2 = clone.GetComponentsInChildren<MonoBehaviour>(true);
			for (int num2 = componentsInChildren2.Length - 1; num2 >= 0; num2--)
			{
				if ((Object)(object)componentsInChildren2[num2] != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren2[num2]);
				}
			}
			RemoveComponents<Collider>(clone);
			RemoveComponents<Rigidbody>(clone);
			RemoveComponents<CharacterController>(clone);
			RemoveComponents<Joint>(clone);
			RemoveComponents<NavMeshAgent>(clone);
			if (definition.RemoveParticles)
			{
				RemoveComponents<ParticleSystemRenderer>(clone);
				RemoveComponents<ParticleSystem>(clone);
			}
			if (definition.RemoveTrailRenderers)
			{
				RemoveComponents<TrailRenderer>(clone);
			}
		}

		private static void RemoveComponents<T>(GameObject clone) where T : Component
		{
			T[] componentsInChildren = clone.GetComponentsInChildren<T>(true);
			for (int num = componentsInChildren.Length - 1; num >= 0; num--)
			{
				if ((Object)(object)componentsInChildren[num] != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren[num]);
				}
			}
		}

		private static bool ContainsUnsafeBehaviours(GameObject clone)
		{
			return clone.GetComponentsInChildren<MonoBehaviour>(true).Length != 0;
		}

		private static void PrepareAnimators(GameObject clone)
		{
			Animator[] componentsInChildren = clone.GetComponentsInChildren<Animator>(true);
			foreach (Animator val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					((Behaviour)val).enabled = true;
					val.speed = 1f;
					val.cullingMode = (AnimatorCullingMode)0;
					val.Rebind();
					val.Update(0f);
				}
			}
		}
	}
	public static class SpiritRegistry
	{
		private static readonly Dictionary<string, SpiritDefinition> Definitions = new Dictionary<string, SpiritDefinition>(StringComparer.OrdinalIgnoreCase);

		private static bool registered;

		public static void RegisterAll()
		{
			if (!registered)
			{
				registered = true;
				Register(EikthyrSpirit.Definition);
				Register(ElderSpirit.Definition);
				Register(BonemassSpirit.Definition);
				Register(ModerSpirit.Definition);
				Debug.Log((object)("Boss Spirits: Registered " + Definitions.Count + " Spirit definition(s)."));
			}
		}

		public static void Register(SpiritDefinition definition)
		{
			if (definition == null)
			{
				throw new ArgumentNullException("definition");
			}
			Definitions[definition.Id] = definition;
		}

		public static bool TryGetByForsakenPower(string powerName, out SpiritDefinition definition)
		{
			definition = null;
			if (string.IsNullOrEmpty(powerName))
			{
				return false;
			}
			string text = Normalize(powerName);
			foreach (SpiritDefinition value in Definitions.Values)
			{
				string[] forsakenPowerNames = value.ForsakenPowerNames;
				for (int i = 0; i < forsakenPowerNames.Length; i++)
				{
					string text2 = Normalize(forsakenPowerNames[i]);
					if (text == text2 || text.Contains(text2) || text2.Contains(text))
					{
						definition = value;
						return true;
					}
				}
			}
			return false;
		}

		public static bool TryGetById(string id, out SpiritDefinition definition)
		{
			definition = null;
			if (string.IsNullOrEmpty(id))
			{
				return false;
			}
			return Definitions.TryGetValue(id, out definition);
		}

		private static string Normalize(string value)
		{
			return value.Trim().Replace("$", "").Replace("_", "")
				.Replace("-", "")
				.Replace(" ", "")
				.ToLowerInvariant();
		}
	}
}
namespace FalseMods.BossSpirits.Progression
{
	public static class ForsakenPowerManager
	{
		private const float ObservationInterval = 0.1f;

		private static readonly string[] MemberNames = new string[3] { "m_guardianPower", "guardianPower", "GuardianPower" };

		private static Player observedPlayer;

		private static string lastSelectedPower;

		private static float nextObservationTime;

		public static void Initialize()
		{
			observedPlayer = null;
			lastSelectedPower = null;
			nextObservationTime = 0f;
			Debug.Log((object)"Boss Spirits: Forsaken Power selection tracking initialized.");
		}

		public static void Update()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				observedPlayer = null;
				lastSelectedPower = null;
				nextObservationTime = 0f;
				return;
			}
			if ((Object)(object)localPlayer != (Object)(object)observedPlayer)
			{
				observedPlayer = localPlayer;
				lastSelectedPower = null;
				nextObservationTime = 0f;
			}
			if (!(Time.time < nextObservationTime))
			{
				nextObservationTime = Time.time + 0.1f;
				ObserveSelectedPower(localPlayer);
			}
		}

		public static bool TryGetEquippedPowerName(Player player, out string powerName)
		{
			powerName = null;
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			if ((Object)(object)player != (Object)(object)observedPlayer)
			{
				observedPlayer = player;
				lastSelectedPower = null;
				nextObservationTime = 0f;
			}
			ObserveSelectedPower(player);
			if (string.IsNullOrEmpty(lastSelectedPower))
			{
				Debug.LogWarning((object)"Boss Spirits: No recognized selected Forsaken Power is available.");
				return false;
			}
			powerName = lastSelectedPower;
			return true;
		}

		private static void ObserveSelectedPower(Player player)
		{
			if (TryReadSelectedPower(player, out var powerName) && SpiritRegistry.TryGetByForsakenPower(powerName, out var definition))
			{
				string b = ((definition.ForsakenPowerNames != null && definition.ForsakenPowerNames.Length != 0) ? definition.ForsakenPowerNames[0] : definition.Id);
				if (!string.Equals(lastSelectedPower, b, StringComparison.OrdinalIgnoreCase))
				{
					lastSelectedPower = b;
					Debug.Log((object)("Boss Spirits: Selected Forsaken Power is now " + definition.DisplayName + "."));
				}
			}
		}

		private static bool TryReadSelectedPower(Player player, out string powerName)
		{
			powerName = null;
			Type type = ((object)player).GetType();
			while (type != null)
			{
				string[] memberNames = MemberNames;
				foreach (string name in memberNames)
				{
					FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field != null && TryConvert(field.GetValue(player), out powerName))
					{
						return true;
					}
					PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (property != null && property.CanRead && TryConvert(property.GetValue(player, null), out powerName))
					{
						return true;
					}
				}
				type = type.BaseType;
			}
			return false;
		}

		private static bool TryConvert(object value, out string powerName)
		{
			powerName = null;
			if (value == null)
			{
				return false;
			}
			string text = value as string;
			if (!string.IsNullOrEmpty(text))
			{
				powerName = text;
				return true;
			}
			Object val = (Object)((value is Object) ? value : null);
			if (val != (Object)null && !string.IsNullOrEmpty(val.name))
			{
				powerName = val.name;
				return true;
			}
			text = Convert.ToString(value);
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			powerName = text;
			return true;
		}
	}
}
namespace FalseMods.BossSpirits.Networking
{
	public sealed class RemoteSpiritProxy : MonoBehaviour
	{
		private const float PositionSmoothTime = 0.1f;

		private const float RotationSharpness = 12f;

		private readonly Dictionary<Animator, HashSet<int>> animatorParameters = new Dictionary<Animator, HashSet<int>>();

		private SpiritDefinition definition;

		private Animator[] animators;

		private Vector3 targetPosition;

		private Quaternion targetRotation;

		private float targetMovementSpeed;

		private Vector3 positionVelocity;

		public long OwnerPeerId { get; private set; }

		public float LastUpdateTime { get; private set; }

		public long InstanceId { get; private set; }

		public string SpiritId
		{
			get
			{
				if (definition == null)
				{
					return string.Empty;
				}
				return definition.Id;
			}
		}

		public void Initialize(long ownerPeerId, SpiritDefinition spiritDefinition, SpiritNetworkState initialState)
		{
			//IL_0034: 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_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_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)
			OwnerPeerId = ownerPeerId;
			InstanceId = initialState.InstanceId;
			definition = spiritDefinition;
			animators = ((Component)this).GetComponentsInChildren<Animator>(true);
			CacheAnimatorParameters();
			((Component)this).transform.position = initialState.Position;
			((Component)this).transform.rotation = initialState.Rotation;
			targetPosition = initialState.Position;
			targetRotation = initialState.Rotation;
			targetMovementSpeed = initialState.MovementSpeed;
			LastUpdateTime = Time.time;
			ApplyAnimation();
		}

		public void ApplyState(SpiritNetworkState state)
		{
			//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_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 (state != null && state.InstanceId == InstanceId && !(state.SpiritId != SpiritId))
			{
				targetPosition = state.Position;
				targetRotation = state.Rotation;
				targetMovementSpeed = state.MovementSpeed;
				LastUpdateTime = Time.time;
			}
		}

		private void LateUpdate()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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_0055: 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)
			((Component)this).transform.position = Vector3.SmoothDamp(((Component)this).transform.position, targetPosition, ref positionVelocity, 0.1f);
			float num = 1f - Mathf.Exp(-12f * Time.deltaTime);
			((Component)this).transform.rotation = Quaternion.Slerp(((Component)this).transform.rotation, targetRotation, num);
			ApplyAnimation();
		}

		private void ApplyAnimation()
		{
			Animator[] array = animators;
			foreach (Animator val in array)
			{
				if (!((Object)(object)val == (Object)null) && ((Behaviour)val).enabled)
				{
					SetFloatIfPresent(val, "forward_speed", targetMovementSpeed);
					SetFloatIfPresent(val, "sideway_speed", 0f);
					SetFloatIfPresent(val, "turn_speed", 0f);
					SetBoolIfPresent(val, "inWater", value: false);
				}
			}
		}

		private void CacheAnimatorParameters()
		{
			animatorParameters.Clear();
			Animator[] array = animators;
			foreach (Animator val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					HashSet<int> hashSet = new HashSet<int>();
					AnimatorControllerParameter[] parameters = val.parameters;
					foreach (AnimatorControllerParameter val2 in parameters)
					{
						hashSet.Add(val2.nameHash);
					}
					animatorParameters[val] = hashSet;
				}
			}
		}

		private void SetFloatIfPresent(Animator animator, string name, float value)
		{
			int num = Animator.StringToHash(name);
			if (animatorParameters.TryGetValue(animator, out var value2) && value2.Contains(num))
			{
				animator.SetFloat(num, value, 0.1f, Time.deltaTime);
			}
		}

		private void SetBoolIfPresent(Animator animator, string name, bool value)
		{
			int num = Animator.StringToHash(name);
			if (animatorParameters.TryGetValue(animator, out var value2) && value2.Contains(num))
			{
				animator.SetBool(num, value);
			}
		}
	}
	public static class SpiritNetworkManager
	{
		private const string SummonRpc = "FalseMods.BossSpirits.Summon";

		private const string TransformRpc = "FalseMods.BossSpirits.Transform";

		private const string DespawnRpc = "FalseMods.BossSpirits.Despawn";

		private const string StateRequestRpc = "FalseMods.BossSpirits.StateRequest";

		private const float SendInterval = 0.1f;

		private const float ProxyTimeout = 8f;

		private const float TimeoutCheckInterval = 1f;

		private static readonly Dictionary<long, RemoteSpiritProxy> remoteSpirits = new Dictionary<long, RemoteSpiritProxy>();

		private static readonly Dictionary<long, long> despawnedInstances = new Dictionary<long, long>();

		private static ZRoutedRpc registeredRpc;

		private static bool initialized;

		private static bool requestedWorldState;

		private static bool localSummonAnnounced;

		private static float nextSendTime;

		private static float nextTimeoutCheckTime;

		private static long nextLocalInstanceId;

		private static long currentLocalInstanceId;

		public static void Initialize()
		{
			if (!initialized)
			{
				initialized = true;
				Debug.Log((object)"Boss Spirits: Multiplayer visibility initialized.");
			}
		}

		public static void Update()
		{
			if (!initialized)
			{
				return;
			}
			EnsureRpcRegistered();
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				requestedWorldState = false;
				localSummonAnnounced = false;
				ClearRemoteSpirits();
				return;
			}
			if (!requestedWorldState && registeredRpc != null)
			{
				requestedWorldState = true;
				SendStateRequest();
			}
			ActiveSpirit currentActiveSpirit = SpiritSummonManager.CurrentActiveSpirit;
			if (currentActiveSpirit == null)
			{
				localSummonAnnounced = false;
			}
			else if (registeredRpc != null)
			{
				if (!localSummonAnnounced)
				{
					SendSummon(ZRoutedRpc.Everybody, currentActiveSpirit, playEffect: true);
					localSummonAnnounced = true;
				}
				if (Time.time >= nextSendTime)
				{
					nextSendTime = Time.time + 0.1f;
					SendTransform(currentActiveSpirit);
				}
			}
			if (Time.time >= nextTimeoutCheckTime)
			{
				nextTimeoutCheckTime = Time.time + 1f;
				CleanupTimedOutProxies();
			}
		}

		public static void NotifyLocalSummoned(ActiveSpirit active)
		{
			EnsureRpcRegistered();
			if (active != null && registeredRpc != null)
			{
				nextLocalInstanceId++;
				currentLocalInstanceId = nextLocalInstanceId;
				SendSummon(ZRoutedRpc.Everybody, active, playEffect: true);
				localSummonAnnounced = true;
				nextSendTime = 0f;
			}
		}

		public static void NotifyLocalDespawning(ActiveSpirit active, bool playEffect)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_005a: 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)
			EnsureRpcRegistered();
			if (active == null || (Object)(object)active.GameObject == (Object)null || registeredRpc == null)
			{
				localSummonAnnounced = false;
				return;
			}
			ZPackage val = new ZPackage();
			val.Write(6);
			val.Write(ZNet.GetUID());
			val.Write(currentLocalInstanceId);
			val.Write(playEffect);
			val.Write(active.GameObject.transform.position);
			val.Write(active.GameObject.transform.rotation);
			registeredRpc.InvokeRoutedRPC(ZRoutedRpc.Everybody, "FalseMods.BossSpirits.Despawn", new object[1] { val });
			localSummonAnnounced = false;
			currentLocalInstanceId = 0L;
		}

		public static void Shutdown()
		{
			ClearRemoteSpirits();
			initialized = false;
			registeredRpc = null;
			requestedWorldState = false;
			localSummonAnnounced = false;
			nextSendTime = 0f;
			nextTimeoutCheckTime = 0f;
			currentLocalInstanceId = 0L;
			despawnedInstances.Clear();
		}

		private static void EnsureRpcRegistered()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null && instance != registeredRpc)
			{
				registeredRpc = instance;
				requestedWorldState = false;
				localSummonAnnounced = false;
				registeredRpc.Register<ZPackage>("FalseMods.BossSpirits.Summon", (Action<long, ZPackage>)OnSummon);
				registeredRpc.Register<ZPackage>("FalseMods.BossSpirits.Transform", (Action<long, ZPackage>)OnTransform);
				registeredRpc.Register<ZPackage>("FalseMods.BossSpirits.Despawn", (Action<long, ZPackage>)OnDespawn);
				registeredRpc.Register<ZPackage>("FalseMods.BossSpirits.StateRequest", (Action<long, ZPackage>)OnStateRequest);
				Debug.Log((object)"Boss Spirits: Multiplayer RPCs registered.");
			}
		}

		private static void SendStateRequest()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(6);
			registeredRpc.InvokeRoutedRPC(ZRoutedRpc.Everybody, "FalseMods.BossSpirits.StateRequest", new object[1] { val });
		}

		private static void SendSummon(long targetPeerId, ActiveSpirit active, bool playEffect)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			SpiritNetworkState spiritNetworkState = CreateLocalState(active, playEffect);
			if (spiritNetworkState != null)
			{
				ZPackage val = new ZPackage();
				spiritNetworkState.Write(val);
				registeredRpc.InvokeRoutedRPC(targetPeerId, "FalseMods.BossSpirits.Summon", new object[1] { val });
			}
		}

		private static void SendTransform(ActiveSpirit active)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			if (active == null || !NativeSpiritPrefabRegistry.IsNativeDefinition(active.Definition))
			{
				SpiritNetworkState spiritNetworkState = CreateLocalState(active, playEffect: false);
				if (spiritNetworkState != null)
				{
					ZPackage val = new ZPackage();
					spiritNetworkState.Write(val);
					registeredRpc.InvokeRoutedRPC(ZRoutedRpc.Everybody, "FalseMods.BossSpirits.Transform", new object[1] { val });
				}
			}
		}

		private static SpiritNetworkState CreateLocalState(ActiveSpirit active, bool playEffect)
		{
			//IL_0066: 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)
			if (active == null || (Object)(object)active.GameObject == (Object)null || active.Definition == null || currentLocalInstanceId <= 0)
			{
				return null;
			}
			float movementSpeed = 0f;
			SpiritFollowController component = active.GameObject.GetComponent<SpiritFollowController>();
			if ((Object)(object)component != (Object)null)
			{
				movementSpeed = component.CurrentMovementSpeed;
			}
			return new SpiritNetworkState(ZNet.GetUID(), currentLocalInstanceId, active.Definition.Id, active.GameObject.transform.position, active.GameObject.transform.rotation, movementSpeed, playEffect);
		}

		private static void OnSummon(long senderPeerId, ZPackage package)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: 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_0111: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.m_localPlayer == (Object)null || !SpiritNetworkState.TryRead(package, out var state) || IsLocalOwner(state.OwnerPeerId))
			{
				return;
			}
			if (!SpiritRegistry.TryGetById(state.SpiritId, out var definition))
			{
				Debug.LogWarning((object)("Boss Spirits: Remote Spirit ID is unknown: " + state.SpiritId));
			}
			else if (NativeSpiritPrefabRegistry.IsNativeDefinition(definition))
			{
				if (despawnedInstances.TryGetValue(state.OwnerPeerId, out var value))
				{
					if (value == state.InstanceId)
					{
						return;
					}
					despawnedInstances.Remove(state.OwnerPeerId);
				}
				if (state.PlayEffect)
				{
					SpiritSpawner.PlayNetworkPoof(state.Position, state.Rotation);
				}
			}
			else
			{
				if (despawnedInstances.TryGetValue(state.OwnerPeerId, out var _))
				{
					return;
				}
				if (remoteSpirits.TryGetValue(state.OwnerPeerId, out var value3))
				{
					if (value3.InstanceId == state.InstanceId && value3.SpiritId == state.SpiritId)
					{
						value3.ApplyState(state);
						return;
					}
					RemoveRemoteSpirit(state.OwnerPeerId, playEffect: false, state.Position, state.Rotation);
				}
				if (state.PlayEffect)
				{
					SpiritSpawner.PlayNetworkPoof(state.Position, state.Rotation);
				}
				GameObject val = SpiritModelFactory.CreateRemote(definition, state.Position, state.Rotation);
				if (!((Object)(object)val == (Object)null))
				{
					RemoteSpiritProxy remoteSpiritProxy = val.AddComponent<RemoteSpiritProxy>();
					remoteSpiritProxy.Initialize(state.OwnerPeerId, definition, state);
					remoteSpirits[state.OwnerPeerId] = remoteSpiritProxy;
					Debug.Log((object)("Boss Spirits: Remote " + definition.DisplayName + " appeared."));
				}
			}
		}

		private static void OnTransform(long senderPeerId, ZPackage package)
		{
			//IL_00be: 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_00e4: 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 ((Object)(object)Player.m_localPlayer == (Object)null || !SpiritNetworkState.TryRead(package, out var state) || IsLocalOwner(state.OwnerPeerId))
			{
				return;
			}
			if (despawnedInstances.TryGetValue(state.OwnerPeerId, out var value))
			{
				if (value == state.InstanceId)
				{
					return;
				}
				despawnedInstances.Remove(state.OwnerPeerId);
			}
			if (SpiritRegistry.TryGetById(state.SpiritId, out var definition) && NativeSpiritPrefabRegistry.IsNativeDefinition(definition))
			{
				return;
			}
			if (remoteSpirits.TryGetValue(state.OwnerPeerId, out var value2))
			{
				if (value2.InstanceId == state.InstanceId && value2.SpiritId == state.SpiritId)
				{
					value2.ApplyState(state);
				}
			}
			else
			{
				if (!SpiritRegistry.TryGetById(state.SpiritId, out var definition2))
				{
					return;
				}
				GameObject val = SpiritModelFactory.CreateRemote(definition2, state.Position, state.Rotation);
				if (!((Object)(object)val == (Object)null))
				{
					if (state.PlayEffect)
					{
						SpiritSpawner.PlayNetworkPoof(state.Position, state.Rotation);
					}
					value2 = val.AddComponent<RemoteSpiritProxy>();
					value2.Initialize(state.OwnerPeerId, definition2, state);
					remoteSpirits[state.OwnerPeerId] = value2;
				}
			}
		}

		private static void OnDespawn(long senderPeerId, ZPackage package)
		{
			//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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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)
			if (package.ReadInt() == 6)
			{
				long num = package.ReadLong();
				long value = package.ReadLong();
				if (!IsLocalOwner(num))
				{
					bool playEffect = package.ReadBool();
					Vector3 effectPosition = package.ReadVector3();
					Quaternion effectRotation = package.ReadQuaternion();
					despawnedInstances[num] = value;
					RemoveRemoteSpirit(num, playEffect, effectPosition, effectRotation);
				}
			}
		}

		private static void OnStateRequest(long senderPeerId, ZPackage package)
		{
			if (package.ReadInt() == 6 && !IsLocalSender(senderPeerId))
			{
				ActiveSpirit currentActiveSpirit = SpiritSummonManager.CurrentActiveSpirit;
				if (currentActiveSpirit != null && registeredRpc != null)
				{
					SendSummon(senderPeerId, currentActiveSpirit, playEffect: false);
				}
			}
		}

		private static bool IsLocalSender(long senderPeerId)
		{
			if ((Object)(object)ZNet.instance != (Object)null)
			{
				return senderPeerId == ZNet.GetUID();
			}
			return false;
		}

		private static bool IsLocalOwner(long ownerPeerId)
		{
			if ((Object)(object)ZNet.instance != (Object)null)
			{
				return ownerPeerId == ZNet.GetUID();
			}
			return false;
		}

		private static void CleanupTimedOutProxies()
		{
			//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)
			List<long> list = new List<long>();
			foreach (KeyValuePair<long, RemoteSpiritProxy> remoteSpirit in remoteSpirits)
			{
				if ((Object)(object)remoteSpirit.Value == (Object)null || Time.time - remoteSpirit.Value.LastUpdateTime > 8f)
				{
					list.Add(remoteSpirit.Key);
				}
			}
			foreach (long item in list)
			{
				RemoveRemoteSpirit(item, playEffect: false, Vector3.zero, Quaternion.identity);
			}
		}

		private static void RemoveRemoteSpirit(long ownerPeerId, bool playEffect, Vector3 effectPosition, Quaternion effectRotation)
		{
			//IL_00a9: 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)
			remoteSpirits.TryGetValue(ownerPeerId, out var value);
			remoteSpirits.Remove(ownerPeerId);
			int num = 0;
			RemoteSpiritProxy[] array = Object.FindObjectsByType<RemoteSpiritProxy>((FindObjectsSortMode)0);
			foreach (RemoteSpiritProxy remoteSpiritProxy in array)
			{
				if (!((Object)(object)remoteSpiritProxy == (Object)null) && remoteSpiritProxy.OwnerPeerId == ownerPeerId)
				{
					((Component)remoteSpiritProxy).gameObject.SetActive(false);
					Object.Destroy((Object)(object)((Component)remoteSpiritProxy).gameObject);
					num++;
				}
			}
			if ((Object)(object)value != (Object)null && (Object)(object)((Component)value).gameObject != (Object)null && ((Component)value).gameObject.activeSelf)
			{
				((Component)value).gameObject.SetActive(false);
				Object.Destroy((Object)(object)((Component)value).gameObject);
				num++;
			}
			if (playEffect)
			{
				SpiritSpawner.PlayNetworkPoof(effectPosition, effectRotation);
			}
			Debug.Log((object)("Boss Spirits: Remote despawn removed " + num + " visual proxy object(s) for owner " + ownerPeerId + "."));
		}

		private static void ClearRemoteSpirits()
		{
			foreach (RemoteSpiritProxy value in remoteSpirits.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)value).gameObject);
				}
			}
			remoteSpirits.Clear();
		}
	}
	public sealed class SpiritNetworkState
	{
		public const int ProtocolVersion = 6;

		public long OwnerPeerId;

		public long InstanceId;

		public string SpiritId;

		public Vector3 Position;

		public Quaternion Rotation;

		public float MovementSpeed;

		public bool PlayEffect;

		public SpiritNetworkState()
		{
		}

		public SpiritNetworkState(long ownerPeerId, long instanceId, string spiritId, Vector3 position, Quaternion rotation, float movementSpeed, bool playEffect)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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)
			OwnerPeerId = ownerPeerId;
			InstanceId = instanceId;
			SpiritId = spiritId;
			Position = position;
			Rotation = rotation;
			MovementSpeed = movementSpeed;
			PlayEffect = playEffect;
		}

		public void Write(ZPackage package)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			package.Write(6);
			package.Write(OwnerPeerId);
			package.Write(InstanceId);
			package.Write(SpiritId ?? string.Empty);
			package.Write(Position);
			package.Write(Rotation);
			package.Write(MovementSpeed);
			package.Write(PlayEffect);
		}

		public static bool TryRead(ZPackage package, out SpiritNetworkState state)
		{
			//IL_0042: 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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			state = null;
			if (package == null)
			{
				return false;
			}
			try
			{
				if (package.ReadInt() != 6)
				{
					return false;
				}
				SpiritNetworkState spiritNetworkState = new SpiritNetworkState();
				spiritNetworkState.OwnerPeerId = package.ReadLong();
				spiritNetworkState.InstanceId = package.ReadLong();
				spiritNetworkState.SpiritId = package.ReadString();
				spiritNetworkState.Position = package.ReadVector3();
				spiritNetworkState.Rotation = package.ReadQuaternion();
				spiritNetworkState.MovementSpeed = package.ReadSingle();
				spiritNetworkState.PlayEffect = package.ReadBool();
				state = spiritNetworkState;
				return true;
			}
			catch
			{
				return false;
			}
		}
	}
}
namespace FalseMods.BossSpirits.Lifecycle
{
	public static class SpiritLifecycleManager
	{
		private const float StateCheckInterval = 0.15f;

		private static readonly string[] TeleportMemberNames = new string[3] { "m_teleporting", "teleporting", "IsTeleporting" };

		private static readonly string[] DistantTeleportMemberNames = new string[2] { "m_distantTeleport", "distantTeleport" };

		private static readonly string[] ShipMemberNames = new string[3] { "m_currentShip", "currentShip", "CurrentShip" };

		private static readonly string[] ShipMethodNames = new string[3] { "GetControlledShip", "GetStandingOnShip", "GetCurrentShip" };

		private static bool initialized;

		private static float nextStateCheck;

		private static Player lastPlayer;

		private static bool teleportStateLatched;

		public static void Initialize()
		{
			if (!initialized)
			{
				initialized = true;
				nextStateCheck = 0f;
				lastPlayer = null;
				teleportStateLatched = false;
				Debug.Log((object)"Boss Spirits: Spirit Lifecycle Manager initialized.");
			}
		}

		public static void Update()
		{
			if (!initialized || Time.time < nextStateCheck)
			{
				return;
			}
			nextStateCheck = Time.time + 0.15f;
			Player localPlayer = Player.m_localPlayer;
			bool flag = SpiritSummonManager.HasActiveSpirit || SpiritSpawner.HasPendingOperation;
			if ((Object)(object)localPlayer == (Object)null)
			{
				if (flag)
				{
					SpiritSummonManager.ForceCleanup("the player left the world");
				}
				lastPlayer = null;
				teleportStateLatched = false;
				return;
			}
			if ((Object)(object)lastPlayer != (Object)null && (Object)(object)lastPlayer != (Object)(object)localPlayer && flag)
			{
				SpiritSummonManager.ForceCleanup("the local player changed");
				lastPlayer = localPlayer;
				teleportStateLatched = false;
				return;
			}
			lastPlayer = localPlayer;
			if (!flag)
			{
				return;
			}
			ActiveSpirit currentActiveSpirit = SpiritSummonManager.CurrentActiveSpirit;
			bool flag2 = currentActiveSpirit != null && currentActiveSpirit.Definition.LifecyclePolicy == SpiritLifecyclePolicy.AnchoredWorksite;
			if (!flag2 && IsPlayerDead(localPlayer))
			{
				SpiritSummonManager.ForceCleanup("the player died");
				return;
			}
			bool flag3 = IsPlayerTeleporting(localPlayer);
			if (!flag2 && flag3)
			{
				if (!teleportStateLatched)
				{
					teleportStateLatched = true;
					SpiritSummonManager.ForceCleanup("the player began teleporting");
					return;
				}
			}
			else
			{
				teleportStateLatched = false;
			}
			if (!flag2 && IsPlayerOnShip(localPlayer))
			{
				SpiritSummonManager.RequestLifecycleDespawn("the player boarded a ship");
			}
			else
			{
				CheckForsakenPower(localPlayer);
			}
		}

		public static void Shutdown()
		{
			initialized = false;
			nextStateCheck = 0f;
			lastPlayer = null;
			teleportStateLatched = false;
		}

		private static void CheckForsakenPower(Player player)
		{
			ActiveSpirit currentActiveSpirit = SpiritSummonManager.CurrentActiveSpirit;
			if (currentActiveSpirit != null && ForsakenPowerManager.TryGetEquippedPowerName(player, out var powerName) && (!SpiritRegistry.TryGetByForsakenPower(powerName, out var definition) || definition.Id != currentActiveSpirit.Definition.Id))
			{
				SpiritSummonManager.RequestLifecycleDespawn("the selected Forsaken Power changed");
			}
		}

		private static bool IsPlayerDead(Player player)
		{
			if (TryInvokeNoArgumentMethod(player, "IsDead", out var result) && result is bool)
			{
				return (bool)result;
			}
			return false;
		}

		private static bool IsPlayerTeleporting(Player player)
		{
			if (TryInvokeNoArgumentMethod(player, "IsTeleporting", out var result) && result is bool && (bool)result)
			{
				return true;
			}
			if (TryReadBooleanMember(player, TeleportMemberNames, out var value) && value)
			{
				return true;
			}
			if (TryReadBooleanMember(player, DistantTeleportMemberNames, out value) && value)
			{
				return true;
			}
			return false;
		}

		private static bool IsPlayerOnShip(Player player)
		{
			string[] shipMethodNames = ShipMethodNames;
			object result;
			foreach (string methodName in shipMethodNames)
			{
				if (TryInvokeNoArgumentMethod(player, methodName, out result) && IsUnityObjectAlive(result))
				{
					return true;
				}
			}
			if (TryReadObjectMember(player, ShipMemberNames, out result) && IsUnityObjectAlive(result))
			{
				return true;
			}
			Type type = typeof(Player).Assembly.GetType("Ship");
			if (type == null)
			{
				return false;
			}
			MethodInfo method = type.GetMethod("GetLocalShip", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
			if (method == null)
			{
				return false;
			}
			try
			{
				result = method.Invoke(null, null);
				return IsUnityObjectAlive(result);
			}
			catch
			{
				return false;
			}
		}

		private static bool TryReadBooleanMember(object target, string[] memberNames, out bool value)
		{
			value = false;
			if (!TryReadObjectMember(target, memberNames, out var value2) || !(value2 is bool))
			{
				return false;
			}
			value = (bool)value2;
			return true;
		}

		private static bool TryReadObjectMember(object target, string[] memberNames, out object value)
		{
			value = null;
			if (target == null)
			{
				return false;
			}
			Type type = target.GetType();
			while (type != null)
			{
				foreach (string name in memberNames)
				{
					FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field != null)
					{
						try
						{
							value = field.GetValue(target);
							return true;
						}
						catch
						{
						}
					}
					PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (property != null && property.CanRead)
					{
						try
						{
							value = property.GetValue(target, null);
							return true;
						}
						catch
						{
						}
					}
				}
				type = type.BaseType;
			}
			return false;
		}

		private static bool TryInvokeNoArgumentMethod(object target, string methodName, out object result)
		{
			result = null;
			if (target == null)
			{
				return false;
			}
			Type type = target.GetType();
			while (type != null)
			{
				MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
				if (method != null)
				{
					try
					{
						result = method.Invoke(target, null);
						return true;
					}
					catch
					{
						return false;
					}
				}
				type = type.BaseType;
			}
			return false;
		}

		private static bool IsUnityObjectAlive(object value)
		{
			return (Object)((value is Object) ? value : null) != (Object)null;
		}
	}
}
namespace FalseMods.BossSpirits.Native
{
	internal static class WardAccessCompatibility
	{
		private const BindingFlags PublicStatic = BindingFlags.Static | BindingFlags.Public;

		private static bool resolved;

		private static bool invocationFailed;

		private static MethodInfo checkInsideWardMethod;

		private static MethodInfo checkCustomAccessMethod;

		private static MethodInfo getWardMethod;

		private static MethodInfo getCreaturePushoutMethod;

		private static MethodInfo getBubbleMethod;

		public static bool IsBlocked(Player summoner, Vector3 point)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)summoner == (Object)null)
			{
				return false;
			}
			if (!PrivateArea.CheckAccess(point, 0f, false, true))
			{
				return true;
			}
			ResolveWardIsLove();
			if (invocationFailed || checkInsideWardMethod == null || checkCustomAccessMethod == null)
			{
				return false;
			}
			try
			{
				if (!(bool)checkInsideWardMethod.Invoke(null, new object[2] { point, false }))
				{
					return false;
				}
				object obj = null;
				if (getWardMethod != null)
				{
					obj = getWardMethod.Invoke(null, new object[1] { point });
				}
				if (obj != null && getCreaturePushoutMethod != null && !(bool)getCreaturePushoutMethod.Invoke(null, new object[1] { obj }))
				{
					return false;
				}
				if (obj != null && getBubbleMethod != null && !(bool)getBubbleMethod.Invoke(null, new object[1] { obj }))
				{
					return false;
				}
				return !(bool)checkCustomAccessMethod.Invoke(null, new object[4]
				{
					summoner.GetPlayerID(),
					point,
					0f,
					false
				});
			}
			catch (Exception ex)
			{
				invocationFailed = true;
				Debug.LogWarning((object)("Boss Spirits: WardIsLove compatibility was disabled after its API changed.\n" + ex));
				return false;
			}
		}

		private static void ResolveWardIsLove()
		{
			if (resolved)
			{
				return;
			}
			resolved = true;
			Type type = Type.GetType("WardIsLove.Util.WardMonoscript, WardIsLove");
			Type type2 = Type.GetType("WardIsLove.Util.CustomCheck, WardIsLove");
			Type type3 = Type.GetType("WardIsLove.Extensions.WardMonoscriptExt, WardIsLove");
			if (!(type == null) && !(type2 == null))
			{
				checkInsideWardMethod = type.GetMethod("CheckInWardMonoscript", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
				{
					typeof(Vector3),
					typeof(bool)
				}, null);
				checkCustomAccessMethod = type2.GetMethod("CheckAccess", BindingFlags.Static | BindingFlags.Public, null, new Type[4]
				{
					typeof(long),
					typeof(Vector3),
					typeof(float),
					typeof(bool)
				}, null);
				if (type3 != null)
				{
					getWardMethod = type3.GetMethod("GetWardMonoscript", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Vector3) }, null);
					getCreaturePushoutMethod = FindWardOptionMethod(type3, type, "GetPushoutCreaturesOn", "GetPushoutCreatureOn", "GetCreaturePushoutOn", "GetPushCreaturesOn");
					getBubbleMethod = FindWardOptionMethod(type3, type, "GetBubbleOn", "GetBubbleEnabled", "GetWardBubbleOn");
				}
				if (checkInsideWardMethod != null && checkCustomAccessMethod != null)
				{
					Debug.Log((object)"Boss Spirits: WardIsLove access compatibility enabled.");
				}
			}
		}

		private static MethodInfo FindWardOptionMethod(Type extensionType, Type wardType, params string[] candidateNames)
		{
			foreach (string name in candidateNames)
			{
				MethodInfo method = extensionType.GetMethod(name, BindingFlags.Static | BindingFlags.Public, null, new Type[1] { wardType }, null);
				if (method != null && method.ReturnType == typeof(bool))
				{
					return method;
				}
			}
			return null;
		}
	}
	[DefaultExecutionOrder(500)]
	public sealed class NativeEikthyrController : NativeSpiritMountController
	{
		private const float FollowStopDistance = 13f;

		private const float FollowRunDistance = 25f;

		private const float FollowTeleportDistance = 65f;

		private const float WalkAnimationSpeed = 1.35f;

		private const float RunAnimationSpeed = 1.7f;

		private const float AnimationSpeedBlendRate = 5f;

		private const float MovingSpeedThreshold = 0.35f;

		private const float ForestClutterProbeRadius = 8f;

		private const float WardLeadingProbeDistance = 2.75f;

		private const float EffectSuppressionInterval = 0.25f;

		private const string StaminaMemoryId = "eikthyr";

		private static readonly MethodInfo MoveToMethod = AccessTools.Method(typeof(BaseAI), "MoveTo", new Type[4]
		{
			typeof(float),
			typeof(Vector3),
			typeof(float),
			typeof(bool)
		}, (Type[])null);

		private static readonly MethodInfo ShowHandItemsMethod = AccessTools.Method(typeof(Humanoid), "ShowHandItems", new Type[2]
		{
			typeof(bool),
			typeof(bool)
		}, (Type[])null);

		private static readonly FieldInfo LeftItemField = AccessTools.Field(typeof(Humanoid), "m_leftItem");

		private static readonly FieldInfo RightItemField = AccessTools.Field(typeof(Humanoid), "m_rightItem");

		private Humanoid character;

		private MonsterAI monsterAI;

		private Tameable tameable;

		private Sadle saddle;

		private ZNetView networkView;

		private Rigidbody body;

		private ZSyncTransform syncTransform;

		private ZSyncAnimation syncAnimation;

		private CapsuleCollider mountCollider;

		private readonly Collider[] forestClutterBuffer = (Collider[])(object)new Collider[64];

		private Player owner;

		private bool jumpRequested;

		private bool wasLocallyMounted;

		private bool restoreHandItems;

		private bool deepWaterCleanupRequested;

		private bool forestClutterIgnoreLogged;

		private bool hasWardSafePosition;

		private bool wardBlockLogged;

		private bool staminaMemoryInitialized;

		private float currentAnimationSpeed = 1f;

		private float nextEffectSuppressionTime;

		private int defaultSmallLayer = -1;

		private Vector3 lastWardSafePosition;

		private Quaternion lastWardSafeRotation;

		private Player presentedRemoteRider;

		public override string SpiritDisplayName => "Eikthyr Spirit";

		public override Sadle Saddle => saddle;

		public void InitializeOwner(Player summoningPlayer)
		{
			owner = summoningPlayer;
			CacheComponents();
			ApplyOwnerAndSaddleState();
		}

		public override void RequestJump()
		{
			jumpRequested = true;
		}

		public override bool HandleNativeFollow(BaseAI ai, GameObject target, float deltaTime)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//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_00bf: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ai == (Object)null || (Object)(object)target == (Object)null || (Object)(object)networkView == (Object)null || !networkView.IsValid() || !networkView.IsOwner())
			{
				return false;
			}
			if (IsLocallyMounted())
			{
				return false;
			}
			Vector3 position = target.transform.position;
			float num = Vector3.Distance(((Component)this).transform.position, position);
			if (num >= 65f)
			{
				TeleportBehind(target.transform);
				ai.StopMoving();
				return true;
			}
			if (num < 13f)
			{
				ai.StopMoving();
				return true;
			}
			if (MoveToMethod == null)
			{
				return false;
			}
			bool flag = num > 25f;
			MoveToMethod.Invoke(ai, new object[4] { deltaTime, position, 0f, flag });
			return true;
		}

		private void Awake()
		{
			CacheComponents();
		}

		private void Start()
		{
			if (!RemovePersistedOrphan())
			{
				SuppressDecorativeEffects();
				ApplyOwnerAndSaddleState();
			}
		}

		private void FixedUpdate()
		{
			if ((Object)(object)networkView == (Object)null || !networkView.IsValid() || !networkView.IsOwner())
			{
				return;
			}
			UpdateStaminaMemory();
			IgnoreNearbyForestClutter();
			if (EnforceWardBoundary())
			{
				jumpRequested = false;
				return;
			}
			bool flag = IsLocallyMounted();
			UpdateMountedEquipment(flag);
			if (!flag)
			{
				jumpRequested = false;
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				if (((Character)localPlayer).IsEncumbered())
				{
					localPlayer.StopDoodadControl();
					((Character)localPlayer).Message((MessageType)2, "You are carrying too much to ride.", 0, (Sprite)null);
				}
				else if (!deepWaterCleanupRequested && (Object)(object)character != (Object)null && ((Character)character).IsSwimming() && !((Character)character).IsOnGround())
				{
					deepWaterCleanupRequested = true;
					localPlayer.StopDoodadControl();
					SpiritSummonManager.RequestLifecycleDespawn("Eikthyr entered deep water");
				}
				else if (jumpRequested)
				{
					jumpRequested = false;
					TryNativeJump();
				}
			}
		}

		private void LateUpdate()
		{
			UpdateLocomotionAnimationSpeed();
			if (Time.time >= nextEffectSuppressionTime)
			{
				nextEffectSuppressionTime = Time.time + 0.25f;
				SuppressDecorativeEffects();
			}
			PresentRemoteRiderAtSaddle();
		}

		private void CacheComponents()
		{
			if ((Object)(object)character == (Object)null)
			{
				character = ((Component)this).GetComponent<Humanoid>();
			}
			if ((Object)(object)monsterAI == (Object)null)
			{
				monsterAI = ((Component)this).GetComponent<MonsterAI>();
			}
			if ((Object)(object)tameable == (Object)null)
			{
				tameable = ((Component)this).GetComponent<Tameable>();
			}
			if ((Object)(object)saddle == (Object)null)
			{
				saddle = ((Component)this).GetComponentInChildren<Sadle>(true);
			}
			if ((Object)(object)networkView == (Object)null)
			{
				networkView = ((Component)this).GetComponent<ZNetView>();
			}
			if ((Object)(object)body == (Object)null)
			{
				body = ((Component)this).GetComponent<Rigidbody>();
			}
			if ((Object)(object)body != (Object)null)
			{
				body.interpolation = (RigidbodyInterpolation)1;
			}
			if ((Object)(object)syncTransform == (Object)null)
			{
				syncTransform = ((Component)this).GetComponent<ZSyncTransform>();
			}
			if ((Object)(object)syncAnimation == (Object)null && (Object)(object)character != (Object)null)
			{
				syncAnimation = ((Character)character).GetZAnim();
			}
			if ((Object)(object)mountCollider == (Object)null)
			{
				mountCollider = ((Component)this).GetComponent<CapsuleCollider>();
			}
			if (defaultSmallLayer < 0)
			{
				defaultSmallLayer = LayerMask.NameToLayer("Default_small");
			}
		}

		private void IgnoreNearbyForestClutter()
		{
			//IL_0037: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)mountCollider == (Object)null || !((Collider)mountCollider).enabled || defaultSmallLayer < 0)
			{
				return;
			}
			int num = 1 << defaultSmallLayer;
			Bounds bounds = ((Collider)mountCollider).bounds;
			int num2 = Physics.OverlapSphereNonAlloc(((Bounds)(ref bounds)).center, 8f, forestClutterBuffer, num, (QueryTriggerInteraction)1);
			for (int i = 0; i < num2; i++)
			{
				Collider val = forestClutterBuffer[i];
				forestClutterBuffer[i] = null;
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)mountCollider) && !((Component)val).transform.IsChildOf(((Component)this).transform))
				{
					Physics.IgnoreCollision((Collider)(object)mountCollider, val, true);
					if (!forestClutterIgnoreLogged)
					{
						forestClutterIgnoreLogged = true;
						Debug.Log((object)"Boss Spirits: Eikthyr mount collision now passes through Default_small forest clutter.");
					}
				}
			}
		}

		private bool EnforceWardBoundary()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_0091: 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_00a2: 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_0063: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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_00eb: 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)
			if ((Object)(object)owner == (Object)null || (Object)(object)body == (Object)null)
			{
				return false;
			}
			Vector3 position = body.position;
			Vector3 linearVelocity = body.linearVelocity;
			linearVelocity.y = 0f;
			bool flag = WardAccessCompatibility.IsBlocked(owner, position);
			if (!flag && ((Vector3)(ref linearVelocity)).sqrMagnitude > 0.04f)
			{
				Vector3 point = position + ((Vector3)(ref linearVelocity)).normalized * 2.75f;
				flag = WardAccessCompatibility.IsBlocked(owner, point);
			}
			if (!flag)
			{
				hasWardSafePosition = true;
				lastWardSafePosition = position;
				lastWardSafeRotation = body.rotation;
				return false;
			}
			if (!hasWardSafePosition)
			{
				return false;
			}
			body.position = lastWardSafePosition;
			body.rotation = lastWardSafeRotation;
			body.linearVelocity = Vector3.zero;
			body.angularVelocity = Vector3.zero;
			if ((Object)(object)character != (Object)null)
			{
				((Character)character).SetMoveDir(Vector3.zero);
				((Character)character).SetRun(false);
			}
			if ((Object)(object)monsterAI != (Object)null)
			{
				((BaseAI)monsterAI).StopMoving();
			}
			Physics.SyncTransforms();
			if ((Object)(object)syncTransform != (Object)null)
			{
				syncTransform.SyncNow();
			}
			if (!wardBlockLogged)
			{
				wardBlockLogged = true;
				Debug.Log((object)"Boss Spirits: Eikthyr was stopped at an unpermitted ward boundary.");
			}
			return true;
		}

		private void SuppressDecorativeEffects()
		{
			//IL_001a: 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_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)
			ParticleSystem[] componentsInChildren = ((Component)this).GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					MainModule main = val.main;
					((MainModule)(ref main)).playOnAwake = false;
					EmissionModule emission = val.emission;
					((EmissionModule)(ref emission)).enabled = false;
					val.Stop(true, (ParticleSystemStopBehavior)0);
				}
			}
			ParticleSystemRenderer[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<ParticleSystemRenderer>(true);
			foreach (ParticleSystemRenderer val2 in componentsInChildren2)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					((Renderer)val2).enabled = false;
				}
			}
			TrailRenderer[] componentsInChildren3 = ((Component)this).GetComponentsInChildren<TrailRenderer>(true);
			foreach (TrailRenderer val3 in componentsInChildren3)
			{
				if ((Object)(object)val3 != (Object)null)
				{
					((Renderer)val3).enabled = false;
				}
			}
			Light[] componentsInChildren4 = ((Component)this).GetComponentsInChildren<Light>(true);
			foreach (Light val4 in componentsInChildren4)
			{
				if ((Object)(object)val4 != (Object)null)
				{
					((Behaviour)val4).enabled = false;
				}
			}
		}

		private void PresentRemoteRiderAtSaddle()
		{
			//IL_00e1: 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)
			if ((Object)(object)saddle == (Object)null || (Object)(object)saddle.m_attachPoint == (Object)null || (Object)(object)networkView == (Object)null || !networkView.IsValid())
			{
				presentedRemoteRider = null;
				return;
			}
			ZDO zDO = networkView.GetZDO();
			long num = ((zDO == null) ? 0 : zDO.GetLong(ZDOVars.s_user, 0L));
			if (num == 0L)
			{
				presentedRemoteRider = null;
				return;
			}
			if ((Object)(object)presentedRemoteRider == (Object)null || (Object)(object)presentedRemoteRider == (Object)(object)Player.m_localPlayer || GetPlayerZdoUserId(presentedRemoteRider) != num)
			{
				presentedRemoteRider = FindRemotePlayer(num);
			}
			if (!((Object)(object)presentedRemoteRider == (Object)null) && !((Object)(object)presentedRemoteRider == (Object)(object)Player.m_localPlayer))
			{
				((Component)presentedRemoteRider).transform.SetPositionAndRotation(saddle.m_attachPoint.position, saddle.m_attachPoint.rotation);
			}
		}

		private static Player FindRemotePlayer(long zdoUserId)
		{
			List<Player> allPlayers = Player.GetAllPlayers();
			if (allPlayers == null)
			{
				return null;
			}
			foreach (Player item in allPlayers)
			{
				if ((Object)(object)item != (Object)null && (Object)(object)item != (Object)(object)Player.m_localPlayer && GetPlayerZdoUserId(item) == zdoUserId)
				{
					return item;
				}
			}
			return null;
		}

		private static long GetPlayerZdoUserId(Player player)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return 0L;
			}
			ZDOID zDOID = ((Character)player).GetZDOID();
			return ((ZDOID)(ref zDOID)).UserID;
		}

		private void ApplyOwnerAndSaddleState()
		{
			CacheComponents();
			if ((Object)(object)saddle != (Object)null)
			{
				((Component)saddle).gameObject.SetActive(true);
				NativeEikthyrPrefab.ApplyEikthyrMountIcon(saddle);
			}
			if ((Object)(object)networkView != (Object)null && networkView.IsValid() && networkView.IsOwner())
			{
				ZDO zDO = networkView.GetZDO();
				if (zDO != null)
				{
					zDO.Set(ZDOVars.s_haveSaddleHash, true);
				}
				if ((Object)(object)character != (Object)null)
				{
					((Character)character).SetTamed(true);
				}
				if ((Object)(object)monsterAI != (Object)null && (Object)(object)owner != (Object)null)
				{
					monsterAI.SetFollowTarget(((Component)owner).gameObject);
				}
			}
		}

		private bool RemovePersistedOrphan()
		{
			CacheComponents();
			if ((Object)(object)networkView == (Object)null || !networkView.IsValid())
			{
				return false;
			}
			ZDO zDO = networkView.GetZDO();
			if (zDO == null || (Object)(object)owner != (Object)null || !networkView.IsOwner())
			{
				return false;
			}
			zDO.Persistent = false;
			Debug.LogWarning((object)"Boss Spirits: Removing an ownerless Eikthyr Spirit restored from an earlier test build.");
			networkView.Destroy();
			return true;
		}

		private bool IsLocallyMounted()
		{
			if ((Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)saddle != (Object)null)
			{
				return (object)Player.m_localPlayer.GetDoodadController() == saddle;
			}
			return false;
		}

		private void TryNativeJump()
		{
			if (!((Object)(object)character == (Object)null) && ((Character)character).IsOnGround())
			{
				((Character)character).Jump(false);
			}
		}

		private void UpdateLocomotionAnimationSpeed()
		{
			//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)
			if (!((Object)(object)character == (Object)null) && !((Object)(object)syncAnimation == (Object)null))
			{
				float num = 1f;
				Vector3 velocity = ((Character)character).GetVelocity();
				velocity.y = 0f;
				if (((Character)character).IsOnGround() && ((Vector3)(ref velocity)).magnitude >= 0.35f)
				{
					num = (((Character)character).IsRunning() ? 1.7f : 1.35f);
				}
				currentAnimationSpeed = Mathf.MoveTowards(currentAnimationSpeed, num, 5f * Time.deltaTime);
				syncAnimation.SetSpeed(currentAnimationSpeed);
			}
		}

		private void TeleportBehind(Transform target)
		{
			//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_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_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_0021: 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_0074: 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_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_0059: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			Vector3 forward = target.forward;
			forward.y = 0f;
			if (((Vector3)(ref forward)).sqrMagnitude < 0.001f)
			{
				forward = Vector3.forward;
			}
			((Vector3)(ref forward)).Normalize();
			Vector3 val = target.position - forward * 13f;
			if ((Object)(object)ZoneSystem.instance != (Object)null)
			{
				val.y = ZoneSystem.instance.GetGroundHeight(val);
			}
			val.y += 0.5f;
			Quaternion val2 = Quaternion.LookRotation(forward, Vector3.up);
			if ((Object)(object)body != (Object)null)
			{
				body.position = val;
				body.rotation = val2;
				body.linearVelocity = Vector3.zero;
				body.angularVelocity = Vector3.zero;
			}
			else
			{
				((Component)this).transform.SetPositionAndRotation(val, val2);
			}
			Physics.SyncTransforms();
			if ((Object)(object)syncTransform != (Object)null)
			{
				syncTransform.SyncNow();
			}
		}

		private void UpdateMountedEquipment(bool mounted)
		{
			if (mounted != wasLocallyMounted)
			{
				Player localPlayer = Player.m_localPlayer;
				if (mounted && (Object)(object)localPlayer != (Object)null)
				{
					restoreHandItems = WereHandItemsDrawn(localPlayer);
					((Humanoid)localPlayer).HideHandItems(false, true);
				}
				else if (!mounted && (Object)(object)localPlayer != (Object)null && restoreHandItems && ShowHandItemsMethod != null)
				{
					ShowHandItemsMethod.Invoke(localPlayer, new object[2] { false, true });
					restoreHandItems = false;
				}
				wasLocallyMounted = mounted;
			}
		}

		private static bool WereHandItemsDrawn(Player player)
		{
			if (!(LeftItemField != null) || LeftItemField.GetValue(player) == null)
			{
				if (RightItemField != null)
				{
					return RightItemField.GetValue(player) != null;
				}
				return false;
			}
			return true;
		}

		private void OnDisable()
		{
			CaptureStaminaMemory();
			if ((Object)(object)syncAnimation != (Object)null)
			{
				syncAnimation.SetSpeed(1f);
			}
			UpdateMountedEquipment(mounted: false);
		}

		private void UpdateStaminaMemory()
		{
			if (!((Object)(object)saddle == (Object)null) && !((Object)(object)owner == (Object)null) && !((Object)(object)owner != (Object)(object)Player.m_localPlayer))
			{
				if (!staminaMemoryInitialized)
				{
					NativeSpiritStaminaMemory.Restore("eikthyr", saddle);
					staminaMemoryInitialized = true;
				}
				NativeSpiritStaminaMemory.Capture("eikthyr", saddle);
			}
		}

		private void CaptureStaminaMemory()
		{
			if (staminaMemoryInitialized && (Object)(object)saddle != (Object)null && (Object)(object)owner != (Object)null && (Object)(object)owner == (Object)(object)Player.m_localPlayer && (Object)(object)networkView != (Object)null && networkView.IsValid() && networkView.IsOwner())
			{
				NativeSpiritStaminaMemory.Capture("eikthyr", saddle);
			}
		}
	}
	public static class NativeEikthyrPrefab
	{
		public const string PrefabName = "FalseMods_BossSpirits_Eikthyr";

		private const string SourcePrefabName = "Eikthyr";

		private const string LoxPrefabName = "Lox";

		private const string AsksvinPrefabName = "Asksvin";

		private const string EikthyrTrophyPrefabName = "TrophyEikthyr";

		private const float SpiritStaminaRegenBonus = 1.5f;

		private const float SpiritRunStaminaDrainMultiplier = 3.5f;

		private static readonly Vector3 RiderAttachLocalPosition = new Vector3(0f, 2.43f, 0.54f);

		private static bool initialized;

		private static bool registered;

		private static Sprite cachedEikthyrMountIcon;

		private static bool mountIconWarningLogged;

		public static void Initialize()
		{
			if (!initialized)
			{
				initialized = true;
				CreatureManager.OnVanillaCreaturesAvailable += RegisterFromVanillaPrefabs;
			}
		}

		public static void Shutdown()
		{
			CreatureManager.OnVanillaCreaturesAvailable -= RegisterFromVanillaPrefabs;
			initialized = false;
		}

		public static bool IsNativeDefinition(SpiritDefinition definition)
		{
			if (definition != null)
			{
				return string.Equals(definition.Id, "eikthyr", StringComparison.OrdinalIgnoreCase);
			}
			return false;
		}

		public static GameObject CreateInstance(SpiritDefinition definition, Vector3 position, Quaternion rotation, Player owner)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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)
			if (!registered || (Object)(object)ZNetScene.instance == (Object)null)
			{
				Debug.LogError((object)"Boss Spirits: Native Eikthyr prefab is not registered.");
				return null;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab("FalseMods_BossSpirits_Eikthyr");
			if ((Object)(object)prefab == (Object)null)
			{
				Debug.LogError((object)"Boss Spirits: Registered native Eikthyr prefab was not found.");
				return null;
			}
			GameObject val = new GameObject("Boss Spirits Native Spawn Staging");
			val.transform.position = position;
			val.transform.rotation = rotation;
			val.SetActive(false);
			GameObject val2 = Object.Instantiate<GameObject>(prefab, val.transform);
			val2.transform.localPosition = Vector3.zero;
			val2.transform.localRotation = Quaternion.identity;
			NativeEikthyrController component = val2.GetComponent<NativeEikthyrController>();
			if ((Object)(object)component == (Object)null)
			{
				Debug.LogError((object)"Boss Spirits: Native Eikthyr controller is missing.");
				Object.Destroy((Object)(object)val2);
				Object.Destroy((Object)(object)val);
				return null;
			}
			component.InitializeOwner(owner);
			val2.transform.SetParent((Transform)null, true);
			((Object)val2).name = definition.DisplayName;
			Object.Destroy((Object)(object)val);
			if (!CorrectNetworkPrefabIdentity(val2))
			{
				DestroyInstance(val2);
				return null;
			}
			return val2;
		}

		private static bool CorrectNetworkPrefabIdentity(GameObject instance)
		{
			ZNetView component = instance.GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || component.GetZDO() == null)
			{
				Debug.LogError((object)"Boss Spirits: Native Eikthyr did not create a valid network record after activation.");
				return false;
			}
			int stableHashCode = StringExtensionMethods.GetStableHashCode("FalseMods_BossSpirits_Eikthyr");
			if ((Object)(object)ZNetScene.instance.GetPrefab(stableHashCode) == (Object)null)
			{
				Debug.LogError((object)"Boss Spirits: The custom Eikthyr prefab is not registered in ZNetScene under its network hash.");
				return false;
			}
			ZDO zDO = component.GetZDO();
			if (zDO.GetPrefab() != stableHashCode)
			{
				zDO.SetPrefab(stableHashCode);
				Debug.Log((object)"Boss Spirits: Corrected native Eikthyr network prefab identity.");
			}
			return true;
		}

		public static void DestroyInstance(GameObject instance)
		{
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			ZNetView component = instance.GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid())
			{
				if (!component.IsOwner())
				{
					component.ClaimOwnership();
				}
				component.Destroy();
			}
			else
			{
				Object.Destroy((Object)(object)instance);
			}
		}

		private static void RegisterFromVanillaPrefabs()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			if (registered)
			{
				return;
			}
			try
			{
				GameObject creaturePrefab = CreatureManager.Instance.GetCreaturePrefab("Lox");
				GameObject creaturePrefab2 = CreatureManager.Instance.GetCreaturePrefab("Asksvin");
				if ((Object)(object)creaturePrefab == (Object)null || (Object)(object)creaturePrefab2 == (Object)null)
				{
					Debug.LogError((object)"Boss Spirits: Lox or Asksvin prefab was not available for native mount data.");
					return;
				}
				CreatureConfig val = new CreatureConfig();
				CustomCreature val2 = new CustomCreature("FalseMods_BossSpirits_Eikthyr", "Eikthyr", val);
				ConfigureCreaturePrefab(val2.Prefab, creaturePrefab, creaturePrefab2);
				CreatureManager.Instance.AddCreature(val2);
				registered = true;
				CreatureManager.OnVanillaCreaturesAvailable -= RegisterFromVanillaPrefabs;
				Debug.Log((object)"Boss Spirits: Native Eikthyr mount prefab registered.");
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("Boss Spirits: Native Eikthyr registration failed.\n" + ex));
			}
		}

		private static void ConfigureCreaturePrefab(GameObject prefab, GameObject loxPrefab, GameObject asksvinPrefab)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				throw new InvalidOperationException("Jotunn returned a null Eikthyr clone.");
			}
			prefab.SetActive(false);
			Humanoid component = prefab.GetComponent<Humanoid>();
			MonsterAI component2 = prefab.GetComponent<MonsterAI>();
			Humanoid component3 = loxPrefab.GetComponent<Humanoid>();
			Sadle componentInChildren = loxPrefab.GetComponentInChildren<Sadle>(true);
			Humanoid component4 = asksvinPrefab.GetComponent<Humanoid>();
			Sadle componentInChildren2 = asksvinPrefab.GetComponentInChildren<Sadle>(true);
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || (Object)(object)component3 == (Object)null || (Object)(object)componentInChildren == (Object)null || (Object)(object)component4 == (Object)null || (Object)(object)componentInChildren2 == (Object)null)
			{
				throw new InvalidOperationException("Required Eikthyr, Lox or Asksvin native components were missing.");
			}
			ConfigureCharacter(component, component3);
			ConfigureNativeMountCollider(component, component4);
			ConfigureNetworkLifetime(prefab);
			ConfigurePhysicsSmoothing(prefab);
			ConfigureMonsterAI(component2);
			RemoveCombatEquipment(component);
			RemoveBossDrops(prefab);
			RemoveAttachedParticles(prefab);
			RemoveFootstepVisualEffects(prefab);
			Tameable val = prefab.GetComponent<Tameable>();
			if ((Object)(object)val == (Object)null)
			{
				val = prefab.AddComponent<Tameable>();
			}
			Sadle saddle = CreateNativeSaddle(prefab, componentInChildren, componentInChildren2);
			val.m_startsTamed = true;
			val.m_commandable = false;
			val.m_saddleItem = null;
			val.m_saddle = saddle;
			val.m_dropSaddleOnDeath = false;
			val.m_randomStartingName = new List<string>();
			if ((Object)(object)prefab.GetComponent<NativeEikthyrController>() == (Object)null)
			{
				prefab.AddComponent<NativeEikthyrController>();
			}
			prefab.SetActive(true);
		}

		private static void ConfigureCharacter(Humanoid eikthyr, Humanoid lox)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			((Character)eikthyr).m_name = "Eikthyr Spirit";
			((Character)eikthyr).m_group = "BossSpirits";
			((Character)eikthyr).m_faction = (Faction)11;
			((Character)eikthyr).m_boss = false;
			((Character)eikthyr).m_dontHideBossHud = false;
			((Character)eikthyr).m_bossEvent = string.Empty;
			((Character)eikthyr).m_defeatSetGlobalKey = string.Empty;
			((Character)eikthyr).m_aiSkipTarget = true;
			((Character)eikthyr).m_walkSpeed = ((Character)lox).m_walkSpeed * 1.65f;
			((Character)eikthyr).m_speed = ((Character)lox).m_speed * 1.85f;
			((Character)eikthyr).m_runSpeed = ((Character)lox).m_runSpeed * 2.1f;
			((Character)eikthyr).m_turnSpeed = ((Character)lox).m_turnSpeed * 1.35f;
			((Character)eikthyr).m_runTurnSpeed = ((Character)lox).m_runTurnSpeed * 1.3f;
			((Character)eikthyr).m_acceleration = ((Character)lox).m_acceleration * 1.75f;
			((Character)eikthyr).m_airControl = ((Character)lox).m_airControl;
			((Character)eikthyr).m_groundTilt = ((Character)lox).m_groundTilt;
			((Character)eikthyr).m_groundTiltSpeed = ((Character)lox).m_groundTiltSpeed * 0.25f;
			((Character)eikthyr).m_canSwim = ((Character)lox).m_canSwim;
			((Character)eikthyr).m_swimDepth = ((Character)lox).m_swimDepth;
			((Character)eikthyr).m_swimSpeed = ((Character)lox).m_swimSpeed;
			((Character)eikthyr).m_swimTurnSpeed = ((Character)lox).m_swimTurnSpeed;
			((Character)eikthyr).m_swimAcceleration = ((Character)lox).m_swimAcceleration;
			((Character)eikthyr).m_jumpForce = 9.6f;
			((Character)eikthyr).m_jumpForceForward = 2.4f;
			((Character)eikthyr).m_jumpStaminaUsage = 0f;
		}

		private static void ConfigurePhysicsSmoothing(GameObject prefab)
		{
			Rigidbody component = prefab.GetComponent<Rigidbody>();
			if ((Object)(object)component == (Object)null)
			{
				throw new InvalidOperationException("Eikthyr's native Rigidbody was missing.");
			}
			component.interpolation = (RigidbodyInterpolation)1;
		}

		private static void ConfigureNativeMountCollider(Humanoid eikthyr, Humanoid asksvin)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			CapsuleCollider component = ((Component)eikthyr).GetComponent<CapsuleCollider>();
			CapsuleCollider component2 = ((Component)asksvin).GetComponent<CapsuleCollider>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null)
			{
				throw new InvalidOperationException("Eikthyr or Asksvin's native Character capsule was missing.");
			}
			component.center = component2.center;
			component.radius = component2.radius;
			component.height = component2.height;
			component.direction = component2.direction;
			((Collider)component).isTrigger = ((Collider)component2).isTrigger;
			((Collider)component).sharedMaterial = ((Collider)component2).sharedMaterial;
			((Collider)component).contactOffset = ((Collider)component2).contactOffset;
			Debug.Log((object)"Boss Spirits: Eikthyr is using the native Asksvin mount collider.");
		}

		private static void ConfigureNetworkLifetime(GameObject prefab)
		{
			ZNetView component = prefab.GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null)
			{
				throw new InvalidOperationException("Eikthyr's native ZNetView was missing.");
			}
			component.m_persistent = false;
			component.m_distant = false;
		}

		private static void ConfigureMonsterAI(MonsterAI monsterAI)
		{
			monsterAI.m_enableHuntPlayer = false;
			monsterAI.m_attackPlayerObjects = false;
			monsterAI.m_sleeping = false;
			monsterAI.m_consumeItems = new List<ItemDrop>();
		}

		private static void RemoveCombatEquipment(Humanoid humanoid)
		{
			humanoid.m_defaultItems = (GameObject[])(object)new GameObject[0];
			humanoid.m_randomWeapon = (GameObject[])(object)new GameObject[0];
			humanoi