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 Revive API v1.3.4
plugins/ReviveAPI.dll
Decompiled 4 months 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(); } } }