using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using RoR2;
using RoR2.UI;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("EgoPools")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("EgoPools")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("ad0dfd7e-da05-41fe-9133-6134e468d380")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace EgoPools;
[BepInPlugin("com.yourname.egopools", "Ego Pools", "1.3.1")]
public class EgoPoolPlugin : BaseUnityPlugin
{
private sealed class PoolObjectiveTracker : ObjectiveTracker
{
private string cached;
protected override string GenerateString()
{
if (cached == null)
{
cached = "☼ A Cleansing Pool has manifested this stage. ☼";
}
return cached;
}
protected override bool IsDirty()
{
return false;
}
}
[CompilerGenerated]
private sealed class <DelayedPoolMessage>d__18 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public int stageIndex;
private float <waited>5__2;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <DelayedPoolMessage>d__18(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Expected O, but got Unknown
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<waited>5__2 = 0f;
<>2__current = (object)new WaitForSeconds(0.5f);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
<waited>5__2 += 0.5f;
break;
case 2:
<>1__state = -1;
<waited>5__2 += 0.5f;
if ((Object)(object)Run.instance == (Object)null || Run.instance.stageClearCount != stageIndex)
{
return false;
}
break;
}
if (<waited>5__2 < 12f)
{
bool flag = false;
foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
{
object obj;
if (instance == null)
{
obj = null;
}
else
{
CharacterMaster master = instance.master;
obj = ((master != null) ? master.GetBody() : null);
}
CharacterBody val = (CharacterBody)obj;
if (Object.op_Implicit((Object)(object)val) && val.HasBuff(Buffs.HiddenInvincibility))
{
flag = true;
break;
}
}
if (flag)
{
<>2__current = (object)new WaitForSeconds(0.5f);
<>1__state = 2;
return true;
}
}
if ((Object)(object)Run.instance == (Object)null || Run.instance.stageClearCount != stageIndex)
{
return false;
}
if (!AnyPoolExists())
{
return false;
}
Chat.AddMessage("<color=#00ffff><size=20>✦ A Cleansing Pool has manifested this stage. ✦</size></color>");
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private static int lastHandledStage = -1;
private static bool poolSpawnedThisStage = false;
private static EgoPoolPlugin Instance;
private static ConfigEntry<float> SpawnChance;
private static ConfigEntry<int> MinLunarsRequired;
private static ConfigEntry<bool> DisableNaturalPools;
private static ConfigEntry<int> MaxForcedPerStage;
private static ConfigEntry<int> MinStageNumber;
private static ConfigEntry<bool> AlwaysShowMessage;
public void Awake()
{
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Expected O, but got Unknown
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Expected O, but got Unknown
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Expected O, but got Unknown
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: Expected O, but got Unknown
Instance = this;
SpawnChance = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SpawnChance", 1f, new ConfigDescription("Chance (0.0–1.0) for the mod to spawn a Cleansing Pool when conditions are met.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
MinLunarsRequired = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MinLunarsRequired", 0, new ConfigDescription("Total lunar items required across all players before the mod will spawn pools.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 50), Array.Empty<object>()));
DisableNaturalPools = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DisableNaturalPools", false, "If true, remove naturally spawned Cleansing Pools so only the mod controls spawns.");
MaxForcedPerStage = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxForcedPerStage", 1, new ConfigDescription("Maximum number of pools the mod will try to spawn per stage.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 5), Array.Empty<object>()));
MinStageNumber = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MinStageNumber", 1, new ConfigDescription("Do not spawn pools before this stage number (1 = first stage).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), Array.Empty<object>()));
AlwaysShowMessage = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AlwaysShowMessage", false, "If true, the chat message will display whenever a pool exists this stage, even without Egocentrism.");
ObjectivePanelController.collectObjectiveSources += OnCollectObjectiveSources;
SceneDirector.onPostPopulateSceneServer += OnPostPopulateScene;
}
private void OnDestroy()
{
ObjectivePanelController.collectObjectiveSources -= OnCollectObjectiveSources;
SceneDirector.onPostPopulateSceneServer -= OnPostPopulateScene;
if ((Object)(object)Instance == (Object)(object)this)
{
Instance = null;
}
}
private static void OnCollectObjectiveSources(CharacterMaster master, List<ObjectiveSourceDescriptor> dest)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
if (poolSpawnedThisStage && !((Object)(object)master == (Object)null))
{
dest.Add(new ObjectiveSourceDescriptor
{
master = master,
objectiveType = typeof(PoolObjectiveTracker),
source = null
});
}
}
private static bool AnyPlayerHasEgocentrism()
{
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
{
object obj;
if (instance == null)
{
obj = null;
}
else
{
CharacterMaster master = instance.master;
obj = ((master != null) ? master.inventory : null);
}
Inventory val = (Inventory)obj;
if ((Object)(object)val == (Object)null)
{
continue;
}
try
{
if (val.GetItemCount(Items.LunarSun.itemIndex) > 0)
{
return true;
}
}
catch
{
}
}
return false;
}
private static int TotalLunarCountAcrossPlayers()
{
int num = 0;
foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
{
object obj;
if (instance == null)
{
obj = null;
}
else
{
CharacterMaster master = instance.master;
obj = ((master != null) ? master.inventory : null);
}
Inventory val = (Inventory)obj;
if (!((Object)(object)val == (Object)null))
{
num += val.GetTotalItemCountOfTier((ItemTier)3);
}
}
return num;
}
private static bool AnyPoolExists()
{
return Object.FindObjectsOfType<PurchaseInteraction>().Any((PurchaseInteraction pi) => Object.op_Implicit((Object)(object)pi) && ((Object)pi).name.IndexOf("ShrineCleanse", StringComparison.OrdinalIgnoreCase) >= 0);
}
private static int RemoveAllPools()
{
int num = 0;
PurchaseInteraction[] array = Object.FindObjectsOfType<PurchaseInteraction>();
foreach (PurchaseInteraction val in array)
{
if (Object.op_Implicit((Object)(object)val) && ((Object)val).name.IndexOf("ShrineCleanse", StringComparison.OrdinalIgnoreCase) >= 0)
{
Object.Destroy((Object)(object)((Component)((Component)val).transform.root).gameObject);
num++;
}
}
return num;
}
private static void OnPostPopulateScene(SceneDirector dir)
{
//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)
if (!NetworkServer.active || (Object)(object)Run.instance == (Object)null || (Object)(object)dir == (Object)null)
{
return;
}
Scene activeScene = SceneManager.GetActiveScene();
if (((Scene)(ref activeScene)).name.Equals("bazaar", StringComparison.OrdinalIgnoreCase))
{
return;
}
int stageClearCount = Run.instance.stageClearCount;
int num = stageClearCount + 1;
if (stageClearCount == lastHandledStage)
{
return;
}
lastHandledStage = stageClearCount;
poolSpawnedThisStage = false;
bool flag = AnyPlayerHasEgocentrism();
int num2 = TotalLunarCountAcrossPlayers();
if (DisableNaturalPools.Value)
{
RemoveAllPools();
}
else if (AnyPoolExists())
{
if ((flag || AlwaysShowMessage.Value) && (Object)(object)Instance != (Object)null)
{
((MonoBehaviour)Instance).StartCoroutine(DelayedPoolMessage(stageClearCount));
}
return;
}
if (!flag || num < Mathf.Max(1, MinStageNumber.Value) || num2 < Mathf.Max(0, MinLunarsRequired.Value))
{
return;
}
int num3 = Mathf.Max(0, MaxForcedPerStage.Value);
float num4 = Mathf.Clamp01(SpawnChance.Value);
int num5 = 0;
for (int i = 0; i < num3; i++)
{
if ((!(num4 < 1f) || !(Random.value > num4)) && TrySpawnOneVanillaPool())
{
num5++;
}
}
if (num5 > 0)
{
poolSpawnedThisStage = true;
if ((Object)(object)Instance != (Object)null)
{
((MonoBehaviour)Instance).StartCoroutine(DelayedPoolMessage(stageClearCount));
}
}
}
[IteratorStateMachine(typeof(<DelayedPoolMessage>d__18))]
private static IEnumerator DelayedPoolMessage(int stageIndex)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <DelayedPoolMessage>d__18(0)
{
stageIndex = stageIndex
};
}
private static bool TrySpawnOneVanillaPool()
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Expected O, but got Unknown
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Expected O, but got Unknown
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Expected O, but got Unknown
try
{
InteractableSpawnCard val = Resources.Load<InteractableSpawnCard>("SpawnCards/InteractableSpawnCard/iscShrineCleanse");
if (!Object.op_Implicit((Object)(object)val))
{
Debug.LogWarning((object)"[Ego Pools] Could not load iscShrineCleanse.");
return false;
}
DirectorPlacementRule val2 = new DirectorPlacementRule
{
placementMode = (PlacementMode)4
};
Xoroshiro128Plus val3 = new Xoroshiro128Plus(((Object)(object)Run.instance != (Object)null) ? Run.instance.seed : ((ulong)DateTime.UtcNow.Ticks));
DirectorSpawnRequest val4 = new DirectorSpawnRequest((SpawnCard)(object)val, val2, val3);
if (!Object.op_Implicit((Object)(object)DirectorCore.instance.TrySpawnObject(val4)))
{
Debug.LogWarning((object)"[Ego Pools] TrySpawnObject returned null.");
return false;
}
return true;
}
catch (Exception arg)
{
Debug.LogWarning((object)$"[Ego Pools] Spawn error: {arg}");
return false;
}
}
}