Decompiled source of Vikings Summoner v1.5.4

plugins/Vikings_Summoner.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using AzuEPI;
using AzuEPI.Core.Slots;
using AzuExtendedPlayerInventory;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using ItemManager;
using JetBrains.Annotations;
using LocalizationManager;
using Microsoft.CodeAnalysis;
using PieceManager;
using ServerSync;
using Splatform;
using StatusEffectManager;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.UI;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.ObjectPool;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Callbacks;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;

[assembly: Guid("E74EB49A-461D-48EA-85BC-F462D60C98C4")]
[assembly: ComVisible(false)]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyProduct("Vikings_Summoner")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyTitle("Vikings_Summoner")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyFileVersion("1.5.4")]
[assembly: AssemblyCompany("Radamanto")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.5.4.0")]
[module: <76ce5410-1e4b-4240-9388-48f365cfcc51>RefSafetyRules(11)]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[<b257b4c3-0174-4864-a251-b2d9a00c45cf>Embedded]
	internal sealed class <b257b4c3-0174-4864-a251-b2d9a00c45cf>EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[<b257b4c3-0174-4864-a251-b2d9a00c45cf>Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class <75331dbc-839c-437d-a413-c63e0024209e>NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public <75331dbc-839c-437d-a413-c63e0024209e>NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public <75331dbc-839c-437d-a413-c63e0024209e>NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[<b257b4c3-0174-4864-a251-b2d9a00c45cf>Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class <8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public <8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[<b257b4c3-0174-4864-a251-b2d9a00c45cf>Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class <76ce5410-1e4b-4240-9388-48f365cfcc51>RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public <76ce5410-1e4b-4240-9388-48f365cfcc51>RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Vikings_Summoner
{
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	internal static class AzuUtilityExclusivityCompat
	{
		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(0)]
		[HarmonyPatch(typeof(Humanoid), "UnequipItem")]
		private static class Patch_Humanoid_UnequipItem_Guard
		{
			[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
			[HarmonyPriority(int.MaxValue)]
			private static bool Prefix(Humanoid __instance, ItemData item)
			{
				if (KeptItems.Count == 0 || !(__instance is Player) || item == null)
				{
					return true;
				}
				bool flag = SummonerTomeSlot.IsTomeItem(item);
				bool flag2 = SummonerTomeSlot.IsTomeItem(KeptItems.Peek());
				return !flag && !flag2;
			}
		}

		private const string ExclusivityTypeName = "AzuEPI.Game.Slots.UtilityExclusivity";

		private const string EnforceMethodName = "Enforce";

		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(new byte[] { 1, 2 })]
		private static readonly Stack<ItemData> KeptItems = new Stack<ItemData>();

		internal static void Apply(Harmony harmony, ManualLogSource log)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Expected O, but got Unknown
			//IL_00b2: Expected O, but got Unknown
			Type type = AccessTools.TypeByName("AzuEPI.Game.Slots.UtilityExclusivity");
			if (type == null)
			{
				return;
			}
			List<MethodInfo> list = (from m in AccessTools.GetDeclaredMethods(type)
				where m.Name == "Enforce"
				select m).ToList();
			if (list.Count == 0)
			{
				log.LogWarning((object)"[AzuCompat] AzuEPI.Game.Slots.UtilityExclusivity.Enforce not found; grimoires may compete with utility items.");
				return;
			}
			foreach (MethodInfo item in list)
			{
				harmony.Patch((MethodBase)item, new HarmonyMethod(typeof(AzuUtilityExclusivityCompat), "Enforce_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(AzuUtilityExclusivityCompat), "Enforce_Finalizer", (Type[])null), (HarmonyMethod)null);
			}
		}

		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(2)]
		private static void Enforce_Prefix(ItemData keep)
		{
			KeptItems.Push(keep);
		}

		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(2)]
		private static Exception Enforce_Finalizer(Exception __exception)
		{
			if (KeptItems.Count > 0)
			{
				KeptItems.Pop();
			}
			return __exception;
		}
	}
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	internal static class SummonerCllc
	{
		private const string ZdoEffectKey = "CL&LC effect";

		private const string ZdoInfusionKey = "CL&LC infusion";

		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(2)]
		internal static void TryStrip(Character ch)
		{
			if ((Object)(object)ch == (Object)null)
			{
				return;
			}
			ZNetView component = ((Component)ch).GetComponent<ZNetView>();
			if (Object.op_Implicit((Object)(object)component) && component.IsValid())
			{
				ZDO zDO = component.GetZDO();
				if (zDO != null)
				{
					zDO.Set("CL&LC effect", 0);
					zDO.Set("CL&LC infusion", 0);
				}
			}
		}
	}
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(2)]
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	public sealed class SummonerDeathCleanup : MonoBehaviour
	{
		private ZNetView _nview;

		private Character _character;

		private float _deadDelay = 0.2f;

		private bool _destroyQueued;

		private void Awake()
		{
			_nview = ((Component)this).GetComponent<ZNetView>();
			_character = ((Component)this).GetComponent<Character>();
		}

		private void Update()
		{
			if (_destroyQueued || (Object)(object)_character == (Object)null || !_character.IsDead() || (Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.IsOwner())
			{
				return;
			}
			_deadDelay -= Time.deltaTime;
			if (!(_deadDelay > 0f) && _character.IsDead())
			{
				_destroyQueued = true;
				if ((Object)(object)ZNetScene.instance != (Object)null)
				{
					ZNetScene.instance.Destroy(((Component)this).gameObject);
				}
				else
				{
					_nview.Destroy();
				}
				((Behaviour)this).enabled = false;
			}
		}
	}
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	[HarmonyPatch(typeof(EnemyHud), "UpdateHuds")]
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
	[HarmonyPriority(0)]
	internal static class EnemyHud_UpdateHuds_SummonIcons_Patch
	{
		private const string CombatSpriteName = "ico_summon_combat";

		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)]
		private static Sprite _combatSprite;

		private static void Postfix(EnemyHud __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return;
			}
			Dictionary<Character, HudData> huds = __instance.m_huds;
			if (huds == null || huds.Count == 0 || SummonerMarker.Active.Count == 0)
			{
				return;
			}
			EnsureSprites();
			foreach (KeyValuePair<Character, HudData> item in huds)
			{
				UpdateSummonHud(item.Value);
			}
		}

		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(2)]
		private static void UpdateSummonHud(HudData hudData)
		{
			if (hudData == null)
			{
				return;
			}
			Character character = hudData.m_character;
			if ((Object)(object)character == (Object)null || !SummonerMarker.TryGet((Component)(object)character, out var marker))
			{
				return;
			}
			RectTransform alerted = hudData.m_alerted;
			RectTransform aware = hudData.m_aware;
			if (!((Object)(object)alerted == (Object)null) && !((Object)(object)aware == (Object)null))
			{
				SetVisible(alerted, visible: false);
				if (!HasRealCombatTarget(character, marker.AI))
				{
					SetVisible(aware, visible: false);
					return;
				}
				ApplySprite(aware, _combatSprite);
				SetVisible(aware, (Object)(object)_combatSprite != (Object)null);
			}
		}

		private static bool HasRealCombatTarget(Character character, [<75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)] MonsterAI monsterAI)
		{
			if ((Object)(object)monsterAI == (Object)null)
			{
				return false;
			}
			Character targetCreature = monsterAI.m_targetCreature;
			if ((Object)(object)targetCreature != (Object)null && !targetCreature.IsDead() && BaseAI.IsEnemy(character, targetCreature))
			{
				return true;
			}
			StaticTarget targetStatic = monsterAI.m_targetStatic;
			return (Object)(object)targetStatic != (Object)null;
		}

		private static void EnsureSprites()
		{
			if (_combatSprite == null)
			{
				_combatSprite = SummonerAssetLoader.GetSprite("ico_summon_combat");
			}
		}

		private static void ApplySprite(RectTransform rect, [<75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)] Sprite sprite)
		{
			if (!((Object)(object)sprite == (Object)null))
			{
				Image val = ((Component)rect).GetComponent<Image>();
				if ((Object)(object)val == (Object)null)
				{
					val = ((Component)rect).GetComponentInChildren<Image>(true);
				}
				if (!((Object)(object)val == (Object)null) && (Object)(object)val.sprite != (Object)(object)sprite)
				{
					val.sprite = sprite;
				}
			}
		}

		private static void SetVisible(RectTransform rect, bool visible)
		{
			if (((Component)rect).gameObject.activeSelf != visible)
			{
				((Component)rect).gameObject.SetActive(visible);
			}
		}
	}
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
	[HarmonyPatch(typeof(MonsterAI), "UpdateAI")]
	internal static class MonsterAI_UpdateAI_OwnerFollow_Patch
	{
		private const float MinMoveSqrMagnitude = 0.0001f;

		internal static float GroundStopDistance = 6f;

		internal static float FlyingStopDistanceHorizontal = 10f;

		internal static float FlyingFollowHeightOffset = 2.5f;

		internal static float FlyingVerticalTolerance = 1.5f;

		internal static float FlyingVerticalDeadzone = 0.75f;

		private static void Postfix(MonsterAI __instance, float dt, bool __result)
		{
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			if (!__result || !SummonerMarker.TryGet((Component)(object)__instance, out var marker))
			{
				return;
			}
			ZNetView nView = marker.NView;
			if ((Object)(object)nView == (Object)null || !nView.IsValid() || !nView.IsOwner())
			{
				return;
			}
			Player val = marker.ResolveOwnerPlayer();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Character creature = marker.Creature;
			if ((Object)(object)creature == (Object)null)
			{
				return;
			}
			Character targetCreature = ((BaseAI)__instance).GetTargetCreature();
			StaticTarget staticTarget = __instance.GetStaticTarget();
			if (!((Object)(object)staticTarget != (Object)null) && (!((Object)(object)targetCreature != (Object)null) || targetCreature.IsDead() || !((BaseAI)__instance).IsEnemy(targetCreature)))
			{
				Vector3 position = ((Component)val).transform.position;
				Vector3 position2 = ((Component)__instance).transform.position;
				if (!creature.m_flying)
				{
					MoveGround(__instance, position, position2);
				}
				else
				{
					MoveFlying(__instance, position, position2);
				}
			}
		}

		private static void MoveGround(MonsterAI ai, Vector3 ownerPos, Vector3 summonPos)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(ownerPos.x - summonPos.x, 0f, ownerPos.z - summonPos.z);
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude < GroundStopDistance)
			{
				((BaseAI)ai).StopMoving();
			}
			else if (((Vector3)(ref val)).sqrMagnitude <= 0.0001f)
			{
				((BaseAI)ai).StopMoving();
			}
			else
			{
				((BaseAI)ai).MoveTowards(((Vector3)(ref val)).normalized, true);
			}
		}

		private static void MoveFlying(MonsterAI ai, Vector3 ownerPos, Vector3 summonPos)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0016: 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_0019: 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_0021: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ownerPos + Vector3.up * FlyingFollowHeightOffset;
			Vector3 val2 = val - summonPos;
			Vector3 val3 = default(Vector3);
			((Vector3)(ref val3))..ctor(val2.x, 0f, val2.z);
			float magnitude = ((Vector3)(ref val3)).magnitude;
			float num = Mathf.Abs(val2.y);
			bool flag = magnitude < FlyingStopDistanceHorizontal;
			bool flag2 = num <= FlyingVerticalTolerance;
			if (flag && flag2)
			{
				((BaseAI)ai).StopMoving();
				return;
			}
			if (num <= FlyingVerticalDeadzone)
			{
				val2.y = 0f;
			}
			if (((Vector3)(ref val2)).sqrMagnitude <= 0.0001f)
			{
				((BaseAI)ai).StopMoving();
			}
			else
			{
				((BaseAI)ai).MoveTowards(((Vector3)(ref val2)).normalized, true);
			}
		}
	}
	internal static class SummonerHp
	{
		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
		internal static float CalculateFinalHp(SummonerRegistry.SummonDef def, int level)
		{
			float num = Mathf.Max(1f, def.BaseHpCE.Value);
			float num2 = Mathf.Max(0f, def.HpPercentPerStarCE.Value);
			int num3 = Mathf.Max(0, level - 1);
			return Mathf.Max(1f, num * (1f + (float)num3 * (num2 / 100f)));
		}
	}
	[HarmonyPatch(typeof(Character), "SetupMaxHealth")]
	internal static class Character_SetupMaxHealth_SummonHp_Patch
	{
		private readonly struct State
		{
			internal readonly float OldMaxHealth;

			internal readonly float OldHealth;

			internal State(float oldMaxHealth, float oldHealth)
			{
				OldMaxHealth = oldMaxHealth;
				OldHealth = oldHealth;
			}
		}

		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
		private static void Prefix(Character __instance, out State __state)
		{
			__state = (((Object)(object)__instance == (Object)null) ? default(State) : new State(__instance.GetMaxHealth(), __instance.GetHealth()));
		}

		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
		private static void Postfix(Character __instance, State __state)
		{
			SummonerMarker summonerMarker = default(SummonerMarker);
			if (!((Object)(object)__instance == (Object)null) && ((Component)__instance).TryGetComponent<SummonerMarker>(ref summonerMarker))
			{
				string prefabName = Utils.GetPrefabName(((Component)__instance).gameObject);
				if (SummonerRegistry.TryGet(prefabName, out var def) && def != null)
				{
					int level = Mathf.Max(1, __instance.GetLevel());
					float num = SummonerHp.CalculateFinalHp(def, level);
					float num2 = Mathf.Max(1f, __state.OldMaxHealth);
					float num3 = Mathf.Max(0f, __state.OldHealth);
					bool flag = num3 >= num2 - 0.01f;
					float num4 = Mathf.Clamp01(num3 / num2);
					__instance.SetMaxHealth(num);
					__instance.SetHealth(flag ? num : Mathf.Clamp(num * num4, 0f, num));
				}
			}
		}
	}
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
	public sealed class SummonerInteract : MonoBehaviour, Interactable
	{
		private const string RpcUnsummon = "VS_RPC_Unsummon";

		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)]
		private ZNetView _nview;

		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)]
		private SummonerMarker _marker;

		private float _unsummonCd;

		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)]
		private string _lastHover;

		private float _hoverTTL;

		private void Awake()
		{
			_nview = ((Component)this).GetComponent<ZNetView>();
			_marker = ((Component)this).GetComponent<SummonerMarker>();
			if ((Object)(object)_nview != (Object)null)
			{
				_nview.Register("VS_RPC_Unsummon", (Action<long>)RPC_Unsummon);
			}
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			if (hold)
			{
				return false;
			}
			if (Time.time < _unsummonCd)
			{
				return false;
			}
			Player val = (Player)(object)((user is Player) ? user : null);
			if (val == null)
			{
				return false;
			}
			if (!CanUnsummon(val) && !((Character)val).IsDebugFlying())
			{
				return false;
			}
			if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
			{
				return false;
			}
			_unsummonCd = Time.time + 0.5f;
			if (_nview.IsOwner())
			{
				Unsummon();
			}
			else
			{
				_nview.InvokeRPC("VS_RPC_Unsummon", Array.Empty<object>());
			}
			return true;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}

		public string GetHoverText()
		{
			_hoverTTL -= Time.deltaTime;
			if (_hoverTTL > 0f && !string.IsNullOrEmpty(_lastHover))
			{
				return _lastHover;
			}
			string hoverName = GetHoverName();
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return hoverName;
			}
			if (!CanUnsummon(localPlayer) && !((Character)localPlayer).IsDebugFlying())
			{
				_lastHover = hoverName;
				_hoverTTL = 0.2f;
				return hoverName;
			}
			string text = Localization.instance.Localize("$KEY_Use");
			string text2 = Localization.instance.Localize("$vs_summon_unsummon");
			string result = (_lastHover = hoverName + "\n[<color=yellow><b>" + text + "</b></color>] " + text2);
			_hoverTTL = 0.35f;
			return result;
		}

		public string GetHoverName()
		{
			if ((Object)(object)_marker == (Object)null)
			{
				_marker = ((Component)this).GetComponent<SummonerMarker>();
			}
			return ((Object)(object)_marker != (Object)null) ? _marker.GetHoverName() : Localization.instance.Localize(((Object)((Component)this).gameObject).name);
		}

		private void RPC_Unsummon(long sender)
		{
			if (!((Object)(object)_nview == (Object)null) && _nview.IsValid())
			{
				ZDO zDO = _nview.GetZDO();
				if (zDO != null && SummonerOwnerIdentity.IsSenderOwnerOrDebugFlying(sender, zDO))
				{
					Unsummon();
				}
			}
		}

		private void Unsummon()
		{
			SummonerRemoval.TryRemove(((Component)this).gameObject, SummonerRemovalReason.Manual);
		}

		private bool CanUnsummon(Player p)
		{
			if ((Object)(object)p == (Object)null)
			{
				return false;
			}
			if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
			{
				return false;
			}
			ZDO zDO = _nview.GetZDO();
			if (zDO == null)
			{
				return false;
			}
			if (!SummonerOwnerIdentity.TryGetOwnerIdentity(p, out var platformId, out var playerId))
			{
				return false;
			}
			return SummonerOwnerIdentity.IsSameOwner(zDO, platformId, playerId);
		}
	}
	internal static class SummonerTime
	{
		internal static DateTime Now()
		{
			return ((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTime() : DateTime.UtcNow;
		}

		internal static long NowTicks()
		{
			return Now().Ticks;
		}
	}
	[HarmonyPatch(typeof(ZNet), "Awake")]
	internal static class ZNet_Awake_LifetimeServerCleanup_Patch
	{
		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
		private static void Postfix(ZNet __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<SummonerExpiredCleanup>()))
			{
				((Component)__instance).gameObject.AddComponent<SummonerExpiredCleanup>();
			}
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	internal static class ZNetScene_Awake_LifetimePrefabSetup_Patch
	{
		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
		private static void Postfix(ZNetScene __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return;
			}
			foreach (SummonerRegistry.SummonDef value in SummonerRegistry.All.Values)
			{
				if (value != null && !string.IsNullOrWhiteSpace(value.Prefab))
				{
					GameObject prefab = __instance.GetPrefab(value.Prefab);
					if (Object.op_Implicit((Object)(object)prefab))
					{
						SummonerLifetime.EnsurePrefab(prefab);
					}
				}
			}
		}
	}
	public sealed class SummonerExpiredCleanup : MonoBehaviour
	{
		private const float ScanInterval = 10f;

		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(1)]
		private readonly List<ZDO> _summons = new List<ZDO>();

		private float _tick;

		private void Update()
		{
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				((Behaviour)this).enabled = false;
				return;
			}
			_tick -= Time.deltaTime;
			if (!(_tick > 0f))
			{
				_tick = 10f;
				CleanupExpiredSummons();
			}
		}

		private void CleanupExpiredSummons()
		{
			SummonerZdoScan.Collect(_summons);
			for (int i = 0; i < _summons.Count; i++)
			{
				ZDO val = _summons[i];
				if (!val.GetBool("vs_summon_removing", false) && SummonerLifetime.IsExpiredOrMarked(val))
				{
					SummonerLifetime.TryRemoveExpired(val);
				}
			}
			_summons.Clear();
		}
	}
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	public sealed class SummonerLifetime : MonoBehaviour
	{
		internal const string ZdoStartTicks = "vs_decayStartTicks";

		internal const string ZdoLifetimeSec = "vs_decayLifetimeSec";

		internal const string ZdoExpired = "vs_decayExpired";

		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)]
		private Character _character;

		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)]
		private ZNetView _nview;

		private bool _stripped;

		private bool _loaded;

		private bool _removing;

		private float _tick;

		private void Awake()
		{
			_character = ((Component)this).GetComponent<Character>();
			_nview = ((Component)this).GetComponent<ZNetView>();
			StripAffixesOnce();
			((MonoBehaviour)this).StartCoroutine(DelayedLoad());
		}

		private void Update()
		{
			if (_loaded && !_removing && !((Object)(object)_character == (Object)null) && !_character.IsDead() && !((Object)(object)_nview == (Object)null) && _nview.IsValid())
			{
				_tick -= Time.deltaTime;
				if (!(_tick > 0f))
				{
					_tick = GetTickInterval();
					ApplyDecay();
				}
			}
		}

		internal static void EnsurePrefab(GameObject prefab)
		{
			if (Object.op_Implicit((Object)(object)prefab))
			{
				CharacterTimedDestruction component = prefab.GetComponent<CharacterTimedDestruction>();
				if ((Object)(object)component != (Object)null)
				{
					component.m_triggerOnAwake = false;
					((MonoBehaviour)component).CancelInvoke();
				}
				if (!Object.op_Implicit((Object)(object)prefab.GetComponent<SummonerLifetime>()))
				{
					prefab.AddComponent<SummonerLifetime>();
				}
			}
		}

		internal static void Apply(GameObject go, float seconds)
		{
			if (Object.op_Implicit((Object)(object)go))
			{
				seconds = Mathf.Max(seconds, 0.01f);
				CharacterTimedDestruction component = go.GetComponent<CharacterTimedDestruction>();
				if ((Object)(object)component != (Object)null)
				{
					component.m_triggerOnAwake = false;
					((MonoBehaviour)component).CancelInvoke();
				}
				SummonerLifetime summonerLifetime = go.GetComponent<SummonerLifetime>() ?? go.AddComponent<SummonerLifetime>();
				summonerLifetime._character = go.GetComponent<Character>();
				summonerLifetime._nview = go.GetComponent<ZNetView>();
				summonerLifetime._loaded = true;
				summonerLifetime._removing = false;
				summonerLifetime._tick = GetTickInterval();
				summonerLifetime.WriteState(seconds);
				summonerLifetime.StripAffixesOnce();
				summonerLifetime.ApplyDecay();
			}
		}

		internal static bool IsExpiredOrMarked(ZDO zdo)
		{
			if (zdo.GetBool("vs_decayExpired", false))
			{
				return true;
			}
			long num = zdo.GetLong("vs_decayStartTicks", 0L);
			float num2 = zdo.GetFloat("vs_decayLifetimeSec", 0f);
			return num > 0 && num2 > 0f && GetElapsedSeconds(num) >= num2;
		}

		internal static bool TryRemoveExpired(GameObject go)
		{
			if (!Object.op_Implicit((Object)(object)go))
			{
				return false;
			}
			SummonerLifetime component = go.GetComponent<SummonerLifetime>();
			if ((Object)(object)component != (Object)null)
			{
				return component.RemoveExpired();
			}
			MarkExpired(go);
			return SummonerRemoval.TryRemove(go, SummonerRemovalReason.LifetimeExpired);
		}

		internal static bool TryRemoveExpired(ZDO zdo)
		{
			if (zdo == null)
			{
				return false;
			}
			ZNetView val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.FindInstance(zdo) : null);
			if ((Object)(object)val != (Object)null && val.IsValid())
			{
				return TryRemoveExpired(((Component)val).gameObject);
			}
			return SummonerRemoval.TryRemoveZdo(zdo, SummonerRemovalReason.LifetimeExpired);
		}

		private IEnumerator DelayedLoad()
		{
			float timeout = 2f;
			while (timeout > 0f)
			{
				if ((Object)(object)_character == (Object)null)
				{
					_character = ((Component)this).GetComponent<Character>();
				}
				if ((Object)(object)_nview == (Object)null)
				{
					_nview = ((Component)this).GetComponent<ZNetView>();
				}
				if ((Object)(object)_character != (Object)null && (Object)(object)_nview != (Object)null && _nview.IsValid())
				{
					break;
				}
				timeout -= Time.deltaTime;
				yield return null;
			}
			if (!((Object)(object)_character == (Object)null) && !((Object)(object)_nview == (Object)null) && _nview.IsValid())
			{
				_loaded = true;
				_tick = 0f;
				ApplyDecay();
			}
		}

		private void WriteState(float seconds)
		{
			if (!((Object)(object)_nview == (Object)null) && _nview.IsValid())
			{
				ZDO zDO = _nview.GetZDO();
				if (zDO != null)
				{
					zDO.Set("vs_decayStartTicks", SummonerTime.NowTicks());
					zDO.Set("vs_decayLifetimeSec", Mathf.Max(seconds, 0.01f));
					zDO.Set("vs_decayExpired", false);
				}
			}
		}

		private void ApplyDecay()
		{
			if (_removing || (Object)(object)_character == (Object)null || (Object)(object)_nview == (Object)null || !_nview.IsValid())
			{
				return;
			}
			ZDO zDO = _nview.GetZDO();
			if (zDO == null)
			{
				return;
			}
			if (zDO.GetBool("vs_decayExpired", false))
			{
				RemoveExpired();
				return;
			}
			long num = zDO.GetLong("vs_decayStartTicks", 0L);
			float num2 = zDO.GetFloat("vs_decayLifetimeSec", 0f);
			if (num <= 0 || num2 <= 0f)
			{
				return;
			}
			float num3 = GetElapsedSeconds(num);
			if (num3 < 0f)
			{
				num3 = 0f;
			}
			if (num3 >= num2)
			{
				RemoveExpired();
			}
			else
			{
				if (!EnsureOwner())
				{
					return;
				}
				float fullHealthTimePercent = GetFullHealthTimePercent();
				float num4 = num2 * Mathf.Clamp(fullHealthTimePercent, 0f, 100f) / 100f;
				if (!(num3 <= num4))
				{
					float num5 = Mathf.Max(num2 - num4, 0.01f);
					float num6 = num3 - num4;
					float num7 = Mathf.Clamp01(1f - num6 / num5);
					float maxHealth = _character.GetMaxHealth();
					float health = _character.GetHealth();
					float num8 = Mathf.Max(maxHealth * num7, 0.01f);
					if (!(health <= num8 + 0.1f))
					{
						Damage(health - num8);
					}
				}
			}
		}

		private bool EnsureOwner()
		{
			if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
			{
				return false;
			}
			if (_nview.IsOwner())
			{
				return true;
			}
			if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
			{
				_nview.ClaimOwnership();
			}
			return _nview.IsOwner();
		}

		private void Damage(float damage)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_003d: 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)
			if (!((Object)(object)_character == (Object)null) && !(damage <= 0f))
			{
				HitData val = new HitData();
				val.m_damage.m_damage = damage;
				val.m_point = ((Component)this).transform.position;
				_character.ApplyDamage(val, false, true, (DamageModifier)0);
			}
		}

		private bool RemoveExpired()
		{
			if (_removing)
			{
				return true;
			}
			MarkExpired();
			if (!SummonerRemoval.TryRemove(((Component)this).gameObject, SummonerRemovalReason.LifetimeExpired))
			{
				return false;
			}
			_removing = true;
			((Behaviour)this).enabled = false;
			return true;
		}

		private void MarkExpired()
		{
			MarkExpired(((Component)this).gameObject);
		}

		private static void MarkExpired(GameObject go)
		{
			if (SummonerLookup.TryGetZdo(go, out var nview, out var zdo) && !((Object)(object)nview == (Object)null) && zdo != null)
			{
				if (!nview.IsOwner() && (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
				{
					nview.ClaimOwnership();
				}
				if (nview.IsOwner())
				{
					zdo.Set("vs_decayExpired", true);
				}
			}
		}

		private static float GetElapsedSeconds(long startTicks)
		{
			long num = SummonerTime.NowTicks() - startTicks;
			if (num <= 0)
			{
				return 0f;
			}
			double totalSeconds = new TimeSpan(num).TotalSeconds;
			return (totalSeconds > 0.0) ? ((float)totalSeconds) : 0f;
		}

		private static float GetFullHealthTimePercent()
		{
			if (Vikings_SummonerPlugin.CE_SummonDecayFullHealthTimePercent == null)
			{
				return 80f;
			}
			return Mathf.Clamp(Vikings_SummonerPlugin.CE_SummonDecayFullHealthTimePercent.Value, 0f, 100f);
		}

		private static float GetTickInterval()
		{
			if (Vikings_SummonerPlugin.CE_SummonDecayTickInterval == null)
			{
				return 1f;
			}
			return Mathf.Clamp(Vikings_SummonerPlugin.CE_SummonDecayTickInterval.Value, 0.1f, 10f);
		}

		private void StripAffixesOnce()
		{
			if (!_stripped)
			{
				if ((Object)(object)_character == (Object)null)
				{
					_character = ((Component)this).GetComponent<Character>();
				}
				if (!((Object)(object)_character == (Object)null))
				{
					_stripped = true;
					SummonerCllc.TryStrip(_character);
				}
			}
		}
	}
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(2)]
	internal static class SummonerLifetimeUpgradeTotem
	{
		internal static ItemData ResolveWeapon(Character owner, ItemData weapon)
		{
			if (weapon != null && (Object)(object)weapon.m_dropPrefab != (Object)null)
			{
				return weapon;
			}
			Humanoid val = (Humanoid)(object)((owner is Humanoid) ? owner : null);
			if (val == null)
			{
				return null;
			}
			ItemData currentWeapon = val.GetCurrentWeapon();
			if (currentWeapon != null && (Object)(object)currentWeapon.m_dropPrefab != (Object)null)
			{
				return currentWeapon;
			}
			return null;
		}

		internal static float GetBonusSeconds(Character owner, ItemData weapon)
		{
			ItemData val = ResolveWeapon(owner, weapon);
			if (val == null || (Object)(object)val.m_dropPrefab == (Object)null)
			{
				return 0f;
			}
			int num = Mathf.Max(val.m_quality, 1);
			if (num <= 1)
			{
				return 0f;
			}
			string prefabName = Utils.GetPrefabName(val.m_dropPrefab);
			if (string.IsNullOrEmpty(prefabName))
			{
				return 0f;
			}
			if (!SummonerRegistry.TryGetByTotemPrefab(prefabName, out var def) || def == null)
			{
				return 0f;
			}
			float num2 = Mathf.Max(def.LifetimeUpgradeTotemCE.Value, 0f);
			if (num2 <= 0f)
			{
				return 0f;
			}
			return (float)(num - 1) * num2;
		}

		internal static float GetFinalLifetimeSeconds([<75331dbc-839c-437d-a413-c63e0024209e>Nullable(1)] string summonPrefab, Character owner, ItemData weapon)
		{
			float num = Mathf.Max(SummonerRegistry.Get(summonPrefab).LifetimeCE.Value, 0.01f);
			float bonusSeconds = GetBonusSeconds(owner, weapon);
			return Mathf.Max(num + bonusSeconds, 0.01f);
		}
	}
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(2)]
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	public sealed class SummonerMarker : MonoBehaviour
	{
		private const float OwnerResolveInterval = 1f;

		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(1)]
		internal static readonly List<SummonerMarker> Active = new List<SummonerMarker>();

		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(1)]
		private static readonly Dictionary<Component, SummonerMarker> ByComponent = new Dictionary<Component, SummonerMarker>();

		internal Character Creature;

		internal ZNetView NView;

		internal MonsterAI AI;

		internal Tameable Tame;

		internal SummonerState State;

		internal SummonerInteract Interaction;

		private int _activeIndex = -1;

		private string _hoverName;

		private Player _ownerPlayer;

		private float _nextOwnerResolve;

		private void Awake()
		{
			Creature = ((Component)this).GetComponent<Character>();
			NView = ((Component)this).GetComponent<ZNetView>();
			AI = ((Component)this).GetComponent<MonsterAI>();
			Tame = ((Component)this).GetComponent<Tameable>();
			State = ((Component)this).GetComponent<SummonerState>();
			Interaction = ((Component)this).GetComponent<SummonerInteract>();
		}

		private void OnEnable()
		{
			if (_activeIndex < 0)
			{
				_activeIndex = Active.Count;
				Active.Add(this);
				if ((Object)(object)Creature != (Object)null)
				{
					ByComponent[(Component)(object)Creature] = this;
				}
				if ((Object)(object)AI != (Object)null)
				{
					ByComponent[(Component)(object)AI] = this;
				}
				if ((Object)(object)Tame != (Object)null)
				{
					ByComponent[(Component)(object)Tame] = this;
				}
			}
		}

		private void OnDisable()
		{
			Unregister();
		}

		private void OnDestroy()
		{
			Unregister();
		}

		private void Unregister()
		{
			if (_activeIndex >= 0)
			{
				int index = Active.Count - 1;
				SummonerMarker summonerMarker = Active[index];
				Active[_activeIndex] = summonerMarker;
				summonerMarker._activeIndex = _activeIndex;
				Active.RemoveAt(index);
				_activeIndex = -1;
				if (Creature != null)
				{
					ByComponent.Remove((Component)(object)Creature);
				}
				if (AI != null)
				{
					ByComponent.Remove((Component)(object)AI);
				}
				if (Tame != null)
				{
					ByComponent.Remove((Component)(object)Tame);
				}
			}
		}

		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
		internal static bool TryGet([<75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)] Component component, out SummonerMarker marker)
		{
			marker = null;
			if (component == null)
			{
				return false;
			}
			return ByComponent.TryGetValue(component, out marker) && Object.op_Implicit((Object)(object)marker);
		}

		internal ZDO GetZDO()
		{
			if ((Object)(object)NView == (Object)null || !NView.IsValid())
			{
				return null;
			}
			return NView.GetZDO();
		}

		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
		internal string GetHoverName()
		{
			if (_hoverName != null)
			{
				return _hoverName;
			}
			string prefabName = Utils.GetPrefabName(((Component)this).gameObject);
			if (!string.IsNullOrEmpty(prefabName))
			{
				_hoverName = Localization.instance.Localize("$enemy_" + prefabName);
			}
			else if ((Object)(object)Creature != (Object)null && !string.IsNullOrEmpty(Creature.m_name))
			{
				_hoverName = Localization.instance.Localize(Creature.m_name);
			}
			else
			{
				_hoverName = Localization.instance.Localize(((Object)((Component)this).gameObject).name);
			}
			return _hoverName;
		}

		internal Player ResolveOwnerPlayer()
		{
			float time = Time.time;
			if (Object.op_Implicit((Object)(object)_ownerPlayer) && time < _nextOwnerResolve)
			{
				return _ownerPlayer;
			}
			_nextOwnerResolve = time + 1f;
			ZDO zDO = GetZDO();
			_ownerPlayer = ((zDO != null) ? SummonerOwnerIdentity.FindOwnerPlayer(zDO) : null);
			return _ownerPlayer;
		}

		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
		internal string GetInteractionHoverText()
		{
			SummonerInteract interaction = Interaction;
			return Object.op_Implicit((Object)(object)interaction) ? interaction.GetHoverText() : string.Empty;
		}
	}
	public sealed class SummonerVfxProfile : MonoBehaviour
	{
		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(1)]
		public EffectList UnSummonEffect = new EffectList();
	}
	[HarmonyPatch(typeof(ZNet), "Awake")]
	internal static class ZNet_Awake_RegisterRpcs_Patch
	{
		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
		private static void Postfix(ZNet __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<SummonerRpcRegistrar>()))
			{
				((Component)__instance).gameObject.AddComponent<SummonerRpcRegistrar>();
			}
		}
	}
	internal sealed class SummonerRpcRegistrar : MonoBehaviour
	{
		private bool _registered;

		private float _tick;

		private void Update()
		{
			if (_registered)
			{
				((Behaviour)this).enabled = false;
				return;
			}
			_tick -= Time.deltaTime;
			if (!(_tick > 0f))
			{
				_tick = 0.25f;
				if (ZRoutedRpc.instance != null)
				{
					ZRoutedRpc.instance.Register<string, int>("VS_RPC_RemoveOwnedSummons", (Action<long, string, int>)SummonerOwnerCleanup.RPC_RemoveOwnedSummons);
					ZRoutedRpc.instance.Register<ZPackage>("VS_RPC_EnforceSummonLimits", (Action<long, ZPackage>)SummonerProgression.RPC_EnforceSummonLimits);
					ZRoutedRpc.instance.Register("VS_RPC_SummonLimitReached", (Action<long>)SummonerProgression.RPC_SummonLimitReached);
					ZRoutedRpc.instance.Register<ZDOID, Vector3, int>("VS_RPC_UnsummonFx", (Action<long, ZDOID, Vector3, int>)SummonerRemoval.RPC_UnsummonFx);
					_registered = true;
					((Behaviour)this).enabled = false;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "OnDeath")]
	internal static class Player_OnDeath_RemoveOwnedSummons_Patch
	{
		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
		private static void Postfix(Player __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				SummonerOwnerCleanup.RequestRemoveOwnedSummons(__instance, SummonerRemovalReason.OwnerDeath);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "TeleportTo", new Type[]
	{
		typeof(Vector3),
		typeof(Quaternion),
		typeof(bool)
	})]
	internal static class Player_TeleportTo_RemoveOwnedSummons_Patch
	{
		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
		private static void Postfix(Player __instance, bool __result)
		{
			if (__result && !((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				SummonerOwnerCleanup.RequestRemoveOwnedSummons(__instance, SummonerRemovalReason.OwnerTeleport);
			}
		}
	}
	[HarmonyPatch(typeof(ZNet), "Disconnect", new Type[] { typeof(ZNetPeer) })]
	internal static class ZNet_Disconnect_RemoveOwnedSummons_Patch
	{
		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
		private static void Prefix(ZNet __instance, ZNetPeer peer)
		{
			if (!((Object)(object)__instance == (Object)null) && peer != null && __instance.IsServer() && SummonerOwnerIdentity.TryGetPeerIdentity(peer, out var platformId, out var playerId))
			{
				SummonerOwnerCleanup.RemoveOwnedSummonsOnServer(platformId, playerId, SummonerRemovalReason.OwnerLogout, 0L);
			}
		}
	}
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
	internal static class SummonerOwnerCleanup
	{
		internal const string RpcRemoveOwnedSummons = "VS_RPC_RemoveOwnedSummons";

		private static readonly List<ZDO> ScanBuffer = new List<ZDO>();

		private static readonly List<ZDO> RemoveBuffer = new List<ZDO>();

		internal static void RequestRemoveOwnedSummons(Player owner, SummonerRemovalReason reason)
		{
			if ((Object)(object)owner == (Object)null || !SummonerOwnerIdentity.TryGetOwnerIdentity(owner, out var platformId, out var playerId))
			{
				return;
			}
			platformId = SummonerOwnerIdentity.NormalizeOwnerId(platformId);
			if (string.IsNullOrWhiteSpace(platformId))
			{
				return;
			}
			if (SummonerState.IsServer())
			{
				RemoveOwnedSummonsOnServer(platformId, playerId, reason, 0L);
				return;
			}
			RemoveLoadedOwnedSummons(platformId, playerId, reason);
			if (ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC("VS_RPC_RemoveOwnedSummons", new object[2]
				{
					platformId,
					(int)reason
				});
			}
		}

		internal static void RPC_RemoveOwnedSummons(long sender, string steamId, int reason)
		{
			if (SummonerState.IsServer())
			{
				steamId = SummonerOwnerIdentity.NormalizeOwnerId(steamId);
				if (!string.IsNullOrWhiteSpace(steamId) && (reason == 2 || reason == 3) && SummonerOwnerIdentity.TryGetSenderIdentity(sender, out var platformId, out var playerId) && string.Equals(steamId, platformId, StringComparison.Ordinal))
				{
					RemoveOwnedSummonsOnServer(platformId, playerId, (SummonerRemovalReason)reason, sender);
				}
			}
		}

		internal static void RemoveOwnedSummonsOnServer(string steamId, long playerId, SummonerRemovalReason reason, long skipZdoOwner = 0L)
		{
			if (string.IsNullOrWhiteSpace(steamId) || !SummonerState.IsServer())
			{
				return;
			}
			SummonerZdoScan.Collect(ScanBuffer);
			RemoveBuffer.Clear();
			for (int i = 0; i < ScanBuffer.Count; i++)
			{
				ZDO val = ScanBuffer[i];
				if (!val.GetBool("vs_summon_removing", false) && (skipZdoOwner == 0L || val.GetOwner() != skipZdoOwner) && SummonerOwnerIdentity.IsSameOwner(val, steamId, playerId))
				{
					RemoveBuffer.Add(val);
				}
			}
			ScanBuffer.Clear();
			for (int j = 0; j < RemoveBuffer.Count; j++)
			{
				SummonerRemoval.TryRemoveZdo(RemoveBuffer[j], reason);
			}
			RemoveBuffer.Clear();
		}

		private static void RemoveLoadedOwnedSummons(string steamId, long playerId, SummonerRemovalReason reason)
		{
			List<SummonerMarker> active = SummonerMarker.Active;
			for (int num = active.Count - 1; num >= 0; num--)
			{
				SummonerMarker summonerMarker = active[num];
				if (Object.op_Implicit((Object)(object)summonerMarker))
				{
					Character creature = summonerMarker.Creature;
					if (!((Object)(object)creature == (Object)null) && !creature.IsDead())
					{
						ZDO zDO = summonerMarker.GetZDO();
						if (zDO != null && SummonerOwnerIdentity.IsSameOwner(zDO, steamId, playerId))
						{
							SummonerRemoval.TryRemove(((Component)summonerMarker).gameObject, reason);
						}
					}
				}
			}
		}
	}
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
	internal sealed class SummonerOwnerRegenDebuff : SE_Stats
	{
		internal const string EffectName = "SE_VS_SummonOwnerRegenDebuff";

		private int _activeSummons;

		private string _iconText = string.Empty;

		internal void SetActiveSummons(int activeSummons)
		{
			if (activeSummons < 0)
			{
				activeSummons = 0;
			}
			if (activeSummons != _activeSummons)
			{
				_activeSummons = activeSummons;
				_iconText = ((activeSummons > 0) ? activeSummons.ToString() : string.Empty);
			}
		}

		public override string GetIconText()
		{
			if (!(((StatusEffect)this).m_character is Player))
			{
				return "";
			}
			return _iconText;
		}

		public override string GetTooltipString()
		{
			int num = ((((StatusEffect)this).m_character is Player) ? _activeSummons : 0);
			float num2 = Mathf.Max(0f, (1f - base.m_healthRegenMultiplier) * 100f);
			string text = ((StatusEffect)this).m_tooltip;
			if (Localization.instance != null && !string.IsNullOrWhiteSpace(text))
			{
				text = Localization.instance.Localize(text);
			}
			if (string.IsNullOrWhiteSpace(text))
			{
				return string.Empty;
			}
			return string.Format(text, num, num2.ToString("0.#"));
		}
	}
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
	internal static class SummonerOwnerDebuff
	{
		private static readonly int EffectHash = StringExtensionMethods.GetStableHashCode("SE_VS_SummonOwnerRegenDebuff");

		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)]
		private static SummonerOwnerRegenDebuff _template;

		internal static void EnsureRegistered()
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_template != (Object)null))
			{
				_template = ScriptableObject.CreateInstance<SummonerOwnerRegenDebuff>();
				((Object)_template).name = "SE_VS_SummonOwnerRegenDebuff";
				((StatusEffect)_template).m_name = "$vs_summon_regen_burden_name";
				((StatusEffect)_template).m_tooltip = "$vs_summon_regen_burden_tooltip";
				((StatusEffect)_template).m_category = "Equipment";
				((StatusEffect)_template).m_icon = SummonerAssetLoader.GetSprite("ico_debuff");
				((StatusEffect)_template).m_flashIcon = false;
				((StatusEffect)_template).m_cooldownIcon = false;
				((StatusEffect)_template).m_startMessageType = (MessageType)2;
				((StatusEffect)_template).m_startMessage = "";
				((StatusEffect)_template).m_stopMessageType = (MessageType)2;
				((StatusEffect)_template).m_stopMessage = "";
				((StatusEffect)_template).m_ttl = 0f;
				((SE_Stats)_template).m_healthRegenMultiplier = 1f;
			}
		}

		internal static void EnsureInObjectDb()
		{
			EnsureRegistered();
			if (!((Object)(object)ObjectDB.instance == (Object)null) && !((Object)(object)_template == (Object)null) && !ObjectDB.instance.m_StatusEffects.Contains((StatusEffect)(object)_template))
			{
				ObjectDB.instance.m_StatusEffects.Add((StatusEffect)(object)_template);
				ObjectDB.instance.UpdateRegisters();
			}
		}

		internal static int CountActiveSummons(Player owner)
		{
			if (!SummonerOwnerIdentity.TryGetOwnerIdentity(owner, out var platformId, out var playerId))
			{
				return 0;
			}
			int num = 0;
			List<SummonerMarker> active = SummonerMarker.Active;
			for (int i = 0; i < active.Count; i++)
			{
				SummonerMarker summonerMarker = active[i];
				if (!Object.op_Implicit((Object)(object)summonerMarker))
				{
					continue;
				}
				Character creature = summonerMarker.Creature;
				if (!((Object)(object)creature == (Object)null) && !creature.IsDead())
				{
					ZDO zDO = summonerMarker.GetZDO();
					if (zDO != null && !zDO.GetBool("vs_summon_removing", false) && SummonerOwnerIdentity.IsSameOwner(zDO, platformId, playerId))
					{
						num++;
					}
				}
			}
			return num;
		}

		internal static float CalculateHealthRegenMultiplier(int activeSummons)
		{
			float num = Mathf.Max(0f, Vikings_SummonerPlugin.CE_ActiveSummonHealthRegenPenaltyPerSummon.Value);
			return Mathf.Max(0f, 1f - (float)activeSummons * num);
		}

		internal static void UpdateDebuff(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			SEMan seman = ((Character)player).m_seman;
			if (seman == null)
			{
				return;
			}
			if (!Vikings_SummonerPlugin.CE_ActiveSummonHealthRegenDebuffEnabled.Value)
			{
				seman.RemoveStatusEffect(EffectHash, true);
				return;
			}
			if (!TryResolveOwner(player, out var _, out var _))
			{
				seman.RemoveStatusEffect(EffectHash, true);
				return;
			}
			int num = CountActiveSummons(player);
			if (num <= 0)
			{
				seman.RemoveStatusEffect(EffectHash, true);
				return;
			}
			EnsureInObjectDb();
			StatusEffect statusEffect = seman.GetStatusEffect(EffectHash);
			SummonerOwnerRegenDebuff summonerOwnerRegenDebuff = statusEffect as SummonerOwnerRegenDebuff;
			if ((Object)(object)summonerOwnerRegenDebuff == (Object)null)
			{
				statusEffect = seman.AddStatusEffect(EffectHash, true, 0, 0f, (short)(-1));
				summonerOwnerRegenDebuff = statusEffect as SummonerOwnerRegenDebuff;
				if ((Object)(object)summonerOwnerRegenDebuff == (Object)null)
				{
					return;
				}
			}
			((SE_Stats)summonerOwnerRegenDebuff).m_healthRegenMultiplier = CalculateHealthRegenMultiplier(num);
			summonerOwnerRegenDebuff.SetActiveSummons(num);
		}

		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(2)]
		internal static void EnsureUpdater(Player player)
		{
			SummonerOwnerDebuffUpdater summonerOwnerDebuffUpdater = default(SummonerOwnerDebuffUpdater);
			if (!((Object)(object)player == (Object)null) && !((Object)(object)player != (Object)(object)Player.m_localPlayer) && TryResolveOwner(player, out var _, out var _) && !((Component)player).TryGetComponent<SummonerOwnerDebuffUpdater>(ref summonerOwnerDebuffUpdater))
			{
				((Component)player).gameObject.AddComponent<SummonerOwnerDebuffUpdater>();
			}
		}

		internal static bool HasValidOwnerIdentity(Player player)
		{
			string steamId;
			string ownerName;
			return TryResolveOwner(player, out steamId, out ownerName);
		}

		private static bool TryResolveOwner(Player player, out string steamId, out string ownerName)
		{
			return SummonerOwnerIdentity.TryGetSteamIdentity(player, out steamId, out ownerName);
		}
	}
	internal sealed class SummonerOwnerDebuffUpdater : MonoBehaviour
	{
		private const float UpdateInterval = 1f;

		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)]
		private Player _player;

		private float _tick;

		private void Awake()
		{
			_player = ((Component)this).GetComponent<Player>();
			_tick = 0f;
		}

		private void Update()
		{
			if (!((Object)(object)_player == (Object)null) && !((Object)(object)_player != (Object)(object)Player.m_localPlayer) && !((Character)_player).IsDead())
			{
				_tick -= Time.deltaTime;
				if (!(_tick > 0f) && SummonerOwnerDebuff.HasValidOwnerIdentity(_player))
				{
					_tick = 1f;
					SummonerOwnerDebuff.UpdateDebuff(_player);
				}
			}
		}

		private void OnDestroy()
		{
			if (((Character)(_player?)).m_seman != null)
			{
				((Character)_player).m_seman.RemoveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VS_SummonOwnerRegenDebuff"), true);
			}
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	internal static class ObjectDB_Awake_OwnerDebuff_Patch
	{
		private static void Postfix()
		{
			SummonerOwnerDebuff.EnsureInObjectDb();
		}
	}
	[HarmonyPatch(typeof(Player), "SetPlayerID", new Type[]
	{
		typeof(long),
		typeof(string)
	})]
	internal static class Player_SetPlayerID_OwnerDebuff_Patch
	{
		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
		private static void Postfix(Player __instance, long playerID, string name)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				SummonerOwnerDebuff.EnsureUpdater(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "Start")]
	internal static class Player_Start_OwnerDebuff_Patch
	{
		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
		private static void Postfix(Player __instance)
		{
			SummonerOwnerDebuff.EnsureUpdater(__instance);
		}
	}
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	internal static class SummonerOwnerIdentity
	{
		internal static bool TryGetSteamIdentity(Player player, out string steamId, out string playerName)
		{
			steamId = string.Empty;
			playerName = string.Empty;
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			playerName = GetSafePlayerName(player);
			if (TryGetSteamIdByCharacterZdo(player, out steamId))
			{
				steamId = NormalizeOwnerId(steamId);
				return !string.IsNullOrWhiteSpace(steamId);
			}
			if ((Object)(object)player == (Object)(object)Player.m_localPlayer)
			{
				UserInfo localUser = UserInfo.GetLocalUser();
				steamId = NormalizeOwnerId(((object)Unsafe.As<PlatformUserID, PlatformUserID>(ref localUser.UserId)/*cast due to .constrained prefix*/).ToString());
				if (!string.IsNullOrWhiteSpace(localUser.Name))
				{
					playerName = localUser.Name;
				}
				return !string.IsNullOrWhiteSpace(steamId);
			}
			return false;
		}

		internal static bool TryGetOwnerIdentity(Player player, out string platformId, out long playerId)
		{
			playerId = 0L;
			if (!TryGetSteamIdentity(player, out platformId, out var _))
			{
				return false;
			}
			playerId = player.GetPlayerID();
			return true;
		}

		internal static bool PlayerIdMatches(long storedPlayerId, long playerId)
		{
			return storedPlayerId == 0L || playerId == 0L || storedPlayerId == playerId;
		}

		internal static bool IsSameOwner(ZDO zdo, string platformId, long playerId)
		{
			if (zdo == null)
			{
				return false;
			}
			string text = NormalizeOwnerId(zdo.GetString("VS_OwnerSteamID", string.Empty));
			string text2 = NormalizeOwnerId(platformId);
			if (string.IsNullOrWhiteSpace(text) || string.IsNullOrWhiteSpace(text2))
			{
				return false;
			}
			if (!string.Equals(text, text2, StringComparison.Ordinal))
			{
				return false;
			}
			return PlayerIdMatches(zdo.GetLong("VS_OwnerID", 0L), playerId);
		}

		[return: <75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)]
		internal static Player FindOwnerPlayer(ZDO zdo)
		{
			if (zdo == null)
			{
				return null;
			}
			string text = NormalizeOwnerId(zdo.GetString("VS_OwnerSteamID", string.Empty));
			if (text.Length == 0)
			{
				return null;
			}
			return SummonerPlayerCache.Find(text, zdo.GetLong("VS_OwnerID", 0L));
		}

		internal unsafe static bool TryGetPeerIdentity(ZNetPeer peer, out string platformId, out long playerId)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			platformId = string.Empty;
			playerId = 0L;
			if (peer == null || (Object)(object)ZNet.instance == (Object)null)
			{
				return false;
			}
			if (((ZDOID)(ref peer.m_characterID)).IsNone())
			{
				return false;
			}
			List<PlayerInfo> playerList = ZNet.instance.GetPlayerList();
			if (playerList == null)
			{
				return false;
			}
			for (int i = 0; i < playerList.Count; i++)
			{
				PlayerInfo val = playerList[i];
				if (!(val.m_characterID != peer.m_characterID))
				{
					platformId = NormalizeOwnerId(((object)(*(PlatformUserID*)(&val.m_userInfo.m_id))/*cast due to .constrained prefix*/).ToString());
					playerId = GetCharacterPlayerId(peer);
					return !string.IsNullOrWhiteSpace(platformId);
				}
			}
			return false;
		}

		private static long GetCharacterPlayerId(ZNetPeer peer)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (((ZDOID)(ref peer.m_characterID)).IsNone() || ZDOMan.instance == null)
			{
				return 0L;
			}
			ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID);
			return (zDO != null) ? zDO.GetLong(ZDOVars.s_playerID, 0L) : 0;
		}

		internal static bool TryGetSenderIdentity(long sender, out string platformId, out long playerId)
		{
			platformId = string.Empty;
			playerId = 0L;
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return false;
			}
			ZNetPeer peer = ZNet.instance.GetPeer(sender);
			return peer != null && TryGetPeerIdentity(peer, out platformId, out playerId);
		}

		internal unsafe static bool IsSenderOwnerOrDebugFlying(long sender, ZDO zdo)
		{
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			if (zdo == null || (Object)(object)ZNet.instance == (Object)null)
			{
				return false;
			}
			if (sender == ZDOMan.GetSessionID())
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null)
				{
					return false;
				}
				if (((Character)localPlayer).IsDebugFlying())
				{
					return true;
				}
				string platformId;
				long playerId;
				return TryGetOwnerIdentity(localPlayer, out platformId, out playerId) && IsSameOwner(zdo, platformId, playerId);
			}
			List<PlayerInfo> playerList = ZNet.instance.GetPlayerList();
			if (playerList == null)
			{
				return false;
			}
			for (int i = 0; i < playerList.Count; i++)
			{
				PlayerInfo val = playerList[i];
				if (((ZDOID)(ref val.m_characterID)).IsNone() || ((ZDOID)(ref val.m_characterID)).UserID != sender)
				{
					continue;
				}
				Player val2 = FindPlayerByCharacterId(val.m_characterID);
				if ((Object)(object)val2 != (Object)null && ((Character)val2).IsDebugFlying())
				{
					return true;
				}
				string platformId2 = NormalizeOwnerId(((object)(*(PlatformUserID*)(&val.m_userInfo.m_id))/*cast due to .constrained prefix*/).ToString());
				long playerId2 = 0L;
				if (ZNet.instance.IsServer())
				{
					ZNetPeer peer = ZNet.instance.GetPeer(sender);
					if (peer != null)
					{
						playerId2 = GetCharacterPlayerId(peer);
					}
				}
				else if ((Object)(object)val2 != (Object)null)
				{
					playerId2 = val2.GetPlayerID();
				}
				return IsSameOwner(zdo, platformId2, playerId2);
			}
			return false;
		}

		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(2)]
		private static Player FindPlayerByCharacterId(ZDOID characterId)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			List<Player> allPlayers = Player.GetAllPlayers();
			for (int i = 0; i < allPlayers.Count; i++)
			{
				Player val = allPlayers[i];
				if (!((Object)(object)val == (Object)null))
				{
					ZNetView nview = ((Character)val).m_nview;
					if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.GetZDO().m_uid == characterId)
					{
						return val;
					}
				}
			}
			return null;
		}

		internal static void RepairOwnerZDO(ZNetView nview, ZDO zdo, string steamId, string playerName)
		{
			if ((Object)(object)nview == (Object)null || zdo == null)
			{
				return;
			}
			steamId = NormalizeOwnerId(steamId);
			if (string.IsNullOrWhiteSpace(steamId))
			{
				return;
			}
			if (!nview.IsOwner() && (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
			{
				nview.ClaimOwnership();
			}
			if (nview.IsOwner())
			{
				if (!string.Equals(NormalizeOwnerId(zdo.GetString("VS_OwnerSteamID", string.Empty)), steamId, StringComparison.Ordinal))
				{
					zdo.Set("VS_OwnerSteamID", steamId);
				}
				if (!string.IsNullOrWhiteSpace(playerName) && !string.Equals(zdo.GetString("VS_OwnerName", string.Empty), playerName, StringComparison.Ordinal))
				{
					zdo.Set("VS_OwnerName", playerName);
				}
				if (!string.IsNullOrWhiteSpace(playerName) && !string.Equals(zdo.GetString(ZDOVars.s_follow, string.Empty), playerName, StringComparison.Ordinal))
				{
					zdo.Set(ZDOVars.s_follow, playerName);
				}
			}
		}

		internal static string NormalizeOwnerId(string id)
		{
			return string.IsNullOrWhiteSpace(id) ? string.Empty : id.Trim();
		}

		private unsafe static bool TryGetSteamIdByCharacterZdo(Player player, out string steamId)
		{
			//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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			steamId = string.Empty;
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return false;
			}
			ZNetView nview = ((Character)player).m_nview;
			if ((Object)(object)nview == (Object)null || !nview.IsValid())
			{
				return false;
			}
			ZDO zDO = nview.GetZDO();
			if (zDO == null)
			{
				return false;
			}
			ZDOID uid = zDO.m_uid;
			if (((ZDOID)(ref uid)).IsNone())
			{
				return false;
			}
			List<PlayerInfo> playerList = ZNet.instance.GetPlayerList();
			if (playerList == null || playerList.Count == 0)
			{
				return false;
			}
			for (int i = 0; i < playerList.Count; i++)
			{
				PlayerInfo val = playerList[i];
				if (!((ZDOID)(ref val.m_characterID)).IsNone() && val.m_characterID == uid)
				{
					steamId = NormalizeOwnerId(((object)(*(PlatformUserID*)(&val.m_userInfo.m_id))/*cast due to .constrained prefix*/).ToString());
					return !string.IsNullOrWhiteSpace(steamId);
				}
			}
			return false;
		}

		internal static string GetSafePlayerName(Player player)
		{
			string text = player.GetPlayerName();
			if (string.IsNullOrWhiteSpace(text) || text == "...")
			{
				text = ((Character)player).GetHoverName();
			}
			return text;
		}
	}
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
	internal static class SummonerPlayerCache
	{
		private const float RefreshInterval = 1f;

		private static readonly Dictionary<string, Player> ByPlatformId = new Dictionary<string, Player>(StringComparer.Ordinal);

		private static float _nextRefresh;

		private static int _playerCount = -1;

		[return: <75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)]
		internal static Player Find(string platformId, long playerId)
		{
			if (string.IsNullOrEmpty(platformId))
			{
				return null;
			}
			Refresh();
			if (!ByPlatformId.TryGetValue(platformId, out var value) || !Object.op_Implicit((Object)(object)value))
			{
				return null;
			}
			if (!SummonerOwnerIdentity.PlayerIdMatches(playerId, value.GetPlayerID()))
			{
				return null;
			}
			return value;
		}

		private static void Refresh()
		{
			List<Player> allPlayers = Player.GetAllPlayers();
			float time = Time.time;
			if (time < _nextRefresh && allPlayers.Count == _playerCount)
			{
				return;
			}
			_nextRefresh = time + 1f;
			_playerCount = allPlayers.Count;
			ByPlatformId.Clear();
			for (int i = 0; i < allPlayers.Count; i++)
			{
				Player val = allPlayers[i];
				if (!((Object)(object)val == (Object)null) && SummonerOwnerIdentity.TryGetSteamIdentity(val, out var steamId, out var _))
				{
					ByPlatformId[steamId] = val;
				}
			}
		}
	}
	internal static class SummonerPrefabs
	{
		public static void Register()
		{
			foreach (SummonerRegistry.SummonDef value in SummonerRegistry.All.Values)
			{
				PrefabManager.RegisterPrefab("rd_armor", value.Prefab);
			}
		}
	}
	internal readonly struct SummonerProgressionEntry
	{
		internal readonly int MinSkill;

		internal readonly int MaxSkill;

		internal readonly int SummonLevel;

		internal readonly int MaxInstances;

		internal SummonerProgressionEntry(int minSkill, int maxSkill, int summonLevel, int maxInstances)
		{
			MinSkill = minSkill;
			MaxSkill = maxSkill;
			SummonLevel = ((summonLevel < 1) ? 1 : summonLevel);
			MaxInstances = ((maxInstances < 1) ? 1 : maxInstances);
		}
	}
	internal readonly struct SummonerProgressionResult
	{
		internal readonly int SummonLevel;

		internal readonly int MaxInstances;

		internal SummonerProgressionResult(int summonLevel, int maxInstances)
		{
			SummonLevel = ((summonLevel < 1) ? 1 : summonLevel);
			MaxInstances = ((maxInstances < 1) ? 1 : maxInstances);
		}
	}
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
	internal static class SummonerProgression
	{
		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
		private sealed class ParsedProgression
		{
			internal string Raw = string.Empty;

			internal bool Valid;

			internal List<SummonerProgressionEntry> Entries = new List<SummonerProgressionEntry>();
		}

		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
		private readonly struct SummonLimit
		{
			internal readonly string Prefab;

			internal readonly int MaxInstances;

			internal SummonLimit(string prefab, int maxInstances)
			{
				Prefab = prefab;
				MaxInstances = ((maxInstances >= 0) ? maxInstances : 0);
			}
		}

		internal const string RpcEnforceSummonLimits = "VS_RPC_EnforceSummonLimits";

		internal const string RpcSummonLimitReached = "VS_RPC_SummonLimitReached";

		private const int MaxLimitsPerRequest = 256;

		private static readonly Dictionary<string, ParsedProgression> ParsedByPrefab = new Dictionary<string, ParsedProgression>(StringComparer.Ordinal);

		private static readonly List<ZDO> ScanBuffer = new List<ZDO>();

		private static readonly List<ZDO> OwnedBuffer = new List<ZDO>();

		private static readonly List<ZDO> GroupBuffer = new List<ZDO>();

		internal static bool TryGetGateFromConfig(string prefab, out int minGate)
		{
			minGate = 0;
			if (!TryParse(prefab, out var result))
			{
				return false;
			}
			if (result.Count == 0)
			{
				return false;
			}
			minGate = result[0].MinSkill;
			for (int i = 1; i < result.Count; i++)
			{
				if (result[i].MinSkill < minGate)
				{
					minGate = result[i].MinSkill;
				}
			}
			return true;
		}

		internal static bool TryResolve(string prefab, float bloodMagic, out SummonerProgressionResult result)
		{
			result = default(SummonerProgressionResult);
			if (!TryParse(prefab, out var result2))
			{
				return false;
			}
			if (result2.Count == 0)
			{
				return false;
			}
			int num = Mathf.FloorToInt(bloodMagic);
			SummonerProgressionEntry? summonerProgressionEntry = null;
			for (int i = 0; i < result2.Count; i++)
			{
				SummonerProgressionEntry value = result2[i];
				if (num < value.MinSkill)
				{
					break;
				}
				summonerProgressionEntry = value;
			}
			if (!summonerProgressionEntry.HasValue)
			{
				return false;
			}
			result = new SummonerProgressionResult(summonerProgressionEntry.Value.SummonLevel, summonerProgressionEntry.Value.MaxInstances);
			return true;
		}

		private static bool TryParse(string prefab, out List<SummonerProgressionEntry> result)
		{
			string text = SummonerRegistry.Get(prefab).ProgressionCE?.Value ?? string.Empty;
			if (ParsedByPrefab.TryGetValue(prefab, out var value) && string.Equals(value.Raw, text, StringComparison.Ordinal))
			{
				result = value.Entries;
				return value.Valid;
			}
			bool flag = TryParseValue(text, out result);
			ParsedByPrefab[prefab] = new ParsedProgression
			{
				Raw = text,
				Valid = flag,
				Entries = result
			};
			return flag;
		}

		private static bool TryParseValue(string raw, out List<SummonerProgressionEntry> result)
		{
			result = new List<SummonerProgressionEntry>();
			if (string.IsNullOrWhiteSpace(raw))
			{
				return false;
			}
			string[] array = raw.Split(new char[1] { ';' });
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length == 0)
				{
					return false;
				}
				string[] array2 = text.Split(new char[1] { ':' });
				if (array2.Length != 3)
				{
					return false;
				}
				string[] array3 = array2[0].Split(new char[1] { '-' });
				if (array3.Length != 2)
				{
					return false;
				}
				if (!int.TryParse(array3[0].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2))
				{
					return false;
				}
				if (!int.TryParse(array3[1].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result3))
				{
					return false;
				}
				if (!int.TryParse(array2[1].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result4))
				{
					return false;
				}
				if (!int.TryParse(array2[2].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result5))
				{
					return false;
				}
				if (result2 < 0)
				{
					return false;
				}
				if (result3 < result2)
				{
					return false;
				}
				if (result4 < 1)
				{
					return false;
				}
				if (result5 < 1)
				{
					return false;
				}
				result.Add(new SummonerProgressionEntry(result2, result3, result4, result5));
			}
			result.Sort(delegate(SummonerProgressionEntry a, SummonerProgressionEntry b)
			{
				int minSkill = a.MinSkill;
				return minSkill.CompareTo(b.MinSkill);
			});
			return result.Count > 0;
		}

		internal static void EnforceMaxInstances(string prefab, Humanoid owner, int maxInstances, ZDOID newest)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			Player val = (Player)(object)((owner is Player) ? owner : null);
			if (val != null)
			{
				List<SummonLimit> limits = new List<SummonLimit>(1)
				{
					new SummonLimit(prefab, maxInstances)
				};
				RequestEnforce(val, limits, newest);
			}
		}

		internal static void EnforceAllSummonLimits(Humanoid owner)
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			Player val = (Player)(object)((owner is Player) ? owner : null);
			if (val == null || !TryResolveOwner(val, out var _, out var _))
			{
				return;
			}
			Skills skills = ((Character)owner).GetSkills();
			if ((Object)(object)skills == (Object)null)
			{
				return;
			}
			float skillLevel = skills.GetSkillLevel((SkillType)10);
			List<SummonLimit> list = new List<SummonLimit>(SummonerRegistry.All.Count);
			foreach (string key in SummonerRegistry.All.Keys)
			{
				if (!TryResolve(key, skillLevel, out var result))
				{
					list.Add(new SummonLimit(key, 0));
					continue;
				}
				int maxInstances = SummonerSummonExtra.ApplyExtraMaxSummons((Character)(object)owner, result.MaxInstances);
				list.Add(new SummonLimit(key, maxInstances));
			}
			RequestEnforce(val, list, ZDOID.None);
		}

		private static void RequestEnforce(Player p, List<SummonLimit> limits, ZDOID newest)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			if (limits.Count == 0 || !SummonerOwnerIdentity.TryGetOwnerIdentity(p, out var platformId, out var playerId))
			{
				return;
			}
			if (SummonerState.IsServer())
			{
				if (EnforceOnServer(platformId, playerId, limits, newest) > 0)
				{
					ShowLimitReachedMessage(p);
				}
			}
			else if (ZRoutedRpc.instance != null)
			{
				ZPackage val = new ZPackage();
				val.Write(newest);
				val.Write(limits.Count);
				for (int i = 0; i < limits.Count; i++)
				{
					val.Write(limits[i].Prefab);
					val.Write(limits[i].MaxInstances);
				}
				ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "VS_RPC_EnforceSummonLimits", new object[1] { val });
			}
		}

		internal static void RPC_EnforceSummonLimits(long sender, ZPackage pkg)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			if (!SummonerState.IsServer() || pkg == null || !SummonerOwnerIdentity.TryGetSenderIdentity(sender, out var platformId, out var playerId))
			{
				return;
			}
			ZDOID newest = pkg.ReadZDOID();
			int num = pkg.ReadInt();
			if (num <= 0 || num > 256)
			{
				return;
			}
			List<SummonLimit> list = new List<SummonLimit>(num);
			for (int i = 0; i < num; i++)
			{
				string text = pkg.ReadString();
				int maxInstances = pkg.ReadInt();
				if (!string.IsNullOrEmpty(text) && SummonerRegistry.All.ContainsKey(text))
				{
					list.Add(new SummonLimit(text, maxInstances));
				}
			}
			if (list.Count != 0 && EnforceOnServer(platformId, playerId, list, newest) > 0 && ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(sender, "VS_RPC_SummonLimitReached", Array.Empty<object>());
			}
		}

		internal static void RPC_SummonLimitReached(long sender)
		{
			if (!SummonerState.IsServer() && ZRoutedRpc.instance != null && sender == ZRoutedRpc.instance.GetServerPeerID())
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null)
				{
					ShowLimitReachedMessage(localPlayer);
				}
			}
		}

		private static void ShowLimitReachedMessage(Player p)
		{
			((Character)p).Message((MessageType)2, "$hud_maxsummonsreached", 0, (Sprite)null, false);
		}

		private static int EnforceOnServer(string steamId, long playerId, List<SummonLimit> limits, ZDOID newest)
		{
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			SummonerZdoScan.Collect(ScanBuffer);
			OwnedBuffer.Clear();
			for (int i = 0; i < ScanBuffer.Count; i++)
			{
				ZDO val = ScanBuffer[i];
				if (!val.GetBool("vs_summon_removing", false) && SummonerOwnerIdentity.IsSameOwner(val, steamId, playerId))
				{
					OwnedBuffer.Add(val);
				}
			}
			ScanBuffer.Clear();
			bool flag = !((ZDOID)(ref newest)).IsNone();
			int num = 0;
			for (int j = 0; j < limits.Count; j++)
			{
				SummonLimit summonLimit = limits[j];
				GroupBuffer.Clear();
				for (int k = 0; k < OwnedBuffer.Count; k++)
				{
					ZDO val2 = OwnedBuffer[k];
					if ((!flag || !(val2.m_uid == newest)) && string.Equals(SummonerZdoScan.GetSummonPrefab(val2), summonLimit.Prefab, StringComparison.Ordinal))
					{
						GroupBuffer.Add(val2);
					}
				}
				int num2 = Mathf.Max(0, summonLimit.MaxInstances - (flag ? 1 : 0));
				int num3 = GroupBuffer.Count - num2;
				if (num3 <= 0)
				{
					continue;
				}
				GroupBuffer.Sort(CompareSpawnTime);
				for (int l = 0; l < num3; l++)
				{
					if (SummonerRemoval.TryRemoveZdo(GroupBuffer[l], SummonerRemovalReason.ProgressionLimit))
					{
						num++;
					}
				}
			}
			GroupBuffer.Clear();
			OwnedBuffer.Clear();
			return num;
		}

		private static int CompareSpawnTime(ZDO a, ZDO b)
		{
			return GetSpawnTicks(a).CompareTo(GetSpawnTicks(b));
		}

		private static long GetSpawnTicks(ZDO zdo)
		{
			long num = zdo.GetLong(ZDOVars.s_spawnTime, 0L);
			return (num > 0) ? num : long.MaxValue;
		}

		private static bool TryResolveOwner(Player p, out string steamId, out string ownerName)
		{
			return SummonerOwnerIdentity.TryGetSteamIdentity(p, out steamId, out ownerName);
		}
	}
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	internal static class SummonerRegistry
	{
		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
		internal sealed class SummonDef
		{
			public SummonSpec Spec = null;

			public ConfigEntry<float> LifetimeCE = null;

			public ConfigEntry<float> LifetimeUpgradeTotemCE = null;

			public ConfigEntry<float> BaseHpCE = null;

			public ConfigEntry<float> HpPercentPerStarCE = null;

			public ConfigEntry<string> ProgressionCE = null;

			public ConfigEntry<float> SpawnHealthPercentCE = null;

			public ConfigEntry<float> SpawnEitrCE = null;

			public string Prefab => Spec.Prefab;

			public string TotemPrefab => Spec.TotemPrefab;

			[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)]
			public string UnspawnVfxPrefab
			{
				[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(2)]
				get
				{
					return Spec.UnspawnVfxPrefab;
				}
			}

			[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)]
			public string UnspawnSfxPrefab
			{
				[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(2)]
				get
				{
					return Spec.UnspawnSfxPrefab;
				}
			}
		}

		internal static readonly Dictionary<string, SummonDef> All = new Dictionary<string, SummonDef>(StringComparer.Ordinal);

		internal static readonly Dictionary<string, SummonDef> ByTotemPrefab = new Dictionary<string, SummonDef>(StringComparer.Ordinal);

		internal static void Add(SummonDef def)
		{
			string prefab = def.Prefab;
			string totemPrefab = def.TotemPrefab;
			if (string.IsNullOrWhiteSpace(prefab))
			{
				throw new ArgumentException("Invalid summon prefab.", "prefab");
			}
			if (string.IsNullOrWhiteSpace(totemPrefab))
			{
				throw new ArgumentException("Invalid summon totem prefab.", "totemPrefab");
			}
			if (All.ContainsKey(prefab))
			{
				throw new InvalidOperationException("Duplicate summon prefab '" + prefab + "'.");
			}
			if (ByTotemPrefab.ContainsKey(totemPrefab))
			{
				throw new InvalidOperationException("Duplicate summon totem prefab '" + totemPrefab + "'.");
			}
			All.Add(prefab, def);
			ByTotemPrefab.Add(totemPrefab, def);
		}

		internal static SummonDef Get(string prefab)
		{
			if (All.TryGetValue(prefab, out var value))
			{
				return value;
			}
			throw new ArgumentOutOfRangeException("prefab", prefab, "Unknown summon prefab.");
		}

		internal static bool TryGet(string prefab, [<75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)] out SummonDef def)
		{
			return All.TryGetValue(prefab, out def);
		}

		internal static bool TryGetByTotemPrefab(string totemPrefab, [<75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)] out SummonDef def)
		{
			return ByTotemPrefab.TryGetValue(totemPrefab, out def);
		}
	}
	internal enum SummonerRemovalReason
	{
		Manual,
		LifetimeExpired,
		OwnerDeath,
		OwnerTeleport,
		ProgressionLimit,
		DeathCleanup,
		OwnerIdentityFailed,
		OwnerLogout
	}
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
	internal static class SummonerRemoval
	{
		internal const string ZdoRemoving = "vs_summon_removing";

		internal const string RpcUnsummonFx = "VS_RPC_UnsummonFx";

		internal static bool TryRemove(GameObject go, SummonerRemovalReason reason)
		{
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)go))
			{
				return false;
			}
			SummonerMarker summonerMarker = default(SummonerMarker);
			if (!go.TryGetComponent<SummonerMarker>(ref summonerMarker))
			{
				return false;
			}
			ZNetView component = go.GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return false;
			}
			ZDO zDO = component.GetZDO();
			if (zDO == null)
			{
				return false;
			}
			if (zDO.GetBool("vs_summon_removing", false))
			{
				return false;
			}
			if (!component.IsOwner() && (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
			{
				component.ClaimOwnership();
			}
			if (!component.IsOwner())
			{
				return false;
			}
			zDO.Set("vs_summon_removing", true);
			if (reason != SummonerRemovalReason.DeathCleanup)
			{
				if (ZRoutedRpc.instance != null)
				{
					BroadcastUnsummonFx(zDO);
				}
				else
				{
					SummonerVfxProfile component2 = go.GetComponent<SummonerVfxProfile>();
					if ((Object)(object)component2 != (Object)null && component2.UnSummonEffect != null && component2.UnSummonEffect.HasEffects())
					{
						component2.UnSummonEffect.Create(go.transform.position, go.transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
					}
				}
			}
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				ZNetScene.instance.Destroy(go);
			}
			else
			{
				component.Destroy();
			}
			return true;
		}

		internal static bool TryRemoveZdo(ZDO zdo, SummonerRemovalReason reason)
		{
			if (zdo == null)
			{
				return false;
			}
			if (zdo.GetBool("vs_summon_removing", false))
			{
				return false;
			}
			ZNetView val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.FindInstance(zdo) : null);
			if ((Object)(object)val != (Object)null && val.IsValid())
			{
				return TryRemove(((Component)val).gameObject, reason);
			}
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				return false;
			}
			if (ZDOMan.instance == null)
			{
				return false;
			}
			if (!zdo.IsOwner())
			{
				zdo.SetOwner(ZDOMan.GetSessionID());
			}
			zdo.Set("vs_summon_removing", true);
			if (reason != SummonerRemovalReason.DeathCleanup)
			{
				BroadcastUnsummonFx(zdo);
			}
			ZDOMan.instance.DestroyZDO(zdo);
			return true;
		}

		private static void BroadcastUnsummonFx(ZDO zdo)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "VS_RPC_UnsummonFx", new object[3]
				{
					zdo.m_uid,
					zdo.GetPosition(),
					zdo.GetPrefab()
				});
			}
		}

		internal static void RPC_UnsummonFx(long sender, ZDOID uid, Vector3 position, int prefabHash)
		{
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			if (Application.isBatchMode || ZRoutedRpc.instance == null || (Object)(object)ZNetScene.instance == (Object)null || !SummonerZdoScan.IsSummonPrefab(prefabHash))
			{
				return;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(prefabHash);
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				return;
			}
			SummonerVfxProfile component = prefab.GetComponent<SummonerVfxProfile>();
			if ((Object)(object)component == (Object)null || component.UnSummonEffect == null || !component.UnSummonEffect.HasEffects())
			{
				return;
			}
			GameObject val = ZNetScene.instance.FindInstance(uid);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			if (sender != ZRoutedRpc.instance.m_id && sender != ZRoutedRpc.instance.GetServerPeerID())
			{
				ZNetView component2 = val.GetComponent<ZNetView>();
				ZDO val2 = (((Object)(object)component2 != (Object)null && component2.IsValid()) ? component2.GetZDO() : null);
				if (val2 == null || val2.GetOwner() != sender)
				{
					return;
				}
			}
			component.UnSummonEffect.Create(val.transform.position, val.transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
		}
	}
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
	internal static class SummonerZdoScan
	{
		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)]
		private static HashSet<int> _prefabHashes;

		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(new byte[] { 2, 1 })]
		private static Dictionary<int, string> _prefabNames;

		private static void EnsureBuilt()
		{
			if (_prefabHashes != null && _prefabNames != null)
			{
				return;
			}
			HashSet<int> hashSet = new HashSet<int>();
			Dictionary<int, string> dictionary = new Dictionary<int, string>();
			foreach (string key in SummonerRegistry.All.Keys)
			{
				int stableHashCode = StringExtensionMethods.GetStableHashCode(key);
				hashSet.Add(stableHashCode);
				dictionary[stableHashCode] = key;
			}
			_prefabHashes = hashSet;
			_prefabNames = dictionary;
		}

		internal static bool IsSummonPrefab(int prefabHash)
		{
			if (prefabHash == 0)
			{
				return false;
			}
			EnsureBuilt();
			return _prefabHashes.Contains(prefabHash);
		}

		internal static void Collect(List<ZDO> result)
		{
			SummonerZdoIndex.CopyTo(result);
		}

		internal static string GetSummonPrefab(ZDO zdo)
		{
			string text = zdo.GetString("VS_SummonPrefab", string.Empty);
			if (!string.IsNullOrWhiteSpace(text))
			{
				return text;
			}
			EnsureBuilt();
			string value;
			return _prefabNames.TryGetValue(zdo.GetPrefab(), out value) ? value : string.Empty;
		}
	}
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
	internal static class SummonerSpawnAbilityScope
	{
		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(0)]
		private sealed class Marker
		{
		}

		private static readonly ConditionalWeakTable<SpawnAbility, Marker> Marked = new ConditionalWeakTable<SpawnAbility, Marker>();

		internal static bool TryGetSummonPrefabs(SpawnAbility sa, out List<GameObject> prefabs)
		{
			prefabs = new List<GameObject>();
			if ((Object)(object)sa == (Object)null || sa.m_spawnPrefab == null || sa.m_spawnPrefab.Length == 0)
			{
				return false;
			}
			for (int i = 0; i < sa.m_spawnPrefab.Length; i++)
			{
				GameObject val = sa.m_spawnPrefab[i];
				if (!Object.op_Implicit((Object)(object)val))
				{
					return false;
				}
				string prefabName = Utils.GetPrefabName(((Object)val).name);
				if (string.IsNullOrEmpty(prefabName))
				{
					return false;
				}
				if (!SummonerRegistry.All.ContainsKey(prefabName))
				{
					return false;
				}
				prefabs.Add(val);
			}
			return prefabs.Count > 0;
		}

		internal static bool IsMarked(SpawnAbility sa)
		{
			Marker value;
			return (Object)(object)sa != (Object)null && Marked.TryGetValue(sa, out value);
		}

		internal static void Mark(SpawnAbility sa)
		{
			if (!((Object)(object)sa == (Object)null))
			{
				Unmark(sa);
				Marked.Add(sa, new Marker());
			}
		}

		internal static void Unmark(SpawnAbility sa)
		{
			if (!((Object)(object)sa == (Object)null))
			{
				Marked.Remove(sa);
			}
		}
	}
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	internal static class SummonerSpawnAbilityContext
	{
		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(2)]
		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
		private sealed class SpawnSetupContext
		{
			internal Character Owner;

			internal ItemData Weapon;
		}

		private static readonly ConditionalWeakTable<SpawnAbility, SpawnSetupContext> Table = new ConditionalWeakTable<SpawnAbility, SpawnSetupContext>();

		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(2)]
		internal static void Set([<75331dbc-839c-437d-a413-c63e0024209e>Nullable(1)] SpawnAbility ability, Character owner, ItemData weapon)
		{
			if (!((Object)(object)ability == (Object)null))
			{
				Table.Remove(ability);
				Table.Add(ability, new SpawnSetupContext
				{
					Owner = owner,
					Weapon = weapon
				});
			}
		}

		[return: <75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)]
		internal static Character GetOwner(SpawnAbility ability)
		{
			SpawnSetupContext value;
			return ((Object)(object)ability != (Object)null && Table.TryGetValue(ability, out value)) ? value.Owner : null;
		}

		[return: <75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)]
		internal static ItemData GetWeapon(SpawnAbility ability)
		{
			SpawnSetupContext value;
			return ((Object)(object)ability != (Object)null && Table.TryGetValue(ability, out value)) ? value.Weapon : null;
		}

		internal static void Clear(SpawnAbility ability)
		{
			if (!((Object)(object)ability == (Object)null))
			{
				Table.Remove(ability);
			}
		}
	}
	[HarmonyPatch(typeof(SpawnAbility), "Setup")]
	internal static class SpawnAbility_Setup_SummonMark_Patch
	{
		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
		private static bool Prefix(SpawnAbility __instance, Character owner, ItemData item)
		{
			SummonerSpawnAbilityContext.Set(__instance, owner, item);
			if (SummonerSpawnAbility.ShouldBlockSetup(__instance, owner))
			{
				SummonerSpawnAbilityScope.Unmark(__instance);
				SummonerSpawnAbilityContext.Clear(__instance);
				SummonerSpawnAbility.DestroySpawnAbilityObject(__instance);
				return false;
			}
			SummonerSpawnAbility.TryMarkFromSetup(__instance);
			return true;
		}
	}
	[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(1)]
	[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
	internal static class SummonerSpawnAbility
	{
		[<8c367786-59d8-41b6-b7fa-84fc76a453fa>NullableContext(2)]
		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
		private readonly struct SpawnContext
		{
			[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(1)]
			internal readonly SpawnAbility Ability;

			internal readonly Character Owner;

			internal readonly ItemData Weapon;

			internal readonly Skills Skills;

			internal readonly float BloodMagic;

			[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(1)]
			internal readonly List<GameObject> Prefabs;

			internal SpawnContext([<75331dbc-839c-437d-a413-c63e0024209e>Nullable(1)] SpawnAbility ability, Character owner, ItemData weapon, Skills skills, float bloodMagic, [<75331dbc-839c-437d-a413-c63e0024209e>Nullable(1)] List<GameObject> prefabs)
			{
				Ability = ability;
				Owner = owner;
				Weapon = weapon;
				Skills = skills;
				BloodMagic = bloodMagic;
				Prefabs = prefabs;
			}
		}

		[<75331dbc-839c-437d-a413-c63e0024209e>Nullable(0)]
		private readonly struct ValidSummonPrefab
		{
			internal readonly GameObject Prefab;

			internal readonly string Name;

			internal readonly SummonerProgressionResult Progression;

			internal ValidSummonPrefab(GameObject prefab, string name, SummonerProgressionResult progression)
			{
				Prefab = prefab;
				Name = name;
				Progression = progression;
			}
		}

		private static void ShowInvalidProgressionMessage(Character owner)
		{
			Player val = (Player)(object)((owner is Player) ? owner : null);
			if (val != null)
			{
				((Character)val).Message((MessageType)2, "Invalid summon progression config.", 0, (Sprite)null, false);
			}
		}

		internal static bool ShouldBlockSetup(SpawnAbility sa, [<75331dbc-839c-437d-a413-c63e0024209e>Nullable(2)] Character owner)
		{
			if ((Object)(object)owner == (Object)null)
			{
				return false;
			}
			if (!SummonerSpawnAbilityScope.TryGetSummonPrefabs(sa, out var prefabs))
			{
				return false;
			}
			float num = ResolveRequiredBloodMagic(prefabs);
			if (num < 0f)
			{
				ShowInvalidProgressionMessage(owner);
				return true;
			}
			Skills skills = owner.GetSkills();
			if ((Object)(object)skills == (Object)null)
			{
				return false;
			}
			float skillLevel = skills.GetSkillLevel((SkillType)10);
			if (skillLevel >= num)
			{
				return false;
			}
			ShowBloodMagicGateMessage(owner, skillLevel, num);
			return true;
		}

		internal static bool TryMarkFromSetup(SpawnAbility sa)
		{
			SummonerSpawnAbilityScope.Unmark(sa);
			if (!SummonerSpawnAbilityScope.TryGetSummonPrefabs(sa, out var _))
			{
				return false;
			}
			SummonerSpawnAbilityScope.Mark(sa);
			return true;
		}

		internal static bool TryBuildSpawnOverride(SpawnAbility sa, ref IEnumerator result)
		{
			if (!SummonerSpawnAbilityScope.IsMarked(sa))
			{
				return false;
			}
			if (!SummonerSpawnAbilityScope.TryGetSummonPrefabs(sa, out var prefabs))
			{
				SummonerSpawnAbilityScope.Unmark(sa);
				SummonerSpawnAbilityContext.Clear(sa);
				result = AbortSpawn();
				return true;
			}
			result = SpawnOverride(BuildContext(sa, prefabs));
			return true;
		}

		private static SpawnContext BuildContext(SpawnAbility sa, List<GameObject> prefabs)
		{
			Character owner = SummonerSpawnAbilityContext.GetOwner(sa);
			ItemData weapon = SummonerSpawnAbilityContext.GetWeapon(sa);
			Skills val = (Object.op_Implicit((Object)(object)owner) ? owner.GetSkills() : null);
			float bloodMagic = (((Object)(object)val != (Object)null) ? val.GetSkillLevel((SkillType)10) : 0f);
			return new SpawnContext(sa, owner, weapon, val, bloodMagic, prefabs);
		}

		private static float ResolveRequiredBloodMagic(List<GameObject> prefabs)
		{
			int num = int.MaxValue;
			bool flag = false;
			for (int i = 0; i < prefabs.Count; i++)
			{
				string prefabName = Utils.GetPrefabName(((Object)prefabs[i]).name);
				if (string.IsNullOrEmpty(prefabName))
				{
					return -1f;
				}
				if (!SummonerProgression.TryGetGateFromConfig(prefabName, out var minGate))
				{
					return -1f;
				}
				if (!flag || minGate < num)
				{
					num = minGate;
					flag = true;
				}
			}
			return flag ? ((float)num) : (-1f);
		}

		private static void ShowBloodMagicGateMessage(Character owner, float have, float required)
		{
			Player val = (Player)(object)((owner is Player) ? owner : null);
			if (val != null)
			{
				int num = Mathf.FloorToInt(have);
				int num2 = Mathf.FloorToInt(required);
				string arg = $"<color=red><b>{num}</b></color>";
				string arg2 = $"<color=red><b>{num2}</b></color>";
				string format = Localization.instance.Localize("$vs_bm_gate_msg");
				string text = string.Format(format, arg, arg2);
				((Character)val).Message((MessageType)2, text, 0, (Sprite)null, false);
			}
		}

		private static void ShowBloodMagicGateMessageIfPossible(SpawnContext ctx)
		{
			if (!((Object)(object)ctx.Owner == (Object)null))
			{
				float num = ResolveRequiredBloodMagic(ctx.Prefabs);
				if (num < 0f)
				{
					ShowInvalidProgressionMessage(ctx.Owner);
				}
				else
				{
					ShowBloodMagicGateMessage(ctx.Owner, ctx.BloodMagic, num);
				}
			}
		}

		private static IEnumerator AbortSpawn()
		{
			yield break;
		}

		private static IEnumerator SpawnOverride(SpawnContext ctx)
		{
			try
			{
				SpawnAbility sa = ctx.Ability;
				if (sa.m_initialSpawnDelay > 0f)
				{
					yield return (object)new WaitForSeconds(sa.m_initialSpawnDelay);
				}
				int toSpawn = Random.Range(sa.m_minToSpawn, sa.m_maxToSpawn);
				int i = 0;
				while (i < toSpawn)
				{
					IEnumerator step = SpawnOne(ctx, i, toSpawn);
					while (step.MoveNext())
					{
						yield return step.Current;
					}
					int num = i + 1;
					i = num;
				}
			}
			finally
			{
				SummonerSpawnAbilityScope.Unmark(ctx.Ability);
				SummonerSpawnAbilityContext.Clear(ctx.Ability);
				DestroySpawnAbilityObjectIfNeeded(ctx.Ability);
			}
		}

		private static IEnumerator SpawnOne(SpawnContext ctx, int index, int spawnCount)
		{
			SpawnAbility sa = ctx.Ability;
			if (!TryResolveSpawnPoint(ctx, index, spawnCount, out var targetPosition, out var spawnPoint))
			{
				yield break;
			}
			if (!TrySelectSummonPrefab(ctx.Prefabs, ctx.BloodMagic, out var prefab, out var summonPrefab, out var progression))
			{
				ShowBloodMagicGateMessageIfPossible(ctx);
				yield break;
			}
			int finalMaxInstances = SummonerSummonExtra.ApplyExtraMaxSummons(ctx.Owner, progression.MaxInstances);
			float finalLifetime = SummonerLifetimeUpgradeTotem.GetFinalLifetimeSeconds(summonPrefab, ctx.Owner, ctx.Weapon);
			sa.m_preSpawnEffects.Create(spawnPoint, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			if (sa.m_preSpawnDelay > 0f)
			{
				yield return (object)new WaitForSeconds(sa.m_preSpawnDelay);
			}
			GameObject go = SpawnSummonInstance(prefab, spawnPoint);
			if (Object.op_Implicit((Object)(object)go))
			{
				ApplyLifetime(go, finalLifetime);
				ApplyRandomYRotation(sa, go);
				SetupSpawnedProjectile(sa, ctx.Owner, go, targetPosition);
				ApplyCopiedSkillFactor(sa, ctx.Skills, go);
				ApplyProgression(go, new SummonerProgressionResult(progression.SummonLevel, finalMaxInstances));
				SummonerState.Begin(go, ctx.Owner, summonPrefab, finalMaxInstances);
				RegisterPlayerSummonStat(sa, ctx.Owner);
				ApplyWakeupAnimation(sa, go);
				ApplyAiState(sa, go);
				SetupAoe(sa, go.GetComponent<Character>(), spawnPoint);
				sa.m_spawnEffects.Create(spawnPoint, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
				if (sa.m_spawnDelay > 0f)
				{
					yield return (object)new WaitForSeconds(sa.m_spawnDelay);
				}
			}
		}

		private static bool TryResolveSpawnPoint(SpawnContext ctx, int index, int spawnCount, out Vector3 targetPosition, out Vector3 spawnPoint)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			SpawnAbility ability = ctx.Ability;
			targetPosition = ((Component)ability).transform.position;
			spawnPoint = targetPosition;
			if (!TryResolveTargetPosition(ctx, index, spawnCount, out targetPosition))
			{
				return false;
			}
			return TryResolveFinalSpawnPoint(ability, targetPosition, index, spawnCount, out spawnPoint);
		}

		private static bool TryResolveTargetPosition(SpawnContext ctx, int index, int spawnCount, out Vector3 targetPosition)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Invalid comparison between Unknown and I4
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			SpawnAbility ability = ctx.Ability;
			targetPosition = ((Component)ability).transform.position;
			bool result = false;
			int num = (((int)ability.m_targetType != 4) ? 1 : 5);
			for (int i = 0; i < num; i++)
			{
				if (result = FindTarget(ability, ctx.Owner, out targetPosition, index, spawnCount))
				{
					break;
				}
				if ((int)ability.m_targetType == 4 && i == num - 1)
				{
					targetPosition = ((Component)ability).transform.position;
					result = true;
				}
			}
			return result;
		}

		private static bool TryResolveFinalSpawnPoint(SpawnAbility sa, Vector3 targetPosition, int index, int spawnCount, out Vector3 spawnPoint)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid I