using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Nyxpiri.Collections.Generic; using Nyxpiri.ULTRAKILL.NyxLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyVersion("0.0.0.0")] namespace Nyxpiri.ULTRAKILL.Hydra; internal static class Log { private static ManualLogSource _logger; public static void Initialize(ManualLogSource logger) { Assert.IsNull((object)_logger, "Log.Initialize called when _logger wasn't null?"); _logger = logger; } public static void Fatal(object data) { _logger.LogFatal(data); } public static void Error(object data) { _logger.LogError(data); } public static void Warning(object data) { _logger.LogWarning(data); } public static void Message(object data) { _logger.LogMessage(data); } public static void Info(object data) { _logger.LogInfo(data); } public static void Debug(object data) { if (Options.LogDebugInfo.Value) { _logger.LogDebug(data); } } } public static class HydraDupeQueue { public struct QueuedDupeInfo { public Vector3 Position; public Quaternion Rotation; public Vector3 LocalScale; public EnemyHydra.SharedData SharedData; public EnemyCloneStore CloneStore; public int Depth; public EnemyType EnemyType; public Transform CloneParent; public bool BossBar; } public static int InstantiatedThisTick = 0; public static ulong NumFixedUpdates = 0uL; private static Queue DupeQueue = new Queue(256); private static Stack ImmediatelyDupeStack = new Stack(256); public static void Initialize() { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown EnemyEvents.PreDeath = (Action)Delegate.Combine(EnemyEvents.PreDeath, new Action(PreEnemyDeath)); EnemyEvents.PreDeath = (Action)Delegate.Combine(EnemyEvents.PreDeath, (Action)delegate(EnemyComponents eid, bool instakill) { GameObject gameObject = ((Component)eid).gameObject; EnemyComponents component = gameObject.GetComponent(); EnemyHydra hydraComp = component.GetHydraComp(); hydraComp.NotifyOfDeath(instakill); }); EnemyEvents.Death = (Action)Delegate.Combine(EnemyEvents.Death, new Action(DuringEnemyDeath)); EnemyEvents.PostDeath = (Action)Delegate.Combine(EnemyEvents.PostDeath, new Action(PostEnemyDeath)); UpdateEvents.OnLateUpdate += new OnLateUpdateEventHandler(LateUpdate); UpdateEvents.OnFixedUpdate += new OnFixedUpdateEventHandler(FixedUpdate); } private static void FixedUpdate() { if (Cheats.IsCheatDisabled("nyxpiri.hydra-mode")) { return; } for (int i = InstantiatedThisTick; i < Options.HydraMaxPerUpdate.Value; i++) { if (DupeQueue.Count == 0) { break; } QueuedDupeInfo dupeInfo = DupeQueue.Dequeue(); InstantiateDupe(dupeInfo); } InstantiatedThisTick = 0; NumFixedUpdates++; } public static void EnqueueDupe(QueuedDupeInfo dupeInfo) { if (InstantiatedThisTick >= Options.HydraMaxPerUpdate.Value) { DupeQueue.Enqueue(dupeInfo); } else { ImmediatelyDupeStack.Push(dupeInfo); } } private static void PreEnemyDeath(EnemyComponents enemy, bool instakill) { GameObject gameObject = ((Component)enemy).gameObject; EnemyHydra hydraComp = enemy.GetHydraComp(); hydraComp.NotifyOfDeath(instakill); } private static void PostEnemyDeath(EnemyComponents enemy, bool instakill) { } private static void DuringEnemyDeath(EnemyComponents enemy) { GameObject gameObject = ((Component)enemy).gameObject; EnemyHydra hydraComp = enemy.GetHydraComp(); hydraComp.NotifyOfDeath(instakill: false); hydraComp.DuringDeath(); } private static void LateUpdate() { if (!Cheats.IsCheatDisabled("nyxpiri.hydra-mode")) { while (ImmediatelyDupeStack.Count > 0) { InstantiateDupe(ImmediatelyDupeStack.Pop()); } } } public static void InstantiateDupe(QueuedDupeInfo dupeInfo) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) InstantiatedThisTick++; GameObject val = dupeInfo.CloneStore.GetNewInstance(dupeInfo.CloneParent); GameObject val2 = null; EnemyComponents val3; if ((int)dupeInfo.EnemyType == 4) { val2 = val; val3 = val.GetComponentInChildren(); Assert.IsNotNull((Object)(object)val3, ""); val = ((Component)val3).gameObject; } else { Assert.IsNotNull((Object)(object)val, ""); val3 = val.GetComponent(); } val.transform.position = dupeInfo.Position; val.transform.rotation = dupeInfo.Rotation; val.SetActive(true); if (val2 != null) { val2.SetActive(true); } EnemyIdentifier component = val.GetComponent(); component.spawnIn = false; component.timeSinceSpawned = TimeSince.op_Implicit(0f); Assert.IsNotNull((Object)(object)val3, ""); Assert.IsNotNull((Object)(object)val3.GetHydraComp(), ""); Assert.IsNotNull((Object)(object)val3.GetHydraComp().Shared, ""); val3.GetHydraComp().Depth = dupeInfo.Depth; if (dupeInfo.BossBar) { component.BossBar(true); } dupeInfo.CloneStore.RemoveReservation(); } } public static class EnemyHydraEnemyComponentsExtension { public static EnemyHydra GetHydraComp(this EnemyComponents enemy) { return enemy.GetMonoByIndex(EnemyHydra.MonoRegistrarIdx); } } public class EnemyHydra : MonoBehaviour { public class SharedData : ScriptableObject { private ReserveList Instances = new ReserveList(16); public bool CountAsKill = false; public Bounds Bounds = default(Bounds); public Action OnDeactivated = null; internal string CreatorName = ""; public ScriptableObject EnemySpecificShared = null; private static int SharedIDIncrementer; public int InstanceCount => Instances.Count; public int GlobalIdx { get; private set; } = -1; public bool Active { get; private set; } = false; protected SharedData() { }//IL_001a: Unknown result type (might be due to invalid IL or missing references) internal void UnregisterInstance(int sharedIdx) { Instances.RemoveAt(sharedIdx); if (InstanceCount == 0) { Deactivate(); } } internal int RegisterInstance(GameObject gameObject) { int result = Instances.Add(gameObject); if (!Active) { Activate(); } return result; } private void Deactivate() { Assert.IsTrue(Active, ""); Log.Debug("EnemyHydraMod.SharedData '" + ((Object)this).name + "' with creator '" + CreatorName + "' deactivated!"); OnDeactivated?.Invoke(); Active = false; } private void Activate() { Assert.IsFalse(Active, ""); Log.Debug("EnemyHydraMod.SharedData '" + ((Object)this).name + "' with creator '" + CreatorName + "' activated!"); Active = true; } private void Awake() { ((Object)this).name = ((Object)this).name + SharedIDIncrementer; SharedIDIncrementer++; Log.Debug("EnemyHydraMod.SharedData '" + ((Object)this).name + "' with creator '" + CreatorName + "' awakened!"); } private void OnDestroy() { Log.Debug("EnemyHydraMod.SharedData '" + ((Object)this).name + "' with creator '" + CreatorName + "' destroyed!"); if (Active) { Deactivate(); } } } public SharedData Shared = null; public int Depth = -1; [NonSerialized] public EnemyIdentifier Eid = null; [NonSerialized] public EnemyComponents Enemy = null; public EnemyGameplayRank GameplayRank = (EnemyGameplayRank)3; [NonSerialized] public bool ContributesToInstanceCount = false; [NonSerialized] public Action PreDeath = null; private bool _excludedFromHydraCheat = false; private float NoDupeTime = 0f; private bool NotifiedOfDeathCalled = false; private static FieldAccess parryLightFA = new FieldAccess("parryLight", BindingFlags.Instance | BindingFlags.NonPublic); public bool CanDuplicate => Shared.InstanceCount < Options.HydraMaxFromOne.Value && (NoDupeTime < 0f || Depth == 0); public bool HydraKilled { get; private set; } = false; public bool HydraDuped { get; private set; } = false; public int SharedIdx { get; private set; } = -1; public string SharedName { get; private set; } = null; public static int MonoRegistrarIdx { get; private set; } public bool ExcludedFromHydraCheat { get { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Invalid comparison between Unknown and I4 int result; if (!_excludedFromHydraCheat) { if (Eid?.puppet ?? false) { EnemyIdentifier eid = Eid; result = ((eid == null || (int)eid.enemyType != 36) ? 1 : 0); } else { result = 0; } } else { result = 1; } return (byte)result != 0; } } protected void OnDestroy() { TryUnregisterWithShared(); } protected void OnEnable() { if (SharedName != null) { TryRegisterWithShared(); } } protected void OnDisable() { if (SharedName != null) { TryUnregisterWithShared(); } } private void TryUnregisterWithShared() { if (ExcludedFromHydraCheat) { return; } Assert.IsNotNull((Object)(object)Shared, "Shared was null! Shared Name: '" + SharedName + "'"); if (ContributesToInstanceCount) { Log.Debug(((Object)this).name + ": unregistered with shared!"); if (!Eid.dead) { PreDeath?.Invoke(); } Shared.UnregisterInstance(SharedIdx); SharedIdx = -1; ContributesToInstanceCount = false; if (Depth != 0) { } MusicManager instance = MonoSingleton.Instance; if (instance != null) { instance.PlayCleanMusic(); } } } protected void Update() { if (!Cheats.IsCheatDisabled("nyxpiri.hydra-mode") && !ExcludedFromHydraCheat && !Eid.Dead && NoDupeTime >= 0f) { NoDupeTime -= Time.deltaTime / Mathf.Max(1f, (float)Shared.InstanceCount * 0.3f + 0.667f); if (NoDupeTime <= 0f) { NoDupeTime = -1f; } } } protected void Awake() { Eid = ((Component)this).GetComponent(); Enemy = ((Component)this).GetComponent(); if ((Object)(object)Shared == (Object)null) { InitializeAsNew(); } } protected void Start() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Invalid comparison between Unknown and I4 //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Invalid comparison between Unknown and I4 //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Invalid comparison between Unknown and I4 //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Expected I4, but got Unknown //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Invalid comparison between Unknown and I4 //IL_0394: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_039d: Unknown result type (might be due to invalid IL or missing references) //IL_039f: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Invalid comparison between Unknown and I4 //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_03aa: Invalid comparison between Unknown and I4 if ((int)Eid.enemyType == 39 || (int)Eid.enemyType == 21 || ((int)Eid.enemyType == 35 && ((Object)((Component)Eid).gameObject).name.Contains("rain", StringComparison.OrdinalIgnoreCase)) || (int)Eid.enemyType == 22 || Enemy.UniquelySolo) { _excludedFromHydraCheat = true; return; } Assert.IsNotNull((Object)(object)Eid, "For object by name " + ((Object)((Component)this).gameObject).name); if (Eid.dead) { return; } Assert.IsTrue(Depth >= 0, "For object by name " + ((Object)((Component)this).gameObject).name); Assert.IsNotNull((Object)(object)Shared, "For object by name " + ((Object)((Component)this).gameObject).name + " shared was null! Shared Name: '" + SharedName + "'"); MusicManager instance = MonoSingleton.Instance; if (instance != null) { instance.PlayBattleMusic(); } if (Depth > 0) { Eid.dontCountAsKills = true; } else { Shared.CountAsKill = !Eid.dontCountAsKills; } GameplayRank = EnemyUtils.GetEnemyGameplayRank(Eid); if ((int)Eid.enemyType == 38) { NoDupeTime = Options.HydraBossWaitTime.Value; } else if ((int)Eid.enemyType == 41) { NoDupeTime = (Eid.isBoss ? Options.HydraUltraBossWaitTime.Value : Options.HydraBossWaitTime.Value); } else { EnemyGameplayRank gameplayRank = GameplayRank; EnemyGameplayRank val = gameplayRank; switch ((int)val) { case 0: NoDupeTime = Options.HydraDefaultWaitTime.Value; break; case 1: NoDupeTime = Options.HydraMiniBossWaitTime.Value; break; case 2: NoDupeTime = Options.HydraBossWaitTime.Value; break; case 3: NoDupeTime = Options.HydraUltraBossWaitTime.Value; break; } } if (Cheats.Enabled) { float num = Enemy.Health; for (int i = 0; i < Depth; i++) { num *= Options.HydraHealthDecayScale.Value; } Enemy.Health = num; } if (Depth > 0) { if ((int)Eid.enemyType == 4) { ((Component)((Component)this).gameObject.transform.parent).gameObject.AddComponent(); } else { ((Component)this).gameObject.AddComponent(); } } DroneFlesh component = ((Component)Eid).GetComponent(); if (Depth > 0 && (Object)(object)component != (Object)null) { Light component2 = ((Component)this).GetComponent(); if ((Object)(object)component2 != (Object)null) { ((Behaviour)component2).enabled = false; } Light[] componentsInChildren = ((Component)this).GetComponentsInChildren(); Light[] array = componentsInChildren; foreach (Light val2 in array) { ((Behaviour)val2).enabled = false; } } if ((Object)(object)component != (Object)null) { ((Component)this).gameObject.AddComponent(); } EnemyType enemyType = Eid.enemyType; EnemyType val3 = enemyType; if ((int)val3 != 1 && (int)val3 == 30) { ((Component)this).gameObject.AddComponent(); } TryRegisterWithShared(); } private void TryRegisterWithShared() { Assert.IsNotNull((Object)(object)Shared, "Shared was null! Shared Name: '" + SharedName + "'"); if (!ContributesToInstanceCount) { Log.Debug(((Object)this).name + ": registered with shared!"); SharedIdx = Shared.RegisterInstance(((Component)this).gameObject); ContributesToInstanceCount = true; } } public void NotifyOfDeath(bool instakill) { //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_035f: Invalid comparison between Unknown and I4 //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_023b: 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_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Expected I4, but got Unknown if (NotifiedOfDeathCalled) { return; } Log.Debug($"{((Object)this).name}: EnemyHydraMod::NotifyOfDeath called with instakill as {instakill}"); NotifiedOfDeathCalled = true; if (ExcludedFromHydraCheat) { return; } if ((Object)(object)Eid == (Object)null) { Eid = ((Component)this).GetComponent(); } if (!ContributesToInstanceCount || !Cheats.IsCheatEnabled("nyxpiri.hydra-mode")) { return; } Eid.dontCountAsKills = true; PreDeath?.Invoke(); if (Depth != 0 || !Shared.CountAsKill || !Cybergrind.IsActive) { } if (!instakill) { TryEnqueueDupe(isB: false); TryEnqueueDupe(isB: true); } TryUnregisterWithShared(); if (!HydraDuped && Shared.InstanceCount == 0) { Log.Debug($"{((Object)this).name}: EnemyHydraMod::NotifyOfDeath called and we were hydrakilled, {Shared.InstanceCount} remaining instances, HydraDuped: {HydraDuped}"); HydraKilled = true; if (Shared.CountAsKill) { StatsManager instance = MonoSingleton.Instance; instance.kills++; ContributeToActivateNextWave(); Enemy.Enemy.gz.EnemyDeath(Eid); if (Shared.CountAsKill && !Cybergrind.IsActive) { } } GameObject val = Object.Instantiate(parryLightFA.GetValue(MonoSingleton.Instance), MonoSingleton.Instance.GetTarget().position, Quaternion.identity, MonoSingleton.Instance.GetTarget()); Light val2 = default(Light); if (val.TryGetComponent(ref val2)) { ((Behaviour)val2).enabled = false; } AudioSource componentInChildren = val.GetComponentInChildren(); componentInChildren.volume *= Options.HydraKillSoundVolume.Value; Log.Debug(((Object)this).name + ": About to try give points for hydra kill..."); EnemyGameplayRank gameplayRank = GameplayRank; EnemyGameplayRank val3 = gameplayRank; switch ((int)val3) { case 0: MonoSingleton.Instance.AddPoints(10, "HYDRA KILL", (GameObject)null, Eid, -1, "", ""); break; case 1: MonoSingleton.Instance.AddPoints(50, "KINDA BIG HYDRA KILL", (GameObject)null, Eid, -1, "", ""); break; case 2: MonoSingleton.Instance.AddPoints(100, "BIG HYDRA KILL", (GameObject)null, Eid, -1, "", ""); break; case 3: MonoSingleton.Instance.AddPoints(0, "HOW??", (GameObject)null, Eid, -1, "", ""); MonoSingleton.Instance.AddPoints(1000, "ULTRA HYDRA KILL", (GameObject)null, Eid, -1, "", ""); break; default: throw new InvalidOperationException(); } Log.Debug(((Object)this).name + ": Points should have been given for hydra kill"); } else { Eid.puppet = !instakill; if ((int)Eid.enemyType == 38) { Eid.drone.spawnOnDeath = null; Eid.drone.cantInstaExplode = true; } Log.Debug($"{((Object)this).name}: EnemyHydraMod::NotifyOfDeath called and we were NOT hydrakilled, {Shared.InstanceCount} remaining instances, HydraDuped: {HydraDuped}"); } } private void ContributeToActivateNextWave() { ActivateNextWave activateNextWave = Enemy.Cloning.ActivateNextWave; if (activateNextWave != null) { activateNextWave.AddDeadEnemy(); } } private void TryEnqueueDupe(bool isB) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Invalid comparison between Unknown and I4 //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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_00e2: 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_014d: Invalid comparison between Unknown and I4 //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Invalid comparison between Unknown and I4 //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Invalid comparison between Unknown and I4 //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Invalid comparison between Unknown and I4 //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Invalid comparison between Unknown and I4 //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Invalid comparison between Unknown and I4 //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Invalid comparison between Unknown and I4 //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Invalid comparison between Unknown and I4 //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) if (ExcludedFromHydraCheat || !CanDuplicate) { return; } Log.Debug(((Object)this).name + ": Now HydraDuped by TryEnqueueDupe"); HydraDuped = true; HydraDupeQueue.QueuedDupeInfo dupeInfo = default(HydraDupeQueue.QueuedDupeInfo); if ((int)Eid.enemyType == 1) { dupeInfo.Position = ((Component)((Component)Eid.drone).GetComponent()).transform.position; } else { dupeInfo.Position = ((Component)this).transform.position; } dupeInfo.Rotation = ((Component)this).transform.rotation; dupeInfo.LocalScale = ((Component)this).transform.localScale; dupeInfo.SharedData = Shared; dupeInfo.Depth = Depth + 1; dupeInfo.EnemyType = Eid.enemyType; dupeInfo.BossBar = (Object)(object)((Component)this).GetComponent() != (Object)null; dupeInfo.CloneStore = Enemy.Cloning.Store; dupeInfo.CloneStore.AddReservation(); ActivateNextWave activateNextWave = Enemy.Cloning.ActivateNextWave; dupeInfo.CloneParent = ((activateNextWave != null) ? ((Component)activateNextWave).transform : null); if ((int)Eid.enemyType == 19) { ref Vector3 position = ref dupeInfo.Position; position += dupeInfo.Rotation * Vector3.right * (isB ? (-4.25f) : 4.25f); goto IL_0291; } float num = 1f; EnemyType enemyType = Eid.enemyType; EnemyType val = enemyType; if ((int)val <= 17) { if ((int)val != 2) { if ((int)val != 11) { if ((int)val == 17) { goto IL_01f7; } } else { num = 0f; } } else { num = 0f; } } else if ((int)val != 23) { if ((int)val != 24) { if ((int)val == 30) { goto IL_01f7; } } else { num = 0f; } } else { num = 0f; } goto IL_0214; IL_01f7: num = 0f; goto IL_0214; IL_0291: HydraDupeQueue.EnqueueDupe(dupeInfo); return; IL_0214: if ((Object)(object)((Component)this).GetComponent() != (Object)null) { num = 0.01f; } ref Vector3 position2 = ref dupeInfo.Position; position2 += Vector3.Project(((Bounds)(ref dupeInfo.SharedData.Bounds)).size, dupeInfo.Rotation * Vector3.right) * (isB ? (-1f) : 1f) * 0.3f * num; goto IL_0291; } private void InitializeAsNew() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Invalid comparison between Unknown and I4 Shared = ScriptableObject.CreateInstance(); TryRegisterWithShared(); Shared.Bounds = EnemyUtils.SolveEnemyBounds(((Component)this).gameObject); if ((Object)(object)((Component)this).GetComponent() != (Object)null) { Shared.EnemySpecificShared = (ScriptableObject)(object)new FleshDroneHydra.SharedData(); } EnemyType enemyType = Eid.enemyType; EnemyType val = enemyType; if ((int)val == 30) { Shared.EnemySpecificShared = (ScriptableObject)(object)new FleshPanopticonHydra.SharedData(); } Depth = 0; Shared.CreatorName = ((Object)((Component)this).gameObject).name; SharedName = ((Object)Shared).name; } internal void DuringDeath() { TryUnregisterWithShared(); } internal static void Initialize() { MonoRegistrarIdx = EnemyComponents.MonoRegistrar.Register(); } } public static class Cheats { public const string HydraMode = "nyxpiri.hydra-mode"; } [BepInPlugin("nyxpiri.ultrakill.hydra", "Hydra", "0.0.0")] [BepInProcess("ULTRAKILL.exe")] public class Hydra : BaseUnityPlugin { protected void Awake() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown Log.Initialize(((BaseUnityPlugin)this).Logger); Cheats.ReadyForCheatRegistration += new ReadyForCheatRegistrationEventHandler(RegisterCheats); HydraDupeQueue.Initialize(); EnemyHydra.Initialize(); Options.Config = ((BaseUnityPlugin)this).Config; Options.Initialize(); Harmony.CreateAndPatchAll(((object)this).GetType().Assembly, (string)null); if (!File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath)) { ((BaseUnityPlugin)this).Config.Save(); } } protected void Start() { LevelModder.RegisterLevelMod("Level P-2"); } protected void Update() { } protected void LateUpdate() { } protected void OnApplicationFocus(bool hasFocus) { if (hasFocus) { ((BaseUnityPlugin)this).Config.Reload(); } } private void RegisterCheats(CheatsManager cheatsManager) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown cheatsManager.RegisterCheat((ICheat)new ToggleCheat("Hydra Mode", "nyxpiri.hydra-mode", (Action)delegate { }, (Action)delegate { EnemyCloneManager.RequestInstanceStoreCapacity(5); }), "MITOSIS"); if (Cheats.IsCheatEnabled("nyxpiri.hydra-mode")) { EnemyCloneManager.RequestInstanceStoreCapacity(5); } } } [HarmonyPatch(typeof(SisyphusPrimeIntro), "OnCollisionEnter")] internal static class SisyphusPrimeIntroOnCollisionEnterPatch { public static void Prefix(SisyphusPrimeIntro __instance, Collider col) { } public static void Postfix(SisyphusPrimeIntro __instance, Collider col) { FieldPublisher val = new FieldPublisher(__instance, "hasHitGround"); if (val.Value && Cheats.IsCheatEnabled("nyxpiri.hydra-mode")) { ((Component)__instance).gameObject.GetComponent().enabled = false; ((Component)__instance).GetComponent().detectCollisions = false; Rigidbody[] componentsInChildren = ((Component)__instance).GetComponentsInChildren(); Collider[] componentsInChildren2 = ((Component)__instance).GetComponentsInChildren(); Collider[] array = componentsInChildren2; foreach (Collider val2 in array) { val2.enabled = false; } Rigidbody[] array2 = componentsInChildren; foreach (Rigidbody val3 in array2) { val3.detectCollisions = false; } } } } public class P2Additions : LevelMod { private int NumVirtues = 0; private int NumMindflayers = 0; private int NumHideousMasses = 0; private bool IsBattleWithClean = false; private GameObject PanopticonRadio = null; private long createPanopticonRadioQueued = 0L; public override void OnSceneLoad() { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown Log.Debug("Level Additions for P-2 OnSceneLoad called!"); EnemyEvents.PostStart = (Action)Delegate.Combine(EnemyEvents.PostStart, new Action(OnEnemySpawned)); EnemyEvents.Death = (Action)Delegate.Combine(EnemyEvents.Death, new Action(OnEnemyDie)); EnemyEvents.PreDestroy = (Action)Delegate.Combine(EnemyEvents.PreDestroy, new Action(OnEnemyDestroy)); UpdateEvents.OnUpdate += new OnUpdateEventHandler(Update); } private void Update() { createPanopticonRadioQueued--; if (createPanopticonRadioQueued != 1 || !((Object)(object)PanopticonRadio == (Object)null)) { return; } createPanopticonRadioQueued = 0L; GameObject val = GameObject.Find("BossMusics"); AudioSource[] componentsInChildren = val.GetComponentsInChildren(); AudioSource[] array = componentsInChildren; foreach (AudioSource val2 in array) { if (!((Object)(object)val2.clip == (Object)null) && ((Object)val2.clip).name.Contains("panopticon")) { PanopticonRadio = Object.Instantiate(((Component)val2).gameObject); PanopticonRadio.SetActive(false); val2.maxDistance = 400f; } } } public override void OnSceneUnload() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown EnemyEvents.PostStart = (Action)Delegate.Remove(EnemyEvents.PostStart, new Action(OnEnemySpawned)); EnemyEvents.Death = (Action)Delegate.Remove(EnemyEvents.Death, new Action(OnEnemyDie)); EnemyEvents.PreDestroy = (Action)Delegate.Remove(EnemyEvents.PreDestroy, new Action(OnEnemyDestroy)); UpdateEvents.OnUpdate -= new OnUpdateEventHandler(Update); DisableBattleWithClean(); } private void OnEnemySpawned(EnemyComponents enemy) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Invalid comparison between Unknown and I4 //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Invalid comparison between Unknown and I4 //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Invalid comparison between Unknown and I4 //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Invalid comparison between Unknown and I4 Assert.IsTrue(((Component)enemy).gameObject.activeInHierarchy, ""); if (enemy.Eid.Dead || !((Behaviour)enemy).enabled || !((Behaviour)enemy).isActiveAndEnabled) { return; } EnemyType enemyType = enemy.Eid.enemyType; EnemyType val = enemyType; if ((int)val != 2) { if ((int)val != 5) { if ((int)val == 9) { Log.Debug("P2Additions Detected a Virtue spawn!"); NumVirtues++; } } else { Log.Debug("P2Additions Detected a Mindflayer spawn!"); NumMindflayers++; } } else { Log.Debug("P2Additions Detected a HideousMass spawn!"); NumHideousMasses++; } if (Cheats.IsCheatEnabled("nyxpiri.hydra-mode")) { if (NumMindflayers >= 2 && NumVirtues >= 2) { EnableBattleWithClean(); } else if (NumVirtues >= 3 && NumHideousMasses >= 1) { EnableBattleWithClean(); } } else { DisableBattleWithClean(); } if ((int)enemy.Eid.enemyType == 30 && Cheats.IsCheatEnabled("nyxpiri.hydra-mode")) { createPanopticonRadioQueued = (((Object)(object)PanopticonRadio == (Object)null) ? 20 : (-1)); } } private void EnableBattleWithClean() { if (!IsBattleWithClean) { Log.Debug($"Level Additions for P-2 trying to play battle music with clean!\nNumVirtues: {NumVirtues}\nNumMindflayers: {NumMindflayers}"); Music.AddPlayCleanWithBattleVote(); IsBattleWithClean = true; } } private void DisableBattleWithClean() { if (IsBattleWithClean) { Log.Debug("Level Additions for P-2 trying to NOT play battle music with clean!"); Music.SubtractPlayCleanWithBattleVote(); IsBattleWithClean = false; } } private void OnEnemyDie(EnemyComponents enemy) { //IL_0007: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 EnemyType enemyType = enemy.Eid.enemyType; EnemyType val = enemyType; if ((int)val <= 5) { if ((int)val != 2) { if ((int)val == 5) { Log.Debug("P2Additions Detected a Mindflayer death!"); NumMindflayers--; } } else { Log.Debug("P2Additions Detected a HideousMass death!"); NumHideousMasses--; } } else if ((int)val != 9) { if ((int)val != 30 || !Cheats.IsCheatEnabled("nyxpiri.hydra-mode") || PanopticonRadio.activeSelf) { return; } EnemyHydra.SharedData shared = ((Component)enemy).GetComponent().Shared; shared.OnDeactivated = (Action)Delegate.Combine(shared.OnDeactivated, (Action)delegate { if ((Object)(object)PanopticonRadio != (Object)null) { Object.Destroy((Object)(object)PanopticonRadio.gameObject); } }); PanopticonRadio.GetComponent().time = 22f; AudioSource component = PanopticonRadio.GetComponent(); component.volume += 0.1f; GameObject obj = UnityEngineObjectExtensions.NullInvalid(PanopticonRadio); if (obj != null) { obj.SetActive(true); } } else { Log.Debug("P2Additions Detected a Virtue death!"); NumVirtues--; } } private void OnEnemyDestroy(EnemyComponents enemy) { //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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0023: Invalid comparison between Unknown and I4 //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Invalid comparison between Unknown and I4 if (enemy.Eid.dead) { return; } EnemyType enemyType = enemy.Eid.enemyType; EnemyType val = enemyType; if ((int)val != 2) { if ((int)val != 5) { if ((int)val == 9) { Log.Debug("P2Additions Detected a Virtue destruction!"); NumVirtues--; } } else { Log.Debug("P2Additions Detected a Mindflayer destruction!"); NumMindflayers--; } } else { Log.Debug("P2Additions Detected a HideousMass destruction!"); NumHideousMasses--; } } } public static class Options { public static ConfigEntry LogDebugInfo; public static ConfigEntry HydraHealthDecayScale; public static ConfigEntry HydraDefaultWaitTime; public static ConfigEntry HydraMiniBossWaitTime; public static ConfigEntry HydraBossWaitTime; public static ConfigEntry HydraUltraBossWaitTime; public static ConfigEntry HydraKillSoundVolume; public static ConfigEntry HydraMaxDepth; public static ConfigEntry HydraMaxFromOneBoss; public static ConfigEntry HydraMaxFromOne; public static ConfigEntry HydraMaxPerUpdate; public static ConfigEntry HydraPrefabPoolCapacity; public static ConfigEntry HydraPrefabPoolGrowPerUpdate; internal static ConfigFile Config; public static void Initialize() { HydraHealthDecayScale = Config.Bind("Balance", "HydraHealthDecayScale", 0.5f, (ConfigDescription)null); HydraDefaultWaitTime = Config.Bind("Balance.Normal", "HydraDefaultWaitTime", 0.45f, (ConfigDescription)null); HydraMiniBossWaitTime = Config.Bind("", "HydraMiniBossWaitTime", 0.75f, (ConfigDescription)null); HydraBossWaitTime = Config.Bind("", "HydraBossWaitTime", 1.5f, (ConfigDescription)null); HydraUltraBossWaitTime = Config.Bind("", "HydraUltraBossWaitTime", 2.75f, (ConfigDescription)null); HydraMaxFromOneBoss = Config.Bind("Balance.Boss", "HydraMaxFromOneBoss", 6, (ConfigDescription)null); HydraMaxDepth = Config.Bind("Balance", "HydraMaxDepth", 16, (ConfigDescription)null); HydraMaxFromOne = Config.Bind("Balance.Normal", "HydraMaxFromOne", 12, (ConfigDescription)null); HydraMaxPerUpdate = Config.Bind("Performance", "HydraMaxPerFrame", 4, (ConfigDescription)null); HydraPrefabPoolCapacity = Config.Bind("Performance", "HydraPrefabPoolCapacity", 20, (ConfigDescription)null); HydraPrefabPoolGrowPerUpdate = Config.Bind("Performance", "HydraPrefabPoolGrowPerUpdate", 3, (ConfigDescription)null); HydraKillSoundVolume = Config.Bind("Cosmetic", "HydraKillSoundVolume", 2f, (ConfigDescription)null); LogDebugInfo = Config.Bind("Diagnostics", "LogDebugInfo", false, (ConfigDescription)null); } } [Serializable] public class FleshDroneHydra : MonoBehaviour { public class SharedData : ScriptableObject { public FleshPrison Prison = null; } private EnemyHydra Hydra = null; public SharedData Shared = null; private bool RegisteredWithPrison = false; private bool QueuedDeath = false; protected void Start() { Hydra = ((Component)this).GetComponent(); Shared = (SharedData)(object)Hydra.Shared.EnemySpecificShared; if (Hydra.Depth > 0) { RegisterWithPrison(); } } protected void FixedUpdate() { if (Hydra.Depth > 0) { RegisterWithPrison(); if ((Object)(object)Shared.Prison == (Object)null) { Hydra.Eid.InstaKill(); return; } if (((Component)Shared.Prison).GetComponent().dead) { Hydra.Eid.InstaKill(); return; } } if (QueuedDeath) { Hydra.Eid.InstaKill(); } } private void RegisterWithPrison() { if (!RegisteredWithPrison && !Hydra.Eid.dead) { Shared.Prison?.currentDrones.Add(((Component)this).GetComponent()); RegisteredWithPrison = true; } } internal void NotifyPrisonDied() { if (!Hydra.Eid.dead) { Hydra.Eid.InstaKill(); } } internal void QueueDeath() { QueuedDeath = true; } } [Serializable] public class FleshPanopticonHydra : MonoBehaviour { public class SharedData : ScriptableObject { public uint NumLights = 0u; } private EnemyHydra Hydra = null; private SharedData Shared = null; private bool ContributingLights = false; protected void Start() { Hydra = ((Component)this).GetComponent(); Shared = (SharedData)(object)Hydra.Shared.EnemySpecificShared; if (Hydra.Depth > 0 && Shared.NumLights > 2) { Light[] componentsInChildren = ((Component)((Component)this).transform).GetComponentsInChildren(); Light[] array = componentsInChildren; foreach (Light val in array) { if (((Object)((Component)val).gameObject).name.Contains("Spot")) { Object.Destroy((Object)(object)val); } } } else { Shared.NumLights++; ContributingLights = true; } EnemyHydra hydra = Hydra; hydra.PreDeath = (Action)Delegate.Combine(hydra.PreDeath, new Action(PreDeath)); } private void PreDeath() { if (ContributingLights) { ContributingLights = false; Shared.NumLights--; } FleshPrison component = ((Component)this).GetComponent(); foreach (DroneFlesh currentDrone in component.currentDrones) { if ((Object)(object)currentDrone == (Object)null) { continue; } if ((Object)(object)((Component)currentDrone).GetComponent() == (Object)null) { EnemyIdentifier component2 = ((Component)currentDrone).GetComponent(); if (component2 != null) { component2.InstaKill(); } } else { ((Component)currentDrone).GetComponent().NotifyPrisonDied(); } } } private void FixedUpdate() { FleshPrison component = ((Component)this).GetComponent(); if (component.currentDrones.Count <= 0) { return; } foreach (DroneFlesh currentDrone in component.currentDrones) { if ((Object)(object)currentDrone == (Object)null) { continue; } FleshDroneHydra component2 = ((Component)currentDrone).GetComponent(); if ((Object)(object)component2 != (Object)null) { if ((Object)(object)component2.Shared == (Object)null) { continue; } component2.Shared.Prison = component; } if (!ContributingLights) { component2.QueueDeath(); } } } }