Decompiled source of Loop The Gungeon v1.0.2

LoopTheGungeon.dll

Decompiled 2 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Alexandria.CharacterAPI;
using Alexandria.DungeonAPI;
using Alexandria.ItemAPI;
using Alexandria.Misc;
using Alexandria.NPCAPI;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Brave.BulletScript;
using Dungeonator;
using HarmonyLib;
using HutongGames.PlayMaker;
using InControl;
using LoopTheGungeon.Config;
using LoopTheGungeon.Console;
using LoopTheGungeon.Content;
using LoopTheGungeon.Core;
using LoopTheGungeon.Patches;
using LoopTheGungeon.Util;
using LoopTheGungeon.Visuals;
using Microsoft.CodeAnalysis;
using SGUI;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("LoopTheGungeon")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LoopTheGungeon")]
[assembly: AssemblyCopyright("Copyright ©  2020")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("d6d7a494-722e-4763-959b-c2d6b6a42b01")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
}
public static class HellRage
{
	public struct RageSnapshot
	{
		public int Stacks;

		public float Duration;

		public float DamageMult;
	}

	public class HellRageOnCombat : MonoBehaviour
	{
		private float _currentDamageMultiplier = 1.2f;

		private float _currentDuration = 3f;

		private Color _currentFlatColor = new Color(0.5f, 0f, 0f, 0.75f);

		private PlayerController _owner;

		private Action _enteredCombatHandler;

		private Coroutine _activationCo;

		private Coroutine _rageCo;

		private StatModifier _damageMod;

		private float _rageTimeLeft;

		private bool _buffActive;

		public void Init(PlayerController owner)
		{
			_owner = owner;
			if (_enteredCombatHandler == null)
			{
				_enteredCombatHandler = OnEnteredCombat;
			}
			if ((Object)(object)_owner != (Object)null)
			{
				PlayerController owner2 = _owner;
				owner2.OnEnteredCombat = (Action)Delegate.Remove(owner2.OnEnteredCombat, _enteredCombatHandler);
				PlayerController owner3 = _owner;
				owner3.OnEnteredCombat = (Action)Delegate.Combine(owner3.OnEnteredCombat, _enteredCombatHandler);
			}
		}

		private void OnDestroy()
		{
			CleanupSubscriptions();
			CleanupBuff(_owner);
		}

		private void CleanupSubscriptions()
		{
			if ((Object)(object)_owner != (Object)null && _enteredCombatHandler != null)
			{
				PlayerController owner = _owner;
				owner.OnEnteredCombat = (Action)Delegate.Remove(owner.OnEnteredCombat, _enteredCombatHandler);
			}
			_enteredCombatHandler = null;
			_owner = null;
		}

		private void OnEnteredCombat()
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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)
			if ((Object)(object)_owner == (Object)null)
			{
				return;
			}
			int rageStacks = GetRageStacks(_owner);
			if (rageStacks > 0)
			{
				float num = 2f + 2f * (float)rageStacks;
				_currentDuration = Mathf.Min(num, 10f);
				float num2 = 1.2f;
				if (rageStacks > 4)
				{
					_currentDamageMultiplier = num2 + (float)(rageStacks - 4) * 0.1f;
					_currentFlatColor = new Color(0.388f, 0.067f, 0.729f, 0.75f);
				}
				else
				{
					_currentDamageMultiplier = num2;
					_currentFlatColor = new Color(0.5f, 0f, 0f, 0.75f);
				}
				_rageTimeLeft = _currentDuration;
				if (_rageCo == null)
				{
					_rageCo = ((MonoBehaviour)_owner).StartCoroutine(RageCR(_owner));
				}
			}
		}

		private IEnumerator RageCR(PlayerController player)
		{
			yield return (object)new WaitForSeconds(0.5f);
			if (!_buffActive)
			{
				_buffActive = true;
				_damageMod = new StatModifier
				{
					amount = _currentDamageMultiplier,
					modifyType = (ModifyMethod)1,
					statToBoost = (StatType)5
				};
				player.ownerlessStatModifiers.Add(_damageMod);
				player.stats.RecalculateStats(player, false, false);
				if ((Object)(object)((GameActor)player).CurrentGun != (Object)null)
				{
					((GameActor)player).CurrentGun.ForceImmediateReload(false);
				}
			}
			float particleCounter = 0f;
			while (_rageTimeLeft > 0f)
			{
				_rageTimeLeft -= BraveTime.DeltaTime;
				float num = ((_rageTimeLeft <= 1f) ? (1f - _rageTimeLeft) : 0f);
				player.baseFlatColorOverride = Vector3Extensions.WithAlpha(_currentFlatColor, Mathf.Lerp(_currentFlatColor.a, 0f, num));
				if ((int)GameManager.Options.ShaderQuality != 0 && (int)GameManager.Options.ShaderQuality != 3 && Object.op_Implicit((Object)(object)player) && player.IsVisible && !((GameActor)player).IsFalling)
				{
					particleCounter += BraveTime.DeltaTime * 40f;
					if (particleCounter > 1f)
					{
						int num2 = Mathf.FloorToInt(particleCounter);
						particleCounter %= 1f;
						GlobalSparksDoer.DoRandomParticleBurst(num2, Vector2Extensions.ToVector3ZisY(((BraveBehaviour)player).sprite.WorldBottomLeft, 0f), Vector2Extensions.ToVector3ZisY(((BraveBehaviour)player).sprite.WorldTopRight, 0f), Vector3.up, 90f, 0.5f, (float?)null, (float?)null, (Color?)null, (SparksType)1);
					}
				}
				yield return null;
				if ((Object)(object)player == (Object)null)
				{
					break;
				}
			}
			CleanupBuff(player);
			_rageCo = null;
		}

		public void PlayActivationFx(float seconds = 2f, int burstCount = 40)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_owner == (Object)null))
			{
				if (GetRageStacks(_owner) > 4)
				{
					_currentFlatColor = new Color(0.388f, 0.067f, 0.729f, 0.75f);
				}
				else
				{
					_currentFlatColor = new Color(0.5f, 0f, 0f, 0.75f);
				}
				if (_activationCo != null)
				{
					((MonoBehaviour)_owner).StopCoroutine(_activationCo);
				}
				_activationCo = ((MonoBehaviour)_owner).StartCoroutine(ActivationFxCR(_owner, seconds, burstCount));
			}
		}

		private IEnumerator ActivationFxCR(PlayerController player, float seconds, int burstCount)
		{
			if (!Object.op_Implicit((Object)(object)player))
			{
				yield break;
			}
			try
			{
				if ((int)GameManager.Options.ShaderQuality != 0 && (int)GameManager.Options.ShaderQuality != 3 && player.IsVisible && !((GameActor)player).IsFalling && (Object)(object)((BraveBehaviour)player).sprite != (Object)null)
				{
					GlobalSparksDoer.DoRandomParticleBurst(Mathf.Max(1, burstCount), Vector2Extensions.ToVector3ZisY(((BraveBehaviour)player).sprite.WorldBottomLeft, 0f), Vector2Extensions.ToVector3ZisY(((BraveBehaviour)player).sprite.WorldTopRight, 0f), Vector3.up, 90f, 0.6f, (float?)null, (float?)null, (Color?)null, (SparksType)1);
				}
			}
			catch
			{
			}
			float t = 0f;
			float dur = Mathf.Max(0.05f, seconds);
			while (t < dur && Object.op_Implicit((Object)(object)player) && _rageCo == null)
			{
				t += BraveTime.DeltaTime;
				float num = 1f - Mathf.Clamp01(t / dur);
				player.baseFlatColorOverride = Vector3Extensions.WithAlpha(_currentFlatColor, _currentFlatColor.a * num);
				yield return null;
			}
			if (Object.op_Implicit((Object)(object)player))
			{
				player.baseFlatColorOverride = Color.clear;
			}
			_activationCo = null;
		}

		private void CleanupBuff(PlayerController player)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player != (Object)null)
			{
				player.baseFlatColorOverride = Color.clear;
				if (_buffActive && _damageMod != null)
				{
					player.ownerlessStatModifiers.Remove(_damageMod);
					player.stats.RecalculateStats(player, false, false);
				}
			}
			_damageMod = null;
			_buffActive = false;
			_rageTimeLeft = 0f;
		}
	}

	public static int GetRageStacks(PlayerController p)
	{
		if (!Object.op_Implicit((Object)(object)p))
		{
			return 0;
		}
		MasteryShrineInteractable.ShrineRageMarker component = ((Component)p).GetComponent<MasteryShrineInteractable.ShrineRageMarker>();
		if (!Object.op_Implicit((Object)(object)component))
		{
			return 0;
		}
		return Mathf.Max(0, component.Stacks);
	}

	public static RageSnapshot GetRageSnapshot(PlayerController p)
	{
		RageSnapshot result = default(RageSnapshot);
		int num = (result.Stacks = GetRageStacks(p));
		if (num <= 0)
		{
			result.Duration = 0f;
			result.DamageMult = 1f;
			return result;
		}
		float num2 = 2f + 2f * (float)num;
		result.Duration = Mathf.Min(num2, 10f);
		float num3 = 1.2f;
		if (num > 4)
		{
			result.DamageMult = num3 + (float)(num - 4) * 0.1f;
		}
		else
		{
			result.DamageMult = num3;
		}
		return result;
	}
}
namespace Mod.Patches
{
	[HarmonyPatch(typeof(InfinilichDeathController), "HandleClockhair")]
	public static class Patch_InfinilichDeathController_HandleClockhair
	{
		private static bool _loopShotTriggeredThisClockhair;

		private static Vector2 _camVel;

		private const float MAX_CAM_DRIFT_FROM_LICH = 25f;

		private const float EDGE_UV = 0.1f;

		private const float PAN_SPEED_MAX = 5f;

		private const float PAN_ACCEL = 10f;

		[HarmonyPrefix]
		private static bool Prefix(InfinilichDeathController __instance, PlayerController interactor, ref IEnumerator __result)
		{
			__result = CustomHandleClockhair(__instance, interactor);
			return false;
		}

		private static IEnumerator CustomHandleClockhair(InfinilichDeathController self, PlayerController interactor)
		{
			_loopShotTriggeredThisClockhair = false;
			_camVel = Vector2.zero;
			try
			{
				GameManager.Instance.PrimaryPlayer.SetInputOverride("past");
				if ((int)GameManager.Instance.CurrentGameType == 1 && Object.op_Implicit((Object)(object)GameManager.Instance.SecondaryPlayer))
				{
					GameManager.Instance.SecondaryPlayer.SetInputOverride("past");
				}
				GameUIRoot.Instance.ToggleLowerPanels(false, false, string.Empty);
				GameUIRoot.Instance.HideCoreUI(string.Empty);
				CameraController camera = GameManager.Instance.MainCameraController;
				Vector2 val = Vector2.op_Implicit(camera.OverridePosition);
				Vector2 desiredCamCenter = ((BraveBehaviour)((BraveBehaviour)self).aiAnimator).sprite.WorldCenter;
				camera.SetManualControl(true, true);
				_camVel = Vector2.zero;
				if (Vector2.Distance(val, desiredCamCenter) > 2.5f)
				{
					camera.OverridePosition = Vector2.op_Implicit(desiredCamCenter);
				}
				Transform clockhairTransform = ((GameObject)Object.Instantiate(BraveResources.Load("Clockhair", ".prefab"))).transform;
				ClockhairController clockhair = ((Component)clockhairTransform).GetComponent<ClockhairController>();
				float elapsed = 0f;
				float duration = clockhair.ClockhairInDuration;
				Vector3 clockhairTargetPosition = Vector2.op_Implicit(((GameActor)GameManager.Instance.PrimaryPlayer).CenterPosition);
				Vector3 clockhairStartPosition = clockhairTargetPosition + new Vector3(-20f, 5f, 0f);
				((BraveBehaviour)clockhair).renderer.enabled = true;
				((BraveBehaviour)clockhair).spriteAnimator.alwaysUpdateOffscreen = true;
				((BraveBehaviour)clockhair).spriteAnimator.Play("clockhair_intro");
				clockhair.hourAnimator.Play("hour_hand_intro");
				clockhair.minuteAnimator.Play("minute_hand_intro");
				clockhair.secondAnimator.Play("second_hand_intro");
				while (elapsed < duration)
				{
					if (GameManager.INVARIANT_DELTA_TIME == 0f)
					{
						elapsed += 0.05f;
					}
					elapsed += GameManager.INVARIANT_DELTA_TIME;
					float num = elapsed / duration;
					float num2 = Mathf.SmoothStep(0f, 1f, num);
					clockhairTargetPosition = Vector2.op_Implicit(GetTargetClockhairPosition(self, Vector3Extensions.XY(clockhairTargetPosition)));
					Vector3 val2 = Vector3.Slerp(clockhairStartPosition, clockhairTargetPosition, num2);
					clockhairTransform.position = Vector3Extensions.WithZ(val2, 0f);
					UpdateCameraDuringLichClockhair(camera, desiredCamCenter);
					UpdateEyes(self, Vector3Extensions.XY(clockhairTransform.position), isInDanger: false);
					if (num > 0.5f)
					{
						((BraveBehaviour)clockhair).renderer.enabled = true;
					}
					if (num > 0.75f)
					{
						((Component)clockhair.hourAnimator).GetComponent<Renderer>().enabled = true;
						((Component)clockhair.minuteAnimator).GetComponent<Renderer>().enabled = true;
						((Component)clockhair.secondAnimator).GetComponent<Renderer>().enabled = true;
					}
					((BraveBehaviour)clockhair).sprite.UpdateZDepth();
					yield return null;
				}
				clockhair.SetMotionType(1f);
				BraveInput currentInput = BraveInput.GetInstanceForPlayer(GameManager.Instance.PrimaryPlayer.PlayerIDX);
				float shotTargetTime2 = 0f;
				float holdDuration = 3f;
				Vector3 lastScreenShakeAmount = Vector3.zero;
				Vector3 lastJitterAmount = Vector3.zero;
				bool targetingPlayer;
				PlayerController targetedPlayer;
				while (true)
				{
					Transform transform = ((BraveBehaviour)clockhair).transform;
					transform.position -= lastJitterAmount;
					((BraveBehaviour)clockhair).transform.position = Vector2.op_Implicit(GetTargetClockhairPosition(self, Vector3Extensions.XY(((BraveBehaviour)clockhair).transform.position)));
					((BraveBehaviour)clockhair).sprite.UpdateZDepth();
					bool num3 = CheckLichTarget(self, clockhairTransform);
					targetingPlayer = false;
					targetedPlayer = null;
					if (Object.op_Implicit((Object)(object)GameManager.Instance.PrimaryPlayer) && Object.op_Implicit((Object)(object)((BraveBehaviour)GameManager.Instance.PrimaryPlayer).healthHaver) && ((BraveBehaviour)GameManager.Instance.PrimaryPlayer).healthHaver.IsAlive && CheckPlayerTarget(GameManager.Instance.PrimaryPlayer, clockhairTransform))
					{
						targetingPlayer = true;
						targetedPlayer = GameManager.Instance.PrimaryPlayer;
					}
					if (!targetingPlayer && (int)GameManager.Instance.CurrentGameType == 1 && Object.op_Implicit((Object)(object)GameManager.Instance.SecondaryPlayer) && Object.op_Implicit((Object)(object)((BraveBehaviour)GameManager.Instance.SecondaryPlayer).healthHaver) && ((BraveBehaviour)GameManager.Instance.SecondaryPlayer).healthHaver.IsAlive && CheckPlayerTarget(GameManager.Instance.SecondaryPlayer, clockhairTransform))
					{
						targetingPlayer = true;
						targetedPlayer = GameManager.Instance.SecondaryPlayer;
					}
					bool flag = num3 || targetingPlayer;
					clockhair.SetMotionType(flag ? (-10f) : 1f);
					bool flag2 = ((OneAxisInputControl)currentInput.ActiveActions.ShootAction).IsPressed || ((OneAxisInputControl)currentInput.ActiveActions.InteractAction).IsPressed;
					shotTargetTime2 = ((flag2 && flag) ? (shotTargetTime2 + BraveTime.DeltaTime) : Mathf.Max(0f, shotTargetTime2 - BraveTime.DeltaTime * 3f));
					UpdateCameraDuringLichClockhair(camera, desiredCamCenter);
					UpdateEyes(self, Vector3Extensions.XY(((BraveBehaviour)clockhair).transform.position), flag2);
					if ((((OneAxisInputControl)currentInput.ActiveActions.ShootAction).WasReleased || ((OneAxisInputControl)currentInput.ActiveActions.InteractAction).WasReleased) && flag && shotTargetTime2 > holdDuration && !GameManager.Instance.IsPaused)
					{
						break;
					}
					if (shotTargetTime2 > 0f)
					{
						lastScreenShakeAmount = camera.DoFrameScreenShake(Mathf.Lerp(0f, 0.5f, shotTargetTime2 / holdDuration), Mathf.Lerp(3f, 8f, shotTargetTime2 / holdDuration), Vector2.op_Implicit(Vector3.right), lastScreenShakeAmount, Time.realtimeSinceStartup);
						float num4 = Mathf.Lerp(0f, 0.35f, shotTargetTime2 / holdDuration);
						float num5 = 0.5f;
						float num6 = Mathf.Lerp(4f, 7f, shotTargetTime2 / holdDuration);
						clockhair.UpdateDistortion(num4, num5, num6);
						float num7 = Mathf.Lerp(2f, 0.25f, shotTargetTime2 / holdDuration);
						clockhair.UpdateDesat(true, num7);
						shotTargetTime2 = Mathf.Min(holdDuration + 0.25f, shotTargetTime2 + BraveTime.DeltaTime);
						float num8 = Mathf.Lerp(0f, 0.5f, (shotTargetTime2 - 1f) / (holdDuration - 1f));
						Vector3 val3 = Vector2Extensions.ToVector3ZUp(Random.insideUnitCircle * num8, 0f);
						BraveInput.DoSustainedScreenShakeVibration(shotTargetTime2 / holdDuration * 0.8f);
						Transform transform2 = ((BraveBehaviour)clockhair).transform;
						transform2.position += val3;
						lastJitterAmount = val3;
						clockhair.SetMotionType(Mathf.Lerp(-10f, -2400f, shotTargetTime2 / holdDuration));
					}
					else
					{
						lastJitterAmount = Vector3.zero;
						camera.ClearFrameScreenShake(lastScreenShakeAmount);
						lastScreenShakeAmount = Vector3.zero;
						clockhair.UpdateDistortion(0f, 0f, 0f);
						clockhair.UpdateDesat(false, 0f);
						shotTargetTime2 = 0f;
						BraveInput.DoSustainedScreenShakeVibration(0f);
					}
					yield return null;
				}
				camera.ClearFrameScreenShake(lastScreenShakeAmount);
				BraveInput.DoSustainedScreenShakeVibration(0f);
				BraveInput.DoVibrationForAllPlayers((Time)10, (Strength)30);
				((MonoBehaviour)clockhair).StartCoroutine(clockhair.WipeoutDistortionAndFade(0.5f));
				GameObjectExtensions.SetLayerRecursively(((Component)clockhair).gameObject, LayerMask.NameToLayer("Unoccluded"));
				Pixelator.Instance.FadeToBlack(0.2f, true, 0.2f);
				Pixelator.Instance.DoRenderGBuffer = false;
				Pixelator.Instance.LerpToLetterbox(0.45f, 0.45f);
				((BraveBehaviour)clockhair).spriteAnimator.PlayAndDisableRenderer("clockhair_fire");
				((Component)clockhair.hourAnimator).GetComponent<Renderer>().enabled = false;
				((Component)clockhair.minuteAnimator).GetComponent<Renderer>().enabled = false;
				((Component)clockhair.secondAnimator).GetComponent<Renderer>().enabled = false;
				yield return null;
				if (!targetingPlayer || !((Object)(object)targetedPlayer != (Object)null) || _loopShotTriggeredThisClockhair)
				{
					yield break;
				}
				_loopShotTriggeredThisClockhair = true;
				LoopManager.PendingLichRewards = true;
				try
				{
					clockhair.UpdateDesat(false, 0f);
				}
				catch
				{
				}
				try
				{
					clockhair.UpdateDistortion(0f, 0f, 0f);
				}
				catch
				{
				}
				try
				{
					GameManager.Instance.PrimaryPlayer.ClearInputOverride("past");
				}
				catch
				{
				}
				try
				{
					if (Object.op_Implicit((Object)(object)GameManager.Instance.SecondaryPlayer))
					{
						GameManager.Instance.SecondaryPlayer.ClearInputOverride("past");
					}
				}
				catch
				{
				}
				try
				{
					((MonoBehaviour)GameManager.Instance).StopAllCoroutines();
				}
				catch
				{
				}
				try
				{
					LoopManager.LoopLoadingScreenState.UseCustomLoadScreenOnce = true;
				}
				catch
				{
				}
				try
				{
					TimeTubeTransition.StartLoopTimeTubeThenLoop((MonoBehaviour)(object)GameManager.Instance, 0f, "Lich");
				}
				catch
				{
				}
			}
			finally
			{
				_camVel = Vector2.zero;
			}
		}

		private static void UpdateCameraDuringLichClockhair(CameraController cam, Vector2 lichAnchor)
		{
			//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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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)
			//IL_0099: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: 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)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: 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_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)cam == (Object)null) && !((Object)(object)cam.Camera == (Object)null))
			{
				Vector3 val = cam.Camera.ScreenToViewportPoint(Input.mousePosition);
				float num = 0f;
				if (val.x < 0.1f)
				{
					num = (val.x - 0.1f) / 0.1f;
				}
				else if (val.x > 0.9f)
				{
					num = (val.x - 0.9f) / 0.1f;
				}
				float num2 = 0f;
				if (val.y < 0.1f)
				{
					num2 = (val.y - 0.1f) / 0.1f;
				}
				else if (val.y > 0.9f)
				{
					num2 = (val.y - 0.9f) / 0.1f;
				}
				Vector2 val2 = new Vector2(num, num2) * 5f;
				_camVel = Vector2.MoveTowards(_camVel, val2, BraveTime.DeltaTime * 10f);
				Vector2 val3 = Vector2.op_Implicit(cam.OverridePosition) + _camVel * BraveTime.DeltaTime;
				float num3 = Vector2.Distance(val3, lichAnchor);
				if (num3 > 25f && num3 > 0.001f)
				{
					val3 = lichAnchor + (val3 - lichAnchor) * (25f / num3);
				}
				cam.OverridePosition = Vector2.op_Implicit(val3);
			}
		}

		private static bool CheckPlayerTarget(PlayerController target, Transform clockhairTransform)
		{
			//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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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)
			return Vector2.Distance(Vector3Extensions.XY(clockhairTransform.position) + new Vector2(-0.375f, 0.25f), ((GameActor)target).CenterPosition) < 0.625f;
		}

		private static bool CheckLichTarget(InfinilichDeathController self, Transform clockhairTransform)
		{
			//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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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)
			try
			{
				return Vector2.Distance(Vector3Extensions.XY(clockhairTransform.position) + new Vector2(-0.375f, 0.25f), ((GameActor)((BraveBehaviour)self).aiActor).CenterPosition + new Vector2(0f, -1.25f)) < 0.875f;
			}
			catch
			{
				return false;
			}
		}

		private static Vector2 GetTargetClockhairPosition(InfinilichDeathController self, Vector2 currentClockhairPosition)
		{
			//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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_00cd: 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_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_0034: 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_0043: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			BraveInput instanceForPlayer = BraveInput.GetInstanceForPlayer(GameManager.Instance.PrimaryPlayer.PlayerIDX);
			if (!instanceForPlayer.IsKeyboardAndMouse(false))
			{
				Vector2 val = currentClockhairPosition + ((TwoAxisInputControl)instanceForPlayer.ActiveActions.Aim).Vector * 10f * BraveTime.DeltaTime;
				val = Vector2.Max(GameManager.Instance.MainCameraController.MinVisiblePoint, val);
				return Vector2.Min(GameManager.Instance.MainCameraController.MaxVisiblePoint, val);
			}
			Vector2 val2 = Vector3Extensions.XY(GameManager.Instance.MainCameraController.Camera.ScreenToWorldPoint(Input.mousePosition)) + new Vector2(0.375f, -0.25f);
			val2 = Vector2.Max(GameManager.Instance.MainCameraController.MinVisiblePoint, val2);
			return Vector2.Min(GameManager.Instance.MainCameraController.MaxVisiblePoint, val2);
		}

		private static void UpdateEyes(InfinilichDeathController self, Vector2 clockhairPosition, bool isInDanger)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				AccessTools.Method(typeof(InfinilichDeathController), "UpdateEyes", (Type[])null, (Type[])null)?.Invoke(self, new object[2] { clockhairPosition, isInDanger });
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch(typeof(LichIntroDoer), "PlayerWalkedIn")]
	public static class Patch_Lich_Start_TrackFlawless
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static OnDamagedEvent <>9__0_0;

			internal void <Postfix>b__0_0(float resultValue, float maxValue, CoreDamageTypes damageTypes, DamageCategory damageCategory, Vector2 damageDirection)
			{
				try
				{
					LoopManager.LastLichWasFlawless = false;
				}
				catch
				{
				}
			}
		}

		[HarmonyPostfix]
		private static void Postfix()
		{
			//IL_0059: 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)
			//IL_0064: Expected O, but got Unknown
			try
			{
				LoopManager.LastLichWasFlawless = true;
				GameManager instance = GameManager.Instance;
				if (((instance != null) ? instance.AllPlayers : null) == null)
				{
					return;
				}
				for (int i = 0; i < instance.AllPlayers.Length; i++)
				{
					PlayerController val = instance.AllPlayers[i];
					if (!Object.op_Implicit((Object)(object)val) || (Object)(object)((BraveBehaviour)val).healthHaver == (Object)null)
					{
						continue;
					}
					HealthHaver healthHaver = ((BraveBehaviour)val).healthHaver;
					object obj = <>c.<>9__0_0;
					if (obj == null)
					{
						OnDamagedEvent val2 = delegate
						{
							try
							{
								LoopManager.LastLichWasFlawless = false;
							}
							catch
							{
							}
						};
						<>c.<>9__0_0 = val2;
						obj = (object)val2;
					}
					healthHaver.OnDamaged += (OnDamagedEvent)obj;
				}
			}
			catch
			{
			}
		}
	}
}
namespace LoopTheGungeon
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("milz.etg.loopthegungeon", "Loop The Gungeon", "1.0.2")]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "milz.etg.loopthegungeon";

		public const string NAME = "Loop The Gungeon";

		public const string VERSION = "1.0.2";

		public static Plugin Instance;

		public static Harmony HarmonyInstance;

		public static int GlobalLoopOffset = -1;

		private static bool _commandsRegistered;

		private bool _patched;

		private bool _hooksInstalled;

		private SceneHandler _sceneHandler;

		private SaveHandler _saveHandler;

		private void Awake()
		{
			GlobalLoopOffset = -1;
			Instance = this;
			_saveHandler = new SaveHandler();
			_sceneHandler = new SceneHandler(_saveHandler);
			try
			{
				InstallHooksOnce();
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("[{0}] Hook install failed: {1}", "Loop The Gungeon", arg));
			}
			try
			{
				ConfigManager.InitCustomConfig((BaseUnityPlugin)(object)this);
				ConfigManager.BindConfig();
				_saveHandler.TryRestorePendingResumeFromDisk();
			}
			catch (Exception arg2)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("[{0}] Config init failed: {1}", "Loop The Gungeon", arg2));
			}
			try
			{
				ToolsCharApi.AddComplex(Databases.Strings.Core, "#LOOP_SHERPA_FORGE", "Direct service to {wq}Looping{w} Chamber 5. The Forge.");
			}
			catch (Exception arg3)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("[{0}] String injection failed: {1}", "Loop The Gungeon", arg3));
			}
			try
			{
				TryApplyHarmonyPatches();
			}
			catch (Exception arg4)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("[{0}] Harmony patching failed: {1}", "Loop The Gungeon", arg4));
			}
		}

		private void InstallHooksOnce()
		{
			if (_hooksInstalled)
			{
				return;
			}
			_hooksInstalled = true;
			try
			{
				SceneManager.sceneLoaded += _sceneHandler.OnSceneLoaded;
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("[{0}] sceneLoaded hook failed: {1}", "Loop The Gungeon", arg));
			}
			try
			{
				DungeonHooks.OnPostDungeonGeneration += LoopManager.OnPostDungeonGeneration;
			}
			catch (Exception arg2)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("[{0}] OnPostDungeonGeneration LoopManager hook failed: {1}", "Loop The Gungeon", arg2));
			}
			try
			{
				DungeonHooks.OnPostDungeonGeneration += ForgeHandler.OnPostDungeonGeneration;
			}
			catch (Exception arg3)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("[{0}] OnPostDungeonGeneration ForgeHandler hook failed: {1}", "Loop The Gungeon", arg3));
			}
			try
			{
				DungeonHooks.OnPostDungeonGeneration += MasteryShrine.OnPostDungeonGeneration;
			}
			catch (Exception arg4)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("[{0}] OnPostDungeonGeneration MasteryShrine hook failed: {1}", "Loop The Gungeon", arg4));
			}
		}

		public void Start()
		{
			ETGModMainBehaviour.WaitForGameManagerStart((Action<GameManager>)GMStart);
		}

		private void GMStart(GameManager g)
		{
			if ((Object)(object)g == (Object)null)
			{
				return;
			}
			try
			{
				MasterRoundHell.Init();
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("[{0}] MasterRoundHell.Init failed: {1}", "Loop The Gungeon", arg));
			}
			IntroWave.LogIntro("Loop The Gungeon started LOoOoping!");
			if (!LoopManager.IsResumeFlow())
			{
				LoopManager.ResetNoticeEmitted = false;
			}
			if (_commandsRegistered)
			{
				return;
			}
			_commandsRegistered = true;
			try
			{
				ConsoleCommands.RegisterDebugCommands();
			}
			catch (Exception arg2)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("[{0}] RegisterDebugCommands failed: {1}", "Loop The Gungeon", arg2));
			}
			try
			{
				ETGModConsole.Commands.AddGroup("loop", (Action<string[]>)delegate
				{
				});
			}
			catch (Exception arg3)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("[{0}] AddGroup(loop) failed: {1}", "Loop The Gungeon", arg3));
			}
		}

		private void TryApplyHarmonyPatches()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			if (_patched)
			{
				return;
			}
			try
			{
				HarmonyInstance = new Harmony("milz.etg.loopthegungeon");
				Harmony harmonyInstance = HarmonyInstance;
				MethodInfo method = typeof(GameManager).GetMethod("DelayedLoadCharacterSelect", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if ((object)method == null)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"[Loop The Gungeon] Patch FAIL: GameManager.DelayedLoadCharacterSelect not found.");
				}
				else
				{
					harmonyInstance.Patch((MethodBase)method, new HarmonyMethod(typeof(LoopManager), "SaveAndQuitBoundary", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				harmonyInstance.PatchAll(Assembly.GetExecutingAssembly());
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[Loop The Gungeon] Harmony PatchAll OK.");
				_patched = true;
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("[{0}] Harmony patching FAILED: {1}", "Loop The Gungeon", arg));
			}
		}

		private void OnDestroy()
		{
			try
			{
				_saveHandler?.StopCoroutines();
			}
			catch
			{
			}
			try
			{
				_sceneHandler?.StopCoroutines();
			}
			catch
			{
			}
			if (_hooksInstalled)
			{
				_hooksInstalled = false;
				if (_sceneHandler != null)
				{
					SceneManager.sceneLoaded -= _sceneHandler.OnSceneLoaded;
				}
				DungeonHooks.OnPostDungeonGeneration -= LoopManager.OnPostDungeonGeneration;
				DungeonHooks.OnPostDungeonGeneration -= MasteryShrine.OnPostDungeonGeneration;
			}
			DungeonHooks.OnPostDungeonGeneration -= ForgeHandler.OnPostDungeonGeneration;
			if (Instance == this)
			{
				Instance = null;
			}
			try
			{
				ProjectileSpeedScaler.RestoreBaselineNow();
			}
			catch
			{
			}
			ButtonSpritesOverride.ClearRuntimeCaches(destroyUnityObjects: true);
			try
			{
				LoopManager.ResetMasteryShrineRuntime();
				ShrineSpritesOverride.TryResetMasteryShrineVisuals();
				ShrineSpritesOverride.ClearRuntimeCaches(destroyUnityObjects: true);
			}
			catch
			{
			}
		}

		internal static void StopAndNull(ref Coroutine c)
		{
			if (c != null && (Object)(object)Instance != (Object)null)
			{
				try
				{
					((MonoBehaviour)Instance).StopCoroutine(c);
				}
				catch
				{
				}
				c = null;
			}
		}

		internal static Coroutine StartGlobalCoroutine(IEnumerator e)
		{
			if ((Object)(object)Instance == (Object)null)
			{
				return null;
			}
			try
			{
				return ((MonoBehaviour)Instance).StartCoroutine(e);
			}
			catch
			{
				return null;
			}
		}

		internal void ClearResumeAnnouncement()
		{
			try
			{
				_saveHandler?.ClearResumeAnnouncement();
			}
			catch
			{
			}
		}

		internal void ArmResumeAnnouncementIfNeeded()
		{
			try
			{
				_saveHandler?.ArmResumeAnnouncementIfNeeded();
			}
			catch
			{
			}
		}

		public static bool ShouldSuppressResumeArming()
		{
			try
			{
				return SaveHandler.ShouldSuppressResumeArming();
			}
			catch
			{
				return false;
			}
		}
	}
}
namespace LoopTheGungeon.Visuals
{
	public static class ShrineSpritesOverride
	{
		private readonly struct CreatedKey : IEquatable<CreatedKey>
		{
			public readonly string CollectionStable;

			public readonly string Name;

			public CreatedKey(tk2dSpriteCollectionData c, string name)
			{
				CollectionStable = GetCollectionStableId(c);
				Name = name ?? string.Empty;
			}

			public bool Equals(CreatedKey other)
			{
				if (string.Equals(CollectionStable, other.CollectionStable, StringComparison.Ordinal))
				{
					return string.Equals(Name, other.Name, StringComparison.Ordinal);
				}
				return false;
			}

			public override bool Equals(object obj)
			{
				if (obj is CreatedKey other)
				{
					return Equals(other);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return (17 * 31 + StringComparer.Ordinal.GetHashCode(CollectionStable ?? "")) * 31 + StringComparer.Ordinal.GetHashCode(Name ?? "");
			}
		}

		private readonly struct MatKey : IEquatable<MatKey>
		{
			public readonly int BaseMatId;

			public readonly int TexId;

			public MatKey(Material baseMat, Texture2D tex)
			{
				BaseMatId = (Object.op_Implicit((Object)(object)baseMat) ? ((Object)baseMat).GetInstanceID() : 0);
				TexId = (Object.op_Implicit((Object)(object)tex) ? ((Object)tex).GetInstanceID() : 0);
			}

			public bool Equals(MatKey other)
			{
				if (BaseMatId == other.BaseMatId)
				{
					return TexId == other.TexId;
				}
				return false;
			}

			public override bool Equals(object obj)
			{
				if (obj is MatKey other)
				{
					return Equals(other);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return (BaseMatId * 397) ^ TexId;
			}
		}

		private sealed class LruCache<TKey, TValue>
		{
			private struct Entry
			{
				public TKey Key;

				public TValue Value;
			}

			private readonly int _cap;

			private readonly Dictionary<TKey, LinkedListNode<Entry>> _map;

			private readonly LinkedList<Entry> _lru;

			private readonly Action<TValue> _onEvict;

			public int Count => _map.Count;

			public LruCache(int capacity, Action<TValue> onEvict)
			{
				_cap = Mathf.Max(1, capacity);
				_map = new Dictionary<TKey, LinkedListNode<Entry>>(_cap);
				_lru = new LinkedList<Entry>();
				_onEvict = onEvict;
			}

			public bool TryGetValue(TKey key, out TValue value)
			{
				if (_map.TryGetValue(key, out var value2))
				{
					_lru.Remove(value2);
					_lru.AddFirst(value2);
					value = value2.Value.Value;
					return true;
				}
				value = default(TValue);
				return false;
			}

			public void Set(TKey key, TValue value)
			{
				if (_map.TryGetValue(key, out var value2))
				{
					value2.Value = new Entry
					{
						Key = key,
						Value = value
					};
					_lru.Remove(value2);
					_lru.AddFirst(value2);
					return;
				}
				while (_map.Count >= _cap)
				{
					EvictOne();
				}
				Entry value3 = default(Entry);
				value3.Key = key;
				value3.Value = value;
				LinkedListNode<Entry> linkedListNode = new LinkedListNode<Entry>(value3);
				_lru.AddFirst(linkedListNode);
				_map[key] = linkedListNode;
			}

			private void EvictOne()
			{
				LinkedListNode<Entry> last = _lru.Last;
				if (last == null)
				{
					return;
				}
				_lru.RemoveLast();
				_map.Remove(last.Value.Key);
				if (_onEvict == null)
				{
					return;
				}
				try
				{
					_onEvict(last.Value.Value);
				}
				catch
				{
				}
			}

			public void Clear(bool destroyValues)
			{
				if (destroyValues && _onEvict != null)
				{
					foreach (Entry item in _lru)
					{
						try
						{
							_onEvict(item.Value);
						}
						catch
						{
						}
					}
				}
				_map.Clear();
				_lru.Clear();
			}
		}

		private const int MaxCachedMaterials = 64;

		private const int MaxCreatedIdMap = 128;

		private const int LEAD_LEGEND_TIER = 30;

		private const string INTERNAL_STATUE_BLACKSMITH_PRE = "LOOP_STATUE_BLACKSMITH_PRE";

		private const string INTERNAL_STATUE_BLACKSMITH_SPENT = "LOOP_STATUE_BLACKSMITH_SPENT";

		private const string INTERNAL_STATUE_LICH_PRE = "LOOP_STATUE_LICH_PRE";

		private const string INTERNAL_STATUE_LICH_SPENT = "LOOP_STATUE_LICH_SPENT";

		private const string INTERNAL_STATUE_BLACKSMITH_LEGEND_PRE = "LOOP_STATUE_BLACKSMITH_LEGEND_PRE";

		private const string INTERNAL_STATUE_BLACKSMITH_LEGEND_SPENT = "LOOP_STATUE_BLACKSMITH_LEGEND_SPENT";

		private const string INTERNAL_STATUE_LICH_LEGEND_PRE = "LOOP_STATUE_LICH_LEGEND_PRE";

		private const string INTERNAL_STATUE_LICH_LEGEND_SPENT = "LOOP_STATUE_LICH_LEGEND_SPENT";

		private const string INTERNAL_PEDESTAL_NORMAL = "LOOP_PEDESTAL_NORMAL";

		private const string INTERNAL_PEDESTAL_LEGEND = "LOOP_PEDESTAL_LEGEND";

		private static readonly LruCache<MatKey, Material> _matCache = new LruCache<MatKey, Material>(64, DestroyMaterial);

		private static readonly LruCache<CreatedKey, int> _createdIds = new LruCache<CreatedKey, int>(128, null);

		private static bool _tabletIconsInstalled;

		private static bool _portraitAtlasIconsInstalled;

		public static void ClearIds()
		{
			_createdIds.Clear(destroyValues: false);
		}

		public static void ClearRuntimeCaches(bool destroyUnityObjects)
		{
			_createdIds.Clear(destroyValues: false);
			_matCache.Clear(destroyUnityObjects);
		}

		public static void TryResetMasteryShrineVisuals()
		{
			try
			{
				string lastLoopSource = LoopManager.LastLoopSource;
				bool spent = !MasteryShrineInteractable.AnyAlivePlayerCanUseShrine();
				MasteryShrineInteractable masteryShrineInteractable = Object.FindObjectOfType<MasteryShrineInteractable>();
				if ((Object)(object)masteryShrineInteractable != (Object)null)
				{
					Apply(((Component)masteryShrineInteractable).gameObject, lastLoopSource, spent);
				}
			}
			catch
			{
			}
		}

		private static bool IsLeadLegendUnlocked()
		{
			try
			{
				return RunSummary.HasMasteryTitleReached(30);
			}
			catch
			{
				return false;
			}
		}

		private static string GetCollectionStableId(tk2dSpriteCollectionData c)
		{
			if (!Object.op_Implicit((Object)(object)c))
			{
				return "null";
			}
			if (!string.IsNullOrEmpty(c.spriteCollectionName))
			{
				return c.spriteCollectionName;
			}
			return ((Object)c).name ?? "null";
		}

		private static void DestroySafe(Object o)
		{
			try
			{
				if (o != (Object)null)
				{
					Object.Destroy(o);
				}
			}
			catch
			{
			}
		}

		private static void DestroyMaterial(Material m)
		{
			DestroySafe((Object)(object)m);
		}

		private static Material GetOrCreateMaterial(Material baseMat, Texture2D tex)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)baseMat) || !Object.op_Implicit((Object)(object)tex))
			{
				return null;
			}
			MatKey key = new MatKey(baseMat, tex);
			if (_matCache.TryGetValue(key, out var value) && Object.op_Implicit((Object)(object)value))
			{
				return value;
			}
			Material val = new Material(baseMat);
			val.mainTexture = (Texture)(object)tex;
			((Object)val).hideFlags = (HideFlags)20;
			_matCache.Set(key, val);
			return val;
		}

		public static bool Apply(GameObject shrineRoot, string form, bool spent)
		{
			try
			{
				if (!Object.op_Implicit((Object)(object)shrineRoot))
				{
					return false;
				}
				bool flag = false;
				bool flag2 = IsLeadLegendUnlocked();
				tk2dBaseSprite val = FindSpriteOnChild(shrineRoot.transform, "ShrineStatue");
				if (Object.op_Implicit((Object)(object)val))
				{
					Texture2D tex = null;
					string internalName = null;
					if (flag2)
					{
						if (spent)
						{
							if (form == "Lich")
							{
								tex = ModTextures.MasteryShrine.StatueLichLegendSpentTex;
								internalName = "LOOP_STATUE_LICH_LEGEND_SPENT";
							}
							else if (form == "Blacksmith")
							{
								tex = ModTextures.MasteryShrine.StatueBlacksmithLegendSpentTex;
								internalName = "LOOP_STATUE_BLACKSMITH_LEGEND_SPENT";
							}
						}
						else if (form == "Lich")
						{
							tex = ModTextures.MasteryShrine.StatueLichLegendPreTex;
							internalName = "LOOP_STATUE_LICH_LEGEND_PRE";
						}
						else if (form == "Blacksmith")
						{
							tex = ModTextures.MasteryShrine.StatueBlacksmithLegendPreTex;
							internalName = "LOOP_STATUE_BLACKSMITH_LEGEND_PRE";
						}
					}
					else if (spent)
					{
						if (form == "Lich")
						{
							tex = ModTextures.MasteryShrine.StatueLichSpentTex;
							internalName = "LOOP_STATUE_LICH_SPENT";
						}
						else if (form == "Blacksmith")
						{
							tex = ModTextures.MasteryShrine.StatueBlacksmithSpentTex;
							internalName = "LOOP_STATUE_BLACKSMITH_SPENT";
						}
					}
					else if (form == "Lich")
					{
						tex = ModTextures.MasteryShrine.StatueLichPreTex;
						internalName = "LOOP_STATUE_LICH_PRE";
					}
					else if (form == "Blacksmith")
					{
						tex = ModTextures.MasteryShrine.StatueBlacksmithPreTex;
						internalName = "LOOP_STATUE_BLACKSMITH_PRE";
					}
					flag |= SwapSpriteSingle(val, tex, internalName);
				}
				tk2dBaseSprite val2 = FindSpriteOnChild(shrineRoot.transform, "shrine_Base");
				if (Object.op_Implicit((Object)(object)val2))
				{
					Texture2D tex2 = (flag2 ? ModTextures.MasteryShrine.PedestalLegendTex : ModTextures.MasteryShrine.PedestalNormalTex);
					string internalName2 = (flag2 ? "LOOP_PEDESTAL_LEGEND" : "LOOP_PEDESTAL_NORMAL");
					flag |= SwapSpriteSingle(val2, tex2, internalName2);
				}
				return flag;
			}
			catch
			{
				return false;
			}
		}

		private static tk2dBaseSprite FindSpriteOnChild(Transform root, string childName)
		{
			try
			{
				if (!Object.op_Implicit((Object)(object)root))
				{
					return null;
				}
				Transform val = root.Find(childName);
				if (!Object.op_Implicit((Object)(object)val))
				{
					return null;
				}
				return ((Component)val).GetComponent<tk2dBaseSprite>();
			}
			catch
			{
				return null;
			}
		}

		private static bool SwapSpriteSingle(tk2dBaseSprite spr, Texture2D tex, string internalName)
		{
			try
			{
				if (!Object.op_Implicit((Object)(object)spr) || !Object.op_Implicit((Object)(object)tex))
				{
					return false;
				}
				tk2dSpriteCollectionData collection = spr.Collection;
				if (!Object.op_Implicit((Object)(object)collection) || collection.spriteDefinitions == null)
				{
					return false;
				}
				int num = spr.spriteId;
				if (num < 0 || num >= collection.spriteDefinitions.Length)
				{
					num = 0;
				}
				int num2 = AddTexAsSpriteDef(collection, num, tex, internalName);
				if (num2 < 0)
				{
					return false;
				}
				spr.SetSprite(collection, num2);
				spr.ForceBuild();
				ModTextures.Tk2dUpdateMaterialSafe(spr);
				return true;
			}
			catch
			{
				return false;
			}
		}

		public static int AddTexAsSpriteDef(tk2dSpriteCollectionData collection, int templateSpriteId, Texture2D tex, string name, float worldHeight = -1f)
		{
			CreatedKey key = new CreatedKey(collection, name);
			if (_createdIds.TryGetValue(key, out var value) && value >= 0)
			{
				return value;
			}
			try
			{
				if (!Object.op_Implicit((Object)(object)collection) || !Object.op_Implicit((Object)(object)tex))
				{
					return -1;
				}
				tk2dSpriteDefinition[] array = collection.spriteDefinitions;
				if (array == null || array.Length == 0)
				{
					return -1;
				}
				try
				{
					tk2dSpriteDefinition[] spriteDefinitions = collection.spriteDefinitions;
					if (spriteDefinitions != null)
					{
						for (int i = 0; i < spriteDefinitions.Length; i++)
						{
							tk2dSpriteDefinition val = spriteDefinitions[i];
							if (val != null && string.Equals(val.name, name, StringComparison.Ordinal))
							{
								_createdIds.Set(new CreatedKey(collection, name), i);
								return i;
							}
						}
					}
				}
				catch
				{
				}
				tk2dSpriteDefinition val2 = array[Mathf.Clamp(templateSpriteId, 0, array.Length - 1)];
				if (val2 == null)
				{
					return -1;
				}
				tk2dSpriteDefinition val3 = CloneDefinition(val2, tex, name);
				ResizeDefByPixelRatio(val3, val2, tex);
				if (worldHeight > 0f)
				{
					ResizeDefinitionToWorldHeight(val3, tex, worldHeight);
				}
				int num = array.Length;
				Array.Resize(ref array, num + 1);
				array[num] = val3;
				collection.spriteDefinitions = array;
				_createdIds.Set(key, num);
				return num;
			}
			catch
			{
				return -1;
			}
		}

		public static int AddBadgeSpriteDef(tk2dSpriteCollectionData collection, Material baseMat, Texture2D tex, string name, float pixelsPerUnit = 16f)
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			//IL_00df: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: 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_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)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: 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_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)collection) || !Object.op_Implicit((Object)(object)tex) || !Object.op_Implicit((Object)(object)baseMat))
			{
				return -1;
			}
			int num = Mathf.RoundToInt(pixelsPerUnit * 1000f);
			string text = $"{name}__ppu{num}";
			CreatedKey key = new CreatedKey(collection, text);
			if (_createdIds.TryGetValue(key, out var value) && value >= 0)
			{
				return value;
			}
			tk2dSpriteDefinition[] spriteDefinitions = collection.spriteDefinitions;
			if (spriteDefinitions != null)
			{
				for (int i = 0; i < spriteDefinitions.Length; i++)
				{
					tk2dSpriteDefinition val = spriteDefinitions[i];
					if (val != null && string.Equals(val.name, text, StringComparison.Ordinal))
					{
						_createdIds.Set(key, i);
						return i;
					}
				}
			}
			try
			{
				tk2dSpriteDefinition val2 = new tk2dSpriteDefinition();
				val2.name = text;
				val2.materialInst = GetOrCreateMaterial(baseMat, tex);
				val2.uvs = (Vector2[])(object)new Vector2[4];
				val2.uvs[0] = new Vector2(0f, 0f);
				val2.uvs[1] = new Vector2(1f, 0f);
				val2.uvs[2] = new Vector2(0f, 1f);
				val2.uvs[3] = new Vector2(1f, 1f);
				float num2 = ((pixelsPerUnit <= 0.0001f) ? 0.0625f : (1f / pixelsPerUnit));
				float num3 = (float)((Texture)tex).width * num2;
				float num4 = (float)((Texture)tex).height * num2;
				float num5 = num3 * 0.5f;
				float num6 = num4 * 0.5f;
				val2.position0 = new Vector3(0f - num5, 0f - num6, 0f);
				val2.position1 = new Vector3(num5, 0f - num6, 0f);
				val2.position2 = new Vector3(0f - num5, num6, 0f);
				val2.position3 = new Vector3(num5, num6, 0f);
				val2.texelSize = new Vector2(num2, num2);
				int num7 = collection.spriteDefinitions.Length;
				Array.Resize(ref collection.spriteDefinitions, num7 + 1);
				collection.spriteDefinitions[num7] = val2;
				_createdIds.Set(key, num7);
				return num7;
			}
			catch
			{
				return -1;
			}
		}

		private static tk2dSpriteDefinition CloneDefinition(tk2dSpriteDefinition template, Texture2D newTex, string name)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			tk2dSpriteDefinition val = new tk2dSpriteDefinition();
			CopyAllInstanceFields(template, val);
			val.name = name;
			if ((Object)(object)val.materialInst != (Object)null)
			{
				val.materialInst = GetOrCreateMaterial(val.materialInst, newTex);
			}
			SetFullUvsIfPresent(val);
			return val;
		}

		private static void CopyAllInstanceFields(object src, object dst)
		{
			if (src == null || dst == null)
			{
				return;
			}
			Type type = src.GetType();
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			FieldInfo[] fields = type.GetFields(bindingAttr);
			foreach (FieldInfo fieldInfo in fields)
			{
				try
				{
					if (!fieldInfo.IsInitOnly)
					{
						object obj = fieldInfo.GetValue(src);
						if (obj != null && obj.GetType().IsArray)
						{
							obj = ((Array)obj).Clone();
						}
						fieldInfo.SetValue(dst, obj);
					}
				}
				catch
				{
				}
			}
		}

		private static void SetFullUvsIfPresent(tk2dSpriteDefinition def)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			if (def != null && def.uvs != null && def.uvs.Length >= 4)
			{
				def.uvs[0] = new Vector2(0f, 0f);
				def.uvs[1] = new Vector2(1f, 0f);
				def.uvs[2] = new Vector2(0f, 1f);
				def.uvs[3] = new Vector2(1f, 1f);
			}
		}

		private static void ResizeDefinitionToWorldHeight(tk2dSpriteDefinition def, Texture2D tex, float worldHeight)
		{
			//IL_0081: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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)
			if (def != null && !((Object)(object)tex == (Object)null) && ((Texture)tex).width > 0 && ((Texture)tex).height > 0)
			{
				float num = (float)((Texture)tex).width / (float)((Texture)tex).height;
				float num2 = worldHeight * num * 0.5f;
				float num3 = worldHeight * 0.5f;
				Vector3 position = default(Vector3);
				((Vector3)(ref position))..ctor(0f - num2, 0f - num3, 0f);
				Vector3 position2 = default(Vector3);
				((Vector3)(ref position2))..ctor(num2, 0f - num3, 0f);
				Vector3 position3 = default(Vector3);
				((Vector3)(ref position3))..ctor(0f - num2, num3, 0f);
				Vector3 position4 = default(Vector3);
				((Vector3)(ref position4))..ctor(num2, num3, 0f);
				def.position0 = position;
				def.position1 = position2;
				def.position2 = position3;
				def.position3 = position4;
			}
		}

		private static void ResizeDefByPixelRatio(tk2dSpriteDefinition def, tk2dSpriteDefinition template, Texture2D newTex)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_0030: 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)
			//IL_003e: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: 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)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: 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_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			if (def == null || template == null || (Object)(object)newTex == (Object)null || ((Texture)newTex).width <= 0 || ((Texture)newTex).height <= 0)
			{
				return;
			}
			Vector3 position = template.position0;
			Vector3 position2 = template.position1;
			Vector3 position3 = template.position2;
			_ = template.position3;
			Vector3 val = position2 - position;
			Vector3 val2 = position3 - position;
			float magnitude = ((Vector3)(ref val)).magnitude;
			float magnitude2 = ((Vector3)(ref val2)).magnitude;
			if (magnitude <= 0.0001f || magnitude2 <= 0.0001f)
			{
				return;
			}
			Vector2 texelSize = template.texelSize;
			if (!(texelSize.x <= 1E-06f) && !(texelSize.y <= 1E-06f))
			{
				float num = magnitude / texelSize.x;
				float num2 = magnitude2 / texelSize.y;
				if (!(num <= 1f) && !(num2 <= 1f))
				{
					float num3 = (float)((Texture)newTex).width / num;
					float num4 = (float)((Texture)newTex).height / num2;
					Vector3 val3 = val * num3;
					Vector3 val4 = val2 * num4;
					Vector3 val5 = (position + position2) * 0.5f;
					def.position0 = val5 - 0.5f * val3;
					def.position1 = val5 + 0.5f * val3;
					def.position2 = def.position0 + val4;
					def.position3 = def.position1 + val4;
				}
			}
		}

		internal static void TryInstallUiIcons()
		{
			TryInstallTabletIcons();
			TryInstallConversationAtlasIcons();
		}

		internal static void TryInstallTabletIcons()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			if (_tabletIconsInstalled)
			{
				return;
			}
			try
			{
				GameObject val = (GameObject)ResourceCache.Acquire("ControllerButtonSprite");
				tk2dBaseSprite val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<tk2dBaseSprite>() : null);
				tk2dSpriteCollectionData val3 = (Object.op_Implicit((Object)(object)val2) ? val2.Collection : null);
				if (!((Object)(object)val3 == (Object)null))
				{
					EnsureSpriteInCollection(val3, ModTextures.UI.HellRoundTex, "loop_hell_round");
					EnsureSpriteInCollection(val3, ModTextures.UI.CoolnessTex, "loop_coolness");
					EnsureSpriteInCollection(val3, ModTextures.UI.CurseTex, "loop_curse");
					EnsureSpriteInCollection(val3, ModTextures.UI.RageTex, "loop_rage");
					_tabletIconsInstalled = true;
				}
			}
			catch
			{
			}
		}

		internal static void TryInstallConversationAtlasIcons()
		{
			if (_portraitAtlasIconsInstalled)
			{
				return;
			}
			try
			{
				GameUIRoot instance = GameUIRoot.Instance;
				if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.ConversationBar == (Object)null))
				{
					dfSprite portraitSprite = instance.ConversationBar.portraitSprite;
					if (!((Object)(object)portraitSprite == (Object)null) && !((Object)(object)portraitSprite.Atlas == (Object)null))
					{
						dfAtlas atlas = portraitSprite.Atlas;
						EnsureSpriteInAtlas(atlas, ModTextures.UI.CurseBoxTex, "loop_curse_box");
						EnsureSpriteInAtlas(atlas, ModTextures.UI.HellRoundBoxTex, "loop_hell_round_box");
						_portraitAtlasIconsInstalled = true;
					}
				}
			}
			catch
			{
			}
		}

		private static void EnsureSpriteInCollection(tk2dSpriteCollectionData col, Texture2D tex, string name)
		{
			if ((Object)(object)col == (Object)null || (Object)(object)tex == (Object)null || string.IsNullOrEmpty(name))
			{
				return;
			}
			tk2dSpriteDefinition[] spriteDefinitions = col.spriteDefinitions;
			if (spriteDefinitions != null)
			{
				for (int i = 0; i < spriteDefinitions.Length; i++)
				{
					if (spriteDefinitions[i] != null && spriteDefinitions[i].name == name)
					{
						return;
					}
				}
			}
			SpriteBuilder.AddSpriteToCollection(tex, col, name);
		}

		private static void EnsureSpriteInAtlas(dfAtlas atlas, Texture2D tex, string name)
		{
			if ((Object)(object)atlas == (Object)null || (Object)(object)tex == (Object)null || string.IsNullOrEmpty(name))
			{
				return;
			}
			try
			{
				if (atlas[name] != (ItemInfo)null)
				{
					return;
				}
			}
			catch
			{
			}
			try
			{
				ToolsCharApi.AddNewItemToAtlas(atlas, tex, name);
			}
			catch
			{
			}
		}
	}
	internal static class ModTextures
	{
		internal static class MasteryShrine
		{
			public static Texture2D StatueBlacksmithPreTex => LoadPng("Resources/MasteryShrine", "statue_blacksmith_pre.png", (FilterMode)0);

			public static Texture2D StatueBlacksmithSpentTex => LoadPng("Resources/MasteryShrine", "statue_blacksmith_spent.png", (FilterMode)0);

			public static Texture2D StatueBlacksmithLegendPreTex => LoadPng("Resources/MasteryShrine", "statue_blacksmith_legend_pre.png", (FilterMode)0);

			public static Texture2D StatueBlacksmithLegendSpentTex => LoadPng("Resources/MasteryShrine", "statue_blacksmith_legend_spent.png", (FilterMode)0);

			public static Texture2D StatueLichPreTex => LoadPng("Resources/MasteryShrine", "statue_lich_pre.png", (FilterMode)0);

			public static Texture2D StatueLichSpentTex => LoadPng("Resources/MasteryShrine", "statue_lich_spent.png", (FilterMode)0);

			public static Texture2D StatueLichLegendPreTex => LoadPng("Resources/MasteryShrine", "statue_lich_legend_pre.png", (FilterMode)0);

			public static Texture2D StatueLichLegendSpentTex => LoadPng("Resources/MasteryShrine", "statue_lich_legend_spent.png", (FilterMode)0);

			public static Texture2D PedestalNormalTex => LoadPng("Resources/MasteryShrine", "pedestal_normal.png", (FilterMode)0);

			public static Texture2D PedestalLegendTex => LoadPng("Resources/MasteryShrine", "pedestal_legend.png", (FilterMode)0);

			public static Texture2D Mr1LitTex => LoadPng("Resources/MasteryShrine", "mastery_badge_1.png", (FilterMode)0);

			public static Texture2D Mr2LitTex => LoadPng("Resources/MasteryShrine", "mastery_badge_2.png", (FilterMode)0);

			public static Texture2D Mr3LitTex => LoadPng("Resources/MasteryShrine", "mastery_badge_3.png", (FilterMode)0);

			public static Texture2D Mr4LitTex => LoadPng("Resources/MasteryShrine", "mastery_badge_4.png", (FilterMode)0);

			public static Texture2D Mr5LitTex => LoadPng("Resources/MasteryShrine", "mastery_badge_5.png", (FilterMode)0);

			public static Texture2D Mr6LitTex => LoadPng("Resources/MasteryShrine", "mastery_badge_6.png", (FilterMode)0);
		}

		internal static class LoopButton
		{
			public static Texture2D Talk1EvolvingTex => LoadPng("Resources/LoopButton", "loop_button_evolving_talk_1.png", (FilterMode)0);

			public static Texture2D Talk2EvolvingTex => LoadPng("Resources/LoopButton", "loop_button_evolving_talk_2.png", (FilterMode)0);

			public static Texture2D Talk3EvolvingTex => LoadPng("Resources/LoopButton", "loop_button_evolving_talk_3.png", (FilterMode)0);

			public static Texture2D Talk1FixedTex => LoadPng("Resources/LoopButton", "loop_button_fixed_talk_1.png", (FilterMode)0);

			public static Texture2D Talk2FixedTex => LoadPng("Resources/LoopButton", "loop_button_fixed_talk_2.png", (FilterMode)0);

			public static Texture2D Talk3FixedTex => LoadPng("Resources/LoopButton", "loop_button_fixed_talk_3.png", (FilterMode)0);
		}

		internal static class TitleScreen
		{
			public static Texture2D Looper1Tex => LoadPng("Resources/TitleScreen", "looper_1.png", (FilterMode)0);

			public static Texture2D Looper2Tex => LoadPng("Resources/TitleScreen", "looper_2.png", (FilterMode)0);

			public static Texture2D Looper3Tex => LoadPng("Resources/TitleScreen", "looper_3.png", (FilterMode)0);

			public static Texture2D Looper4Tex => LoadPng("Resources/TitleScreen", "looper_4.png", (FilterMode)0);

			public static Texture2D Looper5Tex => LoadPng("Resources/TitleScreen", "looper_5.png", (FilterMode)0);

			public static Texture2D Looper6Tex => LoadPng("Resources/TitleScreen", "looper_6.png", (FilterMode)0);

			public static Texture2D Looper7Tex => LoadPng("Resources/TitleScreen", "looper_7.png", (FilterMode)0);

			public static Texture2D Looper8Tex => LoadPng("Resources/TitleScreen", "looper_8.png", (FilterMode)0);
		}

		internal static class UI
		{
			public static Texture2D CoolnessTex => LoadPng("Resources/UI", "coolness_icon.png", (FilterMode)0);

			public static Texture2D RageTex => LoadPng("Resources/UI", "rage_icon.png", (FilterMode)0);

			public static Texture2D CurseTex => LoadPng("Resources/UI", "curse_icon.png", (FilterMode)0);

			public static Texture2D CurseBoxTex => LoadPng("Resources/UI", "curse_box_icon.png", (FilterMode)0);

			public static Texture2D HellRoundTex => LoadPng("Resources/UI", "hell_round_icon.png", (FilterMode)0);

			public static Texture2D HellRoundBoxTex => LoadPng("Resources/UI", "hell_round_box_icon.png", (FilterMode)0);
		}

		private sealed class CacheEntry
		{
			public Texture2D Tex;

			public long LooseLastWriteUtcTicks;
		}

		public static bool PreferLooseFiles = false;

		private static readonly string PluginDir = ResolvePluginDir();

		private static readonly Dictionary<string, CacheEntry> _cache = new Dictionary<string, CacheEntry>(StringComparer.OrdinalIgnoreCase);

		private static Action<tk2dBaseSprite> _tk2dUpdateMaterial;

		private static string ResolvePluginDir()
		{
			try
			{
				string text = null;
				try
				{
					Plugin instance = Plugin.Instance;
					object obj;
					if (instance == null)
					{
						obj = null;
					}
					else
					{
						PluginInfo info = ((BaseUnityPlugin)instance).Info;
						obj = ((info != null) ? info.Location : null);
					}
					text = (string)obj;
				}
				catch
				{
				}
				if (string.IsNullOrEmpty(text))
				{
					text = Assembly.GetExecutingAssembly().Location;
				}
				return string.IsNullOrEmpty(text) ? string.Empty : Path.GetDirectoryName(text);
			}
			catch
			{
				return string.Empty;
			}
		}

		private static Texture2D LoadPng(string folderUnderPluginDir, string fileName, FilterMode filter)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected I4, but got Unknown
			//IL_0082: 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)
			if (string.IsNullOrEmpty(fileName))
			{
				return null;
			}
			string cacheKey = folderUnderPluginDir + "/" + fileName + "|f=" + (int)filter;
			if (PreferLooseFiles && !string.IsNullOrEmpty(PluginDir))
			{
				string fullPath = Path.Combine(Path.Combine(PluginDir, folderUnderPluginDir.Replace('/', Path.DirectorySeparatorChar)), fileName);
				Texture2D val = TryLoadLoosePngCached(cacheKey, fullPath, filter);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return TryLoadEmbeddedPngCached(cacheKey, folderUnderPluginDir, fileName, filter);
		}

		private static Texture2D TryLoadLoosePngCached(string cacheKey, string fullPath, FilterMode filter)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (string.IsNullOrEmpty(fullPath) || !File.Exists(fullPath))
				{
					return null;
				}
				long ticks = File.GetLastWriteTimeUtc(fullPath).Ticks;
				if (_cache.TryGetValue(cacheKey, out var value) && value != null && (Object)(object)value.Tex != (Object)null && value.LooseLastWriteUtcTicks == ticks)
				{
					return value.Tex;
				}
				byte[] array = File.ReadAllBytes(fullPath);
				Texture2D val = new Texture2D(2, 2, (TextureFormat)5, false);
				if (!ImageConversion.LoadImage(val, array))
				{
					Object.Destroy((Object)(object)val);
					return null;
				}
				((Texture)val).filterMode = filter;
				((Texture)val).wrapMode = (TextureWrapMode)1;
				((Object)val).hideFlags = (HideFlags)20;
				if (value != null && (Object)(object)value.Tex != (Object)null)
				{
					Object.Destroy((Object)(object)value.Tex);
				}
				_cache[cacheKey] = new CacheEntry
				{
					Tex = val,
					LooseLastWriteUtcTicks = ticks
				};
				return val;
			}
			catch
			{
				return null;
			}
		}

		private static Texture2D TryLoadEmbeddedPngCached(string cacheKey, string folderUnderRoot, string fileName, FilterMode filter)
		{
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (_cache.TryGetValue(cacheKey, out var value) && value != null && (Object)(object)value.Tex != (Object)null && value.LooseLastWriteUtcTicks == 0L)
				{
					return value.Tex;
				}
				string text = folderUnderRoot.Replace('/', '.').Replace('\\', '.');
				string name = "LoopTheGungeon." + text + "." + fileName;
				Assembly executingAssembly = Assembly.GetExecutingAssembly();
				using Stream stream = executingAssembly.GetManifestResourceStream(name);
				if (stream == null)
				{
					string[] manifestResourceNames = executingAssembly.GetManifestResourceNames();
					for (int i = 0; i < manifestResourceNames.Length; i++)
					{
						ETGModConsole.Log((object)manifestResourceNames[i], false);
					}
					return null;
				}
				byte[] array = new byte[stream.Length];
				stream.Read(array, 0, array.Length);
				Texture2D val = new Texture2D(2, 2, (TextureFormat)5, false);
				if (!ImageConversion.LoadImage(val, array))
				{
					Object.Destroy((Object)(object)val);
					return null;
				}
				((Texture)val).filterMode = filter;
				((Texture)val).wrapMode = (TextureWrapMode)1;
				((Object)val).hideFlags = (HideFlags)20;
				if (value != null && (Object)(object)value.Tex != (Object)null)
				{
					Object.Destroy((Object)(object)value.Tex);
				}
				_cache[cacheKey] = new CacheEntry
				{
					Tex = val,
					LooseLastWriteUtcTicks = 0L
				};
				return val;
			}
			catch
			{
				return null;
			}
		}

		public static void ClearAllCachedTextures(bool destroyUnityObjects)
		{
			if (destroyUnityObjects)
			{
				foreach (KeyValuePair<string, CacheEntry> item in _cache)
				{
					try
					{
						if ((Object)(object)item.Value?.Tex != (Object)null)
						{
							Object.Destroy((Object)(object)item.Value.Tex);
						}
					}
					catch
					{
					}
				}
			}
			_cache.Clear();
		}

		public static void Tk2dUpdateMaterialSafe(tk2dBaseSprite spr)
		{
			if ((Object)(object)spr == (Object)null)
			{
				return;
			}
			try
			{
				if (_tk2dUpdateMaterial == null)
				{
					MethodInfo method = typeof(tk2dBaseSprite).GetMethod("UpdateMaterial", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if ((object)method == null)
					{
						return;
					}
					_tk2dUpdateMaterial = (Action<tk2dBaseSprite>)Delegate.CreateDelegate(typeof(Action<tk2dBaseSprite>), null, method);
				}
				_tk2dUpdateMaterial(spr);
			}
			catch
			{
			}
		}
	}
	public static class ButtonSpritesOverride
	{
		private sealed class InstancedTk2dMarker : MonoBehaviour
		{
		}

		private sealed class LoopButtonAppliedMarker : MonoBehaviour
		{
			public bool EvolvingEnabled;
		}

		private sealed class RuntimeAtlas
		{
			public Texture2D AtlasTex;

			public Material Mat;
		}

		private readonly struct CreatedKey : IEquatable<CreatedKey>
		{
			public readonly string CollectionStable;

			public readonly string Name;

			public CreatedKey(tk2dSpriteCollectionData c, string name)
			{
				CollectionStable = GetCollectionStableId(c);
				Name = name ?? string.Empty;
			}

			public bool Equals(CreatedKey other)
			{
				if (string.Equals(CollectionStable, other.CollectionStable, StringComparison.Ordinal))
				{
					return string.Equals(Name, other.Name, StringComparison.Ordinal);
				}
				return false;
			}

			public override bool Equals(object obj)
			{
				if (obj is CreatedKey other)
				{
					return Equals(other);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return (17 * 31 + StringComparer.Ordinal.GetHashCode(CollectionStable ?? "")) * 31 + StringComparer.Ordinal.GetHashCode(Name ?? "");
			}
		}

		private readonly struct AtlasKey : IEquatable<AtlasKey>
		{
			public readonly string ShaderName;

			public readonly string BaseAtlasName;

			public readonly int BaseW;

			public readonly int BaseH;

			public AtlasKey(Material templateMat)
			{
				Texture2D val = (Texture2D)(((Object)(object)templateMat != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
				ShaderName = ((Object.op_Implicit((Object)(object)templateMat) && Object.op_Implicit((Object)(object)templateMat.shader)) ? (((Object)templateMat.shader).name ?? "") : "");
				BaseAtlasName = (Object.op_Implicit((Object)(object)val) ? (((Object)val).name ?? "") : "");
				BaseW = (Object.op_Implicit((Object)(object)val) ? ((Texture)val).width : 0);
				BaseH = (Object.op_Implicit((Object)(object)val) ? ((Texture)val).height : 0);
			}

			public bool Equals(AtlasKey other)
			{
				if (BaseW == other.BaseW && BaseH == other.BaseH && string.Equals(ShaderName, other.ShaderName, StringComparison.Ordinal))
				{
					return string.Equals(BaseAtlasName, other.BaseAtlasName, StringComparison.Ordinal);
				}
				return false;
			}

			public override bool Equals(object obj)
			{
				if (obj is AtlasKey other)
				{
					return Equals(other);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return (((17 * 31 + BaseW) * 31 + BaseH) * 31 + StringComparer.Ordinal.GetHashCode(ShaderName ?? "")) * 31 + StringComparer.Ordinal.GetHashCode(BaseAtlasName ?? "");
			}
		}

		private readonly struct MatKey : IEquatable<MatKey>
		{
			public readonly string ShaderName;

			public readonly string BaseMatName;

			public readonly string TexName;

			public readonly int TexW;

			public readonly int TexH;

			public MatKey(Material baseMat, Texture2D tex)
			{
				ShaderName = ((Object.op_Implicit((Object)(object)baseMat) && Object.op_Implicit((Object)(object)baseMat.shader)) ? (((Object)baseMat.shader).name ?? "") : "");
				BaseMatName = (Object.op_Implicit((Object)(object)baseMat) ? (((Object)baseMat).name ?? "") : "");
				TexName = (Object.op_Implicit((Object)(object)tex) ? (((Object)tex).name ?? "") : "");
				TexW = (Object.op_Implicit((Object)(object)tex) ? ((Texture)tex).width : 0);
				TexH = (Object.op_Implicit((Object)(object)tex) ? ((Texture)tex).height : 0);
			}

			public bool Equals(MatKey other)
			{
				if (TexW == other.TexW && TexH == other.TexH && string.Equals(ShaderName, other.ShaderName, StringComparison.Ordinal) && string.Equals(BaseMatName, other.BaseMatName, StringComparison.Ordinal))
				{
					return string.Equals(TexName, other.TexName, StringComparison.Ordinal);
				}
				return false;
			}

			public override bool Equals(object obj)
			{
				if (obj is MatKey other)
				{
					return Equals(other);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return ((((17 * 31 + TexW) * 31 + TexH) * 31 + StringComparer.Ordinal.GetHashCode(ShaderName ?? "")) * 31 + StringComparer.Ordinal.GetHashCode(BaseMatName ?? "")) * 31 + StringComparer.Ordinal.GetHashCode(TexName ?? "");
			}
		}

		private sealed class LruCache<TKey, TValue>
		{
			private struct Entry
			{
				public TKey Key;

				public TValue Value;
			}

			private readonly int _cap;

			private readonly Dictionary<TKey, LinkedListNode<Entry>> _map;

			private readonly LinkedList<Entry> _lru;

			private readonly Action<TValue> _onEvict;

			public int Count => _map.Count;

			public LruCache(int capacity, Action<TValue> onEvict)
			{
				_cap = Mathf.Max(1, capacity);
				_map = new Dictionary<TKey, LinkedListNode<Entry>>(_cap);
				_lru = new LinkedList<Entry>();
				_onEvict = onEvict;
			}

			public bool TryGetValue(TKey key, out TValue value)
			{
				if (_map.TryGetValue(key, out var value2))
				{
					_lru.Remove(value2);
					_lru.AddFirst(value2);
					value = value2.Value.Value;
					return true;
				}
				value = default(TValue);
				return false;
			}

			public void Set(TKey key, TValue value)
			{
				if (_map.TryGetValue(key, out var value2))
				{
					value2.Value = new Entry
					{
						Key = key,
						Value = value
					};
					_lru.Remove(value2);
					_lru.AddFirst(value2);
					return;
				}
				while (_map.Count >= _cap)
				{
					EvictOne();
				}
				Entry value3 = default(Entry);
				value3.Key = key;
				value3.Value = value;
				LinkedListNode<Entry> linkedListNode = new LinkedListNode<Entry>(value3);
				_lru.AddFirst(linkedListNode);
				_map[key] = linkedListNode;
			}

			private void EvictOne()
			{
				LinkedListNode<Entry> last = _lru.Last;
				if (last == null)
				{
					return;
				}
				_lru.RemoveLast();
				_map.Remove(last.Value.Key);
				if (_onEvict == null)
				{
					return;
				}
				try
				{
					_onEvict(last.Value.Value);
				}
				catch
				{
				}
			}

			public void Clear(bool destroyValues)
			{
				if (destroyValues && _onEvict != null)
				{
					foreach (Entry item in _lru)
					{
						try
						{
							_onEvict(item.Value);
						}
						catch
						{
						}
					}
				}
				_map.Clear();
				_lru.Clear();
			}
		}

		private readonly struct Key : IEquatable<Key>
		{
			public readonly tk2dSpriteCollectionData Col;

			public readonly int SpriteId;

			public Key(tk2dSpriteCollectionData col, int id)
			{
				Col = col;
				SpriteId = id;
			}

			public bool Equals(Key other)
			{
				if (Col == other.Col)
				{
					return SpriteId == other.SpriteId;
				}
				return false;
			}

			public override bool Equals(object obj)
			{
				if (obj is Key other)
				{
					return Equals(other);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return (17 * 31 + (Object.op_Implicit((Object)(object)Col) ? ((Object)Col).GetInstanceID() : 0)) * 31 + SpriteId;
			}
		}

		private static bool? _cachedEvolvingSprites;

		private const int MaxCachedMaterials = 128;

		private const int MaxCachedAtlases = 16;

		private const int MaxCreatedIdMap = 512;

		private static readonly LruCache<MatKey, Material> _matCache = new LruCache<MatKey, Material>(128, DestroyMaterial);

		private static readonly LruCache<AtlasKey, RuntimeAtlas> _atlasCache = new LruCache<AtlasKey, RuntimeAtlas>(16, DestroyRuntimeAtlas);

		private static readonly LruCache<CreatedKey, int> _createdIds = new LruCache<CreatedKey, int>(512, null);

		private static bool EvolvingSpritesEnabled()
		{
			if (_cachedEvolvingSprites.HasValue)
			{
				return _cachedEvolvingSprites.Value;
			}
			try
			{
				_cachedEvolvingSprites = ConfigManager.CfgEvolvingButtonDialogue != null && ConfigManager.CfgEvolvingButtonDialogue.Value;
				return _cachedEvolvingSprites.Value;
			}
			catch
			{
				_cachedEvolvingSprites = false;
				return false;
			}
		}

		public static void InvalidateButtonSpriteConfigCache()
		{
			_cachedEvolvingSprites = null;
		}

		private static string GetCollectionStableId(tk2dSpriteCollectionData c)
		{
			if (!Object.op_Implicit((Object)(object)c))
			{
				return "null";
			}
			try
			{
				PropertyInfo property = ((object)c).GetType().GetProperty("spriteCollectionName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if ((object)property != null)
				{
					string text = property.GetValue(c, null) as string;
					if (!string.IsNullOrEmpty(text))
					{
						return text;
					}
				}
			}
			catch
			{
			}
			return ((Object)c).name ?? "null";
		}

		private static void DestroyMaterial(Material m)
		{
			try
			{
				if (Object.op_Implicit((Object)(object)m))
				{
					Object.Destroy((Object)(object)m);
				}
			}
			catch
			{
			}
		}

		private static void DestroyRuntimeAtlas(RuntimeAtlas ra)
		{
			if (ra == null)
			{
				return;
			}
			try
			{
				if (Object.op_Implicit((Object)(object)ra.AtlasTex))
				{
					Object.Destroy((Object)(object)ra.AtlasTex);
				}
			}
			catch
			{
			}
			try
			{
				if (Object.op_Implicit((Object)(object)ra.Mat))
				{
					Object.Destroy((Object)(object)ra.Mat);
				}
			}
			catch
			{
			}
		}

		public static void ClearRuntimeCaches(bool destroyUnityObjects)
		{
			_createdIds.Clear(destroyValues: false);
			_matCache.Clear(destroyUnityObjects);
			_atlasCache.Clear(destroyUnityObjects);
		}

		private static Material GetOrCreateMaterial(Material baseMat, Texture2D tex)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)baseMat) || !Object.op_Implicit((Object)(object)tex))
			{
				return null;
			}
			MatKey key = new MatKey(baseMat, tex);
			if (_matCache.TryGetValue(key, out var value) && Object.op_Implicit((Object)(object)value))
			{
				return value;
			}
			Material val = new Material(baseMat);
			val.mainTexture = (Texture)(object)tex;
			((Object)val).hideFlags = (HideFlags)20;
			_matCache.Set(key, val);
			return val;
		}

		private static void CopyAllInstanceFields(object src, object dst)
		{
			if (src == null || dst == null)
			{
				return;
			}
			Type type = src.GetType();
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			FieldInfo[] fields = type.GetFields(bindingAttr);
			foreach (FieldInfo fieldInfo in fields)
			{
				try
				{
					if (!fieldInfo.IsInitOnly)
					{
						object obj = fieldInfo.GetValue(src);
						if (obj != null && obj.GetType().IsArray)
						{
							obj = ((Array)obj).Clone();
						}
						fieldInfo.SetValue(dst, obj);
					}
				}
				catch
				{
				}
			}
		}

		private static bool TryGetTemplateUvRect(tk2dSpriteDefinition template, out float uMin, out float uMax, out float vMin, out float vMax)
		{
			//IL_005b: 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_0061: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			uMin = (uMax = (vMin = (vMax = 0f)));
			if (template == null)
			{
				return false;
			}
			Vector2[] uvs = template.uvs;
			if (uvs == null || uvs.Length < 4)
			{
				return false;
			}
			uMin = (uMax = uvs[0].x);
			vMin = (vMax = uvs[0].y);
			for (int i = 1; i < 4; i++)
			{
				Vector2 val = uvs[i];
				if (val.x < uMin)
				{
					uMin = val.x;
				}
				if (val.x > uMax)
				{
					uMax = val.x;
				}
				if (val.y < vMin)
				{
					vMin = val.y;
				}
				if (val.y > vMax)
				{
					vMax = val.y;
				}
			}
			return true;
		}

		private static void UvRectToPixelRect(Texture2D atlas, float uMin, float uMax, float vMin, float vMax, out int x, out int y, out int w, out int h)
		{
			int width = ((Texture)atlas).width;
			int height = ((Texture)atlas).height;
			int num = Mathf.FloorToInt(uMin * (float)width);
			int num2 = Mathf.CeilToInt(uMax * (float)width);
			int num3 = Mathf.FloorToInt(vMin * (float)height);
			int num4 = Mathf.CeilToInt(vMax * (float)height);
			x = Mathf.Clamp(num, 0, width - 1);
			y = Mathf.Clamp(num3, 0, height - 1);
			w = Mathf.Clamp(num2 - x, 1, width - x);
			h = Mathf.Clamp(num4 - y, 1, height - y);
		}

		private static void BlitScaled(Texture2D src, Texture2D dst, int dstX, int dstY, int dstW, int dstH)
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)src) || !Object.op_Implicit((Object)(object)dst))
			{
				return;
			}
			Color32[] pixels = src.GetPixels32();
			int width = ((Texture)src).width;
			int height = ((Texture)src).height;
			Color32[] array = (Color32[])(object)new Color32[dstW * dstH];
			for (int i = 0; i < dstH; i++)
			{
				for (int j = 0; j < dstW; j++)
				{
					int num = i * width / dstH;
					int num2 = j * height / dstW;
					if (num < 0)
					{
						num = 0;
					}
					else if (num >= width)
					{
						num = width - 1;
					}
					if (num2 < 0)
					{
						num2 = 0;
					}
					else if (num2 >= height)
					{
						num2 = height - 1;
					}
					array[i * dstW + j] = pixels[num2 * width + num];
				}
			}
			dst.SetPixels32(dstX, dstY, dstW, dstH, array);
		}

		private static RuntimeAtlas GetOrCreateRuntimeAtlas(Material templateMat)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)templateMat))
			{
				return null;
			}
			Texture mainTexture = templateMat.mainTexture;
			Texture2D val = (Texture2D)(object)((mainTexture is Texture2D) ? mainTexture : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			AtlasKey key = new AtlasKey(templateMat);
			if (_atlasCache.TryGetValue(key, out var value) && value != null && Object.op_Implicit((Object)(object)value.AtlasTex))
			{
				return value;
			}
			Texture2D val2 = new Texture2D(((Texture)val).width, ((Texture)val).height, (TextureFormat)4, false, false);
			((Texture)val2).filterMode = (FilterMode)0;
			((Texture)val2).wrapMode = (TextureWrapMode)1;
			((Object)val2).name = ((Object)val).name + "_LOOP_RUNTIME_ATLAS";
			((Object)val2).hideFlags = (HideFlags)20;
			try
			{
				val2.SetPixels32(val.GetPixels32());
			}
			catch
			{
				Color32[] pixels = (Color32[])(object)new Color32[((Texture)val2).width * ((Texture)val2).height];
				val2.SetPixels32(pixels);
			}
			val2.Apply(false, false);
			value = new RuntimeAtlas
			{
				AtlasTex = val2,
				Mat = GetOrCreateMaterial(templateMat, val2)
			};
			_atlasCache.Set(key, value);
			return value;
		}

		private static tk2dSpriteDefinition CloneDefinition(tk2dSpriteDefinition template, Texture2D newTex, string name)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			if (template == null || (Object)(object)newTex == (Object)null)
			{
				return null;
			}
			tk2dSpriteDefinition val = new tk2dSpriteDefinition();
			CopyAllInstanceFields(template, val);
			val.name = name ?? string.Empty;
			Material materialInst = template.materialInst;
			RuntimeAtlas orCreateRuntimeAtlas = GetOrCreateRuntimeAtlas(materialInst);
			if (orCreateRuntimeAtlas != null && (Object)(object)orCreateRuntimeAtlas.AtlasTex != (Object)null && TryGetTemplateUvRect(template, out var uMin, out var uMax, out var vMin, out var vMax))
			{
				UvRectToPixelRect(orCreateRuntimeAtlas.AtlasTex, uMin, uMax, vMin, vMax, out var x, out var y, out var w, out var h);
				BlitScaled(newTex, orCreateRuntimeAtlas.AtlasTex, x, y, w, h);
				orCreateRuntimeAtlas.AtlasTex.Apply(false, false);
			}
			if ((Object)(object)materialInst != (Object)null && orCreateRuntimeAtlas != null && (Object)(object)orCreateRuntimeAtlas.AtlasTex != (Object)null)
			{
				val.materialInst = GetOrCreateMaterial(materialInst, orCreateRuntimeAtlas.AtlasTex);
			}
			return val;
		}

		private static int AddTexAsSpriteDef(tk2dSpriteCollectionData collection, int templateSpriteId, Texture2D tex, string name)
		{
			if (!Object.op_Implicit((Object)(object)collection) || !Object.op_Implicit((Object)(object)tex))
			{
				return -1;
			}
			CreatedKey key = new CreatedKey(collection, name);
			if (_createdIds.TryGetValue(key, out var value) && value >= 0)
			{
				return value;
			}
			tk2dSpriteDefinition[] array = collection.spriteDefinitions;
			if (array == null || array.Length == 0)
			{
				return -1;
			}
			tk2dSpriteDefinition val = array[Mathf.Clamp(templateSpriteId, 0, array.Length - 1)];
			if (val == null)
			{
				return -1;
			}
			tk2dSpriteDefinition val2 = CloneDefinition(val, tex, name);
			int num = array.Length;
			Array.Resize(ref array, num + 1);
			array[num] = val2;
			collection.spriteDefinitions = array;
			_createdIds.Set(key, num);
			return num;
		}

		private static Texture2D GetTalkTex(int idx1Based, bool evolving)
		{
			if (evolving)
			{
				return (Texture2D)(idx1Based switch
				{
					1 => ModTextures.LoopButton.Talk1EvolvingTex, 
					2 => ModTextures.LoopButton.Talk2EvolvingTex, 
					3 => ModTextures.LoopButton.Talk3EvolvingTex, 
					_ => null, 
				});
			}
			return (Texture2D)(idx1Based switch
			{
				1 => ModTextures.LoopButton.Talk1FixedTex, 
				2 => ModTextures.LoopButton.Talk2FixedTex, 
				3 => ModTextures.LoopButton.Talk3FixedTex, 
				_ => null, 
			});
		}

		private static tk2dSpriteAnimationClip FindClipByContains(tk2dSpriteAnimator animator, string token)
		{
			if ((Object)(object)animator == (Object)null || (Object)(object)animator.Library == (Object)null || animator.Library.clips == null)
			{
				return null;
			}
			if (token == null)
			{
				token = "";
			}
			tk2dSpriteAnimationClip[] clips = animator.Library.clips;
			foreach (tk2dSpriteAnimationClip val in clips)
			{
				if (val != null && val.name != null && val.name.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return val;
				}
			}
			return null;
		}

		private static void EnsureInstancedAnimatorLibraryOnly(tk2dSpriteAnimator anim)
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			if ((Object)(object)anim == (Object)null || (Object)(object)((Component)anim).gameObject.GetComponent<InstancedTk2dMarker>() != (Object)null)
			{
				return;
			}
			if ((Object)(object)anim.Library != (Object)null)
			{
				tk2dSpriteAnimation val = Object.Instantiate<tk2dSpriteAnimation>(anim.Library);
				((Object)val).name = ((Object)anim.Library).name + "_LOOP_RUNTIME";
				if (val.clips != null)
				{
					tk2dSpriteAnimationClip[] clips = val.clips;
					tk2dSpriteAnimationClip[] array = (tk2dSpriteAnimationClip[])(object)new tk2dSpriteAnimationClip[clips.Length];
					for (int i = 0; i < clips.Length; i++)
					{
						tk2dSpriteAnimationClip val2 = clips[i];
						if (val2 == null)
						{
							array[i] = null;
							continue;
						}
						tk2dSpriteAnimationClip val3 = new tk2dSpriteAnimationClip();
						CopyAllInstanceFields(val2, val3);
						val3.name = val2.name;
						if (val2.frames != null)
						{
							tk2dSpriteAnimationFrame[] array2 = (tk2dSpriteAnimationFrame[])(object)new tk2dSpriteAnimationFrame[val2.frames.Length];
							for (int j = 0; j < val2.frames.Length; j++)
							{
								tk2dSpriteAnimationFrame val4 = val2.frames[j];
								if (val4 == null)
								{
									array2[j] = null;
									continue;
								}
								tk2dSpriteAnimationFrame val5 = new tk2dSpriteAnimationFrame();
								CopyAllInstanceFields(val4, val5);
								array2[j] = val5;
							}
							val3.frames = array2;
						}
						array[i] = val3;
					}
					val.clips = array;
				}
				anim.Library = val;
			}
			((Component)anim).gameObject.AddComponent<InstancedTk2dMarker>();
		}

		public static bool ApplyLoopButtonAnimator(tk2dSpriteAnimator anim)
		{
			if ((Object)(object)anim == (Object)null || (Object)(object)anim.Sprite == (Object)null)
			{
				return false;
			}
			bool evolving = EvolvingSpritesEnabled();
			LoopButtonAppliedMarker loopButtonAppliedMarker = ((Component)anim).gameObject.GetComponent<LoopButtonAppliedMarker>();
			if ((Object)(object)loopButtonAppliedMarker != (Object)null && loopButtonAppliedMarker.EvolvingEnabled == evolving)
			{
				return false;
			}
			EnsureInstancedAnimatorLibraryOnly(anim);
			tk2dSpriteAnimationClip val = FindClipByContains(anim, "button_hell_talk");
			tk2dSpriteAnimationClip val2 = FindClipByContains(anim, "button_hell_idle");
			if (val == null && val2 == null)
			{
				return false;
			}
			bool flag = false;
			string text = (evolving ? "EV" : "FIXED");
			if (val2 != null)
			{
				List<Key> uniqueKeysInClip = GetUniqueKeysInClip(anim, val2);
				List<int> list = AddLoopSequenceUsingKeys(uniqueKeysInClip, (int _) => GetTalkTex(1, evolving), "button_hell_idle_" + text + "_");
				if (list.Count == uniqueKeysInClip.Count)
				{
					RemapClipByKeys(anim, val2, uniqueKeysInClip, list);
					flag = true;
				}
			}
			if (val != null)
			{
				List<Key> uniqueKeysInClip2 = GetUniqueKeysInClip(anim, val);
				List<int> list2 = AddLoopSequenceUsingKeys(uniqueKeysInClip2, (int idx) => GetTalkTex(idx, evolving), "button_hell_talk_" + text + "_");
				if (list2.Count == uniqueKeysInClip2.Count)
				{
					RemapClipByKeys(anim, val, uniqueKeysInClip2, list2);
					flag = true;
				}
			}
			if (flag)
			{
				try
				{
					anim.Sprite.ForceBuild();
					ModTextures.Tk2dUpdateMaterialSafe(anim.Sprite);
					anim.UpdateAnimation(0f);
				}
				catch
				{
				}
				if ((Object)(object)loopButtonAppliedMarker == (Object)null)
				{
					loopButtonAppliedMarker = ((Component)anim).gameObject.AddComponent<LoopButtonAppliedMarker>();
				}
				loopButtonAppliedMarker.EvolvingEnabled = evolving;
				if (Scaling.DebugSpam)
				{
					ETGModConsole.Log((object)"<color=#48ff00>[LOOP]</color> <color=#FFFFFF>Button sprites applied.</color>", false);
				}
			}
			return flag;
		}

		private static List<Key> GetUniqueKeysInClip(tk2dSpriteAnimator anim, tk2dSpriteAnimationClip clip)
		{
			List<Key> list = new List<Key>();
			if ((Object)(object)anim == (Object)null || clip == null || clip.frames == null)
			{
				return list;
			}
			HashSet<Key> hashSet = new HashSet<Key>();
			for (int i = 0; i < clip.frames.Length; i++)
			{
				tk2dSpriteAnimationFrame val = clip.frames[i];
				if (val == null)
				{
					continue;
				}
				tk2dSpriteCollectionData val2 = (((Object)(object)val.spriteCollection != (Object)null) ? val.spriteCollection : anim.Sprite.Collection);
				if (!((Object)(object)val2 == (Object)null))
				{
					Key item = new Key(val2, val.spriteId);
					if (hashSet.Add(item))
					{
						list.Add(item);
					}
				}
			}
			return list;
		}

		private static void RemapClipByKeys(tk2dSpriteAnimator anim, tk2dSpriteAnimationClip clip, List<Key> uniqueOld, List<int> newIds)
		{
			if (clip == null || clip.frames == null || uniqueOld == null || newIds == null || uniqueOld.Count != newIds.Count)
			{
				return;
			}
			Dictionary<Key, int> dictionary = new Dictionary<Key, int>(uniqueOld.Count);
			for (int i = 0; i < uniqueOld.Count; i++)
			{
				dictionary[uniqueOld[i]] = newIds[i];
			}
			for (int j = 0; j < clip.frames.Length; j++)
			{
				tk2dSpriteAnimationFrame val = clip.frames[j];
				if (val == null)
				{
					continue;
				}
				tk2dSpriteCollectionData val2 = (((Object)(object)val.spriteCollection != (Object)null) ? val.spriteCollection : anim.Sprite.Collection);
				if (!((Object)(object)val2 == (Object)null))
				{
					Key key = new Key(val2, val.spriteId);
					if (dictionary.TryGetValue(key, out var value))
					{
						val.spriteId = value;
					}
				}
			}
		}

		private static List<int> AddLoopSequenceUsingKeys(List<Key> uniqueOld, Func<int, Texture2D> getTex, string internalPrefix)
		{
			List<int> list = new List<int>(uniqueOld.Count);
			for (int i = 0; i < uniqueOld.Count; i++)
			{
				Key key = uniqueOld[i];
				if ((Object)(object)key.Col == (Object)null)
				{
					return new List<int>();
				}
				Texture2D tex = get