Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Vikings Summoner v1.5.4
plugins/Vikings_Summoner.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
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