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<QueuedDupeInfo> DupeQueue = new Queue<QueuedDupeInfo>(256);
private static Stack<QueuedDupeInfo> ImmediatelyDupeStack = new Stack<QueuedDupeInfo>(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<EnemyComponents, bool>)Delegate.Combine(EnemyEvents.PreDeath, new Action<EnemyComponents, bool>(PreEnemyDeath));
EnemyEvents.PreDeath = (Action<EnemyComponents, bool>)Delegate.Combine(EnemyEvents.PreDeath, (Action<EnemyComponents, bool>)delegate(EnemyComponents eid, bool instakill)
{
GameObject gameObject = ((Component)eid).gameObject;
EnemyComponents component = gameObject.GetComponent<EnemyComponents>();
EnemyHydra hydraComp = component.GetHydraComp();
hydraComp.NotifyOfDeath(instakill);
});
EnemyEvents.Death = (Action<EnemyComponents>)Delegate.Combine(EnemyEvents.Death, new Action<EnemyComponents>(DuringEnemyDeath));
EnemyEvents.PostDeath = (Action<EnemyComponents, bool>)Delegate.Combine(EnemyEvents.PostDeath, new Action<EnemyComponents, bool>(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<EnemyComponents>();
Assert.IsNotNull((Object)(object)val3, "");
val = ((Component)val3).gameObject;
}
else
{
Assert.IsNotNull((Object)(object)val, "");
val3 = val.GetComponent<EnemyComponents>();
}
val.transform.position = dupeInfo.Position;
val.transform.rotation = dupeInfo.Rotation;
val.SetActive(true);
if (val2 != null)
{
val2.SetActive(true);
}
EnemyIdentifier component = val.GetComponent<EnemyIdentifier>();
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>(EnemyHydra.MonoRegistrarIdx);
}
}
public class EnemyHydra : MonoBehaviour
{
public class SharedData : ScriptableObject
{
private ReserveList<GameObject> Instances = new ReserveList<GameObject>(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<TimeController, GameObject> parryLightFA = new FieldAccess<TimeController, GameObject>("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<MusicManager>.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<EnemyIdentifier>();
Enemy = ((Component)this).GetComponent<EnemyComponents>();
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<MusicManager>.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<DestroyOnCheckpointRestart>();
}
else
{
((Component)this).gameObject.AddComponent<DestroyOnCheckpointRestart>();
}
}
DroneFlesh component = ((Component)Eid).GetComponent<DroneFlesh>();
if (Depth > 0 && (Object)(object)component != (Object)null)
{
Light component2 = ((Component)this).GetComponent<Light>();
if ((Object)(object)component2 != (Object)null)
{
((Behaviour)component2).enabled = false;
}
Light[] componentsInChildren = ((Component)this).GetComponentsInChildren<Light>();
Light[] array = componentsInChildren;
foreach (Light val2 in array)
{
((Behaviour)val2).enabled = false;
}
}
if ((Object)(object)component != (Object)null)
{
((Component)this).gameObject.AddComponent<FleshDroneHydra>();
}
EnemyType enemyType = Eid.enemyType;
EnemyType val3 = enemyType;
if ((int)val3 != 1 && (int)val3 == 30)
{
((Component)this).gameObject.AddComponent<FleshPanopticonHydra>();
}
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<EnemyIdentifier>();
}
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<StatsManager>.Instance;
instance.kills++;
ContributeToActivateNextWave();
Enemy.Enemy.gz.EnemyDeath(Eid);
if (Shared.CountAsKill && !Cybergrind.IsActive)
{
}
}
GameObject val = Object.Instantiate<GameObject>(parryLightFA.GetValue(MonoSingleton<TimeController>.Instance), MonoSingleton<PlayerTracker>.Instance.GetTarget().position, Quaternion.identity, MonoSingleton<PlayerTracker>.Instance.GetTarget());
Light val2 = default(Light);
if (val.TryGetComponent<Light>(ref val2))
{
((Behaviour)val2).enabled = false;
}
AudioSource componentInChildren = val.GetComponentInChildren<AudioSource>();
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<StyleHUD>.Instance.AddPoints(10, "<color=#a2beff>HYDRA KILL</color>", (GameObject)null, Eid, -1, "", "");
break;
case 1:
MonoSingleton<StyleHUD>.Instance.AddPoints(50, "<color=#8d96fe>KINDA BIG HYDRA KILL</color>", (GameObject)null, Eid, -1, "", "");
break;
case 2:
MonoSingleton<StyleHUD>.Instance.AddPoints(100, "<color=#8a2af7>BIG HYDRA KILL</color>", (GameObject)null, Eid, -1, "", "");
break;
case 3:
MonoSingleton<StyleHUD>.Instance.AddPoints(0, "<color=#ffdb00>HOW??</color>", (GameObject)null, Eid, -1, "", "");
MonoSingleton<StyleHUD>.Instance.AddPoints(1000, "<color=#ffdb00>ULTRA HYDRA KILL</color>", (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<Rigidbody>()).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<BossHealthBar>() != (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<CancerousRodent>() != (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<SharedData>();
TryRegisterWithShared();
Shared.Bounds = EnemyUtils.SolveEnemyBounds(((Component)this).gameObject);
if ((Object)(object)((Component)this).GetComponent<DroneFlesh>() != (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<EnemyHydra>();
}
}
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<P2Additions>("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<ToggleCheat>)delegate
{
}, (Action<ToggleCheat, CheatsManager>)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<SisyphusPrimeIntro, bool> val = new FieldPublisher<SisyphusPrimeIntro, bool>(__instance, "hasHitGround");
if (val.Value && Cheats.IsCheatEnabled("nyxpiri.hydra-mode"))
{
((Component)__instance).gameObject.GetComponent<Collider>().enabled = false;
((Component)__instance).GetComponent<Rigidbody>().detectCollisions = false;
Rigidbody[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<Rigidbody>();
Collider[] componentsInChildren2 = ((Component)__instance).GetComponentsInChildren<Collider>();
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<EnemyComponents>)Delegate.Combine(EnemyEvents.PostStart, new Action<EnemyComponents>(OnEnemySpawned));
EnemyEvents.Death = (Action<EnemyComponents>)Delegate.Combine(EnemyEvents.Death, new Action<EnemyComponents>(OnEnemyDie));
EnemyEvents.PreDestroy = (Action<EnemyComponents>)Delegate.Combine(EnemyEvents.PreDestroy, new Action<EnemyComponents>(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>();
AudioSource[] array = componentsInChildren;
foreach (AudioSource val2 in array)
{
if (!((Object)(object)val2.clip == (Object)null) && ((Object)val2.clip).name.Contains("panopticon"))
{
PanopticonRadio = Object.Instantiate<GameObject>(((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<EnemyComponents>)Delegate.Remove(EnemyEvents.PostStart, new Action<EnemyComponents>(OnEnemySpawned));
EnemyEvents.Death = (Action<EnemyComponents>)Delegate.Remove(EnemyEvents.Death, new Action<EnemyComponents>(OnEnemyDie));
EnemyEvents.PreDestroy = (Action<EnemyComponents>)Delegate.Remove(EnemyEvents.PreDestroy, new Action<EnemyComponents>(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<EnemyHydra>().Shared;
shared.OnDeactivated = (Action)Delegate.Combine(shared.OnDeactivated, (Action)delegate
{
if ((Object)(object)PanopticonRadio != (Object)null)
{
Object.Destroy((Object)(object)PanopticonRadio.gameObject);
}
});
PanopticonRadio.GetComponent<AudioSource>().time = 22f;
AudioSource component = PanopticonRadio.GetComponent<AudioSource>();
component.volume += 0.1f;
GameObject obj = UnityEngineObjectExtensions.NullInvalid<GameObject>(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<bool> LogDebugInfo;
public static ConfigEntry<float> HydraHealthDecayScale;
public static ConfigEntry<float> HydraDefaultWaitTime;
public static ConfigEntry<float> HydraMiniBossWaitTime;
public static ConfigEntry<float> HydraBossWaitTime;
public static ConfigEntry<float> HydraUltraBossWaitTime;
public static ConfigEntry<float> HydraKillSoundVolume;
public static ConfigEntry<int> HydraMaxDepth;
public static ConfigEntry<int> HydraMaxFromOneBoss;
public static ConfigEntry<int> HydraMaxFromOne;
public static ConfigEntry<int> HydraMaxPerUpdate;
public static ConfigEntry<int> HydraPrefabPoolCapacity;
public static ConfigEntry<int> HydraPrefabPoolGrowPerUpdate;
internal static ConfigFile Config;
public static void Initialize()
{
HydraHealthDecayScale = Config.Bind<float>("Balance", "HydraHealthDecayScale", 0.5f, (ConfigDescription)null);
HydraDefaultWaitTime = Config.Bind<float>("Balance.Normal", "HydraDefaultWaitTime", 0.45f, (ConfigDescription)null);
HydraMiniBossWaitTime = Config.Bind<float>("", "HydraMiniBossWaitTime", 0.75f, (ConfigDescription)null);
HydraBossWaitTime = Config.Bind<float>("", "HydraBossWaitTime", 1.5f, (ConfigDescription)null);
HydraUltraBossWaitTime = Config.Bind<float>("", "HydraUltraBossWaitTime", 2.75f, (ConfigDescription)null);
HydraMaxFromOneBoss = Config.Bind<int>("Balance.Boss", "HydraMaxFromOneBoss", 6, (ConfigDescription)null);
HydraMaxDepth = Config.Bind<int>("Balance", "HydraMaxDepth", 16, (ConfigDescription)null);
HydraMaxFromOne = Config.Bind<int>("Balance.Normal", "HydraMaxFromOne", 12, (ConfigDescription)null);
HydraMaxPerUpdate = Config.Bind<int>("Performance", "HydraMaxPerFrame", 4, (ConfigDescription)null);
HydraPrefabPoolCapacity = Config.Bind<int>("Performance", "HydraPrefabPoolCapacity", 20, (ConfigDescription)null);
HydraPrefabPoolGrowPerUpdate = Config.Bind<int>("Performance", "HydraPrefabPoolGrowPerUpdate", 3, (ConfigDescription)null);
HydraKillSoundVolume = Config.Bind<float>("Cosmetic", "HydraKillSoundVolume", 2f, (ConfigDescription)null);
LogDebugInfo = Config.Bind<bool>("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<EnemyHydra>();
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<EnemyIdentifier>().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<DroneFlesh>());
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<EnemyHydra>();
Shared = (SharedData)(object)Hydra.Shared.EnemySpecificShared;
if (Hydra.Depth > 0 && Shared.NumLights > 2)
{
Light[] componentsInChildren = ((Component)((Component)this).transform).GetComponentsInChildren<Light>();
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<FleshPrison>();
foreach (DroneFlesh currentDrone in component.currentDrones)
{
if ((Object)(object)currentDrone == (Object)null)
{
continue;
}
if ((Object)(object)((Component)currentDrone).GetComponent<FleshDroneHydra>() == (Object)null)
{
EnemyIdentifier component2 = ((Component)currentDrone).GetComponent<EnemyIdentifier>();
if (component2 != null)
{
component2.InstaKill();
}
}
else
{
((Component)currentDrone).GetComponent<FleshDroneHydra>().NotifyPrisonDied();
}
}
}
private void FixedUpdate()
{
FleshPrison component = ((Component)this).GetComponent<FleshPrison>();
if (component.currentDrones.Count <= 0)
{
return;
}
foreach (DroneFlesh currentDrone in component.currentDrones)
{
if ((Object)(object)currentDrone == (Object)null)
{
continue;
}
FleshDroneHydra component2 = ((Component)currentDrone).GetComponent<FleshDroneHydra>();
if ((Object)(object)component2 != (Object)null)
{
if ((Object)(object)component2.Shared == (Object)null)
{
continue;
}
component2.Shared.Prison = component;
}
if (!ContributingLights)
{
component2.QueueDeath();
}
}
}
}