Decompiled source of ShrinesOfTheTarnished v0.1.8

plugins/ShrinesOfTheTarnished.dll

Decompiled 21 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.CharacterAI;
using RoR2.Navigation;
using ShrinesOfTheTarnished.Modules.Shrines;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ShrinesOfTheTarnished")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ShrinesOfTheTarnished")]
[assembly: AssemblyTitle("ShrinesOfTheTarnished")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace ShrinesOfTheTarnished
{
	internal static class Log
	{
		internal static ManualLogSource _logSource;

		internal static void Init(ManualLogSource logSource)
		{
			_logSource = logSource;
		}

		internal static void Debug(object data)
		{
			_logSource.LogDebug(data);
		}

		internal static void Error(object data)
		{
			_logSource.LogError(data);
		}

		internal static void Fatal(object data)
		{
			_logSource.LogFatal(data);
		}

		internal static void Info(object data)
		{
			_logSource.LogInfo(data);
		}

		internal static void Message(object data)
		{
			_logSource.LogMessage(data);
		}

		internal static void Warning(object data)
		{
			_logSource.LogWarning(data);
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.jerelo.ShrinesOfTheTarnished", "Shrines of the Tarnished", "0.1.8")]
	public class ShrinesPlugin : BaseUnityPlugin
	{
		public const string MODUID = "com.jerelo.ShrinesOfTheTarnished";

		public const string MODNAME = "Shrines of the Tarnished";

		public const string MODVERSION = "0.1.8";

		public static ShrinesPlugin instance;

		private void Awake()
		{
			instance = this;
			Log.Init(((BaseUnityPlugin)this).Logger);
			ShrineKit.MinPerStage = ((BaseUnityPlugin)this).Config.Bind<int>("Spawning", "MinShrinesPerStage", 1, "Every regular stage gets at least this many different Tarnished shrines (0-4). The director can roll more, up to one of each.").Value;
			ShrineKit.CategoryWeight = ((BaseUnityPlugin)this).Config.Bind<float>("Spawning", "DirectorWeight", 10f, "How often the stage director picks one of these shrines. Vanilla per-stage weights for comparison: chests ~45, drones ~14, shrines ~10, barrels ~10.").Value;
			ShrineKit.InvasionInSolo = ((BaseUnityPlugin)this).Config.Bind<bool>("Spawning", "InvasionInSolo", false, "Let The Invasion (a PvP shrine: it turns its user against the team) appear in single-player runs.").Value;
			InvasionShrineSetup.Init();
			MoreShrinesSetup.Init();
			ShrineKit.EnablePerStageGuarantee();
		}
	}
}
namespace ShrinesOfTheTarnished.Modules
{
	internal static class Language
	{
		public const string ContextSize = "140%";

		public static void Add(string token, string text)
		{
			LanguageAPI.Add(token, text);
		}

		public static void AddContext(string token, string text)
		{
			LanguageAPI.Add(token, "<size=140%>" + text + "</size>");
		}
	}
}
namespace ShrinesOfTheTarnished.Modules.Shrines
{
	public class CorruptionShrineController : BaseShrineController
	{
		private enum Outcome
		{
			Red,
			Void,
			Lunar,
			Boss,
			White,
			Curse,
			Nothing
		}

		private static readonly (Outcome outcome, float weight)[] Table = new(Outcome, float)[7]
		{
			(Outcome.Red, 20f),
			(Outcome.Void, 10f),
			(Outcome.Lunar, 10f),
			(Outcome.Boss, 5f),
			(Outcome.White, 25f),
			(Outcome.Curse, 10f),
			(Outcome.Nothing, 20f)
		};

		private const float VOID_WHITE = 0.6f;

		private const float VOID_GREEN = 0.3f;

		private const int CURSE_STACKS = 11;

		[Server]
		protected override void OnPurchased(Interactor interactor)
		{
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			if (_used)
			{
				return;
			}
			CharacterBody component = ((Component)interactor).GetComponent<CharacterBody>();
			CharacterMaster val = (Object.op_Implicit((Object)(object)component) ? component.master : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val.playerCharacterMasterController == (Object)null)
			{
				return;
			}
			base.OnPurchased(interactor);
			List<ItemIndex> list = BaseShrineController.OwnedItems(component.inventory, (ItemDef def) => ((int)def.tier == 0 || (int)def.tier == 1) && def.canRemove);
			if (list.Count == 0)
			{
				Refund(val, Object.op_Implicit((Object)(object)_purchase) ? _purchase.cost : 0);
				BaseShrineController.Say("<style=cIsHealing>The shrine demands an item of the earth. " + Util.GetBestBodyName(((Component)component).gameObject) + " has none to give.</style>");
				return;
			}
			component.inventory.RemoveItemPermanent(list[Random.Range(0, list.Count)], 1);
			Run instance = Run.instance;
			Vector3 corePosition = component.corePosition;
			switch (Roll())
			{
			case Outcome.Red:
				Drop(Object.op_Implicit((Object)(object)instance) ? instance.availableTier3DropList : null, Object.op_Implicit((Object)(object)instance) ? instance.availableTier2DropList : null, corePosition);
				BaseShrineController.Say("<style=cIsHealing>The shrine is pleased. The offering is transmuted.</style>");
				return;
			case Outcome.Void:
			{
				float value = Random.value;
				List<PickupIndex> tier = ((!Object.op_Implicit((Object)(object)instance)) ? null : ((value < 0.6f) ? instance.availableVoidTier1DropList : ((value < 0.90000004f) ? instance.availableVoidTier2DropList : instance.availableVoidTier3DropList)));
				Drop(tier, Object.op_Implicit((Object)(object)instance) ? instance.availableTier1DropList : null, corePosition);
				BaseShrineController.Say("<style=cIsVoid>The offering is twisted by the Void.</style>");
				break;
			}
			case Outcome.Lunar:
				Drop(Object.op_Implicit((Object)(object)instance) ? instance.availableLunarItemDropList : null, Object.op_Implicit((Object)(object)instance) ? instance.availableTier1DropList : null, corePosition);
				BaseShrineController.Say("<style=cIsLunar>The offering returns... changed. Heretical.</style>");
				break;
			case Outcome.Boss:
				Drop(Object.op_Implicit((Object)(object)instance) ? instance.availableBossDropList : null, Object.op_Implicit((Object)(object)instance) ? instance.availableTier1DropList : null, corePosition);
				BaseShrineController.Say("<style=cIsDamage>The offering hardens into a trophy.</style>");
				break;
			case Outcome.White:
				Drop(Object.op_Implicit((Object)(object)instance) ? instance.availableTier1DropList : null, null, corePosition);
				BaseShrineController.Say("<style=cIsHealing>The corruption spits back something weaker.</style>");
				break;
			case Outcome.Curse:
			{
				for (int num = 0; num < 11; num++)
				{
					component.AddBuff(Buffs.PermanentCurse);
				}
				BaseShrineController.Say("<style=cIsHealth>The corruption seeps into " + Util.GetBestBodyName(((Component)component).gameObject) + ". Their vitality withers until the next stage.</style>");
				break;
			}
			default:
				BaseShrineController.Say("<style=cIsHealth>The offering is consumed.</style>");
				break;
			}
			_used = false;
			if (Object.op_Implicit((Object)(object)_purchase))
			{
				_purchase.SetAvailable(true);
			}
		}

		private static Outcome Roll()
		{
			float num = 0f;
			(Outcome, float)[] table = Table;
			for (int i = 0; i < table.Length; i++)
			{
				(Outcome, float) tuple = table[i];
				num += tuple.Item2;
			}
			float num2 = Random.value * num;
			table = Table;
			for (int i = 0; i < table.Length; i++)
			{
				(Outcome, float) tuple2 = table[i];
				if (num2 < tuple2.Item2)
				{
					return tuple2.Item1;
				}
				num2 -= tuple2.Item2;
			}
			return Outcome.Nothing;
		}

		private void Drop(List<PickupIndex> tier, List<PickupIndex> fallback, Vector3 toward)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			PickupIndex? val = BaseShrineController.PickFromTier(tier, fallback);
			if (val.HasValue)
			{
				DropPickup(val.Value, toward);
			}
		}
	}
	public class InvasionShrineController : NetworkBehaviour
	{
		[SyncVar]
		private bool _active;

		[SyncVar]
		private float _timerRemaining;

		[SyncVar]
		private uint _ticksPaid;

		[SyncVar]
		private NetworkInstanceId _bossMasterId = NetworkInstanceId.Invalid;

		private PurchaseInteraction _purchase;

		private GameObject _bossMasterObject;

		private const float DURATION = 90f;

		private const float TICK_SECONDS = 10f;

		private const float HEALTH_MULTIPLIER = 10f;

		private const float IMMUNITY_SECONDS = 3f;

		private const uint GOLD_PER_TICK = 40u;

		private const uint LUNAR_PER_TICK = 1u;

		private const uint ATTACKER_GOLD_REWARD = 150u;

		private const float TIMER_END_STEAL_FRACTION = 0.05f;

		private const float REVIVE_DELAY = 2f;

		private readonly List<CharacterMaster> _fallen = new List<CharacterMaster>();

		private readonly HashSet<CharacterMaster> _deadAtStart = new HashSet<CharacterMaster>();

		private float _reviveTimer = -1f;

		private void Awake()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			_purchase = ((Component)this).GetComponent<PurchaseInteraction>();
			if (Object.op_Implicit((Object)(object)_purchase))
			{
				if (_purchase.onPurchase == null)
				{
					_purchase.onPurchase = new PurchaseEvent();
				}
				((UnityEvent<Interactor>)(object)_purchase.onPurchase).AddListener((UnityAction<Interactor>)OnPurchased);
			}
		}

		[Server]
		private void OnPurchased(Interactor interactor)
		{
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			if (_active)
			{
				return;
			}
			CharacterBody component = ((Component)interactor).GetComponent<CharacterBody>();
			CharacterMaster val = (Object.op_Implicit((Object)(object)component) ? component.master : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val.playerCharacterMasterController == (Object)null)
			{
				return;
			}
			_fallen.Clear();
			_deadAtStart.Clear();
			_reviveTimer = -1f;
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				if (Object.op_Implicit((Object)(object)instance.master) && IsDead(instance.master))
				{
					_deadAtStart.Add(instance.master);
				}
			}
			ConvertToBoss(val);
			_active = true;
			_timerRemaining = 90f;
			_ticksPaid = 0u;
			_bossMasterId = ((NetworkBehaviour)val).netId;
			_bossMasterObject = ((Component)val).gameObject;
			if (Object.op_Implicit((Object)(object)_purchase))
			{
				_purchase.SetAvailable(false);
			}
			Chat.ServerAttemptBroadcastChat("<style=cIsPvP>The Invasion has begun!</style> " + Util.GetBestBodyName(((Component)component).gameObject) + " has turned against the team. Kill them before the timer runs out!");
		}

		[Server]
		private void ConvertToBoss(CharacterMaster master)
		{
			CharacterBody body = master.GetBody();
			if (Object.op_Implicit((Object)(object)body))
			{
				body.baseMaxHealth *= 10f;
				body.RecalculateStats();
				body.healthComponent.health = body.healthComponent.fullHealth;
				body.AddTimedBuff(Buffs.HiddenInvincibility, 3f);
				TeamComponent teamComponent = body.teamComponent;
				if (Object.op_Implicit((Object)(object)teamComponent))
				{
					teamComponent.teamIndex = (TeamIndex)2;
				}
			}
		}

		[Server]
		private void RevertBoss(CharacterMaster master)
		{
			CharacterBody body = master.GetBody();
			if (Object.op_Implicit((Object)(object)body))
			{
				body.baseMaxHealth /= 10f;
				body.RecalculateStats();
				body.healthComponent.health = body.healthComponent.fullHealth;
				TeamComponent teamComponent = body.teamComponent;
				if (Object.op_Implicit((Object)(object)teamComponent))
				{
					teamComponent.teamIndex = (TeamIndex)1;
				}
			}
		}

		[Server]
		private void FixedUpdate()
		{
			if (!NetworkServer.active)
			{
				return;
			}
			if (_active || _reviveTimer >= 0f)
			{
				TrackFallen();
			}
			if (_reviveTimer >= 0f)
			{
				_reviveTimer -= Time.fixedDeltaTime;
				if (_reviveTimer < 0f)
				{
					ReviveFallen();
				}
			}
			if (!_active)
			{
				return;
			}
			CharacterMaster val = FindBossMaster();
			if (!((Object)(object)val == (Object)null))
			{
				_timerRemaining -= Time.fixedDeltaTime;
				if (_timerRemaining > 0f && Mathf.FloorToInt((90f - _timerRemaining) / 10f) > _ticksPaid)
				{
					_ticksPaid++;
					PayTick(val);
				}
				if (IsDead(val))
				{
					EndInvasion(attackersWon: true);
				}
				else if (_timerRemaining <= 0f)
				{
					StealFromAttackers(val);
					RevertBoss(val);
					EndInvasion(attackersWon: false);
				}
			}
		}

		private static bool IsDead(CharacterMaster m)
		{
			CharacterBody body = m.GetBody();
			if (m.lostBodyToDeath)
			{
				if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)body.healthComponent))
				{
					return !body.healthComponent.alive;
				}
				return true;
			}
			return false;
		}

		private void TrackFallen()
		{
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				CharacterMaster master = instance.master;
				if (Object.op_Implicit((Object)(object)master) && !_deadAtStart.Contains(master) && IsDead(master))
				{
					if (!_fallen.Contains(master))
					{
						_fallen.Add(master);
					}
					master.preventGameOver = true;
				}
			}
		}

		private void ReviveFallen()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			foreach (CharacterMaster item in _fallen)
			{
				if (Object.op_Implicit((Object)(object)item) && IsDead(item) && Object.op_Implicit((Object)(object)item.bodyPrefab))
				{
					CharacterBody component = item.bodyPrefab.GetComponent<CharacterBody>();
					Vector3 val = (Vector3)(((??)TeleportHelper.FindSafeTeleportDestination(item.deathFootPosition, component, RoR2Application.rng)) ?? item.deathFootPosition);
					CharacterBody val2 = item.Respawn(val, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f), true);
					if (Object.op_Implicit((Object)(object)val2))
					{
						val2.AddTimedBuff(Buffs.Immune, 3f);
						num++;
					}
				}
			}
			_fallen.Clear();
			_deadAtStart.Clear();
			if (num > 0)
			{
				Chat.ServerAttemptBroadcastChat("<style=cIsHealing>The shrine returns those the Invasion claimed.</style>");
			}
		}

		[Server]
		private CharacterMaster FindBossMaster()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)_bossMasterObject))
			{
				return _bossMasterObject.GetComponent<CharacterMaster>();
			}
			GameObject val = NetworkServer.FindLocalObject(_bossMasterId);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			return val.GetComponent<CharacterMaster>();
		}

		[Server]
		private void PayTick(CharacterMaster master)
		{
			int num = (Object.op_Implicit((Object)(object)Run.instance) ? Run.instance.GetDifficultyScaledCost(40) : 40);
			master.GiveMoney((uint)num);
			master.GetBody();
			NetworkUser val = FindNetworkUser(master);
			if (Object.op_Implicit((Object)(object)val))
			{
				val.AwardLunarCoins(1u);
			}
			Chat.ServerAttemptBroadcastChat("<style=cIsLunar>The traitor feeds on the shrine... +" + num + " gold, +" + 1u + " lunar coin.</style>");
		}

		[Server]
		private void StealFromAttackers(CharacterMaster bossMaster)
		{
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				CharacterMaster master = instance.master;
				if (!((Object)(object)master == (Object)null) && !((Object)(object)master == (Object)(object)bossMaster))
				{
					uint num = (uint)((float)master.money * 0.05f);
					if (num != 0)
					{
						master.money -= num;
						bossMaster.GiveMoney(num);
					}
				}
			}
		}

		[Server]
		private NetworkUser FindNetworkUser(CharacterMaster master)
		{
			foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList)
			{
				if (Object.op_Implicit((Object)(object)readOnlyInstances.masterController) && (Object)(object)readOnlyInstances.masterController.master == (Object)(object)master)
				{
					return readOnlyInstances;
				}
			}
			return null;
		}

		[Server]
		private void DropReward()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if (Random.value < 1f / 3f && Run.instance.availableTier3DropList.Count > 0)
			{
				ShrineKit.LaunchDroplet(Run.instance.availableTier3DropList[Random.Range(0, Run.instance.availableTier3DropList.Count)], ((Component)this).transform);
			}
			else if (Run.instance.availableTier2DropList.Count > 0)
			{
				List<PickupIndex> availableTier2DropList = Run.instance.availableTier2DropList;
				for (int i = 0; i < 2; i++)
				{
					ShrineKit.LaunchDroplet(availableTier2DropList[Random.Range(0, availableTier2DropList.Count)], ((Component)this).transform);
				}
			}
		}

		[Server]
		private void EndInvasion(bool attackersWon)
		{
			CharacterMaster val = FindBossMaster();
			_active = false;
			_bossMasterObject = null;
			TrackFallen();
			_reviveTimer = 2f;
			if (attackersWon)
			{
				int num = (Object.op_Implicit((Object)(object)Run.instance) ? Run.instance.GetDifficultyScaledCost(150) : 150);
				foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
				{
					if (Object.op_Implicit((Object)(object)instance.master) && (Object)(object)instance.master != (Object)(object)val)
					{
						instance.master.GiveMoney((uint)num);
					}
				}
				Chat.ServerAttemptBroadcastChat("<style=cIsHealth>The team slew the traitor! The shrine pays out.</style>");
				DropReward();
			}
			else
			{
				Chat.ServerAttemptBroadcastChat("<style=cIsPvP>The Invasion failed. The traitor walks away richer.</style>");
			}
		}
	}
	public static class InvasionShrineSetup
	{
		public static GameObject shrinePrefab;

		private static DirectorCard _card;

		private const string NAME_TOKEN = "SHRINE_INVASION_NAME";

		private const string CONTEXT_TOKEN = "SHRINE_INVASION_CONTEXT";

		public static void Init()
		{
			BuildPrefabAndCard();
			Hooks();
			Language.Add("SHRINE_INVASION_NAME", "The Invasion");
			Language.AddContext("SHRINE_INVASION_CONTEXT", "Someone must turn traitor. <style=cIsPvP>First to interact becomes the boss.</style>");
			PrefabAPI.RegisterNetworkPrefab(shrinePrefab);
		}

		private static void BuildPrefabAndCard()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: 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_0060: Expected O, but got Unknown
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: 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)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Expected O, but got Unknown
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Expected O, but got Unknown
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Expected O, but got Unknown
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Expected O, but got Unknown
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Expected O, but got Unknown
			GameObject val = new GameObject("ShrineInvasion");
			val.layer = LayerIndex.defaultLayer.intVal;
			val.transform.SetParent(ShrineKit.TemplateParent(), false);
			val.AddComponent<NetworkIdentity>();
			PurchaseInteraction val2 = val.AddComponent<PurchaseInteraction>();
			if (val2.onPurchase == null)
			{
				val2.onPurchase = new PurchaseEvent();
			}
			if (val2.onDetailedPurchaseServer == null)
			{
				val2.onDetailedPurchaseServer = new DetailedPurchaseEvent();
			}
			val2.displayNameToken = "SHRINE_INVASION_NAME";
			val2.contextToken = "SHRINE_INVASION_CONTEXT";
			val2.costType = (CostTypeIndex)0;
			val2.cost = 0;
			val2.isShrine = true;
			val2.automaticallyScaleCostWithDifficulty = false;
			val2.setUnavailableOnTeleporterActivated = true;
			val2.ignoreSpherecastForInteractability = false;
			val2.shouldProximityHighlight = true;
			SphereCollider obj = val.AddComponent<SphereCollider>();
			obj.radius = 4f;
			obj.center = new Vector3(0f, 1.5f, 0f);
			((Collider)obj).isTrigger = true;
			val.AddComponent<InvasionShrineController>();
			if (!ShrineAssets.TryAttachModel(val, "ShrineInvasion"))
			{
				GameObject val3 = new GameObject("Visual");
				val3.transform.SetParent(val.transform, false);
				MakePrimitive(val3, (PrimitiveType)2, new Vector3(0f, 2.2f, 0f), new Vector3(0.9f, 2.2f, 0.9f), new Color(0.08f, 0.07f, 0.09f));
				MakePrimitive(val3, (PrimitiveType)2, new Vector3(0f, 1.2f, 0f), new Vector3(0.95f, 0.08f, 0.95f), new Color(0.9f, 0.1f, 0.1f), emissive: true);
				MakePrimitive(val3, (PrimitiveType)2, new Vector3(0f, 2.6f, 0f), new Vector3(0.95f, 0.08f, 0.95f), new Color(0.9f, 0.1f, 0.1f), emissive: true);
				MakePrimitive(val3, (PrimitiveType)0, new Vector3(0f, 3.3f, 0f), new Vector3(0.5f, 0.5f, 0.5f), new Color(0.7f, 0.05f, 0.05f), emissive: true);
			}
			ShrineKit.MakeInteractable(val);
			shrinePrefab = val;
			InteractableSpawnCard val4 = ScriptableObject.CreateInstance<InteractableSpawnCard>();
			((Object)val4).name = "iscShrineInvasion";
			((SpawnCard)val4).prefab = val;
			((SpawnCard)val4).sendOverNetwork = true;
			((SpawnCard)val4).hullSize = (HullClassification)1;
			((SpawnCard)val4).nodeGraphType = (GraphType)0;
			((SpawnCard)val4).requiredFlags = (NodeFlags)0;
			((SpawnCard)val4).forbiddenFlags = (NodeFlags)16;
			((SpawnCard)val4).directorCreditCost = 20;
			((SpawnCard)val4).occupyPosition = true;
			val4.orientToFloor = false;
			val4.slightlyRandomizeOrientation = false;
			val4.maxSpawnsPerStage = 1;
			_card = new DirectorCard
			{
				spawnCard = (SpawnCard)(object)val4,
				selectionWeight = 10,
				preventOverhead = false,
				minimumStageCompletions = 0
			};
		}

		private static void MakePrimitive(GameObject parent, PrimitiveType type, Vector3 localPos, Vector3 scale, Color color, bool emissive = false)
		{
			//IL_0000: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.CreatePrimitive(type);
			obj.transform.SetParent(parent.transform, false);
			obj.transform.localPosition = localPos;
			obj.transform.localScale = scale;
			Renderer component = obj.GetComponent<Renderer>();
			Material val = ShrineKit.NewShrineMaterial(color, emissive);
			if (Object.op_Implicit((Object)(object)val))
			{
				component.material = val;
			}
		}

		private static void Hooks()
		{
			ShrineKit.RegisterCard(_card, 10f, multiplayerOnly: true);
		}
	}
	public static class MoreShrinesSetup
	{
		public static void Init()
		{
			BuildReflection();
			BuildCorruption();
			BuildSwarm();
		}

		private static void BuildReflection()
		{
			//IL_0046: 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)
			Language.Add("SHRINE_REFLECTION_NAME", "Shrine of Reflection");
			Language.AddContext("SHRINE_REFLECTION_CONTEXT", "Pay to face <style=cIsUtility>your own reflection</style>. Beat yourself to keep a copy of your build.");
			GameObject obj = ShrineKit.BuildShrineRoot<ReflectionShrineController>("ShrineReflection", "SHRINE_REFLECTION_NAME", "SHRINE_REFLECTION_CONTEXT", (CostTypeIndex)1, 50, scaleCost: true);
			ShrineKit.AddObeliskVisual(obj, new Color(0.2f, 0.7f, 0.9f));
			obj.GetComponent<SphereCollider>().radius = 4f;
			DirectorCard obj2 = ShrineKit.MakeCard(obj, 20, 0, 6f);
			obj2.spawnCard.hullSize = (HullClassification)1;
			ShrineKit.RegisterCard(obj2, 6f);
		}

		private static void BuildCorruption()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			Language.Add("SHRINE_CORRUPTION_NAME", "Shrine of Corruption");
			Language.AddContext("SHRINE_CORRUPTION_CONTEXT", "Offer a <style=cIsHealing>lunar coin</style> and an item. The corruption may transmute it... or devour it.");
			GameObject obj = ShrineKit.BuildShrineRoot<CorruptionShrineController>("ShrineCorruption", "SHRINE_CORRUPTION_NAME", "SHRINE_CORRUPTION_CONTEXT", (CostTypeIndex)3, 1, scaleCost: false);
			ShrineKit.AddObeliskVisual(obj, new Color(0.7f, 0.1f, 0.9f));
			obj.GetComponent<PurchaseInteraction>().setUnavailableOnTeleporterActivated = false;
			obj.GetComponent<SphereCollider>().radius = 4f;
			DirectorCard obj2 = ShrineKit.MakeCard(obj, 20, 0, 6f);
			obj2.spawnCard.hullSize = (HullClassification)1;
			ShrineKit.RegisterCard(obj2, 6f);
		}

		private static void BuildSwarm()
		{
			//IL_0046: 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)
			Language.Add("SHRINE_SWARM_NAME", "Shrine of the Swarm");
			Language.AddContext("SHRINE_SWARM_CONTEXT", "Pay to <style=cIsHealth>awaken the Swarm</style>. Slay its waves for the hoard.");
			GameObject obj = ShrineKit.BuildShrineRoot<SwarmShrineController>("ShrineSwarm", "SHRINE_SWARM_NAME", "SHRINE_SWARM_CONTEXT", (CostTypeIndex)1, 80, scaleCost: true);
			ShrineKit.AddObeliskVisual(obj, new Color(0.9f, 0.6f, 0.1f));
			obj.GetComponent<SphereCollider>().radius = 4f;
			DirectorCard obj2 = ShrineKit.MakeCard(obj, 20, 0, 8f);
			obj2.spawnCard.hullSize = (HullClassification)1;
			ShrineKit.RegisterCard(obj2, 8f);
		}
	}
	public class ReflectionShrineController : BaseShrineController
	{
		private const float CLONE_DAMAGE_MULT = 0.8f;

		private const float TIMEOUT = 90f;

		private CharacterMaster _clone;

		private CharacterMaster _buyer;

		private float _timeout;

		private NetworkInstanceId _cloneId = NetworkInstanceId.Invalid;

		[Server]
		protected override void OnPurchased(Interactor interactor)
		{
			//IL_006f: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			if (_used)
			{
				return;
			}
			CharacterBody component = ((Component)interactor).GetComponent<CharacterBody>();
			CharacterMaster val = (Object.op_Implicit((Object)(object)component) ? component.master : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val.playerCharacterMasterController == (Object)null)
			{
				return;
			}
			base.OnPurchased(interactor);
			MasterCopySpawnCard val2 = MasterCopySpawnCard.FromMaster(val, true, false, (Action<CharacterMaster>)null);
			GameObject val3 = null;
			if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)((SpawnCard)val2).prefab) && Object.op_Implicit((Object)(object)DirectorCore.instance))
			{
				DirectorSpawnRequest val4 = new DirectorSpawnRequest((SpawnCard)(object)val2, new DirectorPlacementRule
				{
					placementMode = (PlacementMode)1,
					position = ((Component)this).transform.position,
					minDistance = 5f,
					maxDistance = 20f
				}, Run.instance.treasureRng)
				{
					teamIndexOverride = (TeamIndex)2,
					ignoreTeamMemberLimit = true
				};
				val3 = DirectorCore.instance.TrySpawnObject(val4);
			}
			_clone = (Object.op_Implicit((Object)(object)val3) ? val3.GetComponent<CharacterMaster>() : null);
			if ((Object)(object)_clone == (Object)null)
			{
				BaseShrineController.Say("<style=cIsUtility>The mirror is empty...</style>");
				Refund(val, Object.op_Implicit((Object)(object)_purchase) ? _purchase.cost : 0);
				return;
			}
			_buyer = val;
			_cloneId = ((NetworkBehaviour)_clone).netId;
			_timeout = 90f;
			CharacterBody body = _clone.GetBody();
			if (Object.op_Implicit((Object)(object)body))
			{
				body.baseDamage *= 0.8f;
				body.RecalculateStats();
				body.healthComponent.health = body.healthComponent.fullHealth;
			}
			BaseShrineController.Say("<style=cIsUtility>" + Util.GetBestBodyName(((Component)component).gameObject) + " faces their own reflection.</style> Beat yourself to earn a copy of what you carry.");
		}

		[Server]
		private void FixedUpdate()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			if (_cloneId == NetworkInstanceId.Invalid)
			{
				return;
			}
			CharacterMaster val = (_clone = (Object.op_Implicit((Object)(object)_clone) ? _clone : FindClone()));
			_timeout -= Time.fixedDeltaTime;
			CharacterBody val2 = (Object.op_Implicit((Object)(object)val) ? val.GetBody() : null);
			if ((Object)(object)val2 == (Object)null || (Object.op_Implicit((Object)(object)val2.healthComponent) && !val2.healthComponent.alive))
			{
				List<ItemIndex> list = BaseShrineController.OwnedItems(Object.op_Implicit((Object)(object)_buyer) ? _buyer.inventory : null, null);
				if (list.Count > 0)
				{
					CharacterBody val3 = (Object.op_Implicit((Object)(object)_buyer) ? _buyer.GetBody() : null);
					DropPickup(PickupCatalog.FindPickupIndex(list[Random.Range(0, list.Count)]), Object.op_Implicit((Object)(object)val3) ? new Vector3?(val3.corePosition) : ((Vector3?)null));
					BaseShrineController.Say("<style=cIsHealth>The reflection shatters. Your prize awaits.</style>");
				}
				else
				{
					BaseShrineController.Say("<style=cIsHealth>The reflection shatters.</style>");
				}
				ResetClone();
				return;
			}
			CharacterBody val4 = (Object.op_Implicit((Object)(object)_buyer) ? _buyer.GetBody() : null);
			if ((Object)(object)val4 == (Object)null || !Object.op_Implicit((Object)(object)val4.healthComponent) || !val4.healthComponent.alive)
			{
				val2.healthComponent.Suicide((GameObject)null, (GameObject)null, default(DamageTypeCombo));
				ResetClone();
				BaseShrineController.Say("<style=cIsUtility>With its original fallen, the reflection fades...</style>");
				return;
			}
			BaseAI component = ((Component)val).GetComponent<BaseAI>();
			if (Object.op_Implicit((Object)(object)component) && (Object)(object)component.currentEnemy.gameObject != (Object)(object)((Component)val4).gameObject)
			{
				component.currentEnemy.gameObject = ((Component)val4).gameObject;
			}
			if (_timeout <= 0f)
			{
				if (Object.op_Implicit((Object)(object)val2))
				{
					val2.healthComponent.Suicide((GameObject)null, (GameObject)null, default(DamageTypeCombo));
				}
				ResetClone();
				BaseShrineController.Say("<style=cIsUtility>The reflection fades...</style>");
			}
		}

		private CharacterMaster FindClone()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = NetworkServer.FindLocalObject(_cloneId);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			return val.GetComponent<CharacterMaster>();
		}

		private void ResetClone()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			_clone = null;
			_buyer = null;
			_cloneId = NetworkInstanceId.Invalid;
		}
	}
	internal static class ShrineAssets
	{
		private const string BundleName = "shrinesbundle";

		private static AssetBundle _bundle;

		private static bool _tried;

		private static readonly List<Stream> _streams = new List<Stream>();

		private static readonly Dictionary<string, GameObject> _models = new Dictionary<string, GameObject>();

		private static readonly HashSet<Material> _converted = new HashSet<Material>();

		internal static bool TryAttachModel(GameObject root, string modelName)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Load(modelName);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			GameObject val2 = Object.Instantiate<GameObject>(val, root.transform);
			((Object)val2).name = "Model";
			Log.Debug("attached model '" + modelName + "' from the shrine bundle");
			val2.transform.localPosition = new Vector3(0f, -0.35f, 0f);
			val2.transform.localRotation = Quaternion.identity;
			val2.transform.localScale = Vector3.one;
			Shader val3 = Shader.Find("Hopoo Games/Deferred/Standard");
			if (!Object.op_Implicit((Object)(object)val3))
			{
				Log.Error("Hopoo standard shader not found; shrine models keep Unity's Standard shader");
				return true;
			}
			Renderer[] componentsInChildren = val2.GetComponentsInChildren<Renderer>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Material[] sharedMaterials = componentsInChildren[i].sharedMaterials;
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					ToHopoo(sharedMaterials[j], val3);
				}
			}
			return true;
		}

		private static void ToHopoo(Material m, Shader hopoo)
		{
			//IL_0031: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)m) && _converted.Add(m))
			{
				bool num = m.IsKeywordEnabled("_EMISSION");
				Color val = (num ? m.GetColor("_EmissionColor") : Color.black);
				Texture val2 = (num ? m.GetTexture("_EmissionMap") : null);
				m.shader = hopoo;
				if (num)
				{
					m.SetTexture("_EmTex", (Texture)(Object.op_Implicit((Object)(object)val2) ? ((object)val2) : ((object)Texture2D.whiteTexture)));
					m.SetColor("_EmColor", val);
					m.SetFloat("_EmPower", 1f);
				}
			}
		}

		internal static GameObject Load(string modelName)
		{
			if (!_tried)
			{
				_tried = true;
				try
				{
					Stream manifestResourceStream = typeof(ShrineAssets).Assembly.GetManifestResourceStream("shrinesbundle");
					if (manifestResourceStream != null)
					{
						_bundle = AssetBundle.LoadFromStream(manifestResourceStream);
						if (Object.op_Implicit((Object)(object)_bundle))
						{
							_streams.Add(manifestResourceStream);
						}
						else
						{
							manifestResourceStream.Dispose();
						}
					}
					if (!Object.op_Implicit((Object)(object)_bundle))
					{
						_bundle = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)ShrinesPlugin.instance).Info.Location), "AssetBundles", "shrinesbundle"));
					}
					if (!Object.op_Implicit((Object)(object)_bundle))
					{
						Log.Error("shrine bundle 'shrinesbundle' not found in the dll or in an AssetBundles folder next to it");
					}
				}
				catch (Exception ex)
				{
					Log.Error("loading the shrine bundle failed: " + ex);
				}
			}
			if ((Object)(object)_bundle == (Object)null)
			{
				return null;
			}
			if (_models.TryGetValue(modelName, out var value))
			{
				return value;
			}
			GameObject val = _bundle.LoadAsset<GameObject>(modelName);
			if ((Object)(object)val == (Object)null)
			{
				Log.Error("the shrine bundle has no '" + modelName + "'");
			}
			_models[modelName] = val;
			return val;
		}
	}
	public static class ShrineKit
	{
		private static readonly List<DirectorCard> _cards = new List<DirectorCard>();

		private static readonly HashSet<DirectorCard> _multiplayerOnly = new HashSet<DirectorCard>();

		private static bool _hooked;

		private static bool _guarded;

		public const string CategoryName = "ModdedShrines";

		public static float CategoryWeight = 10f;

		public static int MinPerStage = 1;

		public static bool InvasionInSolo = false;

		private static GameObject _templates;

		private static readonly HashSet<string> NoGuarantee = new HashSet<string> { "moon", "moon2", "voidraid", "voidstage", "meridian", "space" };

		private const float DROP_OUT = 3.5f;

		private const float DROP_UP = 3f;

		private const float DROP_SPEED_UP = 12f;

		private const float DROP_SPEED_OUT = 7f;

		internal static Transform TemplateParent()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)_templates))
			{
				_templates = new GameObject("ShrinesOfTheTarnishedTemplates");
				_templates.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)_templates);
			}
			return _templates.transform;
		}

		public static GameObject BuildShrineRoot<T>(string name, string nameToken, string contextToken, CostTypeIndex costType, int cost, bool scaleCost) where T : BaseShrineController
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			GameObject val = new GameObject(name)
			{
				layer = LayerIndex.defaultLayer.intVal
			};
			val.transform.SetParent(TemplateParent(), false);
			val.AddComponent<NetworkIdentity>();
			PurchaseInteraction val2 = val.AddComponent<PurchaseInteraction>();
			if (val2.onPurchase == null)
			{
				val2.onPurchase = new PurchaseEvent();
			}
			if (val2.onDetailedPurchaseServer == null)
			{
				val2.onDetailedPurchaseServer = new DetailedPurchaseEvent();
			}
			val2.displayNameToken = nameToken;
			val2.contextToken = contextToken;
			val2.costType = costType;
			val2.cost = cost;
			val2.isShrine = true;
			val2.automaticallyScaleCostWithDifficulty = scaleCost;
			val2.setUnavailableOnTeleporterActivated = true;
			val2.shouldProximityHighlight = true;
			SphereCollider obj = val.AddComponent<SphereCollider>();
			obj.radius = 3.5f;
			obj.center = new Vector3(0f, 1.5f, 0f);
			((Collider)obj).isTrigger = true;
			val.AddComponent<T>();
			return val;
		}

		public static void AddObeliskVisual(GameObject root, Color accent, float height = 2.2f)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			if (!ShrineAssets.TryAttachModel(root, ((Object)root).name))
			{
				GameObject val = new GameObject("Visual");
				val.transform.SetParent(root.transform, false);
				MakePrimitive(val, (PrimitiveType)2, new Vector3(0f, height, 0f), new Vector3(0.9f, height, 0.9f), new Color(0.08f, 0.07f, 0.09f));
				MakePrimitive(val, (PrimitiveType)2, new Vector3(0f, height * 0.55f, 0f), new Vector3(0.95f, 0.08f, 0.95f), accent, emissive: true);
				MakePrimitive(val, (PrimitiveType)2, new Vector3(0f, height * 1.18f, 0f), new Vector3(0.95f, 0.08f, 0.95f), accent, emissive: true);
				MakePrimitive(val, (PrimitiveType)0, new Vector3(0f, height * 1.5f, 0f), new Vector3(0.5f, 0.5f, 0.5f), accent, emissive: true);
			}
		}

		public static Shader ShrineShader()
		{
			string[] array = new string[4] { "Hopoo Games/Deferred/Standard", "Hopoo Games/Deferred/Standard (Specular setup)", "Hopoo Games/FX/Opaque Cloud Remap", "Sprites/Default" };
			foreach (string text in array)
			{
				try
				{
					Shader val = Shader.Find(text);
					if (Object.op_Implicit((Object)(object)val))
					{
						return val;
					}
				}
				catch
				{
				}
			}
			Log.Error("no usable shader found; shrine pieces fall back to the default material");
			return null;
		}

		public static Material NewShrineMaterial(Color color, bool emissive)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			Shader val = ShrineShader();
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			Material val2 = new Material(val);
			val2.color = color;
			if (emissive)
			{
				val2.EnableKeyword("_EMISSION");
				val2.SetColor("_EmissionColor", color * 2.2f);
			}
			return val2;
		}

		public static void MakePrimitive(GameObject parent, PrimitiveType type, Vector3 localPos, Vector3 scale, Color color, bool emissive = false)
		{
			//IL_0000: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.CreatePrimitive(type);
			obj.transform.SetParent(parent.transform, false);
			obj.transform.localPosition = localPos;
			obj.transform.localScale = scale;
			Renderer component = obj.GetComponent<Renderer>();
			Material val = NewShrineMaterial(color, emissive);
			if (Object.op_Implicit((Object)(object)val))
			{
				component.material = val;
			}
		}

		public static void MakeInteractable(GameObject root)
		{
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			Collider[] componentsInChildren = root.GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if ((Object)(object)((Component)val).gameObject != (Object)(object)root && !val.isTrigger)
				{
					((Component)val).gameObject.layer = LayerIndex.world.intVal;
				}
				(((Component)val).GetComponent<EntityLocator>() ?? ((Component)val).gameObject.AddComponent<EntityLocator>()).entity = root;
			}
			if (Object.op_Implicit((Object)(object)root.GetComponent<Highlight>()))
			{
				return;
			}
			Renderer val2 = null;
			float num = -1f;
			Renderer[] componentsInChildren2 = root.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val3 in componentsInChildren2)
			{
				MeshFilter component = ((Component)val3).GetComponent<MeshFilter>();
				float num2;
				if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.sharedMesh))
				{
					num2 = 0f;
				}
				else
				{
					Bounds bounds = component.sharedMesh.bounds;
					Vector3 val4 = Vector3.Scale(((Bounds)(ref bounds)).size, ((Component)val3).transform.lossyScale);
					num2 = ((Vector3)(ref val4)).sqrMagnitude;
				}
				float num3 = num2;
				if (num3 > num)
				{
					num = num3;
					val2 = val3;
				}
			}
			if (Object.op_Implicit((Object)(object)val2))
			{
				Highlight obj = root.AddComponent<Highlight>();
				obj.targetRenderer = val2;
				obj.highlightColor = (HighlightColor)0;
				obj.strength = 1f;
			}
		}

		public static DirectorCard MakeCard(GameObject prefab, int creditCost, int minimumStageCompletions, float weight)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			MakeInteractable(prefab);
			InteractableSpawnCard val = ScriptableObject.CreateInstance<InteractableSpawnCard>();
			((Object)val).name = "isc" + ((Object)prefab).name;
			PrefabAPI.RegisterNetworkPrefab(prefab);
			((SpawnCard)val).prefab = prefab;
			((SpawnCard)val).sendOverNetwork = true;
			((SpawnCard)val).hullSize = (HullClassification)0;
			((SpawnCard)val).nodeGraphType = (GraphType)0;
			((SpawnCard)val).requiredFlags = (NodeFlags)0;
			((SpawnCard)val).forbiddenFlags = (NodeFlags)16;
			((SpawnCard)val).directorCreditCost = creditCost;
			((SpawnCard)val).occupyPosition = true;
			val.orientToFloor = false;
			val.slightlyRandomizeOrientation = false;
			val.maxSpawnsPerStage = 1;
			return new DirectorCard
			{
				spawnCard = (SpawnCard)(object)val,
				selectionWeight = (int)weight,
				preventOverhead = false,
				minimumStageCompletions = minimumStageCompletions
			};
		}

		private static bool IsOurs(PurchaseInteraction pi)
		{
			if (!Object.op_Implicit((Object)(object)pi))
			{
				return false;
			}
			foreach (DirectorCard card in _cards)
			{
				GameObject val = (((Object)(object)card.spawnCard != (Object)null) ? card.spawnCard.prefab : null);
				if ((Object)(object)val != (Object)null && ((Object)((Component)pi).gameObject).name.StartsWith(((Object)val).name, StringComparison.Ordinal))
				{
					return true;
				}
			}
			return false;
		}

		private static bool Allowed(DirectorCard c)
		{
			if (!_multiplayerOnly.Contains(c) || InvasionInSolo)
			{
				return true;
			}
			if (Object.op_Implicit((Object)(object)Run.instance))
			{
				return Run.instance.participatingPlayerCount >= 2;
			}
			return false;
		}

		public static void EnablePerStageGuarantee()
		{
			if (_guarded)
			{
				return;
			}
			_guarded = true;
			SceneDirector.onPostPopulateSceneServer += delegate
			{
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: Invalid comparison between Unknown and I4
				//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
				//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
				//IL_01cf: Expected O, but got Unknown
				//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d1: Expected O, but got Unknown
				try
				{
					SceneDef mostRecentSceneDef = SceneCatalog.mostRecentSceneDef;
					if (Object.op_Implicit((Object)(object)ClassicStageInfo.instance) && Object.op_Implicit((Object)(object)mostRecentSceneDef) && (int)mostRecentSceneDef.sceneType == 1 && !NoGuarantee.Contains(mostRecentSceneDef.cachedName) && _cards.Count != 0 && Object.op_Implicit((Object)(object)Run.instance) && Object.op_Implicit((Object)(object)DirectorCore.instance))
					{
						HashSet<string> hashSet = new HashSet<string>();
						PurchaseInteraction[] array = Object.FindObjectsOfType<PurchaseInteraction>();
						foreach (PurchaseInteraction val in array)
						{
							if (IsOurs(val))
							{
								hashSet.Add(((Object)val).name.Replace("(Clone)", ""));
							}
						}
						int count = hashSet.Count;
						List<DirectorCard> list = new List<DirectorCard>();
						foreach (DirectorCard card in _cards)
						{
							if (Allowed(card) && Object.op_Implicit((Object)(object)card.spawnCard) && !hashSet.Contains(((Object)card.spawnCard.prefab).name))
							{
								list.Add(card);
							}
						}
						for (int num = list.Count - 1; num > 0; num--)
						{
							int index = Run.instance.treasureRng.RangeInt(0, num + 1);
							DirectorCard value = list[num];
							list[num] = list[index];
							list[index] = value;
						}
						List<string> list2 = new List<string>();
						foreach (DirectorCard item in list)
						{
							if (hashSet.Count >= MinPerStage)
							{
								break;
							}
							for (int j = 0; j < 4; j++)
							{
								DirectorSpawnRequest val2 = new DirectorSpawnRequest(item.spawnCard, new DirectorPlacementRule
								{
									placementMode = (PlacementMode)4
								}, Run.instance.treasureRng);
								if (Object.op_Implicit((Object)(object)DirectorCore.instance.TrySpawnObject(val2)))
								{
									hashSet.Add(((Object)item.spawnCard.prefab).name);
									list2.Add(((Object)item.spawnCard.prefab).name);
									break;
								}
							}
						}
						Log.Info(mostRecentSceneDef.cachedName + ": " + hashSet.Count + " Tarnished shrines (" + count + " from the director" + ((list2.Count > 0) ? (", guaranteed " + string.Join(", ", list2)) : "") + ")");
					}
				}
				catch (Exception ex)
				{
					Log.Error("Guaranteed shrine spawn failed: " + ex);
				}
			};
		}

		public static string DevSpawnShrine(string arg)
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Expected O, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Expected O, but got Unknown
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)DirectorCore.instance) || !Object.op_Implicit((Object)(object)Run.instance))
			{
				return "no body/director/run";
			}
			foreach (DirectorCard card in _cards)
			{
				if (!((Object)(object)card.spawnCard == (Object)null) && !((Object)(object)card.spawnCard.prefab == (Object)null) && !(((Object)card.spawnCard.prefab).name != (arg ?? "").Trim()))
				{
					DirectorSpawnRequest val2 = new DirectorSpawnRequest(card.spawnCard, new DirectorPlacementRule
					{
						placementMode = (PlacementMode)1,
						minDistance = 8f,
						maxDistance = 30f,
						position = val.footPosition
					}, Run.instance.treasureRng);
					GameObject val3 = DirectorCore.instance.TrySpawnObject(val2);
					return Object.op_Implicit((Object)(object)val3) ? ("spawned " + ((Object)val3).name + " " + Vector3.Distance(val.transform.position, val3.transform.position).ToString("F0") + " m away") : ("placement failed for " + arg);
				}
			}
			return "no card " + arg;
		}

		public static string DevInteractCheck(string arg)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: 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)
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
			Interactor val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<Interactor>() : null);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				return "no interactor";
			}
			PurchaseInteraction val3 = Nearest(val, arg);
			float num = (Object.op_Implicit((Object)(object)val3) ? Vector3.Distance(val.transform.position, ((Component)val3).transform.position) : 0f);
			if (!Object.op_Implicit((Object)(object)val3))
			{
				return "no shrine of ours";
			}
			Vector3 val4 = (Object.op_Implicit((Object)(object)val.inputBank) ? val.inputBank.aimOrigin : val.corePosition);
			Vector3 val5 = ((Component)val3).transform.position + Vector3.up * 1.5f - val4;
			Ray val6 = default(Ray);
			((Ray)(ref val6))..ctor(val4, ((Vector3)(ref val5)).normalized);
			GameObject val7 = val2.FindBestInteractableObject(val6, num + 5f, val.transform.position, 3f);
			return ((Object)val3).name + " at " + num.ToString("F0") + " m: interactor finds " + (Object.op_Implicit((Object)(object)val7) ? ((Object)val7).name : "NOTHING");
		}

		private static PurchaseInteraction Nearest(CharacterBody body, string kind)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			PurchaseInteraction result = null;
			float num = float.MaxValue;
			PurchaseInteraction[] array = Object.FindObjectsOfType<PurchaseInteraction>();
			foreach (PurchaseInteraction val in array)
			{
				if (IsOurs(val) && (string.IsNullOrWhiteSpace(kind) || ((Object)val).name.StartsWith(kind.Trim(), StringComparison.Ordinal)))
				{
					float num2 = (Object.op_Implicit((Object)(object)body) ? Vector3.Distance(body.transform.position, ((Component)val).transform.position) : 0f);
					if (num2 < num)
					{
						result = val;
						num = num2;
					}
				}
			}
			return result;
		}

		public static string DevUseShrine(string arg)
		{
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Invalid comparison between Unknown and I4
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Invalid comparison between Unknown and I4
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			string[] array = (arg ?? "").Split(',');
			bool flag = array.Length > 1 && array[1].Trim() == "free";
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
			Interactor val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<Interactor>() : null);
			PurchaseInteraction val3 = Nearest(val, array[0]);
			if (!Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)val3))
			{
				return "no interactor or no " + array[0];
			}
			if ((int)val3.costType == 3 && !flag)
			{
				return ((Object)val3).name + " costs a lunar coin; not spent in tests";
			}
			if ((int)val3.costType == 1 && Object.op_Implicit((Object)(object)val.master))
			{
				CharacterMaster master = val.master;
				master.money += (uint)(val3.cost + 100);
			}
			CostTypeIndex costType = val3.costType;
			int cost = val3.cost;
			if (flag)
			{
				val3.costType = (CostTypeIndex)0;
				val3.cost = 0;
			}
			bool available = val3.available;
			try
			{
				val3.OnInteractionBegin(val2);
			}
			finally
			{
				if (flag)
				{
					val3.costType = costType;
					val3.cost = cost;
				}
			}
			return ((Object)val3).name + " cost " + (flag ? "nothing (free test use)" : (val3.cost + " " + ((object)Unsafe.As<CostTypeIndex, CostTypeIndex>(ref val3.costType)/*cast due to .constrained prefix*/).ToString())) + ": available " + available + " -> " + val3.available;
		}

		public static void LaunchDroplet(PickupIndex index, Transform shrine, Vector3? toward = null)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = default(Vector3);
			if (toward.HasValue)
			{
				val = toward.Value - shrine.position;
			}
			else
			{
				Vector2 insideUnitCircle = Random.insideUnitCircle;
				((Vector3)(ref val))..ctor(insideUnitCircle.x, 0f, insideUnitCircle.y);
			}
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				val = shrine.forward;
			}
			((Vector3)(ref val)).Normalize();
			Vector3 val2 = shrine.position + val * 3.5f + Vector3.up * 3f;
			PickupDropletController.CreatePickupDroplet(index, val2, Vector3.up * 12f + val * 7f);
		}

		public static string DevKillPlayer()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.healthComponent))
			{
				return "no body";
			}
			val.healthComponent.godMode = false;
			val.healthComponent.Suicide((GameObject)null, (GameObject)null, default(DamageTypeCombo));
			return "player alive after suicide: " + val.healthComponent.alive;
		}

		public static string DevReport()
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
			StringBuilder stringBuilder = new StringBuilder();
			int num = 0;
			PurchaseInteraction[] array = Object.FindObjectsOfType<PurchaseInteraction>();
			foreach (PurchaseInteraction val2 in array)
			{
				if (IsOurs(val2))
				{
					num++;
					StringBuilder stringBuilder2 = stringBuilder.Append(" | ").Append(((Object)val2).name).Append(" at ");
					Vector3 position = ((Component)val2).transform.position;
					stringBuilder2.Append(((Vector3)(ref position)).ToString("F0"));
					if (Object.op_Implicit((Object)(object)val))
					{
						stringBuilder.Append(' ').Append(Vector3.Distance(val.transform.position, ((Component)val2).transform.position).ToString("F0")).Append(" m");
					}
					Renderer[] componentsInChildren = ((Component)val2).GetComponentsInChildren<Renderer>();
					stringBuilder.Append(" renderers=").Append(componentsInChildren.Length).Append(val2.available ? " available" : " used");
				}
			}
			SceneDef mostRecentSceneDef = SceneCatalog.mostRecentSceneDef;
			return (Object.op_Implicit((Object)(object)mostRecentSceneDef) ? mostRecentSceneDef.cachedName : "?") + ": " + num + " of our shrines" + stringBuilder;
		}

		public static string DevRenderShrine(string arg)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			//IL_0097: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Expected O, but got Unknown
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Expected O, but got Unknown
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
			string[] array = (arg ?? "shrine").Split(',');
			PurchaseInteraction val2 = Nearest(val, (array.Length > 1) ? array[1] : null);
			float num = ((Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val)) ? Vector3.Distance(val.transform.position, ((Component)val2).transform.position) : 0f);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				return "no shrine of ours in this stage";
			}
			arg = array[0];
			GameObject val3 = new GameObject("ShrineDevCam");
			try
			{
				Camera obj = val3.AddComponent<Camera>();
				Vector3 val4 = ((Component)val2).transform.position + ((Component)val2).transform.up * 2.5f;
				((Component)obj).transform.position = val4 + new Vector3(8f, 3f, 8f);
				((Component)obj).transform.LookAt(val4);
				obj.fieldOfView = 50f;
				RenderTexture val5 = (obj.targetTexture = new RenderTexture(1280, 720, 24, (RenderTextureFormat)0));
				obj.Render();
				RenderTexture.active = val5;
				Texture2D val7 = new Texture2D(((Texture)val5).width, ((Texture)val5).height, (TextureFormat)3, false);
				val7.ReadPixels(new Rect(0f, 0f, (float)((Texture)val5).width, (float)((Texture)val5).height), 0, 0);
				RenderTexture.active = null;
				string text = Path.Combine(Paths.BepInExRootPath, "devout");
				Directory.CreateDirectory(text);
				File.WriteAllBytes(Path.Combine(text, (arg ?? "shrine") + ".png"), ImageConversion.EncodeToPNG(val7));
				obj.targetTexture = null;
				Object.Destroy((Object)(object)val5);
				Object.Destroy((Object)(object)val7);
			}
			finally
			{
				Object.Destroy((Object)(object)val3);
			}
			return "rendered " + ((Object)val2).name + " (" + num.ToString("F0") + " m away)";
		}

		public static void RegisterCard(DirectorCard card, float weight, bool multiplayerOnly = false)
		{
			card.selectionWeight = (int)weight;
			_cards.Add(card);
			if (multiplayerOnly)
			{
				_multiplayerOnly.Add(card);
			}
			if (_hooked)
			{
				return;
			}
			_hooked = true;
			SceneDirector.onGenerateInteractableCardSelection += delegate(SceneDirector director, DirectorCardCategorySelection selection)
			{
				try
				{
					int num = selection.FindCategoryIndexByName("ModdedShrines");
					if (num < 0)
					{
						num = selection.AddCategory("ModdedShrines", CategoryWeight);
					}
					int num2 = 0;
					foreach (DirectorCard card2 in _cards)
					{
						if (card2.IsAvailable() && Allowed(card2))
						{
							selection.AddCard(num, card2);
							num2++;
						}
					}
					Log.Debug("Shrines injected: " + num2 + " (category weight " + CategoryWeight + ")");
				}
				catch (Exception ex)
				{
					Log.Error("Shrine injection failed: " + ex);
				}
			};
		}
	}
	public abstract class BaseShrineController : NetworkBehaviour
	{
		protected PurchaseInteraction _purchase;

		protected bool _used;

		protected virtual void Awake()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			_purchase = ((Component)this).GetComponentInParent<PurchaseInteraction>() ?? ((Component)this).GetComponent<PurchaseInteraction>();
			if (Object.op_Implicit((Object)(object)_purchase))
			{
				if (_purchase.onPurchase == null)
				{
					_purchase.onPurchase = new PurchaseEvent();
				}
				((UnityEvent<Interactor>)(object)_purchase.onPurchase).AddListener((UnityAction<Interactor>)OnPurchased);
			}
		}

		[Server]
		protected virtual void OnPurchased(Interactor interactor)
		{
			if (!_used)
			{
				_used = true;
				if (Object.op_Implicit((Object)(object)_purchase))
				{
					_purchase.SetAvailable(false);
				}
			}
		}

		protected static int ScaledCost(int baseCost)
		{
			if (!Object.op_Implicit((Object)(object)Run.instance))
			{
				return baseCost;
			}
			return Run.instance.GetDifficultyScaledCost(baseCost);
		}

		protected static PickupIndex? PickFromTier(List<PickupIndex> list, List<PickupIndex> fallback)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			List<PickupIndex> list2 = ((list != null && list.Count > 0) ? list : fallback);
			if (list2 == null || list2.Count == 0)
			{
				return null;
			}
			return list2[Random.Range(0, list2.Count)];
		}

		protected void DropPickup(PickupIndex index, Vector3? toward = null)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			ShrineKit.LaunchDroplet(index, ((Component)this).transform, toward);
		}

		protected static void Say(string message)
		{
			Chat.ServerAttemptBroadcastChat(message);
		}

		protected static List<ItemIndex> OwnedItems(Inventory inv, Func<ItemDef, bool> filter)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Invalid comparison between Unknown and I4
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			List<ItemIndex> list = new List<ItemIndex>();
			if (!Object.op_Implicit((Object)(object)inv))
			{
				return list;
			}
			for (int i = 0; i < ItemCatalog.itemCount; i++)
			{
				ItemIndex val = (ItemIndex)i;
				if (inv.GetItemCountPermanent(val) <= 0)
				{
					continue;
				}
				ItemDef itemDef = ItemCatalog.GetItemDef(val);
				if (!((Object)(object)itemDef == (Object)null) && !itemDef.hidden && (int)itemDef.tier != 5)
				{
					PickupIndex val2 = PickupCatalog.FindPickupIndex(val);
					if (((PickupIndex)(ref val2)).isValid && (filter == null || filter(itemDef)))
					{
						list.Add(val);
					}
				}
			}
			return list;
		}

		protected void Refund(CharacterMaster buyer, int paid)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Invalid comparison between Unknown and I4
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Invalid comparison between Unknown and I4
			_used = false;
			if (Object.op_Implicit((Object)(object)_purchase))
			{
				_purchase.SetAvailable(true);
			}
			if (!Object.op_Implicit((Object)(object)buyer) || !Object.op_Implicit((Object)(object)_purchase) || paid <= 0)
			{
				return;
			}
			if ((int)_purchase.costType == 1)
			{
				buyer.money += (uint)paid;
			}
			else
			{
				if ((int)_purchase.costType != 3)
				{
					return;
				}
				foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList)
				{
					if (Object.op_Implicit((Object)(object)readOnlyInstances.masterController) && (Object)(object)readOnlyInstances.masterController.master == (Object)(object)buyer)
					{
						readOnlyInstances.AwardLunarCoins((uint)paid);
						break;
					}
				}
			}
		}
	}
	public class SwarmShrineController : BaseShrineController
	{
		private const int WAVES = 3;

		private const float WAVE_INTERVAL = 15f;

		private const float FIRST_WAVE = 2f;

		private const float TIME_TO_CLEAR = 30f;

		private const float TOTAL_DURATION = 62f;

		private const float CHANCE_RED = 0.01f;

		private const float CHANCE_WHITE = 0.8f;

		private const float CHANCE_GREEN = 0.095f;

		private const float BASE_WAVE_CREDIT = 100f;

		private const float STAGE_AHEAD = 1.15f;

		private int _wavesSpawned;

		private float _nextWave;

		private float _timeLeft;

		private bool _running;

		private Xoroshiro128Plus _rng;

		private readonly List<CharacterMaster> _monsters = new List<CharacterMaster>();

		[Server]
		protected override void OnPurchased(Interactor interactor)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			if (!_used)
			{
				base.OnPurchased(interactor);
				_running = true;
				_wavesSpawned = 0;
				_monsters.Clear();
				_nextWave = 2f;
				_timeLeft = 62f;
				_rng = new Xoroshiro128Plus(Object.op_Implicit((Object)(object)Run.instance) ? Run.instance.treasureRng.nextUlong : ((ulong)DateTime.Now.Ticks));
				BaseShrineController.Say("<style=cIsHealing>The Swarm awakens! Slay all " + 3 + " waves for the shrine's hoard!</style>");
			}
		}

		[Server]
		private void FixedUpdate()
		{
			if (_running)
			{
				_timeLeft -= Time.fixedDeltaTime;
				_nextWave -= Time.fixedDeltaTime;
				if (_wavesSpawned < 3 && _nextWave <= 0f)
				{
					SpawnWave(_wavesSpawned + 1);
					_wavesSpawned++;
					_nextWave = 15f;
				}
				if (_wavesSpawned >= 3 && AliveMonsters() == 0)
				{
					_running = false;
					DropReward();
					BaseShrineController.Say("<style=cIsHealth>The Swarm is slain. The hoard is yours.</style>");
				}
				else if (_timeLeft <= 0f)
				{
					_running = false;
					BaseShrineController.Say("<style=cIsHealth>The Swarm endures. The hoard is lost.</style>");
				}
			}
		}

		private int AliveMonsters()
		{
			int num = 0;
			foreach (CharacterMaster monster in _monsters)
			{
				CharacterBody val = (Object.op_Implicit((Object)(object)monster) ? monster.GetBody() : null);
				if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.healthComponent) && val.healthComponent.alive)
				{
					num++;
				}
			}
			return num;
		}

		[Server]
		private void DropReward()
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			Run instance = Run.instance;
			if (Object.op_Implicit((Object)(object)instance))
			{
				float nextNormalizedFloat = _rng.nextNormalizedFloat;
				List<PickupIndex> list = ((nextNormalizedFloat < 0.01f) ? instance.availableTier3DropList : ((nextNormalizedFloat < 0.81f) ? instance.availableTier1DropList : ((!(nextNormalizedFloat < 0.905f)) ? instance.availableBossDropList : instance.availableTier2DropList)));
				PickupIndex? val = BaseShrineController.PickFromTier(list, instance.availableTier1DropList);
				if (val.HasValue)
				{
					DropPickup(val.Value);
				}
			}
		}

		[Server]
		private void SpawnWave(int wave)
		{
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Expected O, but got Unknown
			int num = wave + 2;
			float num2 = (Object.op_Implicit((Object)(object)Run.instance) ? Run.instance.difficultyCoefficient : 1f);
			int num3 = Mathf.Max(1, Mathf.RoundToInt(num2 * 0.14999998f / 0.33f));
			DirectorCard val = PickMonster(num, wave);
			if (val == null)
			{
				Log.Warning("Swarm: this stage has no monster to send");
				return;
			}
			BaseShrineController.Say("<style=cIsHealth>Wave " + wave + "/" + 3 + "!</style>");
			int num4 = 0;
			for (int i = 0; i < num; i++)
			{
				DirectorSpawnRequest val2 = new DirectorSpawnRequest(val.GetSpawnCard(), new DirectorPlacementRule
				{
					placementMode = (PlacementMode)1,
					position = ((Component)this).transform.position,
					minDistance = 8f,
					maxDistance = 30f
				}, _rng)
				{
					teamIndexOverride = (TeamIndex)2,
					ignoreTeamMemberLimit = true
				};
				GameObject val3 = (Object.op_Implicit((Object)(object)DirectorCore.instance) ? DirectorCore.instance.TrySpawnObject(val2) : null);
				CharacterMaster val4 = (Object.op_Implicit((Object)(object)val3) ? val3.GetComponent<CharacterMaster>() : null);
				if (Object.op_Implicit((Object)(object)val4))
				{
					_monsters.Add(val4);
					num4++;
					if (Object.op_Implicit((Object)(object)val4.inventory))
					{
						val4.inventory.GiveItemPermanent(Items.LevelBonus, num3);
					}
					CharacterBody body = val4.GetBody();
					if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)body.healthComponent))
					{
						body.RecalculateStats();
						body.healthComponent.health = body.healthComponent.fullHealth;
					}
				}
			}
			Log.Debug("Swarm wave " + wave + ": " + num4 + "/" + num + " " + ((Object)val.GetSpawnCard()).name + " (+" + num3 + " levels)");
		}

		private DirectorCard PickMonster(int count, int wave)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			WeightedSelection<DirectorCard> val = (Object.op_Implicit((Object)(object)ClassicStageInfo.instance) ? ClassicStageInfo.instance.monsterSelection : null);
			if (val == null)
			{
				return null;
			}
			float num = 100f * (Object.op_Implicit((Object)(object)Run.instance) ? Run.instance.difficultyCoefficient : 1f) * 1.15f * (1f + 0.25f * (float)(wave - 1));
			WeightedSelection<DirectorCard> val2 = new WeightedSelection<DirectorCard>(8);
			DirectorCard val3 = null;
			for (int i = 0; i < val.Count; i++)
			{
				ChoiceInfo<DirectorCard> val4 = val.choices[i];
				DirectorCard value = val4.value;
				if (value == null || !value.IsAvailable())
				{
					continue;
				}
				SpawnCard spawnCard = value.GetSpawnCard();
				CharacterSpawnCard val5 = (CharacterSpawnCard)(object)((spawnCard is CharacterSpawnCard) ? spawnCard : null);
				CharacterMaster val6 = ((Object.op_Implicit((Object)(object)val5) && Object.op_Implicit((Object)(object)((SpawnCard)val5).prefab)) ? ((SpawnCard)val5).prefab.GetComponent<CharacterMaster>() : null);
				CharacterBody val7 = ((Object.op_Implicit((Object)(object)val6) && Object.op_Implicit((Object)(object)val6.bodyPrefab)) ? val6.bodyPrefab.GetComponent<CharacterBody>() : null);
				if (Object.op_Implicit((Object)(object)val7) && !val7.isChampion)
				{
					if (val3 == null || value.cost < val3.cost)
					{
						val3 = value;
					}
					if ((float)(value.cost * count) <= num)
					{
						val2.AddChoice(value, val4.weight);
					}
				}
			}
			if (val2.Count <= 0)
			{
				return val3;
			}
			return val2.Evaluate(_rng.nextNormalizedFloat);
		}
	}
}