Some mods may be broken due to the recent Alloyed Collective update.
Decompiled source of Revive API v1.3.4
plugins/ReviveAPI.dll
Decompiled 2 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using HG.Reflection; using HarmonyLib; using IL.RoR2; using IL.RoR2.Artifacts; using Microsoft.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; using MonoMod.Cil; using On.RoR2; using RoR2; using RoR2.Artifacts; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: OptIn] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ReviveAPI")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+74e3eac968abd412176e0aefd8ceb676b02d1e53")] [assembly: AssemblyProduct("ReviveAPI")] [assembly: AssemblyTitle("ReviveAPI")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ReviveAPI { [Serializable] [BepInPlugin("com.brynzananas.reviveapi", "Revive API", "1.3.4")] public class ReviveAPI : BaseUnityPlugin { public delegate bool CanReviveDelegate(CharacterMaster characterMaster); public delegate bool CanReviveNewDelegate(CharacterMaster characterMaster, out CanReviveInfo canReviveInfo); public delegate void OnReviveDelegate(CharacterMaster characterMaster); public delegate void OnReviveNewDelegate(CharacterMaster characterMaster, CanReviveInfo canReviveInfo); public class CanReviveInfo { public CanTakeResult canTakeResult; } public class CustomRevive { [Obsolete("Use canReviveNew instead")] public CanReviveDelegate canRevive; public CanReviveNewDelegate canReviveNew; public OnReviveDelegate onRevive; public OnReviveNewDelegate onReviveNew; public PendingOnRevive[] pendingOnRevives; public int priority; } public class PendingOnRevive { internal CharacterMaster characterMaster; public float timer; public OnReviveDelegate onReviveDelegate; } public const string ModGuid = "com.brynzananas.reviveapi"; public const string ModName = "Revive API"; public const string ModVer = "1.3.4"; public const bool ENABLE_TEST = false; public static ManualLogSource ManualLogger; private static List<PendingOnRevive> pendingRevives = new List<PendingOnRevive>(); private static List<CustomRevive> customRevives = new List<CustomRevive>(); private bool hooksSet; private static CanReviveInfo canReviveInfoGlobal; private static CustomRevive customReviveGlobal; public static PendingOnRevive[] defaultPendingOnRevives { get { PendingOnRevive pendingOnRevive = new PendingOnRevive(); pendingOnRevive.timer = 2f; pendingOnRevive.onReviveDelegate = SimpleRespawn; PendingOnRevive pendingOnRevive2 = pendingOnRevive; pendingOnRevive = new PendingOnRevive(); pendingOnRevive.timer = 2f; pendingOnRevive.onReviveDelegate = SimpleRespawnSound; PendingOnRevive pendingOnRevive3 = pendingOnRevive; return new PendingOnRevive[2] { pendingOnRevive2, pendingOnRevive3 }; } } public void Awake() { ManualLogger = ((BaseUnityPlugin)this).Logger; SetHooks(); } public void FixedUpdate() { for (int i = 0; i < pendingRevives.Count; i++) { PendingOnRevive pendingOnRevive = pendingRevives[i]; pendingOnRevive.timer -= Time.fixedDeltaTime; if (pendingOnRevive.timer <= 0f) { pendingRevives.Remove(pendingOnRevive); if (Object.op_Implicit((Object)(object)pendingOnRevive.characterMaster)) { pendingOnRevive.onReviveDelegate?.Invoke(pendingOnRevive.characterMaster); } } } } public static void SimpleRespawn(CharacterMaster characterMaster) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) Vector3 val = characterMaster.deathFootPosition; if (characterMaster.killedByUnsafeArea) { val = (Vector3)(((??)TeleportHelper.FindSafeTeleportDestination(characterMaster.deathFootPosition, characterMaster.bodyPrefab.GetComponent<CharacterBody>(), RoR2Application.rng)) ?? characterMaster.deathFootPosition); } characterMaster.Respawn(val, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f), true); } public static void SimpleRespawnSound(CharacterMaster characterMaster) { characterMaster.PlayExtraLifeSFX(); } public void Destroy() { UnsetHooks(); } private void SetHooks() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown if (!hooksSet) { TeamDeathArtifactManager.OnServerCharacterDeathGlobal += new Manipulator(TeamDeathArtifactManager_OnServerCharacterDeathGlobal); DoppelgangerInvasionManager.OnCharacterDeathGlobal += new Manipulator(DoppelgangerInvasionManager_OnCharacterDeathGlobal); CharacterMaster.IsDeadAndOutOfLivesServer += new Manipulator(CharacterMaster_IsDeadAndOutOfLivesServer); CharacterMaster.IsExtraLifePendingServer += new hook_IsExtraLifePendingServer(CharacterMaster_IsExtraLifePendingServer); CharacterMaster.TryReviveOnBodyDeath += new hook_TryReviveOnBodyDeath(CharacterMaster_TryReviveOnBodyDeath); hooksSet = true; } } private bool CharacterMaster_TryReviveOnBodyDeath(orig_TryReviveOnBodyDeath orig, CharacterMaster self, CharacterBody body) { if (CanReviveBeforeVanilla(self)) { return ReviveBeforeVanilla(self); } bool flag = orig.Invoke(self, body); if (!flag && CanReviveAfterVanilla(self)) { flag = ReviveAfterVanilla(self); } return flag; } private void UnsetHooks() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown if (hooksSet) { TeamDeathArtifactManager.OnServerCharacterDeathGlobal -= new Manipulator(TeamDeathArtifactManager_OnServerCharacterDeathGlobal); DoppelgangerInvasionManager.OnCharacterDeathGlobal -= new Manipulator(DoppelgangerInvasionManager_OnCharacterDeathGlobal); CharacterMaster.IsDeadAndOutOfLivesServer -= new Manipulator(CharacterMaster_IsDeadAndOutOfLivesServer); CharacterMaster.IsExtraLifePendingServer -= new hook_IsExtraLifePendingServer(CharacterMaster_IsExtraLifePendingServer); CharacterMaster.TryReviveOnBodyDeath -= new hook_TryReviveOnBodyDeath(CharacterMaster_TryReviveOnBodyDeath); hooksSet = false; } } private bool CharacterMaster_IsExtraLifePendingServer(orig_IsExtraLifePendingServer orig, CharacterMaster self) { bool flag = orig.Invoke(self); if (!flag) { flag = pendingRevives.Where((PendingOnRevive x) => (Object)(object)x.characterMaster == (Object)(object)self).ToArray().Length != 0; } return flag; } private void TeamDeathArtifactManager_OnServerCharacterDeathGlobal(ILContext iLContext) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Expected O, but got Unknown //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(iLContext); ILLabel val2 = null; if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchLdsfld(x, typeof(TeamDeathArtifactManager), "forceSpectatePrefab") })) { val2 = val.DefineLabel(); val2.Target = val.Prev; } else { ((BaseUnityPlugin)this).Logger.LogError((object)(((MemberReference)iLContext.Method).Name + " finding forceSpectatePrefab label IL Hook failed!")); } val = new ILCursor(iLContext); ILLabel beforeCheck = null; if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[5] { (Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0), (Instruction x) => ILPatternMatchingExt.MatchLdfld(x, typeof(DamageReport), "victimMaster"), (Instruction x) => ILPatternMatchingExt.MatchCallvirt<CharacterMaster>(x, "get_playerCharacterMasterController"), (Instruction x) => ILPatternMatchingExt.MatchCall<Object>(x, "op_Implicit"), (Instruction x) => ILPatternMatchingExt.MatchBrfalse(x, ref beforeCheck) })) { val.Emit(OpCodes.Ldarg_0); val.Emit(OpCodes.Ldfld, AccessTools.Field(typeof(DamageReport), "victimMaster")); val.EmitDelegate<Func<CharacterMaster, bool>>((Func<CharacterMaster, bool>)CanReviveBeforeVanilla); val.Emit(OpCodes.Brtrue_S, (object)beforeCheck); } else { ((BaseUnityPlugin)this).Logger.LogError((object)(((MemberReference)iLContext.Method).Name + " before IL Hook failed!")); } val = new ILCursor(iLContext); ILLabel afterCheck = null; if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[5] { (Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0), (Instruction x) => ILPatternMatchingExt.MatchLdfld(x, typeof(DamageReport), "victimMaster"), (Instruction x) => ILPatternMatchingExt.MatchLdfld(x, typeof(CharacterMaster), "seekerSelfRevive"), (Instruction x) => ILPatternMatchingExt.MatchBrfalse(x, ref afterCheck), (Instruction x) => ILPatternMatchingExt.MatchRet(x) })) { Instruction prev = val.Emit(OpCodes.Ldarg_0).Prev; val.Emit(OpCodes.Ldfld, AccessTools.Field(typeof(DamageReport), "victimMaster")); val.EmitDelegate<Func<CharacterMaster, bool>>((Func<CharacterMaster, bool>)CanReviveAfterVanilla); val.Emit(OpCodes.Brfalse_S, (object)val2); afterCheck.Target = prev; val.Emit(OpCodes.Ret); } else { ((BaseUnityPlugin)this).Logger.LogError((object)(((MemberReference)iLContext.Method).Name + " after IL Hook failed!")); } } private void CharacterMaster_IsDeadAndOutOfLivesServer(ILContext iLContext) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: 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) ILCursor val = new ILCursor(iLContext); ILLabel iLLabel = null; if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[4] { (Instruction x) => ILPatternMatchingExt.MatchLdsfld(x, typeof(Items), "ExtraLife"), (Instruction x) => ILPatternMatchingExt.MatchCallvirt<Inventory>(x, "GetItemCountEffective"), (Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, 0), (Instruction x) => ILPatternMatchingExt.MatchBgt(x, ref iLLabel) })) { val.Emit(OpCodes.Ldarg_0); val.Emit(OpCodes.Ldc_I4_0); val.Emit(OpCodes.Ldc_I4_0); val.EmitDelegate<Func<CharacterMaster, bool, bool, bool>>((Func<CharacterMaster, bool, bool, bool>)CanReviveAndOrRevive); val.Emit(OpCodes.Brtrue_S, (object)iLLabel); } else { ((BaseUnityPlugin)this).Logger.LogError((object)(((MemberReference)iLContext.Method).Name + " IL Hook failed!")); } } private void DoppelgangerInvasionManager_OnCharacterDeathGlobal(ILContext iLContext) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_00bf: 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_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Expected O, but got Unknown //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(iLContext); ILLabel returnLabel = null; if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[5] { (Instruction x) => ILPatternMatchingExt.MatchLdloc(x, 0), (Instruction x) => ILPatternMatchingExt.MatchLdsfld(x, typeof(Items), "InvadingDoppelganger"), (Instruction x) => ILPatternMatchingExt.MatchCallvirt<Inventory>(x, "GetItemCountEffective"), (Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, 0), (Instruction x) => ILPatternMatchingExt.MatchBle(x, ref returnLabel) })) { val.Emit(OpCodes.Ldarg_1); val.Emit(OpCodes.Ldfld, AccessTools.Field(typeof(DamageReport), "victimMaster")); val.EmitDelegate<Func<CharacterMaster, bool>>((Func<CharacterMaster, bool>)CanReviveBeforeVanilla); val.Emit(OpCodes.Brtrue_S, (object)returnLabel); } else { ((BaseUnityPlugin)this).Logger.LogError((object)(((MemberReference)iLContext.Method).Name + " before IL Hook failed!")); } val = new ILCursor(iLContext); ILLabel iLLabel = null; if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[7] { (Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 1), (Instruction x) => ILPatternMatchingExt.MatchLdfld(x, typeof(DamageReport), "victimBody"), (Instruction x) => ILPatternMatchingExt.MatchCallvirt<CharacterBody>(x, "get_equipmentSlot"), (Instruction x) => ILPatternMatchingExt.MatchCallvirt<EquipmentSlot>(x, "get_equipmentIndex"), (Instruction x) => ILPatternMatchingExt.MatchLdsfld(x, typeof(Equipment), "HealAndRevive"), (Instruction x) => ILPatternMatchingExt.MatchCallvirt<EquipmentDef>(x, "get_equipmentIndex"), (Instruction x) => ILPatternMatchingExt.MatchBeq(x, ref iLLabel) })) { val.Emit(OpCodes.Ldarg_1); val.Emit(OpCodes.Ldfld, AccessTools.Field(typeof(DamageReport), "victimMaster")); val.EmitDelegate<Func<CharacterMaster, bool>>((Func<CharacterMaster, bool>)CanReviveAfterVanilla); val.Emit(OpCodes.Brtrue_S, (object)iLLabel); } else { ((BaseUnityPlugin)this).Logger.LogError((object)(((MemberReference)iLContext.Method).Name + " after IL Hook failed!")); } } private void CharacterMaster_OnBodyDeath(ILContext iLContext) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Expected O, but got Unknown //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0406: Unknown result type (might be due to invalid IL or missing references) //IL_043d: Unknown result type (might be due to invalid IL or missing references) //IL_044b: Unknown result type (might be due to invalid IL or missing references) //IL_0479: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(iLContext); Instruction val2 = null; Instruction val3 = null; ILLabel ilLabel = null; int num = default(int); ILLabel val6 = default(ILLabel); if (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[4] { (Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0), (Instruction x) => ILPatternMatchingExt.MatchLdloca(x, ref num), (Instruction x) => ILPatternMatchingExt.MatchCall<Component>(x, "TryGetComponent"), (Instruction x) => ILPatternMatchingExt.MatchBrfalse(x, ref val6) })) { val2 = val.Next; } else { ((BaseUnityPlugin)this).Logger.LogError((object)(((MemberReference)iLContext.Method).Name + " IL hook 1 failed!")); } val = new ILCursor(iLContext); ILLabel val5 = default(ILLabel); if (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[4] { (Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 1), (Instruction x) => ILPatternMatchingExt.MatchLdsfld(x, typeof(Buffs), "ExtraLifeBuff"), (Instruction x) => ILPatternMatchingExt.MatchCallvirt<CharacterBody>(x, "HasBuff"), (Instruction x) => ILPatternMatchingExt.MatchBrfalse(x, ref val5) })) { val3 = val.Next; val.Emit(OpCodes.Ldarg_0); val.EmitDelegate<Func<CharacterMaster, bool>>((Func<CharacterMaster, bool>)CanReviveBeforeVanilla); val.Emit(OpCodes.Brfalse_S, val3); val.Emit(OpCodes.Ldarg_0); val.EmitDelegate<Func<CharacterMaster, bool>>((Func<CharacterMaster, bool>)ReviveBeforeVanilla); val.Emit(OpCodes.Brtrue_S, val2); } else { ((BaseUnityPlugin)this).Logger.LogError((object)(((MemberReference)iLContext.Method).Name + " IL hook 2 failed!")); } val = new ILCursor(iLContext); ILLabel val4 = default(ILLabel); if (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[6] { (Instruction x) => ILPatternMatchingExt.MatchLdloca(x, 5), (Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0), (Instruction x) => ILPatternMatchingExt.MatchCall<CharacterMaster>(x, "get_inventory"), (Instruction x) => ILPatternMatchingExt.MatchLdloca(x, 1), (Instruction x) => ILPatternMatchingExt.MatchCall<ItemTransformation>(x, "TryTake"), (Instruction x) => ILPatternMatchingExt.MatchBrfalse(x, ref val4) }) && val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[6] { (Instruction x) => ILPatternMatchingExt.MatchLdloca(x, 5), (Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0), (Instruction x) => ILPatternMatchingExt.MatchCall<CharacterMaster>(x, "get_inventory"), (Instruction x) => ILPatternMatchingExt.MatchLdloca(x, 1), (Instruction x) => ILPatternMatchingExt.MatchCall<ItemTransformation>(x, "TryTake"), (Instruction x) => ILPatternMatchingExt.MatchBrfalse(x, ref ilLabel) })) { Instruction target = ilLabel.Target; val.GotoLabel(ilLabel, (MoveType)0, false); ilLabel.Target = val.Emit(OpCodes.Ldarg_0).Prev; val.EmitDelegate<Func<CharacterMaster, bool>>((Func<CharacterMaster, bool>)CanReviveAfterVanilla); val.Emit(OpCodes.Brfalse_S, target); val.Emit(OpCodes.Ldarg_0); val.EmitDelegate<Func<CharacterMaster, bool>>((Func<CharacterMaster, bool>)ReviveAfterVanilla); val.Emit(OpCodes.Brtrue_S, val2); } else { ((BaseUnityPlugin)this).Logger.LogError((object)(((MemberReference)iLContext.Method).Name + " IL hook 3 failed!")); } } private static bool CanReviveBeforeVanilla(CharacterMaster characterMaster) { return CanRevive(characterMaster, customRevives.Where((CustomRevive item) => item.priority > 0).ToArray()); } private static bool CanReviveAfterVanilla(CharacterMaster characterMaster) { return CanRevive(characterMaster, customRevives.Where((CustomRevive item) => item.priority <= 0).ToArray()); } private static bool CanRevive(CharacterMaster characterMaster, CustomRevive[] customRevives) { foreach (CustomRevive customRevive in customRevives) { if (customRevive.canRevive != null && customRevive.canRevive(characterMaster)) { return true; } if (customRevive.canReviveNew != null && customRevive.canReviveNew(characterMaster, out var canReviveInfo)) { canReviveInfoGlobal = canReviveInfo; return true; } } return false; } private static bool ReviveBeforeVanilla(CharacterMaster characterMaster) { return Revive(characterMaster, customRevives.Where((CustomRevive item) => item.priority > 0).ToArray()); } private static bool ReviveAfterVanilla(CharacterMaster characterMaster) { return Revive(characterMaster, customRevives.Where((CustomRevive item) => item.priority <= 0).ToArray()); } private static bool Revive(CharacterMaster characterMaster, CustomRevive[] customRevives) { foreach (CustomRevive customRevive in customRevives) { if (customRevive.canRevive != null && customRevive.canRevive(characterMaster)) { customRevive.onRevive?.Invoke(characterMaster); if (customRevive.pendingOnRevives != null) { HandlePendingOnRevives(customRevive, characterMaster); } return true; } if (customRevive.canReviveNew != null && customRevive.canReviveNew(characterMaster, out canReviveInfoGlobal)) { customRevive.onReviveNew?.Invoke(characterMaster, canReviveInfoGlobal); if (customRevive.pendingOnRevives != null) { HandlePendingOnRevives(customRevive, characterMaster); } return true; } } return false; } private static void HandlePendingOnRevives(CustomRevive customRevive, CharacterMaster characterMaster) { PendingOnRevive[] pendingOnRevives = customRevive.pendingOnRevives; foreach (PendingOnRevive pendingOnRevive in pendingOnRevives) { PendingOnRevive item = new PendingOnRevive { timer = Mathf.Max(1f, pendingOnRevive.timer), characterMaster = characterMaster, onReviveDelegate = pendingOnRevive.onReviveDelegate }; pendingRevives.Add(item); } } private static bool CanReviveAndOrRevive(CharacterMaster characterMaster, bool reverse, bool onRevive) { bool flag = reverse; foreach (CustomRevive customRevife in customRevives) { if (customRevife.canRevive == null || !customRevife.canRevive(characterMaster)) { continue; } flag = !flag; if (!onRevive) { break; } customRevife.onRevive?.Invoke(characterMaster); if (customRevife.pendingOnRevives != null) { PendingOnRevive[] pendingOnRevives = customRevife.pendingOnRevives; foreach (PendingOnRevive pendingOnRevive in pendingOnRevives) { PendingOnRevive item = new PendingOnRevive { timer = Mathf.Max(1f, pendingOnRevive.timer), characterMaster = characterMaster, onReviveDelegate = pendingOnRevive.onReviveDelegate }; pendingRevives.Add(item); } } break; } return flag; } public static void AddCustomRevive(CanReviveNewDelegate canReviveNewDelegate, int priority) { CustomRevive customRevive = new CustomRevive { canReviveNew = canReviveNewDelegate, pendingOnRevives = defaultPendingOnRevives, priority = priority }; AddCustomRevive(customRevive); } public static void AddCustomRevive(CanReviveNewDelegate canReviveNewDelegate, OnReviveNewDelegate onReviveNewDelegate, int priority) { CustomRevive customRevive = new CustomRevive { canReviveNew = canReviveNewDelegate, onReviveNew = onReviveNewDelegate, pendingOnRevives = null, priority = priority }; AddCustomRevive(customRevive); } public static void AddCustomRevive(CanReviveNewDelegate canReviveNewDelegate, OnReviveNewDelegate onReviveNewDelegate, PendingOnRevive[] pendingOnRevives, int priority) { CustomRevive customRevive = new CustomRevive { canReviveNew = canReviveNewDelegate, onReviveNew = onReviveNewDelegate, pendingOnRevives = pendingOnRevives, priority = priority }; AddCustomRevive(customRevive); } public static void AddCustomRevive(CanReviveNewDelegate canReviveNewDelegate) { CustomRevive customRevive = new CustomRevive { canReviveNew = canReviveNewDelegate, pendingOnRevives = defaultPendingOnRevives, priority = -1 }; AddCustomRevive(customRevive); } public static void AddCustomRevive(CanReviveNewDelegate canReviveNewDelegate, OnReviveNewDelegate onReviveNewDelegate) { CustomRevive customRevive = new CustomRevive { canReviveNew = canReviveNewDelegate, onReviveNew = onReviveNewDelegate, pendingOnRevives = null, priority = -1 }; AddCustomRevive(customRevive); } public static void AddCustomRevive(CanReviveNewDelegate canReviveNewDelegate, PendingOnRevive[] pendingOnRevives) { CustomRevive customRevive = new CustomRevive { canReviveNew = canReviveNewDelegate, pendingOnRevives = pendingOnRevives, priority = -1 }; AddCustomRevive(customRevive); } public static void AddCustomRevive(CanReviveNewDelegate canReviveNewDelegate, OnReviveNewDelegate onReviveNewDelegate, PendingOnRevive[] pendingOnRevives) { CustomRevive customRevive = new CustomRevive { canReviveNew = canReviveNewDelegate, onReviveNew = onReviveNewDelegate, pendingOnRevives = pendingOnRevives, priority = -1 }; AddCustomRevive(customRevive); } public static void AddCustomRevive(CanReviveDelegate canReviveDelegate, int priority) { CustomRevive customRevive = new CustomRevive { canRevive = canReviveDelegate, pendingOnRevives = defaultPendingOnRevives, priority = priority }; AddCustomRevive(customRevive); } public static void AddCustomRevive(CanReviveDelegate canReviveDelegate, OnReviveDelegate onReviveDelegate, int priority) { CustomRevive customRevive = new CustomRevive { canRevive = canReviveDelegate, onRevive = onReviveDelegate, pendingOnRevives = defaultPendingOnRevives, priority = priority }; AddCustomRevive(customRevive); } public static void AddCustomRevive(CanReviveDelegate canReviveDelegate, PendingOnRevive[] pendingOnRevives, int priority) { CustomRevive customRevive = new CustomRevive { canRevive = canReviveDelegate, pendingOnRevives = pendingOnRevives, priority = priority }; AddCustomRevive(customRevive); } public static void AddCustomRevive(CanReviveDelegate canReviveDelegate, OnReviveDelegate onReviveDelegate, PendingOnRevive[] pendingOnRevives, int priority) { CustomRevive customRevive = new CustomRevive { canRevive = canReviveDelegate, onRevive = onReviveDelegate, pendingOnRevives = pendingOnRevives, priority = priority }; AddCustomRevive(customRevive); } public static void AddCustomRevive(CanReviveDelegate canReviveDelegate) { CustomRevive customRevive = new CustomRevive { canRevive = canReviveDelegate, pendingOnRevives = defaultPendingOnRevives, priority = -1 }; AddCustomRevive(customRevive); } public static void AddCustomRevive(CanReviveDelegate canReviveDelegate, OnReviveDelegate onReviveDelegate) { CustomRevive customRevive = new CustomRevive { canRevive = canReviveDelegate, onRevive = onReviveDelegate, pendingOnRevives = defaultPendingOnRevives, priority = -1 }; AddCustomRevive(customRevive); } public static void AddCustomRevive(CanReviveDelegate canReviveDelegate, PendingOnRevive[] pendingOnRevives) { CustomRevive customRevive = new CustomRevive { canRevive = canReviveDelegate, pendingOnRevives = pendingOnRevives, priority = -1 }; AddCustomRevive(customRevive); } public static void AddCustomRevive(CanReviveDelegate canReviveDelegate, OnReviveDelegate onReviveDelegate, PendingOnRevive[] pendingOnRevives) { CustomRevive customRevive = new CustomRevive { canRevive = canReviveDelegate, onRevive = onReviveDelegate, pendingOnRevives = pendingOnRevives, priority = -1 }; AddCustomRevive(customRevive); } public static void AddCustomRevive(CustomRevive customRevive) { customRevives.Add(customRevive); customRevives = customRevives.OrderByDescending((CustomRevive x) => x.priority).ToList(); } } }